CSAPP:拆炸弹实验笔记

拆炸弹实验介绍

拆炸弹实验是CSAPP书附赠的一个有趣的实验。“炸弹”是一个可执行文件。用户执行“炸弹”后需要进行6个输入,只要输入错误一次,炸弹就会爆炸。用户需要将“炸弹”反汇编成汇编代码,并用GDB进行调试,推测出6个正确的输入分别是什么。
本门课程的助教给我们搭建了自动化的测试平台。同学可以在平台上领取专属于自己的炸弹(每个人的炸弹都有些小不同)和查看自己的分数。我领到的炸弹是39号。下载地址:
链接: https://pan.baidu.com/s/1FP2YkbnjtO_-pu9IkOmMqQ 提取码: ms8m

拆炸弹前需要知道的

需要用到的GDB命令

disas

这个命令是用于反汇编的。
disas 函数名用于反汇编一个函数,并输出得到的汇编代码
在这里插入图片描述

break

用于设置断点

  1. break 函数名:在这个函数开始的地方设置一个断点
  2. break *指令的地址:在这一行指令处设置断点。
    例:break *0x0000000000400ef0

x

查看内存地址内容的指令

info breakpoints

查看已经设置好的断点信息

ni

单步调试。让程序运行到下一行

continue或c

让程序运行到下一个断点处停下来

如何防止炸弹爆炸

炸弹每爆炸一次会从总成绩中扣除0.5分,最多扣除20分。(这条是网上看到的,不知道对不对)
通过对phase_1,phase_2,phase_3,phase_4,phase_5,phase_6这六个函数进行disas操作以后可以发现,炸弹的爆炸行为是由explode_bomb这个函数启动的。故我们只需要在explode_bomb这个函数打上断点,如下图所示
在这里插入图片描述
之后,如果炸弹“准备爆炸”(即:程序进入explode_bomb这个函数),程序就会停下来。这时候就可以用run这个操作从头再来,而不会导致扣分。
在这里插入图片描述

拆炸弹的过程

phase_1(字符串比较)

第一关是最简单的一关。首先用 break phase_1在第一关的函数开始处打上断点,然后运行程序。随便进行一个输入
在这里插入图片描述
程序停下来后,用disas phase_1查看第一关函数的汇编代码。

在这里插入图片描述
先使用两次ni指令让程序运行到<+9>的位置。
可以看到这里程序调用了<string_not_equal>这个函数,这个函数很显然是判断两个字符串是否是相等的。%eax这个寄存器应该是存储了这个函数的返回值。
再看<+14>和<+16>的位置。如果 %eax & %eax的结果是0的话(即<string_not_equal>返回0),则跳到23行,任务完成。否则(即<string_not_equal>返回1),炸弹就会爆炸。
因此,我们发现这关是要求输入一个字符串。如果我们输入的这个字符串和炸弹中的答案一样的话,就可以拆除这一关,否则炸弹就会爆炸。
我们使用info registers指令查看当前所有的寄存器的内容。
在这里插入图片描述
可以看到 %rsi和%rdi这两个寄存器都存储了一个地址。这两个地址应该是被当做实参,传到了<string_not_equal>这个函数里。因此我们对这两个地址的内容进行查看。
在这里插入图片描述
可以看到%rdi中的地址存储的是我们的输入,而%rsi中的地址存储的就是正确答案了。
因此,本关的答案是I can see Russia from my house!

phase_2(循环)

第二关的汇编代码如下

=> 0x0000000000400f0c <+0>:	push   %rbp
   0x0000000000400f0d <+1>:	push   %rbx
   0x0000000000400f0e <+2>:	sub    $0x28,%rsp
   0x0000000000400f12 <+6>:	mov    %rsp,%rsi
   0x0000000000400f15 <+9>:	callq  0x4015bf <read_six_numbers>
   0x0000000000400f1a <+14>:	cmpl   $0x0,(%rsp)
   0x0000000000400f1e <+18>:	jns    0x400f44 <phase_2+56>
   0x0000000000400f20 <+20>:	callq  0x401589 <explode_bomb>
   0x0000000000400f25 <+25>:	jmp    0x400f44 <phase_2+56>
   0x0000000000400f27 <+27>:	mov    %ebx,%eax
   0x0000000000400f29 <+29>:	add    -0x4(%rbp),%eax
   0x0000000000400f2c <+32>:	cmp    %eax,0x0(%rbp)
   0x0000000000400f2f <+35>:	je     0x400f36 <phase_2+42>
   0x0000000000400f31 <+37>:	callq  0x401589 <explode_bomb>
   0x0000000000400f36 <+42>:	add    $0x1,%ebx
   0x0000000000400f39 <+45>:	add    $0x4,%rbp
   0x0000000000400f3d <+49>:	cmp    $0x6,%ebx
   0x0000000000400f40 <+52>:	jne    0x400f27 <phase_2+27>
   0x0000000000400f42 <+54>:	jmp    0x400f50 <phase_2+68>
   0x0000000000400f44 <+56>:	lea    0x4(%rsp),%rbp
   0x0000000000400f49 <+61>:	mov    $0x1,%ebx
   0x0000000000400f4e <+66>:	jmp    0x400f27 <phase_2+27>
   0x0000000000400f50 <+68>:	add    $0x28,%rsp
   0x0000000000400f54 <+72>:	pop    %rbx
--Type <RET> for more, q to quit, c to continue without paging--c
   0x0000000000400f55 <+73>:	pop    %rbp
   0x0000000000400f56 <+74>:	retq   
End of assembler dump.

我们可以在<+9>处看到这个程序调用了<read_six_numbers>这个函数,即读取了6个数字。因此我们可以知道第二关的输入应该是6个数字。我们这里把这六个输入的数字记为a1,a2,a3,a4,a5,a6。

使用几次ni指令使程序运行到<+14>的位置。我们可以发现,我们的a1,a2,a3
a4,a5,a6这六个数字分别存在%rsp,%rsp+0x4,%rsp+0x8,%rsp+0xc,%rsp+0x10,%rsp+0x14这六个栈上的位置中(不确定的话,可以输入几个123,456,789这样的独特数字来确定)

接下来我们看这一段代码

=> 0x0000000000400f1a <+14>:	cmpl   $0x0,(%rsp)
   0x0000000000400f1e <+18>:	jns    0x400f44 <phase_2+56>
   0x0000000000400f20 <+20>:	callq  0x401589 <explode_bomb>

第14行将我们输入的第一个数字a1与0x0进行比较,如果第一个输入a1比0小的话,炸弹就会直接爆炸!

因此,我们输入一个大于等于0的a1后,程序跳转到56行。

我们观察这一段代码,这应该是一段循环。

   0x0000000000400f27 <+27>:	mov    %ebx,%eax
   0x0000000000400f29 <+29>:	add    -0x4(%rbp),%eax
   0x0000000000400f2c <+32>:	cmp    %eax,0x0(%rbp)
   0x0000000000400f2f <+35>:	je     0x400f36 <phase_2+42>
   0x0000000000400f31 <+37>:	callq  0x401589 <explode_bomb>
   0x0000000000400f36 <+42>:	add    $0x1,%ebx
   0x0000000000400f39 <+45>:	add    
  • 4
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值