BOMBLAB实验总结

CSAPP实验BOMB,很头疼,看不懂,勉强做完了。

答案是这样的:

Border relations with Canada have never been better.
1 2 4 8 16 32
2 707
7 0
9?>567
4 3 2 1 6 5

在bomb文件夹新建一个文件input.txt,再在gdb下运行如下指令:

run < input.txt

就可以不用自己输入跑实验了。

做实验时记得一定要加一句:

b explode_bomb

防止踩雷~

phase_1

main函数里有这两行:

  400e32:	e8 67 06 00 00       	callq  40149e <read_line>
400e37: 48 89 c7 mov %rax,%rdi
400e3a: e8 a1 00 00 00 callq 400ee0 <phase_1>

这就可以说明我们输入的数据放进了%rdi里面。再进phase_1看看。

0000000000400ee0 <phase_1>:
400ee0: 48 83 ec 08 sub $0x8,%rsp
400ee4: be 00 24 40 00 mov $0x402400,%esi
400ee9: e8 4a 04 00 00 callq 401338 <strings_not_equal>
400eee: 85 c0 test %eax,%eax
400ef0: 74 05 je 400ef7 <phase_1+0x17>
400ef2: e8 43 05 00 00 callq 40143a <explode_bomb>
400ef7: 48 83 c4 08 add $0x8,%rsp
400efb: c3 retq

第一阶段,发现需要让%eax为0,才不会执行到explode_bomb。然而这里好像没调用%eax,只好去strings_not_equal看看。

0000000000401338 <strings_not_equal>:
401338: 41 54 push %r12
40133a: 55 push %rbp
40133b: 53 push %rbx
40133c: 48 89 fb mov %rdi,%rbx
40133f: 48 89 f5 mov %rsi,%rbp
401342: e8 d4 ff ff ff callq 40131b <string_length>
401347: 41 89 c4 mov %eax,%r12d
40134a: 48 89 ef mov %rbp,%rdi
40134d: e8 c9 ff ff ff callq 40131b <string_length>
401352: ba 01 00 00 00 mov $0x1,%edx
401357: 41 39 c4 cmp %eax,%r12d
40135a: 75 3f jne 40139b <strings_not_equal+0x63>
40135c: 0f b6 03 movzbl (%rbx),%eax
40135f: 84 c0 test %al,%al
401361: 74 25 je 401388 <strings_not_equal+0x50>
401363: 3a 45 00 cmp 0x0(%rbp),%al
401366: 74 0a je 401372 <strings_not_equal+0x3a>
401368: eb 25 jmp 40138f <strings_not_equal+0x57>
40136a: 3a 45 00 cmp 0x0(%rbp),%al
40136d: 0f 1f 00 nopl (%rax)
401370: 75 24 jne 401396 <strings_not_equal+0x5e>
401372: 48 83 c3 01 add $0x1,%rbx
401376: 48 83 c5 01 add $0x1,%rbp
40137a: 0f b6 03 movzbl (%rbx),%eax
40137d: 84 c0 test %al,%al
40137f: 75 e9 jne 40136a <strings_not_equal+0x32>
401381: ba 00 00 00 00 mov $0x0,%edx
401386: eb 13 jmp 40139b <strings_not_equal+0x63>
401388: ba 00 00 00 00 mov $0x0,%edx
40138d: eb 0c jmp 40139b <strings_not_equal+0x63>
40138f: ba 01 00 00 00 mov $0x1,%edx
401394: eb 05 jmp 40139b <strings_not_equal+0x63>
401396: ba 01 00 00 00 mov $0x1,%edx
40139b: 89 d0 mov %edx,%eax
40139d: 5b pop %rbx
40139e: 5d pop %rbp
40139f: 41 5c pop %r12
4013a1: c3 retq

还是有点疑惑,去string_length看看。

000000000040131b <string_length>:
40131b: 80 3f 00 cmpb $0x0,(%rdi)
40131e: 74 12 je 401332 <string_length+0x17>
401320: 48 89 fa mov %rdi,%rdx
401323: 48 83 c2 01 add $0x1,%rdx
401327: 89 d0 mov %edx,%eax
401329: 29 f8 sub %edi,%eax
40132b: 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,%eax
401337: c3 retq

我们发现%eax是用来存储长度的,%rdi放的是数据。顺腾摸瓜发现,分别使用了%rdi%rsi两个地方的数据。然后发现在一开头有一句代码:

  400ee4:	be 00 24 40 00       	mov    $0x402400,%esi

程序在一个地方导入了一个数据,好奇去看看

x /s 0x402400
结果:Border relations with Canada have never been better.

这句话就是最终答案。

phase_2

先去瞅瞅代码:

0000000000400efc <phase_2>:
400efc: 55 push %rbp
400efd: 53 push %rbx
400efe: 48 83 ec 28 sub $0x28,%rsp
400f02: 48 89 e6 mov %rsp,%rsi
400f05: 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),%eax
400f1a: 01 c0 add %eax,%eax
400f1c: 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,%rbx
400f29: 48 39 eb cmp %rbp,%rbx
400f2c: 75 e9 jne 400f17 <phase_2+0x1b>
400f2e: eb 0c jmp 400f3c <phase_2+0x40>
400f30: 48 8d 5c 24 04 lea 0x4(%rsp),%rbx
400f35: 48 8d 6c 24 18 lea 0x18(%rsp),%rbp
400f3a: eb db jmp 400f17 <phase_2+0x1b>
400f3c: 48 83 c4 28 add $0x28,%rsp
400f40: 5b pop %rbx
400f41: 5d pop %rbp
400f42: c3 retq

看到那个read_six_numbers就是读进去6个数咯。

000000000040145c <read_six_numbers>:
40145c: 48 83 ec 18 sub $0x18,%rsp
401460: 48 89 f2 mov %rsi,%rdx
401463: 48 8d 4e 04 lea 0x4(%rsi),%rcx
401467: 48 8d 46 14 lea 0x14(%rsi),%rax
40146b: 48 89 44 24 08 mov %rax,0x8(%rsp)
401470: 48 8d 46 10 lea 0x10(%rsi),%rax
401474: 48 89 04 24 mov %rax,(%rsp)
401478: 4c 8d 4e 0c lea 0xc(%rsi),%r9
40147c: 4c 8d 46 08 lea 0x8(%rsi),%r8
401480: be c3 25 40 00 mov $0x4025c3,%esi
401485: b8 00 00 00 00 mov $0x0,%eax
40148a: e8 61 f7 ff ff callq 400bf0 <__isoc99_sscanf@plt>
40148f: 83 f8 05 cmp $0x5,%eax
401492: 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,%rsp
40149d: c3 retq

跑到这个函数一看开头一个%18,说明栈指针移动了24个字节,一个数据4个字节,6个数字就刚好。我就懒得看代码,猜它放进了栈里存着。

然后到爆炸前查看了一下%rsp后32位,果然存了进去。

x /b32 $rsp

在看看这一段:

  400f17:	8b 43 fc             	mov    -0x4(%rbx),%eax
400f1a: 01 c0 add %eax,%eax
400f1c: 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,%rbx
400f29: 48 39 eb cmp %rbp,%rbx
400f2c: 75 e9 jne 400f17 <phase_2+0x1b>
400f2e: eb 0c jmp 400f3c <phase_2+0x40>
400f30: 48 8d 5c 24 04 lea 0x4(%rsp),%rbx
400f35: 48 8d 6c 24 18 lea 0x18(%rsp),%rbp
400f3a: eb db jmp 400f17 <phase_2+0x1b>

这一段,就是存了个第二个数字的数据,存了个结尾。把这个数据的前一个数据乘2,看与这个数据是否相等。相等就往前一个数据看。一直下去,直到这个数据和结尾的数据相同,就跳出循环。

所以很明显,他需要等比数列,比值是2。

由于设定了起始数据为1,那么答案就是:

1 2 4 8 16 32

phase_3

丢一段代码上来:

0000000000400f43 <phase_3>:
400f43: 48 83 ec 18 sub $0x18,%rsp
400f47: 48 8d 4c 24 0c lea 0xc(%rsp),%rcx
400f4c: 48 8d 54 24 08 lea 0x8(%rsp),%rdx
400f51: be cf 25 40 00 mov $0x4025cf,%esi
400f56: b8 00 00 00 00 mov $0x0,%eax
400f5b: e8 90 fc ff ff callq 400bf0 <__isoc99_sscanf@plt>
400f60: 83 f8 01 cmp $0x1,%eax
400f63: 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),%eax
400f75: ff 24 c5 70 24 40 00 jmpq *0x402470(,%rax,8)
400f7c: b8 cf 00 00 00 mov $0xcf,%eax
400f81: eb 3b jmp 400fbe <phase_3+0x7b>
400f83: b8 c3 02 00 00 mov $0x2c3,%eax
400f88: eb 34 jmp 400fbe <phase_3+0x7b>
400f8a: b8 00 01 00 00 mov $0x100,%eax
400f8f: eb 2d jmp 400fbe <phase_3+0x7b>
400f91: b8 85 01 00 00 mov $0x185,%eax
400f96: eb 26 jmp 400fbe <phase_3+0x7b>
400f98: b8 ce 00 00 00 mov $0xce,%eax
400f9d: eb 1f jmp 400fbe <phase_3+0x7b>
400f9f: b8 aa 02 00 00 mov $0x2aa,%eax
400fa4: eb 18 jmp 400fbe <phase_3+0x7b>
400fa6: b8 47 01 00 00 mov $0x147,%eax
400fab: 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,%eax
400fb7: eb 05 jmp 400fbe <phase_3+0x7b>
400fb9: b8 37 01 00 00 mov $0x137,%eax
400fbe: 3b 44 24 0c cmp 0xc(%rsp),%eax
400fc2: 74 05 je 400fc9 <phase_3+0x86>
400fc4: e8 71 04 00 00 callq 40143a <explode_bomb>
400fc9: 48 83 c4 18 add $0x18,%rsp
400fcd: c3 retq

有了第一题的经验,看到了这句:

  400f51:	be cf 25 40 00       	mov    $0x4025cf,%esi

就立马查看了里面放了啥,结果是:

%d %d

嗯,也就是要读两个数。

再看这句:

  400f6a:	83 7c 24 08 07       	cmpl   $0x7,0x8(%rsp)
400f6f: 77 3c ja 400fad <phase_3+0x6a>

第一个数要小于7。

然后这段代码:

  400f75:	ff 24 c5 70 24 40 00 	jmpq   *0x402470(,%rax,8)
400f7c: b8 cf 00 00 00 mov $0xcf,%eax
400f81: eb 3b jmp 400fbe <phase_3+0x7b>
400f83: b8 c3 02 00 00 mov $0x2c3,%eax
400f88: eb 34 jmp 400fbe <phase_3+0x7b>
400f8a: b8 00 01 00 00 mov $0x100,%eax
400f8f: eb 2d jmp 400fbe <phase_3+0x7b>
400f91: b8 85 01 00 00 mov $0x185,%eax
400f96: eb 26 jmp 400fbe <phase_3+0x7b>
400f98: b8 ce 00 00 00 mov $0xce,%eax
400f9d: eb 1f jmp 400fbe <phase_3+0x7b>
400f9f: b8 aa 02 00 00 mov $0x2aa,%eax
400fa4: eb 18 jmp 400fbe <phase_3+0x7b>
400fa6: b8 47 01 00 00 mov $0x147,%eax
400fab: 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,%eax
400fb7: eb 05 jmp 400fbe <phase_3+0x7b>
400fb9: b8 37 01 00 00 mov $0x137,%eax

说明,由第一个输入的数决定%eax的值。

再看这段:

  400fbe:	3b 44 24 0c          	cmp    0xc(%rsp),%eax
400fc2: 74 05 je 400fc9 <phase_3+0x86>

也就是说第二个数跟第一个数的输入之后选择出来的%eax要相同。

然后我们有7个选择,我们选2,也就是:

2 707

phase_4

贴一下代码:

000000000040100c <phase_4>:
40100c: 48 83 ec 18 sub $0x18,%rsp
401010: 48 8d 4c 24 0c lea 0xc(%rsp),%rcx
401015: 48 8d 54 24 08 lea 0x8(%rsp),%rdx
40101a: be cf 25 40 00 mov $0x4025cf,%esi
40101f: b8 00 00 00 00 mov $0x0,%eax
401024: e8 c7 fb ff ff callq 400bf0 <__isoc99_sscanf@plt>
401029: 83 f8 02 cmp $0x2,%eax
40102c: 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,%edx
40103f: be 00 00 00 00 mov $0x0,%esi
401044: 8b 7c 24 08 mov 0x8(%rsp),%edi
401048: e8 81 ff ff ff callq 400fce <func4>
40104d: 85 c0 test %eax,%eax
40104f: 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,%rsp
401061: c3 retq

前半段输入数字和phase_3是一样的,读进去两个数。

看段代码:

  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>

这就是暗示我们,第一个输入的数字要小于等于14。

  40103a:	ba 0e 00 00 00       	mov    $0xe,%edx
40103f: be 00 00 00 00 mov $0x0,%esi
401044: 8b 7c 24 08 mov 0x8(%rsp),%edi
401048: e8 81 ff ff ff callq 400fce <func4>

看到这里,我们去func4看看。

0000000000400fce <func4>:
400fce: 48 83 ec 08 sub $0x8,%rsp # 栈指针移动
400fd2: 89 d0 mov %edx,%eax # %edx 移动到 %eax (0xe)
400fd4: 29 f0 sub %esi,%eax # %eax 减一个 %esi (0)
400fd6: 89 c1 mov %eax,%ecx # %eax 移动到 %ecx (0xe)
400fd8: c1 e9 1f shr $0x1f,%ecx # %ecx 逻辑右移31位 (0)
400fdb: 01 c8 add %ecx,%eax # %ecx 加到 %eax (0xe)
400fdd: d1 f8 sar %eax # %eax 算数右移1位 (0x7)
400fdf: 8d 0c 30 lea (%rax,%rsi,1),%ecx
# %rax = 0x7, %rsi = 0, %ecx = 0x7
400fe2: 39 f9 cmp %edi,%ecx #
400fe4: 7e 0c jle 400ff2 <func4+0x24>
400fe6: 8d 51 ff lea -0x1(%rcx),%edx
400fe9: e8 e0 ff ff ff callq 400fce <func4>
400fee: 01 c0 add %eax,%eax
400ff0: eb 15 jmp 401007 <func4+0x39>
400ff2: b8 00 00 00 00 mov $0x0,%eax
400ff7: 39 f9 cmp %edi,%ecx
400ff9: 7d 0c jge 401007 <func4+0x39>
400ffb: 8d 71 01 lea 0x1(%rcx),%esi
400ffe: e8 cb ff ff ff callq 400fce <func4>
401003: 8d 44 00 01 lea 0x1(%rax,%rax,1),%eax
401007: 48 83 c4 08 add $0x8,%rsp
40100b: c3 retq

我发现,在这段程序里,我只需要让%edi大于等于且小于等于%ecx即可。也就是说只要%edi == %ecx就能直接跳过炸弹且跳出函数,让%eax为0。很简单就能算出来%ecx0x7

再看这段:

  401051:	83 7c 24 0c 00       	cmpl   $0x0,0xc(%rsp)
401056: 74 05 je 40105d <phase_4+0x51>

也就是说,第二个数以一定要是0,才可以不踩下面的炸弹。

答案就是:

7 0

phase_5

做到这的时候被教授嘲讽了好难受呀QAQ……

嗯,不管了,先贴代码:

0000000000401062 <phase_5>:
401062: 53 push %rbx
401063: 48 83 ec 20 sub $0x20,%rsp
401067: 48 89 fb mov %rdi,%rbx
40106a: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax
401071: 00 00
401073: 48 89 44 24 18 mov %rax,0x18(%rsp)
401078: 31 c0 xor %eax,%eax
40107a: e8 9c 02 00 00 callq 40131b <string_length>
40107f: 83 f8 06 cmp $0x6,%eax
401082: 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),%ecx
40108f: 88 0c 24 mov %cl,(%rsp)
401092: 48 8b 14 24 mov (%rsp),%rdx
401096: 83 e2 0f and $0xf,%edx
401099: 0f b6 92 b0 24 40 00 movzbl 0x4024b0(%rdx),%edx
4010a0: 88 54 04 10 mov %dl,0x10(%rsp,%rax,1)
4010a4: 48 83 c0 01 add $0x1,%rax
4010a8: 48 83 f8 06 cmp $0x6,%rax
4010ac: 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,%esi
4010b8: 48 8d 7c 24 10 lea 0x10(%rsp),%rdi
4010bd: e8 76 02 00 00 callq 401338 <strings_not_equal>
4010c2: 85 c0 test %eax,%eax
4010c4: 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,%eax
4010d7: eb b2 jmp 40108b <phase_5+0x29>
4010d9: 48 8b 44 24 18 mov 0x18(%rsp),%rax
4010de: 64 48 33 04 25 28 00 xor %fs:0x28,%rax
4010e5: 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,%rsp
4010f2: 5b pop %rbx
4010f3: c3 retq

咱们输入的东西存进了%rdi。然后这一段:

  40107a:	e8 9c 02 00 00       	callq  40131b <string_length>
40107f: 83 f8 06 cmp $0x6,%eax
401082: 74 4e je 4010d2 <phase_5+0x70>

很明显告诉我们,要输入6个数字。

这段代码:

  40108b:	0f b6 0c 03          	movzbl (%rbx,%rax,1),%ecx
40108f: 88 0c 24 mov %cl,(%rsp)
401092: 48 8b 14 24 mov (%rsp),%rdx
401096: 83 e2 0f and $0xf,%edx
401099: 0f b6 92 b0 24 40 00 movzbl 0x4024b0(%rdx),%edx
4010a0: 88 54 04 10 mov %dl,0x10(%rsp,%rax,1)
4010a4: 48 83 c0 01 add $0x1,%rax
4010a8: 48 83 f8 06 cmp $0x6,%rax
4010ac: 75 dd jne 40108b <phase_5+0x29>

就很明显啦,要循环6次把数据放进栈里。

注意这里:

  401096:	83 e2 0f             	and    $0xf,%edx
401099: 0f b6 92 b0 24 40 00 movzbl 0x4024b0(%rdx),%edx
4010a0: 88 54 04 10 mov %dl,0x10(%rsp,%rax,1)

这里的意思是,只看后四位的数据,在0x4024b0中找这个数据对应的位置的字母,再放进栈中。

于是你跑到这个位置去看数据,就会发现那句金句:

(之前我就是直接复制flyers到里面去,然后奇怪了半天……)

这里还是没懂对吧,往下看到这:

  4010ae:	c6 44 24 16 00       	movb   $0x0,0x16(%rsp)
4010b3: be 5e 24 40 00 mov $0x40245e,%esi
4010b8: 48 8d 7c 24 10 lea 0x10(%rsp),%rdi
4010bd: e8 76 02 00 00 callq 401338 <strings_not_equal>

想起来之前做的实验,我猜你赶紧回去看0x40245e存了个什么样的字符串。反正你会得到一个flyers的字符串。

要让栈里的数据和这个字符串相同哦~也就是说要根据上面那个数组的数据,对着这个字符串确定索引。

最终你的答案应该就是:

9?>567

phase_6

这个部分真的是极其复杂……

00000000004010f4 <phase_6>:
4010f4: 41 56 push %r14
4010f6: 41 55 push %r13
4010f8: 41 54 push %r12
4010fa: 55 push %rbp
4010fb: 53 push %rbx # 传递参数
4010fc: 48 83 ec 50 sub $0x50,%rsp # 给函数腾空间
401100: 49 89 e5 mov %rsp,%r13 # r13存储栈指针
401103: 48 89 e6 mov %rsp,%rsi # rsi存储栈指针
401106: e8 51 03 00 00 callq 40145c <read_six_numbers># 读入6个数进栈中
40110b: 49 89 e6 mov %rsp,%r14 # r14存储栈指针
40110e: 41 bc 00 00 00 00 mov $0x0,%r12d # r12存储0
401114: 4c 89 ed mov %r13,%rbp # rbp存储r13栈指针的当前的位置
401117: 41 8b 45 00 mov 0x0(%r13),%eax # 当前指针位置放置的数据放进eax
40111b: 83 e8 01 sub $0x1,%eax # eax的数据减1
40111e: 83 f8 05 cmp $0x5,%eax
401121: 76 05 jbe 401128 <phase_6+0x34># eax要小于6,否则引爆炸弹
401123: e8 12 03 00 00 callq 40143a <explode_bomb># 输入数据总数要1-6之间
401128: 41 83 c4 01 add $0x1,%r12d # r12 = 1, 2,3,4,5,6
40112c: 41 83 fc 06 cmp $0x6,%r12d
401130: 74 21 je 401153 <phase_6+0x5f># 当r12为6时跳出循环
401132: 44 89 e3 mov %r12d,%ebx # 将r12的数据放进ebx
401135: 48 63 c3 movslq %ebx,%rax # ebx的数据放进rax
401138: 8b 04 84 mov (%rsp,%rax,4),%eax # 将栈中的6个数分别放进eax
40113b: 39 45 00 cmp %eax,0x0(%rbp)
40113e: 75 05 jne 401145 <phase_6+0x51># 剩余5个数要都不跟第一个数当前栈指针的数相同才能不踩炸弹
401140: e8 f5 02 00 00 callq 40143a <explode_bomb># 6个数要各不相同,且取值为1-6
401145: 83 c3 01 add $0x1,%ebx # ebx加1
401148: 83 fb 05 cmp $0x5,%ebx
40114b: 7e e8 jle 401135 <phase_6+0x41># 跳回循环起点,只要没做满6次
40114d: 49 83 c5 04 add $0x4,%r13 # r13栈指针指向下一个数
401151: eb c1 jmp 401114 <phase_6+0x20># 跳回循环起点
401153: 48 8d 74 24 18 lea 0x18(%rsp),%rsi # 将栈指针中6个数据后的指针存在rsi
401158: 4c 89 f0 mov %r14,%rax # r14的栈指针存到rax里
40115b: b9 07 00 00 00 mov $0x7,%ecx # ecx存进一个值为7
401160: 89 ca mov %ecx,%edx # ecx的值放进edx,值为7
401162: 2b 10 sub (%rax),%edx # 将rax指针中存放的数,变成7-x,放进edx
401164: 89 10 mov %edx,(%rax) # 将栈指针指向的值更新为7-x
401166: 48 83 c0 04 add $0x4,%rax # rax指针移动到下一个数据
40116a: 48 39 f0 cmp %rsi,%rax
40116d: 75 f1 jne 401160 <phase_6+0x6c># 循环更新所有的数
40116f: be 00 00 00 00 mov $0x0,%esi # esi存储0
401174: eb 21 jmp 401197 <phase_6+0xa3># 跳转,163
401176: 48 8b 52 08 mov 0x8(%rdx),%rdx # rdx链表指向下一位
40117a: 83 c0 01 add $0x1,%eax # eax+1
40117d: 39 c8 cmp %ecx,%eax
40117f: 75 f5 jne 401176 <phase_6+0x82># 找到一个与当前栈指针指向的数据相同的为止
401181: eb 05 jmp 401188 <phase_6+0x94>
401183: ba d0 32 60 00 mov $0x6032d0,%edx # edx 存放链表的起点
401188: 48 89 54 74 20 mov %rdx,0x20(%rsp,%rsi,2) # 在栈+32的位置放置地址
40118d: 48 83 c6 04 add $0x4,%rsi # rsi+4
401191: 48 83 fe 18 cmp $0x18,%rsi
401195: 74 14 je 4011ab <phase_6+0xb7># 要进行6次后才到下一阶段
401197: 8b 0c 34 mov (%rsp,%rsi,1),%ecx # 栈指针指向的第一个数存储进ecx
40119a: 83 f9 01 cmp $0x1,%ecx
40119d: 7e e4 jle 401183 <phase_6+0x8f>
40119f: b8 01 00 00 00 mov $0x1,%eax # eax中存1
4011a4: ba d0 32 60 00 mov $0x6032d0,%edx # edx存链表起点
4011a9: eb cb jmp 401176 <phase_6+0x82># 数字要找到对应的点放
4011ab: 48 8b 5c 24 20 mov 0x20(%rsp),%rbx # 将链表起点的指针放到rbx
4011b0: 48 8d 44 24 28 lea 0x28(%rsp),%rax # 将第二个点的指针放进rax
4011b5: 48 8d 74 24 50 lea 0x50(%rsp),%rsi # 将最后一个点指针放进rsi
4011ba: 48 89 d9 mov %rbx,%rcx # 将rbx指针放进rcx
4011bd: 48 8b 10 mov (%rax),%rdx # 将rax存放的节点值放进rdx
4011c0: 48 89 51 08 mov %rdx,0x8(%rcx) # 将rdx存到rcx后继
4011c4: 48 83 c0 08 add $0x8,%rax # rax向下个节点运动
4011c8: 48 39 f0 cmp %rsi,%rax
4011cb: 74 05 je 4011d2 <phase_6+0xde># 做6次,把链表更新好
4011cd: 48 89 d1 mov %rdx,%rcx
4011d0: eb eb jmp 4011bd <phase_6+0xc9>
4011d2: 48 c7 42 08 00 00 00 movq $0x0,0x8(%rdx) # 将rdx后继置null
4011d9: 00
4011da: bd 05 00 00 00 mov $0x5,%ebp # 5进ebp
4011df: 48 8b 43 08 mov 0x8(%rbx),%rax # 链表起点第二个放进rax
4011e3: 8b 00 mov (%rax),%eax # 值
4011e5: 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),%rbx #
4011f2: 83 ed 01 sub $0x1,%ebp
4011f5: 75 e8 jne 4011df <phase_6+0xeb>
4011f7: 48 83 c4 50 add $0x50,%rsp
4011fb: 5b pop %rbx
4011fc: 5d pop %rbp
4011fd: 41 5c pop %r12
4011ff: 41 5d pop %r13
401201: 41 5e pop %r14
401203: c3 retq

不一边看一边写注释是真的看不懂……

上面的注释也写的差不多了,这段代码主要是分几部分:

  1. 读入6个数,且6个数必须是在1-6之间各不相同的数,否则爆炸。
  2. 将所有的数都更新成与7的模。
  3. 按照输入顺序,将$0x6032d0中的链表存进栈中,要求链表的结点值要和输入的数字顺序相同。
  4. 将链表重新连接起来。
  5. 要求链表中每个节点的值的后半部分要从大到小排列。

然后可以反推了,根据这个链表的后半部分,可以得到序列:

3 4 5 6 1 2

由于要取模,所以需要输入的序列是:

4 3 2 1 6 5

secret_phase

好像我现在才知道有这个阶段,先去看看~

CSAPP:bomblab的更多相关文章

  1. CSAPP 之 BombLab 详解

    前言 本篇博客将会展示 CSAPP 之 BombLab 的拆弹过程,粉碎 Dr.Evil 的邪恶阴谋.Dr.Evil 的替身,杀手皇后,总共设置了 6 个炸弹,每个炸弹对应一串字符串,如果字符串错误, ...

  2. CSAPP:第十二章 并发编程

    CSAPP:第十二章 并发编程 12.1 线程执行模型12.2 多线程之间并发通信12.3 其他并发问题   使用应用级并发的应用程序称为并发程序.现代操作系统提供三种基本的构造并发程序的方法: 进程 ...

  3. CSAPP:第十一章 网络编程

    CSAPP:第十一章 网络编程 11.1 客户端服务器模型11.2 全球IP因特网11.3 套接字接口 11.1 客户端服务器模型   每个网络应用都是基于客户端-服务器模型.采用这个模型,一个应用是 ...

  4. CSAPP:第十章 系统级I/O

    CSAPP:第十章 系统级I/O 10.1 unix I/O10.2 文件10.3 读取文件元数据10.4 读取目录内容10.5 共享文件10.6 我们该使用哪些I/O函数? 10.1 unix I/ ...

  5. CSAPP:第九章 虚拟内存

    CSAPP:第九章 虚拟内存 关键点:虚拟内存.物理内存 9.1 物理地址和虚拟地址9.2 地址空间9.3 虚拟内存作为缓存的公工具 9.1 物理地址和虚拟地址   计算机的主存被组织成一个由M个连续 ...

  6. CSAPP:第八章 异常控制流2

    CSAPP:第八章 异常控制流2 关键点:进程控制.信号 8.4 进程控制8.5 信号 8.4 进程控制   Unix提供了大量从C程序中操作进程的系统调用.8.4.1 获取进程ID  每个进程都有一 ...

  7. CSAPP:第八章 异常控制流1

    CSAPP:第八章 异常控制流1 关键点:异常 8.1 异常8.2 进程   现代系统通过使控制流发生突变来对这些情况做出反应,一般而言,我们把这些突变称为异常控制流(Exceptional Cont ...

  8. CSAPP:第三章程序的机器级表示1

    CSAPP:程序的机器级表示1 关键点:数据格式.操作数指示符. 数据格式访问信息操作数指示符举例说明 数据格式   术语字(word)表示16位数据类型,32位数为双字(double words), ...

  9. CSAPP:信息的表和处理2

    CSAPP:信息的表和处理2 关键点:浮点数.浮点数运算. 二进制小数IEEE浮点数表示浮点数转换(单精度)参考 二进制小数   形如表示的二进制数,其中每个位的取值范围位0和1.这种表示方式的定义如 ...

随机推荐

  1. application/octet-stream二进制流, springboot项目, postman 测试参数设置

    这里使用 原生String接受,之后解析,

  2. .h5图像文件(数据集)的读取并存储 工具贴(二)

    概述 H5文件是层次数据格式第5代的版本(Hierarchical Data Format,HDF5),它是用于存储科学数据的一种文件格式和库文件.由美国超级计算中心与应用中心研发的文件格式,用以存储 ...

  3. 孟老板 Paging3 (二) 结合Room

    BaseAdapter系列 ListAdapter系列 Paging3 (一) 入门 Paging3 (二) 结合 Room Paging3 (二)  结合Room Paging 数据源不开放, 无法 ...

  4. 孟老板 ListAdapter封装, 告别Adapter代码 (三)

    BaseAdapter系列 ListAdapter封装, 告别Adapter代码 (一) ListAdapter封装, 告别Adapter代码 (二) ListAdapter封装, 告别Adapter ...

  5. div和img垂直居中的方法

    div垂直居中可以使用height和line-height,多个div的话就不适用了. 可以使用下面的方式垂直居中 <div class="parent"> <d ...

  6. kube-controller-manager源码分析-AD controller分析

    kubernetes ceph-csi分析目录导航 概述 kube-controller-manager组件中,有两个controller与存储相关,分别是PV controller与AD contr ...

  7. App免责声明

    一切移动客户端用户在下载并浏览xxxAPP软件时均被视为已经仔细阅读本条款并完全同意.凡以任何方式使用本APP,或直接.间接使用本APP资料者,均被视为自愿接受本网页相关声明和用户服务协议的约束. x ...

  8. 『心善渊』Selenium3.0基础 — 15、Selenium对多窗口的操作

    目录 1.多标签/多窗口之间的切换 2.句柄练习 1.多标签/多窗口之间的切换 (1)多标签/多窗口场景: 在页面操作过程中有时候点击某个链接会弹出新的窗口,这时就需要切换到新打开的窗口上进行操作,如 ...

  9. centos7 system自定义服务

      1.介绍 centos中service命令与/etc/init.d的关系 service httpd start 其实是启动了存放在/etc/init.d目录下的脚本. 但是centos7的服务管 ...

  10. 16、lamp的搭建

    搭建web02服务器作为web01的负载均衡服务器: httpd和nginx配置比较相似,也有虚拟主机,一个http服务需要配置多个站点,基于ip(基本用不到).端口(内部网站).域名(外部网站): ...