问题描述

炸弹实验

实验目的

本次实验为熟悉汇编程序及其调试方法的实验。
实验内容包含2个文件bomb(可执行文件)和bomb.c(c源文件)。
实验主题内容为:程序运行在linux环境中。程序运行中有6个关卡(6个phase),每个phase需要用户在终端上输入特定的字符或者数字才能通关,否则会引爆炸弹!那么如何才能知道输入什么内容呢?这需要你使用gdb工具反汇编出汇编代码,结合c语言文件找到每个关卡的入口函数。然后分析汇编代码,找到在每个phase程序段中,引导程序跳转到“explode_bomb”程序段的地方,并分析其成功跳转的条件,以此为突破口寻找应该在命令行输入何种字符通关。
实验需要用到gdb工具,可到网上查找gdb使用方法和参数。

实验环境

Ubuntu 16.04 32位

实验内容及步骤

一条来自老学姐的忠告:
说实话这个炸弹实验还是蛮有趣的,建议大家自己多尝试,实在没有思路了再来看网上的解决方案,而且做完以后分析汇编的能力真的大幅度提升呐!!!还有还有,做这个实验一定要一鼓作气,最好是找一天专门来拆,还有隐藏关,别被它吓到,其实不难,主要是看如何进去。
好啦,学姐不唠叨啦
下面咱们继续学习之旅
我爱学习!!!!

【实验原理】
二进制炸弹是作为一个目标代码文件提供给学生们的程序,运行时,它提示用户输入6个不 同的字符串。如果其中任何一个不正确,炸弹就会“爆炸”:打印出一条错误信息。学生通过反汇 编和逆向工程来确定是哪六个字符串,从而解除他们各自炸弹的雷管
【实验过程】
一、准备阶段
1、下载好32位的实验代码后,将文件解压缩并且通过共享文件夹操作将文件添加到虚拟机中,双击查看bomb.c代码,将c代码完整看了一遍,发现看这里的c代码是无从下手的,代码中只含有主函数,触发炸弹的过程被隐藏了起来。阅读老师给出的readme文件后,得知本题需要在Linux终端中对汇编代码进行分析并且调试才能得出答案。
2、输入objdump -d bomb,将可执行文件反汇编成汇编文件,为方便查看,可以使用objdump -d bomb >1.txt将汇编代码输出到txt文档里
3、试探一下炸弹爆炸的效果,gdb调试该可执行文件,随便输入一个字符串,果然爆炸了

二、开始拆炸弹
首先找到main函数,发现它调用了从phase1到phase6这六个函数。这几个函数就是每一关需要看懂的函数。
第一关:首先找到phase1,其代表的应该是第一关,代码如下:

首先进行汇编代码的分析,首先是esp指针向下移,创造了一个更大的空间,然后代码$0x804a1e4,0x4(%esp)有立即数,是将该地址的值传递到%esp+0x4的位置,输入gdb bomb 进入调试状态,使用x/s 0x804a1e4查看该地址的内容,回车显示处字符串“I am not part of the problem. I am a Republican.”,下面的代码语句mov 0x20(%esp),%eax是将输入的字符串放进%eax中,然后下面一句是将其放进%esp中,再调用函数<string_not_equal>,容易推测得出要输入的应该是地址0x804a1e4的内容。
je是如果等于则跳转,test %eax %eax是将两者进行逻辑与运算。分析可知,如果%eax!=0时,会调用<explode_bomb>。
验证:设置断点b phase_1,输入run运行,进入程序,在输入提示的下一行输入“I am not part of the problem. I am a Republican.”,终端显示“phase 1 defused. How about the next one?”,第一关顺利通过。

第二关:找到phase2,其代表第二关,汇编代码如下:

下面进行汇编代码的分析:首先很容易观察到在phase_2中存在对于函数<read_six_number>的调用,通过分析可知第二关需要输入六个正确的数字,数字怎么推算出来就需要看下面的汇编代码了。
jns 8048bf5 <phase_2+0x41>是比较%esp+0x18与0,如果%esp+0x18不为负则跳转,如果为负则会引发炸弹。%esp+0x18是我们需要输入的第一个数,推测得知这里需要输入一个非负数,这里我按照了自己的喜好选择了喜欢的1,然后跳转到一个循环,第二个数到第六个数都由循环推测出。首先将eax与ebx置1,随后的关键指令是add 0x14(%esp,%ebx,4),%eax与cmp %eax,0x18(%esp,%ebx,4),判断当前输入的数与上一个数+当前%eax的值是否相等,不等就会触发炸弹。随后eax与ebx加1,继续循环,直到不满足循环条件.
设几个数为num[1]-num[6],其中num[1]为非负数,num[2]至num[6]的规律可以用以下等式来概括:num[n]=num[n-1]+n-1
验证:终端输入“1 2 4 7 11 16”显示“That’s number 2. Keep going!”第二关成功通过。

第三关:找到phase_3,其汇编代码如下:

下面进行汇编代码的分析:
首先能很明显的发现函数scanf的调用,在调用函数之前,注意到存在立即数寻址:movl $0x804a23e,0x4(%esp)。输入指令x/s 0x804a23e,查看到该地址存放的内容为:%d %c %d:

即输入三个内容,两个数字加一个字符。cmp $0x2,%eax表示必须输入至少两个参数。往下到达cmpl $0x7,0x28(%esp)与ja 8048d41 <phase_3+0x140>,输入的第一个参数必须小于7,否则会爆炸。再往下可以看到jmp 0x804a260(,%eax,4),这里是典型的switch语句,即跳转到以地址0x804a260为基址的跳转表中。输入p/x *0x804a260,可以查看到对应的地址为0x8048c50。

为简单起见,我的第一个参数选择0,则这里计算出来的地址是0x8048c50,找到该地址,执行指令mov $0x78,%eax以及cmpl $0x39f,0x2c(%esp),推测%esp+2c的值必须等于0x39f,接下来跳转到0x08048d4b,是cmp 0x27(%esp),%al,推测%esp+0x27的值应该等于%al的值,%al即%eax的低8位,也就是跳转之前赋值的0x78。于是得出结论,在输入的第一个数为0的情况下,答案分别为0 x 927。
下面使用Linux终端验证:
输入0 x 927 ,回车显示“Halfway there”,第三关成功通过。

第四关:找到phase_4,其汇编代码如下:

下面进行汇编代码的分析:
首先找到movl $0x804a3cf,0x4(%esp),这里又是一个立即数,使用gdb调试查看该地址的值,显示出“%d %d”,可以推测出这一关是需要输入两个数。接着判断scanf函数的返回值,必须要输入两个参数。接下来:cmpl $0xe,0x18(%esp)要求第一个数必须首先满足小于0xe的条件,接下来又调用了函数func4(),此函数的汇编代码如下:

调用函数func4()后的返回值必须要小于等于3,所以这里有对于第一个数有了更进一步的限制,分析func4()的功能,发现其实际上是一个递归,将其转换为c语言,由于计算递归比较麻烦,所以我使用了代码来计算出所有满足要求的数。

运行发现结果有:12,13,所以第一个数的取值情况只有12或者13两种。对于第二个要输入的数,cmpl $0x3,0x1c(%esp)限制了第二个输入的数只能为3。
验证:取其中一种答案组合:13,3,回车显示“So you got that one. Try this one”,第四关成功通过。

第五关:找到phase_5,其汇编代码如下:

下面进行汇编代码的分析:
由string_length和之后的cmp $0x6,%eax可以推测要输入一个长度为6的字符串。接下来是一个循环,首先将edx与eax置0,然后每次循环eax加1,直到6时退出循环,每次循环中movzbl (%ebx,%eax,1),%ecx以及and $0xf,%ecx即依次取出字符串中字符的最后一个字节,然后将这个值与0x0804a280相加后的地址里的值累加到最后的值与0x45比较。现在分析到这样的程度凑答案是很难的,使用gdb查看0x0804a280开始的16个地址分别存储的值(因为是十六进制)

查看ASCII码表的a到z的低四位,与上面的相对应。这时候拼凑就相对更容易,凑出来0x45=0xe+5*0xb。也就是对应的jlllll。
验证:Linux终端输入jlllll,回车显示“Good work! On to the next…”,第五关成功通过。

第六关:找到phase_6,其汇编代码如下:


下面进行汇编代码的分析:
首先依然是快速浏览一遍先搞清楚本关的目的,call 80491dc <read_six_numbers>表明本关又是需要输入六个数。紧随其后是一个略复杂的循环,循环中第一个关键部分是sub $0x1,%eax, cmp $0x5,%eax以及jbe 8048e9c <phase_6+0x2f>,也就是每个数都必须小于等于6,第二个关键部分的语句是一个嵌套的循环,mov 0x10(%esp,%ebx,4),%eax, cmp %eax,0xc(%esp,%esi,4),此部分的意思是对于每一次循环当前数的后面的数都不能等于它,一句话总结就是六个数互不相等且小于等于6.
判断每个数互不相等后,接着跳转到了地址0x8048ee3,此部分的代码过于复杂,我解题的时候是靠猜测的。分析到mov $0x804c13c,%edx时,发现又有立即数,本着在炸弹实验中不能放过任何一个立即数的原则,打开终端尝试输入“x/s 0x804c13c”以字符串的格式查看内容,但是输出的内容非常奇怪,又尝试“x/50w 0x804c13c”将从地址0x804c13c开始的50句打印出来,输出的内容依然看不懂,于是参考了资料,发现这里的地址原来是一个链表的指针,于是尝试输入“p/x *0x0804c13c@32”,查看列表内容,结果如下图所示:

三个数一组,第一个数是一个权值,第二个数按照123456排序下来,第三个数是下一个节点的首地址。中间那段代码我只看懂了一部分,cmp %eax,(%ebx),jge 8048f32 <phase_6+0xc5>,此部分的代码存在很多比较与移动数据,推测可能是在排序,具体按照什么排序,又猜测可能是按照权值在排序,在此列表中按照权值排序得出的答案是:6 2 5 3 4 1
验证:在终端中输入6 2 5 3 4 1,回车显示“Congratulations! You’ve defused the bomb!”第六关成功通过。炸弹成功拆除咯!

隐藏关:
由于phase_defused在之前的关卡中都没有出现过,因此推测其可能与隐藏关有关,下面对其进行分析:
以下是汇编代码:

根据上面的经验,对所有立即数都进行值的查看,可以得到:

这个说明了参数要有两个整数,一个字符串

有一个判断字符串相等的函数,查看地址内容可知第四关后面要输入DrEvil才开始隐藏关。

Secret_phase汇编分析:

下面对函数fun7进行分析,fun7的返回值要为3,查看fun7汇编代码;
将其转换为c++代码,

此函数会用于对一颗二叉树进行查询操作,最初传入函数的那个地址就是根结点的地址,具体的返回值来说就像代码中写的那样,当当前节点的值等于查询操作时,返回0,否则根据值的大小判断是继续查询左子树还是右子树。
二叉树的存储如下:

要思考得到3,方法有2*(0*2+1)+1,即二叉树遍历顺序为右右,据此,应该输入0x6b,即十进制下的107。
验证:输入107,显示“Wow, you ‘ve defused the secret stage!”

至此,全部炸弹成功解除!

计算机系统实验2:炸弹实验bomb相关推荐

  1. CSAPP实验二:二进制炸弹(Bomb Lab)

    本系列文章为中国科学技术大学计算机专业学科基础课<计算机系统>布置的实验,上课所用教材和内容为黑书CSAPP,当时花费很大精力和弯路,现来总结下各个实验,本文章为第二个实验--二进制炸弹( ...

  2. 计算机系统二进制炸弹实验报告,二进制拿炸弹实验报告完整版.doc

    课程名称:计算机系统原理实验 实验课时:32课时 实验项目名称:BombLab二进制炸弹 实验材料:可执行文件bomb.源代码bomb.c.说明README 实验环境:Linux操作系统(安装虚拟机和 ...

  3. 哈工大 计算机系统 二进制炸弹实验报告

    实验报告 实 验(三) 题     目 Binary Bomb 二进制炸弹 专       业 计算机学院 学    号 班    级 学       生 指 导 教 师 实 验 地 点 实 验 日 ...

  4. 计算机系统实验-缓冲区炸弹

    计算机系统实验-缓冲区炸弹 概述 Trojan1 Trojan2 Trojan3 Trojan4 概述 攻击指令:0XDDDBBFFF #include <stdio.h> #includ ...

  5. 计算机系统(1) 实验五 中断实验

    计算机系统(1) 实验五 中断实验 一.实验目的 二.实验背景及要求 (一)实验背景: (二)实验要求:实现三部分程序 1.用户程序: 2.键盘中断处理程序: 3.操作系统使能代码: 三.实验步骤 1 ...

  6. 微型计算机系统原理及应用实验,微型计算机系统原理及应用实验报告 .doc

    微型计算机系统原理及应用实验报告 微型计算机系统 原理及应用 ---实验报告--- 实验题目: 8255并行接口 学 院: 信息科学与技术学院 班 级: 姓 名: 学 号: 一.实验目的 学习和掌握8 ...

  7. 计算机系统(1)实验二 LC-3机器码编程实验

    计算机系统(1)实验二 LC-3机器码编程实验 文章目录 计算机系统(1)实验二 LC-3机器码编程实验 实验目的 实验内容与实验要求 实验步骤 程序代码及注释 实验结论 实验目的 1.分析和理解试验 ...

  8. 计算机系统硬件认识步骤,实验一 微型计算机系统硬件组成及外设认识指导书.doc...

    文档介绍: 实验一 微型计算机系统硬件组成及外设认识指导书.doc实验一微型计算机系统硬件组成及外设认识[实验目的]了解微型机系统的硬件组成与配置培养对微型机硬件各组成部件的识别能力为实验二计算机硬件 ...

  9. 计算机系统(2) 实验四 缓冲区溢出攻击实验

    计算机系统(2) 实验四 缓冲区溢出攻击实验 一. 实验目标: 二.实验环境: 三.实验内容 四.实验步骤和结果 (一)返回到smoke (二)返回到fizz()并准备相应参数 (三)返回到bang( ...

  10. 计算机系统(1)实验二 LC-3机器码编程试验

    实验二 LC-3机器码编程试验 实验目的: 实验内容: 实验要求: 实验步骤 实验结论: 实验目的: 熟悉和理解LC-3的机器指令格式. 进一步掌握在LC-3仿真平台下机器代码的设计输入和调试过程. ...

最新文章

  1. 全栈技术实践经历告诉你:开发一个商城小程序要多少钱?
  2. 有序数组二分查找java_详解Java数据结构和算法(有序数组和二分查找)
  3. 给Java初学者的十条小建议,快来收藏吧
  4. matlab机械臂工作空间代码_老外研发模拟肌肉运动的机械臂,与人类协同工作动作完美同步...
  5. vim编辑模式_sublime vim模式和快捷键
  6. java 抛出空指针_java - Java ServerSocket抛出空指针异常 - 堆栈内存溢出
  7. C语言 底层IO readwrite
  8. 微波网络转移参量[A]表示阻抗矩阵[Z]和导纳矩阵[Y]
  9. VB+ACCESS酒店服务管理系统
  10. 点击发票填开就出现金税盘处于报税期,不能开票,怎么回事呢?
  11. 基于AM5728 DSP+ARM平台的嵌入式车牌识别
  12. 广州岑村科目二a考场,第一次考满分通过
  13. 亚马逊员工的至暗时刻:1.5W人血淋淋的裁员开始..
  14. android 夜间模式功能,Android 夜间模式的三种实现
  15. 万字HTTP学习笔记
  16. java double输出 lf_为什么double类型输入(scanf)用%lf,输出(printf)用%f?
  17. Gstore官网学习二:安装(笔者自带填坑)
  18. Matlab + Gurobi入门
  19. SQL中CONVERT()函数用法详解
  20. C#接口与继承的区别

热门文章

  1. Factory method 'dataSource' threw exception; nested exception is java.lang.NullPointerException
  2. 盘搜和网盘资源搜索神器——又落后了
  3. appinventor计算机教程,App Inventor编程开发集锦2-计算器-第2课-实现常规操作
  4. python模拟抛硬币_1-简单的Python程序-模拟抛硬币
  5. rebase操作使用方法
  6. 2019.6.24 校内测试 NOIP模拟 Day 2 分析+题解
  7. 已知 XYZ+YZZ=532,其中,X、Y、Z 为数字,编程求出 X、Y 和 Z 的值。
  8. 一步步教你Windows配置ISCSI共享存储
  9. UFS和EMMC的区别--原理学习
  10. incre在c语言,longest incresing sequence