Bomblab感想

文章目录
  1. 1. 写在前面
  2. 2. 拆弹记录
    1. 2.1. 第一个炸弹
    2. 2.2. 第二个炸弹
    3. 2.3. 第三个炸弹
    4. 2.4. 第四个炸弹
    5. 2.5. 第五个炸弹
    6. 2.6. 第六个炸弹

写在前面

bomblab 比起 datalab 更友好一些,除了考察对汇编代码的理解以外,也在锻炼我们的 gdb 调试技能。用时共计 2+2+0.8+0.5+1.5+4 = 10.8h,比 datalab 用时略少一点。刚开始拆弹的时候是很兴奋的,做到后面倒是感觉有点无聊了,我感觉 attacklab 可能更有趣一些(虽然我还没做)。

拆弹记录

首先肯定要对 bomb 进行反汇编,我是用 objdump 来反汇编,并把结果保存到了 txt 文件中。拿到汇编以后随便翻翻找到 phase 们,之后就进入拆弹阶段了。

第一个炸弹

phase_1 简单易懂,只是判断输入是否与某个字符串相等。我一开始以为字符串就是“0x402400”,后面才想到这是那个字符串的地址。用 gdb 设置断点即可得知字符串。
(别看我说得那么轻松,也是折腾了两小时多,毕竟完全没有 gdb 经验 🫠)

第二个炸弹

这也是一个不难的炸弹,把汇编代码往下读就能解决,喜欢的话可以加点注释帮助自己理解。
不过我仍然做了两个小时,主要在疑惑 read_six_numbers 后数字被读到了哪里。还有个有趣的犯蠢的地方,我一开始把 400f35 处的 0x18 当成了十进制 18,疑惑了很久 4n 怎么可能等于 18,后面猛然惊醒发现那是十六进制。🤣

在这里我用到了这些新指令:

1
2
3
4
5
si  # 单步执行
x/10xw $sp # 查看栈指针(sp)处的10个字(word),以十六进制(x)显示
x/10i $pc # 查看当前位置之后的10条指令
i registers eax # 查看寄存器值

第三个炸弹

用时 50 分钟(有进步!),这次有了更系统的拆弹方法——先把代码分段,然后分析代码提出若干个猜测和问题,随着解答问题就逐渐做掉了。🫠
我们可以轻松注意到输入的数字不能少于一个,再往下读就会 400f75 这一行,算一算就会很自然地猜测:输入要求我们选一个选项,跳过去然后 cmp。

这里是我拆弹时提出的问题以及解答:

  1. 输入按怎样的格式存储起来?存储在哪里?
    分析栈后发现,看起来是读取了两个数字,存储在栈中
  2. 400f6a 那行是怎么比较的?0x8(%rsp)是什么,输入值吗?猜测这是要求输入的选项值只能在 0-7 之间?
    设一个断点就能回答这个问题了。
  3. 400f75 跳到了哪里?是根据选项跳跃吗?
    根据选项跳跃
  4. 从选项跳到了 400fbe 后,0xc(%rsp)是定值还是会根据输入变化?
    0xc(%rsp)是输入的第二个值。由于 8 对齐,我们需要用 0xc(%rsp)而非 0x10(%rsp)来得到第二个值。

第四个炸弹

用时半小时,我连 func4 都不想读,直接用 gdb 来执行 func4,找到返回 0 的输入就行了。这种解法感觉有逃课的嫌疑,不过你就说快不快吧!
在这里我用到了这个新指令:

1
2
(gdb) call (int)func4(11, 0, 14)

第五个炸弹

用时 1.5h,做到这里,我比起刚开始时已经对汇编代码熟悉不少了。首先把代码分成若干个小部分,然后猜测并验证每个部分的功能就能解决这个炸弹。比较有趣的地方是这里加入了一个金丝雀,我还疑惑了一阵子这是什么,后来才想到这是书上讲的金丝雀。

第六个炸弹

用时 4h,对这个炸弹,我感觉“根据运行时的状况猜代码的作用”比“分析代码”更加重要。一开始同样是把代码分成多个小局部,然后分段猜作用。这里引入了链表,还挺有趣。

彩蛋?什么彩弹?