CA2_BombLab记录
前言
Todo:晚上再补充内容
强烈建议做这个lab之前先看完CSAPP对应部分以及网课对应部分,特别是要把常用寄存器的作用搞明白
第一题
先观察bomb.c文件,发现有几个重要的函数,其中phase_1到phase_6是我们需要破解的,read_line是用来读取用户输入的,phase_defused是用来输出破解成功的信息的,explode_bomb是用来输出破解失败的信息的
第一题我们可以先在phase_1处打上断点,然后随便输入一个值,观察情况
phase_1及其短小,其中有一个地址0x402400,我们用x/s 0x402400查看一下,发现是一个字符串Border relations with Canada have never been better.,就得到答案了
第二题
首先对phase_2打上断点,然后随便输入一个值
发现会首先调用read_six_numbers,暗示我们应该输入6个数字0x400f0a处有cmpl $0x1,(%rsp)其后面一行是je 0x400f30 <phase_2+52>说明返回值必须为1
所以给read_six_numbers打上断点,看看它在干什么

发现有一连串的操作,挺绕的,先继续往下看到有一个地址0x4025c3,用x/s查看一下,发现内容是”%d %d %d %d %d %d”,外加0x40148f处的 cmp $0x5,%eax(成功读取的数值不是6就直接引爆炸弹) 说明我们确实应该输入6个数字.
退出之前在仔细观察一下那一些leaq指令发现他们是以rsi寄存器中存储的地址为基准的,再回头看看phase_2的代码,我们发现它在调用read_six_numbers之前申请了0x28位地址空间,然后把栈顶指针rsp赋值给了rsi(作为参数传递),所以这个read_six_numbers函数是通过栈来传递参数的

我尝试输入 1 2 3 4 5 6,然后在read_six_numbers退出的时候参看栈的情况

我的猜测是正确的,我们的输入被逆序压入栈中(一个int类型占用4bytes)
继续往下看,发现下一行语句是cmpl $0x1,(%rsp),而rsp处存储第一个输入,所以第一个数是1,再分析这些语句

我们发现有一个循环,每循环一次数值*2,直到循环结束,所以答案是1 2 4 8 16 32
第三题

首先对Phase_3打上断点,然后随便输入一个值

发现一个地址,用x/s 0x4025cf查看,

根据Phase_2的经验,我们应该要输入两个数字
继续往下看,0x400f60处的cmp $0x1,%eax也表明我们至少要输入两个数字,否则直接explode_bomb
重新随便输入两个数字,发现0x400f6a处的cmpl $0x7,0x8(%rsp),rsp是栈指针,0x8(%rsp)是我们输入的第一个元素,所以说明我们输入的第一个数字不能大于7

接下来就是重点了,我们看见0x400f75处有指令jmp *0x402470(,%rax,8)

这是一个大坑,这条指令表示直接跳转到 0x402470 + M8 所存储的地址处(而不是 0x402470 + M8 处!!!)
使用x/x查看0x402470处的内容

发现是一连串地址(顺序是从右到左是因为Intel处理器采用的是小端排序)
对应关系

上面若干跳转最后都变成比较第二个数和 %eax 中数是否相等,所以第一个数字和第二个数字有对应关系:
| 第一个数字 | 第二个数字十六进制 | 第二个数字十进制 |
|---|---|---|
| 0 | cf | 207 |
| 1 | 137 | 311 |
| 2 | 2c3 | 707 |
| 3 | 100 | 256 |
| 4 | 185 | 389 |
| 5 | ce | 206 |
| 6 | 2aa | 682 |
| 7 | 147 | 327 |
答案是任意一个都行,比如第一个数字是 0,第二个数字是 207
第四题
照常给phase_4打上断点,我们发现依旧是输入两个数字
0x40102e处的cmpl $0xe,0x8(%rsp)和0x401033处的jbe 0x40103a <phase_4+46>表示第一个数字必须小于0xe
在0x401058处发现它会调用func4,通过观察,似乎edi,esi,edx寄存器被作为参数传递给了func4
继续往后看,发现0x40104d处的test %eax,%eax和0x40104f处的jne 0x401058 <phase_4+76>表示eax(返回值)必须等于0
然后,在第0x401051行,cmpl $0x0,0xc(%rsp),第0x401056行je 0x40105d <phase_4+81>得出第二个参数应该是0
打一个断点,看func4到底在搞什么东西😁

很明显,这是一个递归,在网上找了一张流程图(我画的太丑了,不想放上来😂)

通过流程图可以看出,有一条路是不用走递归的,(就是最左边一条)

所以edi(就是我们输入的第一个参数)应该是7
所以输入应该是7 0
第五题
照常打上断点,随便输入一个值

发现有调用string_length函数,所以我们应该输入一个字符串
仔细下一行我们可以看出字符串长度应该为6
发现了一个地址,指向的字符串是“maduiersnfotvbylSo you think you can stop the bomb with ctrl-c, do you?”明显长度不对
给那一行打上断点,查看运行至那一行时候的rdx寄存器的值,然后用x/s查看0x4024b0的字符串,发现是“secret phase!”靠,又被摆了一道,看来不能投机取巧,只能慢慢分析了
往后看,就会发现有一个地址0x40245e似乎被传递给了strings_not_equal,对应的字符串是“flyers” ,长度是对的,应该就是目标字符串了
所以,应该分析循环的逻辑

逻辑有点复杂,所以我画了一张流程图来辅助理解

可以看出,“Flyers”对应字符串“maduiersnfotvbylSo you think you can stop the bomb with ctrl-c, do you?”中的位置分别是9,15,14,5,6,7,我们需要让我们输入的字符串模16得到的数是这几个数
为了方便,我选取了ionefg
第六题
第六题的代码很长,我先把它分成几个部分
第一部分
照常打上断点,随便输入一个值
发现在经历了一系列栈操作后,又调用了read_six_numbers函数,根据第二题的经验,输入的6个数字会被依次逆序压入栈中,分别存储在%rsp、%rsp+4、%rsp+8、%rsp+12、%rsp+16、%rsp+20处
虽然这个函数的代码很长,有很多跳转语句,但是经过仔细观察,我发现可以大致分为几个部分

第一部分依次遍历每个元素,保证各个元素在1-6之间且不相等
第二部分
第二部分用7-数组的逐个元素,并更新各个数组元素
在0x401183处我们发现了一个地址,使用x/128x查看附近的内存,我们发现它是叫node_n,其中每个node偏移8位的位置指向下一个node,所以它是一个链表

第三部分
接下来就进入了第三部分


经过分析,我们发现第二个部分是把各节点的地址依次存放进栈中
我们查看一下内存的情况,发现在0x7fffffffda30到0x7fffffffda50处依次存储着各个值,这些值的顺序是我们输入数字的顺序

第四部分
第四部分是验证数据(存储在rsp+20开始的指针序列)是否是按照逆序排列
按照逆序,应该是3 4 5 6 1 2所以指针应该是(顺序是node3->node4->node5->node6->node1->node2)
node中数据的排序3 4 5 6 1 2,所以输入4 3 2 1 6 5
结束!

Todo:似乎还有隐藏彩蛋,等以后分析