GDB 实战拆解 CSAPP BombLab5 个核心命令定位 Phase 5 隐藏字符串在计算机系统课程中BombLab 是一个极具挑战性的实验项目它要求我们通过逆向工程的手段逐步拆解一个包含多个阶段的二进制炸弹。本文将聚焦于 Phase 5展示如何仅用 GDB 的 5 个核心命令x/s, x/16bx, info registers, break, stepi来独立发现并破解这一阶段的隐藏逻辑。1. 实验环境准备首先需要配置好调试环境。我们推荐使用以下 GDB 初始化脚本保存为 .gdbinit 文件set disassembly-flavor intel layout asm break phase_5 run这个脚本会设置反汇编风格为 Intel 语法更易读打开汇编代码视图在 phase_5 函数处设置断点自动运行程序关键工具链版本信息工具版本用途GDB10.1调试分析objdump2.36反汇编Ubuntu20.04运行环境2. Phase 5 初步分析当程序执行到 phase_5 时我们首先观察函数入口处的汇编代码phase_5: push rbx sub rsp,0x20 mov rbx,rdi ; 保存输入字符串指针 mov rax,QWORD PTR fs:0x28 ; 栈保护 mov QWORD PTR [rsp0x18],rax xor eax,eax call 40131b string_length cmp eax,0x6 je 4010d2 phase_50x70 ; 输入长度必须为6 call 40143a explode_bomb这里已经可以获取两个关键信息输入必须是一个长度为6的字符串输入字符串指针保存在 rbx 寄存器使用 GDB 命令验证(gdb) x/s $rbx test123 ; 示例输入 (gdb) p $eax $1 7 ; 字符串长度3. 关键数据结构解析接下来程序会进入一个循环结构这是 Phase 5 的核心逻辑40108b: movzx ecx,BYTE PTR [rbxrax*1] ; 取第rax个字符 40108f: mov BYTE PTR [rsp],cl 401092: mov rdx,QWORD PTR [rsp] 401096: and edx,0xf ; 取低4位 401099: movzx edx,BYTE PTR [rdx0x4024b0] ; 查表 4010a0: mov BYTE PTR [rsprax*10x10],dl 4010a4: add rax,0x1 4010a8: cmp rax,0x6 4010ac: jne 40108b phase_50x29这段代码揭示了一个查表转换过程遍历输入字符串的每个字符取字符的 ASCII 码低4位作为索引通过索引从内存地址 0x4024b0 处查表获取新字符使用 GDB 查看这个关键的数据表(gdb) x/16bx 0x4024b0 0x4024b0 array.3449: 0x6d 0x61 0x64 0x75 0x69 0x65 0x72 0x73 0x4024b8 array.34498:0x6e 0x66 0x6f 0x74 0x76 0x62 0x79 0x6c将其转换为 ASCII 字符| 索引 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | a | b | c | d | e | f | |------|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---| | 字符 | m | a | d | u | i | e | r | s | n | f | o | t | v | b | y | l |4. 逆向推导输入条件程序在转换后会进行字符串比较4010ae: mov BYTE PTR [rsp0x16],0x0 4010b3: mov esi,0x40245e 4010b8: lea rdi,[rsp0x10] 4010bd: call 401338 strings_not_equal 4010c2: test eax,eax 4010c4: je 4010d9 phase_50x77 4010c6: call 40143a explode_bomb查看目标字符串(gdb) x/s 0x40245e 0x40245e: flyers因此我们需要找到一个6字符的输入经过查表转换后得到flyers。根据之前的表我们可以建立索引映射目标字符flyers表索引9fe567十进制91514567接下来推导原始输入字符。根据查表逻辑输入字符的 ASCII 码低4位必须等于上述索引值。例如第一个字符ASCII 0xf 9 可能的 ASCII 值)(0x29), 9(0x39), I(0x49), Y(0x59), i(0x69), y(0x79)5. 构建有效输入通过上述分析我们可以构建一个可行的输入方案。选择可打印字符得到以下对应关系位置目标索引可选字符19) 9 I Y i y215 (0xf)/ ? O _ o314 (0xe). N ^ n ~45% 5 E U e u56 6 F V f v67 7 G W g w一个可行的解是 ionefg验证过程如下获取每个字符的 ASCII 码 i(0x69), o(0x6f), n(0x6e), e(0x65), f(0x66), g(0x67)取低4位 9, f, e, 5, 6, 7查表转换 m a d u i e r s n f o t v b y l 9→f, f→l, e→y, 5→e, 6→r, 7→s组合结果 flyers - 匹配目标字符串6. 自动化调试脚本为了更高效地调试可以准备以下 GDB 脚本保存为 phase5.gdbbreak *0x40108b commands printf Processing char %d: %c (0x%x)\n, $rax, [$rbx$rax], [$rbx$rax] x/1bx $rbx$rax info registers rdx end break *0x4010b3 commands x/s $rsp0x10 x/s 0x40245e end使用方式(gdb) source phase5.gdb (gdb) run这个脚本会在两个关键位置中断字符处理循环开始处显示当前处理的字符信息字符串比较前显示转换结果和目标字符串7. 通用分析流程总结通过这个案例我们可以总结出分析循环查表类汇编代码的通用流程确定输入格式使用 string_length 或类似函数判断输入要求检查输入存储位置寄存器/栈地址识别循环结构查找循环计数器如 rax定位循环开始和结束指令分析数据处理逻辑跟踪每个输入字节的处理过程注意位操作AND, OR, SHIFT等识别关键数据表的内存地址逆向推导条件确定最终比较的目标值反向映射处理逻辑考虑多解情况验证解决方案在调试器中测试候选输入单步跟踪处理过程检查中间结果这种分析方法不仅适用于 BombLab也可以应用于其他类似的逆向工程场景。关键在于耐心地跟踪数据流逐步构建对程序逻辑的完整理解。