Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
fpicker — Frida-based in-process fuzzing suite with AFL++ proxy, standalone active/passive modes, and shared memory communication for high-performance coverage-guided vulnerability discovery across platforms. | Kitploit
Tools/GitHubGitHub/ttdennis/fpicker
Dynamic Analysis (Sandboxing)Vulnerability AnalysisExploitationFuzzingBinary Analysis
GitHubttdennis/fpicker

fpicker

Frida-based in-process fuzzing suite with AFL++ proxy, standalone active/passive modes, and shared memory communication for high-performance coverage-guided vulnerability discovery across platforms.

View Repository
29634221 year agoReviewed by Kitploit

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

fpicker

Fpicker logo

fpicker is a Frida-based fuzzing suite that offers a variety of fuzzing modes for in-process fuzzing, such as an AFL++ mode or a passive tracing mode. It should run on all platforms that are supported by Frida.

  • Installation Instructions
  • Building and Running
  • Creating a Fuzzing Harness
  • Modes and Configuration

Some background information and the thoughts and ideas behind fpicker can be found in a blogpost I wrote.

Fpicker is based on previous efforts on ToothPicker, which was developed during my master thesis. Most of fpicker was developed during working hours at my employer (ERNW).

Requirements and Installation

Required for running fpicker:

  • frida_compile to compile the harness script into one JS file
  • The frida-core-devkit for the respective platform found at Frida releases on GitHub.
    • Depending on the platform you want to target store the library as libfrida-core-ios.a, libfrida-core-macos.a, or libfrida-core-linux.a.
    • The same goes for the header files (frida-core.h). Store them as frida-core-linux.h or frida-core-ios.h depending on the platform.
    • The makefile was built this way so you can build for different systems on the same system (e.g., your host system and the phone).
    • If you prefer to use a specific version, adjust the Makefile accordingly.
    • To update to the latest version, simply run update_frida_version.sh before building.

Required only when running in AFL++ mode:

  • AFL++
    • on macOS:
      • Compile with CFLAGS="-DUSEMMAP=1".
    • on iOS:
      • Compile with CFLAGS="-DUSEMMAP=1 -DTARGET_OS_IOS".

Building and Running

Fpicker can be built for macOS, iOS or Linux. The Makefile currently only supports building for iOS on macOS but it should be totally possible to build fpicker using an iOS toolchain on Linux.

Depending on the desired target run:

make fpicker-macos
make fpicker-ios
make fpicker-linux

to build fpicker.

Once fpicker is built, the fuzzing harness needs to be built next:

See the examples folder for different sample fuzzing cases. The general approach is as follows:

  • Create a custom harness for the target (e.g. examples/test/test.js) (see here for more information on harnesses)
  • Compile the custom harness using frida-compile frida-compile test.js -o harness.js

Now fpicker can start fuzzing. The exact command highly depends on the configuration and setup. In the following, a few example cases are given. These mostly correspond to the examples in the examples folder.

  • Run fpicker as AFL++ proxy attaching to a target process fuzzing a specific function in process:
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
  • Run fpicker in standalone mode attaching to a server and running a client program to send the fuzzing input:
./fpicker --fuzzer-mode standalone -e attach -p server-process -f harness.js --input-mode cmd \\
    --command "./client-send @@" -i indir -o outdir
  • Run fpicker in standalone mode attaching to a server, fuzzing in-process with a custom mutator cmd:
./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"
  • Run fpicker in passive mode attaching to a server collecting coverage and payloads:
./fpicker --fuzzer-mode passive --communication-mode send -e attach -p server-process -o outdir -f harness.js
  • Run fpicker in standalone mode attaching to a running process on a remote device, fuzzing in-process with a custom mutator cmd:
./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"

Creating a Fuzzing Harness

Each target requires its own fuzzing harness. The most important part of this harness is defining the entry function of Frida's Stalker, which effectively determines at which point the instrumentation is inserted. In the in-process mode this is simple. The function would usually be the one that is called on each fuzzing iteration. However, it could also be a different one.

A minimalist harness implementation (in command mode) could be this:

// Import the fuzzer base class
const Fuzzer = require("harness/fuzzer.js");

// The custom fuzzer needs to subclass the Fuzzer class to work properly
class TestFuzzer extends Fuzzer.Fuzzer {
    constructor() {
        // The constructor needs to specify the address of the targeted function and a NativeFunction
        // object that can later be called by the fuzzer.

        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;

This harness configures the instrumentation to follow the function FUZZ_FUNCTION. The instrumentation will start when this function is entered and stops when the function returns. This function should be chosen carefully as it is expensive and the more (potentially unimportant) parts of the process are instrumented, the slower the fuzzer gets. Of course, this is a consideration between speed and intended coverage. Additionally, the fuzzer currently only supports functions that are only entered once during one fuzzing iteration, i.e., the function should not be called more than once during one fuzz case, otherwise the coverage information might become unreliable.

When the in-process mode is used, another function is required in the fuzzer script. The fuzz method. It will get called on each iteration. It will be called with two parameters, a pointer to a buffer and the length of the buffer. Our exemplary target function takes two parameters, a pointer to a buffer and its length. Thus, we can just pass the parameters were getting in the fuzz method.

fuzz(payload, len) {
    this.target_function(payload, parseInt(len));
}

In passive mode, a callback needs to be specified that processes the required data. The fuzzer expects to receive a payload buffer and its length. Depending on the target function that is fuzzed, this data needs to be extracted. In the following example, we again have a function that has two parameters: a pointer to a buffer and its length. The args parameter contains all potential parameters the target function receives, so the length parameter (which is the second one in our case) can be accessed with args[1]. We then read the buffer as Uint8Array and send it back to the fuzzer using the sendPassiveCorpus method.

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

    // this encodes the data and sends it back to the fuzzer
    this.sendPassiveCorpus(data, len);
}
Download Tool