本文写的是炸弹lab的第三层密码,刚开始解的时候,确实有点摸不着头脑,后来重新看了一遍视频,把当时划水放过的switch重点看了一遍,发现第三重密码其实就是一个switch判断。
正如教授所说,switch在判断条件不稀疏的时候,gcc并不是采用我们第一印象的if-else chain 来进行编译,而是采用了一种叫jump table 的结构来判断。在汇编语言里面,最具有特征的就是,间接跳转指令。
这条指令中的地址0x402470,显然是jump table的的首地址,之后的%rax代表的是代码块的index。
我们在观察上一条指令
mov 0x8(%rsp),%eax
通过做实验,我们会发现这恰好就是我们输入的第一个参数的内容,也就是说,我们输入的第一个参数正是参与switch判断的参数。这这里正是通过jump table 将我们输入的参数转换成对应的代码block的首地址,在跳转到block这一过程。
我们沿着顺序来阅读,第一次引爆炸弹的函数是
通过实验,我们容易发现,当输入的参数在2个以上时,%eax的值都是2,而只有一个参数时,%eax为1,这里的爆炸函数告诉我们,参数显然应该是2。
我们可以大胆猜测一下,该函数甚至只会提取输入的前两个参数,这一点,我们可以在后面的实验验证。
我们在phase_3 输入 5,8两个数试试。(第一个参数必须小于7,我们接下来解释这一点,同时验证上述猜测)
这一段代码,有一个内存引用,十分之可疑。设置断点,continue到这个位置。
废话不多说,直接上图
(额。。。忽略第二个,纯属手误,大家应该看得出来,0x12!=12,hhhh~)
回到正题,这几行输出表明了一个这样的内存状态。
虽然不知道为何要空出两个int 大小的空间,但确实现在可以发现到这一步为止,%rsp可以得到输入的数。
接下来,就是视频内教授所提的了,
这一大段就是,c语言的switch语句中的内容,当然,switch的条件从这里的汇编代码是看不出来的,因为jump table被隐藏了,但是我们可以通过实验得出jumptable,注意到这里的jmp 0x400fbe,有点像c语言switch中的break。
如果你足够细心你会发现这里有7个case,
而
这里是教授特意提醒的点了,ja把大于7和小于0的数字同时过滤了,所以其表示的case应该是0-7共8个case,我们反过来找汇编代码。
果然在下面找到我们需要的东西了。
接下来就是制作jump table了,这个需要实验,我这里贴上我的实验结果吧。
也就是说,对于phase_3,这8组组合,任意一组都可以破除第三重密码。
这里为增强说服力,笔者贴其中之一的结果
到目前为止,这个实验做了一半了,笔者会继续更新后面的内容,欢迎关注哦~