csapp--拆解二进制炸弹

阶段一:
操作步骤:
1:gdb bomb;
2:设置炸弹断点 break explode_bomb;
3:设置断点 break phase_1;
4:输入地址:x/s 0x402680,查看值;
csapp--拆解二进制炸弹
4: r 运行;
5:输入 Please do not use brute force to defuse your bomb!即可;
分析过程:一眼看到这个汇编代码,一开始很迷惑,发现%esi 被赋予一个初值,而且长度和地址相似,
于是直接查看该地址发现字符串“Please do not use brute force to defuse your bomb!”,此后调用比
较字符串的函数,相等不爆,不相等就爆炸。于是可知,我们需要输入与地址 0x402680 上一样的字符串,
即可。字符函数分析如下截图
csapp--拆解二进制炸弹
主函数分析:
csapp--拆解二进制炸弹
运行结果:
csapp--拆解二进制炸弹
阶段二
操作步骤:
1:gdb bomb;
2:设置炸弹断点 break explode_bomb;
3:设置断点 break phase_2;
4:r 运行;
分析过程:
1:
csapp--拆解二进制炸弹
六个数的输入;
2:
发现规律:
Num1 + 1 = num2;
Num2 + 2 = num3;
Num3 + 3 = num4;
Num4 + 4 = num5;
Num5 + 5 = num6;
即公差满足等差数列的函数;
csapp--拆解二进制炸弹
运行结果:
csapp--拆解二进制炸弹
阶段三
操作步骤:
1:gdb bomb;
2:设置炸弹断点 break explode_bomb;
3:设置断点 break phase_3;
4:r 运行;
5:查看跳转表:x/6gx 0x4026f0
csapp--拆解二进制炸弹
6:根据跳转表与输入的数字计算出对应的数值即可。
分析过程:
根据如下判断只需输入一个数字即可。
cmp $0x1,%eax
383 400fda: 7f 05 jg 400fe1 <phase_3+0x30>//当长度大于 1 时,有符号
384 400fdc: e8 c6 06 00 00 callq 4016a7 <explode_bomb>
jmpq *0x4026f0(,%rax,8)//选址即可。
csapp--拆解二进制炸弹
运行结果
csapp--拆解二进制炸弹
阶段四
操作步骤:
1:gdb bomb;
2:设置炸弹断点 break explode_bomb;
3:设置断点 break phase_4;
4:r 运行;
5:输入两个参数值;
分析过程:
递归函数 c 语言实现:
csapp--拆解二进制炸弹
1:首先判断输入的是两个数字,否则爆炸;
2:传入参数,然后调用递归函数,fun4;
3:首先递归函数的返回值必须等于 7,否则爆炸;
4:那么根据已经给的定值 7,我们可以确定递归调用的第二个参数值;
5:然后再根据反汇编写出源程序即可;
部分分析如截图过程:
csapp--拆解二进制炸弹
csapp--拆解二进制炸弹
csapp--拆解二进制炸弹
运行结果:
csapp--拆解二进制炸弹
阶段五
操作步骤:
1:gdb bomb;
2:设置炸弹断点 break explode_bomb;
3:设置断点 break phase_5;
4:查看两个地址中的字符串内容
csapp--拆解二进制炸弹
csapp--拆解二进制炸弹
4:r 运行;
5:输入字符串;
分析过程
1:
csapp--拆解二进制炸弹
确定长度为 6 的输入;
2:
csapp--拆解二进制炸弹
与运算取低四位;
3:
csapp--拆解二进制炸弹
比较字符串;
4:
csapp--拆解二进制炸弹
结果验证;
其中隐藏在两个地址中的字符串分别是: ”maduiersnfotvbylSo you think you can stop the bomb with
ctrl-c, do you?”和“flames”;
题目的意思是根据我们输入的字符串的每一个字符的第四位当作偏移量,去所给的一大串字符串中寻
找计算出来的指定位置的字符,用他们构成长度为 6 的字符串,并且与“flames”长度相等,即可。
csapp--拆解二进制炸弹
运行结果
csapp--拆解二进制炸弹
阶段六
1:gdb bomb;
2:设置炸弹断点 break explode_bomb;
3:设置断点 break phase_6;
4:r 运行;
5:1,2,3,4,5,6;//因为都要小于等于 6,并且不能有重复的。
分析过程:
在进行开始阶段的输入的六个数排除重复的可能(即六个数都不一样,范围小于等于六);
csapp--拆解二进制炸弹
之后,在读取 mov $0x6042f0,%edx//存储链表指针的首地址时,发现该地址给出的时 node,很明
显后面的操作很大可能是与链表有关的。并且在
csapp--拆解二进制炸弹
mov %rdx,0x20(%rsp,%rsi,2)中发现:a[0]等于 1 时,意思就是链表的顺序是由输入的数组数字决定的,
比如 2,4,1,5,6,3,那么头节点就应该是 3 号节点,第二个指针为 1 号结点。而且在进行如此循环操
作之后输链表的地址(即顺序)是:
csapp--拆解二进制炸弹
根据我们前面的分析,这个链表的节点顺序是按照我们输入的顺序决定的,并且最大的是 1 号,次之往后
退。那么对应的顺序是:4 6 2 1 3 5 ,那么输入的数组是 7-4=3,7-6=1,7-2=5,7-1=6,7-3=4,7-5=2,
即 3 1 5 6 4 2.
csapp--拆解二进制炸弹
csapp--拆解二进制炸弹
csapp--拆解二进制炸弹
运行结果:
csapp--拆解二进制炸弹
阶段七
首先找到的方式:
一:在 phase_defused 中发现有调用 secret_phase 函数
csapp--拆解二进制炸弹
二:经过分析发现,在输入两个数的答案地方,可以允许输入第三个单词:DrEvill
csapp--拆解二进制炸弹
csapp--拆解二进制炸弹
三:在输入我的答案 132 4 之后加上 DrEvil 即可在第六关之后进入秘密关卡。

进入后的分析:
1:读入字符串,并且将字符串转化为数字;
csapp--拆解二进制炸弹
2:返回值要小于等于 1001,即我们输入的数字要小于等于 1001;
csapp--拆解二进制炸弹
3:输入指令 x/8x 0x604110
csapp--拆解二进制炸弹
4:调用 fun7 函数,并且传入了树的根节点地址与我们输入的值
csapp--拆解二进制炸弹
5:fun7 函数分析
csapp--拆解二进制炸弹
1)如果指针为空,就返回
csapp--拆解二进制炸弹
2)结点的值小于等于我们输入的参数的值
csapp--拆解二进制炸弹
3)结点值等于我们输入的参数的值时,返回并结束
csapp--拆解二进制炸弹
csapp--拆解二进制炸弹
4)结点的值小于我们输入的参数的值时,递归调用自己,并且传入右子树地址
csapp--拆解二进制炸弹
5)结点的值大于我们输入的参数的值时,递归调用自己,并且传入左子树地址
csapp--拆解二进制炸弹
6)输入指令,按照返回值必须为 7,发现都是王右子树递归,并且次数为 3 次
csapp--拆解二进制炸弹
得到 0x3e9(H) = 1001(10);
即结束。