[笔记]计算机基础 3 CSAPP Lab2-BombLab
BombLabs是CSAPP的第二个Lab,主要考察的是对于汇编的阅读能力。
BombLab做起来其实并不难,大概花了大半天就能完成,但确实对于栈的理解会得到提升,并且深深的感受到循环、数组、链表的底层魅力。
并且由于对Bomb的忌惮,你不得不使用GDB对汇编进行不断地b、si、i r rax、x/x来进行控制与管理。
总而言之,你需要观察汇编代码并且根据Bomb触发条件从而输入正确的字符串。
文章目录
- Lab
-
- Phase 1
- Phase 2
- Phase 3
- Phase 4
- Phase 5
- Phase 6
- 总结
Lab
Phase 1
Phase 1主要需要关注3个区域的代码
0000000000400ee0 <phase_1>:400ee0: 48 83 ec 08 sub $0x8,%rsp400ee4: be 00 24 40 00 mov $0x402400,%esi400ee9: e8 4a 04 00 00 callq 401338 <strings_not_equal>400eee: 85 c0 test %eax,%eax400ef0: 74 05 je 400ef7 <phase_1+0x17>400ef2: e8 43 05 00 00 callq 40143a <explode_bomb>400ef7: 48 83 c4 08 add $0x8,%rsp400efb: c3 retq 000000000040131b <string_length>:40131b: 80 3f 00 cmpb $0x0,(%rdi)40131e: 74 12 je 401332 <string_length+0x17>401320: 48 89 fa mov %rdi,%rdx401323: 48 83 c2 01 add $0x1,%rdx401327: 89 d0 mov %edx,%eax401329: 29 f8 sub %edi,%eax40132b: 80 3a 00 cmpb $0x0,(%rdx)40132e: 75 f3 jne 401323 <string_length+0x8>401330: f3 c3 repz retq 401332: b8 00 00 00 00 mov $0x0,%eax401337: c3 retq0000000000401338 <strings_not_equal>:401338: 41 54 push %r1240133a: 55 push %rbp40133b: 53 push %rbx40133c: 48 89 fb mov %rdi,%rbx40133f: 48 89 f5 mov %rsi,%rbp401342: e8 d4 ff ff ff callq 40131b <string_length>401347: 41 89 c4 mov %eax,%r12d40134a: 48 89 ef mov %rbp,%rdi40134d: e8 c9 ff ff ff callq 40131b <string_length>401352: ba 01 00 00 00 mov $0x1,%edx401357: 41 39 c4 cmp %eax,%r12d40135a: 75 3f jne 40139b <strings_not_equal+0x63>40135c: 0f b6 03 movzbl (%rbx),%eax40135f: 84 c0 test %al,%al401361: 74 25 je 401388 <strings_not_equal+0x50>401363: 3a 45 00 cmp 0x0(%rbp),%al401366: 74 0a je 401372 <strings_not_equal+0x3a>401368: eb 25 jmp 40138f <strings_not_equal+0x57>40136a: 3a 45 00 cmp 0x0(%rbp),%al40136d: 0f 1f 00 nopl (%rax)401370: 75 24 jne 401396 <strings_not_equal+0x5e>401372: 48 83 c3 01 add $0x1,%rbx401376: 48 83 c5 01 add $0x1,%rbp40137a: 0f b6 03 movzbl (%rbx),%eax40137d: 84 c0 test %al,%al40137f: 75 e9 jne 40136a <strings_not_equal+0x32>401381: ba 00 00 00 00 mov $0x0,%edx401386: eb 13 jmp 40139b <strings_not_equal+0x63>401388: ba 00 00 00 00 mov $0x0,%edx40138d: eb 0c jmp 40139b <strings_not_equal+0x63>40138f: ba 01 00 00 00 mov $0x1,%edx401394: eb 05 jmp 40139b <strings_not_equal+0x63>401396: ba 01 00 00 00 mov $0x1,%edx40139b: 89 d0 mov %edx,%eax40139d: 5b pop %rbx40139e: 5d pop %rbp40139f: 41 5c pop %r124013a1: c3 retq
分别为phase1、string_length、strings_not_equal三个部分。
我们知道%rdi中保存着函数的第一个参数,也就是我们所输入的字符串,而400ee4处的mov $0x402400,%esi,将某个值保存在负责第二个参数的寄存器%rsi中,根据strings_not_equal的命名,我们可以初步推测,phase1是比较两个字符串。
- string_length很容易看懂,就是一个统计字符串长度的汇编代码,到字符串末尾的’\\0’为止
- string_not_equal稍微费劲一点,首先比较两个字符串的长度,若不一致,则返回1,并且将在phase 1中引爆炸弹;接下来逐个字符比较,全相等时才返回0。
在GDB中采用x/s 0x400ee4查看这部分的变量,可以发现,结果如下:
(gdb) x/s 0x402400
0x402400: "Border relations with Canada have never been better."
这就是我们所需要的第一个字符串了,输入Border relations with Canada have never been better.,成功接触d第一个炸弹。
(gdb) r "Border relations with Canada have never been better."
Starting program: /home/usr/csapplab/bomblab/bomb/bomb ans.txt
Welcome to my fiendish little bomb. You have 6 phases with
which to blow yourself up. Have a nice day!
Phase 1 defused. How about the next one?
Phase 2
Phase 2主要需要关注2个区域的代码
0000000000400efc <phase_2>:400efc: 55 push %rbp400efd: 53 push %rbx400efe: 48 83 ec 28 sub $0x28,%rsp400f02: 48 89 e6 mov %rsp,%rsi400f05: e8 52 05 00 00 callq 40145c <read_six_numbers>400f0a: 83 3c 24 01 cmpl $0x1,(%rsp)400f0e: 74 20 je 400f30 <phase_2+0x34>400f10: e8 25 05 00 00 callq 40143a <explode_bomb>400f15: eb 19 jmp 400f30 <phase_2+0x34>400f17: 8b 43 fc mov -0x4(%rbx),%eax400f1a: 01 c0 add %eax,%eax400f1c: 39 03 cmp %eax,(%rbx)400f1e: 74 05 je 400f25 <phase_2+0x29>400f20: e8 15 05 00 00 callq 40143a <explode_bomb>400f25: 48 83 c3 04 add $0x4,%rbx400f29: 48 39 eb cmp %rbp,%rbx400f2c: 75 e9 jne 400f17 <phase_2+0x1b>400f2e: eb 0c jmp 400f3c <phase_2+0x40>400f30: 48 8d 5c 24 04 lea 0x4(%rsp),%rbx400f35: 48 8d 6c 24 18 lea 0x18(%rsp),%rbp400f3a: eb db jmp 400f17 <phase_2+0x1b>400f3c: 48 83 c4 28 add $0x28,%rsp400f40: 5b pop %rbx400f41: 5d pop %rbp400f42: c3 retq 000000000040145c <read_six_numbers>:40145c: 48 83 ec 18 sub $0x18,%rsp401460: 48 89 f2 mov %rsi,%rdx401463: 48 8d 4e 04 lea 0x4(%rsi),%rcx401467: 48 8d 46 14 lea 0x14(%rsi),%rax40146b: 48 89 44 24 08 mov %rax,0x8(%rsp)401470: 48 8d 46 10 lea 0x10(%rsi),%rax401474: 48 89 04 24 mov %rax,(%rsp)401478: 4c 8d 4e 0c lea 0xc(%rsi),%r940147c: 4c 8d 46 08 lea 0x8(%rsi),%r8401480: be c3 25 40 00 mov $0x4025c3,%esi401485: b8 00 00 00 00 mov $0x0,%eax40148a: e8 61 f7 ff ff callq 400bf0 <__isoc99_sscanf@plt>40148f: 83 f8 05 cmp $0x5,%eax401492: 7f 05 jg 401499 <read_six_numbers+0x3d>401494: e8 a1 ff ff ff callq 40143a <explode_bomb>401499: 48 83 c4 18 add $0x18,%rsp40149d: c3 retq
分别为phase2、read_six_numbers两个个部分。
直接关注read_six_numbers,可以看到直接分配了24个字节的栈空间,并且将6个参数寄存器都用上了还不够,还压入了栈2个参数(0x401467 - 0x401477),我们知道%rdi保存着字符串,那么第二个参数%rsi保存着的0x4025c3很可能是理解这个部分的关键,使用x/s 4025c3查看一下。
(gdb) x/s 0x4025c3
0x4025c3: "%d %d %d %d %d %d"
这下配合sscanf的标识,我们就知道了,这里很可能调用的是一个scanf函数,接受一个字符串,并且读取6个int整数,挨个放入栈中。
因此我们可以首先确定我们应该输入的是6个整数,并以空格隔开。不然0x40148f处判断是否是六个的指令,将在输入数字不是6个时引爆炸弹。
接下来重新阅读phase2,其本质就是进行了一个循环判断,利用%rbp作为终点( %rsp + 24 正好对应6个int的24字节 ),判断栈内每一个元素是否满足首项为1,比例为2的等比数列。
那么答案就很自然地是1 2 4 8 16 32,将这部分答案与phase1的答案一起放入ans.txt。
(gdb) r ans.txt
Starting program: /home/usr/csapplab/bomblab/bomb/bomb ans.txt
Welcome to my fiendish little bomb. You have 6 phases with
which to blow yourself up. Have a nice day!
Phase 1 defused. How about the next one?
That's number 2. Keep going!
Phase 3
Phase 3代码如下
0000000000400f43 <phase_3>:400f43: 48 83 ec 18 sub $0x18,%rsp400f47: 48 8d 4c 24 0c lea 0xc(%rsp),%rcx400f4c: 48 8d 54 24 08 lea 0x8(%rsp),%rdx400f51: be cf 25 40 00 mov $0x4025cf,%esi400f56: b8 00 00 00 00 mov $0x0,%eax400f5b: e8 90 fc ff ff callq 400bf0 <__isoc99_sscanf@plt>400f60: 83 f8 01 cmp $0x1,%eax400f63: 7f 05 jg 400f6a <phase_3+0x27>400f65: e8 d0 04 00 00 callq 40143a <explode_bomb>400f6a: 83 7c 24 08 07 cmpl $0x7,0x8(%rsp)400f6f: 77 3c ja 400fad <phase_3+0x6a>400f71: 8b 44 24 08 mov 0x8(%rsp),%eax400f75: ff 24 c5 70 24 40 00 jmpq *0x402470(,%rax,8)400f7c: b8 cf 00 00 00 mov $0xcf,%eax400f81: eb 3b jmp 400fbe <phase_3+0x7b>400f83: b8 c3 02 00 00 mov $0x2c3,%eax400f88: eb 34 jmp 400fbe <phase_3+0x7b>400f8a: b8 00 01 00 00 mov $0x100,%eax400f8f: eb 2d jmp 400fbe <phase_3+0x7b>400f91: b8 85 01 00 00 mov $0x185,%eax400f96: eb 26 jmp 400fbe <phase_3+0x7b>400f98: b8 ce 00 00 00 mov $0xce,%eax400f9d: eb 1f jmp 400fbe <phase_3+0x7b>400f9f: b8 aa 02 00 00 mov $0x2aa,%eax400fa4: eb 18 jmp 400fbe <phase_3+0x7b>400fa6: b8 47 01 00 00 mov $0x147,%eax400fab: eb 11 jmp 400fbe <phase_3+0x7b>400fad: e8 88 04 00 00 callq 40143a <explode_bomb>400fb2: b8 00 00 00 00 mov $0x0,%eax400fb7: eb 05 jmp 400fbe <phase_3+0x7b>400fb9: b8 37 01 00 00 mov $0x137,%eax400fbe: 3b 44 24 0c cmp 0xc(%rsp),%eax400fc2: 74 05 je 400fc9 <phase_3+0x86>400fc4: e8 71 04 00 00 callq 40143a <explode_bomb>400fc9: 48 83 c4 18 add $0x18,%rsp400fcd: c3 retq
与phase2类似地查看x/s 0x4025cf,发现结果为
(gdb) x/s 0x4025cf
0x4025cf: "%d %d"
那么这一轮所需要输入地就是2个int了。
而0x400f60处的引爆,我们利用文件输入末尾的回车就可以冒充第三个数,因此也无需计较这一点。
接着我们观400f75 jmpq *0x402470(,%rax,8) 这一行,提示我们将根据0x(%rsp)处的值(也就是第一个数)决定所跳转到的 M[ 0x402470+8i ]值处的地址(不是0x402470+8i)。
直接查看0x402470处保存的8个地址。
(gdb) x/16x 0x402470
0x402470: 0x00400f7c 0x00000000 0x00400fb9 0x00000000
0x402480: 0x00400f83 0x00000000 0x00400f8a 0x00000000
0x402490: 0x00400f91 0x00000000 0x00400f98 0x00000000
0x4024a0: 0x00400f9f 0x00000000 0x00400fa6 0x00000000
可以看到,分别对应着phase3汇编处六个分支,且每个分支最后都会jmp到400fbe,将0xc(%rsp)(即第二个数)与分支中所的赋值进行比较。可用的组合如下:
- 0 207
- 1 311
- 2 707
- 3 256
- 4 389
- 5 206
- 6 682
- 7 327
随便选择其一即可通过。
(gdb) r ans.txt
Starting program: /home/usr/csapplab/bomblab/bomb/bomb ans.txt
Welcome to my fiendish little bomb. You have 6 phases with
which to blow yourself up. Have a nice day!
Phase 1 defused. How about the next one?
That's number 2. Keep going!
Halfway there!
Phase 4
Phase 4重要代码如下
0000000000400fce <func4>:400fce: 48 83 ec 08 sub $0x8,%rsp400fd2: 89 d0 mov %edx,%eax400fd4: 29 f0 sub %esi,%eax400fd6: 89 c1 mov %eax,%ecx400fd8: c1 e9 1f shr $0x1f,%ecx400fdb: 01 c8 add %ecx,%eax400fdd: d1 f8 sar %eax400fdf: 8d 0c 30 lea (%rax,%rsi,1),%ecx400fe2: 39 f9 cmp %edi,%ecx400fe4: 7e 0c jle 400ff2 <func4+0x24>400fe6: 8d 51 ff lea -0x1(%rcx),%edx400fe9: e8 e0 ff ff ff callq 400fce <func4>400fee: 01 c0 add %eax,%eax400ff0: eb 15 jmp 401007 <func4+0x39>400ff2: b8 00 00 00 00 mov $0x0,%eax400ff7: 39 f9 cmp %edi,%ecx400ff9: 7d 0c jge 401007 <func4+0x39>400ffb: 8d 71 01 lea 0x1(%rcx),%esi400ffe: e8 cb ff ff ff callq 400fce <func4>401003: 8d 44 00 01 lea 0x1(%rax,%rax,1),%eax401007: 48 83 c4 08 add $0x8,%rsp40100b: c3 retq 000000000040100c <phase_4>:40100c: 48 83 ec 18 sub $0x18,%rsp401010: 48 8d 4c 24 0c lea 0xc(%rsp),%rcx401015: 48 8d 54 24 08 lea 0x8(%rsp),%rdx40101a: be cf 25 40 00 mov $0x4025cf,%esi40101f: b8 00 00 00 00 mov $0x0,%eax401024: e8 c7 fb ff ff callq 400bf0 <__isoc99_sscanf@plt>401029: 83 f8 02 cmp $0x2,%eax40102c: 75 07 jne 401035 <phase_4+0x29>40102e: 83 7c 24 08 0e cmpl $0xe,0x8(%rsp)401033: 76 05 jbe 40103a <phase_4+0x2e>401035: e8 00 04 00 00 callq 40143a <explode_bomb>40103a: ba 0e 00 00 00 mov $0xe,%edx40103f: be 00 00 00 00 mov $0x0,%esi401044: 8b 7c 24 08 mov 0x8(%rsp),%edi401048: e8 81 ff ff ff callq 400fce <func4>40104d: 85 c0 test %eax,%eax40104f: 75 07 jne 401058 <phase_4+0x4c>401051: 83 7c 24 0c 00 cmpl $0x0,0xc(%rsp)401056: 74 05 je 40105d <phase_4+0x51>401058: e8 dd 03 00 00 callq 40143a <explode_bomb>40105d: 48 83 c4 18 add $0x18,%rsp401061: c3 retq
与phase4也是输入2个int,其中401051 cmpl $0x0,0xc(%rsp) 要求int2为0。
而int1要求经过递归函数func4后返回0。
直接观察fun4,可以发现
- 如果int1=7,可以直接在第一次函数就返回0。
- 如果int1>7就会进入第二次循环,此时由于会返回2 * %rax + 1,即返回1,故不满足条件。
- 如果int1<7经过推算也会满足条件。
直接选用最保险的7,输入7 0。
(gdb) r ans.txt
Starting program: /home/usr/csapplab/bomblab/bomb/bomb ans.txt
Welcome to my fiendish little bomb. You have 6 phases with
which to blow yourself up. Have a nice day!
Phase 1 defused. How about the next one?
That's number 2. Keep going!
Halfway there!
So you got that one. Try this one.
Phase 5
Phase 5重要代码如下
0000000000401062 <phase_5>:401062: 53 push %rbx401063: 48 83 ec 20 sub $0x20,%rsp401067: 48 89 fb mov %rdi,%rbx40106a: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax401071: 00 00 401073: 48 89 44 24 18 mov %rax,0x18(%rsp)401078: 31 c0 xor %eax,%eax40107a: e8 9c 02 00 00 callq 40131b <string_length>40107f: 83 f8 06 cmp $0x6,%eax401082: 74 4e je 4010d2 <phase_5+0x70>401084: e8 b1 03 00 00 callq 40143a <explode_bomb>401089: eb 47 jmp 4010d2 <phase_5+0x70>40108b: 0f b6 0c 03 movzbl (%rbx,%rax,1),%ecx40108f: 88 0c 24 mov %cl,(%rsp)401092: 48 8b 14 24 mov (%rsp),%rdx401096: 83 e2 0f and $0xf,%edx401099: 0f b6 92 b0 24 40 00 movzbl 0x4024b0(%rdx),%edx4010a0: 88 54 04 10 mov %dl,0x10(%rsp,%rax,1)4010a4: 48 83 c0 01 add $0x1,%rax4010a8: 48 83 f8 06 cmp $0x6,%rax4010ac: 75 dd jne 40108b <phase_5+0x29>4010ae: c6 44 24 16 00 movb $0x0,0x16(%rsp)4010b3: be 5e 24 40 00 mov $0x40245e,%esi4010b8: 48 8d 7c 24 10 lea 0x10(%rsp),%rdi4010bd: e8 76 02 00 00 callq 401338 <strings_not_equal>4010c2: 85 c0 test %eax,%eax4010c4: 74 13 je 4010d9 <phase_5+0x77>4010c6: e8 6f 03 00 00 callq 40143a <explode_bomb>4010cb: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)4010d0: eb 07 jmp 4010d9 <phase_5+0x77>4010d2: b8 00 00 00 00 mov $0x0,%eax4010d7: eb b2 jmp 40108b <phase_5+0x29>4010d9: 48 8b 44 24 18 mov 0x18(%rsp),%rax4010de: 64 48 33 04 25 28 00 xor %fs:0x28,%rax4010e5: 00 00 4010e7: 74 05 je 4010ee <phase_5+0x8c>4010e9: e8 42 fa ff ff callq 400b30 <__stack_chk_fail@plt>4010ee: 48 83 c4 20 add $0x20,%rsp4010f2: 5b pop %rbx4010f3: c3 retq
phase5和phase1有相似之处,所以我们直接根据4010b3: mov $0x40245e,%esi 对 0x40245e 处的字符串进行查看。
(gdb) x/s 0x40245e
0x40245e: "flyers"
但一直到0x401099 movzbl 0x4024b0(%rdx),%edx,phase5做成了一件事,那就是将输入字符串逐个取出字符,并只保留最低4位,根据最低4位作为offset,对0x4024b0 + offset进行取值,并且储存在%edx之中。
那么我们就直接查看0x4024b0,因为offset由最低4位取得,所以只需要查看16个即可。
(gdb) x/16c 0x4024b0
0x4024b0 : 109 'm' 97 'a' 100 'd' 117 'u' 105 'i' 101 'e' 114 'r' 115 's'
0x4024b8 : 110 'n' 102 'f' 111 'o' 116 't' 118 'v' 98 'b' 121 'y' 108 'l'
正好我们所需要的flyers都在其中,其对应的offset分别为9、15、14、5、6、7,在ASCII表中找到以9、F、E、5、6、7作为低四位的字符输入即可。
我选择了IONEFG,输入即通过。
(gdb) r ans.txt
Starting program: /home/usr/csapplab/bomblab/bomb/bomb ans.txt
Welcome to my fiendish little bomb. You have 6 phases with
which to blow yourself up. Have a nice day!
Phase 1 defused. How about the next one?
That's number 2. Keep going!
Halfway there!
So you got that one. Try this one.
Good work! On to the next...
Phase 6
Phase 6代码如下,不得不说太长了,看起来好费劲
00000000004010f4 <phase_6>:4010f4: 41 56 push %r144010f6: 41 55 push %r134010f8: 41 54 push %r124010fa: 55 push %rbp4010fb: 53 push %rbx4010fc: 48 83 ec 50 sub $0x50,%rsp401100: 49 89 e5 mov %rsp,%r13401103: 48 89 e6 mov %rsp,%rsi401106: e8 51 03 00 00 callq 40145c <read_six_numbers>40110b: 49 89 e6 mov %rsp,%r1440110e: 41 bc 00 00 00 00 mov $0x0,%r12d401114: 4c 89 ed mov %r13,%rbp401117: 41 8b 45 00 mov 0x0(%r13),%eax40111b: 83 e8 01 sub $0x1,%eax40111e: 83 f8 05 cmp $0x5,%eax401121: 76 05 jbe 401128 <phase_6+0x34>401123: e8 12 03 00 00 callq 40143a <explode_bomb>401128: 41 83 c4 01 add $0x1,%r12d40112c: 41 83 fc 06 cmp $0x6,%r12d401130: 74 21 je 401153 <phase_6+0x5f>401132: 44 89 e3 mov %r12d,%ebx401135: 48 63 c3 movslq %ebx,%rax401138: 8b 04 84 mov (%rsp,%rax,4),%eax40113b: 39 45 00 cmp %eax,0x0(%rbp)40113e: 75 05 jne 401145 <phase_6+0x51>401140: e8 f5 02 00 00 callq 40143a <explode_bomb>401145: 83 c3 01 add $0x1,%ebx401148: 83 fb 05 cmp $0x5,%ebx40114b: 7e e8 jle 401135 <phase_6+0x41>40114d: 49 83 c5 04 add $0x4,%r13401151: eb c1 jmp 401114 <phase_6+0x20>401153: 48 8d 74 24 18 lea 0x18(%rsp),%rsi401158: 4c 89 f0 mov %r14,%rax40115b: b9 07 00 00 00 mov $0x7,%ecx401160: 89 ca mov %ecx,%edx401162: 2b 10 sub (%rax),%edx401164: 89 10 mov %edx,(%rax)401166: 48 83 c0 04 add $0x4,%rax40116a: 48 39 f0 cmp %rsi,%rax40116d: 75 f1 jne 401160 <phase_6+0x6c>40116f: be 00 00 00 00 mov $0x0,%esi401174: eb 21 jmp 401197 <phase_6+0xa3>401176: 48 8b 52 08 mov 0x8(%rdx),%rdx40117a: 83 c0 01 add $0x1,%eax40117d: 39 c8 cmp %ecx,%eax40117f: 75 f5 jne 401176 <phase_6+0x82>401181: eb 05 jmp 401188 <phase_6+0x94>401183: ba d0 32 60 00 mov $0x6032d0,%edx401188: 48 89 54 74 20 mov %rdx,0x20(%rsp,%rsi,2)40118d: 48 83 c6 04 add $0x4,%rsi401191: 48 83 fe 18 cmp $0x18,%rsi401195: 74 14 je 4011ab <phase_6+0xb7>401197: 8b 0c 34 mov (%rsp,%rsi,1),%ecx40119a: 83 f9 01 cmp $0x1,%ecx40119d: 7e e4 jle 401183 <phase_6+0x8f>40119f: b8 01 00 00 00 mov $0x1,%eax4011a4: ba d0 32 60 00 mov $0x6032d0,%edx4011a9: eb cb jmp 401176 <phase_6+0x82>4011ab: 48 8b 5c 24 20 mov 0x20(%rsp),%rbx4011b0: 48 8d 44 24 28 lea 0x28(%rsp),%rax4011b5: 48 8d 74 24 50 lea 0x50(%rsp),%rsi4011ba: 48 89 d9 mov %rbx,%rcx4011bd: 48 8b 10 mov (%rax),%rdx4011c0: 48 89 51 08 mov %rdx,0x8(%rcx)4011c4: 48 83 c0 08 add $0x8,%rax4011c8: 48 39 f0 cmp %rsi,%rax4011cb: 74 05 je 4011d2 <phase_6+0xde>4011cd: 48 89 d1 mov %rdx,%rcx4011d0: eb eb jmp 4011bd <phase_6+0xc9>4011d2: 48 c7 42 08 00 00 00 movq $0x0,0x8(%rdx)4011d9: 00 4011da: bd 05 00 00 00 mov $0x5,%ebp4011df: 48 8b 43 08 mov 0x8(%rbx),%rax4011e3: 8b 00 mov (%rax),%eax4011e5: 39 03 cmp %eax,(%rbx)4011e7: 7d 05 jge 4011ee <phase_6+0xfa>4011e9: e8 4c 02 00 00 callq 40143a <explode_bomb>4011ee: 48 8b 5b 08 mov 0x8(%rbx),%rbx4011f2: 83 ed 01 sub $0x1,%ebp4011f5: 75 e8 jne 4011df <phase_6+0xeb>4011f7: 48 83 c4 50 add $0x50,%rsp4011fb: 5b pop %rbx4011fc: 5d pop %rbp4011fd: 41 5c pop %r124011ff: 41 5d pop %r13401201: 41 5e pop %r14401203: c3 retq
这里就直接记录一下心得吧,就不详述怎么解决了。
- 从read_six_numbers可以知道,本题也是输入6个int,并以空格隔开
- 0x401121s使用了jbe,意味着都是无符号整数。
- 到0x401153之前,所有的汇编都要求6个数满足以下条件:每个数字各不相同,且0<uint<=6,那么,这个六个数即为1 2 3 4 5 6的某一种排列。
- 0x401153 - 0x40116d ,做了一件事,即将原来的x转为7-x,并且放置在原来的地址。
- 0x40116f - 0x4011a9 实际上对0x4011ab处开始所存储的链表的各个节点进行了链接,并且要求链表必须单调递减,因为此时根据输入值(而非输入顺序)确定了每个值所对应的节点,即val=1的值指向第1个节点。
查看0x4011ab
(gdb) x/24xw 0x6032d0
0x6032d0 <node1>: 0x0000014c 0x00000001 0x006032e0 0x00000000
0x6032e0 <node2>: 0x000000a8 0x00000002 0x006032f0 0x00000000
0x6032f0 <node3>: 0x0000039c 0x00000003 0x00603300 0x00000000
0x603300 <node4>: 0x000002b3 0x00000004 0x00603310 0x00000000
0x603310 <node5>: 0x000001dd 0x00000005 0x00603320 0x00000000
0x603320 <node6>: 0x000001bb 0x00000006 0x00000000 0x00000000
可以清楚的看到<node>的结构,前8个字节保存value,后8个字节保留下一个节点的地址。
根据以上node,可以看出各个节点的值如下
- node1 332
- node2 168
- node3 924
- node4 691
- node5 477
- node6 443
即node3 > node4 > node5 > node6 > node1 > node2,对应的栈中的值排列应为3 4 5 6 1 2
但同时因为x = 7-x的变换,所以,最终答案应为4 3 2 1 6 5,输入,解除炸弹。
(gdb) r ans.txt
Starting program: /home/usr/csapplab/bomblab/bomb/bomb ans.txt
Welcome to my fiendish little bomb. You have 6 phases with
which to blow yourself up. Have a nice day!
Phase 1 defused. How about the next one?
That's number 2. Keep going!
Halfway there!
So you got that one. Try this one.
Good work! On to the next...
Congratulations! You've defused the bomb!
总结
最后查看汇编时,发现还有func7和secret_phase,上网查了查,发现好像是和树有关的操作,只能之后有空再去做了。
从开始Bomblab到结束,大概花了一个下午+一个晚上,做到phase6看了200+行汇编到最后脑子都难受起来了,实际上还是之后才理顺了链表的逻辑,当时完成只依靠排序的规律推导出了4 3 2 1。
虽然大概是前天完成的Bomblab,但拖到了今天才完成了这个博客,主要是这两天还解决了AttackLab,不得不承认这些Lab的设计还是很精妙的,并不是很难,但也没那么简单,让我在痛苦地啃完CSAPP的第3章后对于栈、返回机制的认知真的是大大提升了。
——2023.4.5