diff options
-rw-r--r-- | Makefile | 13 | ||||
-rw-r--r-- | README.md | 2 | ||||
-rw-r--r-- | docs/ChangeLog | 1 | ||||
-rw-r--r-- | gcc_plugin/afl-gcc-pass.so.cc | 6 | ||||
-rwxr-xr-x[-rw-r--r--] | include/android-ashmem.h | 2 | ||||
-rw-r--r-- | include/config.h | 2 | ||||
-rw-r--r-- | llvm_mode/LLVMInsTrim.so.cc | 7 | ||||
-rw-r--r-- | llvm_mode/afl-llvm-pass.so.cc | 6 | ||||
-rwxr-xr-x | qbdi_mode/README.md | 199 | ||||
-rw-r--r-- | qbdi_mode/assets/screen1.png | bin | 0 -> 88333 bytes | |||
-rwxr-xr-x | qbdi_mode/build.sh | 57 | ||||
-rwxr-xr-x | qbdi_mode/demo-so.c | 39 | ||||
-rwxr-xr-x | qbdi_mode/template.cpp | 251 | ||||
-rw-r--r-- | qemu_mode/README.md | 5 | ||||
-rw-r--r-- | qemu_mode/patches/afl-qemu-cpu-inl.h | 6 | ||||
-rw-r--r-- | src/afl-fuzz.c | 2 | ||||
-rwxr-xr-x | unicorn_mode/build_unicorn_support.sh | 2 |
17 files changed, 588 insertions, 12 deletions
diff --git a/Makefile b/Makefile index 9952ee6e..b5ee6a71 100644 --- a/Makefile +++ b/Makefile @@ -41,6 +41,13 @@ AFL_FUZZ_FILES = $(wildcard src/afl-fuzz*.c) PYTHON_INCLUDE ?= /usr/include/python2.7 + +ifdef SOURCE_DATE_EPOCH + BUILD_DATE ?= $(shell date -u -d "@$(SOURCE_DATE_EPOCH)" -I 2>/dev/null || date -u -r "$(SOURCE_DATE_EPOCH)" -I 2>/dev/null || date -u -I) +else + BUILD_DATE ?= $(shell date -I) +endif + ifneq "$(filter Linux GNU%,$(shell uname))" "" LDFLAGS += -ldl endif @@ -62,9 +69,9 @@ endif COMM_HDR = include/alloc-inl.h include/config.h include/debug.h include/types.h -ifeq "$(shell echo '\#include <Python.h>@int main() {return 0; }' | tr @ '\n' | $(CC) -x c - -o .test -I$(PYTHON_INCLUDE) -lpython2.7 2>/dev/null && echo 1 || echo 0 )" "1" +ifeq "$(shell echo '\#include <Python.h>@int main() {return 0; }' | tr @ '\n' | $(CC) -x c - -o .test -I$(PYTHON_INCLUDE) $(LDFLAGS) -lpython2.7 2>/dev/null && echo 1 || echo 0 )" "1" PYTHON_OK=1 - PYFLAGS=-DUSE_PYTHON -I$(PYTHON_INCLUDE) -lpython2.7 + PYFLAGS=-DUSE_PYTHON -I$(PYTHON_INCLUDE) $(LDFLAGS) -lpython2.7 else PYTHON_OK=0 PYFLAGS= @@ -299,7 +306,7 @@ source-only: all radamsa $(MAKE) -C libtokencap %.8: % - @echo .TH $* 8 `date -I` "afl++" > $@ + @echo .TH $* 8 $(BUILD_DATE) "afl++" > $@ @echo .SH NAME >> $@ @echo .B $* >> $@ @echo >> $@ diff --git a/README.md b/README.md index 9333fe1f..02c1bc2d 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,8 @@ * Radamsa mutator (enable with `-R` to add or `-RR` to run it exclusivly). + * qbdi_mode: fuzz android native libraries via QBDI framework + A more thorough list is available in the PATCHES file. diff --git a/docs/ChangeLog b/docs/ChangeLog index d7963d4d..e0042f24 100644 --- a/docs/ChangeLog +++ b/docs/ChangeLog @@ -17,6 +17,7 @@ sending a mail to <afl-users+subscribe@googlegroups.com>. Version ++2.58d (dev): ---------------------- + - qbdi_mode: fuzz android native libraries via QBDI framework - afl-analyze: added AFL_SKIP_BIN_CHECK support - better random numbers for gcc_plugin and llvm_mode (thanks to devnexen) - afl-fuzz: CPU affinity support for DragonFly diff --git a/gcc_plugin/afl-gcc-pass.so.cc b/gcc_plugin/afl-gcc-pass.so.cc index bf16b14b..19e4dfba 100644 --- a/gcc_plugin/afl-gcc-pass.so.cc +++ b/gcc_plugin/afl-gcc-pass.so.cc @@ -202,6 +202,9 @@ static unsigned int inline_instrument(function *fun) { basic_block bb; unsigned finst_blocks = 0; unsigned fcnt_blocks = 0; + tree one = build_int_cst(unsigned_char_type_node, 1); + // tree zero = build_int_cst(unsigned_char_type_node, 0); + /* Set up global type declarations */ tree map_type = build_pointer_type(unsigned_char_type_node); @@ -284,9 +287,6 @@ static unsigned int inline_instrument(function *fun) { /* Update bitmap */ - tree one = build_int_cst(unsigned_char_type_node, 1); - // tree zero = build_int_cst(unsigned_char_type_node, 0); - // gimple_assign <addr_expr, p_6, &map[_2], NULL, NULL> tree map_ptr = create_tmp_var(map_type, "map_ptr"); tree map_ptr2 = create_tmp_var(map_type, "map_ptr2"); diff --git a/include/android-ashmem.h b/include/android-ashmem.h index 984df4d4..2d515cc5 100644..100755 --- a/include/android-ashmem.h +++ b/include/android-ashmem.h @@ -52,7 +52,7 @@ static inline int shmctl(int __shmid, int __cmd, struct shmid_ds *__buf) { if (__cmd == IPC_RMID) { int length = ioctl(__shmid, ASHMEM_GET_SIZE, NULL); - struct ashmem_pin pin = {0, length}; + struct ashmem_pin pin = {0, (unsigned int)length}; ret = ioctl(__shmid, ASHMEM_UNPIN, &pin); close(__shmid); diff --git a/include/config.h b/include/config.h index 9c90155f..5934d733 100644 --- a/include/config.h +++ b/include/config.h @@ -41,7 +41,9 @@ /* Comment out to disable fancy ANSI boxes and use poor man's 7-bit UI: */ +#ifndef ANDROID_DISABLE_FANCY // Fancy boxes are ugly from adb #define FANCY_BOXES +#endif /* Default timeout for fuzzed code (milliseconds). This is the upper bound, also used for detecting hangs; the actual value is auto-scaled: */ diff --git a/llvm_mode/LLVMInsTrim.so.cc b/llvm_mode/LLVMInsTrim.so.cc index 89738812..f723a0fe 100644 --- a/llvm_mode/LLVMInsTrim.so.cc +++ b/llvm_mode/LLVMInsTrim.so.cc @@ -146,6 +146,9 @@ struct InsTrim : public ModulePass { M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_loc", 0, GlobalVariable::GeneralDynamicTLSModel, 0, false); + ConstantInt *Zero = ConstantInt::get(Int8Ty, 0); + ConstantInt *One = ConstantInt::get(Int8Ty, 1); + u64 total_rs = 0; u64 total_hs = 0; @@ -368,7 +371,7 @@ struct InsTrim : public ModulePass { LoadInst *Counter = IRB.CreateLoad(MapPtrIdx); Counter->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); - Value *Incr = IRB.CreateAdd(Counter, ConstantInt::get(Int8Ty, 1)); + Value *Incr = IRB.CreateAdd(Counter, One); #if LLVM_VERSION_MAJOR < 9 if (neverZero_counters_str != @@ -390,7 +393,7 @@ struct InsTrim : public ModulePass { * Counter + 1 -> {Counter, OverflowFlag} * Counter + OverflowFlag -> Counter */ - auto cf = IRB.CreateICmpEQ(Incr, ConstantInt::get(Int8Ty, 0)); + auto cf = IRB.CreateICmpEQ(Incr, Zero); auto carry = IRB.CreateZExt(cf, Int8Ty); Incr = IRB.CreateAdd(Incr, carry); diff --git a/llvm_mode/afl-llvm-pass.so.cc b/llvm_mode/afl-llvm-pass.so.cc index 0c68136b..4ce073a5 100644 --- a/llvm_mode/afl-llvm-pass.so.cc +++ b/llvm_mode/afl-llvm-pass.so.cc @@ -150,6 +150,8 @@ bool AFLCoverage::runOnModule(Module &M) { M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_loc", 0, GlobalVariable::GeneralDynamicTLSModel, 0, false); #endif + ConstantInt *Zero = ConstantInt::get(Int8Ty, 0); + ConstantInt *One = ConstantInt::get(Int8Ty, 1); /* Instrument all the things! */ @@ -287,7 +289,7 @@ bool AFLCoverage::runOnModule(Module &M) { LoadInst *Counter = IRB.CreateLoad(MapPtrIdx); Counter->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); - Value *Incr = IRB.CreateAdd(Counter, ConstantInt::get(Int8Ty, 1)); + Value *Incr = IRB.CreateAdd(Counter, One); #if LLVM_VERSION_MAJOR < 9 if (neverZero_counters_str != @@ -331,7 +333,7 @@ bool AFLCoverage::runOnModule(Module &M) { */ // this is the solution we choose because llvm9 should do the right // thing here - auto cf = IRB.CreateICmpEQ(Incr, ConstantInt::get(Int8Ty, 0)); + auto cf = IRB.CreateICmpEQ(Incr, Zero); auto carry = IRB.CreateZExt(cf, Int8Ty); Incr = IRB.CreateAdd(Incr, carry); /* diff --git a/qbdi_mode/README.md b/qbdi_mode/README.md new file mode 100755 index 00000000..641a6e85 --- /dev/null +++ b/qbdi_mode/README.md @@ -0,0 +1,199 @@ +# qbdi-based binary-only instrumentation for afl-fuzz + +## 1) Introduction + +The code in ./qbdi_mode allows you to build a standalone feature that +using the QBDI framework to fuzz android native library. + + +## 2) Build + +First download the Android NDK + +``` +https://developer.android.com/ndk/downloads +https://dl.google.com/android/repository/android-ndk-r20-linux-x86_64.zip +``` + +Then unzip it and build the standalone-toolchain +For x86_64 standalone-toolchain + +``` +unzip android-ndk-r20-linux-x86_64.zip +cd android-ndk-r20/ +./build/tools/make_standalone_toolchain.py --arch x86_64 --api 21 --install-dir ../android-standalone-toolchain-x86_64 +``` + +For x86 standalone-toolchain + +``` +./build/tools/make_standalone_toolchain.py --arch x86 --api 21 --install-dir ../android-standalone-toolchain-x86 +``` + +In alternative you can also use the prebuilt toolchain, in that case make sure to set the proper CC and CXX env variables because there are many different compilers for each API version in the prebuilt toolchain. + +For example: + +``` +export STANDALONE_TOOLCHAIN_PATH=~/Android/Sdk/ndk/20.1.5948944/toolchains/llvm/prebuilt/linux-x86_64/ +export CC=x86_64-linux-android21-clang +export CXX=x86_64-linux-android21-clang++ +``` + +Then download the QBDI SDK from website + +``` +https://qbdi.quarkslab.com/ +``` + +For Android x86_64 +``` +https://github.com/QBDI/QBDI/releases/download/v0.7.0/QBDI-0.7.0-android-X86_64.tar.gz +``` + +Then decompress the sdk + +``` +mkdir android-qbdi-sdk-x86_64 +cp QBDI-0.7.0-android-X86_64.tar.gz android-qbdi-sdk-x86_64/ +cd android-qbdi-sdk-x86_64/ +tar xvf QBDI-0.7.0-android-X86_64.tar.gz +``` + +Now set the `STANDALONE_TOOLCHAIN_PATH` to the path of standalone-toolchain + +``` +export STANDALONE_TOOLCHAIN_PATH=/home/hac425/workspace/android-standalone-toolchain-x86_64 +``` + +set the `QBDI_SDK_PATH` to the path of QBDI SDK + +``` +export QBDI_SDK_PATH=/home/hac425/workspace/AFLplusplus/qbdi_mode/android-qbdi-sdk-x86_64/ +``` + +Then run the build.sh + +``` +./build.sh x86_64 +``` + +this could build the afl-fuzz and also the qbdi template for android x86_64 + + +### Example + +The demo-so.c is an vulnerable library, it has a function for test + +```c +int target_func(char *buf, int size) { + + printf("buffer:%p, size:%p\n", buf, size); + switch (buf[0]) { + + case 1: + puts("222"); + if (buf[1] == '\x44') { + + puts("null ptr deference"); + *(char *)(0) = 1; + + } + + break; + case 0xff: + if (buf[2] == '\xff') { + + if (buf[1] == '\x44') { + + puts("crash...."); + *(char *)(0xdeadbeef) = 1; + + } + + } + + break; + default: puts("default action"); break; + + } + + return 1; + +} +``` + +This could be build to `libdemo.so`. + +Then we should load the library in template.cpp and find the `target` function address. +```c + void *handle = dlopen(lib_path, RTLD_LAZY); + .......................................... + .......................................... + .......................................... + p_target_func = (target_func)dlsym(handle, "target_func"); +``` + +then we read the data from file and call the function in `fuzz_func` + +```c +QBDI_NOINLINE int fuzz_func() { + + if (afl_setup()) { afl_forkserver(); } + + /* Read the input from file */ + unsigned long len = 0; + char * data = read_file(input_pathname, &len); + + /* Call the target function with the input data */ + p_target_func(data, len); + return 1; + +} +``` + +Just compile it +``` +./build.sh x86_64 +``` + +Then push the `afl-fuzz`, `loader`, `libdemo.so`, the `libQBDI.so` from the QBDI SDK and the `libc++_shared.so` from android-standalone-toolchain to android device + +``` +adb push afl-fuzz /data/local/tmp +adb push libdemo.so /data/local/tmp +adb push loader /data/local/tmp +adb push android-qbdi-sdk-x86_64/usr/local/lib/libQBDI.so /data/local/tmp +adb push ../../android-standalone-toolchain-x86_64/sysroot/usr/lib/x86_64-linux-android/libc++_shared.so +/data/local/tmp +``` + +In android adb shell, run the loader to test if it runs +``` +cd /data/local/tmp +export LD_LIBRARY_PATH=/data/local/tmp +mkdir in +echo 0000 > in/1 +./loader libdemo.so in/1 +p_target_func:0x716d96a98600 + offset:0x600 + offset:0x580 +buffer:0x716d96609050, size:0x5 + offset:0x628 + offset:0x646 + offset:0x64b + offset:0x65c + offset:0x6df + offset:0x590 +default action + offset:0x6eb +``` + +Now run `afl-fuzz` to fuzz the demo library + +``` +./afl-fuzz -i in -o out -- ./loader /data/local/tmp/libdemo.so @@ +``` + + + diff --git a/qbdi_mode/assets/screen1.png b/qbdi_mode/assets/screen1.png new file mode 100644 index 00000000..3cf1cb76 --- /dev/null +++ b/qbdi_mode/assets/screen1.png Binary files differdiff --git a/qbdi_mode/build.sh b/qbdi_mode/build.sh new file mode 100755 index 00000000..c2912e94 --- /dev/null +++ b/qbdi_mode/build.sh @@ -0,0 +1,57 @@ + +if [ -z ${STANDALONE_TOOLCHAIN_PATH} ]; then + echo "please set the android-standalone-toolchain path in STANDALONE_TOOLCHAIN_PATH environmental variable" + echo "for example: " + echo " export STANDALONE_TOOLCHAIN_PATH=/home/android-standalone-toolchain-21/" + exit +fi + +if [ -z ${QBDI_SDK_PATH} ]; then + echo "please set the qbdi sdk path in QBDI_SDK_PATH environmental variable" + echo "for example: " + echo " export QBDI_SDK_PATH=/home/QBDI-Android/" + exit +fi + + + +if [ "$1" = "x86" ]; then + echo "build x86 qbdi" + compiler_prefix="${STANDALONE_TOOLCHAIN_PATH}/bin/" + if [ -z ${CC} ]; then + export CC=i686-linux-android-gcc + fi + if [ -z ${CXX} ]; then + export CXX=i686-linux-android-g++ + fi +elif [ "$1" = "x86_64" ]; then + echo "build x86_64 qbdi" + compiler_prefix="${STANDALONE_TOOLCHAIN_PATH}/bin/" + if [ -z ${CC} ]; then + export CC=x86_64-linux-android-gcc + fi + if [ -z ${CXX} ]; then + export CXX=x86_64-linux-android-g++ + fi +else + echo "usage: ./build.sh arch[x86, x86_64]" + exit +fi + + +CFLAGS="-I${QBDI_SDK_PATH}/usr/local/include/ -L${QBDI_SDK_PATH}/usr/local/lib/" + +echo "[+] Building the QBDI template" +# build the qbdi template +${compiler_prefix}${CXX} -o loader template.cpp -lQBDI -ldl -w -g ${CFLAGS} + +echo "[+] Building the demo library" +# build the demo share library +${compiler_prefix}${CC} -shared -o libdemo.so demo-so.c -w -g + +echo "[+] Building afl-fuzz for Android" +# build afl-fuzz +cd .. +${compiler_prefix}${CC} -DANDROID_DISABLE_FANCY=1 -O3 -funroll-loops -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign -I include/ -DAFL_PATH=\"/usr/local/lib/afl\" -DBIN_PATH=\"/usr/local/bin\" -DDOC_PATH=\"/usr/local/share/doc/afl\" -Wno-unused-function src/afl-fuzz-misc.c src/afl-fuzz-extras.c src/afl-fuzz-queue.c src/afl-fuzz-one.c src/afl-fuzz-python.c src/afl-fuzz-stats.c src/afl-fuzz-init.c src/afl-fuzz.c src/afl-fuzz-bitmap.c src/afl-fuzz-run.c src/afl-fuzz-globals.c src/afl-common.c src/afl-sharedmem.c src/afl-forkserver.c -o qbdi_mode/afl-fuzz -ldl -w + +echo "[+] All done. Enjoy!" diff --git a/qbdi_mode/demo-so.c b/qbdi_mode/demo-so.c new file mode 100755 index 00000000..dbb7b714 --- /dev/null +++ b/qbdi_mode/demo-so.c @@ -0,0 +1,39 @@ +#include <stdio.h> + +// gcc -shared -o libdemo.so demo-so.c -w +int target_func(char *buf, int size) { + + printf("buffer:%p, size:%p\n", buf, size); + switch (buf[0]) { + + case 1: + puts("222"); + if (buf[1] == '\x44') { + + puts("null ptr deference"); + *(char *)(0) = 1; + + } + + break; + case 0xff: + if (buf[2] == '\xff') { + + if (buf[1] == '\x44') { + + puts("crash...."); + *(char *)(0xdeadbeef) = 1; + + } + + } + + break; + default: puts("default action"); break; + + } + + return 1; + +} + diff --git a/qbdi_mode/template.cpp b/qbdi_mode/template.cpp new file mode 100755 index 00000000..18766d31 --- /dev/null +++ b/qbdi_mode/template.cpp @@ -0,0 +1,251 @@ +#include <iostream> + +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <sys/wait.h> +#include <fcntl.h> +#include <dlfcn.h> + +#ifdef __ANDROID__ +#include "../include/android-ashmem.h" +#endif + +#include <sys/ipc.h> +#include <sys/shm.h> +#include "../config.h" + +#include <QBDI.h> + +/* NeverZero */ + +#if (defined(__x86_64__) || defined(__i386__)) && defined(AFL_QEMU_NOT_ZERO) +#define INC_AFL_AREA(loc) \ + asm volatile( \ + "incb (%0, %1, 1)\n" \ + "adcb $0, (%0, %1, 1)\n" \ + : /* no out */ \ + : "r"(afl_area_ptr), "r"(loc) \ + : "memory", "eax") +#else +#define INC_AFL_AREA(loc) afl_area_ptr[loc]++ +#endif + +using namespace QBDI; + +typedef int (*target_func)(char *buf, int size); + +static const size_t STACK_SIZE = 0x100000; // 1MB +static const QBDI::rword FAKE_RET_ADDR = 0x40000; +target_func p_target_func = NULL; +rword module_base = 0; +rword module_end = 0; +static unsigned char + dummy[MAP_SIZE]; /* costs MAP_SIZE but saves a few instructions */ +unsigned char *afl_area_ptr = NULL; /* Exported for afl_gen_trace */ + +unsigned long afl_prev_loc = 0; + +char input_pathname[PATH_MAX]; + +/* Set up SHM region and initialize other stuff. */ + +int afl_setup(void) { + + char *id_str = getenv(SHM_ENV_VAR); + int shm_id; + if (id_str) { + + shm_id = atoi(id_str); + afl_area_ptr = (unsigned char *)shmat(shm_id, NULL, 0); + if (afl_area_ptr == (void *)-1) return 0; + memset(afl_area_ptr, 0, MAP_SIZE); + + } + + return 1; + +} + +/* Fork server logic, invoked once we hit _start. */ +static void afl_forkserver() { + + static unsigned char tmp[4]; + pid_t child_pid; + + if (write(FORKSRV_FD + 1, tmp, 4) != 4) return; + + while (1) { + + int status; + u32 was_killed; + // wait for afl-fuzz + if (read(FORKSRV_FD, &was_killed, 4) != 4) exit(2); + + child_pid = fork(); + if (child_pid < 0) exit(4); + + if (!child_pid) { + + // child return to execute code + close(FORKSRV_FD); + close(FORKSRV_FD + 1); + return; + + } + + // write child pid to afl-fuzz + if (write(FORKSRV_FD + 1, &child_pid, 4) != 4) exit(5); + + // wait child stop + if (waitpid(child_pid, &status, 0) < 0) exit(6); + + // send child stop status to afl-fuzz + if (write(FORKSRV_FD + 1, &status, 4) != 4) exit(7); + + } + +} + +void afl_maybe_log(unsigned long cur_loc) { + + if (afl_area_ptr == NULL) { return; } + unsigned long afl_idx = cur_loc ^ afl_prev_loc; + afl_idx &= MAP_SIZE -1; + INC_AFL_AREA(afl_idx); + afl_prev_loc = cur_loc >> 1; + +} + +char *read_file(char *path, unsigned long *length) { + + unsigned long len; + char * buf; + + FILE *fp = fopen(path, "rb"); + fseek(fp, 0, SEEK_END); + len = ftell(fp); + buf = (char *)malloc(len); + rewind(fp); + fread(buf, 1, len, fp); + fclose(fp); + *length = len; + return buf; + +} + +QBDI_NOINLINE int fuzz_func() { + + if (afl_setup()) { afl_forkserver(); } + + unsigned long len = 0; + char * data = read_file(input_pathname, &len); + + // printf("In fuzz_func\n"); + p_target_func(data, len); + return 1; + +} + +static QBDI::VMAction bbcallback(QBDI::VMInstanceRef vm, + const QBDI::VMState *state, + QBDI::GPRState * gprState, + QBDI::FPRState *fprState, void *data) { + + // errno = SAVED_ERRNO; + +#ifdef __x86_64__ + unsigned long pc = gprState->rip; +#elif defined(i386) + unsigned long pc = gprState->eip; +#elif defined(__arm__) + unsigned long pc = gprState->pc; +#endif + + // just log the module path + if (pc >= module_base && pc <= module_end) { + + unsigned long offset = pc - module_base; + printf("\toffset:%p\n", offset); + afl_maybe_log(offset); + + } + + return QBDI::VMAction::CONTINUE; + +} + +int main(int argc, char **argv) { + + if (argc < 3) { + + puts("usage: ./loader library_path input_file_path"); + exit(0); + + } + + const char *lib_path; + lib_path = argv[1]; + strcpy(input_pathname, argv[2]); + void *handle = dlopen(lib_path, RTLD_LAZY); + + if (handle == nullptr) { + + perror("Cannot load library"); + exit(EXIT_FAILURE); + + } + + const char *lib_name = lib_path; + if (strrchr(lib_name, '/') != nullptr) lib_name = strrchr(lib_name, '/') + 1; + + // printf("library name:%s\n", lib_name); + // load library module address for log path + for (MemoryMap &map : getCurrentProcessMaps()) { + + // printf("module:%s\n", map.name.c_str()); + if ((map.permission & PF_EXEC) && + strstr(map.name.c_str(), lib_name) != NULL) { + + module_base = map.range.start; + module_end = map.range.end; + + } + + } + + if (module_base == 0) { + + std::cerr << "Fail to find base address" << std::endl; + return -1; + + } + + // printf("module base:%p, module end:%p\n", module_base, module_end); + p_target_func = (target_func)dlsym(handle, "target_func"); + // p_target_func = (target_func)(module_base + 0x61a); + printf("p_target_func:%p\n", p_target_func); + + VM vm; + uint8_t *fakestack = nullptr; + + GPRState *state = vm.getGPRState(); + allocateVirtualStack(state, STACK_SIZE, &fakestack); + vm.addInstrumentedModuleFromAddr(module_base); + vm.addInstrumentedModuleFromAddr((rword)&main); + + vm.addVMEventCB(BASIC_BLOCK_ENTRY, bbcallback, nullptr); + + // QBDI::simulateCall(state, FAKE_RET_ADDR); + // vm.run((rword)&fuzz_func, (rword)FAKE_RET_ADDR); + + rword ret; + vm.call(&ret, (rword)&fuzz_func, {}); + + return 0; + +} + diff --git a/qemu_mode/README.md b/qemu_mode/README.md index c88c1e41..87027f63 100644 --- a/qemu_mode/README.md +++ b/qemu_mode/README.md @@ -46,6 +46,11 @@ You can also compile statically-linked binaries by setting STATIC=1. This can be useful when compiling QEMU on a different system than the one you're planning to run the fuzzer on and is most often used with the HOST variable. +Note: when targetting the i386 architecture, on some bianries the forkserver +handshake may fail due to the lack of reversed memory. Fix it with + +export QEMU_RESERVED_VA=0x1000000 + Note: if you want the QEMU helper to be installed on your system for all users, you need to build it before issuing 'make install' in the parent directory. diff --git a/qemu_mode/patches/afl-qemu-cpu-inl.h b/qemu_mode/patches/afl-qemu-cpu-inl.h index f4c474d8..7c6d3341 100644 --- a/qemu_mode/patches/afl-qemu-cpu-inl.h +++ b/qemu_mode/patches/afl-qemu-cpu-inl.h @@ -84,6 +84,8 @@ __thread abi_ulong afl_prev_loc; /* Set in the child process in forkserver mode: */ static int forkserver_installed = 0; +static int disable_caching = 0; + unsigned char afl_fork_child; unsigned int afl_forksrv_pid; unsigned char is_persistent; @@ -205,6 +207,8 @@ static void afl_setup(void) { behaviour, and seems to work alright? */ rcu_disable_atfork(); + + disable_caching = getenv("AFL_QEMU_DISABLE_CACHE") != NULL; is_persistent = getenv("AFL_QEMU_PERSISTENT_ADDR") != NULL; @@ -422,6 +426,8 @@ static void afl_request_tsl(target_ulong pc, target_ulong cb, uint32_t flags, uint32_t cf_mask, TranslationBlock *last_tb, int tb_exit) { + if (disable_caching) return; + struct afl_tsl t; struct afl_chain c; diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 9b5d6a1c..42bdaebd 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -838,6 +838,7 @@ int main(int argc, char** argv) { seek_to = find_start_position(); write_stats_file(0, 0, 0); + maybe_update_plot_file(0, 0); save_auto(); if (stop_soon) goto stop_fuzzing; @@ -970,6 +971,7 @@ int main(int argc, char** argv) { write_bitmap(); write_stats_file(0, 0, 0); + maybe_update_plot_file(0, 0); save_auto(); stop_fuzzing: diff --git a/unicorn_mode/build_unicorn_support.sh b/unicorn_mode/build_unicorn_support.sh index 7cdbff0a..e987e15a 100755 --- a/unicorn_mode/build_unicorn_support.sh +++ b/unicorn_mode/build_unicorn_support.sh @@ -198,7 +198,7 @@ echo "[*] Installing Unicorn python bindings..." cd bindings/python || exit 1 if [ -z "$VIRTUAL_ENV" ]; then echo "[*] Info: Installing python unicorn using --user" - $PYTHONBIN setup.py install --user || exit 1 + $PYTHONBIN setup.py install --user --prefix=|| exit 1 else echo "[*] Info: Installing python unicorn to virtualenv: $VIRTUAL_ENV" $PYTHONBIN setup.py install || exit 1 |