湖南大学计算机组成原理实验实验3bomblab.pdf
《湖南大学计算机组成原理实验实验3bomblab.pdf》由会员分享,可在线阅读,更多相关《湖南大学计算机组成原理实验实验3bomblab.pdf(26页珍藏版)》请在冰豆网上搜索。
![湖南大学计算机组成原理实验实验3bomblab.pdf](https://file1.bdocx.com/fileroot1/2022-10/9/417f4cb4-d357-4ef5-9a6c-7328e2931686/417f4cb4-d357-4ef5-9a6c-7328e29316861.gif)
课程实验报告课程名称:
计算机组成与结构实验项目名称:
bomblab专业班级:
姓名:
学号:
指导教师:
完成时间:
2016年4月20日信息科学与工程学院实验题目:
bomblab实验目的:
程序运行在linux环境中。
程序运行中有6个关卡(6个phase),每个phase需要用户在终端上输入特定的字符或者数字才能通关,否则会引爆炸弹!
那么如何才能知道输入什么内容呢?
这需要你使用gdb工具反汇编出汇编代码,结合c语言文件找到每个关卡的入口函数。
然后分析汇编代码,找到在每个phase程序段中,引导程序跳转到“explode_bomb”程序段的地方,并分析其成功跳转的条件,以此为突破口寻找应该在命令行输入何种字符通关。
实验环境:
ubuntu14.04虚拟机、gdb工具实验内容及操作步骤:
首先打开bomb.c文件,发现这个文件里只有主函数,没有具体的代码,所以我们要通过反汇编得到6关的具体代码。
反汇编有两个具体的方法:
第一种:
objdump-dbomb1.txt将反汇编结果输出到1.txt中第二种:
使用gdb调试bomb,命令为(gdb)disasfunc_name,其中func_name对应于本次实验中的六个函数phase_16,再将结果复制到word中。
我采用第二种方法得到反汇编代码,下面对六个bomb进行分析、得到我们拆炸弹所需的密码。
Phase_1内容如下0x08048f61:
push%ebp0x08048f62:
mov%esp,%ebp0x08048f64:
sub$0x18,%esp这里对esp-240x08048f67:
movl$0x804a15c,0x4(%esp)这是将$0x804a15c处的值存入esp+4中0x08048f6f:
mov0x8(%ebp),%eaxebp+8就是从调用函数处取出第一个参数,放到eax寄存器中0x08048f72:
mov%eax,(%esp)将eax的值传给esp0x08048f75:
call0x8048fab此处是入口函数的地址0x8048fab,该函数要调用的参数为esp+4(即$0x804a15c处的值),和ebp+8(即我们输入的值)该函数的作用是:
判断字符串是否相等考虑一个函数的返回值要存在eax中,则以下的eax已经发生改变,是判断字符串是否相等的结果0x08048f7a:
test%eax,%eax0x08048f7c:
je0x8048f830x08048f7e:
call0x80490d1以上三句,如果eax不为0,则引爆炸弹,如果eax为0,则跳转到leave语句函数结束。
说明eax为0时,可以进入下一关0x08048f83:
leave0x08048f84:
ret解题过程:
本题的栈帧结构如下:
根据以上分析,我们发现,从键盘输入一个值,放到(新)ebp+8中,接着函数进行调用,把他传到esp中,接着,函数再从$0x804a15c这个地址取值,放到esp+8中,接着,程序对这两个参数进行函数调用,调用判断字符串是否相等的程序stringnotequal进行判断,如果二者相等,则返回值为0,不引爆炸弹,反之,只要二者不相等,则炸弹爆炸。
分析结论:
此处的密码存在地址$0x804a15c中,我们只要查看该地址的值,即可完成该题。
打开gdb调试,运行x/s0x804a15c,查看该处的值故第一题的答案为WehavetostandwithourNorthKoreanallies.Phase_2内容如下:
0x08048d6a:
push%ebp0x08048d6b:
mov%esp,%ebp0x08048d6d:
push%esi0x08048d6e:
push%ebx这是两个调用者保存寄存器,因为接下来的循环中使用到了这两个寄存器的值,所以要进行压栈保存。
0x08048d6f:
sub$0x30,%espesp-480x08048d72:
lea-0x20(%ebp),%eax0x08048d75:
mov%eax,0x4(%esp)以上两句把ebp-32处的地址传给esp+4处0x08048d79:
mov0x8(%ebp),%eax0x08048d7c:
mov%eax,(%esp)以上两句把ebp+8处的值传给esp0x08048d7f:
call0x804910b根据函数名观察,要读取6个数,所以这题要输入六个数字0x08048d84:
cmpl$0x0,-0x20(%ebp)0x08048d88:
jne0x8048d90跳转的地址是引爆炸弹,不相等就引爆,所以ebp-32处的值要等于00x08048d8a:
cmpl$0x1,-0x1c(%ebp)0x08048d8e:
je0x8048d950x08048d90:
call0x80490d1如果相等就继续,不相等就爆炸,所以ebp-28处的值要为10x08048d95:
lea-0x18(%ebp),%ebxebp-24传给ebx0x08048d98:
lea-0x8(%ebp),%esiebp-8传给esi以上两句是数据初始化,ebp-24是第三个数据的地址,ebp-8是“第七个”数据的地址,这个esi设置成ebp-8的地址是用作判断的。
接下来是一个循环计算的过程,具体的过程我在后续的解题思路里做了讲解。
0x08048d9b:
mov-0x4(%ebx),%eax0x08048d9e:
add-0x8(%ebx),%eax0x08048da1:
cmp%eax,(%ebx)0x08048da3:
je0x8048daa0x08048da5:
call0x80490d1不相等就引爆,所以此处分析得ebx要与eax的值相等0x08048daa:
add$0x4,%ebxebx+=40x08048dad:
cmp%esi,%ebx0x08048daf:
jne0x8048d9b0x08048db1:
add$0x30,%esp0x08048db4:
pop%ebx0x08048db5:
pop%esi0x08048db6:
pop%ebp0x08048db7:
ret解题过程:
本题具体思路都已标注说明,下面仅对循环体内容的第一次循环作简要说明。
从0x08048d9b:
mov-0x4(%ebx),%eax此处开始,原来ebx所存的地址为ebp-24,这里将ebx-4,即ebp-28处的值,也就是1,赋给了eax0x08048d9e:
add-0x8(%ebx),%eax这里将ebx-8,也就是ebp-32处的值,也就是0,和eax作add操作,这部得出的结果是:
eax=1+0=10x08048da1:
cmp%eax,(%ebx)0x08048da3:
je0x8048daa0x08048da5:
call0x80490d1不相等就引爆,所以此处分析得ebx要与eax的值相等,而此时的ebx是什么呢?
就是ebp-24,即第三个数,说明第三个数是前两数之和0x08048daa:
add$0x4,%ebx0x08048dad:
cmp%esi,%ebx0x08048daf:
jne0x8048d9b以上三句,如果我们输入的值满足条件,那么ebx上移4位继续循环,也就是继续求前两个数之和赋给第三个数。
0x08048db1:
add$0x30,%esp如果ebx存的值(我们要求6个数,所以最多到ebp-12)和esi存的值(ebp-8,第七个数)相等的话函数结束了做到这里应该也明白了,其实就是一个斐波那契数列前六项。
所以这题的答案为011235另附本题栈帧结构如下:
Phase_3内容如下:
0x08048ea1:
push%ebp0x08048ea2:
mov%esp,%ebp0x08048ea4:
sub$0x28,%espesp-400x08048ea7:
lea-0x10(%ebp),%eax0x08048eaa:
mov%eax,0xc(%esp)ebp-16处地址赋给esp+120x08048eae:
lea-0xc(%ebp),%eax0x08048eb1:
mov%eax,0x8(%esp)ebp-12处地址赋给esp+80x08048eb5:
movl$0x804a23e,0x4(%esp)这个地址的值可查,查出来之后发现是:
%d%d,这就说明肯定要输入两个整数!
0x08048ebd:
mov0x8(%ebp),%eax0x08048ec0:
mov%eax,(%esp)ebp+8的值赋给esp0x08048ec3:
call0x8048840跟上面那个%d%d结合思考一下,发现这个题,要输入两个数0x08048ec8:
cmp$0x1,%eax0x08048ecb:
jg0x8048ed20x08048ecd:
call0x80490d1说明eax(此时sscanf函数的返回值)大于1,这个函数的返回值是输入元素的个数0x08048ed2:
cmpl$0x7,-0xc(%ebp)0x08048ed6:
ja0x8048f43如果ebp-12大于7,则跳到(其实就是炸弹啦)说明ebp-12小于等于7.0x08048ed8:
mov-0xc(%ebp),%eaxebp-12的值赋给eax0x08048edb:
jmp*0x804a1a0(,%eax,4)间接跳转,跳到后面这个地址,这是这个函数的核心!
考虑对不同的ebp-12的值有不同的操作,这很像是一个switch操作。
0x08048ee2:
mov$0x0,%eaxeax清零0x08048ee7:
jmp0x8048f3c0x08048ee9:
mov$0x0,%eax0x08048eee:
xchg%ax,%ax0x08048ef0:
jmp0x8048f370x08048ef2:
mov$0x0,%eax0x08048ef7:
jmp0x8048f320x08048ef9:
mov$0x0,%eax0x08048efe:
xchg%ax,%ax0x08048f00:
jmp0x8048f2d0x08048f02:
mov$0x0,%eax0x08048f07:
jmp0x8048f280x08048f09:
mov$0x0,%eax0x08048f0e:
xchg%ax,%ax0x08048f10:
jmp0x8048f230x08048f12:
mov$0x314,%eax*0x804a1a0这个值,就是上面这个地址,eax=7880x08048f17:
jmp0x8048f1e0x08048f19:
mov$0x0,%eax0x08048f1e:
sub$0x35a,%eaxeax=788-0x35a=-700x08048f23:
add$0x2ef,%eax0x08048f28:
sub$0x216,%eax0x08048f2d:
add$0x216,%eax0x08048f32:
sub$0x216,%eax0x08048f37:
add$0x216,%e