计算机系统lab2——bomb lab

(1)phase_1

先得到汇编代码:

看到函数是<strings_not_equal>,猜测是一个比较字符串是否相等的函数,在0x400ee9处调用了函数strings_not_equal(%rdi,%rsi),在这之前向%esi输入了一个地址0x402400,我们使用命令x/s 0x402400得到待比较的字符串。

所以我们需要输入的字符串和其相等即可。

字符串为  Border relations with Canada have never been better.

(2)phase_2

先得到汇编代码

看到函数是<read_six_numbers>则判断输入是6个数字,在400f0a处(%rsp)中内容和1作比较,如果第一个数!=1就炸弹爆炸;(%rbx)始终保存为过程中的值;(%rbp)储存栈末后一位的指针,作为循环跳出的条件;进入循环400f17,每次比较前一个数的两倍和第二个数,根据400f1a处看到,如果前一个数的两倍!=第二个数,则炸弹爆炸,否则栈指针+1,继续比较。则根据6个数的循环,判断出数字为1 2 4 8 16 32。

(3)phase_3

观察到sscanf函数作为读入函数,则查看其传入参数是什么值;

发现是输入是两个整数;观察关于栈的操作:

 400f43:        48 83 ec 18                  sub    $0x18,%rsp

  400f47:        48 8d 4c 24 0c               lea    0xc(%rsp),%rcx

  400f4c:        48 8d 54 24 08               lea    0x8(%rsp),%rdx

0x8(%rsp)中储存第一个值的地址,0xc(%rsp)储存第二个数的地址;

400f5b:        e8 90 fc ff ff               callq  400bf0 <__isoc99_sscanf@plt>

400f60:        83 f8 01                     cmp    $0x1,%eax

调用读入函数返回的值为读入正确数据的个数,若小于1则炸弹爆炸,否则继续;

400f6a:        83 7c 24 08 07               cmpl   $0x7,0x8(%rsp)

指令将第一个数和7做比较,若大于7则炸弹爆炸,由此看出第一个数一定要<=7;

400f71:        8b 44 24 08                  mov    0x8(%rsp),%eax

400f75:        ff 24 c5 70 24 40 00         jmpq   *0x402470(,%rax,8)

由此看出第二句为switch跳转表,则*0x402470为间接寻址,则使用指令得出其所存储的地址;

则根据输入值直接构成跳转表

  400f75:        ff 24 c5 70 24 40 00         jmpq   *0x402470(,%rax,8)

  400f7c:        b8 cf 00 00 00               mov    $0xcf,%eax

  400f81:        eb 3b                        jmp    400fbe <phase_3+0x7b>

  400f83:        b8 c3 02 00 00               mov    $0x2c3,%eax

  400f88:        eb 34                        jmp    400fbe <phase_3+0x7b>

  400f8a:        b8 00 01 00 00               mov    $0x100,%eax

  400f8f:        eb 2d                        jmp    400fbe <phase_3+0x7b>

  400f91:        b8 85 01 00 00               mov    $0x185,%eax

  400f96:        eb 26                        jmp    400fbe <phase_3+0x7b>

  400f98:        b8 ce 00 00 00               mov    $0xce,%eax

  400f9d:        eb 1f                        jmp    400fbe <phase_3+0x7b>

  400f9f:        b8 aa 02 00 00               mov    $0x2aa,%eax

  400fa4:        eb 18                        jmp    400fbe <phase_3+0x7b>

  400fa6:        b8 47 01 00 00               mov    $0x147,%eax

  400fab:        eb 11                        jmp    400fbe <phase_3+0x7b>

所以输入的字符串是0 207或1 311或2 707或3 256或4 389或5 206或6 682或7 327

(4)phase_4

先得到汇编代码

观察输入函数和phase_3相同,得到输入是两个整数;

   0x0000000000401024 <+24>:        callq  0x400bf0 <__isoc99_sscanf@plt>

   0x0000000000401029 <+29>:        cmp    $0x2,%eax

   0x000000000040102c <+32>:        jne    0x401035 <phase_4+41>

这一段表明sscanf输入函数返回值不等于2的时候就爆炸

   0x000000000040102e <+34>:        cmpl   $0xe,0x8(%rsp)

   0x0000000000401033 <+39>:        jbe    0x40103a <phase_4+46>

   0x0000000000401035 <+41>:        callq  0x40143a <explode_bomb>

由此看出如果第一个数大于14的话就会爆炸;否则调用函数func4

   0x000000000040103a <+46>:        mov    $0xe,%edx

   0x000000000040103f <+51>:        mov    $0x0,%esi

   0x0000000000401044 <+56>:        mov    0x8(%rsp),%edi

   0x0000000000401048 <+60>:        callq  0x400fce <func4>

看出函数的参数为三个数,%edi为第一个参数是我们输入的第一个数,%esi是函数的第二个参数是0,%edx是函数的第三个参数是14

由此我们输入命令观察func4函数的汇编代码

其是一个递归函数,翻译成c语言大致是

   0x000000000040104d <+65>:        test   %eax,%eax

   0x000000000040104f <+67>:        jne    0x401058 <phase_4+76>

   0x0000000000401051 <+69>:        cmpl   $0x0,0xc(%rsp)

   0x0000000000401056 <+74>:        je     0x40105d <phase_4+81>

   0x0000000000401058 <+76>:        callq  0x40143a <explode_bomb>

再观察这一段表现出func4的返回值必须为0和我们输入的第二个数必须为0

最后通过计算得出

0 0或1 0或3 0或7 0都为正确答案

(5)phase_5

   0x0000000000401062 <+0>:        push   %rbx

   0x0000000000401063 <+1>:        sub    $0x20,%rsp

   0x0000000000401067 <+5>:        mov    %rdi,%rbx

   0x000000000040106a <+8>:        mov    %fs:0x28,%rax

   0x0000000000401073 <+17>:        mov    %rax,0x18(%rsp)

将输入的地址%rdi给了%rbx;

观察函数<string_length>为返回字符串长度的值

   0x000000000040107a <+24>:        callq  0x40131b <string_length>

   0x000000000040107f <+29>:        cmp    $0x6,%eax

   0x0000000000401082 <+32>:        je     0x4010d2 <phase_5+112>

   0x0000000000401084 <+34>:        callq  0x40143a <explode_bomb>

可以看到我们需要输入6个字符,否则爆炸

下面是一个字符串处理的六次循环函数

   0x000000000040108b <+41>:        movzbl (%rbx,%rax,1),%ecx

   0x000000000040108f <+45>:        mov    %cl,(%rsp)

   0x0000000000401092 <+48>:        mov    (%rsp),%rdx

   0x0000000000401096 <+52>:        and    $0xf,%edx

   0x0000000000401099 <+55>:        movzbl 0x4024b0(%rdx),%edx

   0x00000000004010a0 <+62>:        mov    %dl,0x10(%rsp,%rax,1)

由上面看到movzbl命令将从%rbx(输入)开始的%rax位置的一个字节赋给%ecx的低16位。接下来先把%cl中的值复制到%rsp处,再将%rsp中的值复制到%rdx中,并且&0xf取%edx的低4位。所以就是取读入的字符串中%rax位置处的字符,并且再取它的低4位放在%edx中。然后再将0x4024b0(%rdx)的一个字节放入%edx再将其末尾2字节放在了0x10(%rsp,%rax,1);

可以看到0x4024b0中的字符串如上;

   0x00000000004010b3 <+81>:        mov    $0x40245e,%esi

   0x00000000004010b8 <+86>:        lea    0x10(%rsp),%rdi

   0x00000000004010bd <+91>:        callq  0x401338 <strings_not_equal>

   0x00000000004010c2 <+96>:        test   %eax,%eax

   0x00000000004010c4 <+98>:        je     0x4010d9 <phase_5+119>

   0x00000000004010c6 <+100>:        callq  0x40143a <explode_bomb>

对比我们输入的字符串和处理后的字符串,调用<strings_not_equal>函数,如果不相同则爆炸;

0x40245e的字符串是如上;

总的来说即以我们输入的六个字符的每一个字符的低8位作为0x4024b0这个字符串的偏移量,取出的和0x40245e中的相同。

再根据ascii码表查表

flyers对应的下标是

9   1001

15 1111

14 1110

5   0101

6   0110

7   0111

yonuvw

得到相应字符;

(6)phase_6

先得到相应的汇编代码(太长了)不截屏了

观察上面这段代码,得出是读取6个值放入栈中;

从中可以看到我们读取的值需要前后相邻的不相等并且<=6,否则就爆炸;

每一个输入的值都用7减去 并且替换原来的值;

可以看出构造了一段地址连续的储存值的空间,

可以使用gdb命令看看地址中的内容

   0x0000000000401183 <+143>:        mov    $0x6032d0,%edx

   0x0000000000401188 <+148>:        mov    %rdx,0x20(%rsp,%rsi,2)

发现是node给了提示,这样的数据结构可能是链表;

并且根据我们输入的值存放的%ecx中的顺序构造;结点的首地址是rsp+0x20

%rbx(0x20(%rsp))储存的是链表的首节点地址,0x28(%rsp)储存在%rax中是链表的第二个结点的地址,0x50(%rsp)是链表的最后一个结点的地址;

取出首地址的值并且根据%rbx和%rax的移动来遍历链表,

   0x00000000004011e5 <+241>:        cmp    %eax,(%rbx)

   0x00000000004011e7 <+243>:        jge    0x4011ee <phase_6+250>

   0x00000000004011e9 <+245>:        callq  0x40143a <explode_bomb>

并且要求链表的前一个结点中存放的数据的最后4字节要

大于后一个结点。

所以使用命令观察地址中的值,观察其顺序;

则得出从大到小的顺序是3 4 5 6 1 2

所以7-x=4 3 2 1 6 5

成功拆弹。

 

总体跑分截图

 

  • 4
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值