深刻理解計算機系統 BombLab 實驗報告

又快有一個月沒寫博客了,最近在看《深刻理解計算機系統》這本書,目前看完了第三章,看完這章,對程序的機器級表示算是有了一個入門,也對 C 語言裏函數棧幀有了一個初步的理解。sass

爲了加深對書本內容的認識,之後每學習完一部分章節,就完成相應書本附帶的實驗題目。socket

第三章對應的實驗是 BombLab,下面是我作這個實驗的過程。函數

BombLab 分爲 6 個普通關卡和一個隱形關卡,爲了開始闖關,得先弄清楚從哪裏開始行動。學習

首先使用 objdump 命令 objdump -t bomb > bomb_symboltable 來生成 bomb 文件的符號表(部分),以下:ui

bomb:     file format elf64-x86-64

SYMBOL TABLE:
0000000000400238 l    d  .interp        0000000000000000              .interp
0000000000400254 l    d  .note.ABI-tag  0000000000000000              .note.ABI-tag
0000000000400274 l    d  .note.gnu.build-id     0000000000000000              .note.gnu.build-id
0000000000400298 l    d  .gnu.hash      0000000000000000              .gnu.hash
00000000004002c8 l    d  .dynsym        0000000000000000              .dynsym
00000000004005c8 l    d  .dynstr        0000000000000000              .dynstr
0000000000400736 l    d  .gnu.version   0000000000000000              .gnu.version
...
...
...
...
...
0000000000000000 F *UND* 0000000000000000 __ctype_b_loc@@GLIBC_2.3 0000000000603750 g O .bss 0000000000000008 stderr@@GLIBC_2.2.5 0000000000000000 F *UND* 0000000000000000 __sprintf_chk@@GLIBC_2.3.4 0000000000000000 F *UND* 0000000000000000 socket@@GLIBC_2.2.5

這個文件內容太多,咱們只提取出含有關鍵字 bomb 的行,以下:spa

0000000000000000 l    df *ABS*  0000000000000000              bomb.c
00000000004013ba g     F .text  0000000000000002              initialize_bomb_solve
000000000040143a g     F .text  0000000000000022              explode_bomb
000000000060375c g     O .bss   0000000000000004              bomb_id
00000000004013a2 g     F .text  0000000000000018              initialize_bomb

 其中 000000000040143a g F .text 0000000000000022 explode_bomb 這一行就是用來引爆炸彈用的,咱們能夠先記住這個地址,以備用。命令行

下面咱們再對 bomb 文件進行反彙編,使用命令 objdump -d bomb > bomb_disassamble 能夠獲得 bomb 文件的反彙編文件,因爲文件內容太多,這裏就不所有貼出來了,在接下來的闖關中,會陸陸續續的講這個文件中的一些彙編貼出來使用。3d

有了這些準備條件,下面咱們開始闖關!指針

注意:接下來全部貼出來的函數的反彙編代碼,均可以經過對 bomb 文件進行反彙編獲得。調試

第一關:

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   

首先看第一條指令 sub $0x8,%rsp,這條指令用來分配 8 字節的函數棧幀,指令 mov $0x402400,%esi ,則將當即數 0x402400 傳入寄存器 %esi 中,而後調用 strings_not_equal 這個函數, test %eax,%eax 這條指令判斷寄存器 %eax 裏是否爲 0,若是爲 0,則直接跳到 add $0x8,%rsp ,將函數指針加 8,釋放棧幀。若是不爲 0,則執行 callq 40143a <explode_bomb> ,引爆炸彈。

下面對 strings_not_equal 函數的反彙編代碼進行分析:

 1 0000000000401338 <strings_not_equal>:
 2   401338:    41 54                    push   %r12
 3   40133a:    55                       push   %rbp
 4   40133b:    53                       push   %rbx
 5   40133c:    48 89 fb                 mov    %rdi,%rbx
 6   40133f:    48 89 f5                 mov    %rsi,%rbp
 7   401342:    e8 d4 ff ff ff           callq  40131b <string_length>
 8   401347:    41 89 c4                 mov    %eax,%r12d
 9   40134a:    48 89 ef                 mov    %rbp,%rdi
10   40134d:    e8 c9 ff ff ff           callq  40131b <string_length>
11   401352:    ba 01 00 00 00           mov    $0x1,%edx
12   401357:    41 39 c4                 cmp    %eax,%r12d
13   40135a:    75 3f                    jne    40139b <strings_not_equal+0x63>
14   40135c:    0f b6 03                 movzbl (%rbx),%eax
15   40135f:    84 c0                    test   %al,%al
16   401361:    74 25                    je     401388 <strings_not_equal+0x50>
17   401363:    3a 45 00                 cmp    0x0(%rbp),%al
18   401366:    74 0a                    je     401372 <strings_not_equal+0x3a>
19   401368:    eb 25                    jmp    40138f <strings_not_equal+0x57>
20   40136a:    3a 45 00                 cmp    0x0(%rbp),%al
21   40136d:    0f 1f 00                 nopl   (%rax)
22   401370:    75 24                    jne    401396 <strings_not_equal+0x5e>
23   401372:    48 83 c3 01              add    $0x1,%rbx
24   401376:    48 83 c5 01              add    $0x1,%rbp
25   40137a:    0f b6 03                 movzbl (%rbx),%eax
26   40137d:    84 c0                    test   %al,%al
27   40137f:    75 e9                    jne    40136a <strings_not_equal+0x32>
28   401381:    ba 00 00 00 00           mov    $0x0,%edx
29   401386:    eb 13                    jmp    40139b <strings_not_equal+0x63>
30   401388:    ba 00 00 00 00           mov    $0x0,%edx
31   40138d:    eb 0c                    jmp    40139b <strings_not_equal+0x63>
32   40138f:    ba 01 00 00 00           mov    $0x1,%edx
33   401394:    eb 05                    jmp    40139b <strings_not_equal+0x63>
34   401396:    ba 01 00 00 00           mov    $0x1,%edx
35   40139b:    89 d0                    mov    %edx,%eax
36   40139d:    5b                       pop    %rbx
37   40139e:    5d                       pop    %rbp
38   40139f:    41 5c                    pop    %r12
39   4013a1:    c3                       retq   

 因爲 strings_not_equal 函數會用到 string_length 函數,因此將 string_length 函數的反彙編代碼一併貼出來:

 40 000000000040131b <string_length>:
 41   40131b:    80 3f 00                 cmpb   $0x0,(%rdi)
 42   40131e:    74 12                    je     401332 <string_length+0x17>
 43   401320:    48 89 fa                 mov    %rdi,%rdx
 44   401323:    48 83 c2 01              add    $0x1,%rdx
 45   401327:    89 d0                    mov    %edx,%eax
 46   401329:    29 f8                    sub    %edi,%eax
 47   40132b:    80 3a 00                 cmpb   $0x0,(%rdx)
 48   40132e:    75 f3                    jne    401323 <string_length+0x8>
 49   401330:    f3 c3                    repz retq 
 50   401332:    b8 00 00 00 00           mov    $0x0,%eax
 51   401337:    c3                       retq   

 代碼 2 ~ 4 行先保存相關的寄存器值。

代碼 5 ~ 6 行將傳給函數的參數保存進寄存器中。

看到這裏,也許能獲得兩個合理的猜測:

  • strings_not_equal 函數用來比較兩個字符串是否相等,這個函數的一個參數就是在函數調用前,經過 mov $0x402400,%esi 這條指令來指定,也許 0x402400 這個值就是已經存放在內存中的某個字符串的首地址(只是猜測)。
  • strings_not_equal 函數的第二個參數是經過 %rdi 來指定,可能就是咱們輸入的字符串的首地址。

若是是這樣的話,那 0x402400 這個地址處存放的字符串就是 phase_1 的答案。

下面咱們經過 GDB 來驗證咱們的猜測。

首先使用 gdb bomb 來啓動咱們須要調試的程序 bomb(前提是這個程序由 gcc bomb.c -g -o bomb 生成)。

命令行進入下面的模式:

這是咱們再輸入:

break explode_bomb
break phase_1

 來爲程序設置相應的斷點。

而後執行 run 來運行,程序會在第一個斷點處停下,這時須要咱們輸入一個字符串,因爲只是來驗證猜測,先隨便輸入一個字符串,接着會到達第二個斷點處,以下:

接下來咱們使用 stepi 命令來單步執行,使用 disas 命令能夠查看咱們當前執行到什麼地方,最後使用 print 命令來查看寄存器相關的信息,以下:

因此字符串Border relations with Canada have never been better.就是 phase_1 最終的答案。

第二關

這是  phase_2  的反彙編代碼:

 1 0000000000400efc <phase_2>:
 2   400efc:    55                       push   %rbp
 3   400efd:    53                       push   %rbx
 4   400efe:    48 83 ec 28              sub    $0x28,%rsp
 5   400f02:    48 89 e6                 mov    %rsp,%rsi
 6   400f05:    e8 52 05 00 00           callq  40145c <read_six_numbers>
 7   400f0a:    83 3c 24 01              cmpl   $0x1,(%rsp)
 8   400f0e:    74 20                    je     400f30 <phase_2+0x34>      # 知足條件,跳轉到 20 行
 9   400f10:    e8 25 05 00 00           callq  40143a <explode_bomb>      # 不知足,直接引爆炸彈
10   400f15:    eb 19                    jmp    400f30 <phase_2+0x34>
11   400f17:    8b 43 fc                 mov    -0x4(%rbx),%eax
12   400f1a:    01 c0                    add    %eax,%eax
13   400f1c:    39 03                    cmp    %eax,(%rbx)
14   400f1e:    74 05                    je     400f25 <phase_2+0x29>      # 知足條件,跳轉到 16 行
15   400f20:    e8 15 05 00 00           callq  40143a <explode_bomb>      # 不知足,則引爆炸彈
16   400f25:    48 83 c3 04              add    $0x4,%rbx
17   400f29:    48 39 eb                 cmp    %rbp,%rbx
18   400f2c:    75 e9                    jne    400f17 <phase_2+0x1b>      # 知足條件,跳轉到 11 行
19   400f2e:    eb 0c                    jmp    400f3c <phase_2+0x40>      # 不知足,跳轉到 23 行
20   400f30:    48 8d 5c 24 04           lea    0x4(%rsp),%rbx
21   400f35:    48 8d 6c 24 18           lea    0x18(%rsp),%rbp
22   400f3a:    eb db                    jmp    400f17 <phase_2+0x1b>
23   400f3c:    48 83 c4 28              add    $0x28,%rsp
24   400f40:    5b                       pop    %rbx
25   400f41:    5d                       pop    %rbp
26   400f42:    c3                       retq   

函數功能分析: 

這個函數先保存相應的寄存器(第 2 ~ 3 行),接着爲函數分配 0x28 字節的棧幀(第 4 行),

這是  read_six_numbers  的反彙編代碼:

 1 000000000040145c <read_six_numbers>:
 2   40145c:    48 83 ec 18              sub    $0x18,%rsp
 3   401460:    48 89 f2                 mov    %rsi,%rdx
 4   401463:    48 8d 4e 04              lea    0x4(%rsi),%rcx
 5   401467:    48 8d 46 14              lea    0x14(%rsi),%rax
 6   40146b:    48 89 44 24 08           mov    %rax,0x8(%rsp)
 7   401470:    48 8d 46 10              lea    0x10(%rsi),%rax
 8   401474:    48 89 04 24              mov    %rax,(%rsp)
 9   401478:    4c 8d 4e 0c              lea    0xc(%rsi),%r9
10   40147c:    4c 8d 46 08              lea    0x8(%rsi),%r8
11   401480:    be c3 25 40 00           mov    $0x4025c3,%esi
12   401485:    b8 00 00 00 00           mov    $0x0,%eax
13   40148a:    e8 61 f7 ff ff           callq  400bf0 <__isoc99_sscanf@plt>
14   40148f:    83 f8 05                 cmp    $0x5,%eax
15   401492:    7f 05                    jg     401499 <read_six_numbers+0x3d>   # 知足條件則跳轉到 17 行
16   401494:    e8 a1 ff ff ff           callq  40143a <explode_bomb>
17   401499:    48 83 c4 18              add    $0x18,%rsp
18   40149d:    c3                       retq  

函數功能分析:

范德薩發

相關文章
相關標籤/搜索