大家千万不要着急,不要慌张,即使自己并不了解多少汇编代码的知识,即使自己计基课上的基础知识学的并不扎实,也都不要紧,因为这次计基实验考察的重点并不是基础知识,而是对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,那么程序就会跳到第<phase_3+224>行,可是第<phase_3+224>行就是引爆炸弹!!!所以我们不能那样子做,所以我们输入的第一个整数应该小于等于7。因此,重新输入phase_3的答案字符串为'7 8',然后重新启动gdb,一路"ni"到现在的位置,如 图4:重新输入phase_3的答案字符串为'7 8',然后重新启动gdb,一路"ni"到现在的位置 所示。
(图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: 判断第二个整数)
在这里,我们必须要跳到第<phase_3+157>行去,否则程序顺序执行的话,就会执行到第<phase_3+152>行,就会引爆炸弹。那么该如何跳到第<phase_3+157>行去呢?应该让(%esp+8)的值与%eax的值相等,而(%esp+8)的值为8,也就是我们输入的第二个整数,%eax的值为0,所以我们不妨重新输入"4 0"作为phase_3的答案字符串,然后一路"ni"到当前位置,如 图8:重新输入"4 0"作为phase_3的答案字符串,然后一路"ni"到当前位置 所示。
(图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时,不会引爆炸弹 所示的情况出现时,停下来分析。在这里其实隐藏了第<phase_4+72>行,而这一行就是引爆炸弹,意思是我们输入的第一个整数必须小于等于14,否则就会引爆炸弹。但是考虑到我们输入的第一个整数是'4',因为不会在这里便立刻就引爆炸弹,所以我们可以继续"ni"下去,直到 图14:调用func4函数 ,func4函数是干什么用的呢?我们也没有心思去研究func4的功能,所以反复尝试第一个整数,尝试1、2、3、4、5、6、8、9、10、11、12、13、14,发现仅当第一个整数为13时才能通过,接着第二个整数为31时才能通过。最终成功拆弹,如 图15:成功拆除phase_4 所示。而我们的phase_4的答案字符串即为"13 31"。
(图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 <array.3068>: 0x00000002
pwndbg> x 0x565581e4
0x565581e4 <array.3068+4>: 0x0000000a
pwndbg> x 0x565581e8
0x565581e8 <array.3068+8>: 0x00000006
pwndbg> x 0x565581ec
0x565581ec <array.3068+12>: 0x00000001
pwndbg> x 0x565581f0
0x565581f0 <array.3068+16>: 0x0000000c
pwndbg> x 0x565581f4
0x565581f4 <array.3068+20>: 0x00000010
pwndbg> x 0x565581f8
0x565581f8 <array.3068+24>: 0x00000009
pwndbg> x 0x565581fc
0x565581fc <array.3068+28>: 0x00000003
pwndbg> x 0x56558200
0x56558200 <array.3068+32>: 0x00000004
pwndbg> x 0x56558204
0x56558204 <array.3068+36>: 0x00000007
pwndbg> x 0x56558208
0x56558208 <array.3068+40>: 0x0000000e
pwndbg> x 0x5655820c
0x5655820c <array.3068+44>: 0x00000005
pwndbg> x 0x56558210
0x56558210 <array.3068+48>: 0x0000000b
pwndbg> x 0x56558214
0x56558214 <array.3068+52>: 0x00000008
pwndbg> x 0x56558218
0x56558218 <array.3068+56>: 0x0000000f
pwndbg> x 0x5655821c
0x5655821c <array.3068+60>: 0x0000000d
(图16:不同内存地址中的数)
至此,我们得到的答案为:
I turned the moon into something I call a Death Star.
0 1 1 2 3 5
4 0
13 31
mmmmmc