其他分享
首页 > 其他分享> > CSAPP炸弹实验bomblab

CSAPP炸弹实验bomblab

作者:互联网

bomblab是计组里面我做的最认真的一个实验了
折腾汇编两三个小时最后过关的感觉很有成就感!
这边给上我做的时候的一些过程,可以给大家参考

main函数分析

首先是找到main函数,发现它调用了从phase_1到phase_6这六个函数。这应该就是每一关需要看懂的函数了。

第一关: 入门

找到phase_1,代码如下:
第一关

我们看到0x08048b53的指令是将0x0804a1a4的值准备给strings_not_equal函数,于是我们在gdb中查看对应位置的值,得到
第一关gdb
于是可以猜测第一关的所需输入即为You can Russia from land here in Alaska.

于是开始第一关的尝试。非常重要的一步是在<explode_bomb>之前设置断点,找到该函数的入口地址是0x80490e6,即执行break *0x80490e6。然后输入命令run,进入程序,在输入提示的下一行输入You can Rusia from land here in Alska.,终端显示“Phase 1 defused. How about the next one?”表示第一关顺利通过。
第一关过关

第二关: 差等差数列

找到phase_2函数,代码如下:
第二关
按照上一关的联想,这一次的任务即为read_six_numbers,即输入6个数字。因此可以猜测是当6个数字输入正确时通过。

翻译过来就是从第二个数开始依次是数1加1、数2加2、数3加3、数4加4和数5加5。

解答:当输入的第一个数为0时,6个数依次为0、1、3、6、10、15
第二关过关

第三关: switch跳转表

找到phase_3函数,代码如下:
第三关
可以看到0x08048bce对应的操作为mov $0x804a3c3, %eax
于是查看对应地址的值,发现是"%d %d",于是可以得知是输入两个数字
第三关gdb1
首先我们看到当输入小于等于7时将值移到eax,然后根据eax的值进行跳址。可以看到这是一个典型switch跳转表,我们查看输入的第一个数为0时对应0x0804a200地址的值
第三关gdb2
然后根据计算,得到最后的结果为十进制-616,测试成功过关
第三关过关

第四关: 递归

找到phase_4函数,代码如下:
第四关
类比上题,我们已经知道0x0804a3c3对应值为"%d %d",可以知道这题同样也是要输入2个数字。
cmp $0x1,%eaxjle可以得知输入第二个数需要大于1,cmp $0x4,%eaxjle可以知道输入第一个数需要小于等于4,因此输入的第二个数的范围2到4
我们看到函数中调用了func4函数,于是我们查看func4
第四关func4

func4(n, a) = (n-1) + func4(n-1, a) + func4(n-2, a)
func4(1, a) = a
func4(0, a) = 0

phase_4中即是计算func4(5,a),于是当输入的第二个数为2,第一个数就为24
第四关过关

第五关:ASCII

找到phase_5函数,代码如下:
第五关

由于需要相加得0x41,凑配出0xa+5*0xb,查表得alllll,也就是这一关的过关密钥
第五关过关

第六关: 链表

找到phase_6函数,代码如下:
第六关
说实话当初看到这一大段代码,我脑壳都裂开,但还是耐下性子一行一行看了
这里把这一大段汇编代码分成4大部分

初始

从调用read_six_numbers可见这题又是输入6个数字

第一部分

第一部分,里面有一个循环

  1. eax等于输入第esi个数,给eax减一
  2. eax大于5就引爆炸弹,同时由于是无符号比较,即jbe,因此当eax值小于0时其会变成一个极大数,同样大于5。
  3. 将初始为1的esi与6比较,若相等则跳出循环进入第二部分
  4. 通过mov 0x10(%esp, %ebx, 4), %eaxcmp %eax, 0xc(%esp, %esi, 4)可以得出esi不能等于ebx+1
  5. ebx加1后当ebx小于等于5时回到4。否则跳回1。

这组循环非常的拗口,但是初步判断可以得知是限制输入的6个数的条件
仔细分析后得知这一段的功能是判断输入的6个数都要小于等于6并大于等于1,并且不能存在两两相等

第二部分

第二部分经过分析是当数组不越界时即对输入6个数进行操作。使每个数都对应其对于7的取反,也就是changed_input[i]=7-input[i]
由于有了前面的基础,这里就不进行逐行的汇编代码分析了。

第三部分

第三部分经过分析是在数组后的连续空间申请一个每个元素为8个字节的数组,记为tmp[6]
然后通过循环来实现tmp[i]=8*(changed_input[i]-1)+0x0804c13c。若changed_input[i]<1tmp[i]=0x0804c13c
与第二部分的结果相结合,可以得到tmp[i]=8*(6-input[i])+0x0804c13c。而这个0x0804c13c非常可疑,于是我们查看对应位置的值
第六关0x804c13c
我们看到这个就能猜出大概。这是一个链表。并且可以得出链表的具体形式
第六关链表结构
于是就可以知道,这一部分的操作是将我们输入的数字与链表元素相对应,6对应1,5对应2以此类推。

第四部分

第四个部分显然就是具体操作了。经过分析是对其进行大小比较,前一个需要大于等于后一个。由此可以知道,我们所需要的是输入按照值大到小的顺序对链表进行排序,同时注意反向对应。
链表序号1>3>4>6>5>2
输入序号6 4 3 1 2 5
第六关过关
到这里,这个炸弹就被破解了,是吗?

发现隐藏关卡

我们观察main函数中,每个phase函数后面都跟着一个phase_defuse函数,但在先前的分析中又不起作用,于是我们猜测这与隐藏关的触发有关。
发现隐藏关phase_defuse
从上往下看首先发现cmpl $0x6,0x804c3cc,估计是看你是否已经通过了前面6关,没有的话就直接跳到结束部分。若已经通过6关,应该会往下执行。又有一句出现了立即数的movl $0x804a3c9,0x4(%esp) , 用x/s 0x804a3c9,得到 "%d %d %s"。发现与phase3和phase4前面的输入相同都是2个数字
发现隐藏关gdb1
下面是movl $0x804a3d2,(%esp),同样地,得到"DrEvil",猜测便是激活所需的字符串
发现隐藏关gdb2
于是我们回去看到phase_3phase_4都是调用的sscanf函数,于是我们猜测是在phase_3phase_4后面额外输入DrEvil即可解锁
然后我们看到下面的指令有movl $0x0804a298,(%esp),我们查看对应地址的字符串,得到
发现隐藏关gdb3
可见至此隐藏关卡就解锁了
发现隐藏关发现
验证果然解锁了隐藏关卡

隐藏关: BST

找到secret_phase函数,代码如下:
隐藏关

那么问题就很简单,就是要让fun7返回4

下面看fun7的汇编代码
隐藏关fun7

  1. 若第二个参数b较小,再次调用fun7,传入参数a+4,b。然后将fun7的返回值乘2后返回该值。
  2. 当两个参数相等时返回0。
  3. 若b较大,则再次调用fun7,传入参数a+8,b。然后返回返回值的2倍加1。

我们在secret_phase里调用fun7传入的第一个参数为0x0804c088,查看其作为地址对应的值
隐藏关gdb1
所以可以得到我们一开始输入的并非数字加上字符串,而是只要求那个数字x,然后调用fun7并传参&36和x。
由于需要返回4,在几种分支情况中,可以得到需要b<*a,即输入的数字小于36。
我们查看0x0804c088及其后地址的对应值
隐藏关gdb2
可以看到这对应一个跳转表
隐藏关BST
画出其结构发现是一棵BST。
我们思考要得到4,方法只有(0*2+1)*2*2,也就是b<*a且b<*(a+4)且b>*(*(a+4)+4)且b==(*(*(a+4)+4)+8)
也就是对应BST从根结点开始左,左,右对应结点的值即0x7
于是输入0x7对应十进制7,顺利通过所有关卡!!!
隐藏关过关

实验结果

第一关:You can Russia from land here in Alaska.
第二关:0 1 3 6 10 15(不唯一)
第三关:0 -616(不唯一)
第四关:24 2(不唯一)
第五关:alllll(不唯一)
第六关:6 4 3 1 2 5
隐藏关:7

标签:CSAPP,函数,func4,bomblab,eax,炸弹,phase,ebx,输入
来源: https://blog.csdn.net/Broken__Ice/article/details/111145372