fpicker: Frida-based fuzzing suite
fpicker
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.
Fpicker is based on previous efforts on ToothPicker, which was developed during my master thesis. Most of the fpicker was developed during working hours at my employer (ERNW).
Modes and Configuration
pficker offers a large set of modes and configurations that are explained in the following. Most of these modes can be combined in different ways. At the end of this section is a table that shows which options can be combined and what their implementation status is.
Fuzzer Mode
Fpicker has three different fuzzing modes: AFL++ Mode, Standalone Active Mode, and Standalone Passive Mode:
- AFL++ Mode: In AFL++ mode, fpicker acts as a proxy between AFL++ and the target process. Using Frida’s instrumentation capabilities, AFL’s coverage bitmap is populated while the target is fuzzed with input data generated by AFL++.
- Standalone Active Mode: In standalone active mode, the fuzzer uses Frida’s Stalker call summaries to gather coverage in form of basic blocks that are executed during an iteration. This is nothing new and has been implemented in various forms before. However, in combination with some of the other fuzzer settings, this can have various benefits. It is also a good alternative if AFL++ is not applicable or desired in a given environment or case.
- Standalone Passive Mode: Passive mode is less of a fuzzer and more of a tracer. Essentially, it does the same as standalone active mode. However, it does not send its own inputs. It just attaches to a certain function and collects coverage. Once new coverage is observed, both the coverage and the input is stored.
Input Mode
While fpicker is largely designed as an in-process fuzzer, it also supports fuzzing via an external command. For this fpicker offers two input modes.
- Input Mode In-Process: In in-process input mode, the harness directly calls a specified function in the target process. The fuzzer sends the payload to the harness and the harness prepares the payload in such a way that it can call the targeted function.
- Input Mode CMD: In command input mode, the payload is redirected to an external command. This is useful it is too complex to prepare the parameters another other state when directly calling the target function. The coverage collection still needs to be attached to a certain function. Maybe there is a client that can be supplied with a payload which then triggers the target function.
Communication Mode
Communication mode determines how the injected harness communicates with the fuzzer. This largely depends on the target application. Frida offers an API to send and receive messages from the injected agent script. This type of communication is quite costly. One of the factors is that the transported message needs to be encoded in JSON. So sending binary data is straight-forward. Therefore, fpicker offers a second communication mode over shared memory. However, this only works if it is possible to establish shared memory between the fuzzer and the target application, which means that this mode cannot be used when the target is attached to the fuzzer host via USB. In CMD input mode, the communication mode only refers to how the coverage information is communicated back to the fuzzer, not how the payload is sent, as this is deferred to an external command.
- Communication Mode Send: In send communication mode the payload is sent by using Frida’s RPC calling mechanism. This lets the fuzzer execute a JavaScript function within the injected harness script. This function inside the harness can then do all the necessary preparations to call the target function. Once the target function is returned from, coverage collection will stop and the harness can signal the fuzzer that the iteration is finished. This is done by sending the coverage information back to the fuzzer using Frida’s send API.
- Communication Mode SHM: In SHM communication mode the fuzzer and the harness script communicate via shared memory and semaphores. A buffer in shared memory is used to send the payload and receive the coverage information. Instead of sending and receiving, the two components use waiting and posting to the semaphore. Depending on the system and the target, this introduces quite some performance gains. Especially, because the binary payload is written to memory once and does not have to be encoded and decoded or copied into other memory locations. Unfortunately, this mode sometimes leads to low stability when running with AFL++. Not sure why, yet.
Exec Mode
Exec mode can be either spawn or attach. This is pretty self-explanatory. fpicker can either attach to a running process or spawn a process. One thing that is a major difference between the two modes is that, should the attached target crash, the fpicker will not try to respawn.
Standalone Mutator
In standalone mode, fpicker offers three different input mutation strategies. Nicely put, input mutation certainly has lots of room for improvement.
- Standalone Mutator NULL: This mutator does not mutate the payload and just returns a copy of the same payload. Mostly for testing purposes. Otherwise not really useful.
- Standalone Mutator Rand: A very bad random mutator. All it does is randomly replace values at random locations in the original payload. It does not change the payload length.
- Standalone Mutator Custom: This mutator can call an external command to mutate payloads. It writes the payload to stdin and receives the mutated payload from stdout. Due to its shallow implementation, it has quite a performance impact.
Network devices
With option -D remote it is possible to fuzz a process running on a network device. For this, the remote device must be running frida-server. As a sample configuration, use SSH with port forwarding to bind the frida-server default listening port 27042 on the remote device to a socket on the local client.
ssh -N user@network.device -L 127.0.0.1:27042:127.0.0.1:27042
Then use frida-ps to validate the configuration by listing processes on the remote device:
frida-ps -R
Install & Use
Copyright (c) 2021 Dennis Heinze (ttdennis)