简单的前言
最近的作业有个二进制炸弹问题,具体点说就是使用汇编语言完成一些小问题,形式比较有趣,一起看看吧。
题目描述
-
实验目的
通过对一个二进制可执行程序(称为“二进制炸弹”)的理解和逆向工程,加深对对程序的机器级表示、汇编语言、调试器和逆向工程等方面知识的理解和掌握。 -
实验内容
作为实验目标的二进制炸弹“binary bombs” Linux可执行程序包含了多个阶段(或关卡),在每个阶段程序要求你输入一个特定字符串,如果输入满足程序代码所定义的要求,该阶段的炸弹就被拆除了,否则程序输出“炸弹爆炸BOOM!!! ”的提示并转到下一阶段再次等待对应的输入 ——实验的目标是设法得出解除尽可能多阶段的字符串。
为完成二进制炸弹拆除任务,需要通过反汇编和理解可执行炸弹文件程序或使用gdb调试器跟踪每一阶段的机器代码,从中理解关键机器指令的行为和作用,进而设法推断拆除炸弹所需的目标字符串。 -
实验环境:Linux 32-bit,C/汇编语言
一般来说,正在看本文的你肯定装好了虚拟机,和能运行32位程序的Linux系统,好了话不多说,系好安全带,准备出发。
环境准备
- 将炸弹数据包bomblab.tar(或解压缩后的文件夹)拷贝到虚拟机目录中,并使用图形化界面或者cmd进入炸弹压缩包所在目录(不会真有人不用图形界面直接肝黑白屏的代码吧,不会吧不会吧),
学生实验数据包:bomblab.tar(随不同学号有所不同)
解压命令:tar xvf bomblab.tar
数据包中包含下面文件:
bomb:二进制可执行炸弹程序
bomb.c:bomb程序的main函数
一些工具
objdump:反汇编二进制炸弹程序,获得其中汇编指令供分析
objdump -d bomb 输出bomb程序的反汇编结果
objdump -t bomb 打印bomb程序的符号表,其中包含bomb中所有函数、全局变量的名称和存储地址
而你需要的是,按以下步骤进行
1、先解压
2、objdump -d bomb > bomb.s 获得bomb程序的反汇编结果并保存于文本文件bomb.s中供分析
好了,现在多了一个小朋友,叫bomb.s 可以直接双击打开
打开以后就是代码,看不懂没关系,接下来的日子你不得不看的懂这些优美的代码(hhh)。
打开以后先来看看,按ctrl+f进行搜索,找到第一个炸弹phase_0
·
~~~好了,本期教程到此结束,剩下的内容自己看看代码就会了~
·
·
不闹了严肃点,我们继续前进。
二进制炸弹目标程序
包含了7个阶段以及1个隐藏阶段,分别集中考察对以下二进制程序表示各方面的理解和掌握:
- 阶段0:字符串比较
阶段1:浮点表示
阶段2:循环
阶段3:条件/分支
阶段4:递归调用和栈
阶段5:指针
阶段6:链表/指针/结构
隐藏阶段:只有给本文点赞以后才会出现(作为最后一个阶段)
接下来我们采用葫芦娃救爷爷模式(一个一个解决),马上开始,没上厕所的赶快去,喝水的喝水,犯困的抽自己两下,活动活动脖子,精神点【doge】.
实验阶段0 - 字符串比较
08049465 <phase_0>:
8049465: 55 push %ebp
8049466: 89 e5 mov %esp,%ebp
8049468: 83 ec 08 sub $0x8,%esp
804946b: 83 ec 08 sub $0x8,%esp
804946e: 68 d8 b1 04 08 push $0x804b1d8
8049473: ff 75 08 pushl 0x8(%ebp)
8049476: e8 05 08 00 00 call 8049c80 <strings_not_equal>
804947b: 83 c4 10 add $0x10,%esp
804947e: 85 c0 test %eax,%eax
8049480: 74 0c je 804948e <phase_0+0x29>
8049482: e8 61 0a 00 00 call 8049ee8 <explode_bomb>
8049487: b8 00 00 00 00 mov $0x0,%eax
804948c: eb 05 jmp 8049493 <phase_0+0x2e>
804948e: b8 01 00 00 00 mov $0x1,%eax
8049493: c9 leave
8049494: c3 ret
这一题比较简单,因为课程文档里有详细讲解。简单说下吧。
- 右键打开终端,输入 gdb bomb
- 然后打断点 输入 b phase_0
- 之后执行 输入 r
如图所示
看到了前两句欢迎语句,是不是很开心呢。have a nice day 哦
以看到,第11行代码会调用 <explode_bomb> ,也就是引爆炸弹,这不是我们所想要的,因此我们要避免程序运行到这一行。观察程序的结构,程序在第8行调用 strings_not_equal ,比较了 %eax和 %eax中的内容,而在这之前,程序push了 $0x804b1d8处的数据移动寄存器中,并可以猜到,地址$0x804b1d8处的数据是程序内置的正确答案,正是我们输入的字符串。
所以现在的问题是:如何获取地址$0x804b1d8处的数据内容?为此,我们需要运行程序,并且在合适的位置停下,这样你就可以查看答案了。
所以这么操作:
先随便输入几个字符,然后回车,
程序停在了断点处,然后用x/s 地址
(温馨小贴士,亲这边建议您右键单击复制粘贴呢哦,终端里不能ctrl+CV呢哦)
回车,出现了一串字符,为答案,复制保存即可。
先创建个文件保存答案
- 方法:输入
gedit 文件名字
,就可以创建成功啦。
继续。
重新打开终端,验证一下。
这次断点打在phase_1 别忘了。
还有那个运行改成r code 就可以直接运行读入文本里的答案了。
仔细点慢慢来。
欢迎语句下多了一行文字,大概意思就是答案正确,你好棒棒。
go on
实验阶段1 - 浮点表示
好了,经过第0个题,我们已经熟悉了很多,接着看看。
因为时间问题。不写太详细了,只写一下最快速的解题方法。而且对于汇编语言这一块,笔者水平确实有限,刚好能做题,具体知识原理还在摸爬滚打,如感觉光解题不讲知识点没营养,点个赞就可以关闭本文章了【坏笑】。
第1题代码
08049495 <phase_1>:
8049495: 55 push %ebp
8049496: 89 e5 mov %esp,%ebp
8049498: 83 ec 18 sub $0x18,%esp
804949b: c7 45 f4 9b 3a c7 17 movl $0x17c73a9b,-0xc(%ebp)
80494a2: db 45 f4 fildl -0xc(%ebp)
80494a5: d9 5d f0 fstps -0x10(%ebp)
80494a8: 8d 45 e8 lea -0x18(%ebp),%eax
80494ab: 50 push %eax
80494ac: 8d 45 ec lea -0x14(%ebp),%eax
80494af: 50 push %eax
80494b0: 68 ff b1 04 08 push $0x804b1ff
80494b5: ff 75 08 pushl 0x8(%ebp)
80494b8: e8 13 fc ff ff call 80490d0 <__isoc99_sscanf@plt>
80494bd: 83 c4 10 add $0x10,%esp
80494c0: 83 f8 02 cmp $0x2,%eax
80494c3: 74 0c je 80494d1 <phase_1+0x3c>
80494c5: e8 1e 0a 00