当前位置:首页 > 华科_计算机系统实验报告
实验2: 拆弹实验
2.1 实验概述
实验目的:增强对程序的机器级表示、汇编语言、调试器和逆向工程等方面原理与技能的掌握。
实验目标:需要拆除尽可能多的炸弹。
实验要求:使用gdb调试器和objdump来反汇编炸弹的可执行文件,并单步跟踪调试每一阶段的机器代码,从中理解每一汇编语言代码的行为或作用,进而设法“推断”出拆除炸弹所需的目标字符串。 实验语言:c。 实验环境:linux
2.2 实验内容
一个“binary bombs”(二进制炸弹,下文将简称为炸弹)是一个Linux可执行C程序,包含了6个阶段(phase1~phase6)。炸弹运行的每个阶段要求你输入一个特定的字符串,若你的输入符合程序预期的输入,该阶段的炸弹就被“拆除”,否则炸弹“爆炸”并打印输出 \字样。实验的目标是拆除尽可能多的炸弹层次。
每个炸弹阶段考察了机器级语言程序的一个不同方面,难度逐级递增: * 阶段1:字符串比较 * 阶段2:循环 * 阶段3:条件/分支 * 阶段4:递归调用和栈 * 阶段5:指针
* 阶段6:链表/指针/结构
另外还有一个隐藏阶段,但只有当你在第4阶段的解之后附加一特定字符串后才会出现。
为了完成二进制炸弹拆除任务,你需要使用gdb调试器和objdump来反汇编炸弹的可执行文件,并单步跟踪调试每一阶段的机器代码,从中理解每一汇编语言代码的行为或作用,进而设法“推断”出拆除炸弹所需的目标字符串。这可能需要你在每一阶段的开始代码前和引爆炸弹的函数前设置断点,以便于调试。
2.2.1 阶段1 字符串比较
1. 任务描述:通过phase_1的反汇编代码找出要输入的字符串。
2. 实验设计:利用gdb结合断点来动态地分析。 3. 实验过程:
观察phase_1的反汇编代码,如图2.1.1所示:
图2.1.1
发现在调用strings_not_equal对比字符串之前,有一个地址送入了堆栈,大胆猜测该地址就是正确字符串的首址,于是在phase_1处下个断点,运行至此处后,用x命令查看字符串。如图2.1.2所示:
图2.1.2
故猜测“Border relations with Canada have never been better.”就是所需字符串。重新执行该程序,直接输入该字符串,观察结果。如图2.1.3所示:
图2.1.3
4. 实验结果:如图2.1.3所示,阶段一拆弹成功!
阶段一很简单,当初的找出字符串首地址就可以了,没有什么大的难点。
2.2.2 阶段2 循环
1. 任务描述:通过phase_2的反汇编代码推断第二阶段要输入的数据 2. 实验设计:利用gdb结合断点来动态地分析 3. 实验过程:
观察phase_1的前一部分反汇编代码,如图2.2.1所示:
图2.2.1
发现输入的应该是六个数字,而且要求[esp+0x18]必须大于等于0才行,于是测试输入“0 1 2 3 4 5”,观察这些数字在调用read_six_numbers后是如何存放在栈中的,如图2.2.2所示:
图2.2.2
观察到执行read_six_numbers后,输入的数字依次存放在esp+0x18、esp+0x1c、esp+0x20、esp+0x24、esp+0x28、esp+0x2c中,故对输入的数字首先就要有第一个数不能小于0。继续观察phase_2的后一部分反汇编代码,如图2.2.3所示:
图2.2.3
能容易发现这是一个循环,首先将ebx赋值为1,然后比较[esp+ebx*4+0x14]加上ebx与[esp+ebx*4+0x18]是否相等,相等就ebx加一继续执行,直到ebx等于6后退出。
然后来分析应该输入的值。第一个数只要大于等于0就可以。
不妨就输入0。他将会被保存在esp+0x18处。所以ebx等于1时,有[esp+ebx*4+0x18]=[esp+0x1c]=[esp+ebx*4+0x14]+ebx=[esp+0x18]+1。故第二
个输入的数字应该为0+1=1。同理分析可得后面的数依次为3、6、10、15。故这六个数依次为0、1、3、6、10、15。
重新执行该程序,直接输入“0 1 3 6 10 15”,观察结果。如图2.2.4所示:
图2.2.4
4. 实验结果:如图2.2.4所示,阶段二拆弹成功!
阶段二涉及到了小的循环,慢慢的依次执行很同意就能发现规律,也不是很难。
2.2.3 阶段3 条件/分支
1. 任务描述:通过phase_3的反汇编代码推断第三阶段要输入的数据 2. 实验设计:利用gdb结合断点来动态地分析 3. 实验过程:
观察phase_3的前一部分反汇编代码,如图2.3.1所示:
图2.3.1
发现输入的应该要求__isoc99_sscanf@plt的返回值大于1,于是观察调用__isoc99_sscanf@plt时格式字符串的值,在0x8048c23处下断点然后进入函数单步调试,并测试输入“0 1 2 3 4”,如图2.3.2所示:
图2.3.2
观察到格式字符串为“%d %d”,故只需输入两个数字即可。同phase_2操作可以发现输入的数字依次存放在esp+0x18、esp+0x1c中。继续观察phase_3的
共分享92篇相关文档