CSAPP lab2 二进制拆弹 binary bombs phase_1
这个实验从开始到完成大概花了三天的时间,由于我们还没有学习编译原理、汇编语言等课程,为了完成这个实验我投机取巧了太多,看了网上很多的解题方法,为了更加深入学习编译反编译,觉得需要从头开始好好梳理一下。这个系列的博客我将按照拆弹个数一个个的分析,应该会有七篇。。。。。。
给出对应于7个阶段的7篇博客
phase_1 https://www.cnblogs.com/wkfvawl/p/10632044.html
phase_2 https://www.cnblogs.com/wkfvawl/p/10636214.html
phase_3 https://www.cnblogs.com/wkfvawl/p/10651205.html
phase_4 https://www.cnblogs.com/wkfvawl/p/10672680.html
phase_5 https://www.cnblogs.com/wkfvawl/p/10703941.html
phase_6 https://www.cnblogs.com/wkfvawl/p/10742405.html
secret_phase https://www.cnblogs.com/wkfvawl/p/10745307.html
解题前准备
Step1:将下载的炸弹包拷贝到Linux主机上;
Step2::使用tar -xvf “bomb名”进行解压;

解压后生成3个文件:
1)README:炸弹所属的用户信息;
2)bomb:二进制炸弹文件;
3)bomb.c:二进制炸弹文件的框架源文件,供解题者参考。
Step3:使用objdump -d bomb对二进制炸弹进行反汇编,并将其保存到一个文本文件中。

注:
1、这里将反汇编生成的文件重定向到asm.txt,后续的解题过程均通过分析该文件进行。
2、本例所有的分析过程均在vim中进行,大家可以使用自己熟悉的工具。
1 phase_1
phase_1要求输入一个字符串,二进制炸弹会判断输入的字符串是否与目标字符串相等。
观察框架源文件bomb.c:

从上可以看出:
1、首先调用了read_line()函数,用于输入炸弹秘钥,输入放置在char* input中。
2、调用phase_1函数,输入参数即为input,可以初步判断,phase_1函数将输入的input字符串与程序内部的炸弹秘钥进行比较。
因此下一步的主要任务是从asm.txt中查找在哪个地方调用了readline函数以及phase_1函数。
1.1 寻找并分析调用phase_1函数的代码
打开asm.txt,在其中搜索phase_1:

从上图可以看出一些信息:
1、第330行:调用了read_line函数;read_line的返回结果(char* input)放置在eax(累加器)寄存器中。(从函数返回的结果一般都放置在eax寄存器中)
2、第331行:将read_line函数的返回结果放置在当前esp(栈指针寄存在)指针指向的栈顶。
3、第332行:在逻辑地址0x8048b47位置调用了phase_1函数。同时也说明了phase_1函数的入口地址为0x8048c00。
4、结合前面bomb.c的分析,从上可以看出第331行,是在为调用phase_1准备参数,我们可以分析出此时函数调用栈的情况:

5、从上面可以看出,phase_1函数入口在虚拟地址0x8048c00,下一步需要分析phase_1函数。
1.2 phase_1函数分析
在asm.txt中寻找8048c00(或者继续寻找phase_1)。
从上图可以看出一些信息:
1、第378行:sub $0x1c, %esp,将函数栈空间扩展了0x1c字节(28个字节)
2、第379行:将0x804a3ec 放置到了esp+4的地方。
3、第381/382行:将input的内容放置到了esp的地方。注:20(%esp)正好是栈中存放input的内容。
4、第383行:调用strings_not_equal函数。
5、显然,第379行以及第381/382行是在为调用strings_not_equal函数准备参数。在调用strings_not_equal函数之前(即382行执行之后,383行执行之前),
函数栈帧变成如下:
6、第384行:test %eax %eax,是对eax寄存器里的内容(string_not_equal函数的返回内容)进行位与操作,如果为0,则置zf标志(零标志)为1;
7、第385行:是一个je指令,je指令判断zf标志(零标志)为1时(也即strings_not_equal函数返回的是0的情况下),跳转到phase_2 + 0x20的地方,即0x8048c20的地方,说明炸弹拆除成功。否则,call 804939b <explode_bomb>,顾名思义,是爆炸炸弹,即拆除炸弹失败。
8、从上面的分析来看,上图中显示的栈帧中,esp的内容是输入的字符串的首地址,而esp + 4的内容是0x804a3ec,应该是在程序中保存的被比较的字符串(即拆弹字符串)的首地址,而按照strings_not_equal的名字来看,如果是不等,则返回1,等则返回0。如果等,代表输入的拆弹字符串是正确的。
C语言伪代码:
int32_t strings_not_equal(int32_t a1, int32_t a2);
void explode_bomb(int32_t a1, int32_t a2);
void phase_1(int32_t a1) {
int32_t eax2;
int32_t v3;
eax2 = strings_not_equal(a1, "Why make trillions when we could make... billions?");
if (eax2 != ) {
explode_bomb(v3, a1);
}
return;
}
所以下一步应该在运行的时候,查看0x804a3ec地址的内容,这即是我们要输入的拆弹字符串。
但为进一步判断我们上面的分析,下面再大致分析一下strings_not_equal函数。
1.3 strings_not_equal函数分析
根据上面的代码,可以看出strings_not_equal函数的地址在0x80490ba的地方。搜索80490ba或者strings_not_equal。


执行第762 - 765行之后,函数栈帧为:

注意:
1、第766行,将esp + 0x14的内容(input(输入字符串首地址))送入到了ebx寄存器,第767行,将esp + 0x18的内容(0x804a3ec)送入到了esi寄存器。验证了我们前面所介绍的0x804a3ec地址所在的地方应该是拆弹字符串所在的首地址。
2、768-770行:求input字符串的长度,结果送入到edi寄存器。
3、771-772行:求0x804a3ec字符串的长度,结果保存在eax寄存器中。
4、773行:将1送入edx,通过后面的分析,可以知道edx存放的是返回结果,也即默认返回结果为1,即不等。
5、774-775行:比较edi和eax的内容,即input字符串与0x804a3ec为首地址的字符串长度进行比较,如果不等,则跳转到strings_not_equal + 0x63的地方:0x80490ba + 0x63 = 0x804911d(此地的指令是将edx的内容送入到eax,并返回,注意第773行,edx的内容被赋值为1),也即返回1,代表两个字符串不等。
6、后面的汇编代码,是逐一比较两个字符串的内容,如果相等,则返回0,如果不等则返回1。
综合前面的分析,以C语言来表示strings_not_equal,其大致含义是:
int32_t string_length(signed char* a1);
int32_t strings_not_equal(signed char* a1, signed char* a2) {
signed char* ebx3;
signed char* esi4;
int32_t eax5;
int32_t eax6;
int32_t edx7;
int32_t eax8;
int32_t eax9;
ebx3 = a1;
esi4 = a2;
eax5 = string_length(ebx3);
eax6 = string_length(esi4);
edx7 = ;
if (eax5 != eax6) {
addr_0x804911d_2:
return edx7;
} else {
eax8 = (int32_t)(uint32_t)(unsigned char)*ebx3;
if (*(signed char*)&eax8 == ) {
edx7 = ;
goto addr_0x804911d_2;
} else {
if (*(signed char*)&eax8 == *esi4) {
do {
++ebx3;
++esi4;
eax9 = (int32_t)(uint32_t)(unsigned char)*ebx3;
if (*(signed char*)&eax9 == )
break;
} while (*(signed char*)&eax9 == *esi4);
goto addr_0x8049118_8;
} else {
edx7 = ;
goto addr_0x804911d_2;
}
}
}
edx7 = ;
goto addr_0x804911d_2;
addr_0x8049118_8:
edx7 = ;
goto addr_0x804911d_2;
}
以上C语言代码基本和汇编代码相对应,可以对照理解。
1.4 寻找拆弹字符串
使用objdump --start-address=0x804a3ec -s bomb,即可查看以0x804a3ec开头的段信息。下图是一个示例,我们可以看出0x804a3ec开头的字符串,正是前面找到的拆弹字符串!
从这里我们也可以看出,所有直接硬编码进入代码的字符串,以只读数据的形式存放在只读数据段中。

CSAPP lab2 二进制拆弹 binary bombs phase_1的更多相关文章
- CSAPP lab2 二进制拆弹 binary bombs phase_6
给出对应于7个阶段的7篇博客 phase_1 https://www.cnblogs.com/wkfvawl/p/10632044.htmlphase_2 https://www.cnblogs. ...
- CSAPP lab2 二进制拆弹 binary bombs phase_4
给出对应于7个阶段的7篇博客 phase_1 https://www.cnblogs.com/wkfvawl/p/10632044.htmlphase_2 https://www.cnblogs. ...
- CSAPP lab2 二进制拆弹 binary bombs phase_5
给出对应于7个阶段的7篇博客 phase_1 https://www.cnblogs.com/wkfvawl/p/10632044.htmlphase_2 https://www.cnblogs. ...
- CSAPP lab2 二进制拆弹 binary bombs phase_3
给出对应于7个阶段的7篇博客 phase_1 https://www.cnblogs.com/wkfvawl/p/10632044.htmlphase_2 https://www.cnblogs. ...
- CSAPP lab2 二进制拆弹 binary bombs phase_2
给出对应于7个阶段的7篇博客 phase_1 https://www.cnblogs.com/wkfvawl/p/10632044.htmlphase_2 https://www.cnblogs. ...
- [逆向工程] 二进制拆弹Binary Bombs 快乐拆弹 详解
二进制拆弹 binary bombs 教你最快速解题,成功拆弹 最近计算机基础课,的实验lab2,二进制拆弹,可以说是拆的我很快乐了(sub n, %hair) 此处头发减n 我刚开始做的时候很是懵逼 ...
- 2016年11月3日JS脚本简介数据类型: 1.整型:int 2.小数类型: float(单精度) double(双精度) decimal () 3.字符类型: chr 4.字符串类型:sting 5.日期时间:datetime 6.布尔型数据:bool 7.对象类型:object 8.二进制:binary 语言类型: 1.强类型语言:c++ c c# java 2.弱类型语
数据类型: 1.整型:int 2.小数类型: float(单精度) double(双精度) decimal () 3.字符类型: chr 4.字符串类型:sting 5.日期时间:datetime 6 ...
- MySQL 二进制日志(Binary Log)
同大多数关系型数据库一样,日志文件是MySQL数据库的重要组成部分. MySQL有几种不同的日志文件.通常包括错误日志文件,二进制日志,通用日志,慢查询日志,等等.这些日志能够帮助我们定位mysqld ...
- CSAPP Lab2: Binary Bomb
著名的CSAPP实验:二进制炸弹 就是通过gdb和反汇编猜测程序意图,共有6关和一个隐藏关卡 只有输入正确的字符串才能过关,否则会程序会bomb终止运行 隐藏关卡需要输入特定字符串方会开启 实验材料下 ...
随机推荐
- 使用C#获取Windows Phone手机的各种数据(转)
转自:http://www.sum16.com/desinger/use-c-sharp-get-windows-phone-information.html 使用C#获取Windows Phone手 ...
- Beta阶段总结博客
Beta阶段的规划 1.完善并做完阿尔法版本 2.美化界面 3.规格化GIt的使用 4.新增登录注册功能 5.与服务器端有了交互,实现了前后端的对接 6.增加了一些特效 7.每个人分了模块并且最后对于 ...
- python 使用csv 文件写入 出现多余空行数据解决方案
因为csv.writerow() 方法会造成读取时每条数据后多一条空数据 解决方案如下: 分为两种情况 python2 和 python3 先说python2版本 with open('xxx.csv ...
- [BUG] python实例化N次类,调用类函数log会输出N遍的bug 解决办法
最近再写DOU用例时,采用的是 unittest测试框架,就涉及到将其它所有模块需要全部在一个 .py文件中进行实例化,然后再运行时发现在控制台中同一个日志信息会打印多次(实例化几次,同一消息就会打印 ...
- 【Ansible 文档】【译文】网络支持
Networking Support 网络支持 Working with Networking Devices 使用网络设备 自从Ansible 2.1开始,你现在可以使用成熟模型 - 编写 play ...
- XSS详解
什么是XSS(跨站脚本攻击) XSS又叫CSS (Cross Site Script) ,跨站脚本攻击.它指的是恶意攻击者往Web页面里插入恶意html代码或者javascript代码,当用户浏览该页 ...
- libco协程库上下文切换原理详解
缘起 libco 协程库在单个线程中实现了多个协程的创建和切换.按照我们通常的编程思路,单个线程中的程序执行流程通常是顺序的,调用函数同样也是 “调用——返回”,每次都是从函数的入口处开始执行.而li ...
- Android MaterialDesign之水波点击效果的几种实现方法
什么是水波点击的效果? 下面是几种不同的实现方法的效果图以及实现方法 Video_2016-08-31_003846 如何实现? 方法一 使用官方提供的RippleDrawable类 优点:使用方 ...
- NRF51822/NRF51802/NRF52810/NRF52811的详解区别
nRF51系列 - 多协议低功耗蓝牙和ANT/ANT+ 和2.4GHz专用系统级芯片 NRF51822-QFAA和NRF51802-QFAA在FLASH RAM的容量没有差别:区别在于:1.接收灵敏度 ...
- Java并发(一)并发编程的挑战
目录 一.上下文切换 1. 多线程一定快吗 2. 测试上下文切换次数和时长 3. 如何减少上下文切换 4. 减少上下文切换实战 二.死锁 三.资源限制的挑战 四.本章小结 并发编程的目的是为了让程序运 ...