逆向思维玩转Bomb Lab:我是如何不靠答案,用汇编和GDB推理出所有密码的
逆向思维玩转Bomb Lab:我是如何不靠答案,用汇编和GDB推理出所有密码的
1. 初识Bomb Lab:一场逆向思维的冒险
第一次接触Bomb Lab时,我就被这个实验的巧妙设计所吸引。它不像传统的编程作业那样要求你编写代码,而是让你扮演"拆弹专家"的角色,通过逆向工程的手段找出隐藏在程序中的密码。这种角色转换带来的新鲜感让我立刻投入其中。
Bomb Lab的核心是一个包含六个关卡的二进制程序,每个关卡都需要输入正确的密码才能通过。如果输入错误,"炸弹"就会爆炸——程序会立即终止并输出失败信息。我们的任务就是通过分析程序的汇编代码,找出每个关卡的正确密码。
逆向工程的关键思维:
- 从结果反推过程
- 关注程序的行为而非实现
- 利用有限的线索构建完整的逻辑链条
- 通过假设和验证不断逼近真相
2. 准备工作:搭建分析环境
在开始拆弹之前,需要准备好分析工具和环境。我选择了以下工具组合:
# 安装必要工具 sudo apt-get install gdb objdump分析工具链:
- GDB:强大的调试器,可以单步执行、查看寄存器和内存
- objdump:反汇编工具,将二进制转换为汇编代码
- strings:提取程序中的字符串常量
- hexdump:查看二进制文件内容
首先使用objdump生成汇编代码:
objdump -d bomb > bomb.asm这样我们就得到了程序的完整汇编代码,可以作为静态分析的起点。
3. 第一关:字符串比较的奥秘
第一关看似简单,却很好地引入了逆向工程的基本方法。通过分析phase_1函数的汇编代码,我发现它主要做了以下几件事:
- 调用read_line读取用户输入
- 将输入字符串与某个固定地址的字符串比较
- 根据比较结果决定是否引爆炸弹
关键线索出现在这行汇编代码:
mov $0x402400,%esi使用GDB查看这个地址的内容:
(gdb) x/s 0x402400 0x402400: "Border relations with Canada have never been better."逆向思维要点:
- 关注函数调用前后的寄存器变化
- 识别关键数据的内存地址
- 利用调试工具验证假设
4. 第二关:数字序列的规律
第二关开始引入更复杂的逻辑。通过分析phase_2函数,我发现它要求输入6个数字,并且这些数字必须满足特定的数学关系。
关键代码片段:
cmpl $0x1,(%rsp) # 第一个数字必须是1 mov -0x4(%rbx),%eax # 获取前一个数字 add %eax,%eax # 前一个数字乘以2 cmp %eax,(%rbx) # 比较当前数字是否等于前一个的两倍这揭示了一个简单的规律:每个数字都是前一个的两倍。因此正确的序列是:1, 2, 4, 8, 16, 32。
分析技巧:
- 识别循环结构
- 跟踪栈上数据的访问模式
- 理解数字在内存中的存储方式
5. 第三关:跳转表的秘密
第三关引入了更复杂的控制流结构。phase_3函数使用sscanf读取两个数字,然后根据第一个数字的值进行跳转。
关键发现:
jmpq *0x402470(,%rax,8) # 跳转表结构通过分析跳转表,我构建了第一个数字与第二个数字的对应关系:
| 第一个数字 | 第二个数字 |
|---|---|
| 0 | 207 |
| 1 | 311 |
| 2 | 707 |
| 3 | 256 |
| 4 | 389 |
| 5 | 206 |
| 6 | 682 |
跳转表分析要点:
- 识别switch-case结构
- 计算跳转目标的地址
- 理解无符号比较的含义
6. 第四关:递归函数的挑战
第四关引入了递归函数调用。phase_4要求输入两个数字,其中第一个数字需要满足func4函数的特定条件。
func4的关键逻辑:
mov %edx,%eax sub %esi,%eax mov %eax,%ecx shr $0x1f,%ecx add %ecx,%eax sar %eax这实际上是一个二分查找的变种。通过分析,我发现当输入数字为7时,func4会返回0,满足通关条件。
递归函数分析技巧:
- 跟踪函数参数和返回值
- 识别递归终止条件
- 绘制函数调用树
7. 第五关:字符转换的谜题
第五关phase_5要求输入6个字符,然后对每个字符进行转换:
movzbl (%rbx,%rax,1),%ecx # 获取字符 and $0xf,%edx # 取低4位 movzbl 0x4024b0(%rdx),%edx # 查表转换通过分析转换表,我找到了正确的字符序列对应的ASCII码:9, 15, 14, 5, 6, 7。
字符处理要点:
- 理解ASCII编码
- 识别查表操作
- 分析位操作的含义
8. 第六关:链表结构的解析
第六关是最复杂的一关,phase_6涉及链表操作。程序要求输入6个数字,然后:
- 对数字进行转换:每个数字x变为7-x
- 根据转换后的数字访问链表节点
- 确保节点值按降序排列
关键数据结构:
0x6032d0: 0x000000010000014c 0x6032e0: 0x00000002000000a8 0x6032f0: 0x000000030000039c 0x603300: 0x00000004000002b3 0x603310: 0x00000005000001dd 0x603320: 0x00000006000001bb通过分析,正确的输入序列是:4, 3, 2, 1, 6, 5。
链表分析技巧:
- 识别next指针的偏移量
- 绘制链表结构图
- 理解节点排序的逻辑
9. 隐藏关卡:二叉树的遍历
在完成所有关卡后,我发现还有一个隐藏的secret_phase。要触发它,需要在第四关输入额外的字符串"DrEvil"。
secret_phase要求输入一个数字,然后调用fun7函数进行验证。通过分析,我发现fun7实际上是在遍历一棵二叉树:
fun7: test %rdi,%rdi je .L1 mov (%rdi),%edx cmp %esi,%edx jle .L2 mov 0x8(%rdi),%rdi call fun7 add %eax,%eax jmp .L3 .L2: mov $0x0,%eax cmp %esi,%edx je .L3 mov 0x10(%rdi),%rdi call fun7 lea 0x1(%rax,%rax,1),%eax jmp .L3 .L1: mov $0xffffffff,%eax .L3: ret通过分析二叉树的结构,我找到了满足条件的数字:22。
二叉树分析要点:
- 识别左右子节点的指针偏移
- 理解递归遍历的逻辑
- 跟踪返回值的变化规律
10. 逆向工程的思维模式
通过这次Bomb Lab的实践,我总结了逆向工程的几个关键思维模式:
- 分而治之:将复杂问题分解为小问题逐个击破
- 假设验证:提出合理假设并用实验验证
- 模式识别:识别常见的代码模式和数据结构
- 工具运用:熟练使用调试和分析工具
- 耐心细致:不放过任何细节和线索
这些思维模式不仅在逆向工程中有用,在解决其他复杂问题时也同样适用。Bomb Lab不仅是一个技术练习,更是一种思维训练,它教会我们如何系统地分析和解决未知问题。
