在这个实验中,我们需要使用反汇编工具得到汇编代码,并且通过分析和使用gdb调试工具来拆除6个炸弹.
首先通过objdump -d bomb 反汇编bomb得到bomb的汇编代码
首先看phase_1的代码
phase_1考察的是过程调用的参数传递和栈
phase_1开辟了8个字节大小的栈帧,是用来在callq时将下一条指令的地址,即400eee压栈.
输入字符串的首地址保存在寄存器%rdi中,400ee4处将地址0x402400传递给%esi,然后调用strings_not_equal,从名字可知道strings_not_equal比较%rdi和%rsi处的字符串是否相等,返回值保存在%eax中,不相等则会引爆炸弹.为此我们需要查看地址0x402400处的内容,这里需要使用gdb中的x/命令,x后跟有三个可选参数,x/nfu,n是一个正整数,表示需要显示的内存单元的个数,f表示显示的格式,如s表示以字符串格式显示,x表示以16进制形式显示,u表示从当前地址往后请求的字节数,默认为4字节,b表示单字,h表示双字,w表示4字,g表示八字.这里我们要显示字符串,可以直接用 x 0x402400
输入字符串后拆除成功
虽然通过函数名字猜出了用途,但是为了学习还是看一下strings_not_equal函数
这个函数思路比较简单,先计算%rdi处字符串的长度,将结果保存在%r12d,再计算%rsi的长度,将结果保存在
%rax,然后比较%rsi和%rax的值,不相等返回1,相等则循环比较字符串的内容,直到某个字符不等或者遇到某个字符串结束为止.
接着看phase_2
开始时将栈顶寄存器赋值给了%rsi作为参数,调用<read_six_numbers>,以下是read_six_numbers的代码
开始是一系列的开辟栈帧,调用者保存寄存器和参数传递先不看,可以看到之后调用了<__isoc99_sscanf@plt>,大致可以看出调用了sscanf参数,从参数看出共使用了八个参数,因为寄存器最多传递6个参数,因此最后两个参数用栈传递,八个参数分别为%rdi,%rsi,%rdx,%rcx,%r8,%9,M[%rsp],M[%rsp + 8],从函数名字可以看出是读6个数,那么为什么需要8个参数呢,先使用x查询%rdi和%rsi