diff options
-rw-r--r-- | custom_mutators/custom_send_tcp/Makefile | 7 | ||||
-rw-r--r-- | custom_mutators/custom_send_tcp/README.md | 13 | ||||
-rw-r--r-- | custom_mutators/custom_send_tcp/custom_send_tcp.c | 113 | ||||
-rw-r--r-- | docs/Changelog.md | 2 |
4 files changed, 135 insertions, 0 deletions
diff --git a/custom_mutators/custom_send_tcp/Makefile b/custom_mutators/custom_send_tcp/Makefile new file mode 100644 index 00000000..8549ccad --- /dev/null +++ b/custom_mutators/custom_send_tcp/Makefile @@ -0,0 +1,7 @@ +all: custom_send_tcp.so + +custom_send_tcp.so: + $(CC) -Wno-unused-result -g -O3 -shared -fPIC -o custom_send_tcp.so -I../../include custom_send_tcp.c + +clean: + rm -f custom_send_tcp.so *.o *~ core diff --git a/custom_mutators/custom_send_tcp/README.md b/custom_mutators/custom_send_tcp/README.md new file mode 100644 index 00000000..7b4bb869 --- /dev/null +++ b/custom_mutators/custom_send_tcp/README.md @@ -0,0 +1,13 @@ +# Send testcases via TCP custom mutator + +This custom mutator sends the fuzzing testcases via TCP. + +`AFL_CUSTOM_MUTATOR_LATE_SEND` - MUST be set! +`CUSTOM_SEND_IP` - the IP address to send to (basically only 127.0.0.1 makes sense) +`CUSTOM_SEND_PORT` - the TCP port to send to +`CUSTOM_SEND_READ` - if the custom mutator should wait for a reply from the target + +Example: +``` +CUSTOM_SEND_IP=127.0.0.1 CUSTOM_SEND_PORT=8000 CUSTOM_SEND_READ=1 AFL_CUSTOM_MUTATOR_LATE_SEND=1 AFL_CUSTOM_MUTATOR_LIBRARY=custom_send_tcp.so ./afl-fuzz ... +``` diff --git a/custom_mutators/custom_send_tcp/custom_send_tcp.c b/custom_mutators/custom_send_tcp/custom_send_tcp.c new file mode 100644 index 00000000..53689ced --- /dev/null +++ b/custom_mutators/custom_send_tcp/custom_send_tcp.c @@ -0,0 +1,113 @@ +#include <time.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <arpa/inet.h> +#include <sys/select.h> + +#include "afl-fuzz.h" + +static int my_debug = 0; +static int my_read = 0; + +#define DEBUG(...) if (my_debug) printf(__VA_ARGS__) + +typedef struct tcp_send_mutator { + afl_state_t* afl; + struct sockaddr_in server_addr; +} tcp_send_mutator_t; + +void *afl_custom_init(afl_state_t* afl, uint32_t seed) { + const char* ip = getenv("CUSTOM_SEND_IP"); + const char* port = getenv("CUSTOM_SEND_PORT"); + + if (getenv("AFL_DEBUG")) my_debug = 1; + if (getenv("CUSTOM_SEND_READ")) my_read = 1; + + if (!ip || !port) { + fprintf(stderr, "You forgot to set CUSTOM_SEND_IP and/or CUSTOM_SEND_PORT\n"); + exit(1); + } + + tcp_send_mutator_t* mutator = calloc(1, sizeof(tcp_send_mutator_t)); + if (!mutator) { + fprintf(stderr, "Failed to allocate mutator struct\n"); + exit(1); + } + + mutator->afl = afl; + + bzero(&mutator->server_addr, sizeof(mutator->server_addr)); + mutator->server_addr.sin_family = AF_INET; + if (inet_pton(AF_INET, ip, &mutator->server_addr.sin_addr) <= 0) { + fprintf(stderr, "Could not convert target ip address!\n"); + exit(1); + } + mutator->server_addr.sin_port = htons(atoi(port)); + + printf("[+] Custom tcp send mutator setup ready to go!\n"); + + return mutator; +} + +int try_connect(tcp_send_mutator_t *mutator, int sock, int max_attempts) { + while (max_attempts > 0) { + if (connect(sock, (struct sockaddr*)&mutator->server_addr, sizeof(mutator->server_addr)) == 0) { + return 0; + } + + // Even with AFL_CUSTOM_LATE_SEND=1, there is a race between the + // application under test having started to listen for connections and + // afl_custom_fuzz_send being called. To address this race, we attempt + // to connect N times and sleep a short period of time in between + // connection attempts. + struct timespec t; + t.tv_sec = 0; + t.tv_nsec = 100; + nanosleep(&t, NULL); + --max_attempts; + } + return 1; +} + +void afl_custom_fuzz_send(tcp_send_mutator_t *mutator, uint8_t *buf, size_t buf_size) { + int sock = socket(AF_INET, SOCK_STREAM, 0); + + int written = 0; + if (sock >= 0 && try_connect(mutator, sock, 10000) == 0) { + DEBUG("connected, write()\n"); + written = write(sock, buf, buf_size); + } else { + DEBUG("socket() or connect() error: %d\n", errno); + } + + if (written < 0) { + DEBUG("write() error: %d\n", errno); + } else if (my_read) { + struct timeval timeout; + timeout.tv_sec = 1; + timeout.tv_usec = 0; + + fd_set set; + FD_ZERO(&set); + FD_SET(sock, &set); + + int select_res = select(sock + 1, &set, NULL, NULL, &timeout); + if (select_res == -1) { + DEBUG("select() error: %d\n", errno); + } else if (select_res == 0) { + DEBUG("read() timeout!\n"); + } else { + uint8_t buf[64]; + (void)read(sock, buf, sizeof(buf)); + } + } + + close(sock); +} + +void afl_custom_deinit(tcp_send_mutator_t* mutator) { + free(mutator); +} diff --git a/docs/Changelog.md b/docs/Changelog.md index c16214e4..0212fd61 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -18,6 +18,8 @@ a function entry - AFL_DEBUG is now the same as AFL_FRIDA_VERBOSE - AFL_FRIDA_DEBUG_MAPS now works as expected + - custom mutators: + - custom_send_tcp custom mutator added, thanks to @dergoegge ### Version ++4.21c (release) |