CSAPP 3e: Bomb lab (phase_1)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CSAPP 3e: Bomb lab (phase_1)相关的知识,希望对你有一定的参考价值。
这一个lab拖了好久才开始慢慢完成,花的时间比较多,我也是没想到会需要这么多时间来折腾。考虑到如果把所有关卡的内容都一次发出来,太长了。所以分开操作吧。
然后,有一点是,在开始解题前的确该好好认识一下GDB,因为要使用这个工具。虽然我也感觉有些东西是可以等需要的时候再查的,但是后来找到了一篇介绍gdb命令的,写的比较详细,就下载了打印出来,占用了几节课的时间好好看了一下,就感觉特别有用,比之前更加熟悉了GDB。大概是在网页上看的时候比较急躁,所以吸收不好吧23333。还有,在解题过程中参考了不少网上前辈的资料,向每位分享知识的前辈致敬。
我的操作方法是把程序反汇编到一个文本中,反汇编了两个版本,一个是objdump -d bomb > bomb_disas.s (反汇编bomb中需要执行指令的那些section),另一个是 objdump -D bomb > bomb_disas2.s (反汇编bomb中所有的section). 这个放在Windows系统中,便于查看,分析,主要是感觉notepad++看着舒服啦。然后,调试是在虚拟机中进行的。
关于GDB命令的东西,如果你还没有接触过,那还是先了解一下的好,或者可以在阅读途中碰上了再百度。
在Linux中,gdb bomb用GDB打开bomb,输入list可以查看代码。不过bomb lab 文件夹中也有源码。通过这个可以看到代码中每个关卡的通用格式,比如:
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. */
每一关的函数是phase_x,这里x是关卡数。看第一关的汇编函数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 callq 401338 <strings_not_equal> 400eee: 85 c0 test %eax,%eax
400ef0: 74 05 je 400ef7 <phase_1+0x17>
400ef2: e8 43 05 00 00 callq 40143a <explode_bomb>
400ef7: 48 83 c4 08 add $0x8,%rsp 400efb: c3 retq
一个是 strings_not_eaqual ,一个是 explode_bomb .这里先说这个explode_bomb是解密失败后引发爆炸(bomb)的函数。具体可以自行去调用查看,在bomb_disas.s中查找该函数即可查看其执行过程,不予细说了。然后,这里另一个函数是 strings_not_eaqual .从字面上也可以理解,这个函数是检查两个字符串是否一样。应用就是你输入的字符串如果跟他指向的另一串字符串不一样,就bomb了,请看查看这个函数的代码。
0000000000401338 <strings_not_equal>: 401338: 41 54 push %r12 40133a: 55 push %rbp 40133b: 53 push %rbx 40133c: 48 89 fb mov %rdi,%rbx ;%rdi是储存输入的字符串首地址 40133f: 48 89 f5 mov %rsi,%rbp ;由phase(1)知道;;%rsi是储存拆弹密码字符串的首地址. 401342: e8 d4 ff ff ff callq 40131b <string_length> ;计算字符串长度, 401347: 41 89 c4 mov %eax,%r12d 40134a: 48 89 ef mov %rbp,%rdi 40134d: e8 c9 ff ff ff callq 40131b <string_length> 401352: ba 01 00 00 00 mov $0x1,%edx 401357: 41 39 c4 cmp %eax,%r12d ;字符串长度不一样的话,就bomb. 40135a: 75 3f jne 40139b <strings_not_equal+0x63> 40135c: 0f b6 03 movzbl (%rbx),%eax ;零扩展传递第一个字符到%eax. 40135f: 84 c0 test %al,%al ;第一个为0就ret,以0作为返回值。 401361: 74 25 je 401388 <strings_not_equal+0x50> ;但是要考虑字符串长度,所以0不是正确答案 401363: 3a 45 00 cmp 0x0(%rbp),%al ;对比第一个字符串,相同则进入循环,否则bomb 401366: 74 0a je 401372 <strings_not_equal+0x3a> ;0x401372进入循环。 401368: eb 25 jmp 40138f <strings_not_equal+0x57> 40136a: 3a 45 00 cmp 0x0(%rbp),%al ;循环的起始地址 40136d: 0f 1f 00 nopl (%rax) 401370: 75 24 jne 401396 <strings_not_equal+0x5e> ;第N个字符不相同则bomb. 401372: 48 83 c3 01 add $0x1,%rbx ;所输入字符串向后移一位,为了向后检查 401376: 48 83 c5 01 add $0x1,%rbp ;密码字符串后移,为了向后检查 40137a: 0f b6 03 movzbl (%rbx),%eax ;零扩展传递第N个字符到%eax 40137d: 84 c0 test %al,%al 40137f: 75 e9 jne 40136a <strings_not_equal+0x32> ;第N个字符不是%0,即字符串未结束,则继续循环 401381: ba 00 00 00 00 mov $0x0,%edx 401386: eb 13 jmp 40139b <strings_not_equal+0x63> 401388: ba 00 00 00 00 mov $0x0,%edx 40138d: eb 0c jmp 40139b <strings_not_equal+0x63> 40138f: ba 01 00 00 00 mov $0x1,%edx 401394: eb 05 jmp 40139b <strings_not_equal+0x63> 401396: ba 01 00 00 00 mov $0x1,%edx 40139b: 89 d0 mov %edx,%eax 40139d: 5b pop %rbx 40139e: 5d pop %rbp 40139f: 41 5c pop %r12 4013a1: c3 retq
这里重点就是%rdi存储输入所输入的字符串的首地址,%rsi存储拆弹密码字符串的首地址。
再回过来查看phase_1, 第二行将0x402400赋值给了寄存器%esi。
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 callq 401338 <strings_not_equal> 400eee: 85 c0 test %eax,%eax ;%eax返回值为1就bomb 400ef0: 74 05 je 400ef7 <phase_1+0x17> ;通过查看strings_not_equal函数知道 400ef2: e8 43 05 00 00 callq 40143a <explode_bomb> ;0x402400位置的字符串即为第一关答案. 400ef7: 48 83 c4 08 add $0x8,%rsp ;在gdb中用 x/s 0x402400查看内存即可看到答案。 400efb: c3 retq
在gdb中用 x/s 0x402400查看内存中的字符串就得到了答案。
输入该字符串即可通过第一关。
至此,第一关结束。加油挑战!
对我来说,感觉这bomb lab拖了好久才完成的原因,主要还是在于对GDB工具的不了解,所以弄得是无从下手。所以如果有后来者看到这篇文章,希望你先好好熟悉一下GDB,这样才可以事半功倍。
以上是关于CSAPP 3e: Bomb lab (phase_1)的主要内容,如果未能解决你的问题,请参考以下文章