深入理解计算机系统(CSAPP)
  • 本电子书信息
  • 出版信息
    • 出版者的话
    • 中文版序一
    • 中文版序二
    • 译者序
    • 前言
    • 关于作者
  • 第 1 章:计算机系统漫游
    • 1.1 信息就是位 + 上下文
    • 1.2 程序被其他程序翻译成不同的格式
    • 1.3 了解编译系统如何工作是大有益处的
    • 1.4 处理器读并解释储存在内存中的指令
    • 1.5 高速缓存至关重要
    • 1.6 存储设备形成层次结构
    • 1.7 操作系统管理硬件
    • 1.8 系统之间利用网络通信
    • 1.9 重要主题
    • 1.10 小结
  • 第一部分:程序结构和执行
    • 第 2 章:信息的表示和处理
      • 2.1 信息存储
      • 2.2 整数表示
      • 2.3 整数运算
      • 2.4 浮点数
      • 2.5 小结
      • 家庭作业
    • 第 3 章:程序的机器级表示
      • 3.1 历史观点
      • 3.2 程序编码
      • 3.3 数据格式
      • 3.4 访问信息
    • 第 4 章:处理器体系结构
    • 第 5 章:优化程序性能
    • 第 6 章:存储器层次结构
  • 第二部分:在系统上运行程序
    • 第 7 章:链接
      • 7.1 编译器驱动程序
      • 7.2 静态链接
      • 7.3 目标文件
      • 7.4 可重定位目标文件
      • 7.5 符号和符号表
      • 7.6 符号解析
      • 7.7 重定位
      • 7.8 可执行目标文件
      • 7.9 加载可执行目标文件
      • 7.10 动态链接共享库
      • 7.11 从应用程序中加载和链接共享库
      • 7.12 位置无关代码
      • 7.13 库打桩机制
      • 7.14 处理目标文件的工具
      • 7.15 小结
      • 家庭作业
    • 第 8 章:异常控制流
      • 8.1 异常
      • 8.2 进程
      • 8.3 系统调用错误处理
      • 8.4 进程控制
      • 8.5 信号
      • 8.6 非本地跳转
      • 8.7 操作进程的工具
      • 8.8 小结
      • 家庭作业
    • 第 9 章:虚拟内存
      • 9.1 物理和虚拟寻址
      • 9.2 地址空间
      • 9.3 虚拟内存作为缓存的工具
      • 9.4 虚拟内存作为内存管理的工具
      • 9.5 虚拟内存作为内存保护的工具
      • 9.6 地址翻译
      • 9.7 案例研究:Intel Core i7 / Linux 内存系统
      • 9.8 内存映射
      • 9.9 动态内存分配
      • 9.10 垃圾收集
      • 9.11 C 程序中常见的与内存有关的错误
      • 9.12 小结
      • 家庭作业
  • 第三部分:程序间的交互和通信
    • 第 10 章:系统级 I/O
      • 10.1 Unix I/O
      • 10.2 文件
      • 10.3 打开和关闭文件
      • 10.4 读和写文件
      • 10.5 用 RIO 包健壮地读写
      • 10.6 读取文件元数据
      • 10.7 读取目录内容
      • 10.8 共享文件
      • 10.9 I/O 重定向
      • 10.10 标准 I/O
      • 10.11 综合:我该使用哪些 I/O 函数?
      • 10.12 小结
      • 家庭作业
    • 第 11 章:网络编程
      • 11.1 客户端—服务器编程模型
      • 11.2 网络
      • 11.3 全球 IP 因特网
      • 11.4 套接字接口
      • 11.5 Web 服务器
      • 11.6 综合:TINY Web 服务器
      • 11.7 小结
      • 家庭作业
    • 第 12 章:并发编程
      • 12.1 基于进程的并发编程
      • 12.2 基于 I/O 多路复用的并发编程
      • 12.3 基于线程的并发编程
      • 12.4 多线程程序中的共享变量
      • 12.5 用信号量同步线程
      • 12.6 使用线程提高并行性
      • 12.7 其他并发问题
      • 12.8 小结
      • 家庭作业
  • 附录 A:错误处理
  • 参考文献
  • 实验
    • 实验总览
      • 常见问题
    • 实验 1:Data Lab
      • README(讲师版)
      • README(学生版)
      • Writeup
    • 实验 2:Bomb Lab
      • README(讲师版)
      • Writeup
    • 实验 3:Attack Lab
    • 实验 4:Architechture Lab
    • 实验 5:Cache Lab
    • 实验 6:Performance Lab
    • 实验 7:Shell Lab
    • 实验 8:Malloc Lab
    • 实验 9:Proxy Lab
由 GitBook 提供支持
在本页
  • 1. 介绍
  • 步骤 1:获得你的炸弹
  • 步骤 2:拆除你的炸弹
  • 2. 支持
  • 3. 提交
  • 4. 提示(请读这个!)
  1. 实验
  2. 实验 2:Bomb Lab

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 分。

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

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

linux> ./bomb psol.txt

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

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

2. 支持

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

3. 提交

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

http://$Bomblab::SERVER_NAME:$Bomblab::REQUESTD_PORT/scoreboard

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

4. 提示(请读这个!)

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

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

  • 每次你猜错了炸弹爆炸,你就会损失 1/2 分(最多20分)。

  • 每次你猜错了,就会有一条消息发送到 bomblab 服务器。你可能很快就会让网络中充斥着这些消息,导致系统管理员取消你的计算机访问权限。

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

  • gdb

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

    • 为了防止每次输入错误的输入时炸弹爆炸,你需要学习如何设置断点。

    • 对于在线文档,请在 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 汇编器的信息,可能比你想知道的都多。此外,网络也可能是信息的宝库。如果你被难住了,放心向你的讲师寻求帮助。

上一页README(讲师版)下一页实验 3:Attack Lab

最后更新于4年前

我们没有告诉你这些字符串有多长,也没有告诉你其中有哪些字符。即使你做了(不正确的)假设,它们的长度都小于 80 个字符,并且只包含字母,那么每个阶段都会有268026^{80}2680个猜测。这要很长时间才能跑完,作业到期了你都无法得到答案。

CS:APP 网站 有一个非常方便的单页 gdb 总结,可以打印出来用作参考。下面是使用 gdb 的一些其他提示。

http://csapp.cs.cmu.edu/public/students.html