CMU-CSAPP-Lab2拆解二进制炸弹

一、 实验目的

1.理解C语言程序的机器级表示。
2.初步掌握GDB调试器的用法。
3.阅读C编译器生成的x86-64机器代码,理解不同控制结构生成的基本指令模式,过程的实现。

二、实验工具

  1. SecureCRT
  2. Linux
  3. Objdump命令反汇编
  4. GDB调试工具

三、实验内容

登录bupt1服务器,在home目录下可以找到Evil博士专门为你量身定制的一个bomb,当运行时,它会要求你输入一个字符串,如果正确,则进入下一关,继续要求你输入下一个字符串;否则,炸弹就会爆炸,输出一行提示信息并向计分服务器提交扣分信息。因此,本实验要求你必须通过反汇编和逆向工程对bomb执行文件进行分析,找到正确的字符串来解除这个的炸弹。

本实验通过要求使用课程所学知识拆除一个“binary bombs”来增强对程序的机器级表示、汇编语言、调试器和逆向工程等方面原理与技能的掌握。 “binary bombs”是一个Linux可执行程序,包含了5个阶段(或关卡)。炸弹运行的每个阶段要求你输入一个特定字符串,你的输入符合程序预期的输入,该阶段的炸弹就被拆除引信;否则炸弹“爆炸”,打印输出 “BOOM!!!”。炸弹的每个阶段考察了机器级程序语言的一个不同方面,难度逐级递增。 

为完成二进制炸弹拆除任务,需要使用gdb调试器和objdump来反汇编bomb文件,可以单步跟踪调试每一阶段的机器代码,也可以阅读反汇编代码,从中理解每一汇编语言代码的行为或作用,进而设法推断拆除炸弹所需的目标字符串。实验2的具体内容见实验2说明。

四、实验步骤及实验分析

1、反汇编并利用SSH Secure Shell Client工具下载反汇编代码

通过ls指令显示当前目录下的文件,找到压缩包bomb115.tar,即目标炸弹。通过tar xvf bomb115.tar解压此压缩包,然后再通过ls显示解压出的文件:bomb、bomb.c和README。

通过objdump –d bomb > bomb.txt将炸弹程序反汇编并重定向到bomb.txt,通过ls显示反汇编出的代码文件bomb.txt。

打开SSH Secure Shell Client工具,登录到远程主机,将远程主机上的文件下载到本机上,便于查看。

2、查看目标文件并做好调试准备

文件介绍:

bomb.txt:反汇编得到的代码文件,也是主要研究的目标文件。

bomb.c:主函数,通过调用每一关的函数实现,未显示每关的具体代码。

bomb:炸弹程序,当调试得出每一关的密码后打开程序运行来拆炸弹。

通过gdb bomb指令进入gdb调试环境。

大致浏览反汇编代码,可以观察到整个程序一共有六关,分别为phase_1到phase_6,并有一关隐藏关secret_phase,每次输入错误时会调用引爆函数explode_bomb,因此为避免调试时引爆炸弹,需要首先在引爆函数前设置断点,即b explode_bomb。

3、拆除炸弹 

1、 第一个炸弹

 

程序流程:

  1. 取内存地址0x4024b0处的内容;
  2. 取用户输入的内容(即密码);
  3. 比较两者的值,相等则%eax置为0,进入下一关,不相等则调用引爆程序引爆炸弹。

破解思路:

通过x/s 0x4024b0指令取出该地址的字符串,得到:Only you can give me that feeling.

则密码为:Only you can give me that feeling.

通过 !

2、 第二个炸弹

 

程序流程:

  1. 读取用户输入内容(为6个数字);
  2. 判断输入的第一个值是否为1,不是则引爆炸弹;
  3. 做一个6次循环,判断后一个数是否等于前一个数加上之前循环变量,不是则引爆炸弹;
  4. 六个数字判断相等结束后,进入下一关

破解思路:

设输入内容为一个数组Key[6],则可知Key[0]=1,Key[i+1]=Key[i]+i。

因此第二关的密码是:1 2 6 24 120 720

3、 第三个炸弹

程序流程:

  1. 读取输入参数1和参数2,调用scanf函数传入两个参数;
  2. 比较参数1与7的大小,小于等于7继续,大于7引爆;
  3. 根据参数1的值来搜索跳转地址,计算得到最终的%eax;
  4. 比较参数1与5的大小,小于等于5继续,大于5引爆;
  5. 比较参数2与计算得到的%eax是否相等,相等则进入下一关,不相等则引爆。

重点在于参数1的选择决定了switch的跳转,该实验地址为(设参数1为x):

0x402510+x*8

其中存在一个Switch函数表,这个炸弹我选择参数1为2,则跳转地址为0x00400f33

Switch跳转到改地址开始计算eax%,最终结果为0x328-0xf7=0x231=561。

输入 2 561。

成功 !

4、 第四个炸弹

 

主程序流程:

  1. 读取2个参数,调用scanf函数传入参数;
  2. 比较输入参数与2的大小,小于则引爆;比较输入参数与4的大小,大于则引爆。
  3. 把输入参数传入函数func4,并调用函数func4;
  4. 若函数func4返回值等于%rsp+0x8,则返回,进入下一关,否则引爆炸弹。

func4函数流程:

1.  比较传入参数是否大于1,大于1则继续,小于1则返回0,等于1则返回%rax;

2.  循环%edi=%edi-1,并递归调用函数func4,直到参数小于等于1;

3.  循环变量%edi=edi-2,并传入%esp继续递归调用函数func4;

4.  函数返回的所得值加到%eax;

设b=%edi,a=%esi,则f(a,b)=f(a,b-1)+f(a,b-2)+a;

第二个参数小于1则返回0,等于1则返回%rax(即a)。

炸弹中默认b=8,我们输入a=2,经过上述式子计算得f(8)=561.

输入108 2 或者162 3。

成功 !

5、 第五个炸弹

 

程序流程:

  1. 输入字符串
  2. 调用string_length的字符串长度函数,测得的长度若不为6则引爆;
  3. 做一个6次的循环,循环变量%eax从1到6,;
  4. 我们要使得 string_not_equal返回值为0 ,也就是%ebp处的值和0x4024fe处的值相等,查看0x4024fe处的值,发现为bruins
  5. 循环赋giant了, 依次改变以%ebp为开始位置的char的数组的值 那么b,r,u,I,n,s就存在于该字符串,寻找改变字符串值的语句。
  6. 取得 (0x8[%ebp]+0xc(%ebp)) &0xf的值,作为下标取得0x402550中的值,查看 0x402550处的内存为 maduiersnfotvbylSo you think you can stop the bomb with ctrl-c, do you?
  7. bruins分别对应 13 6 3 4 8 7 所以要取得13 6 3 4 8 7
  8. 我们输入的内容写成 ASCII码应该是xd x6 x3 x4 x8 x7。x表示任取,随便取得 3d 36 33 34 38 37,对应ASCII码为=63487。输入
  9. 成功 !

猜你喜欢

转载自www.cnblogs.com/shr123-/p/10111765.html