/* american fuzzy lop++ - afl-proxy skeleton example --------------------------------------------------- Written by Marc Heuse Copyright 2019-2020 AFLplusplus Project. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: http://www.apache.org/licenses/LICENSE-2.0 HOW-TO ====== You only need to change the while() loop of the main() to send the data of buf[] with length len to the target and write the coverage information to __afl_area_ptr[__afl_map_size] */ #ifdef __ANDROID__ #include "android-ashmem.h" #endif #include "config.h" #include "types.h" #include #include #include #include #include #include #include #include #include #include #include #include #include u8 *__afl_area_ptr; #ifdef __ANDROID__ u32 __afl_map_size = MAP_SIZE; #else __thread u32 __afl_map_size = MAP_SIZE; #endif /* Error reporting to forkserver controller */ void send_forkserver_error(int error) { u32 status; if (!error || error > 0xffff) return; status = (FS_OPT_ERROR | FS_OPT_SET_ERROR(error)); if (write(FORKSRV_FD + 1, (char *)&status, 4) != 4) return; } /* SHM setup. */ static void __afl_map_shm(void) { char *id_str = getenv(SHM_ENV_VAR); char *ptr; /* NOTE TODO BUG FIXME: if you want to supply a variable sized map then uncomment the following: */ /* if ((ptr = getenv("AFL_MAP_SIZE")) != NULL) { u32 val = atoi(ptr); if (val > 0) __afl_map_size = val; } */ if (__afl_map_size > MAP_SIZE) { if (__afl_map_size > FS_OPT_MAX_MAPSIZE) { fprintf(stderr, "Error: AFL++ tools *require* to set AFL_MAP_SIZE to %u to " "be able to run this instrumented program!\n", __afl_map_size); if (id_str) { send_forkserver_error(FS_ERROR_MAP_SIZE); exit(-1); } } else { fprintf(stderr, "Warning: AFL++ tools will need to set AFL_MAP_SIZE to %u to " "be able to run this instrumented program!\n", __afl_map_size); } } if (id_str) { #ifdef USEMMAP const char * shm_file_path = id_str; int shm_fd = -1; unsigned char *shm_base = NULL; /* create the shared memory segment as if it was a file */ shm_fd = shm_open(shm_file_path, O_RDWR, 0600); if (shm_fd == -1) { fprintf(stderr, "shm_open() failed\n"); send_forkserver_error(FS_ERROR_SHM_OPEN); exit(1); } /* map the shared memory segment to the address space of the process */ shm_base = mmap(0, __afl_map_size, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0); if (shm_base == MAP_FAILED) { close(shm_fd); shm_fd = -1; fprintf(stderr, "mmap() failed\n"); send_forkserver_error(FS_ERROR_MMAP); exit(2); } __afl_area_ptr = shm_base; #else u32 shm_id = atoi(id_str); __afl_area_ptr = shmat(shm_id, 0, 0); #endif if (__afl_area_ptr == (void *)-1) { send_forkserver_error(FS_ERROR_SHMAT); exit(1); } /* Write something into the bitmap so that the parent doesn't give up */ __afl_area_ptr[0] = 1; } } /* Fork server logic. */ static void __afl_start_forkserver(void) { u8 tmp[4] = {0, 0, 0, 0}; u32 status = 0; if (__afl_map_size <= FS_OPT_MAX_MAPSIZE) status |= (FS_OPT_SET_MAPSIZE(__afl_map_size) | FS_OPT_MAPSIZE); if (status) status |= (FS_OPT_ENABLED); memcpy(tmp, &status, 4); /* Phone home and tell the parent that we're OK. */ if (write(FORKSRV_FD + 1, tmp, 4) != 4) return; } static u32 __afl_next_testcase(u8 *buf, u32 max_len) { s32 status, res = 0xffffff; /* Wait for parent by reading from the pipe. Abort if read fails. */ if (read(FORKSRV_FD, &status, 4) != 4) return 0; /* we have a testcase - read it */ status = read(0, buf, max_len); /* report that we are starting the target */ if (write(FORKSRV_FD + 1, &res, 4) != 4) return 0; if (status < 1) return 0; else return status; } static void __afl_end_testcase(void) { int status = 0xffffff; if (write(FORKSRV_FD + 1, &status, 4) != 4) exit(1); } /* you just need to modify the while() loop in this main() */ int main(int argc, char *argv[]) { /* This is were the testcase data is written into */ u8 buf[1024]; // this is the maximum size for a test case! set it! u32 len; /* here you specify the map size you need that you are reporting to afl-fuzz. Any value is fine as long as it can be divided by 32. */ __afl_map_size = MAP_SIZE; // default is 65536 /* then we initialize the shared memory map and start the forkserver */ __afl_map_shm(); __afl_start_forkserver(); while ((len = __afl_next_testcase(buf, sizeof(buf))) > 0) { /* here you have to create the magic that feeds the buf/len to the target and write the coverage to __afl_area_ptr */ // ... the magic ... /* report the test case is done and wait for the next */ __afl_end_testcase(); } return 0; }