实验环境
关于环境已经在lab1里配置过了这里主要提醒一下要记得安装gdb
安装命令 sudo yum install gdb
这里我们需要使用objdump -d ./bomb >> bomb.s
反汇编工具来得到汇编代码。
另外,为了方便测试,可以把bomb实验的六个答案写到一个文件里面,测试时,执行./bomb answer.txt。图中的answer.txt文件,该文件中的每一行对应拆解一个炸弹的答案,如下图所示
第一关
通过阅读bomb.c中的main函数,知道这里面的phase_1
就是我们的第一关,然后根据函数名称input = read_line()
;是要验证我们的输入是否合理
/* Do all sorts of secret stuff that makes the bomb harder to defuse. */
initialize_bomb();
printf("Welcome to my fiendish little bomb. You have 6 phases with\n");
printf("which to blow yourself up. Have a nice day!\n");
/* Hmm... Six phases must be more secure than one phase! */
input = read_line(); /* Get input */
phase_1(input); /* Run the phase */
phase_defused(); /* Drat! They figured it out!
* Let me know how they did it. */
printf("Phase 1 defused. How about the next one?\n");
我们先随便输入一个运行起来,看下运行状态。如下图,我们输入as,下方提示BOOM!!爆炸了!!
1、阅读bomb.s代码
找到phase_1函数。
0000000000400ee0 <phase_1>:
400ee0: 48 83 ec 08 sub $0x8,%rsp
400ee4: be 00 24 40 00 mov $0x402400,%esi
400ee9: e8 4a 04 00 00 call 401338 <strings_not_equal>
400eee: 85 c0 test %eax,%eax
400ef0: 74 05 je 400ef7 <phase_1+0x17>
400ef2: e8 43 05 00 00 call 40143a <explode_bomb>
400ef7: 48 83 c4 08 add $0x8,%rsp
400efb: c3 ret
1).第一行,分配phase_1函数栈帧
2).第二行,将0x402400立即数存入第二个参数寄存器esi,rdi参数寄存器内容,由main函数传入,里面存的其实就是我们终端输入的字符串首地址
3).第3行和第4行,调用函数call 401338 <strings_not_equal>,并检测返回值,test %eax,%eax。如果返回值是0,则跳转到je 400ef7指令处,通过释放phase_1函数栈帧,成功返回至main函数;如果返回值是1,则会跳转到call 40143a <explode_bomb>,通过gdb x命令,查看下图0x4025a3地址处内容,显示"\nBOOM!!!"和实际运行拆解炸弹失败时的输出一致。
2、阅读strings_not_equal函数
重点关注esi寄存器,因为我们在phase_1中是将立即数 0x402400传入esi寄存器,在strings_not_equal函数关注第4和第5行代码,这里一个是我们通过终端输入字符串,字符串首地址在rdi寄存器中,一个是rsi寄存器,寄存器内容是0x402400,这里主要是比较这两个地址处的字符串内容是否相同,如果相同就返回0,不同则返回1(代码逻辑不难,大家可以自行研究下),所以我们通过gdb,x/s 0x402400,可以查询到该地址处的内容,如下图所示,这也就是我们第一关的答案。
3.测试
gdb中,可以通过run命令运行,我把第一关答案写到了answer.txt文件中(也可以手动通过终端控制台进行输入),可以看到第一关的炸弹已经拆解了。