• 15-213 Bomb Lab


    bomb lab是一道学习汇编语言的题,一共有六个阶段,全部解开即可完成

    phase_1

    1 0x0000000000400e32 <+146>:    callq  0x40149e <read_line>
    2 0x0000000000400e37 <+151>:    mov    %rax,%rdi
    3 0x0000000000400e3a <+154>:    callq  0x400ee0 <phase_1>

    这三个指令就是phase_1了,第一条是一个调用read_line的命令,众所周知...%rax代表返回值,所以第二条命令则是指:将%rax的值赋给%rdi,记住这个rdi,待会儿有用,然后调用第三条指令phase_1

    1 0x0000000000400ee0 <+0>:    sub    $0x8,%rsp
    2 0x0000000000400ee4 <+4>:    mov    $0x402400,%esi
    3 0x0000000000400ee9 <+9>:    callq  0x401338 <strings_not_equal>
    4 0x0000000000400eee <+14>:    test   %eax,%eax
    5 0x0000000000400ef0 <+16>:    je     0x400ef7 <phase_1+23>
    6 0x0000000000400ef2 <+18>:    callq  0x40143a <explode_bomb>
    7 0x0000000000400ef7 <+23>:    add    $0x8,%rsp
    8 0x0000000000400efb <+27>:    retq   

    第一条和第八条就不看了,从第二条开始,将0x402400赋给了%esi,记住这个数,然后调用了strings_not_equal,这个函数很好理解,判断两个字符串是否相等,这个函数是这样的(一部分)

    1 0x000000000040133c <+4>:    mov    %rdi,%rbx
    2 0x000000000040133f <+7>:    mov    %rsi,%rbp

    从这两行可以看出,这个函数的参数是%rdi和%rsi,%rdi是read_line得到的值,%rsi是0x402400,回到phase_1,第四条指令test判断strings_not_euqal的返回值是否为0,若为零则跳转到0x400ef7,若不为零则会执行explode_bomb,这就是这个炸弹函数,我们不能执行它,所以,我们需要让%eax为零,也就是让%rdi和%rsi的字符串相等,我们使用命令x/s 0x402400查看内存,可以看到如下输出

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

    这就是我们第一题的答案了

    phase_2

    接下来是phase_2,我们还是像第一阶段一样,先看看代码

     1    0x0000000000400efc <+0>:    push   %rbp
     2    0x0000000000400efd <+1>:    push   %rbx
     3    0x0000000000400efe <+2>:    sub    $0x28,%rsp
     4    0x0000000000400f02 <+6>:    mov    %rsp,%rsi
     5    0x0000000000400f05 <+9>:    callq  0x40145c <read_six_numbers>
     6    0x0000000000400f0a <+14>:    cmpl   $0x1,(%rsp)
     7    0x0000000000400f0e <+18>:    je     0x400f30 <phase_2+52>
     8    0x0000000000400f10 <+20>:    callq  0x40143a <explode_bomb>
     9    0x0000000000400f15 <+25>:    jmp    0x400f30 <phase_2+52>
    10    0x0000000000400f17 <+27>:    mov    -0x4(%rbx),%eax
    11    0x0000000000400f1a <+30>:    add    %eax,%eax
    12    0x0000000000400f1c <+32>:    cmp    %eax,(%rbx)
    13    0x0000000000400f1e <+34>:    je     0x400f25 <phase_2+41>
    14    0x0000000000400f20 <+36>:    callq  0x40143a <explode_bomb>
    15    0x0000000000400f25 <+41>:    add    $0x4,%rbx
    16    0x0000000000400f29 <+45>:    cmp    %rbp,%rbx
    17    0x0000000000400f2c <+48>:    jne    0x400f17 <phase_2+27>
    18    0x0000000000400f2e <+50>:    jmp    0x400f3c <phase_2+64>
    19    0x0000000000400f30 <+52>:    lea    0x4(%rsp),%rbx
    20    0x0000000000400f35 <+57>:    lea    0x18(%rsp),%rbp
    21    0x0000000000400f3a <+62>:    jmp    0x400f17 <phase_2+27>
    22    0x0000000000400f3c <+64>:    add    $0x28,%rsp
    23    0x0000000000400f40 <+68>:    pop    %rbx
    24    0x0000000000400f41 <+69>:    pop    %rbp
    25    0x0000000000400f42 <+70>:    retq   

    首先将rsp减28,将rsp赋值给rsi

    这样,rsi和rsp都指向-28

    然后调用read_six_numbers

     1    0x000000000040145c <+0>:    sub    $0x18,%rsp
     2    0x0000000000401460 <+4>:    mov    %rsi,%rdx
     3    0x0000000000401463 <+7>:    lea    0x4(%rsi),%rcx
     4    0x0000000000401467 <+11>:    lea    0x14(%rsi),%rax
     5    0x000000000040146b <+15>:    mov    %rax,0x8(%rsp)
     6    0x0000000000401470 <+20>:    lea    0x10(%rsi),%rax
     7    0x0000000000401474 <+24>:    mov    %rax,(%rsp)
     8    0x0000000000401478 <+28>:    lea    0xc(%rsi),%r9
     9    0x000000000040147c <+32>:    lea    0x8(%rsi),%r8
    10    0x0000000000401480 <+36>:    mov    $0x4025c3,%esi
    11    0x0000000000401485 <+41>:    mov    $0x0,%eax
    12    0x000000000040148a <+46>:    callq  0x400bf0 <__isoc99_sscanf@plt>
    13    0x000000000040148f <+51>:    cmp    $0x5,%eax
    14    0x0000000000401492 <+54>:    jg     0x401499 <read_six_numbers+61>
    15    0x0000000000401494 <+56>:    callq  0x40143a <explode_bomb>
    16    0x0000000000401499 <+61>:    add    $0x18,%rsp
    17    0x000000000040149d <+65>:    retq   

    这个的话主要作用是调用sscanf函数,这是一个c语言函数

    大概是这样的

    1 int sscanf(const char *str, const char *format, ...)

    str就是我们要输入的字符串,而format是模板,这个模板存在0x4025c3所在的内存中,我们通过x指令看一下

    1 0x4025c3:    "%d %d %d %d %d %d"

    6个数字,很清晰

    而sscanf还可以接受任意个参数,用来解析模板中的数字,这6个参数分别是:rdx/rcx/r8/r9/栈顶/栈顶-1

    为了不触发炸弹,我们从汇编代码中推测出rsp指向的内存为1,而整个循环则是判断高位的数是否是低位的2倍,那么就可以得知,从rsp开始的6个数为1,2,4,8,16,32了

    答案便是"1 2 4 8 16 32"

    phase_3

     1    0x0000000000400f43 <+0>:    sub    $0x18,%rsp
     2    0x0000000000400f47 <+4>:    lea    0xc(%rsp),%rcx
     3    0x0000000000400f4c <+9>:    lea    0x8(%rsp),%rdx
     4    0x0000000000400f51 <+14>:    mov    $0x4025cf,%esi
     5    0x0000000000400f56 <+19>:    mov    $0x0,%eax
     6    0x0000000000400f5b <+24>:    callq  0x400bf0 <__isoc99_sscanf@plt>
     7    0x0000000000400f60 <+29>:    cmp    $0x1,%eax
     8    0x0000000000400f63 <+32>:    jg     0x400f6a <phase_3+39>
     9    0x0000000000400f65 <+34>:    callq  0x40143a <explode_bomb>
    10    0x0000000000400f6a <+39>:    cmpl   $0x7,0x8(%rsp)
    11    0x0000000000400f6f <+44>:    ja     0x400fad <phase_3+106>
    12    0x0000000000400f71 <+46>:    mov    0x8(%rsp),%eax
    13    0x0000000000400f75 <+50>:    jmpq   *0x402470(,%rax,8)
    14    0x0000000000400f7c <+57>:    mov    $0xcf,%eax
    15    0x0000000000400f81 <+62>:    jmp    0x400fbe <phase_3+123>
    16    0x0000000000400f83 <+64>:    mov    $0x2c3,%eax
    17    0x0000000000400f88 <+69>:    jmp    0x400fbe <phase_3+123>
    18    0x0000000000400f8a <+71>:    mov    $0x100,%eax
    19    0x0000000000400f8f <+76>:    jmp    0x400fbe <phase_3+123>
    20    0x0000000000400f91 <+78>:    mov    $0x185,%eax
    21    0x0000000000400f96 <+83>:    jmp    0x400fbe <phase_3+123>
    22    0x0000000000400f98 <+85>:    mov    $0xce,%eax
    23    0x0000000000400f9d <+90>:    jmp    0x400fbe <phase_3+123>
    24    0x0000000000400f9f <+92>:    mov    $0x2aa,%eax
    25    0x0000000000400fa4 <+97>:    jmp    0x400fbe <phase_3+123>
    26    0x0000000000400fa6 <+99>:    mov    $0x147,%eax
    27    0x0000000000400fab <+104>:    jmp    0x400fbe <phase_3+123>
    28    0x0000000000400fad <+106>:    callq  0x40143a <explode_bomb>
    29    0x0000000000400fb2 <+111>:    mov    $0x0,%eax
    30    0x0000000000400fb7 <+116>:    jmp    0x400fbe <phase_3+123>
    31 ---Type <return> to continue, or q <return> to quit---
    32    0x0000000000400fb9 <+118>:    mov    $0x137,%eax
    33    0x0000000000400fbe <+123>:    cmp    0xc(%rsp),%eax
    34    0x0000000000400fc2 <+127>:    je     0x400fc9 <phase_3+134>
    35    0x0000000000400fc4 <+129>:    callq  0x40143a <explode_bomb>
    36    0x0000000000400fc9 <+134>:    add    $0x18,%rsp
    37    0x0000000000400fcd <+138>:    retq   

    还是sscanf,首先确定rdx和rcx的位置分别是+8和+c,这就是你要输的两个数字,然后关注+39行,将rdx和7比较,大于则bomb,然后根据rdx的值去访问(0x402470+rdx*8)代表的内存,然后以这个值作为地址,进行跳转

    从0x402470开始的8个跳转地址分别是:

    1 0x402470:    0x400f7c <phase_3+57>    0x400fb9 <phase_3+118>
    2 0x402480:    0x400f83 <phase_3+64>    0x400f8a <phase_3+71>
    3 0x402490:    0x400f91 <phase_3+78>    0x400f98 <phase_3+85>
    4 0x4024a0:    0x400f9f <phase_3+92>    0x400fa6 <phase_3+99>

    尖括号内则是跳转的地址,我们可以知道,如果rdx是7,跳到99,让rcx与0x147比较,相等则成功,这里有8个地址

    根据rdx的不同,rcx的值也不同,从7到0分别是:0x147,0x2aa,0xce,0x185,0x100,0x203,0x137,0xcf,那么答案就显而易见了

    顺便,那个模板的样式是这样的

    1 0x4025cf:    "%d %d"
  • 相关阅读:
    5-JVM常用的命令
    4-JVM 参数
    3-JVM垃圾回收算法和垃圾收集器
    2-JVM内存结构
    1-JVM基础
    非常短的git学习笔记
    白话马尔科夫链蒙特卡罗方法(MCMC)
    写了个小游戏,来玩
    胡小兔的 高考2019 游记
    机房志 | 一篇中二的文章
  • 原文地址:https://www.cnblogs.com/phsy/p/11878796.html
Copyright © 2020-2023  润新知