二进制炸弹——拆弹实验

二进制拆弹实验

这是我们学校计算机系统基础的实验,现在写出实验过程供大家参考。
具体的要求我就不多说,直接拆弹,我尽可能写的详细一点,大家照着来做基本没问题。(文末有本炸弹的反汇编代码)
拆弹开始!!!
阶段一:字符串比较
这个实验是要比较你输入的字符串和程序中预先设定的字符串是否相同,如图所示为第一个炸弹的代码,既然是比较字符串,那一定要有一个预先定义的字符串,推测这个字符串在358行这条语句push $0x8049e9c。
在这里插入图片描述
通过linux的gdb查看地址为0x8049e9c的内容。
在这里插入图片描述
运行测试答案是否正确
在这里插入图片描述
看到第一个炸弹拆除成功。

阶段二:循环
从下面这段代码中,我推测0x20(%ebp)之后连续的六个存储单元存放的是你输入的数字。
在这里插入图片描述
用gdb检验假设是否成立,果然是这样。
在这里插入图片描述
注意到第379行代码,输入的第一个数不能小于0,为方便起见,输入第一个数假设为0。
看下面这一段循环,从385行和386行可以推测,ebx寄存器的作用类似于计数器。第一次循环时,先是给ebx赋值1,再把ebx的值赋值给eax,此时eax的值也是1。然后第389行,让你输入的第一个数和eax相加,加的结果保存在eax中,加完之后eax还是1,因为输入的第一个数是0。390行比较eax和你输入的第二个数是否相同,如果不同就爆炸,相同进入下一次循环,由ebx控制循环5次。至此推测循环逻辑为第i个数为第i-1个数加上i,i从0到5且第一个数为0。
在这里插入图片描述
由上述逻辑预测出来的密钥为0 1 3 6 10 15,gdb检验答案是否正确。
在这里插入图片描述
阶段三:条件/分支
在这里插入图片描述
第415行代码查看跳转表的内容如下
在这里插入图片描述
我们输入的第一个数字放在-0xc(%ebp),由跳转表可知,如果输入的第一个数字为0,则会跳转到地址0x08048b55处继续执行。
找到0x08048b55对应的代码段
在这里插入图片描述
找到这段代码后,后面的程序就是按照顺序执行了。要注意429行,输入的第一个参数不能大于5,我输入的是0,不用担心。下面写出执行过程:
Eax = 0x372;
Eax = eax - 0x2b7;
Eax = eax + 0xf3;
Eax = eax - 0xc1;
Eax = eax + 0xc1;
Eax = eax - 0xc1;
Eax = eax +0xc1;
Eax =eax - 0xc1;
代码第430行比较输入的第二个数和计算出来的eax是否相等,只有两者相等才算拆弹成功。
在第一个数为0的情况下,计算出的eax为237
测试成功
在这里插入图片描述
阶段四:递归调用和栈
在这里插入图片描述
用gdb查看第503行代码中的0x804a02b
在这里插入图片描述
推测应该输入两个整数,由于对程序的认识有限,只知道密钥是由两个整数构成的,所以随便输入两个整数进入gdb进行调试。方便起见,输入的第一个整数为0,
在这里插入图片描述
设置断点,单步执行到了第521行。现在程序要比较0xe和-0xc(%ebp)两者的大小,由第523行代码可以看出,-0xc(%ebp)的值必须要小于0xe,下面通过gdb查看-0xc(%ebp)的值是什么。
在这里插入图片描述
这个地址存放的内容为0,这正好与我们输入的第一个数字相同,因此推测-0xc(%ebp)里存放的就是输入的第一个数字,为验证假设,查看-0x10(%ebp)存放是否为输入的第二个数字。
在这里插入图片描述
确实是输入的第二个数字。
程序继续执行下面的代码:
在这里插入图片描述
第514行代码转到fun4函数处。
Fun4函数是一个递归,这个递归看的我有点晕,琢磨了很长时间也没能看出它的逻辑在哪儿,所以我跳过fun4函数,看调用这个函数之后的下一条语句。
在这里插入图片描述
第516行,比较fun4函数的返回值eax和4是否相等,如果不等则爆炸,相等跳到下面程序段继续执行。
在这里插入图片描述
前面说过,-0x10(%ebp)是输入的第二个数字,那么现在就是比较输入的第二个数字和4的关系,如果不相等,爆炸,相等程序正常结束,炸弹拆解成功。
这个就是提示我们,输入的第二个数字必须为数字4,而又根据前面说过的,输入的第一个数字必须小于等于14,那么现在可以让第一个数字从0开始,一直到14,遍历所有可能的情况,寻找答案。
在这里插入图片描述
最终确定第四个炸弹的密钥为2 4。

阶段五:指针
在这里插入图片描述
看到程序的第537行知道,我们需要输入一个长度为6的字符串,利用gdb单步调试,输入字符串abcdef。
执行完533行后,gdb查看%ebx寄存器的内容。
在这里插入图片描述
发现是一个地址,进而查看这个地址的内容。
在这里插入图片描述
这个地址内存放着字符串abcdef,与输入的字符串相同,再加上这个炸弹是一个关于指针的炸弹,所以推测0x8(%ebp)存放的是一个指针,这个指针指向我们输入的字符串的首地址。
程序继续执行下面代码:
在这里插入图片描述
从第541行到第547行构成一个循环,循环次数有eax控制。这个循环的逻辑就是让每一个字符和0xf进行与运算,运算的结果保存在从%ebp - 0xf开始的连续六个字节的空间。
程序第543行,有一个地址0x8049f0c,gdb查看这个的内容。
在这里插入图片描述
循环结束后,程序继续执行下面代码:
在这里插入图片描述
Gdb 查看0x8049ee2的内容:
在这里插入图片描述
如图所示,这个内存单元存放的是字符串flames。
程序执行到第553行调用字符串比较函数。注意到前面的循环实际上可以理解成对你输入字符进行解码,如果解码之后得到的字符恰好是flames,则拆弹成功。程序第544行告诉了解码之后的字符串存放的位置,gdb查看解码之后的字符串。
在这里插入图片描述
显示的字符串是aduier,这和0x8049f0c存放的内容有些巧合,aduier这个字符串在0x8049fc中连续出现过,而且我们的输入abcdef也是连续的,可以推测出他们之间的对应关系。a的ASCII码值为97,对应着0x8049f0c这个地址内容的字符a,b的ASCII码值为98,对应着0x8049f0c存储单元中的字符d,以此类推,ASCII码值为96的字符对应于m,ASCII码值为101的字符对应于e,ASCII码值为103的字符对应于s,ASCII码值为105的字符对应于f,ASCII码值为111的字符对应于l,根据ASCII码表查找每个ASCII码对应的字符,再排序,得到密钥应为ioa`eg.
在这里插入图片描述

阶段六:链表/指针/结构(此炸弹应为链表)
在这里插入图片描述

第六个炸弹的代码很长,很难从头到尾的读懂它的逻辑。看到第572行代码调用了read_six_numbers函数,推测密钥应该是六个数字。输入1 2 3 4 5 6这六个数字在gdb下一步一步的调试。
在这里插入图片描述
单步运行程序到第586行
在这里插入图片描述
执行完586行后查看eax的值:
在这里插入图片描述
Eax的值正好与输入的第一个数字相同。
注意一个细节,程序第588行,eax必须小于等于5,因为前面有一条eax减一的语句,所以输入的所有数字都必须小于等于6。
程序继续执行,在第589行处跳转到576行。
在这里插入图片描述
程序执行完580行后查看eax的值
在这里插入图片描述
此时的eax为2,正好等于输入的第二个数。此时的第581行功能为比较第一个数和第二个数是否相等,如果相等则爆炸。不相等判断ebx是否小于等于5,从而进入下一次循环。若循环正常结束(未引爆炸弹),说明第一个数与后面的5个数都不相同。因为调试程序时输入的是1 2 3 4 5 6,因此循环能够正常结束。
程序执行586行代码:
在这里插入图片描述
因为此时的esi为1,所以执行完586行代码后eax的值应该为2,也就是说是你输入的第二个数。可以gdb验证一下是不是这样。
在这里插入图片描述
Eax中的值确实是2,前面的假设正确。
后面程序要做的就是比较输入的第二个数和后面的四个数是否相同,以此类推,第三个数和后面的三个数比较。最终,判断出来任意两个数都不相同。
当所有的数字都比较完之后,由第578行语句知,程序跳转到第594行继续执行。
在这里插入图片描述
程序执行到第598行,gdb查看地址的值:
在这里插入图片描述
由上图可知,此链表的首地址为0x804c13c,每个链表单元存放三个数(每个都是4字节,共12字节),第一个为程序预先写好的数字,第二个为用户输入的数字,第三个为下一个链表单元的起始地址。

由第596行知,ecx中存放的是你输入的第ebx(从0开始)个数。
第600行,程序跳转到第605行继续执行。
第608行,程序跳转到第595行继续执行。

又是一个循环。
整个循环的关键在第605行代码,这一行代码修改内存单元的值。
循环结束后,gdb查看相应的内存单元内容:
在这里插入图片描述
查看每个地址对应的内容,得出如下关系:
0x804c13c:0xe2
0x804c148:0x1b3
0x804c154:0x221
0x804c160:0x133
0x804c16c:0x12b
0x804c178:0x87
仔细研究第594行到第608行代码,这一段代码的功能是根据你输入的数字进行链表单元的位置进行重排,原链表的起始地址为0x804c13c,比如你输入的数字为3 4 1 6 2 5,则现在的起始地址应该为原链表的第三个链表单元,现在的第二个链表单元应为原链表的第四个链表单元,以此类推。
循环结束后程序应该执行第609行。
在这里插入图片描述
第612行到617行的功能为将重排后的链表单元连接起来。
613行代码 #0x8(%ecx)内存放的应该是下一个链表单元的起始地址。
在这里插入图片描述
这一段代码的功能是比较第i个节点和第i-1个节点中数值部分的大小,且要求第i-1个节点小于于第i个节点,即按照从小到大的顺序进行排序。
0x804c13c:0xe2
0x804c148:0x1b3
0x804c154:0x221
0x804c160:0x133
0x804c16c:0x12b
0x804c178:0x87
由上述地址和内容的对应关系,可得0x87(6) < 0xe2(1) < 0x12b(5) < 0x133(4) < 0x1b3(2) < 0x221(3).
得到最终密钥6 1 5 4 2 3。
在这里插入图片描述

阶段七:隐藏炸弹
实验介绍中说第四阶段之后会有附加字符串出现,查看代码,果然发现了问题,在phase_defused里调用了secret_phase函数,重点关注出现的地址,用gdb查看地址的内容。
在这里插入图片描述
这个地址里有一个字符串。
在这里插入图片描述
这个地址提示了字符串应该是跟在两个数字后面出现,而根据提示,又是在第四阶段之后才会有字符串,所以字符串只能是出现在第四阶段。
在这里插入图片描述
在第四个炸弹的密钥后面加上字符串“DrEvil”,查看结果。
在这里插入图片描述
发现不对劲,重新看了一下secret_phase函数,发现调用了函数fun7。
在这里插入图片描述
注意到下面的这一段代码:
在这里插入图片描述
这说明fun7函数的返回值只能是7。
在这里插入图片描述
通过gdb调试发现,ecx中的内容即为你输入的内容。下面查看0x804c088地址的内容:
在这里插入图片描述
看汇编代码,发现这是一个树状链表的递归,具体结构如下图:
在这里插入图片描述
遍历所有的可能,最终得到密钥为1001。

拆弹完成!!!
下面附上炸弹的汇编代码供大家学习参考。
链接:https://pan.baidu.com/s/1igLe3t9-UENE8diJCpcc6g
提取码:xqr7

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值