华中科技大学计算机系统基础二进制炸弹bomb拆弹实验报告.docx
- 文档编号:8970671
- 上传时间:2023-05-16
- 格式:DOCX
- 页数:26
- 大小:3.34MB
华中科技大学计算机系统基础二进制炸弹bomb拆弹实验报告.docx
《华中科技大学计算机系统基础二进制炸弹bomb拆弹实验报告.docx》由会员分享,可在线阅读,更多相关《华中科技大学计算机系统基础二进制炸弹bomb拆弹实验报告.docx(26页珍藏版)》请在冰点文库上搜索。
课程实验报告
课程名称:
计算机系统基础
专业班级:
计算机科学与技术CS1502
学号:
U201414596
姓名:
卢振兴
指导教师:
王多强
报告日期:
2017年6月7日
计算机科学与技术学院
1.实验简介
本实验中,你要使用课程所学知识拆除一个“binarybombs”来增强对程序的机器级表示、汇编语言、调试器和逆向工程等方面原理与技能的掌握。
一个“binarybombs”(二进制炸弹,下文将简称为炸弹)是一个Linux可执行C程序,包含了6个阶段(phase1~phase6)。
炸弹运行的每个阶段要求你输入一个特定的字符串,若你的输入符合程序预期的输入,该阶段的炸弹就被“拆除”,否则炸弹“爆炸”并打印输出"BOOM!
!
!
"字样。
实验的目标是拆除尽可能多的炸弹层次。
每个炸弹阶段考察了机器级语言程序的一个不同方面,难度逐级递增:
*阶段1:
字符串比较
*阶段2:
循环
*阶段3:
条件/分支
*阶段4:
递归调用和栈
*阶段5:
指针
*阶段6:
链表/指针/结构
另外还有一个隐藏阶段,但只有当你在第4阶段的解之后附加一特定字符串后才会出现。
为了完成二进制炸弹拆除任务,你需要使用gdb调试器和objdump来反汇编炸弹的可执行文件,并单步跟踪调试每一阶段的机器代码,从中理解每一汇编语言代码的行为或作用,进而设法“推断”出拆除炸弹所需的目标字符串。
这可能需要你在每一阶段的开始代码前和引爆炸弹的函数前设置断点,以便于调试。
实验语言:
C语言
实验环境:
linux
2.实验文件
本次实验中,每位同学会得到一个不同的binarybomb二进制可执行程序及其相关文件,其中包含如下文件:
lbomb:
bomb的可执行程序。
lbomb.c:
bomb程序的main函数。
运行./bomb:
./bomb是一个可执行程序,需要0或1个命令行参数(详见bomb.c源文件中的main()函数)。
如果运行时不指定参数,则该程序打印出欢迎信息后,期待你按行输入每一阶段用来拆除炸弹的字符串,并根据你当前输入的字符串决定你是通过相应阶段还是炸弹爆炸导致任务失败。
你也可将拆除每一阶段炸弹的字符串按行组织在一个文本文件中(比如:
result.txt),然后作为运行程序时的唯一一个命令行参数传给程序(./bombresult.txt),程序会自动读取文本文件中的字符串,并依次检查对应每一阶段的字符串来决定炸弹拆除成败。
3.实验内容
3.1观察整体结构
3.1.1任务描述
了解炸弹程序的整体框架,以备随后的破解。
3.1.2实验过程
1.观察主程序中程序的流程,发现程序是在初始化炸弹后,依次从命令行获取输入语句(input=read_line()),并将输入的语句存入对应关卡的子程序(如phase_1(input))。
如图1.1所示。
图1.1炸弹的主程序
2.用objdump–dbomb>disassemble.txt语句获得反汇编的代码,在反汇编代码中找到phase_X()函数开始炸弹的拆除工作。
3.2字符串比较
3.2.1任务描述
找到与输入字符串相比较的字符串的首地址,将其打印出来,得到结果。
3.2.2实验过程
1.在反汇编代码中,找到phase_1()的位置。
如图2.1所示。
图2.1phase_1()函数
2.从主程序main中得知,read_line函数所读取的内容将会被存放在EAX中,如图2.2所示。
图2.2read_line函数读取的内容存入EAX
3.观察得到用户用于比较的字符串的存储地址为0x804a3a4。
如图1.4所示。
图2.3字符串的存储地址
4.用gdbx/2s查看该字符串的内容,得到字符串为:
Therearerumorsontheinternets.如图1.5所示。
图2.4字符串结果
3.2.3实验结果
向炸弹中输入上述所得字符串,发现成功通过,如图2.5所示。
图2.5成功拆除炸弹1
3.3循环
3.3.1任务描述
根据汇编代码中的循环规律,推导出相应的字符串,拆除炸弹2。
3.3.2实验过程
1.找到phase_2代码,如图3.1所示。
图3.1炸弹2的流程图
2.根据read_six_numbers函数可知,输入的是6个数字。
如图3.2所示。
图3.2read_six_numbers
3.根据两次比较可知,第一个数字是0,第二个数字是1。
如图3.3所示。
图3.3两次比较
4.找到程序循环的位置,观察跳转的方式,如图3.4所示。
图3.4程序的跳转方式
5.在语句中发现,后面的数字必须和它之前的两个数字的和相等,如图3.5所示。
图3.5后方数字必须和前两个数字的和相等,否则爆炸
6.由此可推导出,输入的数字应为斐波那契数列的前六位,即011235。
3.2.3实验结果
向炸弹二中输入上述所得数列,发现成功通过,如图3.6所示。
图3.6拆除第二个炸弹
3.4条件/分支
3.4.1任务描述
根据条件分支的规律,推导出Switch参数表中的一项内容,从而拆除炸弹。
3.4.2实验过程
1.找到phase_3中开始部分的代码。
如图4.1所示。
图4.1phase_3开始部分代码
2.根据$0x804a3ee,0x4(%esp)一句,使用gcdx/2s,输出内容如图4.2所示。
由此可知,输入内容应为一个数字+一个字符+一个数字。
图4.2输入内容格式
3.cmpl$0x7,0x28(%esp); ja8048d43
4.根据参数1可得到跳转地址的向量表,如图4.3所示。
图4.3跳转地址
5.可以发现,当输入为0时,跳转的地址为0x8048c59。
6.由语句:
cmpl$0x2bb,0x2c(%esp)可知,第三个参数的值为0x2bb,转化成10进制为699。
7.由语句:
mov$0x65,%eax;cmp0x27(%esp),%al可知,第二个参数的值为z。
8.因此,炸弹3的一组解为0z699。
3.4.3实验结果
向炸弹三中输入0z699,成功拆弹,如图4.4所示。
图4.4炸弹三拆弹成功
3.5递归
3.5.1任务描述
通过找到反汇编程序中的递归规律,确定输入的参数,从而破解炸弹。
3.5.2实验过程
1.观察主流程,发现①程序首先读取参数,参数个数不为2则引爆;②将第一个参数与e(14)比较,大于14则引爆;③将14、0和第一个参数传入func4函数;④func4的返回参数若不是0则引爆。
⑤第二个参数若不为0则引爆。
如图5.1所示。
图5.1炸弹4主程序及相关注释
2.由此可知;输入的参数为两个;第一个参数不大于14,第二个参数等于0。
3.用gdb查看0x804a631处的内容,发现输入的参数为两个数字。
如图5.2所示。
图5.2输入参数
3.观察func函数,用C语言编写相应的代码段。
#include
#include
#include
intfunc(into,intp,intq);
intmain()
{
inta;
inti;
for(i=0;i<15;i++)
{
a=func(i,0,14);
printf("输入%d->func输出%d\n",i,a);
}
return0;
}
intfunc(into,intp,intq)
{
intdx,ax,bx,cx,si;
dx=o;
ax=p;
bx=q;
cx=bx;
cx=cx-ax;
si=cx;
si=si>>0x1f;
cx+=si;
cx=cx>>1;
cx=cx+ax;
if(cx<=dx)
{
ax=0;
if(cx>=dx)
{
gotoend;
}else{
cx++;
func(dx,cx,bx);
ax=ax+ax+1;
}
}else{
cx--;
func(dx,ax,cx);
ax=ax+ax;
}
end:
returnax;
}
4.当输入参数为7的时候,输出为0,如图5.3所示。
图5.3输入7输出0
5.由此可得,拆弹密钥为70。
3.5.3实验结果
向炸弹3中输入70,拆弹成功,如图5.4所示。
图5.4炸弹4拆弹成功
3.6指针
3.6.1任务描述
根据指针所指向的相关地址,分析出最终的拆弹密码。
3.6.2实验过程
1.观察主程序如图6.1所示,发现①输入的参数至少为2个;②第一个参数不能为15;③数组存放在0x804a420的数组中;④ecx是对数组中取出的数值进行的累加,累加直到eax取到15。
⑤第二个参数值与ecx最终获得的累加值相等。
⑥最终循环次数为15次。
图6.1炸弹5主程序
3.在gdb中观察地址0x804a420中的内容,发现内容正好为一个数组,如图6.2所示。
图6.2数组内容
4.编写一个C语言程序,确定累加结果。
C语言程序如下
intmain()
{
inta[16]={10,2,14,7,8,12,15,11,0,4,1,13,3,9,6,5};
inti;
intcurrent;
intsum=0;
inttimes;
for(i=0;i<15;i++)
{
current=i;
times=0;
sum=0;
while(current!
=15)
{
times++;
sum+=a[current];
current=a[current];
}
if(times==15)
{
printf("当初始下标为%d时,循环15次,此时累加和为:
%d\n",i,sum);
}
}
return0;
}
5.运行发现,当初始下标为5时,循环15次,此时累加和为:
115。
如图6.3所示。
即炸弹密码应为5115
图6.3累加结果
3.6.3实验结果
向第五个炸弹输入5115,成功拆弹。
如图6.4所示。
图6.4第五个炸弹拆弹成功
3.7链表/指针/结构
3.7.1任务描述
运用链表和指针相关知识拆除炸弹。
3.7.2实验过程
1.观察主流程,如图7.1所示,发现程序在开始是按以下几个步骤进行的:
①读取6个数字;②大循环要求:
读入的数字都需要小于6,否则爆炸。
③循环2要求读入的数字后一个与前一个不能相等,否则爆炸。
图7.1炸弹6的开始部分
2.因知道输入的参数是6个数字,并且都要求小于等于6,而且互补相等。
可知这6个数字分别为1、2、3、4、5、6。
3.如图7.2,第二个循环会根据输入的参数寻找相应的索引结点,索引的初始地址为0x804c154,随后的地址是在上一个地址的基础上加8,再取地址。
图7.2根据输入的参数寻找相应的索引地址
4.用gdb对bomb程序进行调试,在调试过程中可以得到相应地址对应的结点数据。
如图7.3所示。
图7.3相应地址对应的结点数据
6.循环3是给相应的结点赋地址与赋值,并将结点串联起来。
循环4在判断后一个节点的值是否大于等于前一个节点。
如图7.4所示。
图7.4循环3和循环4
7.通过刚才的查表可知,各个节点的数据依次为0x12f,0x118,0x216,0x17a,0x20e,0x137。
8.给各个节点进行由小到大的排序,可以得到0x12f
(2),0x118
(1),0x216(6),0x17a(4),0x20e(5),0x137(3)。
9.因此,第六个炸弹的拆弹密码为:
216453。
3.7.3实验结果
向第六个炸弹中输入216453,发现拆弹成功;至此炸弹1-6全部拆弹完成。
如图7.5所示。
图7.5炸弹1-6拆弹成功
3.8隐藏炸弹
3.8.1任务描述
找出隐藏的炸弹,并通过分析炸弹内容将其拆解。
3.8.2实验过程
1.第六关拆除后,在反汇编语言中发现其后还存在一个secret_phase,如图8.1所示。
但在程序正常运行时,并未出现这关。
说明该隐藏关卡需要特殊的方法调出。
图8.1隐藏关卡
3.检索整个汇编代码,发现只有phase_defused中调用过secret_phase。
如图8.2所示。
图8.2phase_defused中出现secret_phase
4.从phase_defused中可以看到call8048860<__isoc99_sscanf@plt>;cmp$0x3,%eax,这两句。
说明只有在输入的参数为3个的时候才会调用secret_phase函数。
在第三、四个炸弹中都用到了sscanf函数,其中第三个炸弹已经有了3个参数。
因此,隐藏炸弹需要在第四个关卡中寻找。
5.通过gdb查找0x804a68b的内容,发现需要输入的内容为“%d%d%s”。
如图8.3所示。
图8.3需要输入的内容
6.程序调用了strings_not_equal函数来比较字符串;因此,可以通过0x804a694来找到相应的串,发现该串为DrEvil。
如图8.4所示。
图8.4DrEvil进入串
7.在第四关的答案后再出入DrEvil,成功找出隐藏关卡。
如图8.5所示。
图8.5成功打开隐藏关卡
8.观察secret_phase的主函数,如图8.6所示,函数的流程如下:
①首先读取一行字符串
②调用strtol函数将字符串转换成长整数。
由0xa可知,输入的字符串将被转换成十进制长整数赋值给eax。
③将eax自减1,并与1000相互比较,大于1000时爆炸。
说明eax的值在1-1001之间。
④将eax作为参数2,$0x804c0a0的值作为参数1传入func7。
⑤返回值需要为1,否则爆炸。
图8.6secret_phase主函数
9.观察fun7,如图8.7所示,发现这是一个递归函数。
其流程可由如下C语言表示。
intfunc7(int*dx,intcx)
{
if(*dx==0)return-1;
intax=0;
if(((*dx-cx)==0))
return0;
elseif((*dx) { ax=func7((dx->right),cx); ax=ax*2+1; } else { ax=func7((dx->left),cx); ax=ax+ax; } returnax; } 图8.7func7函数 10.通过查看内存,得知$0x804c0a0是一个二叉树的表头。 通过查看内存,得知该二叉树中的数值如8.8所示。 图8.8二叉树数值 11.由于返回的eax=1。 1=2*0+1。 因此,输入的参数二与0x32相等。 转化为10进制数即为50。 3.8.3实验结果 至此,所有炸弹的破解密码都已解出。 输入相应的代码,成功地通关。 如图8.9所示。 图8.9成功破解所有密码 4.实验小结 在本次实验中,实验者通过反汇编的文件成功地破解了7个炸弹,包括6个普通炸弹和1个隐藏炸弹。 在炸弹1中,实验者通过查询内存地址中的字符串成功地实现了破解。 在炸弹2中,实验者通过观察程序的循环,成功推导出密码是第一个参数为0的6位斐波那契数列。 在炸弹3中,实验者通过观察传给sscanf的参数了解了输入密码的格式(%d%s%d),并通过判断switch的分支内容破解出了一组解。 在炸弹4中,实验者根据反汇编语言编写了C语言的递归代码;通过用C语言的计算,实现了密码的破解。 在炸弹5中,实验者通过查看内存找出了实验所用到的数;通过编写C语言代码进行累加,得到了破解所需的结果。 在炸弹6中,实验者把握了程序的3大循环,找出了程序生成的链表。 通过对链表的检索,得到了链表所指向的内存值。 通过对这些内存值的排序,得到了最终的排序答案。 根据函数调用的规律,实验者发现了secret_phase的开启密码在实验4中。 通过查看内存得知,开启密码为DrEvil。 在secret_phase中,实验者对其中的二叉树进行了分析,从内存中找到了二叉树的各个值。 通过对递归的推导,最终得到了相应的密码。 经过本次实验,实验者对程序的机器级表示、汇编语言、gdb调试器和逆向工程有了更深的理解。 这种理解加深了实验者对计算机系统的认识;这为后续学习更深入的计算机系统知识打下了基础。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 华中科技大学 计算机系统 基础 二进制 炸弹 bomb 实验 报告