讲一下 AFL 的插桩原理

插桩的本质:反馈导向的模糊测试

AFL 的插桩(instrumentation)就是一套用于收集代码覆盖率的探针。通过这些探针,AFL 可以知道某个输入执行了哪些代码路径

它的工作流程是这样的:

  1. 编译时插桩:用 AFL 提供的特殊编译器(afl-clang-fastafl-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
Copyright © 版权信息 all right reserved,powered by Gitbook该文件修订时间: 2025-09-25 03:13:09

results matching ""

    No results matching ""