CSAPP-Lab2:BombLab
目录
1、实验文档注释
2、实验题目
2.1 分析bomb.c
2.2 反汇编phase_1
2.3 反汇编phase_2
2.4 反汇编phase_3
2.5 反汇编phase_4
2.6 反汇编phase_5
2.7 反汇编phase_6
2.8 反汇编phase_defused
3、总结
1、实验文档注释
邪恶博士公司(PERPETRATOR)特此授予您(受害者)使用此炸弹(bomb)的明确许可。这是一个有时限的许可证,在受害者死亡时到期。PERPETRATOR对受害者的损伤、沮丧、精神错乱、虫眼、腕管综合征、睡眠不足或其他伤害不承担任何责任。除非PERPETRATOR想获得荣誉。受害者不得将此炸弹源代码分发给PERPETRATER的任何敌人。VICTIM不得调试、逆向工程、运行“字符串”、反编译、解密或使用任何其他技术来获得BOMB的知识并消除BOMB。在处理此程序时,可能不穿防炸弹服装。主持人不会为主持人缺乏幽默感而道歉。在法律禁止BOMB的情况下,本许可证无效。
2、实验题目
给了一个 bomb.c(无法编译)和 bomb,运行 bomb 会要求输入六个字符串,任何一个错误的都会BOOM!!! 我们必须利用反汇编工具逆向分析这个文件,找出这六个字符串,从而正确输入。
先启动 gdb 测试一下
gdb bomb

输入 r ,然后输入 test 测试

以上为bomb程序初步运行过程。
2.1 分析bomb.c
代码主要结构为:
input = read_line(); /* Get input */phase_1(input); /* Run the phase */phase_defused(); /* Drat! They figured it out! *//* Let me know how they did it.*/printf("Phase 1 defused. How about the next one?\n");
1、将我们输入的字符串传入 phase_1;
2、若可以执行到 phase_defused 函数,则代表拆除成功(盲猜拆除错误时直接退出程序)
所以我们需要分析这个 phase_1 ,使用正确的输入得到函数可以正确返回
2.2 反汇编phase_1
disassemble phase_1
0x0000000000400ee0 <+0>: sub $0x8,%rsp0x0000000000400ee4 <+4>: mov $0x402400,%esi0x0000000000400ee9 <+9>: callq 0x401338 0x0000000000400eee <+14>: test %eax,%eax0x0000000000400ef0 <+16>: je 0x400ef7 0x0000000000400ef2 <+18>: callq 0x40143a 0x0000000000400ef7 <+23>: add $0x8,%rsp0x0000000000400efb <+27>: retq
1、分配栈帧
2、将 0x402400 放入 esi (存放第二个函数参数的寄存器)
3、调用
4、按位与比较
5、相等跳转
6、不相等跳转
较明显,此处是将 0x402400 的值放入函数中比较,故该值大概率为phase_1答案,直接使用语句 x/s 0x402400 查看
0x402400: "Border relations with Canada have never been better."
所以第一题答案为:Border relations with Canada have never been better.
2.3 反汇编phase_2
disassemble phase_2
0x0000000000400efc <+0>: push %rbp0x0000000000400efd <+1>: push %rbx0x0000000000400efe <+2>: sub $0x28,%rsp
1、rbp 入栈
2、rbx(caller save)入栈
3、分配栈帧
0x0000000000400f02 <+6>: mov %rsp,%rsi0x0000000000400f05 <+9>: callq 0x40145c
1、将 rsp 给 rsi,便于后续操作 rsp
2、rsi作为第二个参数调用
不妨看看
0x000000000040145c <+0>: sub $0x18,%rsp0x0000000000401460 <+4>: mov %rsi,%rdx0x0000000000401463 <+7>: lea 0x4(%rsi),%rcx0x0000000000401467 <+11>: lea 0x14(%rsi),%rax0x000000000040146b <+15>: mov %rax,0x8(%rsp)0x0000000000401470 <+20>: lea 0x10(%rsi),%rax0x0000000000401474 <+24>: mov %rax,(%rsp)0x0000000000401478 <+28>: lea 0xc(%rsi),%r90x000000000040147c <+32>: lea 0x8(%rsi),%r80x0000000000401480 <+36>: mov $0x4025c3,%esi0x0000000000401485 <+41>: mov $0x0,%eax0x000000000040148a <+46>: callq 0x400bf0 <__isoc99_sscanf@plt>0x000000000040148f <+51>: cmp $0x5,%eax0x0000000000401492 <+54>: jg 0x401499 0x0000000000401494 <+56>: callq 0x40143a 0x0000000000401499 <+61>: add $0x18,%rsp0x000000000040149d <+65>: retq
直接看不直观,建议自己画个栈,以 rsi 为头,跟着走一遍,箭头代表指向,最终如下:

所以此时传入了 6 个参数,4 个存入寄存器,2 个存入栈。此时可通过访问 rsi(注意,上层函数的 rsp 即等于此处 rsi )查看 6 个数。返回到上层 phase_2
0x0000000000400f0a <+14>: cmpl $0x1,(%rsp)0x0000000000400f0e <+18>: je 0x400f30 0x0000000000400f10 <+20>: callq 0x40143a 0x0000000000400f15 <+25>: jmp 0x400f30 0x0000000000400f17 <+27>: mov -0x4(%rbx),%eax0x0000000000400f1a <+30>: add %eax,%eax0x0000000000400f1c <+32>: cmp %eax,(%rbx)0x0000000000400f1e <+34>: je 0x400f25 0x0000000000400f20 <+36>: callq 0x40143a 0x0000000000400f25 <+41>: add $0x4,%rbx0x0000000000400f29 <+45>: cmp %rbp,%rbx0x0000000000400f2c <+48>: jne 0x400f17 0x0000000000400f2e <+50>: jmp 0x400f3c 0x0000000000400f30 <+52>: lea 0x4(%rsp),%rbx0x0000000000400f35 <+57>: lea 0x18(%rsp),%rbp0x0000000000400f3a <+62>: jmp 0x400f17 0x0000000000400f3c <+64>: add $0x28,%rsp0x0000000000400f40 <+68>: pop %rbx0x0000000000400f41 <+69>: pop %rbp0x0000000000400f42 <+70>: retq
1、比较 0x01,可知第一个数为 0x01,正确则跳转+52
2、rcx 的值传入 rbx,rbp 后文用作循环终止条件,跳转+27,将 rbx 指向位置的前一个数(即 1)翻倍与rbx比较,则第二个数为 2,跳转+41
3、rbx 地址+0x04,指向第三个数,cmp 可理解为判断循环是否该终止,未终止则跳回+27
4、循环将 rbx 前一个数的两倍与当前 rbx 比较,则可知后续数都是2倍关系
所以第二题答案为:1 2 4 8 16 32
2.4 反汇编phase_3
disassemble phase_3
0x0000000000400f43 <+0>: sub $0x18,%rsp0x0000000000400f47 <+4>: lea 0xc(%rsp),%rcx0x0000000000400f4c <+9>: lea 0x8(%rsp),%rdx0x0000000000400f51 <+14>: mov $0x4025cf,%esi0x0000000000400f56 <+19>: mov $0x0,%eax0x0000000000400f5b <+24>: callq 0x400bf0 <__isoc99_sscanf@plt>0x0000000000400f60 <+29>: cmp $0x1,%eax0x0000000000400f63 <+32>: jg 0x400f6a 0x0000000000400f65 <+34>: callq 0x40143a
1、存栈帧
2、分别存入 rcx 和 rdx
3、将格式化字符串 "%d %d" 的地址 0x4025cf 存储到 esi 寄存器中,用于为 sscanf 函数提供解析格式
4、调用 sscanf 函数开始解析用户输入,将输入内容按照 "%d %d" 的格式拆分为两个整数,并将这两个整数存储到 rcx 和 rdx 位置上
5、看返回值的个数,大于 1 跳到+39
0x0000000000400f6a <+39>: cmpl $0x7,0x8(%rsp)0x0000000000400f6f <+44>: ja 0x400fad
1、若 rdx 大于 7,跳转 bomb
0x0000000000400f71 <+46>: mov 0x8(%rsp),%eax0x0000000000400f75 <+50>: jmpq *0x402470(,%rax,8)
1、把 rdx 值传入 eax
2、跳转到 (0x402470 + %rax * 8) 的位置去
3、若 rax 为 0 ,则跳转到 0x402470,check一下,是跳转到 0x400f7c
(gdb) x/x 0x402470
0x402470: 0x7c
跳转到 0x400f7c
0x0000000000400f7c <+57>: mov $0xcf,%eax0x0000000000400f81 <+62>: jmp 0x400fbe
1、0xcf 存入 eax
2、跳转+123
0x0000000000400fbe <+123>: cmp 0xc(%rsp),%eax0x0000000000400fc2 <+127>: je 0x400fc9
1、比较 rcx 和 0xcf是否相等
2、相等则跳转结束
注:该题答案不唯一,第一个数的取值会导致第个数变化
所以第三题答案之一为:0 207
2.5 反汇编phase_4
disassemble phase_4
0x000000000040100c <+0>: sub $0x18,%rsp0x0000000000401010 <+4>: lea 0xc(%rsp),%rcx0x0000000000401015 <+9>: lea 0x8(%rsp),%rdx0x000000000040101a <+14>: mov $0x4025cf,%esi0x000000000040101f <+19>: mov $0x0,%eax0x0000000000401024 <+24>: callq 0x400bf0 <__isoc99_sscanf@plt>0x0000000000401029 <+29>: cmp $0x2,%eax0x000000000040102c <+32>: jne 0x401035
不再赘述,输入 2 个数,否则 bomb
0x000000000040102e <+34>: cmpl $0xe,0x8(%rsp)0x0000000000401033 <+39>: jbe 0x40103a 0x0000000000401035 <+41>: callq 0x40143a
1、比较 14 和 rdx
2、<= 则跳转,> 则 bomb
0x000000000040103a <+46>: mov $0xe,%edx0x000000000040103f <+51>: mov $0x0,%esi0x0000000000401044 <+56>: mov 0x8(%rsp),%edi0x0000000000401048 <+60>: callq 0x400fce 0x000000000040104d <+65>: test %eax,%eax0x000000000040104f <+67>: jne 0x401058
1、0x0e 存 edx,0x00 存 esi, a 存 edi
2、调用函数
3、确认返回值,不等于 0 的话,爆炸
4、看看
0x00400fce <+0>: sub $0x8,%rsp //栈帧0x00400fd2 <+4>: mov %edx,%eax //eax=0x0e0x00400fd4 <+6>: sub %esi,%eax //eax=0x0e-0=0x0e0x00400fd6 <+8>: mov %eax,%ecx //ecx=0x0e0x00400fd8 <+10>: shr $0x1f,%ecx //逻辑右移31位,ecx=00x00400fdb <+13>: add %ecx,%eax //eax=0x0e+0=0x0e0x00400fdd <+15>: sar %eax //eax=0x07,算术右移(补符号)0x00400fdf <+17>: lea (%rax,%rsi,1),%ecx //ecx=0x07+0x00=0x070x00400fe2 <+20>: cmp %edi,%ecx //%ecx-%edi=0x07-a0x00400fe4 <+22>: jle 0x400ff2 //a>=0x07则跳转+360x00400fe6 <+24>: lea -0x1(%rcx),%edx0x00400fe9 <+27>: callq 0x400fce 0x00400fee <+32>: add %eax,%eax0x00400ff0 <+34>: jmp 0x401007 0x00400ff2 <+36>: mov $0x0,%eax //eax=0x00,返回值0x00400ff7 <+41>: cmp %edi,%ecx //%ecx-%edi0x00400ff9 <+43>: jge 0x401007 //a<=0x07则跳转+570x00400ffb <+45>: lea 0x1(%rcx),%esi0x00400ffe <+48>: callq 0x400fce 0x00401003 <+53>: lea 0x1(%rax,%rax,1),%eax0x00401007 <+57>: add $0x8,%rsp0x0040100b <+61>: retq
1、挺长的,注释写里面了,可以看出 第一个参数需要满足 >=0x07 和 <=0x07,为 0x07
2、回到 phase_4
0x000000000040104d <+65>: test %eax,%eax0x000000000040104f <+67>: jne 0x401058 0x0000000000401051 <+69>: cmpl $0x0,0xc(%rsp)0x0000000000401056 <+74>: je 0x40105d 0x0000000000401058 <+76>: callq 0x40143a 0x000000000040105d <+81>: add $0x18,%rsp0x0000000000401061 <+85>: retq
1、前文提到,确认返回值,不等于 0 的话则跳转+76爆炸
2、比较第二个参数和 0x00
3、相等则跳转+81结束,则第二个参数为 0
所以第4题答案为:7 0
2.6 反汇编phase_5
disassemble phase_5
0x0000000000401062 <+0>: push %rbx0x0000000000401063 <+1>: sub $0x20,%rsp0x0000000000401067 <+5>: mov %rdi,%rbx0x000000000040106a <+8>: mov %fs:0x28,%rax0x0000000000401073 <+17>: mov %rax,0x18(%rsp)0x0000000000401078 <+22>: xor %eax,%eax0x000000000040107a <+24>: callq 0x40131b 0x000000000040107f <+29>: cmp $0x6,%eax0x0000000000401082 <+32>: je 0x4010d2 0x0000000000401084 <+34>: callq 0x40143a
1、rdi 存入 rbx
2、fs 段偏移28的值存入 0x18(%rsp) (防止缓冲区溢出)
3、eax 异或清0
4、调用
0x00000000004010d2 <+112>: mov $0x0,%eax0x00000000004010d7 <+117>: jmp 0x40108b
1、0 放入 eax
2、跳转+41
0x000000000040108b <+41>: movzbl (%rbx,%rax,1),%ecx0x000000000040108f <+45>: mov %cl,(%rsp)0x0000000000401092 <+48>: mov (%rsp),%rdx0x0000000000401096 <+52>: and $0xf,%edx0x0000000000401099 <+55>: movzbl 0x4024b0(%rdx),%edx0x00000000004010a0 <+62>: mov %dl,0x10(%rsp,%rax,1)0x00000000004010a4 <+66>: add $0x1,%rax0x00000000004010a8 <+70>: cmp $0x6,%rax0x00000000004010ac <+74>: jne 0x40108b
1、rbx 存的是输入的 6 个数/字母,rax 初始为 0,则 ecx=rsi
2、ecx 的低 8 位放入 rsp,放入 rdx
3、取 edx 的低 4 位
4、取 0x4024b0 中的字符串,以 %rdx 为索引取一个字母,放入 edx
5、将 edx 的低 8 位存在 rsp+0x10 开始的位置
6、循环 6 次,得到以 rsp+0x10 开始的 6 个字母
0x00000000004010ae <+76>: movb $0x0,0x16(%rsp)0x00000000004010b3 <+81>: mov $0x40245e,%esi0x00000000004010b8 <+86>: lea 0x10(%rsp),%rdi0x00000000004010bd <+91>: callq 0x401338 0x00000000004010c2 <+96>: test %eax,%eax0x00000000004010c4 <+98>: je 0x4010d9 0x00000000004010c6 <+100>: callq 0x40143a
1、0x00 给 rsp+0x16,做字符串结束标志
2、0x40245e(flyers)给 esi
3、依次比较,所以我们需要让前文得到的 rsp+0x10 的 6 个字母为flyers
回看+41处的代码:
0x000000000040108b <+41>: movzbl (%rbx,%rax,1),%ecx0x000000000040108f <+45>: mov %cl,(%rsp)0x0000000000401092 <+48>: mov (%rsp),%rdx0x0000000000401096 <+52>: and $0xf,%edx0x0000000000401099 <+55>: movzbl 0x4024b0(%rdx),%edx0x00000000004010a0 <+62>: mov %dl,0x10(%rsp,%rax,1)0x00000000004010a4 <+66>: add $0x1,%rax0x00000000004010a8 <+70>: cmp $0x6,%rax0x00000000004010ac <+74>: jne 0x40108b
通过对输入的rbx开始的六个数,每个数取最低4位作为索引,所以找到对应的索引值就好。对应的低 4 位分别为:f-1001 l-1111 y-1110 e-0101 r-0110 s-0111
对应到字母的ascii码,则取 IONEFG
所以第 5 题答案为:IONEFG
2.7 反汇编phase_6
disassemble phase_6
0x00000000004010f4 <+0>: push %r140x00000000004010f6 <+2>: push %r130x00000000004010f8 <+4>: push %r120x00000000004010fa <+6>: push %rbp0x00000000004010fb <+7>: push %rbx0x00000000004010fc <+8>: sub $0x50,%rsp0x0000000000401100 <+12>: mov %rsp,%r130x0000000000401103 <+15>: mov %rsp,%rsi0x0000000000401106 <+18>: callq 0x40145c
1、不赘述,保存参数,分配栈帧,call函数
2、函数在 phase_2 中介绍过,所以用此时的 rsp/rsi/r13 都可以按顺序访问得到6个参数
<+23>: mov %rsp,%r14 //r14=rsp/rsi/r13
<+26>: mov $0x0,%r12d //r12d=0x00
<+32>: mov %r13,%rbp //rbp=r13/rsp/rsi
<+35>: mov 0x0(%r13),%eax //eax=r13/rsp/rsi=data[0]
<+39>: sub $0x1,%eax //eax=eax-1
<+42>: cmp $0x5,%eax //eax-0x05
<+45>: jbe 0x401128 //<=5则跳转+52
<+47>: callq 0x40143a //否则bomb
<+52>: add $0x1,%r12d //r12d=0x01
<+56>: cmp $0x6,%r12d //r12d-0x06
<+60>: je 0x401153 //相等则跳出,猜测r12d拿来计数循环6次
<+62>: mov %r12d,%ebx //ebx=r12d
<+65>: movslq %ebx,%rax //rax=ebx
<+68>: mov (%rsp,%rax,4),%eax //eax=rsp+rax*4=rsp+0x04=data[1]
<+71>: cmp %eax,0x0(%rbp) //rbp-eax=data[0]-data[1]
<+74>: jne 0x401145 //!=则跳转+81
<+76>: callq 0x40143a //相等则爆炸
<+81>: add $0x1,%ebx //ebx=ebx+1
<+84>: cmp $0x5,%ebx //ebx-0x05
<+87>: jle 0x401135 //<=5跳回+65,循环保证后面不与当前重复
<+89>: add $0x4,%r13 //r13=r13+0x04
<+93>: jmp 0x401114 //跳转32,执行data[1]
1、太长写注释里了
2、总结为:输入 6 个不同的数、值小于 6
3、运行完跳入+95
<+95>: lea 0x18(%rsp),%rsi //rsi=data[6],没数据
<+100>: mov %r14,%rax //rax=r14=rsi=data[0]
<+103>: mov $0x7,%ecx //ecx=0x07
<+108>: mov %ecx,%edx //edx=ecx=0x07
<+110>: sub (%rax),%edx //edx=edx-rax=0x07-data[0]
<+112>: mov %edx,(%rax) //rax=edx,其实就是data[0]=7-data[0]
<+114>: add $0x4,%rax //rax=rax+0x04=data[1]
<+118>: cmp %rsi,%rax //rax-rsi,判断有没有执行完6个数
<+121>: jne 0x401160 //如果不相等,跳转+108再执行
<+123>: mov $0x0,%esi //esi=0x00
<+128>: jmp 0x401197 //跳转+163
1、注释
2、相当于 data[x] = 7 - data[x],所以此时的 data[x] 变成了 >1
3、顺序执行+123
4、跳转+163
<+130>: mov 0x8(%rdx),%rdx //rdx=rdx+0x08,向后一个节点
<+134>: add $0x1,%eax //eax=eax+0x01=0x02
<+137>: cmp %ecx,%eax //eax-ecx
<+139>: jne 0x401176 //!=0跳转+130,循环就是node像后移data[x]
<+141>: jmp 0x401188 //跳转+148
<+143>: mov $0x6032d0,%edx //edx=$0x6032d0=0x0000014c,是一个链表
<+148>: mov %rdx,0x20(%rsp,%rsi,2) //rsp+rsi*2+0x20(rsp+0+0x20)=某一个节点
<+153>: add $0x4,%rsi //rsi=rsi+0x04
<+157>: cmp $0x18,%rsi //rsi-0x18
<+161>: je 0x4011ab //相等跳出去(那就前一次判断先不进入这边)
<+163>: mov (%rsp,%rsi,1),%ecx //ecx=rsp+rsi*1=data[0]
<+166>: cmp $0x1,%ecx //ecx-0x01
<+169>: jle 0x401183 //<=1则跳转+143
<+171>: mov $0x1,%eax //否则eax=0x01
<+176>: mov $0x6032d0,%edx //edx=$0x6032d0=0x0000014c,是一个链表
<+181>: jmp 0x401176 //跳转+130
1、注释
2、简化一下:以 data[x] 为顺序,依次去查找 node[data[x]] 存在 rsp+0x20 起始的位置
3、所以目前数据如图:

<+183>: mov 0x20(%rsp),%rbx //rbx=node[data[0]]
<+188>: lea 0x28(%rsp),%rax //rax=rsp+0x28
<+193>: lea 0x50(%rsp),%rsi //rsi=rsp+0x50=结尾
<+198>: mov %rbx,%rcx //rcx=node[data[0]]
<+201>: mov (%rax),%rdx //rdx=node[data[1]]
<+204>: mov %rdx,0x8(%rcx) //rcx+0x08=rdx
<+208>: add $0x8,%rax //rax=node[data[1]]+0x08=node[data[2]]
<+212>: cmp %rsi,%rax //rax-rsi
<+215>: je 0x4011d2 //=0结束则跳出
<+217>: mov %rdx,%rcx //rcx=rdx,像后遍历
<+220>: jmp 0x4011bd //跳转+201
1、注释
2、我不太理解这一部分的意义,在我理解 0x20 开始就可以遍历该链表的内容了,这样处理一波以后,似乎还是从 0x20 开始可以遍历?
3、我认为我这部分可能没理解对,注释可能有错
<+222>: movq $0x0,0x8(%rdx) //结尾标志
<+230>: mov $0x5,%ebp //5次循环
<+235>: mov 0x8(%rbx),%rax //rax=node[data[1]]
<+239>: mov (%rax),%eax //eax=node[data[1]]->val
<+241>: cmp %eax,(%rbx) //node[data[0]]-node[data[1]]
<+243>: jge 0x4011ee //大于等于则跳转+250
<+245>: callq 0x40143a //否则bomb
<+250>: mov 0x8(%rbx),%rbx //rbx像后遍历
<+254>: sub $0x1,%ebp //循环结束一次
<+257>: jne 0x4011df //未结束则继续
<+259>: add $0x50,%rsp
<+263>: pop %rbx
<+264>: pop %rbp
<+265>: pop %r12
<+267>: pop %r13
<+269>: pop %r14
<+271>: retq
1、注释
2、此处可以看出了,最后的值要按递减顺序走,node如下:
0x6032d0 : 332 1 6304480 0
0x6032e0 : 168 2 6304496 0
0x6032f0 : 924 3 6304512 0
0x603300 : 691 4 6304528 0
0x603310 : 477 5 6304544 0
0x603320 : 443 6 0 0
1、所以最后需要 node 的顺序是3-4-5-6-1-2
2、倒推 7-data[x] 的大小应该为3-4-5-6-1-2
3、则 data[x] 为4-3-2-1-6-5
4、我以为结束了,结果还有隐藏关卡
所以第六题答案为:4 3 2 1 6 5
2.8 反汇编phase_defused
disassenmble phase_defused
<+0>: sub $0x78,%rsp
<+4>: mov %fs:0x28,%rax
<+13>: mov %rax,0x68(%rsp)
<+18>: xor %eax,%eax //清0eax
<+20>: cmpl $0x6,0x202181(%rip) //判断字符串大小
<+27>: jne 0x40163f //!=6,则跳转+123结束
<+29>: lea 0x10(%rsp),%r8 //r8=rsp+0x10
<+34>: lea 0xc(%rsp),%rcx //rcx=rsp+0x0c
<+39>: lea 0x8(%rsp),%rdx //rdx=rsp+0x08
<+44>: mov $0x402619,%esi //esi="%d %d %s"
<+49>: mov $0x603870,%edi //edi=""
<+54>: callq 0x400bf0 <__isoc99_sscanf@plt>//调用sscanf
<+59>: cmp $0x3,%eax //比较输入是否为3个
<+62>: jne 0x401635 //=3,则跳转+113
<+64>: mov $0x402622,%esi //esi="DrEvil"
<+69>: lea 0x10(%rsp),%rdi //rdi=rsp+0x10,r8目前也是这个
<+74>: callq 0x401338 //if edi!=esi
<+79>: test %eax,%eax //不相等为1
<+81>: jne 0x401635 //不相等则跳转+113
<+83>: mov $0x4024f8,%edi //edi="Curses, .....省略"
<+88>: callq 0x400b10 //
<+93>: mov $0x402520,%edi //edi="But finding,.....省略"
<+98>: callq 0x400b10 //
<+103>: mov $0x0,%eax //eax=0
<+108>: callq 0x401242 //进入隐藏
<+113>: mov $0x402558,%edi
<+118>: callq 0x400b10
<+123>: mov 0x68(%rsp),%rax
<+128>: xor %fs:0x28,%rax
<+137>: je 0x401654
<+139>: callq 0x400b30 <__stack_chk_fail@plt>
<+144>: add $0x78,%rsp
<+148>: retq
1、注释
2、所以目前看是输入 "%d %d %s" 时,其中 "%s" 为 "DrEvil",这种输入格式在第 2 关第 4 关均有
3、打断点 b *0x4015fa(sscanf那一行)
4、r 运行
(gdb) b *0x4015fa
Breakpoint 1 at 0x4015fa
(gdb) r
Welcome to my fiendish little bomb. You have 6 phases with
which to blow yourself up. Have a nice day!
Border relations with Canada have never been better.
Phase 1 defused. How about the next one?
1 2 4 8 16 32
That's number 2. Keep going!
0 207
Halfway there!
7 0
So you got that one. Try this one.
IONEFG
Good work! On to the next...
4 3 2 1 6 5Breakpoint 1, 0x00000000004015fa in phase_defused ()
(gdb) x/s 0x603870
0x603870 : "7 0"
1、依次输入 1-6 题答案
2、可知应该在 "7 0" 后面加 "DrEvil" ,也就是第四题
3、现在,进入 secret_phase
<+0>: push %rbx
<+1>: callq 0x40149e //
<+6>: mov $0xa,%edx //edx=0x0a
<+11>: mov $0x0,%esi //esi=0x00
<+16>: mov %rax,%rdi //rdi=rax
<+19>: callq 0x400bd0 //字符串转整数
<+24>: mov %rax,%rbx //rbx=rax,转换结果
<+27>: lea -0x1(%rax),%eax //eax=rax-0x01
<+30>: cmp $0x3e8,%eax //eax-0x3e8
<+35>: jbe 0x40126c //<=则跳转+42
<+37>: callq 0x40143a //>则爆炸
<+42>: mov %ebx,%esi //esi=ebx,转换结果
<+44>: mov $0x6030f0,%edi //edi=0x6030f0,是36
<+49>: callq 0x401204 //传给fun7
<+54>: cmp $0x2,%eax //eax-0x02
<+57>: je 0x401282 //=2则跳转+64
<+59>: callq 0x40143a //否则bomb
<+64>: mov $0x402438,%edi
<+69>: callq 0x400b10
<+74>: callq 0x4015c4
<+79>: pop %rbx
<+80>: retq
1、注释
2、所以现在是调用 fun7,输入 0x6030f0 中的数和我们输入的数
3、查看 fun7
<+0>: sub $0x8,%rsp //
<+4>: test %rdi,%rdi //按位与,主要是为了标志位,做循环结束标志
<+7>: je 0x401238 //0则跳转+52
<+9>: mov (%rdi),%edx //edx=rdi=0x6030f0的值,是一棵树
<+11>: cmp %esi,%edx //edx-esi
<+13>: jle 0x401220 //<=则跳转+28
<+15>: mov 0x8(%rdi),%rdi //后移去左边,为查下一个节点
<+19>: callq 0x401204 //再来一次
<+24>: add %eax,%eax //eax+=eax
<+26>: jmp 0x40123d //跳转+57结束
<+28>: mov $0x0,%eax //eax=0
<+33>: cmp %esi,%edx //edx-esi
<+35>: je 0x40123d //=0则跳转+57结束
<+37>: mov 0x10(%rdi),%rdi //rdi后移去右边
<+41>: callq 0x401204 //再来一次
<+46>: lea 0x1(%rax,%rax,1),%eax //eax=rax+rax*1+0x01
<+50>: jmp 0x40123d //跳转+57结束
<+52>: mov $0xffffffff,%eax //拉满eax
<+57>: add $0x8,%rsp //
<+61>: retq
1、注释
2、整段类似一个递归,根据输入值 rsi 去在这棵树中查找
3、从 eax=0 开始,每一次查找后,若向左 eax*=2,若向右 eax=eax*2+1,回到 secret_phase
0x0000000000401278 <+54>: cmp $0x2,%eax0x000000000040127b <+57>: je 0x401282 0x000000000040127d <+59>: callq 0x40143a 0x0000000000401282 <+64>: mov $0x402438,%edi0x0000000000401287 <+69>: callq 0x400b10 0x000000000040128c <+74>: callq 0x4015c4 0x0000000000401291 <+79>: pop %rbx0x0000000000401292 <+80>: retq
1、可以看出,要求 fun7 的返回值是 ==2 的,所以前文的输入应该是 22
所以隐藏题答案为:22
3、总结
懵懵懂懂,请多指教!
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
