Fuzzing Network Services
Relevant source files
The following files were used as context for generating this wiki page: - [utils/afl_network_proxy/README.md](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/utils/afl_network_proxy/README.md) - [utils/afl_network_proxy/afl-network-client.c](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/utils/afl_network_proxy/afl-network-client.c) - [utils/afl_network_proxy/afl-network-server.c](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/utils/afl_network_proxy/afl-network-server.c) - [utils/README.md](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/utils/README.md) - [src/afl-fuzz.c](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/src/afl-fuzz.c) - [README.md](https://github.com/lagraviereScience/AFLplusplus/blob/HEAD/README.md)AFL++ provides utilities for fuzzing network services, primarily through the afl-network-proxy tool. This tool allows afl-fuzz to run on one host while the target application runs on another, which is particularly useful for fuzzing targets on embedded systems, devices with limited resources, or systems that reboot on crash. This approach, however, comes with a significant performance penalty, with an expected speed loss of around 90%.
Another utility, socket_fuzzing, offers an alternative method by using an LD_PRELOAD library to redirect a target's socket communication to stdin, allowing standard fuzzing with afl-fuzz. This page focuses on the afl-network-proxy utility.
Sources: utils/afl_network_proxy/README.md, utils/README.md, README.md
Architecture
The afl-network-proxy employs a client-server architecture to separate the fuzzer from the target application.
afl-network-server: This component runs on the target machine. It listens for incoming TCP connections, receives test cases, executes the target binary with the provided input, and sends the resulting coverage and status back to the client.afl-network-client: This component runs on the fuzzer's machine and acts as the target forafl-fuzz. It connects to theafl-network-server, sends test cases received fromafl-fuzz, and waits for the execution results.
The diagram below illustrates the high-level architecture.
Data Flow and Protocol
The communication between the client and server follows a simple protocol over TCP. The server manages the forkserver and execution of the target, while the client acts as a proxy for afl-fuzz.
The sequence of operations for a single fuzzing iteration is as follows:
afl-fuzzstartsafl-network-clientas its target.afl-network-clientestablishes a TCP connection toafl-network-server.- The server accepts the connection and sends a banner to confirm it's an
afl-network-server. afl-fuzzprovides a mutated test case toafl-network-clientvia its shared memory region (shm_fuzz).afl-network-clientreads the test case, sends a 4-byte header with the test case length, followed by the test case data itself to the server.afl-network-serverreceives the data, writes it to a temporary file (.cur_input), and instructs its forkserver to run the target with this input.- After the target executes,
afl-network-servercollects the execution result (fsrv_run_result_t) and the coverage map (trace_bits). - The server sends a 4-byte execution result and the full coverage map back to the client.
afl-network-clientreceives the result and coverage map, writes the map to its own shared memory forafl-fuzzto analyze, and then exits with a code that signals the outcome (e.g., crash, timeout) toafl-fuzz.
The following sequence diagram details the network interaction.
Compilation and Configuration
Compilation
To compile the network proxy, navigate to the utils/afl_network_proxy/ directory and run make. The build system will automatically detect if libdeflate-dev is installed, which can provide a 40-50% performance increase.
For targets with large test cases (10kb+) that are primarily ASCII or contain large blocks of zeros, you can enable test case compression by setting CFLAGS=-DCOMPRESS_TESTCASES=1. However, this is disabled by default as it can degrade performance for most targets.
Sources: utils/afl_network_proxy/README.md
Server Configuration
The afl-network-server is run on the target machine.
Usage:
afl-network-server [options] -- /path/to/target [target_args]
Options:
| Option | Argument | Description | Source |
|---|---|---|---|
-i | port | The TCP port for the server to listen on. | afl-network-server.c:280 |
-m | megs | Memory limit for the child process in megabytes. | afl-network-server.c:303 |
-t | msec | Timeout for each run in milliseconds. | afl-network-server.c:294 |
-f | file | Location for the target to read from (replaces @@). | afl-network-server.c:287 |
-N | Do not unlink the fuzzing input file. | afl-network-server.c:321 |
Example:
afl-network-server -i 1111 -m 25M -t 1000 -- /bin/target -f @@
Sources: utils/afl_network_proxy/README.md, utils/afl_network_proxy/afl-network-server.c:273-324
Client and Fuzzer Configuration
On the main fuzzer node, afl-fuzz is launched with afl-network-client as its target.
Usage:
afl-fuzz [afl_options] -- afl-network-client <TARGET-IP> <PORT>
Important afl-fuzz options:
| Option | Argument | Description | Source |
|---|---|---|---|
-t | msec+ | The timeout for afl-fuzz. It should be set higher than the server's timeout, and the + is crucial to let afl-network-server handle the precise timeout logic. A value 500-1000ms higher than the server's is recommended. | utils/afl_network_proxy/README.md |
Example:
afl-fuzz -i in -o out -t 2000+ -- afl-network-client 192.168.1.100 1111
The target IP can be an IPv4 or IPv6 address, or a hostname. For IPv6, an outgoing interface can be specified (e.g., fe80::1234%eth0).
Sources: utils/afl_network_proxy/README.md, utils/afl_network_proxy/afl-network-client.c:226-241
Performance and Networking Notes
- Performance: Expect a significant performance degradation of about 90% due to network latency.
- TCP Window Size: Ensure the default TCP window size is larger than the
MAP_SIZEused by AFL++. A value of 130kb is suggested. On Linux, this can be checked and set via/proc/sys/net/ipv4/tcp_rmem.
Sources: utils/afl_network_proxy/README.md