Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
fpicker — 基于 Frida 的进程内模糊测试套件,具备 AFL++ 代理、独立主动/被动模式以及共享内存通信,用于跨平台的高性能覆盖引导漏洞发现。 | Kitploit
工具/GitHubGitHub/ttdennis/fpicker
动态分析 (沙盒)漏洞分析漏洞利用模糊测试二进制分析
GitHubttdennis/fpicker

fpicker

基于 Frida 的进程内模糊测试套件,具备 AFL++ 代理、独立主动/被动模式以及共享内存通信,用于跨平台的高性能覆盖引导漏洞发现。

查看仓库
296341年前Kitploit 审核通过

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

fpicker

fpicker 标志

fpicker 是一款基于 Frida 的模糊测试套件,提供了多种进程内模糊测试模式,例如 AFL++ 模式或被动追踪模式。它应能在 Frida 支持的所有平台上运行。

  • 安装说明
  • 构建与运行
  • 创建模糊测试 harness
  • 模式与配置

关于 fpicker 的背景信息以及其设计思路,可在一篇博客文章中找到(该文章由本人撰写)。

fpicker 基于先前在 ToothPicker 上的工作,后者是在我硕士论文期间开发的。fpicker 的大部分功能是在我任职于 ERNW 期间的工作时间内完成的。

要求与安装

运行 fpicker 所需的条件:

  • frida_compile 用于将 harness 脚本编译成一个 JS 文件
  • 在 GitHub 上的 Frida 发布页 中找到对应平台的 frida-core-devkit。
    • 根据目标平台,将库文件保存为 libfrida-core-ios.a、libfrida-core-macos.a 或 libfrida-core-linux.a。
    • 头文件(frida-core.h)同理。根据平台将其保存为 frida-core-linux.h 或 frida-core-ios.h。
    • Makefile 的编写方式允许你在同一系统上为不同系统构建(例如,你的主机系统和手机)。
    • 如果你倾向于使用特定版本,请相应调整 Makefile。
    • 要更新到最新版本,只需在构建前运行 update_frida_version.sh。

仅在 AFL++ 模式下运行所需:

  • AFL++
    • 在 macOS 上:
      • 使用 CFLAGS="-DUSEMMAP=1" 进行编译。
    • 在 iOS 上:
      • 使用 CFLAGS="-DUSEMMAP=1 -DTARGET_OS_IOS" 进行编译。

构建与运行

fpicker 可针对 macOS、iOS 或 Linux 构建。Makefile 目前仅支持在 macOS 上为 iOS 构建,但在 Linux 上使用 iOS 工具链构建 fpicker 也完全可行。

根据目标运行:

root@kitploit:~
make fpicker-macos
make fpicker-ios
make fpicker-linux

来构建 fpicker。

一旦 fpicker 构建完成,下一步需要构建模糊测试 harness:

请参阅 examples 文件夹 中的不同示例模糊测试案例。通用方法如下:

  • 为目标创建一个自定义 harness(例如 examples/test/test.js)(有关 harness 的更多信息,请参见此处)
  • 使用 frida-compile 编译自定义 harness:frida-compile test.js -o harness.js

现在 fpicker 可以开始模糊测试了。具体命令在很大程度上取决于配置和设置。下面给出几个示例情况,它们大多对应于 examples 文件夹 中的示例。

  • 以 AFL++ 代理模式运行 fpicker,附加到目标进程并模糊测试进程内的特定函数:
root@kitploit:~
afl-fuzz -i examples/test-network/in -o ./examples/test-network/out -- \\
    ./fpicker --fuzzer-mode afl -e attach -p test-network -f ./examples/test-network/harness.js
  • 以独立模式运行 fpicker,附加到服务器并运行客户端程序发送模糊测试输入:
root@kitploit:~
./fpicker --fuzzer-mode standalone -e attach -p server-process -f harness.js --input-mode cmd \\
    --command "./client-send @@" -i indir -o outdir
  • 以独立模式运行 fpicker,附加到服务器,使用自定义变异器命令进行进程内模糊测试:
root@kitploit:~
./fpicker --fuzzer-mode active --communication-mode shm -e attach -p server-process -f harness.js \\
    -i indir -o outdir --standalone-mutator cmd --mutator-command "radamsa"
  • 以被动模式运行 fpicker,附加到服务器并收集覆盖率和载荷:
root@kitploit:~
./fpicker --fuzzer-mode passive --communication-mode send -e attach -p server-process -o outdir -f harness.js
  • 以独立模式运行 fpicker,附加到远程设备上正在运行的进程,使用自定义变异器命令进行进程内模糊测试:
root@kitploit:~
./fpicker --fuzzer-mode active -e attach -p test -D remote -o examples/test/out/ -i examples/test/in/ \\
    -f fuzzer-agent.js --standalone-mutator cmd --mutator-command "radamsa"

创建模糊测试 Harness

每个目标都需要自己的模糊测试 harness。该 harness 最重要的部分是定义 Frida 的 Stalker 的入口函数,这实际上决定了在何处插入插桩。在 in-process(进程内)模式下,这很简单。该函数通常是每次模糊测试迭代中被调用的函数。然而,它也可以是其他函数。

一个最小化的 harness 实现(在 command 模式下)可以是这样的:

root@kitploit:~
// 导入模糊测试器基类
const Fuzzer = require("harness/fuzzer.js");

// 自定义模糊测试器需要继承 Fuzzer 类才能正常工作
class TestFuzzer extends Fuzzer.Fuzzer {
    constructor() {
        // 构造函数需要指定目标函数的地址和一个 NativeFunction
        // 对象,该对象之后可以被模糊测试器调用。

        const FUZZ_FUNCTION_ADDR = Module.getExportByName(null, "FUZZ_FUNCTION");
        const FUZZ_FUNCTION = new NativeFunction(
            FUZZ_FUNCTION_ADDR,
            "void", ["pointer", "int64"], {
        });

        super("test", FUZZ_FUNCTION_ADDR, FUZZ_FUNCTION);
    }
}

const f = new TestFuzzer();
exports.fuzzer = f;

这个 harness 配置插桩以追踪函数 FUZZ_FUNCTION。插桩在该函数进入时开始,并在函数返回时停止。应仔细选择此函数,因为其开销较大,并且进程中被插桩的部分越多(可能是不重要的部分),模糊测试器就会越慢。当然,这是一个速度与所需覆盖率之间的权衡。此外,当前模糊测试器仅支持在每次模糊测试迭代中只进入一次的函数,即,在一次模糊测试用例中该函数不应被调用超过一次,否则覆盖率信息可能变得不可靠。

当使用 in-process 模式时,模糊测试器脚本中还需要另一个方法:fuzz 方法。它将在每次迭代中被调用。调用时会传入两个参数:一个指向缓冲区的指针和缓冲区的长度。我们的示例目标函数接受两个参数:一个指向缓冲区的指针及其长度。因此,我们可以直接将 fuzz 方法中获取的参数传递给它。

root@kitploit:~
fuzz(payload, len) {
    this.target_function(payload, parseInt(len));
}

在 passive(被动)模式下,需要指定一个回调函数来处理所需数据。模糊测试器期望接收一个载荷缓冲区及其长度。根据所模糊测试的目标函数,需要提取这些数据。在下面的示例中,我们再次有一个带有两个参数的函数:一个指向缓冲区的指针及其长度。args 参数包含目标函数接收到的所有潜在参数,因此长度参数(在我们的例子中是第二个)可以通过 args[1] 访问。然后我们将缓冲区读取为 Uint8Array,并使用 sendPassiveCorpus 方法将其发送回模糊测试器。

root@kitploit:~
passiveCallback(args) {
    const len = args[1];
    const data = new Uint8Array(Memory.readByteArray(args[0], parseInt(len)));

    // 这将数据编码并发送回模糊测试器
    this.sendPassiveCorpus(data, len);
}

如果目标需要在模糊测试器启动前进行某种准备,fpicker 提供了一个 prepare 方法,该方法在模糊测试器初始化期间被调用。准备工作可以是建立状态,例如,通过实例化一个对象。这样的准备函数可能如下所示:

root@kitploit:~
prepare() {
  // 可以将对象附加到模糊测试器实例上,以便稍后在 fuzz() 方法中使用。
  this.required_object = call_native_function_that_creates_object();
}

模式与配置

fpicker 提供了大量模式和配置,下面将进行解释。大部分模式可以以不同方式组合。本节末尾有一个表格,显示了哪些选项可以组合以及它们的实现状态。

模糊测试器模式

fpicker 有三种不同的 模糊测试模式:AFL++ 模式、独立主动模式和独立被动模式:

  • AFL++ 模式: 在 AFL++ 模式下,fpicker 充当 AFL++ 和目标进程之间的代理。利用 Frida 的插桩能力,在使用 AFL++ 生成的输入数据模糊测试目标时,填充 AFL 的覆盖率位图。

  • 独立主动模式: 在独立主动模式下,模糊测试器使用 Frida 的 Stalker 调用摘要 来收集覆盖率,即每次迭代中执行的基本块。这并非新事物,之前已有多种形式的实现。然而,与其他一些模糊测试器设置结合使用时,它可以带来各种好处。在 AFL++ 不适用或不被期望的环境或场景下,它也是一个很好的替代方案。

  • 独立被动模式: 被动模式与其说是模糊测试器,不如说是一个追踪器。本质上,它与独立主动模式做相同的事情。然而,它 不 发送自己的输入。它只是附加到某个函数并收集覆盖率。一旦观察到新的覆盖率,就会存储覆盖率和输入。

输入模式

虽然 fpicker 主要设计为进程内模糊测试器,但它也支持通过外部命令进行模糊测试。为此,fpicker 提供了两种输入模式。

  • 输入模式 - 进程内: 在进程内输入模式下,harness 直接调用目标进程中的指定函数。模糊测试器将载荷发送给 harness,harness 以能够调用目标函数的方式准备载荷。

  • 输入模式 - CMD: 在命令输入模式下,载荷被重定向到外部命令。当直接调用目标函数时,如果准备参数或其他状态过于复杂,这很有用。覆盖率收集仍需附加到某个函数。可能有一个客户端,可以向其提供载荷,然后触发目标函数。

通信模式

通信模式决定了注入的 harness 如何与模糊测试器通信。这在很大程度上取决于目标应用程序。Frida 提供了一个 API 用于从注入的代理脚本发送和接收消息。这种通信类型开销相当大。其中一个因素是传输的消息需要编码为 JSON。因此发送二进制数据并不直接。为此,fpicker 提供了第二种基于共享内存的通信模式。然而,这仅在可以在模糊测试器和目标应用程序之间建立共享内存时才有效,这意味着当目标通过 USB 连接到模糊测试器主机时,无法使用此模式。在 CMD 输入模式下,通信模式仅指覆盖率信息如何传回模糊测试器,而不是指载荷如何发送,因为后者已交由外部命令处理。

  • 通信模式 - Send: 在发送通信模式下,通过使用 Frida 的 RPC 调用机制发送载荷。这允许模糊测试器在注入的 harness 脚本中执行一个 JavaScript 函数。harness 内部的这个函数然后可以进行所有必要的准备工作来调用目标函数。一旦目标函数返回,覆盖率收集将停止,并且 harness 可以通知模糊测试器迭代已完成。这是通过使用 Frida 的 send API 将覆盖率信息发送回模糊测试器来完成的。

  • 通信模式 - SHM: 在 SHM 通信模式下,模糊测试器和 harness 脚本通过共享内存和信号量进行通信。共享内存中的缓冲区用于发送载荷和接收覆盖率信息。两个组件不是发送和接收,而是使用等待和发布信号量操作。根据系统和目标的不同,这可以带来相当可观的性能提升。特别是因为二进制载荷被写入内存一次,无需编码、解码或复制到其他内存位置。不幸的是,这种模式有时在使用 AFL++ 运行时会导致较低的稳定性。目前还不清楚原因。

执行模式

执行模式可以是 spawn(生成)或 attach(附加)。这很容易理解。fpicker 既可以附加到正在运行的进程,也可以生成一个进程。两种模式的一个主要区别是,如果附加的目标崩溃,fpicker 不会尝试重新生成。

独立突变器

在独立模式下,fpicker 提供了三种不同的输入突变策略。坦白说,输入突变仍有很大的改进空间。

  • 独立突变器 NULL: 此突变器不对载荷进行突变,仅返回同一载荷的副本。主要用于测试目的。否则并不真正有用。

  • 独立突变器 Rand: 一个非常糟糕的随机突变器。它所做的只是在原始载荷的随机位置随机替换值。它不会改变载荷长度。

  • 独立突变器 Custom: 此突变器可以调用外部命令来突变载荷。它将载荷写入 stdin,并从 stdout 接收突变后的载荷。由于其实现较为浅显,对性能有相当大的影响。

USB 设备

使用 -D usb 设备选项,Frida 将选择第一个本地 USB 设备,例如 iPhone 或 Android 手机。

网络设备

使用 -D remote 选项,可以模糊测试在远程网络设备上运行的进程。为此,远程设备必须正在运行 frida-server。作为一个示例配置,使用 SSH 端口转发,将远程设备上的 frida-server 默认监听端口 27042 绑定到本地客户端的一个套接字。

root@kitploit:~
ssh -N [email protected] -L 127.0.0.1:27042:127.0.0.1:27042

在 iPhone 上,还可以使用 iproxy 从 USB 连接转发端口。 这在使用非标准端口上的 Frida gadget 运行于非越狱设备上时可能特别有用。当使用 Frida gadget 时,无论目标应用名称是什么,唯一可用的进程名称将是 Gadget。

root@kitploit:~
iproxy 27042 27042

然后使用 frida-ps 通过列出远程设备上的进程来验证配置:

root@kitploit:~
frida-ps -R
下载工具