CSAPP:BOMB LAB
博客参考了知乎回答:https://zhuanlan.zhihu.com/p/28422249
Phase 1
objdump -d bomb > bomb.s
先将bomb反汇编并输出到bomb.s,-d参数为全部反汇编,还有一个-t参数可以输出程序的符号表,不过我不知道这个符号表有什么用。
分析main函数的代码

结合bomb.c函数

我们能比较容易看出main函数前面的汇编代码主要是做一些初始化和调用输入等功能,不是重点,我们直接关注phase_1开始我们的第一个小实验

第一行和最后一行是调整栈指针指向位置,接下来看下面 这里调用了一个 string_not_equal 函数,从函数名就可以发现这个函数肯定是判断字符串是否相等的,感兴趣有时间的同学可以去看这个函数的汇编码。
在调用完这个函数之后,程序检查了返回值是否为0,如果为0则跳转不爆炸。那么我们看是哪两个字符串在比较:
%esi和%edi是头两个参数寄存器,我们看看里面放了什么,%esi中放入了内存地址 0x402400 内的字符串,我们打印看看是什么

答案很明显了,我们再看看%edi里面放了什么

把read_line的返回值放入%edi中,很明显就是我们的输入字符串。
Phase1的答案即为地址0x402400储存的字符串。
Phase 2

很明显phase2一开始就调用了read_six_numbers函数,我们来分析它

sscanf第一个参数是空出来给输入的,第二个参数是输入模式串,我们可以看到地址为0x4025c3的内存存放着模式串,我们打印一下

很明显这是六个整数,scanf因此还要接收六个地址存放它们,我们可以看到用了剩下四个参数寄存器,并且用了两个位置的栈内存(一个位置为八个字节),这些地址都是以(%rsi)为起点的连续内存空间,其实这就在phase_2的栈帧中
参数整理完毕,我们看它调用了scanf函数后还对比了返回值,返回值保存输入的数目,因此这里的作用是保证输入了六个或以上个整数。
我们把目光放回phase_2函数,它先对比了第一个数是否是1,如果不是就boom,然后把第二个数的地址放到%rbx,终点地址放到%rbp中,然后对比前一个数的两倍是否和自身相等,如果不等就boom,不断循环直到终点地址跳出函数。
所以我们的答案是 1 2 4 8 16 32
Phase 3
这个Phase也很简单

逻辑是输入两个数,第一个数用来帮助跳转(jmbp 0x402470(,%rax,8))跳转到8%rax + 0x402470储存的地址中,我们用 x/16gx可以以16进制一次性打印16个giand word

可以看到储存的跳转地址,我们再看phase_3中的代码,就知道假如第一个输入为1就会跳转到400fb9,这时候第二个数要求为0x137即311。
所以答案为 1 311,注意答案不唯一。
Phase 4

很明显也是读取两个数,并且第一个数小于等于0xe,然后调用fun4要求返回值是0.
我们看fun4里面进行了一堆操作,其实我们可以直接用gdb单步查看寄存器里的值(如果你想用逻辑推理寄存器里面的值也可以,不过很麻烦)


我们可以发现%edi也就是输入的第1个数,要大于等于7并且小于等于7的时候fun4才会mov %0x0, %eax并且直接退出(而不是陷入递归)
所以答案是 7 0
Phase 5

这一阶段一开始读取了一个长度为6的字符串(前面$fs:0x28那行代码是用来保护栈帧的,具体内容见CSAPP 讲内存溢出那一章)
后面也很简单,逐个取出(取六个)输入字符(%rbx和%rdi里面就放了read_line的返回值)和0xf做&存入%rdx,然后取出偏移地址(0x40!24b0+%rdx)的值放到栈中,最后将栈中字符串和0x40245e处字符串比对,要求两者相等。


所以答案可以是 9?567 (不唯一)
Phase 6
分阶段看,第一阶段是读取六个数,这应该不用解释了
然后是一个多重循环:

干的事情就是外部6次循环,内部6-i次(后6-i个数)要求6个数互不相等,否则爆炸。

然后每个数字等于7-自身
然后是取出某些地址,具体逻辑是0x6032e0被数值1取出,数值2取出的是0x8(0x6032e0)存储的地址,具体内容是0x6032f0,数值3数值4,5,6都是这样取出的,我们用gdb打印就可以看出



以上注意:用来存地址的那些地址现在存的不是地址了,是下一个value
最后是判断顺序,未加8地址存储的(也就是下一个value)要比加8地址存储的(也就是原value)要小



浙公网安备 33010602011771号