本内容是本人的作业备份,仅作参考,不可抄袭!

实验任务概述:

本实验通过要求你使用课程所学知识拆除一个“binary bombs”来增强对程序的机器级表示、汇编语言、调试器和逆向工程等方面原理与技能的掌握。一个“binary bombs”(32位二进制炸弹,下文将简称为炸弹)是一个Linux可执行程序,包含了7个阶段(或层次、关卡)。炸弹运行的每个阶段要求你输入一个特定字符串,你的输入符合程序预期的输入,该阶段的炸弹就被拆除引信即解除了,否则炸弹“爆炸”打印输出 “BOOM!!!”。实验的目标是拆除尽可能多的炸弹层次。

每个炸弹阶段考察了机器级程序语言的一个不同方面,难度逐级递增:

➢ 阶段1:字符串比较

➢ 阶段2:循环

➢ 阶段3:条件/分支

➢ 阶段4:递归调用和栈

➢ 阶段5:指针

➢ 阶段6:链表/指针/结构

另外还有一个隐藏阶段(树型结构),只有当你在第4阶段的解后附加一特定字符串后才会出现。

为完成二进制炸弹拆除任务,你需要使用gdb调试器和objdump来反汇编炸弹的可执行文件并跟踪调试每一阶段的机器代码,从中理解每一汇编语言代码的行为或作用,进而设法推断拆除炸弹所需的目标字符串。比如在每一阶段的开始代码前和引爆炸弹的函数前设置断点。

实验步骤:

1.分析main函数

分析bomb.c

分析bomb.c可知,炸弹的运行机制:由read_line获取输入得到input,然后再将input传递给phase_1等函数,然后执行phase_1,如果执行正确,则拆弹成功,进入phase_2.

2.阶段一

分析phase_1的反汇编代码,可以发现在(8048d17)处调用了<strings_not_equal>,这个函数的功能是比较两个字符串是否相等,因此猜测这段代码是要输入一个字符串A,与其内部字符串B比较看是否一致,如果一样就通过。这里输入“rrr”进行测试。

而(8048d0d)处为调用<strings_not_equal>函数前进行的入栈,并且传入了一个地址,猜测入栈的eax,就是题目要求的字符串B,而另一个入栈的0x8(%ebp)猜测就是输入的A

  1. b *(0x8048d17) 在此处设立断点,去看eax中的值
  2. x/s $ebp+0x8 这里将($ebp+0x8)中的内容入栈了,通过x/s查看其中的内容,发现是我们之前输入的“rrr”,可以得知返回的就是A,说明将A入栈了
  3. x/s $eax 以字符串的形式去看eax中存放的东西,得到字符串I turned the moon into something I call a Death Star.  ,可知这就是我们要的字符串B
  4. 重新输入A= I turned the moon into something I call a Death Star. 顺利通过

3.阶段2

观察发现,phase_2在(8048d5d)处调用了一个函数<read_six_numbers>,猜测是读取6个数,并按照一定的规律进行输出。需要输入6个数A B C D E F,这里输入0 1 1 2 3 4进行测试。

(1)b*(0x8048d66)观察在调用函数<read_six_numbers>后内存的存放情况

(2)x/16wx $ebp-0x24查看从($ebp-0x24)开始,16个32位数的存放。可以发现从($ebp-0x24)~($ebp)存放的是输入的A B C D E F:0 1 1 2 3 4

(3)而分析(8048d66)和(8048d68)可以得知如果eax不等于0就会爆炸,而eax中存放的是($ebp-0x24)也就是A,则A必须为0

(4)b*(0x8048d6d) 这里有个cmp,如果eax!=1,就会爆炸。而根据(8048d6a)可知eax中存放的是($ebp-0x20)也就是B,则B必须为1

(5)b *(0x8048d9b) 可以得知6个数除了前两个数A,B,后面的数要通过前两个数相加得到。即A=0 , B=1 ,C=A+B,D=B+C ……,即最后的输出按照累加进行输出

(6)所以可得ABCDEF分别的:0 1 1 2 3 5

成功!

完整代码:

4.阶段3

可以发现phase_4调用了<__isoc99_sscanf@plt>,并且在(8048df8)与(8048dfc)将两个有效地址入栈,可以猜测需要输入两个数分别是A,B而(8048e78)猜测是将A,B根据跳转表,进行相应的计算后得到的数字与特定值进行比较,如果相等即通过.这里输入“4 0”进行测试。

  1. b*(0x8048e15) 调用<__isoc99_sscanf@plt>后,eax=输入的数字个数,这段代码表示如果eax<=1则爆炸,则输入的数字个数需要大于1。
  2. p/x $eax $eax=2,输入两个数顺利通过
  3. b*(0x8048e23) 这里将eax和7进行了比较,需要eax<=7.而这里eax=($ebp-0x1c),查看后发现就是第一个输入A,则A<=7
  4. p/x $eax $eax=4,发现eax等于输入的第一个数字A=4,而eax是被($ebp-0x1c)赋值的,下一步对($ebp-0x1c)进行查看
  5. x/4wx $ebp-0x1c  对从($ebp-0x1c)开始的内存查看四个32位的数据,可以发现从($ebp-0x1c)~( $ebp)分别存放的是:(A B C 输入的数字个数),而查看发现C=0,也就是(4 0 0 2)

  1. b *(0x 8048e78)将($ebp-0x1c)与5进行比较,而($ebp-0x1c)中存放的是第一个输入A,如果A>5就爆炸,所以A<=5
  2. b *(0x 8048e80)可以发现这里将经过L14~L22后得到的($ebp-0x14),与eax进行比较,而eax=($ebp-0x18)=B,所以这里需要将第二个输入B与C比较,如果B=C,则phase_3通过
  3. 那么如何得到C的值呢,通过观察发现(0x8048e34)处跳转指令的跳转地点与第一个输入有关,是一个跳转表的结构。
  4. b*(0x8048e34) 设置断点后,开始跟踪,发现不同的A会得到不同的C,如果输入A=4,则在L22结束后会输出C=0,这时再让输入B=0,即可通过。

完整代码:

5.阶段4

  1. b *(0x8048f51) 这里调用函数<__isoc99_sscanf@plt>
  2. b*(0x8048f5c) 这里如果($ebp-0x18)=2,则通过,否则会爆炸。而通过测试,发现($ebp-0x18)=输入的数字个数,所以可知要输入2个数A,B,这里输入“13 3”进行测试

  1. b *(0x8048f65) 这里如果eax=0则爆炸,而eax=($ebp-0x20)
  2. x/4wx ($ebp-0x20) 观察从($ebp-0x20)地址开始的4个32位的内容,发现    (($ebp-0x20)~($ebp-0x14))内存放的是                          (输入的A,B,输入的数字个数,未知D),

也就是“13,3,2,0”,所以eax!=0,则A!=0

b *(0x8048f6c) 比较($ebp-0x20)和0xe,如果($ebp-0x20)<14,才可通过,也就是A<14

  1. b *(0x8048f76) 为未知D赋值3,D=3

  1. b *(0x8048f88) 调用<func4>函数并且将(第一个输入A,0,0xe)送入栈
  2. 进入func4函数发现内部其实是个递归调用,其中有两次调用入口,分别是X口:(8048ee2)和Y口:(8048f06)
  3. b *(0x8048ecd) 这里比较eax与0x8(%ebp),
  4. p/x $eax发现eax=7,而0x8(%ebp)=第一个输入A,如果eax<A则调转到Y口,从Y口进下一轮递归,如果eax>A,则从X口进,如果eax=A,则直接跳转到(8048f15)
  5. b *(0x8048f15) 可以发现这里是给eax赋0,而测试可发现这里的eax即是func4的返回参数。
  6. b *(0x8048f96) 这里将-0x10(%ebp), -0x14(%ebp)进行比较,即需要将-0x10(%ebp)与D进行比较,由(6)知,D=3,而-0x10(%ebp)=eax=<func4>返回的参数E,所以如果E!=3,则爆炸,所以返回的参数需要等于3,E=3
  7. 如何让返回参数eax=E=3,观察func4函数发现,(0x8048f15)会给eax赋0,所以要避免走(0x8048f15),而只有A=eax时会进入(0x8048f15)。
  8. b *(0x8048ecd) 测试发现eax的值随着A的不同而变化,这里我们输入的A=0xd,这时发现eax进行三次分别值为7 b d,用ni的指令依次往下读

第一次eax=7,A>7,进入Y口

第二次eax=b,A>b,进入Y口

第三次eax=d,A=d,进入(0x8048f15)赋值eax=0

  1. 然后第一次从Y口返回,b*(0x8048f10) 将eax=1
  2. 第二次从Y口返回,b*(0x8048f0e) 将eax=2,b*( 8048f10) eax=eax+1=3
  3. b *(0x8048f96) 返回参数E=3,顺利通过
  4. b *(0x8048f9e) -0x1c(%ebp)= -0x14(%ebp),也就是B=D=3
  5. 得知输入A=13,B=3

6.阶段5

  1. b *(0x8048fe8) 这里调用了<string_length>函数
  2. b *(0x8048ff3) 这里将$0x6,-0x18(%ebp)比较,x/wx $ebp-0x18 得到-0x18(%ebp)=输入的个数,所以这里要求输入的字符个数为6
  3. b *(0x8049046) 这里调用了<strings_not_equal>,可知使要比较输入字符串S与key字符串是否一致,这里输入字符串“rrrrrr”
  4. x/s $ebx-0x2484 可以看到这里存放“flyers”,猜测与key有关
  5. x/s $ebp-0x13 这里存放“dddddd”,这里本来应该是我们输入的“rrrrrr”,现在变成了dddddd,说明字符串发生了某种变换,比较对应关系
  6. b *(0x80490x18),读取0x140(%ebx,%eax,1)= m a d u i e r s n f o t v b y l,而观察两两对应关系,只需要可以发现“flyers”在其中的顺序为”9,15,4,5,6,7”, 说明输入字符串中对应位的字符的最低4位的数值等于"9,f,e,5,6,7",即可通过这一关。查看ASCII值,得到ionefg

7.阶段6

  1. b *(0x804937b) 这里调用了<read_six_numbers>,可知是需要输入6个数字
  2. b*(0x80490xb5) 用ni指令一步一步看代码,发现这是一处(0x80490b5—0x8049105)循环,目的是判断6个数字彼此之间并不相等 ,功能指令在b *(0x80490ea),这里将eax,edx做了比较,
  3. b *(0x80490c7) 这里将eax与6比较,p/x $eax eax=输入的数字,说明输入要小于6所以需要输入6个小于6的数字,b *(0x80490be) 这里要求eax>0,所以要输入6个小于6大于0的数字
  4. b *(0x8049161) 这段循环将每个地址赋值分别对应输入数字所对应的代码
  5. b *(0x804919a) 这里将-0x4c(%ebp)地址里的内容赋值给%edx,将-0x4c(%ebp)+8地址的内容赋值给%eax,x/4wx $ebp-0x4c 查看可以发现更改后,

(3) 19c  (4) b3  (5) d  (6) 3bb  (1) 14c  (2) a8

  1. b *(0x80491a7) 这里将eax,与edx比较,需要将数字所赋值的值从大到小进行排列
  2. 所以输出值为 6 3 1 4 2 5

9.隐藏阶段

首先寻找隐藏关卡的打开入口,发现只有在<phase_defused>中调用了<secret_phase>,而<phase_defused>出现在main()中,由main调用于是从main函数开始看起。

  1. b phase_defused 在<phase_defused>函数上打断点
  2. b *(0x80499db) 这里将eax与0x6进行比较,如果eax=6才可通过,p/x $eax而经过测试发现,每通过一关,eax的数量就会加1,所以这里意思是只有在第6关通过后,才可打开

  1. b*(8049a07)处调用<__isoc99_sscanf@plt>,先看需要输入什么类型的数据。可以发现在调用前将两个特殊地址入栈,可能是需要输入的数据,可以查看一下。
  2. x/s $ebx-0x2231  得$0x804adcf=“%d %d %s”,即输入两个数字加一个字符串
  3. x/s $eax+0xf0 得$0x804d4f0=“13,3” ,即是在第4关的输入后面加一个字符串,这里我们输入“rrr”试一下

  1. b *(0x8049a12) 经过测试发现,-0x60(%ebp)如果输入两个数字就是2,再输入字符串就是3,所以这里是测试是否按“%d %d %s”格式输入。
  2. b *(0x8049a26) 这里调用了<strings_not_equal>,说明要比较输入字符串是否与内部字符串key相同。
  3. x/s $ebp-0x5c 查看结果可以发现 得到“rrr”说明这是我们输入的字符串,
  4. x/s $ebx-0x2228 得到“DrEvil”,这就是内部字符串key,在第四关输入的时候,输入“13 3 DrEvil”,即可进入第七关

  1. 这里进入secret_phase b *(0x8049272) 将0x0与-0x10(%ebp)比较
  2. x/wx ($ebp-0x10) 得到这里的-0x10(%ebp)是指输入的数字
  3. b *(0x8049278) 这里将$0x3e9与-0x10(%ebp),如果输入<=1001,才可通过,这里输入一个数A:7
  4. b *(0x8049293) 这里调用了<func7>函数

  1. 进入<func7>函数,b*0x80491ea 这里将0x0,0x8(%ebp)比较
  2. b *(0x80491fc)这里将%eax,0xc(%ebp)比较,如果eax<=($ebp+0xc),则进入(0x804921a),如果eax>($ebp+0xc),则进入下一轮递归
  3. x/4wx $ebp+0xc 发现$ebp+0xc=7,是输入A。
  4. p/x $eax 发现eax=24
  5. 所以如果eax>A,则进入递归,eax=24>A=7,所以进入下一轮递归

  1. c指令跳转到(0x80491fc)  p/x $eax  发现eax=8,eax=8>A=7,进入下一轮递归
  2. c指令跳转到(0x80491fc)  p/x $eax  发现eax=6,eax=6<A=7, 进入(0x804921a),经过测试发现eax每轮的值为24、8、6、1

  1. b *(0x804921f)这里将%eax,与0xc(%ebp)比较,如果相等则将eax=0
  2. p/x $eax eax=6 发现eax的值等于比A小的那个数,也就是A过不去的那个数,也就是如果eax=A,则将eax=0,而由b *(0x804929e)可知 这里将<func7>的输出值与4比较,如果不等就爆炸,所以我们知道通过<func7>要得到一个4的返回值,而这个返回值存放在eax里,也就是要使eax=4
  3. 如果要使eax=4,则应该避免让eax归0,所以eax!=A,所以A不能等于24、8、6、1这里(eax=6)!=(A=7),可以
  4. b*(0x8049242) 这里将eax=eax+1
  5. b*(0x49240)eax=eax+eax,可以发现如果递归三次从出口出,可以刚好使eax=4,即A=7可以使eax等于4

实验答案:

计算机系统基础实验 BombLab相关推荐

  1. 华中科技大学计算机系统基础实验3报告,华中科技大学计算机系统基础实验报告...

    华中科技大学计算机系统基础实验报告 1 课 程 实 验 报 告 课程名称: 计算机系统基础 专业班级: 学 号: 姓 名: 指导教师: 报告日期: 2016年 5月 24 日 计算机科学与技术学院2 ...

  2. 计算机系统基础实验报告

    计算机系统基础实验报告 语言 C++ 编译器 Dev C++ 实验一:数的机器级表示 编写无符号数的转换: unsigned int unsignedToValue(char binary[],int ...

  3. 计算机系统基础实验-LinkLab实验

    这是大三时的实验课,很久以前的东西,应要求放出来,做的不是很好.linux永远都是很重要的,希望我和大家都记得这个.实际上做到第五阶段我就不会了. 实验课程名称:计算机系统基础 实验项目名称:Link ...

  4. 华中科技大学计算机系统基础实验3报告,华中科技大学计算机系统基础实验报告.doc...

    文档介绍: 课程实验报告课程名称:计算机系统基础专业班级:学号:姓名:指导教师:报告日期:2016年5月24日计算机科学与技术学院目录实验1: 2实验2: 9实验3: 22实验总结 30 实验1:数据 ...

  5. 计算机系统基础实验01运算器算术运算

    计算机系统基础 运算器算术运算 实验目的 掌握ALU的算术运算原理,熟悉ALU数据传送通路和数据传送方式. 实验环境 微机,配置Windows操作系统.LC-3仿真机软件. 实验内容 ALU数据传送通 ...

  6. 计算机系统基础实验:认识logisim软件、门电路逻辑功能测试(仿真)

    通过logisim对逻辑电路进行分析 文章目录 目录 文章目录 前言 一.使用工具 二.实验过程 1.门电路绘制 2.真值表 总结 前言 计算机系统基础也开了实验课,实验内容是利用logisim软件进 ...

  7. 北京邮电大学计算机系统基础实验,第1章 计算机系统基础85666.ppt

    第1章 计算机系统基础85666 盘青梅 gdpqm@126.com 总结:计算机的发展阶段 冯·诺依曼计算机模型(P14) 总线系统结构图 总线(Bus)是计算机各部件传输信息的公共通道.有数据总线 ...

  8. 计算机系统基础实验 pa1

    文章目录 pa1 实验1.修复程序中的BUG 实验2. 表达式求值 2.1填充rules, 2.2 用regex匹配字符串,并将其放入相应的`Tokens`里 2.3 括号检测 pa1 实验1.修复程 ...

  9. 计算机系统基础实验——数据的机器级表示

    实验2 数据的机器级表示 一 .求绝对值的函数 二. 求和函数addOK 三. 条件表达式x?y:z 四. 计算浮点数f的绝对值[f] 一 .求绝对值的函数 题目要求 /* *abs Val- 求x的 ...

最新文章

  1. 2018.10.26 NOIP模拟 瓶子 (dp/贪心)
  2. 【转载】ABAP中数据和对象的动态创建和调用
  3. 着墨中文lisp登入_Lisp的本质 - climbdream的个人空间 - OSCHINA - 中文开源技术交流社区...
  4. linux网络编程之用select方法实现io复用(基于udp)
  5. c均值算法的设计与实现_如何使用C链表实现 LRU 算法
  6. 安卓签名生成工具_ios app如何进行内测?ios app和安卓app的内测有何区别?
  7. [BZOJ3211] 花神游历各国 - 线段树
  8. Ubuntu20.04安装eBPF BCC
  9. Json学习总结(4)——Json基础知识回顾
  10. vce 题库导入_Visual CertExam(VCE)试题制作教程.pdf
  11. 酷睿i9 12900HX性能怎么样 i912900hx相当于桌面什么cpu
  12. iMac一体机安装苹果和Win7双系统
  13. python爬取喜马拉雅音频
  14. SpringBoot实现Java高并发秒杀系统之Service层开发(二)
  15. C语言程序设计案例式教程
  16. 如何为您的入耳式监听器制作定制的硅胶耳模
  17. JavaScript 静态方法
  18. 中国好SaaS走进海尔:企业关注重心从纯模式创新回归资源竞争
  19. 『互联网架构』软件架构-git服务搭建与使用(四)
  20. matebook13 java开发_紧急要跑程序?华为 MateBook X Pro一键搞定立马进状态

热门文章

  1. 同城app开发功能模块
  2. 【滤波】粒子滤波(PF)
  3. c语言与程序设计曹计昌pdf,C语言与程序设计
  4. 外贸收款 工具对比
  5. 带头结点的头插法和尾插法创建单链表
  6. idea更改本地依赖位置Libraries仍然爆红解决方案
  7. 出错解决 | Error: cannot allocate vector of size 109.7 Mb
  8. 用OpenCV的SVM实现简单的手势识别(切水果)[附源码]
  9. u722java应用怎么删除_给新手来聊聊我的中兴U722的缺点和性能怎么样
  10. 应用人脸活体检测技术,可避免人脸识别系统被攻击