CSAPP: Bomb Lab(1)

来源:互联网 发布:混沌战域仙魂进阶数据 编辑:程序博客网 时间:2024/05/21 10:25

实验需要掌握的相关工具

一.gdb(调试工具)

主要作用在于设置断点调试程序。

常用命令 举例 disassemble disassemble phase_1(将函数phase_1反汇编显示出来) print或p p/s (char*)0x123456 打印内存地址中的内容

详细见gdb教程

二. objdump(反编译工具)

主要是两个命令:

  • objdump -d ./bomb>assemble.txt
    反汇编bomb程序,并且输出到assemble.txt。该命令将整个程序反汇编(与gdb中disassemble可以协助使用)
  • objdump -t ./bomb
    输出符号表

三. strings

打印程序中出现的所有的字符串

实验过程

实验准备

实验虚拟机为:ubuntu 14.4 64位
运用objdump将程序反汇编到assemble.txt文件中
main函数的有用的主要反汇编代码如下

    0000000000400da0 <main>:      400da0:   53                      push   %rbx      .......      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>      400e3f:   e8 80 07 00 00          callq  4015c4 <phase_defused>      400e44:   bf a8 23 40 00          mov    $0x4023a8,%edi      400e49:   e8 c2 fc ff ff          callq  400b10 <puts@plt>      400e4e:   e8 4b 06 00 00          callq  40149e <read_line>      400e53:   48 89 c7                mov    %rax,%rdi      400e56:   e8 a1 00 00 00          callq  400efc <phase_2>      400e5b:   e8 64 07 00 00          callq  4015c4 <phase_defused>      400e60:   bf ed 22 40 00          mov    $0x4022ed,%edi      400e65:   e8 a6 fc ff ff          callq  400b10 <puts@plt>      400e6a:   e8 2f 06 00 00          callq  40149e <read_line>      400e6f:   48 89 c7                mov    %rax,%rdi      400e72:   e8 cc 00 00 00          callq  400f43 <phase_3>      400e77:   e8 48 07 00 00          callq  4015c4 <phase_defused>      400e7c:   bf 0b 23 40 00          mov    $0x40230b,%edi      400e81:   e8 8a fc ff ff          callq  400b10 <puts@plt>      400e86:   e8 13 06 00 00          callq  40149e <read_line>      400e8b:   48 89 c7                mov    %rax,%rdi      400e8e:   e8 79 01 00 00          callq  40100c <phase_4>      400e93:   e8 2c 07 00 00          callq  4015c4 <phase_defused>      400e98:   bf d8 23 40 00          mov    $0x4023d8,%edi      400e9d:   e8 6e fc ff ff          callq  400b10 <puts@plt>      400ea2:   e8 f7 05 00 00          callq  40149e <read_line>      400ea7:   48 89 c7                mov    %rax,%rdi      400eaa:   e8 b3 01 00 00          callq  401062 <phase_5>      400eaf:   e8 10 07 00 00          callq  4015c4 <phase_defused>      400eb4:   bf 1a 23 40 00          mov    $0x40231a,%edi      400eb9:   e8 52 fc ff ff          callq  400b10 <puts@plt>      400ebe:   e8 db 05 00 00          callq  40149e <read_line>      400ec3:   48 89 c7                mov    %rax,%rdi      400ec6:   e8 29 02 00 00          callq  4010f4 <phase_6>      400ecb:   e8 f4 06 00 00          callq  4015c4 <phase_defused>      400ed0:   b8 00 00 00 00          mov    $0x0,%eax

Bomb 1

用于验证输入的phase_1()函数反汇编代码如下:

(gdb) disassemble phase_1  //反编译phase_1函数Dump of assembler code for function phase_1:        0x0000000000400ee0 <+0>:    sub    $0x8,%rsp         0x0000000000400ee4 <+4>:    mov    $0x402400,%esi         0x0000000000400ee9 <+9>:    callq  0x401338 <strings_not_equal>        0x0000000000400eee <+14>:   test   %eax,%eax        0x0000000000400ef0 <+16>:   je     0x400ef7 <phase_1+23>        0x0000000000400ef2 <+18>:   callq  0x40143a <explode_bomb>        0x0000000000400ef7 <+23>:   add    $0x8,%rsp        0x0000000000400efb <+27>:   retq       End of assembler dump.

其中我们可以看到mov $0x402400,%esi,将内存地址指向的内容作为strings_not_equal()的第二参数,而在main()的400e37行已经将input变量地址放入rdi中作为第一个参数(相关代码段见下面代码段)。根据strings_not_equal()函数名可以得到该函数是比较两个参数所指向的内容是否相等。故我们在gdb中运用print方法获取

 (gdb) break phase_1 //为函数phase_1设置断点,当进入phase_1时暂停    (gdb) si//单步调试,且函数则进入函数内部    .........//多次单步调试    (gdb) si     0x0000000000400ee9 in phase_1 ()     (gdb) info register //程序运行到400ee9之前的程序寄存器内容列表    rax            0x603780 6305664    rbx            0x0  0    rcx            0x3  3    rdx            0x1  1    rsi            0x402400 4203520   //参数2    rdi            0x603780 6305664   //参数1    rbp            0x0  0x0    rsp            0x7fffffffdd20   0x7fffffffdd20    r8             0x7ffff7ff6004   140737354096644    r9             0x0  0    r10            0x7fffffffdab0   140737488345776    r11            0x7ffff7a45110   140737348129040    r12            0x400c90 4197520    r13            0x7fffffffde10   140737488346640    r14            0x0  0    r15            0x0  0    rip            0x400ee9 0x400ee9 <phase_1+9>    eflags         0x202    [ IF ]    cs             0x33 51    ss             0x2b 43    ds             0x0  0    es             0x0  0    fs             0x0  0    gs             0x0  0    (gdb) p/s (char*)0x402400 //根据分析打印内存地址内容,获取以下字符串    $1 = 0x402400 "Border relations with Canada have never been better."

根据得到的字符串测试bomb确实为正确的结果,解除bomb 1。


Bomb 2

    (gdb) disassemble phase_2    Dump of assembler code for function phase_2:       0x0000000000400efc <+0>: push   %rbp       0x0000000000400efd <+1>: push   %rbx       0x0000000000400efe <+2>: sub    $0x28,%rsp       0x0000000000400f02 <+6>: mov    %rsp,%rsi       0x0000000000400f05 <+9>: callq  0x40145c <read_six_numbers> //读入,并且判断是否读入6个数字       0x0000000000400f0a <+14>:    cmpl   $0x1,(%rsp) //判断第一个数字是否为1       0x0000000000400f0e <+18>:    je     0x400f30  <phase_2+52> //相等则进入循环判断       0x0000000000400f10 <+20>:    callq  0x40143a <explode_bomb>//第一个不是1,则爆炸       0x0000000000400f15 <+25>:    jmp    0x400f30 <phase_2+52>       0x0000000000400f17 <+27>:    mov    -0x4(%rbx),%eax        0x0000000000400f1a <+30>:    add    %eax,%eax       0x0000000000400f1c <+32>:    cmp    %eax,(%rbx) //后一个元素是不是前一个的两倍,因为第一个是1,所以得到后面的元素一定是2、4、8、16、32       0x0000000000400f1e <+34>:    je     0x400f25 <phase_2+41>       0x0000000000400f20 <+36>:    callq  0x40143a <explode_bomb> //不是两倍则炸弹爆炸       0x0000000000400f25 <+41>:    add    $0x4,%rbx       0x0000000000400f29 <+45>:    cmp    %rbp,%rbx       0x0000000000400f2c <+48>:    jne    0x400f17 <phase_2+27>       0x0000000000400f2e <+50>:    jmp    0x400f3c <phase_2+64>       0x0000000000400f30 <+52>:    lea    0x4(%rsp),%rbx       0x0000000000400f35 <+57>:    lea    0x18(%rsp),%rbp       0x0000000000400f3a <+62>:    jmp    0x400f17 <phase_2+27>       0x0000000000400f3c <+64>:    add    $0x28,%rsp       0x0000000000400f40 <+68>:    pop    %rbx       0x0000000000400f41 <+69>:    pop    %rbp       0x0000000000400f42 <+70>:    retq       End of assembler dump.

根据callq 0x40145c <read_six_numbers>上下文可以得到这个字符串是由6个数字组成,并且在该函数中有函数的401480: mov $0x4025c3,%esi行代码中可以读取输入的内存地址中存储的字符串格式为“%d %d %d %d %d %d”。紧接着对于phase_2函数的汇编代码进行阅读分析,先关重要代码注释见上面代码段,可以推测得到第一个数字一定为1,并且后面的数字是第一个数字的两倍。综上所述可以得到拆除该炸弹的字符串为“1 2 4 8 16 32”

根据验证,确认为正确答案

1 0
原创粉丝点击