深入理解计算机系统 CSAPP 实验lab:Bomb Lab

实验资源下载地址:csapp.cs.cmu.edu/3e/labs.html 请先查看writeup

解压后

当我们运行bomb时,发现该程序要求我们输入行,如果输入错误,程序就会返回BOOM!!!提示我们失败了.

所以我们的目标是输入正确的行.以解开bomb程序.

实验前先详细阅读bomb.c

 bomb文件是一个bomb.c编译后的程序,我们由于缺失一些头文件,所以无法编译bomb.c

让我们反编译bomb,以理清程序的具体实现,从而分析出我们要输入的行:

objdump -d bomb > bomb.txt
 phase_1:

 

我们可以看到在call strings_not_equal之前传入了一个参数 0x402400我们不知道这是什么,接着看.

 

call strings_not_equal之后 传入的%esi和%rsi是同一个寄存器,所以参数 0x402400被传到%rbp了,下面我们又看到有(%rbp)的指令很明显了,加载了0x402400,也就是0x402400是一个地址,此时我们希望在运行bomb的时候看一下0x402400地址上是什么东西.这里自然就想到书中和实验网页writeup中提到的gdb调试器了.

gdb bomb

 加个断点,只需要断在%esi接收到参数0x402400之后即可

(gdb)b strings_not_equal

运行:

(gdb)run

以字符串形式输出地址上的数据:

(gdb)x/s 0x402400

关于gdb的命令,自己在网上查着,每个用一用就会了.

不查不知道一查吓一跳,原来是个字符串啊.我们再联想一下这个函数的名字strings_not_equal.不难猜到这是一个比较字符串的函数.我们把查到的字符串保存在a.txt文件中,然后传入bomb,这里先按ctrl+d退出gdb在运行bomb方便一些.

./bomb a.txt

解开阶段一. 

phase_2: 

gdb命令查看寄存器的值:

(gdb)i r

我们先在phase_2中打个断点然后一步步调试.

你看到phase_2里面有一个函数是read_six_numbers ,你就先随便数六个数进去,然后运行起来观察.想想scanf是如何读取六个数的哦?

第一步 它1和你输入的第一个数相比,相等就跳到0x400f30

第二步 加载你输入的第二个数的地址到%rbx

第三步 读取第二步的地址减去4字节后的值到%eax 双倍%eax后和第二步的值比较

这三步是进入首次循环.每次循环对比%rbx和%rbx-4(上一个数)俩地址的值后 给%rbx+4(下一个数)

蓝色框表明的是循环中每次都给%rbx+4,直到%rbx到达%rbp后结束.

用人话说就是,你输入六个数,它先用1和你输入的第一个数相比,然后每次检查下一个数是不是上一个数的两倍.

所以答案是1 2 4 8 16 32这六个咯

其实这个不难,但是要你静下心来慢慢看,慢慢来就是最快的~Keep going!

phase_3:

前面的指令提示了phase_3是接收两个整数.

我们试着将1输入,发现蓝色框计算间接跳转后,直接跳到到了下方的0x400fb9,然后用下一个数去和311比较.我们很自然的猜到第二个数填311就对了.重新运行输入1 311后炸弹就解开了.此时我们很疑惑的是为什么会这样?
于是,我们直接一个个试.因为ja指令是无符号比较小于7,所以我们把断点打在 400f75 跳转语句上.分别输入0-7,然后stepi到下一步,看它们分别跳转到哪里.

(gdb)break * 0x400f75
(gdb)stepi

0 207

1 311

2 707

 3 256

4 389

 5 206

6 682

7 327

这么一看哦,不是按顺序跳转的.很像是一个switch case哦,那我们回想一下,switch case是不是一个跳转表啊?跳转表的话是不是有个首地址?于是乎我们来猜一猜哪个是首地址?

(gdb)x/x 0x422470

哦,真相大白了,原来这就是个首地址0x400f7c加你输入的一个数偏移然后执行对应指令.
所以答案是:

0 207
1 311
2 707
3 256
4 389
5 206
6 682
7 327
这七个里面其中一个都可以.

Halfway there!继续加油!

phase_4:

此处表明第二个数必须是0,第一个数必须小于等于14.

我们输入的第一个数进入func4之后,%edx寄存器一开始都是14.

请注意红色框的两个比较指令.一个小于等于,一个大于等于.两个条件都符合.就是说%edi==%ecx的时候才会结束循环.

绿色框表示%ecx值得变化.从14除以2后比较,如果一直不符合条件就减去1,进入下一次循环后又除以2,直到等于0.

第一个比较条件决定是否继续往下除.

第二个比较条件决定输入的数和商是否相等

14/2=7 , 7<=%edi不符合才继续,否则判断7>=%edi

(7-1)/2=3 , 3<=%edi不符合才继续,否则判断3>=%edi

(3-1)/2=1 , 1<=%edi不符合才继续,否则判断3>=%edi

(1-1)/2=0 , 0<=%edi不符合返回1.func4返回1会爆炸

所以答案以下其中一个都可以

7 0
3 0
1 0
0 0

phase_5:

蓝色框:知道需要六个字符.

绿色框代表每次处理一个字符

红色框是个常量打印出来看看.

一开始我们一个字符一个字符打印,看着很正常.发现,哦?这是个字符串啊一个接着一个啊.

然后我们用/s整个字符串输出.哇靠怎么已打印字符串就显示ctrl-c提示的终结程序了?

我没按ctrl+c啊,程序怎么结束了?????

试了几遍之后发现.

原来0x4024b0 这个字符串就是

"maduiersnfotvbylSo you think you can stop the bomb with ctrl-c, do you?"

目的是为了干扰我们. 

0x4024b0加上每个我们输入的字符的低四位后产生的字符串与目标的0x40245e的"flyers"传入strings_not_equal,一样就解开炸弹.

原字符串:"maduiersnfotvbylSo you think you can stop the bomb with ctrl-c, do you?"

偏移量:

   i&0xf=9

   o&0xf=F

   n&0xf=E

     u&0xf=5

   v&0xf=6

      g&0xf=7

目标字符:"flyers"

原字符+偏移量=目标字符

如:'m'+9='f'

答案是:

ionuvg

答案并不是唯一的,只要字符的低四位符合对应的偏移量即可.由于数量比较多就不一一列出来了.

phase_6:

phase_6又是读取六个数.

2024.8.10.今天是七夕哦,答案已经做出来了用了五天,哈哈,明天再更新吧.

输入的六个数减去1后都要小于等于5不然就爆炸,是无符号比较.

输入的六个数相邻的不可以相等

7减去每一个数的结果 放到栈上,这应该是由于栈是后进先出,所以偏移量刚好是差值.

打断点到0x4011ba

(gdb)b * 0x4011ba

不同的输入顺序不同的运行结果:

phase_6是根据我们输入的数,把数组0x6032d0数组的元素按我们数的顺序放到栈中,再从栈中读到寄存器进行比对.

比对时,(%rbx)比%eax,就是前一个数比后一个数要大不然就爆炸.

0x6032f09244
0x6033006913
0x6033104772
0x6033204431
0x6032e01685
0x6032d03326

所以最终顺序是:4 3 2 1 5 6

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值