README(讲师版)

CS:APP Bomb Lab

给讲师的指导

Copyright (c) 2003-2016, R. Bryant and D. O'Hallaron

此目录包含你用于构建和运行 CS:APP Bomb Lab 的文件。Bomb Lab 教授学生机器级程序的原理,以及一般的调试器和逆向工程技能。

1. 概述

1.1 二进制炸弹

一个“二进制炸弹”是由六个 “阶段” 组成的 Linux 可执行 C 程序,每个阶段都要求学生在 stdin 上输入一个特定的字符串。如果学生输入预期的字符串,则该阶段为 “拆除”,否则炸弹则打印 “BOOM!!!” 表示“爆炸”。学生们的目标是拆除尽可能多的阶段。

1.2 解决二进制炸弹

为了拆除炸弹,学生必须使用一个调试器,通常是 gdb 或 ddd,在每个阶段反汇编二进制文件,并对机器码单步调试。想法是让学生理解每个汇编语句的作用,然后使用这些知识来推断要拆除的字符串。学生通过拆除阶段获得分数,每次爆炸都会损失分数(由讲师配置,但通常为 1/2 分)。因此,他们将很快学会在每个阶段和引爆炸弹的函数之前设置断点。这是一个很好的教训,迫使他们学会使用调试器。

1.3 自动评分服务

我们创建了一个独立的用户级自动评分服务,为你处理 Bomb Lab 的所有方面:学生从服务器下载他们的炸弹。当学生们在研究他们的炸弹时,每一次爆炸和拆除都会传回到服务器上,在服务器上,每个炸弹的当前结果都会显示在一个网络“记分板”上。没有明显的提交,实验会自己评分。

自动评分服务由四个用户级程序组成,这些程序运行在 ./bomblab 主目录中:

  • 请求服务器(bomblab-requestd.pl)。学生下载炸弹并显示记分牌,方法是将浏览器指向一个名为“请求服务器”的简单 HTTP 服务器。请求服务器生成炸弹,将其存档在 tar 文件中,然后将生成的 tar 文件上传回浏览器,在浏览器中可以将其保存在磁盘上并解压。请求服务器还为讲师创建炸弹及其解答的副本。

  • 结果服务器(bomblab-resultd.pl)。每次学生拆除炸弹阶段或引起爆炸时,炸弹都会向 HTTP “结果服务器”发送一条名为 “自动结果字符串” 的简短 HTTP 消息,该服务器只是将自动结果字符串附加到“记分板日志文件”中。

  • 报告守护进程(bomblab-reportd.pl)。“报告守护进程”定期扫描记分板日志文件。报表守护进程查找每个学生为每个阶段提交的最新的拆除字符串,并将这些字符串应用于学生炸弹的本地副本,来验证这些字符串。然后它会更新 HTML 记分板,该记分板汇总了每枚炸弹的当前爆炸和拆除次数,按累计点数排序。

  • 主守护进程(bomblab.pl). “主守护进程”启动并保护请求服务器、结果服务器和报表守护进程,确保这些进程(以及它本身)在任何时间点都在运行。如果其中一个进程由于某种原因死亡,主守护进程会检测到并自动重新启动它。主守护进程是您实际需要运行的唯一程序。

2. 文件

./bomblab 目录包含下列文件:

文件名

说明

Makefile

开始/停止实验和清除文件

bomblab.pl*

主守护进程,守护其他服务器和守护进程

Bomblab.pm

Bomb Lab 配置文件

bomblab-reportd.pl*

报告守护进程,持续更新记分板

bomblab-requestd.pl*

请求服务器,将炸弹提供给学生

bomblab-resultd.pl*

结果服务器,从炸弹得到自动结果字符串

bomblab-scoreboard.html

实时网络记分板

bomblab-update.pl*

帮助 bomblab-reportd.pl 更新记分板

bombs/

包含发送给每个学生的炸弹

log-status.txt

状态日志,来自不同服务器和守护进程的消息

log.txt

自动结果记分板日志,接受自炸弹

makebomb.pl*

帮助脚本,用于制作炸弹

scores.txt

合计每个学生的当前记分板分数

src/

炸弹源文件

writeup/

Bomb Lab 的 LaTeX 报告样例

3. 炸弹术语

  • LabID:该实验的每个实例(用品)都由唯一的名称标识,例如 “f12” 或 “s13”,由讲师选择。和当前 LabID 不同的炸弹的爆炸和拆除动作将被忽略。LabID 不能有空格。

  • BombID:实验给定实例中的每个炸弹都有唯一的非负整数,称为 “bombID”。

  • 通知炸弹(Notifying Bomb):一个炸弹可以用一个 NOTIFY 选项编译,当学生每次爆炸或拆除一个阶段时,炸弹都会发送一条消息。这种炸弹被称为“通知炸弹”。

  • 安静炸弹(Quiet Bomb):如果使用 NONOTIFY 选项编译,则炸弹在爆炸或拆除时不会发送任何消息。这种炸弹被称为“安静炸弹”。

我们还会发现区分定制炸弹和普通炸弹很有帮助:

  • 定制炸弹(Custom Bomb):“定制炸弹”的 BombID > 0,与特定学生关联,可以是通知的或安静的。定制的通知炸弹被限制在讲师确定的一组特定的 Linux 主机上运行。另一方面,定制的安静炸弹可以在任何 Linux 主机上运行。

  • 通用炸弹(Generic Bomb):一个“通用炸弹”的 BombID = 0,与任何特定的学生没有关联,是安静的,因此可以在任何主机上运行。

4. 提供炸弹实验

Bomb Lab 有两种基础版本:在“在线”版本中,讲师使用自动评分服务向每个学生分发定制的通知炸弹,并在实时记分板上自动跟踪他们的进度。在“离线”版本中,讲师手动制作、分发和评分学生炸弹,而不使用自动评分服务。

虽然这两个版本都给了学生丰富的经验,我们推荐在线版本。对于学生来说,这显然是最吸引人和最有趣的,也是老师最容易评分的。但是,它要求你不停地运行自动评分服务,因为在实验期间,讲义、评分和报告都是连续不断地进行的。我们已经使这项服务非常容易运行,但是一些讲师可能不喜欢这个要求,而是选择离线版本。

以下是提供两个版本的实验的说明。

4.1 创建一个 Bomb Lab 目录

确定要创建 Bomb Lab 目录(./bomblab)的通用 Linux 机器($SERVER_NAME),如果提供联机版本,请运行自动评分服务。你只需在这台机器上有一个用户帐户,不需要 root 权限。 Bomb Lab 的每个实例启动时,都伴随着 $SERVER_NAME 上一个全新的 ./bomblab 目录。例如:

linux> tar xvf bomblab.tar
linux> cd bomblab   
linux> make cleanallfiles

4.2 配置 Bomb Lab

通过编辑以下文件配置 Bomb Lab:

  • ./Bomblab.pm:这是主配置文件。你只需修改或检查此文件第 1 节的几个变量。每个变量前面都有一个描述性注释。如果提供离线版本,那么可以忽略其中的大多数设置。

如果你提供在线版本,则还需要编辑以下文件:

  • ./src/config.h:此文件列出了允许运行炸弹的主机的域名。确保你正确地更新了这个,否则你和你的学生将无法运行你的炸弹。

4.3 更新实验报告

更新完配置文件后,请根据你的环境,修改 writeup/bomblab.tex 中的 LaTeX 报告。然后在 ./writeup 目录中键入以下内容:

unix> make clean
unix> make 

这会创建报告的 ps 和 pdf 版本。

4.4 运行在线 Bomb Lab

4.4.1 简短版本

来自 ./bomblab 目录:

(1)重置 Bomb Lab,键入:

linux> make cleanallfiles

(2)开启自动评分服务,键入:

linux> make start

(3)停止自动评分服务,键入:

linux> make stop

你可以随时开启和停止自动评分服务,这不会丢失任何信息。如果不确定服务状态,输入 “make stop; make start” 可以让一切都进入稳定状态。

但是,重置实验室删除所有旧的炸弹、状态日志和记分板日志。只有在调试期间,或者第一次为学生开启实验时,才可以这样做。

学生用浏览器访问如下网址请求炸弹:

http://$SERVER_NAME:$REQUESTD_PORT/

学生用浏览器访问如下网址查看记分板:

http://$SERVER_NAME:$REQUESTD_PORT/scoreboard

4.4.2 较长版本

(1)重置 Bomb Lab。“make stop” 确保没有服务器在运行。“make cleanallfiles” 重置实验,删除实验中特定实例的所有数据,例如状态日志、请求服务器创建的所有炸弹以及记分板日志。当你准备好将实验“上线”给学生时,就这样做。

你准备实验的时候,重置也很有用。在实验上线之前,你可能想为自己请求一些炸弹,运行它们,拆除一些,引爆一些,并确保结果在记分板上正确显示。如果出现问题(比如因为你忘记更新 src/config.h 中允许运行炸弹的机器列表),你可以修复配置,重置实验,然后请求并运行更多的测试炸弹。

注意:如果你在开启实验后重新设置,你将丢失所有学生炸弹记录和他们的解答。你不能验证学生提交的内容。你的学生就得获得新的炸弹并重新开始。

(2)开启 Bomb Lab。“make start” 运行 bomblab.pl,主守护进程启动并监视服务中的其他程序,每隔几秒检查它们的状态,如有必要则重启它们:

(3)停止 Bomb Lab。“make start” 会关闭所有正在运行的服务器。您可以随时开启和停止自动评分服务,而不会丢失任何信息。如果不确定服务状态,输入 “make stop; make start” 可以让一切都进入稳定状态。

请求服务器:请求服务器是一个简单的专用HTTP服务器,它(1)根据需要制作并向学生的浏览器提供自定义炸弹,(2)显示实时记分板的当前状态。

学生通过两个步骤从请求守护进程请求炸弹:

  • 首先,学生用他们最喜欢的浏览器访问 http://$SERVER_NAME:$REQUESTD_PORT/。例如,http://foo.cs.cmu.edu:15213/。请求服务器产生相应,将 HTML 表单发送回浏览器。

  • 接着,学生用他们的用户名和电子邮件地址填写此表单,然后提交表单。请求服务器解析表单,制作一个 bombID = n 的定制的通知炸弹,并将 tar 文件发送到浏览器。然后学生将 tar 文件保存到磁盘上。当学生解压此文件时,会创建一个目录(./bomb),其中包含以下四个文件:

文件名

说明

bomb*

定制的通知炸弹可执行程序

bomb.c

主炸弹程序的源码

ID

标识与该炸弹有关的学生

README

列出炸弹号码、学生和电子邮件地址

solution.txt

该炸弹的解答

结果服务器:每次学生拆除一个阶段或引爆炸弹时,炸弹都会向结果服务器发送一条 HTTP 消息(称为自动结果字符串(autoresult string)),然后结果服务器将消息附加到记分板日志中。每个消息都包含一个 BombID、一个阶段和所发生事件的标示。如果是拆除事件,则消息还包含学生键入的“拆除字符串(defusing string)”以消除阶段。

报告守护进程:报告守护进程定期扫描记分板日志并更新网络记分板。对于每个炸弹,它统计爆炸的次数,最后一个拆除阶段,使用一个安静炸弹的副本验证每个最后拆除的阶段,并在一个标签分隔的文本文件中计算每个学生的分数,该文件名为 “scores. txt” 更新频率适中的配置变量 Bomblab.pm。

讲师和学生使用浏览器访问以下地址查看记分板:

http://$SERVER_NAME:$REQUESTD_PORT/scoreboard

4.4.3. 为在线 Bomb Lab 评分

在线的炸弹实验可以自己评分。在任何时间点,制表符分隔的文件(./bomblab/scores.txt)包含每个学生的最新分数。这个文件是由报告守护进程在每次生成新的记分板时创建的。

4.4.4 在线 Bomb Lab 的补充说明

由于请求服务器和报告守护进程都需要执行炸弹,因此必须在 bomblab/src/config.h 文件的合法计算机列表中包含 $server_NAME。

所有的服务器和守护进程都是无状态(stateless)的,所以您可以随意多次停止(“make stop”)和开启(“make start”)实验,而不会产生任何不良影响。如果您不小心杀死了其中一个守护进程,或者修改了一个守护进程,或者该守护进程由于某种原因死亡,那么请使用 “make stop” 进行清理,然后使用 “make start” 重新启动。如果 Linux 机器崩溃或重启,只需使用 “make start” 重新启动守护进程。

来自服务器的信息和错误消息被添加到“状态日志” bomblab/log-status.txt 中。服务器安静地运行,因此可以在启动时从 init.rc 脚本启动它们。

请参阅 src/README,了解更多关于炸弹的解剖结构以及它们是如何构造的。你不需要理解这些来提供实验,给出它们只是为了完整。

在将实验“上线”给学生之前,我们喜欢做些测试来检查一切,需键入以下内容:

linux> make cleanallfiles   
linux> make start

然后我们用浏览器访问如下地址,为自己请求一个炸弹:

http://$SERVER_NAME:$REQUESTD_PORT

在保存炸弹到磁盘后,我们将其解压,复制到 src/config.h 里已批准列表中的一台主机上,然后对其进行多次引爆和拆除,以确保爆炸和拆除正确记录在记分板上,可以在这里检查:

http://$SERVER_NAME:$REQUESTD_PORT/scoreboard

一旦我们确信一切正常,我们就停止实验:

linux> make stop

然后将其上线:

linux> make cleanallfiles
linux> make start

一旦实验上线,我们可根据需要输入 “make stop” 和 “make start”,但要小心绝不能再次输入 “make cleanallfiles”。

4.5 运行离线 Bomb Lab

在这个版本的实验中,你可以手动制作你自己的安静炸弹,然后把它们分发给学生。学生们在离线状态下(即,独立于任何自动评分服务)拆除炸弹,然后将他们的解答文件交给你,每个文件都由你手动评分。

你可以使用 makebomb.pl 脚本手动制作自己的炸弹。这个 makebomb.pl 脚本也生成炸弹的解答。键入 “./makebomb.pl -h” 查看其参数。

选项 1:提供离线炸弹实验室的最简单方法,是制造一个单一的通用炸弹,每个学生都试图将其拆除:

linux> ./makebomb.pl -s ./src -b ./bombs

这会在 ./bombs/bomb0 下面创建一个通用炸弹和其他文件:

文件名

说明

bomb*

通用炸弹执行程序(分发给学生)

bomb.c

主程序的源代码(分发给学生)

bomb-quiet*

请忽略该文件

ID

请忽略该文件

phases.c

炸弹阶段的 C 代码

README

请忽略该文件

solution.txt

该炸弹的解答

你只向学生分发其中两个文件:./bomb 和./bomb.c。

学生提交他们的解答文件,你可以将解答输入给炸弹来验证:

linux> cd bombs/bomb0
linux> ./bomb < student_solution.txt

这个选项对老师来说很容易,但是我们不推荐它,因为它太容易让学生作弊了。

选项 2。提供离线实验的另一个选项是使用 makebomb.pl 脚本,为每个学生制作一个唯一的定制的安静炸弹:

linux> ./makebomb.pl -i <n> -s ./src -b ./bombs -l bomblab -u <email> -v <uid>

这将为电子邮件地址为 <email> 且用户名为 <uid> 的学生在 ./bombs/bomb 中创建一个定制的安静炸弹:

文件名

说明

bomb*

定制的炸弹执行程序(分发给学生)

bomb.c

主程序的源代码(分发给学生)

bomb-quiet*

请忽略该文件

ID

标识与该炸弹关联的学生

phases.c

炸弹阶段的 C 代码

README

列出炸弹号码、学生和电子邮件地址

solution.txt

该炸弹的解答

你将向学生分发其中的四个文件:bomb、bomb.c、ID 和 README。

每个学生都将提交他们的解答文件,你可以针对运行他们的解答运行他们的定制炸弹,来手动验证:

linux> cd ./bombs/bomb<n>
linux> ./bomb < student_n_solution.txt

不同阶段变种的源代码在 ./src/phases/ 中。

最后更新于