1、 课程实验报告 课 程 名 称:计算机组成与结构 实验项目名称:bomblab 专 业 班 级:姓 名:学 号:指 导 教 师:完 成 时 间:2016 年 4 月 20 日 信息科学与工程学院 实验题目:bomblab 实验目的:程序运行在 linux 环境中。程序运行中有 6 个关卡(6 个 phase),每个 phase需要用户在终端上输入特定的字符或者数字才能通关,否则会引爆炸弹!那么如何才能知道输入什么内容呢?这需要你使用 gdb 工具反汇编出汇编代码,结合 c 语言文件找到每个关卡的入口函数。然后分析汇编代码,找到在每个 phase 程序段中,引导程序跳转到“explode_bom
2、b”程序段的地方,并分析其成功跳转的条件,以此为突破口寻找应该在命令行输入何种字符通关。实验环境:ubuntu14.04 虚拟机、gdb 工具 实验内容及操作步骤:首先打开 bomb.c 文件,发现这个文件里只有主函数,没有具体的代码,所以我们要通过反汇编得到 6 关的具体代码。反汇编有两个具体的方法:第一种:objdump-d bomb 1.txt 将反汇编结果输出到 1.txt 中 第二种:使用 gdb 调试 bomb,命令为(gdb)disas func_name,其中 func_name对应于本次实验中的六个函数 phase_16,再将结果复制到 word 中。我采用第二种方法得到反汇
3、编代码,下面对六个 bomb 进行分析、得到我们拆炸弹所需的密码。Phase_1 内容如下 0 x08048f61:push%ebp 0 x08048f62:mov%esp,%ebp 0 x08048f64:sub$0 x18,%esp 这里对 esp-24 0 x08048f67:movl$0 x804a15c,0 x4(%esp)这是将$0 x804a15c 处的值存入 esp+4 中 0 x08048f6f:mov 0 x8(%ebp),%eax ebp+8 就是从调用函数处取出第一个参数,放到 eax 寄存器中 0 x08048f72:mov%eax,(%esp)将 eax 的值传给
4、esp 0 x08048f75:call 0 x8048fab 此处是入口函数的地址 0 x8048fab,该函数要调用的参数为 esp+4(即$0 x804a15c 处的值),和 ebp+8(即我们输入的值)该函数的作用是:判断字符串是否相等 考虑一个函数的返回值要存在 eax 中,则以下的 eax 已经发生改变,是判断字符串是否相等的结果 0 x08048f7a:test%eax,%eax 0 x08048f7c:je 0 x8048f83 0 x08048f7e:call 0 x80490d1 以上三句,如果 eax 不为 0,则引爆炸弹,如果 eax 为 0,则跳转到 leave 语句
5、函数结束。说明 eax 为 0 时,可以进入下一关 0 x08048f83:leave 0 x08048f84:ret 解题过程:本题的栈帧结构如下:根据以上分析,我们发现,从键盘输入一个值,放到(新)ebp+8 中,接着函数进行调用,把他传到 esp 中,接着,函数再从$0 x804a15c 这个地址取值,放到 esp+8中,接着,程序对这两个参数进行函数调用,调用判断字符串是否相等的程序 string not equal 进行判断,如果二者相等,则返回值为 0,不引爆炸弹,反之,只要二者不相等,则炸弹爆炸。分析结论:此处的密码存在地址$0 x804a15c 中,我们只要查看该地址的值,即可
6、完成该题。打开 gdb 调试,运行 x/s 0 x804a15c,查看该处的值 故第一题的答案为 We have to stand with our North Korean allies.Phase_2 内容如下:0 x08048d6a:push%ebp 0 x08048d6b:mov%esp,%ebp 0 x08048d6d:push%esi 0 x08048d6e:push%ebx 这是两个调用者保存寄存器,因为接下来的循环中使用到了这两个寄存器的值,所以要进行压栈保存。0 x08048d6f:sub$0 x30,%esp esp-48 0 x08048d72:lea -0 x20(%e
7、bp),%eax 0 x08048d75:mov%eax,0 x4(%esp)以上两句把 ebp-32 处的地址传给 esp+4 处 0 x08048d79:mov 0 x8(%ebp),%eax 0 x08048d7c:mov%eax,(%esp)以上两句把 ebp+8 处的值传给 esp 0 x08048d7f:call 0 x804910b 根据函数名观察,要读取 6 个数,所以这题要输入六个数字 0 x08048d84:cmpl$0 x0,-0 x20(%ebp)0 x08048d88:jne 0 x8048d90 跳转的地址是引爆炸弹,不相等就引爆,所以 ebp-32 处的值要等于
8、0 0 x08048d8a:cmpl$0 x1,-0 x1c(%ebp)0 x08048d8e:je 0 x8048d95 0 x08048d90:call 0 x80490d1 如果相等就继续,不相等就爆炸,所以 ebp-28 处的值要为 1 0 x08048d95:lea -0 x18(%ebp),%ebx ebp-24 传给 ebx 0 x08048d98:lea -0 x8(%ebp),%esi ebp-8 传给 esi 以上两句是数据初始化,ebp-24 是第三个数据的地址,ebp-8 是“第七个”数据的地址,这个 esi 设置成 ebp-8 的地址是用作判断的。接下来是一个循环计算
9、的过程,具体的过程我在后续的解题思路里做了讲解。0 x08048d9b:mov -0 x4(%ebx),%eax 0 x08048d9e:add -0 x8(%ebx),%eax 0 x08048da1:cmp%eax,(%ebx)0 x08048da3:je 0 x8048daa 0 x08048da5:call 0 x80490d1 不相等就引爆,所以此处分析得 ebx 要与 eax 的值相等 0 x08048daa:add$0 x4,%ebx ebx+=4 0 x08048dad:cmp%esi,%ebx 0 x08048daf:jne 0 x8048d9b 0 x08048db1:ad
10、d$0 x30,%esp 0 x08048db4:pop%ebx 0 x08048db5:pop%esi 0 x08048db6:pop%ebp 0 x08048db7:ret 解题过程:本题具体思路都已标注说明,下面仅对循环体内容的第一次循环作简要说明。从 0 x08048d9b:mov -0 x4(%ebx),%eax 此处开始,原来 ebx 所存的地址为 ebp-24,这里将 ebx-4,即 ebp-28 处的值,也就是 1,赋给了 eax 0 x08048d9e:add -0 x8(%ebx),%eax 这里将 ebx-8,也就是 ebp-32 处的值,也就是 0,和 eax 作 ad
11、d 操作,这部得出的结果是:eax=1+0=1 0 x08048da1:cmp%eax,(%ebx)0 x08048da3:je 0 x8048daa 0 x08048da5:call 0 x80490d1 不相等就引爆,所以此处分析得 ebx 要与 eax 的值相等,而此时的 ebx 是什么呢?就是 ebp-24,即第三个数,说明第三个数是前两数之和 0 x08048daa:add$0 x4,%ebx 0 x08048dad:cmp%esi,%ebx 0 x08048daf:jne 0 x8048d9b 以上三句,如果我们输入的值满足条件,那么 ebx 上移 4 位继续循环,也就是继续求前两
12、个数之和赋给第三个数。0 x08048db1:add$0 x30,%esp 如果 ebx 存的值(我们要求 6 个数,所以最多到 ebp-12)和 esi 存的值(ebp-8,第七个数)相等的话函数结束了 做到这里应该也明白了,其实就是一个斐波那契数列前六项。所以这题的答案为 0 1 1 2 3 5 另附本题栈帧结构如下:Phase_3 内容如下:0 x08048ea1:push%ebp 0 x08048ea2:mov%esp,%ebp 0 x08048ea4:sub$0 x28,%esp esp-40 0 x08048ea7:lea -0 x10(%ebp),%eax 0 x08048eaa
13、:mov%eax,0 xc(%esp)ebp-16 处地址赋给 esp+12 0 x08048eae:lea -0 xc(%ebp),%eax 0 x08048eb1:mov%eax,0 x8(%esp)ebp-12 处地址赋给 esp+8 0 x08048eb5:movl$0 x804a23e,0 x4(%esp)这个地址的值可查,查出来之后发现是:%d%d,这就说明肯定要输入两个整数!0 x08048ebd:mov 0 x8(%ebp),%eax 0 x08048ec0:mov%eax,(%esp)ebp+8 的值赋给 esp 0 x08048ec3:call 0 x8048840 跟上面
14、那个%d%d 结合思考一下,发现这个题,要输入两个数 0 x08048ec8:cmp$0 x1,%eax 0 x08048ecb:jg 0 x8048ed2 0 x08048ecd:call 0 x80490d1 说明 eax(此时 sscanf 函数的返回值)大于 1,这个函数的返回值是输入元素的个数 0 x08048ed2:cmpl$0 x7,-0 xc(%ebp)0 x08048ed6:ja 0 x8048f43 如果 ebp-12 大于 7,则跳到(其实就是炸弹啦)说明 ebp-12 小于等于 7.0 x08048ed8:mov -0 xc(%ebp),%eax ebp-12 的值赋给
15、 eax 0 x08048edb:jmp *0 x804a1a0(,%eax,4)间接跳转,跳到后面这个地址,这是这个函数的核心!考虑对不同的 ebp-12 的值有不同的操作,这很像是一个 switch 操作。0 x08048ee2:mov$0 x0,%eax eax 清零 0 x08048ee7:jmp 0 x8048f3c 0 x08048ee9:mov$0 x0,%eax 0 x08048eee:xchg%ax,%ax 0 x08048ef0:jmp 0 x8048f37 0 x08048ef2:mov$0 x0,%eax 0 x08048ef7:jmp 0 x8048f32 0 x08
16、048ef9:mov$0 x0,%eax 0 x08048efe:xchg%ax,%ax 0 x08048f00:jmp 0 x8048f2d 0 x08048f02:mov$0 x0,%eax 0 x08048f07:jmp 0 x8048f28 0 x08048f09:mov$0 x0,%eax 0 x08048f0e:xchg%ax,%ax 0 x08048f10:jmp 0 x8048f23 0 x08048f12:mov$0 x314,%eax *0 x804a1a0 这个值,就是上面这个地址,eax=788 0 x08048f17:jmp 0 x8048f1e 0 x08048f19:mov$0 x0,%eax 0 x08048f1e:sub$0 x35a,%eax eax=788-0 x35a=-70 0 x08048f23:add$0 x2ef,%eax 0 x08048f28:sub$0 x216,%eax 0 x08048f2d:add$0 x216,%eax 0 x08048f32:sub$0 x216,%eax 0 x08048f37:add$0 x216,%e
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1