计算机系统实验四:二进制程序逆向工程

参考教材:计算机系统基础 第二版 袁春风 机械工业出版社
参考慕课:计算机系统基础(四):编程与调试实践 https://www.icourse163.org/learn/NJU-1449521162

计算机系统实验导航

实验一:环境安装 https://blog.csdn.net/weixin_46291251/article/details/122477054

实验二:数据的存储与运算 https://blog.csdn.net/weixin_46291251/article/details/122478255

实验三:程序的机器级表示 https://blog.csdn.net/weixin_46291251/article/details/122478979

实验四:二进制程序逆向工程 https://blog.csdn.net/weixin_46291251/article/details/122479554

实验五:缓冲区溢出攻击 https://blog.csdn.net/weixin_46291251/article/details/122479798

实验六:程序的链接 https://blog.csdn.net/weixin_46291251/article/details/122480049

实验源码: xxx

准备

实验内容:

1 二进制炸弹实验的内容、方法和基本步骤;
2 程序机器级表示、分析与调试基本知识和方法的应用。

实验目标:

1 加深对程序的机器级表示、汇编与反汇编、二进制程序分析与调试、逆向工程等方面知识
的理解和掌握;
2 从程序员角度认识计算机系统,分析高级语言对应的机器行为及其对程序执行结果和性能
的影响,解决计算机系统设计、程序开发过程中的关键问题。
3 掌握各种开源的编译调试工具。

实验任务:

1 学习 MOOC 内容

https://www.icourse163.org/learn/NJU-1449521162
第五周 二进制程序逆向工程
第 1 讲 二进制炸弹实验:概述
第 2 讲 二进制炸弹实验:字符串比较
第 3 讲 二进制炸弹实验:浮点数表示
第 4 讲 二进制炸弹实验:课后实验

2 完成作业

一个二进制炸弹是-个Linux 可执行程序,包含了多个阶段(又称为层次、关卡)。在炸
弹程序运行的每个阶段要求输入一个特定字符串,如果该输入字符串符合程序的要求,该阶段的炸弹就被拆除了,否则炸弹“爆炸_即打印输出 “BOM!!” 的提示。
每个炸弹阶段考察了程序与数据的机器级表示的不同方面,难度逐级递增:
●阶段0:字符串比较
●阶段1 :浮点数表示
●阶段2 :循环
●阶段3 :条件/分支
●阶段4 :递归调用和栈
●阶段5:指针
●阶段6 :链表/指针/结构
●另外还有一个隐藏阶段作为阶段7,只有在阶段4的拆解字符串后附加一特定字符串后,才能在实验最后进入隐藏阶段。

实验的目标是拆除尽可能多的炸弹关卡一分析获得 尽可能多的正确拆解字符串。

运行二进制炸弹可执行程序bomb需要指定0或1个命令行参数(详见bomb.c源文件中
的main0函数):
如果运行时不指定参数,则程序打印出欢迎信息后,期望你按行输入每-阶段用来拆
除炸弹的字符串,程序根据输入字符串决定是通过相应阶段还是引爆炸弹导致该阶
段任务失败。
也可将拆除每一炸弹阶段的字符串按行(- 行-个字符串)记录在一个文本文件(必
需采用Unix/Linux换行格式)中(即实验结果提交文件的形式),然后将该文件作为
运行二进制炸弹程序时的唯- -命令行参数,程序将依次检查对应每一阶段的字符 串
来决定炸弹拆除成败。
注意:如果拆解字符串(来自命令行输入或文本文件)不正确导致相应炸弹阶段被引爆,
程序在输出炸弹爆炸的提示文字“BOM!!” 后,将进入下一阶段的字符串检查(等待命令行
输入或读取文件下一行)而不会终止程序的运行。因此,如果暂时未能正确获得某阶段的拆解字符串,可用任意非空字符串(即不同于空格、制表、换行的一个以上字符)临时作为拆解字符串,从而在引爆相应炸弹阶段后,跳到以后阶段继续开展实验。

phase0:字符串

实验结果记录

首先将实验文件中的bomb文件反汇编得到bomb.s文件
在这里插入图片描述

进入bomb.s找到phase_0函数的入口:
这里利用less打开文件,然后输入/phase_0搜索关键词,然后按N快捷键找到匹配的函数入口位置(这里是第二次出现的位置),这样就找到了phase_0的汇编代码,如下图所示:
在这里插入图片描述

分析phase_0的汇编代码,以了解其执行逻辑:
第一行汇编语句是push %ebp,目的是将ebp寄存器在main函数中的旧值压入栈中保存。
然后第二条汇编指令 mov %esp %ebp,把保存了ebp旧值的存储单元地址作为当前栈帧的起始地址,并保存于栈帧基址寄存器ebp中。执行完后,ebp中就存放了phase_0的栈真的起始地址。以后就可以用ebp的地址加偏移量来定位phase_0的各个成员以及其实参的存放位置。
下面两条sub语句分别从栈顶指针寄存器esp中减去了0x8,它们实际上完成了对栈帧空间的分配和。
接下来的三条语句分别是push、pushl和call语句。
在这里插入图片描述

这三条语句完成了对一个名为strings_not_equal的调用,且这个函数位于0x8049c61这个偏移量上。其中第一个push语句把函数的最后一个参数值为常量0x804a1e0的地址压入栈中,第二个pushl语句把函数的第一个参数(ebp寄存器+0x8地址对应的内容,实际上是传递给phase_0函数的第一个参数的值)压入栈中。
Call函数访问了strings_ not equal函数,分析该函数的汇编代码可知:该函数如果输入的两个字符串参数的内容相同, strings_ not equal函数将返回0。
接下来的test指令测试eax寄存器即strings_ not equal函数的返回值是否为0。
在这里插入图片描述

Test如果成立,则在示例汇编代码中, test指令测试时, 将使得je指令跳转到程序的正常结束位置。反之,如果两个字符串的内容不一致,将调用explode. bomb函数引爆炸弹。
故可知成功解开炸弹的关键是通过test,而test是判断strings_ not equal返回0,strings_ not equal返回0的条件是判断的两个字符串相等,这两个字符串一个是程序读入的钥匙,另一个是位于0x804a1e0的一个内置字符串
在这里插入图片描述

所以可以推断,位于0x804a1e0的字符串就是题目的解。
下面通过gdb调试的方法查看位于0x804a1e0的内置字符串的具体值。

结果分析与讨论

打开gdb调试程序,断点设置在phase_0里面调用strings_not_equal函数的额call指令的位置
在这里插入图片描述

由反汇编文件得知其位于0x8049465的位置,在这个位置设置断点然后开始运行。
运行后程序要求输入字符串,随便输入一个字符串后程序运行到断点的位置。
然后利用x

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Cheney822

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值