Bomb Lab:拆除二进制炸弹
Bomb Lab:拆除二进制炸弹
自学包说明:运行配置与原说明的差异
15-213,20xx 年秋季
实验作业 L2:拆除二进制炸弹
布置日期:9 月 13 日;截止日期:9 月 22 日(星期五)。
本次实验的主要负责人是 Harry Bovik(bovik@cs.cmu.edu)。
译注:
20xx、$Bomblab::SERVER_NAME和$Bomblab::REQUESTD_PORT是原课程模板中的占位内容,按原文保留;日期和联系人也沿用原文。
1 引言
邪恶的 Dr. Evil 在课程使用的机器上安放了大量“二进制炸弹”。二进制炸弹是一个由一系列阶段组成的程序。每个阶段都要求你在 stdin 上输入一个特定的字符串。如果输入正确,该阶段就被拆除,炸弹继续进入下一阶段。否则,炸弹就会“爆炸”:打印 "BOOM!!!",然后终止运行。当所有阶段都被拆除时,整个炸弹才算拆除。
炸弹太多,我们无法一一处理,因此要给每位学生分配一个炸弹去拆除。你的任务是,在截止日期之前拆除自己的炸弹,而且这个任务你别无选择,只能接受。祝你好运,欢迎加入拆弹小组!
步骤 1:获取你的炸弹
在浏览器中访问以下地址,即可获取你的炸弹:
http://$Bomblab::SERVER_NAME:$Bomblab::REQUESTD_PORT/
页面会显示一张二进制炸弹申请表,供你填写。输入用户名和电子邮件地址,然后点击 Submit 按钮。服务器会构建你的炸弹,并将其放在名为 bombk.tar 的 tar 文件中返回给浏览器,其中 k 是你的炸弹的唯一编号。
将 bombk.tar 文件保存到你打算开展工作的一个(受保护的)目录中。然后执行命令:tar -xvf bombk.tar。这将创建名为 ./bombk 的目录,其中包含以下文件:
README:标明炸弹及其所有者。bomb:可执行的二进制炸弹。bomb.c:包含炸弹主例程及 Dr. Evil 友好问候的源文件。writeup.{pdf,ps}:实验说明。
如果你出于某种原因申请了多个炸弹,也没有关系。选择其中一个进行实验,删除其余的即可。
步骤 2:拆除你的炸弹
你在本次实验中的任务就是拆除自己的炸弹。
你必须在课程使用的某台机器上完成作业。事实上,据说 Dr. Evil 确实非常邪恶,炸弹一旦在其他地方运行,就一定会爆炸。我们还听说,炸弹内部另有多种防篡改装置。
你可以借助许多工具拆除炸弹。请阅读提示部分,了解一些技巧和思路。最好的方法是使用你喜欢的调试器,逐步执行反汇编后的二进制程序。
每次炸弹爆炸时,它都会通知 bomblab 服务器,并从你的实验最终成绩中扣除 1/2 分(最多扣除 20 分)。因此,引爆炸弹是有代价的。你必须小心!
前四个阶段各值 10 分。第 5 和第 6 阶段稍难一些,因此各值 15 分。你能获得的最高分是 70 分。
虽然各阶段的拆除难度逐步增加,但你在逐个完成阶段的过程中积累的技能,应该能够抵消这种难度增长。不过,最后一个阶段即使对最优秀的学生也是挑战,因此请不要等到最后一刻才开始。
炸弹会忽略空白输入行。如果你运行炸弹时提供了命令行参数,例如:
linux> ./bomb psol.txt
那么它会从 psol.txt 读取输入行,直到遇到 EOF(文件结束),随后切换到 stdin。Dr. Evil 一时心软,加入了这个功能,让你不必反复输入已经拆除的阶段的解答。
为了避免意外引爆炸弹,你需要学习如何单步执行汇编代码,以及如何设置断点。你还需要学习如何检查寄存器和内存状态。完成本实验的一个有益副作用是,你会变得非常擅长使用调试器。这是一项至关重要的技能,将在你今后的职业生涯中带来丰厚回报。
实验安排
这是一个独立完成的项目。所有作业均以电子方式提交。说明和更正将发布在课程留言板上。
提交
不需要专门执行提交操作。在你拆弹的过程中,炸弹会自动将你的进度告知教师。你可以访问课程排行榜,查看自己的完成情况:
http://$Bomblab::SERVER_NAME:$Bomblab::REQUESTD_PORT/scoreboard
该网页会持续更新,显示每个炸弹的拆除进度。
提示(请务必阅读!)
拆除炸弹有许多方法。你可以完全不运行程序,而是对它进行非常细致的检查,弄清楚它究竟做了什么。这是一项有用的技术,但并不总是容易做到。你也可以在调试器中运行它,一步步观察它的行为,并利用这些信息拆除炸弹。这可能是最快的拆弹方法。
我们确实有一项要求:请不要使用蛮力穷举! 你可以编写一个程序,尝试每一种可能的密钥,以找出正确的那一个。但这样做并不好,原因如下:
- 每次猜错并引爆炸弹,都会扣除 1/2 分(最多扣除 20 分)。
- 每次猜错,都会向 bomblab 服务器发送一条消息。你可能很快就会让这些消息挤满网络,并导致系统管理员撤销你的计算机访问权限。
- 我们没有告诉你字符串有多长,也没有告诉你其中包含哪些字符。即使你作出这些字符串都少于 80 个字符且仅包含字母的(错误)假设,每个阶段也会有 2680 种猜测。这需要极长的运行时间,你无法在作业截止之前得到答案。
有许多工具专门用于帮助你弄清程序如何工作,以及在程序不能正常工作时找出问题所在。下面列出了一些可能有助于分析炸弹的工具,以及它们的使用提示。
gdbGNU 调试器是一种命令行调试工具,几乎所有平台上都可以使用。你可以逐行跟踪程序、检查内存和寄存器、查看源代码及汇编代码(我们不会提供炸弹的大部分源代码)、设置断点、设置内存观察点,以及编写脚本。
CS:APP 网站提供了一份非常方便的单页
gdb速查表,你可以打印出来作为参考。以下是使用gdb的另外一些提示:- 为了避免每次输入错误内容都会引爆炸弹,你需要学习如何设置断点。
- 要查看联机文档,可以在
gdb命令提示符下输入help,或在 Unix 提示符下输入man gdb或info gdb。有些人也喜欢在emacs的gdb-mode中运行gdb。
objdump -t此命令会打印炸弹的符号表。符号表包含炸弹中所有函数和全局变量的名称、炸弹所调用的所有函数的名称,以及它们的地址。查看函数名,也许能让你有所发现!
objdump -d使用此命令可以反汇编炸弹中的全部代码。你也可以只查看个别函数。阅读汇编代码可以让你了解炸弹如何工作。
虽然
objdump -d能提供大量信息,但它并不能告诉你全部情况。对系统级函数的调用会以难以理解的形式显示。例如,对sscanf的一次调用可能显示为:8048c36: e8 99 fc ff ff call 80488d4 <_init+0x1a0>要确定这里调用的是
sscanf,你需要在gdb中进行反汇编。strings此工具会显示炸弹中的可打印字符串。
正在寻找某个工具?或者在找文档?别忘了,apropos、man 和 info 命令都是你的好帮手。特别是 man ascii,可能会派上用场。info gas 会提供关于 GNU 汇编器的详尽信息,多到超出你的想象。此外,网络也可能是一座信息宝库。如果遇到难题,尽管向教师求助。