zoukankan      html  css  js  c++  java
  • 深入理解计算机系统 BombLab 实验报告

    又快有一个月没写博客了,最近在看《深入理解计算机系统》这本书,目前看完了第三章,看完这章,对程序的机器级表示算是有了一个入门,也对 C 语言里函数栈帧有了一个初步的理解。

    为了加深对书本内容的认识,以后每学习完一部分章节,就完成相应书本附带的实验题目。

    第三章对应的实验是 BombLab,下面是我做这个实验的过程。

    BombLab 分为 6 个普通关卡和一个隐形关卡,为了开始闯关,得先弄清楚从哪里开始行动。

    首先使用 objdump 命令 objdump -t bomb > bomb_symboltable 来生成 bomb 文件的符号表(部分),如下:

    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 的行,如下:

    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 文件的反汇编文件,由于文件内容太多,这里就不全部贴出来了,在接下来的闯关中,会陆陆续续的讲这个文件中的一些汇编贴出来使用。

    有了这些准备条件,下面我们开始闯关!

    注意:接下来所有贴出来的函数的反汇编代码,都可以通过对 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  

    函数功能分析:

    范德萨发

  • 相关阅读:
    uniapp中pages文件及iconfont引入
    js判断字符串是否为JSON格式
    分布式事务CAP简介
    C#面试题
    关于跨域问题
    JS显示隐藏节点
    JS时间序列化显示
    前端命令
    Java8
    java14环境变量配置超简单
  • 原文地址:https://www.cnblogs.com/KKSJS/p/10127501.html
Copyright © 2011-2022 走看看