diff options
Diffstat (limited to 'libtokencap')
-rw-r--r-- | libtokencap/Makefile | 6 | ||||
-rw-r--r-- | libtokencap/README.md | 13 | ||||
-rw-r--r-- | libtokencap/libtokencap.so.c | 91 |
3 files changed, 101 insertions, 9 deletions
diff --git a/libtokencap/Makefile b/libtokencap/Makefile index 91933140..07c13144 100644 --- a/libtokencap/Makefile +++ b/libtokencap/Makefile @@ -24,6 +24,12 @@ CFLAGS += -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign ifeq "$(shell uname)" "Linux" TARGETS = libtokencap.so endif +ifeq "$(shell uname)" "Darwin" + TARGETS = libtokencap.so +endif +ifeq "$(shell uname)" "FreeBSD" + TARGETS = libtokencap.so +endif all: $(TARGETS) libtokencap.so: libtokencap.so.c ../config.h diff --git a/libtokencap/README.md b/libtokencap/README.md index baf69da1..8aae38bf 100644 --- a/libtokencap/README.md +++ b/libtokencap/README.md @@ -2,7 +2,7 @@ (See ../docs/README for the general instruction manual.) -This Linux-only companion library allows you to instrument `strcmp()`, `memcmp()`, +This companion library allows you to instrument `strcmp()`, `memcmp()`, and related functions to automatically extract syntax tokens passed to any of these libcalls. The resulting list of tokens may be then given as a starting dictionary to afl-fuzz (the -x option) to improve coverage on subsequent @@ -55,9 +55,10 @@ If you don't get any results, the target library is probably not using strcmp() and memcmp() to parse input; or you haven't compiled it with -fno-builtin; or the whole thing isn't dynamically linked, and LD_PRELOAD is having no effect. -PS. The library is Linux-only because there is probably no particularly portable -and non-invasive way to distinguish between read-only and read-write memory -mappings. The `__tokencap_load_mappings()` function is the only thing that would -need to be changed for other OSes. Porting to platforms with /proc/<pid>/maps -(e.g., FreeBSD) should be trivial. +Portability hints: There is probably no particularly portable and non-invasive +way to distinguish between read-only and read-write memory mappings. +The `__tokencap_load_mappings()` function is the only thing that would +need to be changed for other OSes. + +Current supported OSes are: Linux, Darwin, FreeBSD (thanks to @devnexen) diff --git a/libtokencap/libtokencap.so.c b/libtokencap/libtokencap.so.c index 39095beb..ddeae8b8 100644 --- a/libtokencap/libtokencap.so.c +++ b/libtokencap/libtokencap.so.c @@ -22,13 +22,24 @@ #include <stdio.h> #include <string.h> #include <ctype.h> +#include <unistd.h> #include "../types.h" #include "../config.h" -#ifndef __linux__ -#error "Sorry, this library is Linux-specific for now!" -#endif /* !__linux__ */ +#if !defined __linux__ && !defined __APPLE__ && !defined __FreeBSD__ +# error "Sorry, this library is unsupported in this platform for now!" +#endif /* !__linux__ && !__APPLE__ && ! __FreeBSD__ */ + +#if defined __APPLE__ +# include <mach/vm_map.h> +# include <mach/mach_init.h> +#elif defined __FreeBSD__ +# include <sys/types.h> +# include <sys/sysctl.h> +# include <sys/user.h> +# include <sys/mman.h> +#endif /* Mapping data and such */ @@ -46,6 +57,8 @@ static FILE* __tokencap_out_file; static void __tokencap_load_mappings(void) { +#if defined __linux__ + u8 buf[MAX_LINE]; FILE* f = fopen("/proc/self/maps", "r"); @@ -70,6 +83,78 @@ static void __tokencap_load_mappings(void) { fclose(f); +#elif defined __APPLE__ + + struct vm_region_submap_info_64 region; + mach_msg_type_number_t cnt = VM_REGION_SUBMAP_INFO_COUNT_64; + vm_address_t base = 0; + vm_size_t size = 0; + natural_t depth = 0; + + __tokencap_ro_loaded = 1; + + while (1) { + + if (vm_region_recurse_64(mach_task_self(), &base, &size, &depth, + (vm_region_info_64_t)®ion, &cnt) != KERN_SUCCESS) break; + + if (region.is_submap) { + depth++; + } else { + /* We only care of main map addresses and the read only kinds */ + if ((region.protection & VM_PROT_READ) && !(region.protection & VM_PROT_WRITE)) { + __tokencap_ro[__tokencap_ro_cnt].st = (void *)base; + __tokencap_ro[__tokencap_ro_cnt].en = (void *)(base + size); + + if (++__tokencap_ro_cnt == MAX_MAPPINGS) break; + } + } + } + +#elif defined __FreeBSD__ + + int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_VMMAP, getpid()}; + char *buf, *low, *high; + size_t miblen = sizeof(mib)/sizeof(mib[0]); + size_t len; + + if (sysctl(mib, miblen, NULL, &len, NULL, 0) == -1) return; + + len = len * 4 / 3; + buf = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0); + + if (sysctl(mib, miblen, buf, &len, NULL, 0) == -1) { + + munmap(buf, len); + return; + + } + + low = buf; + high = low + len; + + __tokencap_ro_loaded = 1; + + while (low < high) { + struct kinfo_vmentry *region = (struct kinfo_vmentry *)low; + size_t size = region->kve_structsize; + + if (size == 0) break; + + /* We go through the whole mapping of the process and track read-only addresses */ + if ((region->kve_protection & KVME_PROT_READ) && + !(region->kve_protection & KVME_PROT_WRITE)) { + __tokencap_ro[__tokencap_ro_cnt].st = (void *)region->kve_start; + __tokencap_ro[__tokencap_ro_cnt].en = (void *)region->kve_end; + + if (++__tokencap_ro_cnt == MAX_MAPPINGS) break; + } + + low += size; + } + + munmap(buf, len); +#endif } /* Check an address against the list of read-only mappings. */ |