Phase_1
使用命令disas phase_1获取bomb程序的phase_1的反编译出来的汇编代码,其中有下面这几行代码:
0x08048b86 <+6>: movl $0x8049978,0x4(%esp)
0x08048b8e <+14>: mov 0x8(%ebp),%eax
0x08048b91 <+17>: mov %eax,(%esp)
0x08048b94 <+20>: call 0x80490b3 <strings_not_equal>
根据函数的意思可以猜测出该函数的功能为输入两个字符串,如果不相等便会bomb掉,其中0x8049978应该是一个字符常量的地址,在gdb中输入p (char*)0x8049978将这个字符串打印出来为"When I get angry, Mr. Bigglesworth gets upset.",将这句话输入到bomb程序中,第一关通过。
Phase_2
根据call 0x8049020 <read_six_numbers>可以推断出第二关的答案为6个数字,假设从esp至ebp全部的变量都是int类型,用var[0]-var[9]表示过程栈中的10个变量
由
0x08048bb4 <+16>: mov %eax,(%esp)
0x08048bb7 <+19>: call 0x8049020 <read_six_numbers>
0x08048bbc <+24>: mov -0x1c(%ebp),%eax
0x08048bbf <+27>: cmp $0x1,%eax
0x08048bc2 <+30>: je 0x8048bc9 <phase_2+37>
0x08048bc4 <+32>: call 0x804967a <explode_bomb>
可知,var[3]必须为1,否则就会bomb掉。
接下来运行
0x08048bc9 <+37>: movl $0x1,-0x4(%ebp)
0x08048bd0 <+44>: jmp 0x8048bf4 <phase_2+80>
此时将var[9]置为1,然后跳到+80运行
+80的代码如下:
0x08048bf4 <+80>: cmpl $0x5,-0x4(%ebp)
0x08048bf8 <+84>: jle 0x8048bd2 <phase_2+46>
0x08048bfa <+86>: leave
当var[9] <= 5时,程序会一直执行。
+46代码如下:
0x08048bd2 <+46>: mov -0x4(%ebp),%eax
0x08048bd5 <+49>: mov -0x1c(%ebp,%eax,4),%ecx
0x08048bd9 <+53>: mov -0x4(%ebp),%eax
0x08048bdc <+56>: dec %eax
0x08048bdd <+57>: mov -0x1c(%ebp,%eax,4),%edx
0x08048be1 <+61>: mov -0x4(%ebp),%eax
0x08048be4 <+64>: inc %eax
0x08048be5 <+65>: imul %edx,%eax
0x08048be8 <+68>: cmp %eax,%ecx
0x08048bea <+70>: je 0x8048bf1 <phase_2+77>
0x08048bec <+72>: call 0x804967a <explode_bomb>
0x08048bf1 <+77>: incl -0x4(%ebp)
这段汇编的伪代码为:
eax = var[9]
ecx = var[3+eax]
eax = var[9]
eax–
edx = var[3+eax]
eax = var[9]
eax++
eax = eax * edx
if eax != ecx bomb
var[9]++
goto +80
因此phase_2的结果规律为设res[1] = 1,有规则res[i+1] = res[i] * factor,其中factor = i + 1,所以最后的结果为1 2 6 24 120 720。
Phase_3
在phase_3中依然将栈中的变量设为var[0:n]
0x08048c02 <