实验名称

BoomLab

实验目的

理解汇编语言,学会使用调试器

实验资源

1.BoomLab实验文件

2.可执行文件bomb和c代码bomb.c

3.解炸弹小提示.pdf

4.gdb调试器

5.objdump

实验任务

程序运行在linux环境中。程序运行中有6个关卡(6个phase),每个phase需要用户在终端上输入特定的字符或者数字才能通关,否则会引爆炸弹!那么如何才能知道输入什么内容呢?这需要你使用gdb工具反汇编出汇编代码,结合c语言文件找到每个关卡的入口函数。然后分析汇编代码,找到在每个phase程序段中,引导程序跳转到“explode_bomb”程序段的地方,并分析其成功跳转的条件,以此为突破口寻找应该在命令行输入何种字符通关。

首先使用ojbdump反汇编可执行文件bomb,生成bomb.txt

phase_1

这里我对这串代码进行了分析和注释:

这里可以发现寄存器%eax的值来源于strings_not_equal函数,可以从这里入手。而我们发现这个函数的参数来源于我们的输入,和一个奇怪地址的内容。

先启动gdb

对0x8049fdc地址的内容进行查看

这里查看strings_not_equal函数的内容

这里调用了string_length这个函数:

这个代码是用来判断长度是否相等的。

对这个代码分析可以发现,执行逻辑大致为:对于两个字符串,如果长度不等,则直接跳转,%eax为0,否则执行后续内容,判断是否相等,若相等,则%eax的值才能赋值为1,否则还是0。

这样我们就理解了%eax的值是否为0的用处。这里想要避开炸弹,就需要我们给出相同的字符串,这样就可以跳过炸弹爆炸的函数。

如图可知,输入刚刚调试出来的字符串,通过了此关。

phase_2

这里调用了read_six_numbers函数,可以查看一下

这串代码负责读取六个数字

这里还可以用gdb调试:

这里对read_six_numbers函数中立即数的位置进行调试。可以发现是读取六个数字。

关键部分的分析:

据此分析,phase的功能是读取6个数字,第一个数字要为0,第二个数字要为1,剩下的数字要等于前两个数字之和,即应该为0,1,1,2,3,5。否则就会爆炸。那么第二题的答案我们就得到了!

phase_3:

这里调试一下:

这里要读取两个数字。

对地址0x804a02c进行查看

得到跳转表:

0x804a02c: 0x42 0x8c 0x04 0x08  // 地址 0x08048c42

0x804a030: 0x05 0x8c 0x04 0x08  // 地址 0x08048c05

0x804a034: 0x0c 0x8c 0x04 0x08  // 地址 0x08048c0c

0x804a038: 0x13 0x8c 0x04 0x08  // 地址 0x08048c13

0x804a03c: 0x1a 0x8c 0x04 0x08  // 地址 0x08048c1a

0x804a040: 0x21 0x8c 0x04 0x08  // 地址 0x08048c21

0x804a044: 0x28 0x8c 0x04 0x08  // 地址 0x08048c28

0x804a048: 0x2f 0x8c 0x04 0x08  // 地址 0x08048c2f

这里给出关键部分的分析:

可以发现第一个值可以是0-7中的值,第二个值需要对应

这里我们输入2 512即可过关(答案不唯一)

phase_4:

先调试一下:

这里也是需要读取两个数字。

这里对这两个汇编代码关键注释如下:

这里可以发现我们phase_4需要两个参数,第一个参数是z,第二个参数是6,且第二个参数与func4的返回值相等,func4实现了二分查找的功能,且返回值为,当中间值小于目标时,返回2eax+1,大于目标值返回2eax,否则返回eax。

最终递归实现,那么这里为了找到目标值,我使用了一个代码:

通过运行这个代码:

我们需要返回值是6,那么根据这个代码可以发现,目标值应该是6。

接下来可以尝试一下

顺利通关。

phase_5:

关键注释如下:

这里分析可以知道,需要取出6个字符,每个字符计算偏移量后到0x804a04c后面去取字符,最终的新字符串要与目标字符串匹配。

调试信息如下:

我们自己输入的字符串,经过偏移量后取出的结果应该是flyers。

那么倒推可以知道:

字符

偏移量

f

9

l

15

y

14

e

5

r

6

s

7

这时候我们可以写个代码倒推出符合这些的字符:

我们的顺序是9,15,14,5,6,7

可以选择yonufg!

成功过关!

phase_6

对代码分析,关键注释:

这两个部分负责检查每次取出来的数字不能超过6,并且数字是唯一的。

那么就可以知道我们输入的是数字的1,2,3,4,5,6六个数字的排列情况。

这里可以发现,我们输入的数字,在链表中对应的值需要升序排列

进行调试:

这里可以得到节点存储的值

节点

1

b0

2

138

3

79

4

114

5

154

6

2da

按升序排列的顺序就是3,1,4,2,5,6

输入结果,成功!

secret_phase

通过搜索可知,调用secre_phase在phase_defused中:

先对这串代码进行分析:

这里可以先对可疑的地址调试一下

对phase_2设置断点,发现,0x804c3ccc该处的值刚好就是2,然后我又进行了多次断点设置,发现这并不是一个巧合,该处的值恰好就是对应的我们输入了多少个字符串的值,但是输错了就会爆炸,所以这里相当于就是通过几关的值。

看来是有需要输入两个数字加一个字符串的情况。

这里藏了个字符串

这两行应该就是对我们找到了隐藏关卡进行提示。

大致分析就是这样,基本可以猜测是需要我们在通过第三关或第四关时(因为这俩都是俩数字的答案)额外输入一个字符串,并且最终通过六个关卡就可以到隐藏关卡。

但是这里进一步分析:

我们在0x804c4d0需要输入一个字符串

由secret_phase部分引用的read_line,我们可以分析一下。

read_line的功能很简单,但是可以发现,每次调用其时,字符串的地址是在应该地址上发生偏移的,这个基础地址就是0x804c3e

偏移量的计算会根据0x804c3cc中的值发生变化,这里来分析一下:

第一行读取地址0x804c3cc的值,即得到通过多少关卡了,赋值给%edx。

第二行将%ebx赋值为%edx*5

第三行将%ebx左移4位,即乘上16

然后将%ebx的值加上0x804c3e0。

我们现在就可以知道0x804c4d0地址会在哪里了。

0x804c3e0 + 80n = 0x804c4d0,解出n = 3即需要通过三关,0x804c4d0存放的是第四关我们输入的字符串。所以进入隐藏关卡需要在第四关的时候多输入一个

“DrEvil”

成功进入secret_phase部分!

接下来我们跳到重要的核心部分

我们先对前面部分分析:

接下来对调用的fun7进行分析:

这里主要部分如下:

经过分析可知,这个函数也是进行一个二分查找

节点大于目标时,递归的返回值要乘2

小于目标时,返回值是乘2加1

如果等于目标,那么返回值就是0

对于secret_phase的后半部分,其实重要点就一个:

我们需要返回值是7

但是我们对于传入的参数只知道其中一个是我们输入的字符串转数字后,结果不超过1001,另一个貌似需要分析0x804c088的内容

参照里面的数字,里面的值给出了地址,值,左指针,右指针。画出func7需要的二叉查找树

这里要得到返回值是7的输入值,还是写个代码吧,测试0-1001所有数字:

运行结果如图,那么我们要输入的就是1001

成功通关!!!

总结

    1. 实验中出现的问题

【分任务列出实验过程中出现的问题】

1.最开始运行./bomb都运行不了,试了很多遍,也确认了好几次确实没少这个文件,不知道为什么运行不了。后来才知道,因为这个是32位的,而我下载的Ubuntu是64位版本的,所以运行不了。后来下载了一个插件才解决。

2.最开始对于部分汇编代码不是很熟悉,比如jne,shr还有一些操作生成的标志位,如test这些不是很熟练,去查找PPT耗费了很多时间。

3.刚开始对于gdb调试不是很熟练,需要搜索各种用法,对于查询的指令需要用什么也会纠结半天。最主要的就是体现在查看0x804c3ccc的值的时候,之前查看的都是常量,所以我之前用两个终端运行(其中一个负责用gdb调试)能够成功,但是在这里还是发生问题了,这里如果不在gdb中run(运行),结果都是0。

4.我最开始看代码的时候,会细心的把基本上所有行的意思写上去,但是后面嫌麻烦,就只写主要的注释了,有些函数调用时,看见名字就想当然认为是什么功能,导致最后在read_line这个地方卡了很久,一直找不到突破点。

    1. 心得体会

【真实感受】

1.这个实验我个人认为是设计的非常好的,既有趣味性,还能帮助我们进一步加深对汇编代码的认识。而且很能激发我的斗志,基本上开始了就很难停下来,我个人是前四关是一起搞完的,然后再继续搞了第五第六关,最后抽了时间一口气搞完了隐藏关卡。

2.这个实验不但让我们理解了汇编代码,还告诉我们要灵活使用工具,比如gdb,这个真的是帮了很大的忙,就不说有的时候有提示作用,很多时候,没有gdb根本得不到过关的答案。包括还有我们学过的c语言,对于这个实验的函数递归什么需要计算的部分,可以写个代码,简化很大的思维量。

3.上面说到了运用c语言写代码,这个实验确实还帮我们复习了很多算法设计、数据结构等知识。不光是我用代码解决问题,这个实验里面很多关卡的函数也就是设计到了这些,比如链表、二分查找、二叉树、函数递归等等。

4.这个实验总体来说是很考验耐心的,因为有些代码你没看懂,后面可能就完全不知道在干嘛了,而且相对于高级语言,汇编语言读起来的难度更大,很考验我们的专注力。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐