实验目的:
通过二进制炸弹实验,熟悉汇编语言,反汇编工具objdump以及gdb调试工具。
实验过程:
实验包里有三个文件,分别是二进制可执行文件bomb,C语言源程序文件bomb.c以及一个README-bomblab.txt文件。
分别打开看了一下,C语言源程序文件bomb.c文件不是完整的那种C代码文件,她只是给出了一些入口的指引,用input输入数据,但怎么处理这些输入的参数它并没有显示。然后这三个文件比较有用的就是bomb文件,接下来就利用这个文件来通关。
一、第一关:字符串比较
1、先运行可执行文件bomb,随意输入一些东西,发现程序被引爆,通关密码错误。
2、查看汇编代码分析以找到正确的通关密码,由于直接反汇编查看汇编代码在终端界面的小黑框里不方便看,所以在反汇编的时候直接把汇编文件保存在bomb.s文件中,而后在编译器中查看,发现汇编代码超级长,但是在main函数下发现了它调用了phase_1到phase_6以及phase_defused函数,由此可猜测phase_1到phase_6即为所要找的关卡。
3、一关一关来,进入gdb调试界面,查看phase_1的汇编代码,也可以在bomb.s文件中直接看,但那样要拉到代码下端逐次检索,不太方便,分析phase_1函数的汇编代码发现,它调用了两个函数strings_not_equal和explode_bomb(我也查看了这两个函数的汇编代码,前者在里面两次次调用了string_length函数,猜测是为了实现字符串的比较,总之,从这两个函数里没有分析出很有用的东西),根据单词的字面意思,前者是比较两个字符串是否相等,后者是一个爆炸函数。
以下为strings_not equal函数的汇编代码,大概就是先比较两字符串是否相等,若相等,再逐个比较字符是否一样,一样则字符串相等,反之,直接不等,若字符串相等%eax返回0,否则,返回1:
再接着析phase_1的汇编代码,发现在调用strings_not_equal函数后,进行了test指令,比较%eax与%eax是否位0,若为0则字符串相等跳转到leave,释放栈帧,否则,跳转到explode_bomb函数,程序爆炸。
4、根据上述分析,很容易猜测调用strings_not_equal函数前的指令当中出现的立即数$0x804a15c可疑,极有可能就是strings_not_equal函数的参数输入地址值,尝试打印出此地址处的值(以字符串形式)进行验证。
5、在gdb调试界面运行可执行文件,输入之前打印出的字符串,发现第一个炸弹被拆除,所以,第一关由此就成功通过了。
二、第二关
1、有了第一关的经验,先进入gdb调试界面下,然后查看phase_2的汇编代码,看了一遍代码后发现里面调用了函数read_six_numbers,猜测应该是读入六个数字,而后进行了两次相等跳转和不相等跳转以及两次跳转到explode_bomb函数,到这里就没有什么头绪了。
2、查阅了很多资料后(如查看课本汇编代码各个指令的意思),我对phase_2函数的汇编代码进行了分析,并参考课本P149页开始画了栈帧图,由于草稿纸上画得比较乱,这里只能给一个简洁版。
分析phase_2的汇编代码:
1)、首先栈帧指针%esp、%ebp以及寄存器%esi、%ebx入栈,接着开了48字节(16进制的30等于10进制的48)的内存,栈帧结构中我已经明确标出。
2)、然后令%eax指向%ebp-0x20地址,再令%eax寄存器的值传给%esp+0x4地址,接着把%ebp+0x8间接传给%esp,再调用read_six_numbers函数,此函数应该是参数的输入入口。
接着比较%ebp-0x20地址处的值与0是否相等,若不相等,则跳转到explode_bomb函数处,程序爆炸,为了让程序不爆炸,所以要保证%ebp-0x20地址处的值为0,由此猜测此处存储的值即为参数1。
3)、依次类推,%ebp-0x1c地址处存储参数2,接着分析,发现果然不出所料,函数下一步比较了%ebp-0x1c地址处的值和1是否相等,为了让程序跳转到phase_2+43处执行而不爆炸,则参数2必须为1。
4)、接着令%ebx指向%ebp-0x18地址,%esi指向%ebp-0x8地址,然后让参数1和参数2相加存储在%eax中,接着比较%eax和%ebx中存储的值是否相等,为了让程序不爆炸,则%ebx中存储的值必须为1即参数3。
5)、接下来%ebx寄存器指向原本地址处增加4个字节的地址处,也就是参数4所在地址处,此时已经发现了规律,下一个参数即为上两个参数之和,由此推出参数4、参数5、参数6分别为2、3、5。
6)、当%ebx和%esi不相等时,接着循环,否则,循环结束,用add指令增加栈指针实现空间释放,程序结束。
草稿分析图:
精简图:
3、对分析出的6个参数0、1、1、2、3、5进行验证,成功通关。
总结:
日志写完后我才发现,我似乎没有用太多的gdb调试命令,绝大部分是靠画栈帧图结合汇编代码分析出的结果,希望在之后的通关过程中,我能够更多更好的利用gdb调试工具来辅助完成通关,熟练掌握gdb调试。