aboutsummaryrefslogtreecommitdiff
path: root/libtokencap
diff options
context:
space:
mode:
Diffstat (limited to 'libtokencap')
-rw-r--r--libtokencap/Makefile2
-rw-r--r--libtokencap/README.md (renamed from libtokencap/README.tokencap)12
-rw-r--r--libtokencap/libtokencap.so.c70
3 files changed, 38 insertions, 46 deletions
diff --git a/libtokencap/Makefile b/libtokencap/Makefile
index a464f76d..ec4c8f95 100644
--- a/libtokencap/Makefile
+++ b/libtokencap/Makefile
@@ -18,7 +18,7 @@ HELPER_PATH = $(PREFIX)/lib/afl
VERSION = $(shell grep '^\#define VERSION ' ../config.h | cut -d '"' -f2)
-CFLAGS ?= -O3 -funroll-loops
+CFLAGS ?= -O3 -funroll-loops -I ../include/
CFLAGS += -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign
all: libtokencap.so
diff --git a/libtokencap/README.tokencap b/libtokencap/README.md
index 650739f2..baf69da1 100644
--- a/libtokencap/README.tokencap
+++ b/libtokencap/README.md
@@ -1,10 +1,8 @@
-=========================================
-strcmp() / memcmp() token capture library
-=========================================
+# strcmp() / memcmp() token capture library
(See ../docs/README for the general instruction manual.)
-This Linux-only companion library allows you to instrument strcmp(), memcmp(),
+This Linux-only 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
@@ -31,15 +29,18 @@ with -fno-builtin and is linked dynamically. If you wish to automate the first
part without mucking with CFLAGS in Makefiles, you can set AFL_NO_BUILTIN=1
when using afl-gcc. This setting specifically adds the following flags:
+```
-fno-builtin-strcmp -fno-builtin-strncmp -fno-builtin-strcasecmp
-fno-builtin-strcasencmp -fno-builtin-memcmp -fno-builtin-strstr
-fno-builtin-strcasestr
+```
The next step is simply loading this library via LD_PRELOAD. The optimal usage
pattern is to allow afl-fuzz to fuzz normally for a while and build up a corpus,
and then fire off the target binary, with libtokencap.so loaded, on every file
found by AFL in that earlier run. This demonstrates the basic principle:
+```
export AFL_TOKEN_FILE=$PWD/temp_output.txt
for i in <out_dir>/queue/id*; do
@@ -48,6 +49,7 @@ found by AFL in that earlier run. This demonstrates the basic principle:
done
sort -u temp_output.txt >afl_dictionary.txt
+```
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
@@ -55,7 +57,7 @@ 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
+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.
diff --git a/libtokencap/libtokencap.so.c b/libtokencap/libtokencap.so.c
index 54072279..17b6190c 100644
--- a/libtokencap/libtokencap.so.c
+++ b/libtokencap/libtokencap.so.c
@@ -27,30 +27,26 @@
#include "../config.h"
#ifndef __linux__
-# error "Sorry, this library is Linux-specific for now!"
-#endif /* !__linux__ */
-
+#error "Sorry, this library is Linux-specific for now!"
+#endif /* !__linux__ */
/* Mapping data and such */
#define MAX_MAPPINGS 1024
-static struct mapping {
- void *st, *en;
-} __tokencap_ro[MAX_MAPPINGS];
+static struct mapping { void *st, *en; } __tokencap_ro[MAX_MAPPINGS];
static u32 __tokencap_ro_cnt;
static u8 __tokencap_ro_loaded;
static FILE* __tokencap_out_file;
-
/* Identify read-only regions in memory. Only parameters that fall into these
ranges are worth dumping when passed to strcmp() and so on. Read-write
regions are far more likely to contain user input instead. */
static void __tokencap_load_mappings(void) {
- u8 buf[MAX_LINE];
+ u8 buf[MAX_LINE];
FILE* f = fopen("/proc/self/maps", "r");
__tokencap_ro_loaded = 1;
@@ -59,8 +55,8 @@ static void __tokencap_load_mappings(void) {
while (fgets(buf, MAX_LINE, f)) {
- u8 rf, wf;
- void* st, *en;
+ u8 rf, wf;
+ void *st, *en;
if (sscanf(buf, "%p-%p %c%c", &st, &en, &rf, &wf) != 4) continue;
if (wf == 'w' || rf != 'r') continue;
@@ -76,7 +72,6 @@ static void __tokencap_load_mappings(void) {
}
-
/* Check an address against the list of read-only mappings. */
static u8 __tokencap_is_ro(const void* ptr) {
@@ -85,20 +80,19 @@ static u8 __tokencap_is_ro(const void* ptr) {
if (!__tokencap_ro_loaded) __tokencap_load_mappings();
- for (i = 0; i < __tokencap_ro_cnt; i++)
+ for (i = 0; i < __tokencap_ro_cnt; i++)
if (ptr >= __tokencap_ro[i].st && ptr <= __tokencap_ro[i].en) return 1;
return 0;
}
-
/* Dump an interesting token to output file, quoting and escaping it
properly. */
static void __tokencap_dump(const u8* ptr, size_t len, u8 is_text) {
- u8 buf[MAX_AUTO_EXTRA * 4 + 1];
+ u8 buf[MAX_AUTO_EXTRA * 4 + 1];
u32 i;
u32 pos = 0;
@@ -120,9 +114,7 @@ static void __tokencap_dump(const u8* ptr, size_t len, u8 is_text) {
pos += 4;
break;
- default:
-
- buf[pos++] = ptr[i];
+ default: buf[pos++] = ptr[i];
}
@@ -130,11 +122,10 @@ static void __tokencap_dump(const u8* ptr, size_t len, u8 is_text) {
buf[pos] = 0;
- fprintf(__tokencap_out_file, "\"%s\"\n", buf);
+ fprintf(__tokencap_out_file, "\"%s\"\n", buf);
}
-
/* Replacements for strcmp(), memcmp(), and so on. Note that these will be used
only if the target is compiled with -fno-builtins and linked dynamically. */
@@ -151,13 +142,13 @@ int strcmp(const char* str1, const char* str2) {
if (c1 != c2) return (c1 > c2) ? 1 : -1;
if (!c1) return 0;
- str1++; str2++;
+ str1++;
+ str2++;
}
}
-
#undef strncmp
int strncmp(const char* str1, const char* str2, size_t len) {
@@ -171,7 +162,8 @@ int strncmp(const char* str1, const char* str2, size_t len) {
if (!c1) return 0;
if (c1 != c2) return (c1 > c2) ? 1 : -1;
- str1++; str2++;
+ str1++;
+ str2++;
}
@@ -179,7 +171,6 @@ int strncmp(const char* str1, const char* str2, size_t len) {
}
-
#undef strcasecmp
int strcasecmp(const char* str1, const char* str2) {
@@ -193,13 +184,13 @@ int strcasecmp(const char* str1, const char* str2) {
if (c1 != c2) return (c1 > c2) ? 1 : -1;
if (!c1) return 0;
- str1++; str2++;
+ str1++;
+ str2++;
}
}
-
#undef strncasecmp
int strncasecmp(const char* str1, const char* str2, size_t len) {
@@ -213,7 +204,8 @@ int strncasecmp(const char* str1, const char* str2, size_t len) {
if (!c1) return 0;
if (c1 != c2) return (c1 > c2) ? 1 : -1;
- str1++; str2++;
+ str1++;
+ str2++;
}
@@ -221,7 +213,6 @@ int strncasecmp(const char* str1, const char* str2, size_t len) {
}
-
#undef memcmp
int memcmp(const void* mem1, const void* mem2, size_t len) {
@@ -233,7 +224,8 @@ int memcmp(const void* mem1, const void* mem2, size_t len) {
unsigned char c1 = *(const char*)mem1, c2 = *(const char*)mem2;
if (c1 != c2) return (c1 > c2) ? 1 : -1;
- mem1++; mem2++;
+ mem1++;
+ mem2++;
}
@@ -241,7 +233,6 @@ int memcmp(const void* mem1, const void* mem2, size_t len) {
}
-
#undef strstr
char* strstr(const char* haystack, const char* needle) {
@@ -249,16 +240,17 @@ char* strstr(const char* haystack, const char* needle) {
if (__tokencap_is_ro(haystack))
__tokencap_dump(haystack, strlen(haystack), 1);
- if (__tokencap_is_ro(needle))
- __tokencap_dump(needle, strlen(needle), 1);
+ if (__tokencap_is_ro(needle)) __tokencap_dump(needle, strlen(needle), 1);
do {
+
const char* n = needle;
const char* h = haystack;
- while(*n && *h && *n == *h) n++, h++;
+ while (*n && *h && *n == *h)
+ n++, h++;
- if(!*n) return (char*)haystack;
+ if (!*n) return (char*)haystack;
} while (*(haystack++));
@@ -266,7 +258,6 @@ char* strstr(const char* haystack, const char* needle) {
}
-
#undef strcasestr
char* strcasestr(const char* haystack, const char* needle) {
@@ -274,25 +265,24 @@ char* strcasestr(const char* haystack, const char* needle) {
if (__tokencap_is_ro(haystack))
__tokencap_dump(haystack, strlen(haystack), 1);
- if (__tokencap_is_ro(needle))
- __tokencap_dump(needle, strlen(needle), 1);
+ if (__tokencap_is_ro(needle)) __tokencap_dump(needle, strlen(needle), 1);
do {
const char* n = needle;
const char* h = haystack;
- while(*n && *h && tolower(*n) == tolower(*h)) n++, h++;
+ while (*n && *h && tolower(*n) == tolower(*h))
+ n++, h++;
- if(!*n) return (char*)haystack;
+ if (!*n) return (char*)haystack;
- } while(*(haystack++));
+ } while (*(haystack++));
return 0;
}
-
/* Init code to open the output file (or default to stderr). */
__attribute__((constructor)) void __tokencap_init(void) {