Note
- 具体代码请移步至GitHub.
Bomb Lab
实验目的
对可执行文件 bomb
进行调试, 深入其汇编代码, 依次推断出 6 个密码并通过相应 6 个阶段的考验. 除了这 6 个考验以外还存在第七个隐藏考验, 因此实际上共有 7 个阶段的考验以及对应的密码, 具体见下方小节.
实验框架
bomb
- 待调试文件主体
bomb
为可执行文件, 需要对其进行调试并破解得到 6 个密码 (加上隐藏考验总共为 7 个密码).
bomb.c
- 描述主体构成
bomb.c
中使用 C 程序描述了炸弹 bomb 的主体构成, 其中 support.h
与 phases.h
猜测是实现炸弹本体的代码的头文件.
观察 bomb.c
可得到 bomb 的构成如下:
- 首先检查命令行中是否给出文件路径, 并打开标准输入/给定文件.
- 初始化炸弹:
initialize_bomb();
- 连续执行 6 个阶段, 每个阶段均为读入一行输入, 将输入用于解密, 若解密成功则可顺序进入下一阶段, 若 6 个阶段均解密成功则函数退出 (炸弹解除).
- 此外还可选择挑战第七个隐藏考验.
评价标准
- 前 4 个考验每个分别占 10 分, 最后 2 个考验每个占 15 分. 总分为 70 分.
- 对于校内的同学, 每次炸弹爆炸将会向服务器发送一个消息并在最终得分中减去 0.5 分 (最多不超过 20 分, 即 40 次爆炸).
实验思路与总结
目录结构:
- 可执行文件
bomb
的反汇编内容见文件objdump_bomb.txt. - 下列所有函数的机器指令的具体解释见目录disas-output, 某些特定函数所需要的额外信息 (例如跳转表或全局字符串等) 将会在对应的
disas_xxx.txt
文件开头列出. - 测试通过的 7 个密码见文件password.txt.
sig_handler
对炸弹拆除进度进行安全重置 :-)
.
initialize_bomb
函数 initialize_bomb
使用 C 库函数 signal
为信号 SIGINT
安装处理程序 sig_handler
.
string_length
函数 string_length
返回所传入字符串的长度.
strings_not_equal
函数 strings_not_equal
检查传入的 2 个字符串是否相同.
explode_bomb
函数 explode_bomb
输出 "炸弹拆除失败" 的提示信息并终止整个程序.
phase_defused
函数 phase_defused
首先检查是否已经通过前 6 个阶段, 若仍未通过前 6 个阶段则直接返回; 若已经通过前 6 个阶段则尝试从第四个阶段的密码中读取开启隐藏阶段的口令, 若口令读取成功并且与一个已知字符串相同则进入隐藏阶段; 否则输出 "成功拆除炸弹" 的提示信息并返回.
read_six_numbers
函数 read_six_numbers
从传入的字符串中读取 6 个整数.
func4
函数 func4
在一个给定范围内对目标值进行二分查找, 并在递归过程中按一定规则产生最终的返回值.
- 注: 在二分查找时还
func4
还实现了补码下整数除以 2 的幂的算法.
fun7
函数 fun7
在一棵简单的二叉搜索树中查找给定整数, 并在递归过程中按一定规则产生最终的返回值.
phase_1
函数 phase_1
通过调用函数 strings_not_equal
来比较密码是否与一个已知字符串相同.
phase_2
函数 phase_2
首先调用函数 read_six_numbers
从密码中读入 6 个整数, 然后检查这 6 个整数是否满足特定规则.
phase_3
函数 phase_3
首先调用函数 sscanf
读入 2 个整数, 然后实现了一个简单的 C 语言 switch
语句来检查这 2 个数字是否满足特定规则.
phase_4
函数 phase_4
首先调用函数 sscanf
读入 2 个整数, 然后将第一个整数传入函数 func4
并得到 1 个整数结果, 最后检查所返回的整数结果以及第二个整数是否满足特定规则.
phase_5
函数 phase_5
将输入的密码字符串看作是一串整数数组, 通过将数组中的整数作为下标索引某个字母表来将整数数组映射为长度相等的新字符串, 最后比较新字符串是否与一个已知字符串相同.
phase_6
函数 phase_6
首先调用函数 read_six_numbers
从密码中读取 6 个整数, 并使用这 6 个整数从某个全局链表中依次挑选出 6 个结点并连接形成一个新的链表, 最后检查新的链表中的值是否满足特定规则.
secret_phase
函数 secret_phase
首先调用 read_line
函数读入第七个密码, 然后使用 C 库函数 strtol
将其转换为整数, 将该整数传入函数 fun7
得到结果, 最后检查该结果是否满足特定规则.
实验结果展示
见目录 disas-output 下的所有反汇编代码 (已详细注释).
相关资料
GDB
- Beej's Quick Guide to GDB
- GDB: The GNU Project Debugger
- gdbnotes-x86-64.pdf
- How to highlight and color gdb output during interactive debugging? - stackoverflow
Linux 命令
objdump -t <binary-executable>
:- 打印符号表 (symbol table).
objdump -d <binary-executable>
:- 反汇编. 对于像系统调用 (例如
sscanf
) 这样的函数而言, 反汇编得到的函数名有可能不是很直观, 此时在 gdb 中进行反汇编是更好的选择.
- 反汇编. 对于像系统调用 (例如
strings <binary-executable>
:- 打印可执行文件中的所有可打印字符串.
man ascii
:- 打印关于 ascii 编码的相关文档.
info gas
:打印关于 gas 的文档. 如果报错
info: No menu item 'gas' in node '(dir)Top'
, 需要检查binutils
包是否安装:1 2 3 4 5 6
# Check if binutils is installed which as # If binutils is not installed, install it sudo apt-get update sudo apt-get install binutils
如果已经安装, 再检查是否安装文档 (因为有些 Linux 发行版可能会将 doc 和 software 分开打包):
1 2
# Install documentation for binutils, which includes gas sudo apt-get install binutils-doc