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:似乎还有隐藏彩蛋,等以后分析