CSAPP Bomb Lab

CSAPP Bomb Lab_第1张图片
特种部队

CSAPP Bomb Lab_第2张图片
拆炸弹1

CSAPP Bomb Lab_第3张图片
拆炸弹2

我们看了很多关于特种兵在危机关头拆炸弹的场景,觉得很酷吧!所以现在就让我们来拆一个“炸弹”。
Bomb Lab这个实验是相当有趣的,比起之前耗脑的 Data Lab,这个Lab主要是学习反汇编以及阅读反汇编出来的汇编代码。通过对一个二进制可执行文件的反汇编,找出正确的(那根线),然后“剪短“,否则的话就会”Boom!“,不过不会立即伤及生命,如果你在CMU上课,你会丢掉0.5分,如果不是,你会收到愤怒。现在就来看看我的拆炸弹之旅吧!

这里我的环境是OS X El Capitan还有Ubuntu 16.04,所以LLDB和GDB一起上,不过反汇编出来的代码都差不多:

Phase1

Mac没有GDB,所以就使用LLDB来代替喽:

进入LLDB

lldb bomb

使用disassemble进行反汇编,参考bomb.c文件,可以知道主要的几个函数名:首先是Phase_1

(lldb) disas -n phase_1

得到以下汇编代码

bomb`phase_1:
bomb[0x400ee0] <+0>:  subq   $0x8, %rsp
bomb[0x400ee4] <+4>:  movl   $0x402400, %esi
bomb[0x400ee9] <+9>:  callq  0x401338                  ; strings_not_equal
bomb[0x400eee] <+14>: testl  %eax, %eax
bomb[0x400ef0] <+16>: je     0x400ef7                  ; <+23>
bomb[0x400ef2] <+18>: callq  0x40143a                  ; explode_bomb
bomb[0x400ef7] <+23>: addq   $0x8, %rsp
bomb[0x400efb] <+27>: retq

这段代码还是挺好理解的,保存栈指针(Stack pointer),将 $0x402400传给%esi,调用位于0x401338strings_not_equal函数,比较%eax是否为0,不为零则调用explode_bomb函数,为零则返回。所以关键要找出字符串是什么。根据上述的汇编代码,可以发现字符串被保存在0x402400这里,所以使用print来查看:

(lldb) print (char *)0x402400

得到

0x00402400: "Border relations with Canada have never been better."

所以第一关的答案就是这个啦!

Phase2

同样,还是先反汇编出代码

bomb`phase_2:
bomb[0x400efc] <+0>:  pushq  %rbp
bomb[0x400efd] <+1>:  pushq  %rbx
bomb[0x400efe] <+2>:  subq   $0x28, %rsp
bomb[0x400f02] <+6>:  movq   %rsp, %rsi
bomb[0x400f05] <+9>:  callq  0x40145c                  ; read_six_numbers
bomb[0x400f0a] <+14>: cmpl   $0x1, (%rsp)
bomb[0x400f0e] <+18>: je     0x400f30                  ; <+52>
bomb[0x400f10] <+20>: callq  0x40143a                  ; explode_bomb
bomb[0x400f15] <+25>: jmp    0x400f30                  ; <+52>
bomb[0x400f17] <+27>: movl   -0x4(%rbx), %eax
bomb[0x400f1a] <+30>: addl   %eax, %eax
bomb[0x400f1c] <+32>: cmpl   %eax, (%rbx)
bomb[0x400f1e] <+34>: je     0x400f25                  ; <+41>
bomb[0x400f20] <+36>: callq  0x40143a                  ; explode_bomb
bomb[0x400f25] <+41>: addq   $0x4, %rbx
bomb[0x400f29] <+45>: cmpq   %rbp, %rbx
bomb[0x400f2c] <+48>: jne    0x400f17                  ; <+27>
bomb[0x400f2e] <+50>: jmp    0x400f3c                  ; <+64>
bomb[0x400f30] <+52>: leaq   0x4(%rsp), %rbx
bomb[0x400f35] <+57>: leaq   0x18(%rsp), %rbp
bomb[0x400f3a] <+62>: jmp    0x400f17                  ; <+27>
bomb[0x400f3c] <+64>: addq   $0x28, %rsp
bomb[0x400f40] <+68>: popq   %rbx
bomb[0x400f41] <+69>: popq   %rbp
bomb[0x400f42] <+70>: retq

从上述汇编中,可以发现从%rsp位置开始保存数字。反汇编read_six_numbers得到

bomb`read_six_numbers:
bomb[0x40145c] <+0>:  subq   $0x18, %rsp
bomb[0x401460] <+4>:  movq   %rsi, %rdx
bomb[0x401463] <+7>:  leaq   0x4(%rsi), %rcx
bomb[0x401467] <+11>: leaq   0x14(%rsi), %rax
bomb[0x40146b] <+15>: movq   %rax, 0x8(%rsp)
bomb[0x401470] <+20>: leaq   0x10(%rsi), %rax
bomb[0x401474] <+24>: movq   %rax, (%rsp)
bomb[0x401478] <+28>: leaq   0xc(%rsi), %r9
bomb[0x40147c] <+32>: leaq   0x8(%rsi), %r8
bomb[0x401480] <+36>: movl   $0x4025c3, %esi
bomb[0x401485] <+41>: movl   $0x0, %eax
bomb[0x40148a] <+46>: callq  0x400bf0                  ; symbol stub for: __isoc99_sscanf
bomb[0x40148f] <+51>: cmpl   $0x5, %eax
bomb[0x401492] <+54>: jg     0x401499                  ; <+61>
bomb[0x401494] <+56>: callq  0x40143a                  ; explode_bomb
bomb[0x401499] <+61>: addq   $0x18, %rsp
bomb[0x40149d] <+65>: retq

根据Phase1,很敏感的会发现movl $0x4025c3, %esi这行。通过之前一样的方法,得到0x4025c3内存里的字符串,0x004025c3: "%d %d %d %d %d %d"再根据bomb[0x40148a] <+46>: callq 0x400bf0 ; symbol stub for: __isoc99_sscanf这句,猜一下,立马就能联想到scanf("%d %d %d %d %d %d",a,b,c,d,e,f);,也就是说,输入的格式已经确定了。bomb[0x40145c] <+0>: subq $0x18, %rsp这行也暗示了之前bomb[0x400f35] <+57>: leaq 0x18(%rsp), %rbp为什么是0x18(%rsp)。回到phase_2,根据cmpl $0x1, (%rsp)和下一行汇编语句,很容易知道第一个数是1.接着跳到了<+52>,将0x4(%rsp)指向内存里的值传给%rbx,将0x18(%rsp)指向内存里的值传给%rbp

bomb[0x400f17] <+27>: movl   -0x4(%rbx), %eax
bomb[0x400f1a] <+30>: addl   %eax, %eax
bomb[0x400f1c] <+32>: cmpl   %eax, (%rbx)
bomb[0x400f1e] <+34>: je     0x400f25

这段代码是循环里的部分

bomb[0x400f25] <+41>: addq   $0x4, %rbx
bomb[0x400f29] <+45>: cmpq   %rbp, %rbx
bomb[0x400f2c] <+48>: jne    0x400f17                  ; <+27>
bomb[0x400f2e] <+50>: jmp    0x400f3c                  ; <+64>

这是循环条件,所以可以得出这6个数是等比数列1 2 4 8 16 32

Phase3

不多说,老方法:

disas phase_s
bomb`phase_3:
bomb[0x400f43] <+0>:   subq   $0x18, %rsp
bomb[0x400f47] <+4>:   leaq   0xc(%rsp), %rcx
bomb[0x400f4c] <+9>:   leaq   0x8(%rsp), %rdx
bomb[0x400f51] <+14>:  movl   $0x4025cf, %esi
bomb[0x400f56] <+19>:  movl   $0x0, %eax
bomb[0x400f5b] <+24>:  callq  0x400bf0                  ; symbol stub for: __isoc99_sscanf
bomb[0x400f60] <+29>:  cmpl   $0x1, %eax
bomb[0x400f63] <+32>:  jg     0x400f6a                  ; <+39>
bomb[0x400f65] <+34>:  callq  0x40143a                  ; explode_bomb
bomb[0x400f6a] <+39>:  cmpl   $0x7, 0x8(%rsp)
bomb[0x400f6f] <+44>:  ja     0x400fad                  ; <+106>
bomb[0x400f71] <+46>:  movl   0x8(%rsp), %eax
bomb[0x400f75] <+50>:  jmpq   *0x402470(,%rax,8)
bomb[0x400f7c] <+57>:  movl   $0xcf, %eax
bomb[0x400f81] <+62>:  jmp    0x400fbe                  ; <+123>
bomb[0x400f83] <+64>:  movl   $0x2c3, %eax
bomb[0x400f88] <+69>:  jmp    0x400fbe                  ; <+123>
bomb[0x400f8a] <+71>:  movl   $0x100, %eax
bomb[0x400f8f] <+76>:  jmp    0x400fbe                  ; <+123>
bomb[0x400f91] <+78>:  movl   $0x185, %eax
bomb[0x400f96] <+83>:  jmp    0x400fbe                  ; <+123>
bomb[0x400f98] <+85>:  movl   $0xce, %eax
bomb[0x400f9d] <+90>:  jmp    0x400fbe                  ; <+123>
bomb[0x400f9f] <+92>:  movl   $0x2aa, %eax
bomb[0x400fa4] <+97>:  jmp    0x400fbe                  ; <+123>
bomb[0x400fa6] <+99>:  movl   $0x147, %eax
bomb[0x400fab] <+104>: jmp    0x400fbe                  ; <+123>
bomb[0x400fad] <+106>: callq  0x40143a                  ; explode_bomb
bomb[0x400fb2] <+111>: movl   $0x0, %eax
bomb[0x400fb7] <+116>: jmp    0x400fbe                  ; <+123>
bomb[0x400fb9] <+118>: movl   $0x137, %eax
bomb[0x400fbe] <+123>: cmpl   0xc(%rsp), %eax
bomb[0x400fc2] <+127>: je     0x400fc9                  ; <+134>
bomb[0x400fc4] <+129>: callq  0x40143a                  ; explode_bomb
bomb[0x400fc9] <+134>: addq   $0x18, %rsp
bomb[0x400fcd] <+138>: retq

不用骗自己,也不用骗我,你已经被这段代码吓趴下了,不的不承认,为了解决这个玩意,我卡了一天,在YouTuBe上看了n个讲解的视频,终于算是搞明白了!!同样,根据bomb[0x400f51] <+14>: movl $0x4025cf, %esi可以得到%d %d这个格式,代表要输入两个整数。

bomb[0x400f47] <+4>:   leaq   0xc(%rsp), %rcx
bomb[0x400f4c] <+9>:   leaq   0x8(%rsp), %rdx

这两行代表了两个数存的位置。

bomb[0x400f6a] <+39>:  cmpl   $0x7, 0x8(%rsp)
bomb[0x400f6f] <+44>:  ja     0x400fad                  ; <+106>

由这两行,可知第一个数要不能大于7,jaunsigned >,所以第一个数还要是正数。关键的一行是这个bomb[0x400f75] <+50>: jmpq *0x402470(,%rax,8),这是一个switch跳转语句,跳转到0x402470+ %rax * 8的位置。使用p/x来确定跳转的目的地址。

(gdb) p/x *(0x402470)
$1 = 0x400f7c
(gdb) p/x *(0x402470+8)
$2 = 0x400fb9
(gdb) p/x *(0x402470+16)
$3 = 0x400f83
(gdb) p/x *(0x402470+24)
$4 = 0x400f8a
(gdb) p/x *(0x402470+32)
$5 = 0x400f91
(gdb) p/x *(0x402470+40)
$6 = 0x400f98
(gdb) p/x *(0x402470+48)
$7 = 0x400f9f
(gdb) p/x *(0x402470+56)
$8 = 0x400fa6

通过这个跳转表,可得得到8个解

0 207
1 311
2 707
3 256
4 389
5 206
6 682
7 327

每一组解都可以拆掉它。

Phase4

平生最讨厌废话!!!

bomb`phase_4:
bomb[0x40100c] <+0>:  subq   $0x18, %rsp
bomb[0x401010] <+4>:  leaq   0xc(%rsp), %rcx
bomb[0x401015] <+9>:  leaq   0x8(%rsp), %rdx
bomb[0x40101a] <+14>: movl   $0x4025cf, %esi
bomb[0x40101f] <+19>: movl   $0x0, %eax
bomb[0x401024] <+24>: callq  0x400bf0                  ; symbol stub for: __isoc99_sscanf
bomb[0x401029] <+29>: cmpl   $0x2, %eax
bomb[0x40102c] <+32>: jne    0x401035                  ; <+41>
bomb[0x40102e] <+34>: cmpl   $0xe, 0x8(%rsp)
bomb[0x401033] <+39>: jbe    0x40103a                  ; <+46>
bomb[0x401035] <+41>: callq  0x40143a                  ; explode_bomb
bomb[0x40103a] <+46>: movl   $0xe, %edx
bomb[0x40103f] <+51>: movl   $0x0, %esi
bomb[0x401044] <+56>: movl   0x8(%rsp), %edi
bomb[0x401048] <+60>: callq  0x400fce                  ; func4
bomb[0x40104d] <+65>: testl  %eax, %eax
bomb[0x40104f] <+67>: jne    0x401058                  ; <+76>
bomb[0x401051] <+69>: cmpl   $0x0, 0xc(%rsp)
bomb[0x401056] <+74>: je     0x40105d                  ; <+81>
bomb[0x401058] <+76>: callq  0x40143a                  ; explode_bomb
bomb[0x40105d] <+81>: addq   $0x18, %rsp
bomb[0x401061] <+85>: retq

难度越来越大啦!居然开始调函数了,不过同样的方式,可以确定第一个整数小于等于14,第二个数为0。第一个数具体值,需要执行func4。所以:

bomb`func4:
bomb[0x400fce] <+0>:  subq   $0x8, %rsp
bomb[0x400fd2] <+4>:  movl   %edx, %eax
bomb[0x400fd4] <+6>:  subl   %esi, %eax
bomb[0x400fd6] <+8>:  movl   %eax, %ecx
bomb[0x400fd8] <+10>: shrl   $0x1f, %ecx
bomb[0x400fdb] <+13>: addl   %ecx, %eax
bomb[0x400fdd] <+15>: sarl   %eax
bomb[0x400fdf] <+17>: leal   (%rax,%rsi), %ecx
bomb[0x400fe2] <+20>: cmpl   %edi, %ecx
bomb[0x400fe4] <+22>: jle    0x400ff2                  ; <+36>
bomb[0x400fe6] <+24>: leal   -0x1(%rcx), %edx
bomb[0x400fe9] <+27>: callq  0x400fce                  ; <+0>
bomb[0x400fee] <+32>: addl   %eax, %eax
bomb[0x400ff0] <+34>: jmp    0x401007                  ; <+57>
bomb[0x400ff2] <+36>: movl   $0x0, %eax
bomb[0x400ff7] <+41>: cmpl   %edi, %ecx
bomb[0x400ff9] <+43>: jge    0x401007                  ; <+57>
bomb[0x400ffb] <+45>: leal   0x1(%rcx), %esi
bomb[0x400ffe] <+48>: callq  0x400fce                  ; <+0>
bomb[0x401003] <+53>: leal   0x1(%rax,%rax), %eax
bomb[0x401007] <+57>: addq   $0x8, %rsp
bomb[0x40100b] <+61>: retq

看到这里,更加绝望,调用的一个函数都这么长,不过仔细看会发现<+20>和<+41>是一样的,而他们的下一行判断正好相反。注意<+24>和<+45>,以及他们的下一行,都很类似。其实就是递归逼近答案。好吧,随便带入一个0,结果发现正好就正确了。所以输入0 0。倒是测试了一下,发现输入1 0或者3 0或者7 0都正确,果然func4就是翻来覆去结果一样喽。只要第一个数字满足条件就行了。

Phase5

呃。。。刷一下存在感。。。

bomb`phase_5:
bomb[0x401062] <+0>: pushq %rbx
bomb[0x401063] <+1>: subq $0x20, %rsp
bomb[0x401067] <+5>: movq %rdi, %rbx
bomb[0x40106a] <+8>: movq %fs:0x28, %rax
bomb[0x401073] <+17>: movq %rax, 0x18(%rsp)
bomb[0x401078] <+22>: xorl %eax, %eax
bomb[0x40107a] <+24>: callq 0x40131b ; string_length
bomb[0x40107f] <+29>: cmpl $0x6, %eax
bomb[0x401082] <+32>:  je     0x4010d2                  ; <+112>
bomb[0x401084] <+34>:  callq  0x40143a                  ; explode_bomb
bomb[0x401089] <+39>:  jmp    0x4010d2                  ; <+112>
bomb[0x40108b] <+41>:  movzbl (%rbx,%rax), %ecx
bomb[0x40108f] <+45>:  movb   %cl, (%rsp)
bomb[0x401092] <+48>:  movq   (%rsp), %rdx
bomb[0x401096] <+52>:  andl   $0xf, %edx
bomb[0x401099] <+55>:  movzbl 0x4024b0(%rdx), %edx
bomb[0x4010a0] <+62>:  movb   %dl, 0x10(%rsp,%rax)
bomb[0x4010a4] <+66>:  addq   $0x1, %rax
bomb[0x4010a8] <+70>:  cmpq   $0x6, %rax
bomb[0x4010ac] <+74>:  jne    0x40108b                  ; <+41>
bomb[0x4010ae] <+76>:  movb   $0x0, 0x16(%rsp)
bomb[0x4010b3] <+81>:  movl   $0x40245e, %esi
bomb[0x4010b8] <+86>:  leaq   0x10(%rsp), %rdi
bomb[0x4010bd] <+91>:  callq  0x401338                  ; strings_not_equal
bomb[0x4010c2] <+96>:  testl  %eax, %eax
bomb[0x4010c4] <+98>:  je     0x4010d9                  ; <+119>
bomb[0x4010c6] <+100>: callq  0x40143a                  ; explode_bomb
bomb[0x4010cb] <+105>: nopl   (%rax,%rax)
bomb[0x4010d0] <+110>: jmp    0x4010d9                  ; <+119>
bomb[0x4010d2] <+112>: movl   $0x0, %eax
bomb[0x4010d7] <+117>: jmp    0x40108b                  ; <+41>
bomb[0x4010d9] <+119>: movq   0x18(%rsp), %rax
bomb[0x4010de] <+124>: xorq   %fs:0x28, %rax
bomb[0x4010e7] <+133>: je     0x4010ee                  ; <+140>
bomb[0x4010e9] <+135>: callq  0x400b30                  ; symbol stub for: __stack_chk_fail
bomb[0x4010ee] <+140>: addq   $0x20, %rsp
bomb[0x4010f2] <+144>: popq   %rbx
bomb[0x4010f3] <+145>: retq

这道题更让人头大了,只能问问Google有没有什么好办法。这里是参考别人的一个做法:
他用到了一个逆向工具——radare2。

r2 bomb

进入--radare2,首先执行aaa来初始化。afl是用来标示函数的, 所以使用afl~phase来寻找反汇编中的phase,得到

[0x00400c90]> afl~phase
0x004015c4  149  8  sym.phase_defused
0x00401062  146  9  sym.phase_5
0x00400f43  139  8  sym.phase_3
0x00400ee0  28  3  sym.phase_1
0x004012f6  37  1  sym.invalid_phase
0x00401242  81  5  sym.secret_phase
0x0040100c  86  7  sym.phase_4
0x004010f4  272  26  sym.phase_6
0x00400efc  71  8  sym.phase_2

使用seek来选择函数,pdf来打印反汇编的函数:

[0x00400c90]> s sym.phase_5
[0x00401062]> pdf
/ (fcn) sym.phase_5 146
|           ; CALL XREF from 0x00400eaa (sym.phase_5)
|           0x00401062      53             push rbx
|           0x00401063      4883ec20       sub rsp, 0x20
|           0x00401067      4889fb         mov rbx, rdi
|           0x0040106a      64488b042528.  mov rax, qword fs:[0x28]    ; [0x28:8]=0x48b8  ; '('
|           0x00401073      4889442418     mov qword [rsp + 0x18], rax
|           0x00401078      31c0           xor eax, eax
|           0x0040107a      e89c020000     call sym.string_length
|           0x0040107f      83f806         cmp eax, 6
|       ,=< 0x00401082      744e           je 0x4010d2                
|       |   0x00401084      e8b1030000     call sym.explode_bomb
|      ,==< 0x00401089      eb47           jmp 0x4010d2               
|      ||   ; JMP XREF from 0x004010d7 (sym.phase_5)
|      ||   ; JMP XREF from 0x004010ac (sym.phase_5)
|    ..---> 0x0040108b      0fb60c03       movzx ecx, byte [rbx + rax]
|    ||||   0x0040108f      880c24         mov byte [rsp], cl
|    ||||   0x00401092      488b1424       mov rdx, qword [rsp]
|    ||||   0x00401096      83e20f         and edx, 0xf
|    ||||   0x00401099      0fb692b02440.  movzx edx, byte [rdx + str.maduiersnfotvbylSo_you_think_you_can_stop_the_bomb_with_ctrl_c__do_you_] ; [0x4024b0:1]=109 LEA obj.array.3449 ; "maduiersnfotvbylSo you think you can stop the bomb with ctrl-c, do you?" @ 0x4024b0
|    ||||   0x004010a0      88540410       mov byte [rsp + rax + 0x10], dl
|    ||||   0x004010a4      4883c001       add rax, 1
|    ||||   0x004010a8      4883f806       cmp rax, 6
|    `====< 0x004010ac      75dd           jne 0x40108b               
|     |||   0x004010ae      c644241600     mov byte [rsp + 0x16], 0
|     |||   0x004010b3      be5e244000     mov esi, str.flyers         ; "flyers" @ 0x40245e
|     |||   0x004010b8      488d7c2410     lea rdi, [rsp + 0x10]       ; 0x10 
|     |||   0x004010bd      e876020000     call sym.strings_not_equal
|     |||   0x004010c2      85c0           test eax, eax
|    ,====< 0x004010c4      7413           je 0x4010d9                
|    ||||   0x004010c6      e86f030000     call sym.explode_bomb
|    ||||   0x004010cb      0f1f440000     nop dword [rax + rax]
|   ,=====< 0x004010d0      eb07           jmp 0x4010d9               
|   |||||   ; JMP XREF from 0x00401089 (sym.phase_5)
|   |||||   ; JMP XREF from 0x00401082 (sym.phase_5)
|   |||``-> 0x004010d2      b800000000     mov eax, 0
|   ||`===< 0x004010d7      ebb2           jmp 0x40108b               
|   ||      ; JMP XREF from 0x004010d0 (sym.phase_5)
|   ||      ; JMP XREF from 0x004010c4 (sym.phase_5)
|   ``----> 0x004010d9      488b442418     mov rax, qword [rsp + 0x18] ; [0x18:8]=0x400c90 section..text
|           0x004010de      644833042528.  xor rax, qword fs:[0x28]
|       ,=< 0x004010e7      7405           je 0x4010ee                
|       |   0x004010e9      e842faffff     call sym.imp.__stack_chk_fail
|       |   ; JMP XREF from 0x004010e7 (sym.phase_5)
|       `-> 0x004010ee      4883c420       add rsp, 0x20
|           0x004010f2      5b             pop rbx
\           0x004010f3      c3             ret
[0x00401062]>

这题要求输入一个长度为6的字符串,经过一定的变换要得到0x40245e指向的字符串flyers。通过上述的代码,会敏感的发现待转换的字符串在obj.array.3449中,使用如下代码来找到偏移量:

[0x00401062]> px [email protected]
- offset -   0 1  2 3  4 5  6 7  8 9  A B  C D  E F  0123456789ABCDEF
0x004024b0  6d61 6475 6965 7273 6e66 6f74 7662 796c  maduiersnfotvbyl

上面的一个偏移量对应下面的2个字符。
下面将flyers转化为十六进制ascii
[0x00401062]> !rax2 -S flyers666c79657273
得到的666c79657273两个一组,找对应的上面的偏移量,可以得到偏移量list[9, 0xF, 0xE, 5, 6, 7]

使用python来计算出结果

off = [9, 0xF, 0xE, 5, 6, 7]
result = ""
for c in off:
    result += chr(c + 64)

print result

所以这题的答案是IONEFG
看的我眼都花了,不过多看几遍似乎可以看懂吧!!

Phase6

最后一次:

bomb`phase_6:
bomb[0x4010f4] <+0>:   pushq  %r14
bomb[0x4010f6] <+2>:   pushq  %r13
bomb[0x4010f8] <+4>:   pushq  %r12
bomb[0x4010fa] <+6>:   pushq  %rbp
bomb[0x4010fb] <+7>:   pushq  %rbx
bomb[0x4010fc] <+8>:   subq   $0x50, %rsp
bomb[0x401100] <+12>:  movq   %rsp, %r13
bomb[0x401103] <+15>:  movq   %rsp, %rsi
bomb[0x401106] <+18>:  callq  0x40145c                  ; read_six_numbers
bomb[0x40110b] <+23>:  movq   %rsp, %r14
bomb[0x40110e] <+26>:  movl   $0x0, %r12d
bomb[0x401114] <+32>:  movq   %r13, %rbp
bomb[0x401117] <+35>:  movl   (%r13), %eax
bomb[0x40111b] <+39>:  subl   $0x1, %eax
bomb[0x40111e] <+42>:  cmpl   $0x5, %eax
bomb[0x401121] <+45>:  jbe    0x401128                  ; <+52>
bomb[0x401123] <+47>:  callq  0x40143a                  ; explode_bomb
bomb[0x401128] <+52>:  addl   $0x1, %r12d
bomb[0x40112c] <+56>:  cmpl   $0x6, %r12d
bomb[0x401130] <+60>:  je     0x401153                  ; <+95>
bomb[0x401132] <+62>:  movl   %r12d, %ebx
bomb[0x401135] <+65>:  movslq %ebx, %rax
bomb[0x401138] <+68>:  movl   (%rsp,%rax,4), %eax
bomb[0x40113b] <+71>:  cmpl   %eax, (%rbp)
bomb[0x40113e] <+74>:  jne    0x401145                  ; <+81>
bomb[0x401140] <+76>:  callq  0x40143a                  ; explode_bomb
bomb[0x401145] <+81>:  addl   $0x1, %ebx
bomb[0x401148] <+84>:  cmpl   $0x5, %ebx
bomb[0x40114b] <+87>:  jle    0x401135                  ; <+65>
bomb[0x40114d] <+89>:  addq   $0x4, %r13
bomb[0x401151] <+93>:  jmp    0x401114                  ; <+32>
bomb[0x401153] <+95>:  leaq   0x18(%rsp), %rsi
bomb[0x401158] <+100>: movq   %r14, %rax
bomb[0x40115b] <+103>: movl   $0x7, %ecx
bomb[0x401160] <+108>: movl   %ecx, %edx
bomb[0x401162] <+110>: subl   (%rax), %edx
bomb[0x401164] <+112>: movl   %edx, (%rax)
bomb[0x401166] <+114>: addq   $0x4, %rax
bomb[0x40116a] <+118>: cmpq   %rsi, %rax
bomb[0x40116d] <+121>: jne    0x401160                  ; <+108>
bomb[0x40116f] <+123>: movl   $0x0, %esi
bomb[0x401174] <+128>: jmp    0x401197                  ; <+163>
bomb[0x401176] <+130>: movq   0x8(%rdx), %rdx
bomb[0x40117a] <+134>: addl   $0x1, %eax
bomb[0x40117d] <+137>: cmpl   %ecx, %eax
bomb[0x40117f] <+139>: jne    0x401176                  ; <+130>
bomb[0x401181] <+141>: jmp    0x401188                  ; <+148>
bomb[0x401183] <+143>: movl   $0x6032d0, %edx
bomb[0x401188] <+148>: movq   %rdx, 0x20(%rsp,%rsi,2)
bomb[0x40118d] <+153>: addq   $0x4, %rsi
bomb[0x401191] <+157>: cmpq   $0x18, %rsi
bomb[0x401195] <+161>: je     0x4011ab                  ; <+183>
bomb[0x401197] <+163>: movl   (%rsp,%rsi), %ecx
bomb[0x40119a] <+166>: cmpl   $0x1, %ecx
bomb[0x40119d] <+169>: jle    0x401183                  ; <+143>
bomb[0x40119f] <+171>: movl   $0x1, %eax
bomb[0x4011a4] <+176>: movl   $0x6032d0, %edx
bomb[0x4011a9] <+181>: jmp    0x401176                  ; <+130>
bomb[0x4011ab] <+183>: movq   0x20(%rsp), %rbx
bomb[0x4011b0] <+188>: leaq   0x28(%rsp), %rax
bomb[0x4011b5] <+193>: leaq   0x50(%rsp), %rsi
bomb[0x4011ba] <+198>: movq   %rbx, %rcx
bomb[0x4011bd] <+201>: movq   (%rax), %rdx
bomb[0x4011c0] <+204>: movq   %rdx, 0x8(%rcx)
bomb[0x4011c4] <+208>: addq   $0x8, %rax
bomb[0x4011c8] <+212>: cmpq   %rsi, %rax
bomb[0x4011cb] <+215>: je     0x4011d2                  ; <+222>
bomb[0x4011cd] <+217>: movq   %rdx, %rcx
bomb[0x4011d0] <+220>: jmp    0x4011bd                  ; <+201>
bomb[0x4011d2] <+222>: movq   $0x0, 0x8(%rdx)
bomb[0x4011da] <+230>: movl   $0x5, %ebp
bomb[0x4011df] <+235>: movq   0x8(%rbx), %rax
bomb[0x4011e3] <+239>: movl   (%rax), %eax
bomb[0x4011e5] <+241>: cmpl   %eax, (%rbx)
bomb[0x4011e7] <+243>: jge    0x4011ee                  ; <+250>
bomb[0x4011e9] <+245>: callq  0x40143a                  ; explode_bomb
bomb[0x4011ee] <+250>: movq   0x8(%rbx), %rbx
bomb[0x4011f2] <+254>: subl   $0x1, %ebp
bomb[0x4011f5] <+257>: jne    0x4011df                  ; <+235>
bomb[0x4011f7] <+259>: addq   $0x50, %rsp
bomb[0x4011fb] <+263>: popq   %rbx
bomb[0x4011fc] <+264>: popq   %rbp
bomb[0x4011fd] <+265>: popq   %r12
bomb[0x4011ff] <+267>: popq   %r13
bomb[0x401201] <+269>: popq   %r14
bomb[0x401203] <+271>: retq

代码很长,但是使用stepi还是可以弄懂的。首先读取6个数字,并且各不相同。然后,在0x6032d0位置有一个链表,读取这链表的值。

(gdb)x/32wx 
0x6032d0

对于读入的数,这里存在一个操作

bomb[0x40115b] <+103>: movl   $0x7, %ecx
bomb[0x401160] <+108>: movl   %ecx, %edx
bomb[0x401162] <+110>: subl   (%rax), %edx

是的,用7来减每个数并保存。在这个地方

bomb[0x4011e5] <+241>: cmpl   %eax, (%rbx)
bomb[0x4011e7] <+243>: jge    0x4011ee                  ; <+250>

这里暗示节点顺序需要时递减。所以节点重排应该是3 4 5 6 1 2
考虑之前的7减操作,最终的答案是4 3 2 1 6 5

战果

CSAPP Bomb Lab_第4张图片
成果

小结

终于,通过四天左右的思考,经过各种查资料和看视频,拆掉了这个炸弹。虽然还有些东西没有转化到自己的思维里,不过,还有时间努力的,对吧!

你可能感兴趣的:(CSAPP Bomb Lab)