计算机系统_炸弹(boom)实验/逆向工程实验(phase_1)

一、实验要求

       本实验设计为一个黑客拆解二进制炸弹的游戏。我们仅给黑客(同学)提供一个二进制可执行文件bomb_64和主函数所在的源程序bomb.c,不提供每个关卡的源代码。程序运行中有6个关卡(6个phase),每个关卡需要用户输入正确的字符串或数字才能通关,否则会引爆炸弹(打印出一条错误信息,并导致评分下降)!
       要求同学运用GDB调试工具和objdump反汇编工具,通过分析汇编代码,找到在每个phase程序段中,引导程序跳转到“explode_bomb”程序段的地方,并分析其成功跳转的条件,以此为突破口寻找应该在命令行输入何种字符串来通关。

二、实验说明

6个关卡,难度随关卡升级而提升;
通过解读汇编代码来推断其对应的函数结构(推断过程不唯一),某些关卡答案不唯一;
尽力而为,能通几关就几关。
提示:
第一关(知识点:string,函数调用,栈)
第二关(知识点:循环语句,数组)
第三关(知识点: switch语句)
第四关(知识点:递归)
第五关(知识点:字串变换,ascii转换,寻址)
第六关(知识点:寻址)

(第1-5关,各15分。第6关10分。实验总结15分。)

注1:
当前用户可能对bomb文件没有执行权限,建议先用ls查看文件权限,若没有执行权限,请用chmod +x bomb命令增加当前用户对bomb文件的执行权限。
注2:

   若用命令./bomb执行该文件提示no such file时,请先用 su szu 切换到szu账户,然后输入命令sudo apt-get install lib32z1,等待下载安装完毕即可。

三、实验环境:
1. 计算机(Intel CPU)
2. Linux64位操作系统(Ubuntu 17)
3. GDB调试工具

4. objdump反汇编工具

四、实验方法与步骤

1. 首先对bomb文件进行反汇编,并将结果输出到1.txt。

$ objdump -d bomb_64 > 1.txt
2. 为方便查阅汇编代码,在图形化界面中将txt结果用文本编辑器打开。(此步骤仅为了方便查看代码,你可以将代码copy到你常用的编译器上查看)
3. 已知本实验共有6个关卡,通过对bomb.c的C程序代码的浏览,发现只需要对汇编代码的所有phase部分加以解读就可以了。下面先开始第一关,打开txt,定位到phase_1函数处。
汇编代码如下:(举例分析)
0000000000400e70 <phase_1>:
400e70:	48 83 ec 08          	sub    $0x8,%rsp
400e74:	be f8 1a 40 00       	mov    $0x401af8,%esi
400e79:	e8 bf 03 00 00       	callq  40123d <strings_not_equal>
400e7e:	85 c0                	test   %eax,%eax
400e80:	74 05                	je     400e87 <phase_1+0x17>
400e82:	e8 b6 07 00 00       	callq  40163d <explode_bomb>
400e87:	48 83 c4 08          	add    $0x8,%rsp
400e8b:	c3                   	retq

2~4行部分代码是对字符串进行比较

第5行测试%eax == 0,相等为0

第7行引导程序跳转到“explode_bomb”程序段的地方

【代码分析】

首先是为新函数开辟一个帧,申请0x48的内存空间。

400e70:	48 83 ec 08          	sub    $0x8,%rsp
400e74:	be f8 1a 40 00       	mov    $0x401af8,%esi

接下来调用了0x400e79位置的函数 <strings_not_equal>,从函数名可以看出这是一个判断字符串是否相等的函数。继续往下看,后两行的test+je指令,实现的功能是判断eax中的值是否为0,若为0,则跳转到0x400e87位置的add    $0x8,%rsp指令,即0x400e8b的retq。

函数的执行结束,否则调用<explode_bomb>函数,即引爆炸弹。这说明如果发生跳转,即eax中的值为全0时,字符串才是成功匹配的,再查看<strings_not_equal>函数的内容可以发现,如果两字符串相等,那么eax的值就会变为全0的状态。可以推测出,进行比较的两个字符串分别是来自内存地址为0x401af8位置的字符串和phase_1上级函数的参数。进入gdb调试,对内存0x401af8位置内容以字符串类型查看:

【通关操作】


若是输入错误,则会提示爆炸


【深入分析】

要是单纯只要找答案的童鞋可以略过以下部分!!!

000000000040123d <strings_not_equal>:
  40123d:    48 89 5c 24 e8           mov    %rbx,-0x18(%rsp)
  401242:    48 89 6c 24 f0           mov    %rbp,-0x10(%rsp)
  401247:    4c 89 64 24 f8           mov    %r12,-0x8(%rsp)
  40124c:    48 83 ec 18              sub    $0x18,%rsp
  401250:    48 89 fb                 mov    %rdi,%rbx
  401253:    48 89 f5                 mov    %rsi,%rbp
  401256:    e8 c6 ff ff ff           callq  401221 <string_length>
  40125b:    41 89 c4                 mov    %eax,%r12d
  40125e:    48 89 ef                 mov    %rbp,%rdi
  401261:    e8 bb ff ff ff           callq  401221 <string_length>
  401266:    ba 01 00 00 00           mov    $0x1,%edx
  40126b:    41 39 c4                 cmp    %eax,%r12d
  40126e:    75 36                    jne    4012a6 <strings_not_equal+0x69>
<string_length>:
  401221:    b8 00 00 00 00           mov    $0x0,%eax
  401226:    80 3f 00                 cmpb   $0x0,(%rdi)
  401229:    74 10                    je     40123b <string_length+0x1a>
  40122b:    48 89 fa                 mov    %rdi,%rdx
  40122e:    48 83 c2 01              add    $0x1,%rdx
  401232:    89 d0                    mov    %edx,%eax
  401234:    29 f8                    sub    %edi,%eax
  401236:    80 3a 00                 cmpb   $0x0,(%rdx)
  401239:    75 f3                    jne    40122e <string_length+0xd>
  40123b:    f3 c3                    repz retq

string_length 中的代码:

是以%rdi中的内容为地址,然后与0比较(0即是字符串的终结符号“\0”)。所以字符串起始地址应该藏在%rdi中!

再看 strings_not_equal,分别有两次 string_length 调用,再结合函数名 strings_not_equal,可以想见是我们输入的字符串与藏在程序中的字符串进行比较!所以只要在0x401256,0x401261两处设置断点,打印出以%rdi中内容为起始地址的字符串。其中一个是我们输入的字符串,而另一个就是我们寻找的字符串。

现在,就让我们设置断点实操一下:


由于第一串字符是我们自己输入的,我在这里输入的是“hello bomb_mo!"


可以看到,我们之前得到的答案出现了。


猜你喜欢

转载自blog.csdn.net/xindolia_ring/article/details/80142345