> For the complete documentation index, see [llms.txt](https://hansimov.gitbook.io/csapp/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://hansimov.gitbook.io/csapp/labs/bomb-lab/writeup.md).

# Writeup

> bomblab.pdf
>
> 15-213 Fall 20xx
>
> Defusing a Binary Bomb

Harry Bovik (<bovik@cs.cmu.edu>) 是本作业的负责人。

## 1. 介绍

邪恶的**邪恶博士**在我们的班级机器上放置了大量的“二进制炸弹”。二进制炸弹是由一系列阶段组成的程序。每个阶段都要求你在 stdin 上键入一个特定的字符串。如果你输入了正确的字符串，那么这个阶段就被**拆除**，炸弹进入下一个阶段。否则炸弹会**爆炸**，并打印出 “BOOM!!!”，然后终止。当每一个阶段都被拆除时，炸弹才算拆除。

有太多炸弹要我们处理，所以我们给每个学生一个炸弹来拆除。这是你的任务，你别无选择，只能接受，就是在截止时间前拆除你的炸弹。祝你好运，欢迎加入拆弹小组！

### 步骤 1：获得你的炸弹

你可以用 Web 浏览器访问以下地址获得炸弹：

**http\://$Bomblab::SERVER\_NAME:$Bomblab::REQUESTD\_PORT/**

这会显示一个二进制炸弹请求表，让你填写。输入你的用户名和电子邮件地址，然后单击“提交”按钮。服务器将制作你的炸弹，并将其返回给你浏览器一个 tar 文件，名为 bombk.tar，其中 k 是你炸弹的唯一编号。

将 bombk.tar 文件保存到你打算工作的（受保护）目录下。然后给出命令：tar -xvf bombk.tar。这会创建一个名为 ./bombk 的目录，包含以下文件：

| 文件名               | 描述                     |
| ----------------- | ---------------------- |
| README            | 标识炸弹和拥有者               |
| bomb              | 可执行二进制炸弹               |
| bomb.c            | 炸弹主程序的源文件，伴随着邪恶博士的友好问候 |
| writeup.{.pdf,ps} | 实验报告                   |

### 步骤 2：拆除你的炸弹

你在这个实验中的工作就是拆除你的炸弹。

你必须在其中一台机器上完成作业。事实上，有传言说邪恶博士是真的邪恶，如果在别处运行，炸弹总会爆炸。炸弹里还有其他几种防篡改装置，反正我们是这么听说的。

你可以用很多工具来帮助你拆除炸弹。请看**提示**小节的一些提示和想法。最好的方法是使用你最喜欢的调试器来逐步检查反汇编的二进制文件。

每次你的炸弹爆炸，它都会通知 bomblab 服务器，你在实验的最终分数中会损失 1/2 分（最多 20 分），所以引爆炸弹会有后果。你一定要小心！

前四个阶段各有 10 分。第五阶段和第六阶段比较困难，所以他们各有 15 分。所以你能得到的最高分数是 70 分。

虽然阶段逐渐变得更难拆除，但是你从一个阶段到另一个阶段所获得的专业知识应该可以抵消这个困难。然而，最后一个阶段甚至会难住最好的学生，所以请不要等到最后一刻才开始。

炸弹会忽略空白输入行。例如，如果你用命令行参数运行炸弹：

```c
linux> ./bomb psol.txt
```

它从 psol.txt 读入文本行，直至 EOF（文件结束），然后切换到 stdin。由于一时心软，邪恶博士添加了这个功能，这样你就不必再为你已经拆除的阶段重新输入解答了。

为了避免意外引爆炸弹，你需要学习如何单步执行汇编代码以及如何设置断点。你还需要学习如何检查寄存器和内存状态。做这个实验的一个好的附带效果是，你会很好地使用调试器。这是一项至关重要的技能，它将给你的职业生涯带来丰厚的回报。

## 2. 支持

这是一个个人项目。所有提交内容都是电子版。说明和更正将公布在课程网页上。

## 3. 提交

该实验没有显式的提交。炸弹会自动通知讲师你工作的进度。你可以通过查看班级记分板来了解自己的表现：

**http\://$Bomblab::SERVER\_NAME:$Bomblab::REQUESTD\_PORT/scoreboard**

网页会不断更新，以显示每个炸弹的进度。

## 4. 提示（请读这个！）

拆除炸弹的方法有很多种。你可以在不运行程序的情况下对其进行详细的检查，并确切地了解它的功能。这是一种有用的技巧，但并不总是容易做到的。您也可以在调试器下运行它，一步一步地观察它做什么，并使用这些信息来消除它。这可能是最快的化解方法。

我们只提出一个要求，请不要**暴力穷举**！你可以编写一个程序，尝试所有可能的密钥来找到正确的。但这并不好，有这几个原因：

* 每次你猜错了炸弹爆炸，你就会损失 1/2 分（最多20分）。
* 每次你猜错了，就会有一条消息发送到 bomblab 服务器。你可能很快就会让网络中充斥着这些消息，导致系统管理员取消你的计算机访问权限。
* 我们没有告诉你这些字符串有多长，也没有告诉你其中有哪些字符。即使你做了（不正确的）假设，它们的长度都小于 80 个字符，并且只包含字母，那么每个阶段都会有$$26^{80}$$个猜测。这要很长时间才能跑完，作业到期了你都无法得到答案。

有很多工具都是用来帮助你弄清楚程序是如何工作的，以及当程序不工作时有什么问题。以下是一些工具的清单，你可能会发现有助于分析你的炸弹，并提示如何使用它们。

* **gdb**

  GNU 调试器，这是几乎所有平台上都可用的命令行调试器工具。您可以逐行跟踪程序，检查内存和寄存器，同时查看源代码和汇编代码（我们不会为您提供大多数炸弹的源代码）、设置断点、设置内存监视点以及编写脚本。

  CS:APP 网站 <http://csapp.cs.cmu.edu/public/students.html> 有一个非常方便的单页 gdb 总结，可以打印出来用作参考。下面是使用 gdb 的一些其他提示。

  * 为了防止每次输入错误的输入时炸弹爆炸，你需要学习如何设置断点。
  * 对于在线文档，请在 gdb 命令提示符处键入 “**help**”，或在 Unix 提示符下键入 “**man-gdb**” 或 “**info-gdb**”。有些人还喜欢在 emacs 中以 **gdb-mode** 运行 gdb。
* **objdump -t**

  这会打印出炸弹的符号表。符号表包括炸弹中所有函数和全局变量的名称、炸弹调用的所有函数的名称及其地址。通过查看函数名，你可能会学到一些东西！
* **objdump -d**

  用这个来分解炸弹里的所有代码。你也可以只看单个函数。阅读汇编代码可以告诉你炸弹是如何工作的。

  虽然 **objdump -d** 提供了很多信息，但它并不能告诉你整个过程。对系统级函数的调用，是以一种神秘形式显示的。例如，对 sscanf 的调用可能显示为 ：&#x20;

  ```python
  8048c36:   e8 99 fc ff ff   call   80488d4 <_init+0x1a0>
  ```

  要确定调用的是 sscanf，你需要在 gdb 中反汇编。
* **strings**

  这个实用程序会显示炸弹中的可打印字符串。

在找一个特别的工具？文档怎么样？别忘了，命令 **apropos**、**man** 和 **info** 是你的朋友。尤其是 **man ascii** 可能会有用。**info gas** 将告诉你 GNU 汇编器的信息，可能比你想知道的都多。此外，网络也可能是信息的宝库。如果你被难住了，放心向你的讲师寻求帮助。
