二进制炸弹
第一阶段:
Phase_0的反汇编代码:

代码解释:
第1,2,3,4行为构造phase_0函数的栈帧,
第5行为一个立即数(一个地址,函数<strings_not_equal>的第二个参数),
第6行为函数<strings_not_equal>的第一个参数(因为其地址为ebp+8,可知其为main函数传给phase_0函数的一个参数,即为用户输入的)
第7行调用函数<strings_not_equal>对第5行和第6行的两个数进行比较,并将结果(即ZF的值)保存到eax中
第8行为调整栈帧
第9行,eax和eax进行按位与运算,如果eax为0,则test的结果为0,否则结果为1
第10行如果test的结果等于0(即相等,ZF=0)跳到je的地址804947d,执行mov $0x1,%eax,成功返回!
否则继续执行调用explode_bomb,炸弹爆炸!
故我们只需要保证函数<strings_not_equal>的结果为0,即第6行用户的输入与第5行地址的值相等即可。打开gdb,查看

得到解除炸弹的输入。
第二阶段:
Phase_1的反汇编代码:

代码解释:
8049484到8049487:构造栈帧;
804948a将0x2e7bdac0赋值给-0xc(%ebp);
8049491到8049497将上面的数转换为浮点数,并存入-0x10(%ebp);
8049497到80494a4为sscanf函数准备参数,0x8(%ebp)为sscanf第一个参数(我们输入的字符串),0x804b216为第二个参数(sscanf函数格式化参数),-0x14(%ebp)为第三 个参数(-0x10(%ebp)的高4字节),-0x18(%ebp)为第四个参数(-0x10(%ebp)的低4字节)
80494a7为调用sscanf函数;
80494ac为调节栈帧;
80494af比较eax和2,eax表示sscanf函数成功读入参数的个数
80494b2如果等于2,则跳到80494c0处
80494b4否则引爆炸弹
80494c0到80494c9把我们输入的高4字节放到edx中
80494cc把-0x14(%ebp)即sscanf第三个参数放到eax中
80494cf比较edx和eax中的数
80494d1如果不相等,跳到80494e3,炸弹爆炸!
80494d3到80494df同上比较 我们输入的低4字节(edx) 和 sscanf第四个参数(eax)
80494e1如果相等则成功!
80494e3否则爆炸!
故我们输入的两个整数需要与0x2e7bdac0的高字节和低字节相等即可。用gdb查看0x804b216(sscanf函数格式化参数)为:
,可知输入的为两个整数,用空格分隔。
0x2e7bdac0转化为二进制为:101110011110111101101011000000
规格化为:1.01110011110111101101011*10^29
故表示为IEEE754为:
0100111000111001 1110111101101011
高16位转化为整数为:20025
低16位转化为整数为:-4245
故字符串为: 20025 -4245
验证:

成功!
第三阶段:
Phase_2的反汇编代码:


80494f6到80494fd为构造函数的栈帧;
8049500到8049506为read_n_numbers准备参数,其中0x8(%ebp)为第一个参数(我们输入的字符串),$0x8为第二个参数(需要输入的整数个数),%eax为是否函数成功读入的参数
8049509调用函数read_n_numbers
804950e调节栈帧
8049511到8049513判断%eax是否为0,即函数成功读入的 参数,若成功则跳到804951c
804951c将我们输入的第一个数赋值给eax
804951f判断eax是否与$0xcf相等,若相等则跳到8049532(这里可知第一个数为207(0xcf))
8049532把1赋值给-0xc(%ebp),即循环变量i
8049539转跳到8049571
8049571比较-0xc(%ebp),即循环变量i是否<=7,若是跳到804953b进入循环
804953b到8049575为循环体,在循环中,我们输入的数保存到edx中
804955d为比较eax和edx的值是否相等,如果不等就爆炸!
故我们只需要找到每次循环是eax的值即为我们需要的正确输入。
我们已经知道了第一个数为207,故可以通过第一个数找到第二个数,依次类推即可。
打开gdb,在0x804955a处设置断点(b *0x804955a),运行,输入 207 2 3 4 5 6 7 8(只有第一个是已知的,其他的是随便输的),查看eax的值(p $eax),此时得到了第二个数,当然继续执行程序会爆炸(因为其他数是随便输的),所以我们需要重新打开gdb,进行上面操作。
最后得到答案:207 206 203 198 191 182 171 158
验证:

成功!
第四阶段:
Phase_3的反汇编代码:


经过前面三个的历练,这个就简单多了。
1、首先找输入函数sscanf

2、查看参数
参数1:
参数2:
参数3:
参数1为我们输入的字符串,参数2为输入的格式(用gdb查看可知为“%d %d”),参数3为函数是否成功读入输入
3、查看<explode_bomb>函数的位置
程序中有3处,第一处判断是否成功输入,第二、三次为判断我们的输入是否正确,第一个数可以直接在程序中找到,为<=0xd5,即第一个数<=213
故我们只需要通过gdb单步运行,查看寄存器eax的值即可找到第二个数。
打开gdb,在0x804961d处设置断点,运行,因为第一个数<=213,故我取第一个数为210(答案不唯一),然后查看-0xc(%ebp)的值即为第二个数。
(1)先查看ebp的地址

(2)再查看ebp的地址-0xc的内容,即0xffffcfac的内容

即可得到第二个数是279
故答案为 210 279(不唯一)
验证:

成功!

浙公网安备 33010602011771号