实验2: Binary Bombs
2.1 实验概述
本实验中,你要使用课程所学知识拆除一个“binary bombs”来增强对程序的机器级表示、汇编语言、调试器和逆向工程等方面原理与技能的掌握。
一个“binary bombs”(二进制炸弹,下文将简称为炸弹)是一个Linux可执行C程序,包含了6个阶段(phase1~phase6)。炸弹运行的每个阶段要求你输入一个特定的字符串,若你的输入符合程序预期的输入,该阶段的炸弹就被“拆除”,否则炸弹“爆炸”并打印输出\字样。实验的目标是拆除尽可能多的炸弹层次。
每个炸弹阶段考察了机器级语言程序的一个不同方面,难度逐级递增:
* 阶段1:字符串比较 * 阶段2:循环 * 阶段3:条件/分支 * 阶段4:递归调用和栈 * 阶段5:指针
* 阶段6:链表/指针/结构
另外还有一个隐藏阶段,但只有当你在第4阶段的解之后附加一特定字符串后才会出现。
为了完成二进制炸弹拆除任务,你需要使用gdb调试器和objdump来反汇编炸弹的可执行文件,并单步跟踪调试每一阶段的机器代码,从中理解每一汇编语言代码的行为或作用,进而设法“推断”出拆除炸弹所需的目标字符串。这可能需要你在每一阶段的开始代码前和引爆炸弹的函数前设置断点,以便于调试。
实验语言:C语言 实验环境:linux
2.2 实验内容
反汇编bomb,得到汇编代码,根据汇编代码完成拆炸弹任务。
9
2.2.1 阶段1 字符串比较
1.任务描述:找到与输入的字符串进行比较的存储的字符串的首地址,进而得到存储的字符串,得到结果。
2.实验设计:根据反汇编代码一步一步分析,具体见实验过程。 3.实验过程:
将bomb反汇编输出到asm.txt文件中,在反汇编代码中查找phase_1的位置:
从上面的语句可以看出
得知êx里存储的是调用read_line()函数后返回的结果,就是输入的字符串,所以得知和用户输入字符串比较的字符串的存储地址为0x804a204,可用gdb查看这个地址存储的数据内容:
10
翻译过后的结果为The future will be better tomorrow. 4.实验结果:
可见结果正确。
2.2.2 阶段2 循环
1.任务描述:完成炸弹2的拆除
2.实验设计:观察分析phase_2代码,使用gdb调试分析结果 3.实验过程:找到phase_2代码:
11
由read_six_numbers知是要输入6个数字,观察:
可知输入的第一个和第二个必须依次为0,1
观察这两个循环可知只有当输入的数为前两个数之和时才不会bomb,故得到序列0,1,1,2,3,5
4.实验结果:输入上述序列后得:
12
可知结果正确。
2.2.3 阶段3 条件/分支 1.任务描述:完成炸弹3的拆除
2.实验设计:观察分析phase_3代码,使用gdb调试分析结果 3.实验过程:找到phase_3代码如下:
08048c0a
83 ec 3c sub $0x3c,%esp 8d 44 24 2c lea 0x2c(%esp),êx 89 44 24 10 mov êx,0x10(%esp) 8d 44 24 27 lea 0x27(%esp),êx 89 44 24 0c mov êx,0xc(%esp) 8d 44 24 28 lea 0x28(%esp),êx 89 44 24 08 mov êx,0x8(%esp) c7 44 24 04 4e a2 04 movl $0x804a24e,0x4(%esp)
由此行代码查看输入内容:
可知输入的依次是数字、字符、数字
8048c43: 8048c48: … 8048d43:
83 7c 24 28 07 cmpl $0x7,0x28(%esp) 0f 87 f5 00 00 00 ja 8048d43
e8 8d 04 00 00 call 80491d5
13