目录
一.前言
在开始csapp bomb实验前,请确保自己能看懂基本的ATT格式的汇编语言,了解汇编中栈的作用何使用,明白函数调用时参数是如何传递的,明白16个寄存器的作用。
学会使用基本的gdb命令,break(设置断点),delete(删除断点),run(运行),step(逐语句),next(逐过程),continue(继续),disas(查看汇编代码),x(查看地址内容),i r 寄存器(查看寄存器内容)。
通过下面命令将bomb反汇编并将其存放到bomb.asm中,部分函数可能在下面分析中不会出现,需要你自己去分析。
>objdump -d bomb>bomb.asm
如果你已经准备好了,那就开始吧。
二.bomb
1.phase_1
进入gdb,通过指令 l 查看代码,通过 b 在phase_1(input)设置断点。
使用stepi 1,进入phase_1,使用disas查看汇编。观察到函数 string_not_equal接受两个参数%rdi(我们自己的输入)、%rsi,如果%rdi和%rsi相同则将%eax置零。同时如果返回值%eax为零则不会触发bomb。所以我们查看%rsi的值。
ok,我们得到第一个答案。
2.phase_2
分析read_six_number函数,明白函数将我们输入的六个数存放到栈中。分析0x401671到0x401685知道我们的输入需要满足 and
。令
,可以推出答案为 0 1 3 6 10 15。
3.phase_3
我们通过下面命令看看输入格式要求。
观察+67到+82,这段代码在计算jmp跳转的地址,同时在+56的代码要求第一个参数<7。(本人偷懒直接在+85查看计算好的地址)。
我们找到地址为0x40172b的代码,这段代码告诉我们第二个参数==0x1c7。
下面的代码说明字符参数等于%al的值,由上面%eax=0x71,查看ascii码,字符参数为q.
所以结果就为1 q 455
4.phase_4
该题考查我们对函数调用的理解。查看sscanf得到输入格式为%d %d(偷懒,自己通过x看)。看到func4的返回值不为4就bomb,同时第二个参数必须为4。
func(%rdi,%rsi=0,%rdx=14);
该函数接受三个参数,并且开始时%rsi,%rdx的初始值为0和14。通过构造递归树以及返回值为4=2+2,2=1+1,1=0+0+1。所以我们得到递归的路径为7>x,3>x,1<x,x=2。即
得到x=2,答案为2 4。
5.phase_5
该段代码较简单就不放代码了,主要功能即以输入的第一个参数作为数组下标开始,,同时开始对遍历的元素累加,但计数达到15时停止。
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
10 | 2 | 14 | 7 | 8 | 12 | 15 | 11 | 0 | 4 | 1 | 13 | 3 | 9 | 6 | 5 |
通过上面表格,可以知道以5为下标开始,结束时刚好为15,并且5没有被遍历。所以答案为5 115
6.phase_6
该图片展示的代码功能为判断输入的6个数字不重复,并且都小于等于6。
代码功能是按我们输入的数字顺序将链表的节点依次放入栈中。
按照栈中的顺序构建链表。
该图片的主要代码为+245--+251的代码,功能为比较前节点小于后节点。
查看链表的节点信息,通过上面我们知道,当我们将节点值按从小到大的排序,即可得到答案4 1 6 2 5 3。
7.secret_phase
这个隐藏的bomb藏在phase_defused中(如果你刚开始认真看了bomb.asm,你一定会发现的)。
查看输入的格式
上面的代码功能说明,只有当前面六个phase都成功并且在输入格为%d %d 的答案后面加入%s。
在+83和+90那两行发现后string 输入,利用x查看0x40348f的内容,为“DrEvil”。
进入secret_phase中发现其又调用了fun7(%rdi,%rsi),查看fun7。
发现其结构和功能都类似于func4。从secret_phase中得到fun7的返回值为5。通过x查看node,发现其结构类似于二叉树。
nxy表示该节点为第x行第y个节点。我们将5按fun7进行分解,5=2+2+1,2=1+1,1=0+0+1。
所以路径为
结果为0x2f=47
全部结果测试: