大家千万不要着急,不要慌张,即使自己并不了解多少汇编代码的知识,即使自己计基课上的基础知识学的并不扎实,也都不要紧,因为这次计基实验考察的重点并不是基础知识,而是对gdb工具的掌握,以及心细的程度,所以不要害怕,你只管往前走,走到地方了你就知道该怎么做了。
既然我们已经破解了phase_1和phase_2,那么我们不妨将断点打在phase_3上。然后使用命令"r"执行bomb可执行文件,接着输入已破译的phase_1和phase_2答案字符串,接着随便输入"111"作为答案字符串,然后一路"ni",直到 图1:通过'%d %d',我们似乎了解到了什么 所示。既然在phase_2中,我们已经知道了,__isoc99_sscanf@plt这个函数,会将(%esp)的字符串按照(%esp+4)的格式进行读取,也就是将'111'按照'%d %d'进行读取,那么我们不妨退出gdb,重新随便输入'8 9'作为phase_3的答案字符串,然后一路"ni"到当前这个位置,如 图2:退出gdb,重新随便输入'8 9'作为phase_3的答案字符串,然后一路"ni"到当前这个位置 所示
(图1:通过'%d %d',我们似乎了解到了什么)
(图2:退出gdb,重新随便输入'8 9'作为phase_3的答案字符串,然后一路"ni"到当前这个位置)
既然我们随便输入的phase_3的答案字符串是'8 9',能够顺利按照'%d %d'的形式进行读取,那么我们可以大胆的"ni",一直到 图3:判断第一个整数 所示。我们发现,如果(%esp+4)的值大于7,也就是我们输入的第一个整数的值大于7,那么程序就会跳到第
(图3:判断第一个整数)
(图4:重新输入phase_3的答案字符串为'7 8',然后重新启动gdb,一路"ni"到现在的位置)
接着继续"ni"下去,直到 图5:第二次判断第一个整数 所示。第一个整数的值同时还应该小于5,所以我们重新输入phase_3的答案字符串为'4 8',然后重新启动gdb,一路"ni"到现在的位置,如 图6:重新输入phase_3的答案字符串为'4 8',然后重新启动gdb,一路"ni"到现在的位置 所示。
(图5:第二次判断第一个整数)
(图6:重新输入phase_3的答案字符串为'4 8',然后重新启动gdb,一路"ni"到现在的位置)
接着继续"ni",直到 图7: 判断第二个整数 所示。
(图7: 判断第二个整数)
在这里,我们必须要跳到第
(图8:重新输入"4 0"作为phase_3的答案字符串,然后一路"ni"到当前位置)
接着继续"ni"下去,当出现如 图9:成功攻破phase_3 所示的界面时,就证明我们成功找到了phase_3的答案字符串啦!到现在为止,我们找出的答案字符串为:
I turned the moon into something I call a Death Star.
0 1 1 2 3 5
4 0
(图9:成功攻破phase_3)
接着phase_4,我们将断点打在phase_4上,然后随便输入'111'作为答案字符串,观察此时的gdb,如 图10:开始攻破phase_4 所示。
(图10:开始攻破phase_4)
接着一路"ni"下去,直到如 图11:仍然让我们输入两个整数 所示的情况出现,我们仿照着前面的做法,重新输入"4 0"作为phase_4的答案字符串,然后再"ni"到当前位置,如 图12:照着前面的做法,重新输入"4 0"作为phase_4的答案字符串,然后再"ni"到当前位置 所示。
(图11:仍然让我们输入两个整数)
(图12:照着前面的做法,重新输入"4 0"作为phase_4的答案字符串,然后再"ni"到当前位置)
接着一路"ni"下去,直到如 图13:当第一个整数小于等于14时,不会引爆炸弹 所示的情况出现时,停下来分析。在这里其实隐藏了第
(图13:当第一个整数小于等于14时,不会引爆炸弹)
(图14:调用func4函数)
(图15:成功拆除phase_4)
至此,我们获得的所有答案为:
I turned the moon into something I call a Death Star.
0 1 1 2 3 5
4 013 31
接着phase_5。我们自己尝试过几次之后,得到了如下的思路:phase_5的要求是什么呢?phase_5要求我们输入六个字符,比如我们输入的是"abcdef”,因为'a'的ASCII码值的16进制表示为0x61,接着让0x61&0x0F,接着将这个结果乘以4加到0x565581e0之上,也就是0x565581e0+0x4=0x565581e4,然后在内存中找到地址为0x565581e4的内容,将这个内容加到sum上,而0x565581e4的内容为0x0000000a,所以sum=0xa;接着第二个字符是'b',因为'b'的ASCII码值的16进制表示为0x62,接着让0x62&0x0F,接着将这个结果乘以4加到0x565581e0之上,也就是0x565581e0+0x8=0x565581e8,然后在内存中找到地址为0x565581e8的内容,将这个内容加到sum上,而0x565581e8的内容为0x00000006,所以sum=0xa+0x6=0x10... ...重复处理'c','d','e','f',得到了sum的值。而最终能够成功拆弹的要求是,sum的值应该为41D,那么如何才能得到41D呢?可以8+8+8+8+8+1,而哪个内存地址中的内容为8,哪个内存地址中的内容又为1呢?如 图16:不同内存地址中的数 所示。发现0x56558214中为8,0x565581ec中为1,而0x56558214-0x565581e0=0x34,0x34/0x4=0xD,而'm'的ASCII值就是0x6D,所以前5个字符可以选择为'm',而0x565581ec-0x565581e0=0xc,0xc/0x4=0x3,而'c'的ASCII值就是0x63,所以最后1个字符可以选择为'c'。因此针对phase_5,我们可以构造字符串'mmmmmc'。
pwndbg> x 0x565581e0
0x565581e0: 0x00000002
pwndbg> x 0x565581e4
0x565581e4: 0x0000000a
pwndbg> x 0x565581e8
0x565581e8: 0x00000006
pwndbg> x 0x565581ec
0x565581ec: 0x00000001
pwndbg> x 0x565581f0
0x565581f0: 0x0000000c
pwndbg> x 0x565581f4
0x565581f4: 0x00000010
pwndbg> x 0x565581f8
0x565581f8: 0x00000009
pwndbg> x 0x565581fc
0x565581fc: 0x00000003
pwndbg> x 0x56558200
0x56558200: 0x00000004
pwndbg> x 0x56558204
0x56558204: 0x00000007
pwndbg> x 0x56558208
0x56558208: 0x0000000e
pwndbg> x 0x5655820c
0x5655820c: 0x00000005
pwndbg> x 0x56558210
0x56558210: 0x0000000b
pwndbg> x 0x56558214
0x56558214: 0x00000008
pwndbg> x 0x56558218
0x56558218: 0x0000000f
pwndbg> x 0x5655821c
0x5655821c: 0x0000000d
(图16:不同内存地址中的数)
至此,我们得到的答案为:
I turned the moon into something I call a Death Star.
0 1 1 2 3 5
4 0
13 31
mmmmmc