Files
Sec-Interview/Chapter26/26-16.md
T
2025-09-25 04:04:35 +08:00

38 lines
2.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
### 讲一下 AFL 的插桩原理
**插桩的本质:反馈导向的模糊测试**
AFL 的插桩(instrumentation)就是一套用于收集**代码覆盖率**的探针。通过这些探针,AFL 可以知道某个输入执行了哪些代码路径
它的工作流程是这样的:
1. **编译时插桩**:用 AFL 提供的特殊编译器(`afl-clang-fast``afl-gcc`)来编译目标程序
2. **运行时反馈**:当程序执行时,插桩代码会向 AFL 反馈代码执行路径信息
3. **智能变异**:AFL 根据这些反馈,判断哪些输入“有价值”(即探索了新的代码路径),然后对这些有价值的输入进行更多的变异
这个反馈循环是 AFL 高效的关键。它使得 AFL 能够自动绕过复杂的输入校验,深入到程序更深层次的逻辑中,从而找到隐藏的漏洞
**插桩的原理实现**
AFL 的插桩非常轻量级,它采用了一种基于**基本块(Basic Block)**的简单而巧妙的方案。
**1. 什么是基本块?**
在程序中,一个基本块是一段连续的代码,它只有一个入口点(第一条指令)和一个出口点(最后一条指令),且中间没有任何分支跳转
你可以把基本块看作是代码中的最小“执行单元”
**2. AFL 的插桩步骤**
AFL 在编译时,会在**每个基本块的入口**插入一段代码。这段代码会做两件事:
- **获取当前基本块的 ID**:AFL 在编译时会给每个基本块分配一个唯一的随机 ID
- **记录基本块的 ID**:AFL 维护一个**共享内存区域**,通常是一个大小为 64KB 的位图(bitmap
当程序执行到一个新的基本块时,插入的代码会执行以下操作:
1. 获取当前基本块的 ID(假设是 `current_id`
2. 获取**上一个**执行的基本块的 ID(假设是 `prev_id`)。AFL 用一个全局变量来保存这个 `prev_id`
3. 计算一个哈希值:`index = current_id XOR prev_id`
4. 将这个 `index` 映射到位图的某个位置,并将该位置的值加 1
5. 更新 `prev_id`,使其等于 `current_id`