计算机系统基础实验2——bomb
实验介绍
- 使用课程知识拆除一个“Binary Bombs”来增强对程序的机器级表示、汇编语言、调试器和逆向工程等理解。
- 一个“Binary Bombs”(二进制炸弹,简称炸弹)是一个Linux可执行C程序,包含phase1~phase6共6个阶段。
- 炸弹运行各阶段要求输入一个字符串,若输入符合程序预期,该阶段炸弹被“拆除”,否则“爆炸” 。
- 实验目标是你需要拆除尽可能多的炸弹。
实验步骤:
第一步:反汇编
将自己的炸弹文件复制到share目录下
解压炸弹文件,并 cd
到解压出的子目录
对bomb
进行反汇编并将汇编代码输出到asm.txt
中:objdump –d bomb > asm.txt
查看生成的asm.txt
文件,结合bomb.c
中的代码框架和汇编代码,找出:函数之间的调用关系、传递的参数;
第二步:查看汇编源代码asm.txt文件
第三步:执行 gdb bomb
,找到拆弹字符串。
一句话:通过阅读执行判断操作的汇编代码,得出正确输入。
实验内容:
<phase_1> :字符串比较
08048b33 <phase_1>: #字符串比较8048b33: 83 ec 14 sub $0x14,%esp8048b36: 68 2c a1 04 08 push 0x804a12c #(gdb) x/s 0x804812c,便找到输入的字符串;8048b3b:ff 74 24 1c pushl 0x1c(%esp)8048b3f: e8 7c 04 00 00 call 8048fc0 <strings_not_equal>8048b44: 83 c4 10 add $0x10,%esp8048b47: 85 c0 test %eax,%eax #判断两个字符串是否相等。8048b49: 74 05 je 8048b50 <phase_1+0x1d>8048b4b:e8 ad 06 00 00 call 80491fd <explode_bomb>8048b50: 83 c4 0c add $0xc,%esp8048b53: c3 ret
gdb调试,找到判断时所对照的正确字符串,便是正确输入。
gdb bomb
:进入bomb文件的调试界面;
x/s 0x804812c
:找到该位置中存放的正确字符串。
找到的字符串为:When I get angry, Mr. Bigglesworth gets upset.
<phase_2>:循环
//例1:
08048b54 <phase_2>: #循环8048b54: 56 push %esi8048b55: 53 push %ebx #没有修正ebp,还在main函数底部8048b56: 83 ec 2c sub $0x2c,%esp8048b59: 65 a1 14 00 00 00 mov %gs:0x14,%eax #gs段寄存器,保存段内地址8048b5f: 89 44 24 24 mov %eax,0x24(%esp) #检测栈帧有没有被破坏8048b63: 31 c0 xor %eax,%eax8048b65: 8d 44 24 0c lea 0xc(%esp),%eax8048b69: 50 push %eax8048b6a: ff 74 24 3c pushl 0x3c(%esp) #修正到main函数栈帧中取参数,相当于ebp+88048b6e: e8 c7 06 00 00 call 804923a <read_six_numbers> #从input分离出6个数字8048b73: 83 c4 10 add $0x10,%esp 8048b76: 83 7c 24 04 01 cmpl $0x1,0x4(%esp) #判断第一个数是否为18048b7b:74 05 je 8048b82 <phase_2+0x2e>8048b7d:e8 7b 06 00 00 call 80491fd <explode_bomb>8048b82: 8d 5c 24 04 lea 0x4(%esp),%ebx #现在ebx存的是数1所在位置8048b86: 8d 74 24 18 lea 0x18(%esp),%esi #设置esi为为ebx循环的终止位置
//循环部分8048b8a: 8b 03 mov (%ebx),%eax #把ebx中存的数赋给eax8048b8c: 01 c0 add %eax,%eax #eax+=eax;8048b8e: 39 43 04 cmp %eax,0x4(%ebx) #看ebx+4位置上的数是否为eax;8048b91: 74 05 je 8048b98 <phase_2+0x44>8048b93: e8 65 06 00 00 call 80491fd <explode_bomb>8048b98: 83 c3 04 add $0x4,%ebx #找下一个位置上的数,ebx+=4;8048b9b:39 f3 cmp %esi,%ebx #判断ebx是否已经到达终止位置,是否要继续循环8048b9d:75 eb jne 8048b8a <phase_2+0x36> #继续的话,跳转到8048b8a;8048b9f: 8b 44 24 1c mov 0x1c(%esp),%eax8048ba3: 65 33 05 14 00 00 00 xor %gs:0x14,%eax #无影响,不管8048baa: 74 05 je 8048bb1 <phase_2+0x5d>8048bac: e8 df fb ff ff call 8048790 <__stack_chk_fail@plt>8048bb1:83 c4 24 add $0x24,%esp8048bb4:5b pop %ebx8048bb5:5e pop %esi8048bb6:c3 ret
由 call 804923a <read_six_numbers>
可知,输入的字符串包括 6 个数。
由 8048b9d
上的指令jne 8048b8a <phase_2+0x36>
,又跳转回了上面的位置,可以知道这段是循环过程:
ebx
从第一个数所在的位置开始循环,esi
存放最后一个数所在的位置。
每次将 ebx
中的数赋值为到 eax
上,eax*=2
,判断下一位置上的数是否和 eax
中的值相等。也就是说,后面一个数的位置一定是前面一个数的2倍。
而由 cmpl $0x1,0x4(%esp)
可知第一个数为1,那么最终的答案便为1 2 4 8 16 32
。
//例2:
08048b8c <phase2>:8048b8c: 55 push %ebp8048b8d:89 e5 mov %esp,%ebp8048b8f: 56 push %esi8048b90: 53 push %ebx8048b91: 83 ec 28 sub $0x28,%esp8048b94: 8d 45 e0 lea -0x20(%ebp),%eax8048b97: 50 push %eax8048b98: ff 75 08 pushl 0x8(%ebp)8048b9b:e8 ca 05 00 00 call 804916a <readsixnumbers>8048ba0: 83 c4 10 add $0x10,%esp8048ba3: 83 7d e0 00 cmpl $0x0,-0x20(%ebp) #判断第一个值是否为08048ba7: 75 06 jne 8048baf <phase2+0x23>8048ba9: 83 7d e4 01 cmpl $0x1,-0x1c(%ebp) #判断第二个值是否为18048bad: 74 05 je 8048bb4 <phase2+0x28>8048baf: e8 8e 05 00 00 call 8049142 <explodebomb>8048bb4:8d 5d e0 lea -0x20(%ebp),%ebx #将0的地址放入ebx8048bb7:8d 75 f0 lea -0x10(%ebp),%esi #设置ebx的循环终止地址8048bba: eb 07 jmp 8048bc3 <phase2+0x37> #跳过第一次循环的初始值判断部分,直接进行操作
//循环部分8048bbc: 83 c3 04 add $0x4,%ebx #ebx+=4,地址更新8048bbf: 39 f3 cmp %esi,%ebx #判断是否循环到终止位置了8048bc1: 74 11 je 8048bd4 <phase2+0x48> #如果是,退出循环8048bc3: 8b 43 04 mov 0x4(%ebx),%eax #把下一位置的值放到eax中8048bc6: 03 03 add (%ebx),%eax #把当前位置的值累加到eax8048bc8: 39 43 08 cmp %eax,0x8(%ebx) #判断下下位置是否是eax,即其前面两位置之和8048bcb: 74 ef je 8048bbc <phase2+0x30> #如果是,继续循环;否则爆炸。8048bcd: e8 70 05 00 00 call 8049142 <explodebomb>8048bd2:eb e8 jmp 8048bbc <phase2+0x30>8048bd4:8d 65 f8 lea -0x8(%ebp),%esp8048bd7:5b pop %ebx8048bd8:5e pop %esi8048bd9:5d pop %ebp8048bda: c3 ret
<phase_3>:跳转
08048bb7 <phase_3>: #跳转8048bb7:83 ec 1c sub $0x1c,%esp8048bba: 65 a1 14 00 00 00 mov %gs:0x14,%eax8048bc0: 89 44 24 0c mov %eax,0xc(%esp)8048bc4: 31 c0 xor %eax,%eax8048bc6: 8d 44 24 08 lea 0x8(%esp),%eax8048bca: 50 push %eax8048bcb: 8d 44 24 08 lea 0x8(%esp),%eax8048bcf: 50 push %eax8048bd0:68 8d a3 04 08 push $0x804a38d #(gdb) x/s 0x804a38d,得到 "%d %d",可知输入的是数字,数字;8048bd5:ff 74 24 2c pushl 0x2c(%esp)8048bd9:e8 32 fc ff ff call 8048810 <__isoc99_sscanf@plt>8048bde: 83 c4 10 add $0x10,%esp8048be1: 83 f8 01 cmp $0x1,%eax #判断输入数字的个数,一定要大于1;8048be4: 7f 05 jg 8048beb <phase_3+0x34>8048be6: e8 12 06 00 00 call 80491fd <explode_bomb>8048beb: 83 7c 24 04 07 cmpl $0x7,0x4(%esp) #判断输入的第一个值是否大于7,因为只有0~7八个分支;8048bf0: 77 3c ja 8048c2e <phase_3+0x77>8048bf2: 8b 44 24 04 mov 0x4(%esp),%eax 8048bf6: ff 24 85 8c a1 04 08 jmp *0x804a18c(,%eax,4) //#(gdb) p/x *0x804a18c,得到下一条指令的地址0x8048c3a;
# 因为一共8个跳转分支,所以需要得到其跳转位置。(gdb) x/8x 0x804a18c,得到其8个分支的位置
# 跳转表:8048bfd: b8 e7 03 00 00 mov $0x3e7,%eax #第1个,如果输入1的话,跳到此处;8048c02: eb 3b jmp 8048c3f <phase_3+0x88>8048c04: b8 83 03 00 00 mov $0x383,%eax #第2个8048c09: eb 34 jmp 8048c3f <phase_3+0x88>8048c0b: b8 9a 03 00 00 mov $0x39a,%eax #第3个8048c10: eb 2d jmp 8048c3f <phase_3+0x88>8048c12: b8 f0 01 00 00 mov $0x1f0,%eax #第4个8048c17: eb 26 jmp 8048c3f <phase_3+0x88>8048c19: b8 31 01 00 00 mov $0x131,%eax #第5个8048c1e: eb 1f jmp 8048c3f <phase_3+0x88>8048c20: b8 d2 03 00 00 mov $0x3d2,%eax #第6个8048c25: eb 18 jmp 8048c3f <phase_3+0x88>8048c27: b8 6b 01 00 00 mov $0x16b,%eax #第7个8048c2c: eb 11 jmp 8048c3f <phase_3+0x88>8048c2e: e8 ca 05 00 00 call 80491fd <explode_bomb>8048c33: b8 00 00 00 00 mov $0x0,%eax8048c38: eb 05 jmp 8048c3f <phase_3+0x88>8048c3a: b8 ad 01 00 00 mov $0x1ad,%eax #第0个 如果跳转到此处,eax赋值为(1ad)_16,即429;8048c3f: 3b 44 24 08 cmp 0x8(%esp),%eax #判断第二个数是否为eax。8048c43: 74 05 je 8048c4a <phase_3+0x93>8048c45: e8 b3 05 00 00 call 80491fd <explode_bomb>8048c4a: 8b 44 24 0c mov 0xc(%esp),%eax8048c4e: 65 33 05 14 00 00 00 xor %gs:0x14,%eax8048c55: 74 05 je 8048c5c <phase_3+0xa5>8048c57: e8 34 fb ff ff call 8048790 <__stack_chk_fail@plt>8048c5c: 83 c4 1c add $0x1c,%esp8048c5f: c3 ret
给出了一个地址 push $0x804a38d
,那么gdb调试 #(gdb) x/s 0x804a38d
,得到 "%d %d"
,可知输入的是数字,数字
,两个数。
由 cmpl $0x7,0x4(%esp)
可以知道,输入的第一个数最大不超过7,说明只有0~7八个分支。
通过gdb调试指令:x/8x 0x804a18c
,便能找到所有分支的地址。
可见,第0个分支的地址为 0x8048c3a
,跳转到该位置,eax
赋值为(1ad)_16
,即十进制的 429
;所以最终的答案可以为:0 429
。
同理,可以找到第1分支,第2分支…上的数,答案不唯一。
<phase_4>:递归调用
08048c60 <func4>:8048c60: 57 push %edi8048c61: 56 push %esi8048c62: 53 push %ebx8048c63: 8b 5c 24 10 mov 0x10(%esp),%ebx #x = 78048c67: 8b 7c 24 14 mov 0x14(%esp),%edi #y = d28048c6b: 85 db test %ebx,%ebx8048c6d: 7e 2b jle 8048c9a <func4+0x3a> #如果x<=0的话,返回08048c6f: 89 f8 mov %edi,%eax8048c71: 83 fb 01 cmp $0x1,%ebx #否则,若x=1,返回y8048c74: 74 29 je 8048c9f <func4+0x3f> 8048c76: 83 ec 08 sub $0x8,%esp8048c79: 57 push %edi8048c7a: 8d 43 ff lea -0x1(%ebx),%eax8048c7d: 50 push %eax8048c7e: e8 dd ff ff ff call 8048c60 <func4> #以x-1作为形参继续调用func(x-1,y);8048c83: 83 c4 08 add $0x8,%esp8048c86: 8d 34 07 lea (%edi,%eax,1),%esi #esi = y + sub_8048C60(x - 1, y);8048c89: 57 push %edi8048c8a: 83 eb 02 sub $0x2,%ebx8048c8d: 53 push %ebx8048c8e: e8 cd ff ff ff call 8048c60 <func4> #以x-2作为形参继续调用func(x-2,y);8048c93: 83 c4 10 add $0x10,%esp8048c96: 01 f0 add %esi,%eax #否则 x!=1, 返回 esi + func(x-2,y),即y + func(x-1,y) + func(x-2,y)。8048c98: eb 05 jmp 8048c9f <func4+0x3f>8048c9a: b8 00 00 00 00 mov $0x0,%eax8048c9f: 5b pop %ebx8048ca0: 5e pop %esi8048ca1: 5f pop %edi8048ca2: c3 ret 08048ca3 <phase_4>:8048ca3: 83 ec 1c sub $0x1c,%esp8048ca6: 65 a1 14 00 00 00 mov %gs:0x14,%eax8048cac: 89 44 24 0c mov %eax,0xc(%esp)8048cb0: 31 c0 xor %eax,%eax8048cb2: 8d 44 24 04 lea 0x4(%esp),%eax8048cb6: 50 push %eax8048cb7: 8d 44 24 0c lea 0xc(%esp),%eax8048cbb: 50 push %eax8048cbc: 68 8d a3 04 08 push $0x804a38d8048cc1: ff 74 24 2c pushl 0x2c(%esp)8048cc5: e8 46 fb ff ff call 8048810 <__isoc99_sscanf@plt>8048cca: 83 c4 10 add $0x10,%esp8048ccd: 83 f8 02 cmp $0x2,%eax #判断,如果输入数的个数小于等于2的话,爆炸8048cd0: 75 0c jne 8048cde <phase_4+0x3b>8048cd2: 8b 44 24 04 mov 0x4(%esp),%eax8048cd6: 83 e8 02 sub $0x2,%eax8048cd9: 83 f8 02 cmp $0x2,%eax8048cdc: 76 05 jbe 8048ce3 <phase_4+0x40> #判断,第二个数是否大于等于2,小于4 8048cde: e8 1a 05 00 00 call 80491fd <explode_bomb>8048ce3: 83 ec 08 sub $0x8,%esp8048ce6: ff 74 24 0c pushl 0xc(%esp)8048cea: 6a 07 push $0x78048cec: e8 6f ff ff ff call 8048c60 <func4 > #func(7,d2)8048cf1: 83 c4 10 add $0x10,%esp8048cf4: 3b 44 24 08 cmp 0x8(%esp),%eax #判断第一个数是否为函数返回值8048cf8: 74 05 je 8048cff <phase_4+0x5c>8048cfa: e8 fe 04 00 00 call 80491fd <explode_bomb>8048cff: 8b 44 24 0c mov 0xc(%esp),%eax8048d03: 65 33 05 14 00 00 00 xor %gs:0x14,%eax8048d0a: 74 05 je 8048d11 <phase_4+0x6e>8048d0c: e8 7f fa ff ff call 8048790 <__stack_chk_fail@plt>8048d11: 83 c4 1c add $0x1c,%esp8048d14: c3 ret
根据func4函数的汇编代码,还原出其C++程序为:
int __cdecl sub_8048C60(int a1, int a2)
{int result; // eaxint v3; // esiif ( a1 <= 0 )return 0;result = a2;if ( a1 != 1 ){v3 = a2 + sub_8048C60(a1 - 1, a2);result = v3 + sub_8048C60(a1 - 2, a2);}return result;
}
最初状态,a1为定值7,a2为第二个输入的数。
所以,如果第二个输入2的话,函数递归过程为:func(7,2)调用func(6,2)和func(5,2),func(6,2)再调用func(5,2)和func(4,2),func(5,2)再调用func(4,2)和func(3,2)…
所以,为了计算func(7,2),则需依次计算出func(0,2), func(1,2), func(2,2), func(3,2), func(4,2), func(5,2), func(6,2).
结果依次为:2 4 8 14 24 40,那么最终答案为2 + 24 + 40 = 66。
所以,一种答案可为66 2
。
计算机系统基础实验2——bomb相关推荐
- 华中科技大学计算机系统基础实验3报告,华中科技大学计算机系统基础实验报告...
华中科技大学计算机系统基础实验报告 1 课 程 实 验 报 告 课程名称: 计算机系统基础 专业班级: 学 号: 姓 名: 指导教师: 报告日期: 2016年 5月 24 日 计算机科学与技术学院2 ...
- 计算机系统基础实验报告
计算机系统基础实验报告 语言 C++ 编译器 Dev C++ 实验一:数的机器级表示 编写无符号数的转换: unsigned int unsignedToValue(char binary[],int ...
- 《深入理解计算机系统》实验二Bomb Lab
前言 <深入理解计算机系统>实验二Bomb Lab的下载和官网文档的机翻请看 <深入理解计算机系统>实验二Bomb Lab下载和官方文档机翻 用的调试工具是gdb,用到的指令如 ...
- 计算机系统基础实验-LinkLab实验
这是大三时的实验课,很久以前的东西,应要求放出来,做的不是很好.linux永远都是很重要的,希望我和大家都记得这个.实际上做到第五阶段我就不会了. 实验课程名称:计算机系统基础 实验项目名称:Link ...
- 华中科技大学计算机系统基础实验3报告,华中科技大学计算机系统基础实验报告.doc...
文档介绍: 课程实验报告课程名称:计算机系统基础专业班级:学号:姓名:指导教师:报告日期:2016年5月24日计算机科学与技术学院目录实验1: 2实验2: 9实验3: 22实验总结 30 实验1:数据 ...
- 《深入理解计算机系统》实验二Bomb Lab下载和官方文档机翻
前言 <深入理解计算机系统>官网:http://csapp.cs.cmu.edu/3e/labs.html 该篇文章是实验二Bomb Lab的Writeup机翻. 原文:http://cs ...
- 计算机系统基础实验01运算器算术运算
计算机系统基础 运算器算术运算 实验目的 掌握ALU的算术运算原理,熟悉ALU数据传送通路和数据传送方式. 实验环境 微机,配置Windows操作系统.LC-3仿真机软件. 实验内容 ALU数据传送通 ...
- 计算机系统基础实验:认识logisim软件、门电路逻辑功能测试(仿真)
通过logisim对逻辑电路进行分析 文章目录 目录 文章目录 前言 一.使用工具 二.实验过程 1.门电路绘制 2.真值表 总结 前言 计算机系统基础也开了实验课,实验内容是利用logisim软件进 ...
- 北京邮电大学计算机系统基础实验,第1章 计算机系统基础85666.ppt
第1章 计算机系统基础85666 盘青梅 gdpqm@126.com 总结:计算机的发展阶段 冯·诺依曼计算机模型(P14) 总线系统结构图 总线(Bus)是计算机各部件传输信息的公共通道.有数据总线 ...
- 计算机系统基础实验:二进制拆弹实验
一.实验目的: 学习并熟练使用 gdb 调试器和 objdump 理解汇编语言代码的行为或作用 提高阅读和理解汇编代码的能力 二.实验要求 实验共包括七个阶段,每个阶段考察机器级语言程序的不同方面,难 ...
最新文章
- Anconda PyCharm TensorFlow
- python散点图拟合曲线-【python常用图件绘制#01】线性拟合结果图
- Mysql索引基本概念及案例总结(含索引的使用注意事项)
- 宿迁学计算机的学校,宿迁计算机学校
- 360——新式的流氓
- 实验2-3-3 信号处理总结以及Linux下支持的信号列表
- 企业微信API之通讯录同步
- Badboy 录制脚本提示“当前页面的脚本发生错误”解决
- 1114 计算营业额
- 归并排序 (递归 非递归)
- MATLAB源码-GRABIT从图像文件中提取数据点。
- 自旋锁(spinlock)
- SV,class学习笔记五、参数化类(parameterized class)
- BBEdit—HTML文本编辑器
- CDS 获取系统日期时间
- 小i机器人用AI打造金融业认知智能企业
- 【子桓说】从阿里、百度分析,教你判断一家企业是否适合自己
- css怎样给网页加页脚,在移动Web页面中使用CSS固定页脚
- tuned-adm性能优化的配置文件详解
- H265编码 SPS分析
热门文章
- python自动化开发-[第九天]-异常处理、进程
- Java如何实现贪吃蛇小游戏
- IT领域的罗马帝国——微软公司
- Qt 弹出对话框选择图片并显示
- 如何在国内快速访问Github
- 解决服务器空间满/var/lib/docker/overlay2占用很大,千万慎用 docker system prune -a清理 mongodb等数据库容器及镜像可能被删,找回恢复数据
- 要么忙于生存,要么忙于去死
- Jira+Confluence+Fisheye+Crucible安装步骤清单
- 棋牌游戏判断牌型算法---适合所有的棋牌游戏
- python爬虫小说爬取