一、实验目的
- 提升汇编语言逆向分析能力
- 理解程序控制流与内存管理的底层机制
- 掌握动态调试(GDB)与静态分析(objdump)结合的技术
- 培养解决复杂问题的系统性思维
二、实验环境
- 操作系统:Ubuntu 22.04 LTS (64位)
- 工具链:
-
bomblab压缩包——下载bomblab压缩包并输入$ tar –xvf bomb.tar进行解压缩,下载地址:CS:APP3e, Bryant and O'Hallaron,点击handout即可下载(在虚拟机里面)
objdump
反汇编器——使用命令objdump -d bomb > bomb.asm将bomb变成asm文件则可以直接用vim打开修改GDB
调试器 (版本 12.1)——在终端使用命令:sudo apt-get install gdb安装hexedit
二进制查看工具
-
三、实验内容与详细分析
Phase_1:字符串匹配
反汇编代码关键片段
0000000000400ee0 <phase_1>:
400ee0: 48 83 ec 08 sub $0x8,%rsp
400ee4: be 00 24 40 00 mov $0x402400,%esi ; 预设字符串地址
400ee9: e8 4a 04 00 00 callq 401338 <strings_not_equal>
400eee: 85 c0 test %eax,%eax
400ef0: 74 05 je 400ef7 <phase_1+0x17>
400ef2: e8 43 05 00 00 callq 40143a <explode_bomb>
破解步骤
-
定位字符串地址:通过
mov $0x402400,%esi
确定预设字符串存放地址 -
查看内存内容:
(gdb) x/s 0x402400 -> "Border relations with Canada have never been better."
-
验证答案:输入该字符串即可通过
-
整体运行指令图(Ctrl+D可以退出gdb):
Phase_2:等比数列验证
反汇编代码关键逻辑
400f02: 83 7c 24 04 01 cmpl $0x1,0x4(%rsp) ; 检查第一个数是否为1
400f0a: 39 d8 cmp %ebx,%eax ; 比较当前数与前一个数×2
400f17: 83 c3 01 add $0x1,%ebx ; 循环计数器递增
破解步骤
- 输入要求:6个整数组成的等比数列
- 数学关系:an=2×an−1an=2×an−1,初始值为1
- 答案示例:
1 2 4 8 16 32
Phase_3:跳转表与分支选择
反汇编代码关键逻辑
400f6a: ff 24 c5 70 24 40 00 jmpq *0x402470(,%rax,8) ; 跳转表基地址
400f75: b8 37 01 00 00 mov $0x137,%eax ; 对应分支目标值
破解步骤
-
查看跳转表:
(gdb) x/8a 0x402470 -> 0x400f7c, 0x400fb9, ... # 各分支入口地址
-
分支匹配:选择第一个输入为1,对应第二个输入需为311(0x137)
-
答案示例:
1 311
Phase_4:递归函数终止
反汇编代码关键逻辑
40103e: 8d 7c 24 10 lea 0x10(%rsp),%edi
401042: e8 81 ff ff ff callq 400fc8 <func4> ; 递归调用
401058: 83 f8 00 cmp $0x0,%eax ; 要求返回值为0
破解步骤
- 递归分析:
func4
需要返回0 - 输入验证:输入
7 0
可满足终止条件 - 栈帧查看:
(gdb) x/2wx $rsp+0x10 # 查看输入数值存储位置
Phase_5:字符映射转换
反汇编代码关键逻辑
40108b: 0f b6 0c 03 movzbl (%rbx,%rax,1),%ecx ; 取字符低4位
40108f: 88 0c 24 mov %cl,(%rsp)
401092: 48 8b 14 24 mov (%rsp),%rdx
401096: 83 e2 0f and $0xf,%edx ; 取低4位作为索引
401099: 0f b6 92 b0 24 40 00 movzbl 0x4024b0(%rdx),%edx ; 查表
破解步骤
-
字符表查看:
(gdb) x/s 0x4024b0 -> "maduiersnfotvbyl"
-
映射关系:输入字符ASCII码低4位对应表中字符
-
示例答案:
"9?>567"
(映射结果为"ionefg")
Phase_6:链表节点排序
反汇编代码关键逻辑
4011ab: 8b 52 08 mov 0x8(%rdx),%edx ; 遍历链表节点
4011d7: 48 89 d1 mov %rdx,%rcx ; 节点指针交换
4011f5: 41 89 04 94 mov %eax,(%r12,%rdx,4) ; 存储排序结果
破解步骤
-
链表结构分析:
(gdb) x/24wx 0x6032d0 -> Node1: 0x14c (data), 0x6032e0 (next) Node2: 0x0a8 (data), 0x6032f0 (next)
-
排序要求:按节点
data
降序排列输入序号 -
答案示例:
4 3 2 1 6 5
总结果:
所有Phase完成之后的结果应该如下:
四、隐藏阶段触发方法
- 触发条件:在Phase_4答案后追加字符串
"DrEvil"
- 调试验证:
(gdb) break secret_phase (gdb) x/s 0x402619 # 查看隐藏提示信息
五、实验总结
1. 关键技术收获
- 逆向工程技能:通过反汇编与动态调试理解程序控制流
- 内存分析能力:掌握查看寄存器、栈空间与全局数据区的方法
- 算法逆向能力:从机器代码还原递归、循环等高级语言结构
- 系统安全意识:理解缓冲区验证与输入过滤的重要性
2. 难点与突破
阶段 | 核心难点 | 解决方法 |
---|---|---|
Phase3 | 跳转表分支匹配 | 结合内存查看与寄存器跟踪 |
Phase5 | 字符映射关系推导 | ASCII码位运算分析 |
Phase6 | 链表指针操作逻辑还原 | 逐节点内存查看与数据对比 |
3. 实验意义
- 教学价值:将抽象的汇编指令与具体的程序行为建立直接关联
- 工程意义:培养从二进制层面诊断软件问题的能力
- 安全启示:揭示输入验证不足导致的漏洞风险
附录:实验关键数据速查表
地址 | 内容描述 | 示例值/用途 |
---|---|---|
0x402400 | Phase_1预设字符串 | "Border relations..." |
0x402470 | Phase_3跳转表基地址 | 分支入口地址列表 |
0x4024b0 | Phase_5字符映射表 | "maduiersnfotvbyl" |
0x6032d0 | Phase_6链表起始节点 | Node1 {332, 0x6032e0} |