aboutsummaryrefslogtreecommitdiff
path: root/frida_mode
diff options
context:
space:
mode:
authorllzmb <46303940+llzmb@users.noreply.github.com>2021-11-30 20:28:20 +0100
committerGitHub <noreply@github.com>2021-11-30 20:28:20 +0100
commitda13111117efdb70f81deb162bd9e64c9a7d778a (patch)
tree2d9dbe7aac1212e5729a0a744a5b37e957d0d8a0 /frida_mode
parentf2ff029cc25e81fec36abd0b8c676f1dd6a39c77 (diff)
parent5525f8c9ef8bb879dadd0eb942d524827d1b0362 (diff)
downloadafl++-da13111117efdb70f81deb162bd9e64c9a7d778a.tar.gz
Merge branch 'dev' into docs_edit_readme_frida_mode_qemu_mode
Diffstat (limited to 'frida_mode')
-rw-r--r--frida_mode/README.md44
-rw-r--r--frida_mode/include/util.h5
-rw-r--r--frida_mode/src/entry.c2
-rw-r--r--frida_mode/src/instrument/instrument.c2
-rw-r--r--frida_mode/src/persistent/persistent.c6
-rw-r--r--frida_mode/src/seccomp/seccomp_event.c10
-rw-r--r--frida_mode/src/seccomp/seccomp_filter.c10
-rw-r--r--frida_mode/src/stalker.c22
-rw-r--r--frida_mode/src/stats/stats.c6
-rw-r--r--frida_mode/src/util.c34
-rw-r--r--frida_mode/test/bloaty/GNUmakefile114
-rw-r--r--frida_mode/test/bloaty/Makefile13
-rwxr-xr-xfrida_mode/test/bloaty/get_symbol_addr.py36
13 files changed, 245 insertions, 59 deletions
diff --git a/frida_mode/README.md b/frida_mode/README.md
index c7d331b8..c19280e1 100644
--- a/frida_mode/README.md
+++ b/frida_mode/README.md
@@ -141,31 +141,33 @@ instances run CMPLOG mode and instrumentation of the binary is less frequent
(only on CMP, SUB and CALL instructions) performance is not quite so critical.
## Advanced configuration options
-
+* `AFL_FRIDA_DRIVER_NO_HOOK` - See `AFL_QEMU_DRIVER_NO_HOOK`. When using the
+ QEMU driver to provide a `main` loop for a user provided
+ `LLVMFuzzerTestOneInput`, this option configures the driver to read input from
+ `stdin` rather than using in-memory test cases.
* `AFL_FRIDA_INST_COVERAGE_FILE` - File to write DynamoRIO format coverage
information (e.g., to be loaded within IDA lighthouse).
* `AFL_FRIDA_INST_DEBUG_FILE` - File to write raw assembly of original blocks
and their instrumented counterparts during block compilation.
-```
-***
-
-Creating block for 0x7ffff7953313:
- 0x7ffff7953313 mov qword ptr [rax], 0
- 0x7ffff795331a add rsp, 8
- 0x7ffff795331e ret
-
-Generated block 0x7ffff75e98e2
- 0x7ffff75e98e2 mov qword ptr [rax], 0
- 0x7ffff75e98e9 add rsp, 8
- 0x7ffff75e98ed lea rsp, [rsp - 0x80]
- 0x7ffff75e98f5 push rcx
- 0x7ffff75e98f6 movabs rcx, 0x7ffff795331e
- 0x7ffff75e9900 jmp 0x7ffff75e9384
-
-
-***
-```
+ ```
+ ***
+
+ Creating block for 0x7ffff7953313:
+ 0x7ffff7953313 mov qword ptr [rax], 0
+ 0x7ffff795331a add rsp, 8
+ 0x7ffff795331e ret
+
+ Generated block 0x7ffff75e98e2
+ 0x7ffff75e98e2 mov qword ptr [rax], 0
+ 0x7ffff75e98e9 add rsp, 8
+ 0x7ffff75e98ed lea rsp, [rsp - 0x80]
+ 0x7ffff75e98f5 push rcx
+ 0x7ffff75e98f6 movabs rcx, 0x7ffff795331e
+ 0x7ffff75e9900 jmp 0x7ffff75e9384
+
+ ***
+ ```
* `AFL_FRIDA_INST_JIT` - Enable the instrumentation of Just-In-Time compiled
code. Code is considered to be JIT if the executable segment is not backed by
@@ -194,6 +196,8 @@ Generated block 0x7ffff75e98e2
* `AFL_FRIDA_INST_UNSTABLE_COVERAGE_FILE` - File to write DynamoRIO format
coverage information for unstable edges (e.g., to be loaded within IDA
lighthouse).
+* `AFL_FRIDA_JS_SCRIPT` - Set the script to be loaded by the FRIDA scripting
+ engine. See [Scipting.md](Scripting.md) for details.
* `AFL_FRIDA_OUTPUT_STDOUT` - Redirect the standard output of the target
application to the named file (supersedes the setting of `AFL_DEBUG_CHILD`).
* `AFL_FRIDA_OUTPUT_STDERR` - Redirect the standard error of the target
diff --git a/frida_mode/include/util.h b/frida_mode/include/util.h
index 77491ea8..4dc05f20 100644
--- a/frida_mode/include/util.h
+++ b/frida_mode/include/util.h
@@ -8,9 +8,8 @@
#define UNUSED_PARAMETER(x) (void)(x)
#define IGNORED_RETURN(x) (void)!(x)
-guint64 util_read_address(char *key);
-
-guint64 util_read_num(char *key);
+guint64 util_read_address(char *key, guint64 default_value);
+guint64 util_read_num(char *key, guint64 default_value);
gboolean util_output_enabled(void);
gsize util_rotate(gsize val, gsize shift, gsize size);
gsize util_log2(gsize val);
diff --git a/frida_mode/src/entry.c b/frida_mode/src/entry.c
index 562e74eb..de645fdb 100644
--- a/frida_mode/src/entry.c
+++ b/frida_mode/src/entry.c
@@ -62,7 +62,7 @@ void entry_on_fork(void) {
void entry_config(void) {
- entry_point = util_read_address("AFL_ENTRYPOINT");
+ entry_point = util_read_address("AFL_ENTRYPOINT", 0);
if (getenv("AFL_FRIDA_TRACEABLE") != NULL) { traceable = TRUE; }
}
diff --git a/frida_mode/src/instrument/instrument.c b/frida_mode/src/instrument/instrument.c
index d5823654..414dc84c 100644
--- a/frida_mode/src/instrument/instrument.c
+++ b/frida_mode/src/instrument/instrument.c
@@ -246,7 +246,7 @@ void instrument_config(void) {
instrument_tracing = (getenv("AFL_FRIDA_INST_TRACE") != NULL);
instrument_unique = (getenv("AFL_FRIDA_INST_TRACE_UNIQUE") != NULL);
instrument_use_fixed_seed = (getenv("AFL_FRIDA_INST_SEED") != NULL);
- instrument_fixed_seed = util_read_num("AFL_FRIDA_INST_SEED");
+ instrument_fixed_seed = util_read_num("AFL_FRIDA_INST_SEED", 0);
instrument_coverage_unstable_filename =
(getenv("AFL_FRIDA_INST_UNSTABLE_COVERAGE_FILE"));
diff --git a/frida_mode/src/persistent/persistent.c b/frida_mode/src/persistent/persistent.c
index e62f25d0..817d9925 100644
--- a/frida_mode/src/persistent/persistent.c
+++ b/frida_mode/src/persistent/persistent.c
@@ -22,9 +22,9 @@ gboolean persistent_debug = FALSE;
void persistent_config(void) {
hook_name = getenv("AFL_FRIDA_PERSISTENT_HOOK");
- persistent_start = util_read_address("AFL_FRIDA_PERSISTENT_ADDR");
- persistent_count = util_read_num("AFL_FRIDA_PERSISTENT_CNT");
- persistent_ret = util_read_address("AFL_FRIDA_PERSISTENT_RET");
+ persistent_start = util_read_address("AFL_FRIDA_PERSISTENT_ADDR", 0);
+ persistent_count = util_read_num("AFL_FRIDA_PERSISTENT_CNT", 0);
+ persistent_ret = util_read_address("AFL_FRIDA_PERSISTENT_RET", 0);
if (getenv("AFL_FRIDA_PERSISTENT_DEBUG") != NULL) { persistent_debug = TRUE; }
diff --git a/frida_mode/src/seccomp/seccomp_event.c b/frida_mode/src/seccomp/seccomp_event.c
index 0907eff8..e6585f1d 100644
--- a/frida_mode/src/seccomp/seccomp_event.c
+++ b/frida_mode/src/seccomp/seccomp_event.c
@@ -10,13 +10,13 @@
int seccomp_event_create(void) {
-#ifdef SYS_eventfd
+ #ifdef SYS_eventfd
int fd = syscall(SYS_eventfd, 0, 0);
-#else
-# ifdef SYS_eventfd2
+ #else
+ #ifdef SYS_eventfd2
int fd = syscall(SYS_eventfd2, 0, 0);
-# endif
-#endif
+ #endif
+ #endif
if (fd < 0) { FFATAL("seccomp_event_create"); }
return fd;
diff --git a/frida_mode/src/seccomp/seccomp_filter.c b/frida_mode/src/seccomp/seccomp_filter.c
index 5aee398f..1d050303 100644
--- a/frida_mode/src/seccomp/seccomp_filter.c
+++ b/frida_mode/src/seccomp/seccomp_filter.c
@@ -72,13 +72,13 @@ static struct sock_filter filter[] = {
/* Allow us to make anonymous maps */
BPF_STMT(BPF_LD | BPF_W | BPF_ABS, (offsetof(struct seccomp_data, nr))),
-#ifdef __NR_mmap
+ #ifdef __NR_mmap
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_mmap, 0, 3),
-#else
-# ifdef __NR_mmap2
+ #else
+ #ifdef __NR_mmap2
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_mmap2, 0, 3),
-# endif
-#endif
+ #endif
+ #endif
BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
(offsetof(struct seccomp_data, args[4]))),
BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, -1, 0, 1),
diff --git a/frida_mode/src/stalker.c b/frida_mode/src/stalker.c
index b4dd5a47..caa16b3f 100644
--- a/frida_mode/src/stalker.c
+++ b/frida_mode/src/stalker.c
@@ -61,9 +61,10 @@ void stalker_config(void) {
backpatch_enable = (getenv("AFL_FRIDA_INST_NO_BACKPATCH") == NULL);
- stalker_ic_entries = util_read_num("AFL_FRIDA_STALKER_ADJACENT_BLOCKS");
+ stalker_ic_entries = util_read_num("AFL_FRIDA_STALKER_IC_ENTRIES", 32);
- stalker_adjacent_blocks = util_read_num("AFL_FRIDA_STALKER_IC_ENTRIES");
+ stalker_adjacent_blocks =
+ util_read_num("AFL_FRIDA_STALKER_ADJACENT_BLOCKS", 32);
observer = g_object_new(GUM_TYPE_AFL_STALKER_OBSERVER, NULL);
@@ -98,33 +99,32 @@ void stalker_init(void) {
FOKF("Stalker - adjacent_blocks [%u]", stalker_adjacent_blocks);
#if !(defined(__x86_64__) || defined(__i386__))
- if (stalker_ic_entries != 0) {
+ if (getenv("AFL_FRIDA_STALKER_IC_ENTRIES") != NULL) {
FFATAL("AFL_FRIDA_STALKER_IC_ENTRIES not supported");
}
- if (stalker_adjacent_blocks != 0) {
+ if (getenv("AFL_FRIDA_STALKER_ADJACENT_BLOCKS") != NULL) {
FFATAL("AFL_FRIDA_STALKER_ADJACENT_BLOCKS not supported");
}
#endif
- if (stalker_ic_entries == 0) { stalker_ic_entries = 32; }
- if (instrument_coverage_filename == NULL) {
+ if (instrument_coverage_filename != NULL) {
- if (stalker_adjacent_blocks == 0) { stalker_adjacent_blocks = 32; }
-
- } else {
-
- if (stalker_adjacent_blocks != 0) {
+ if (getenv("AFL_FRIDA_STALKER_ADJACENT_BLOCKS") != NULL) {
FFATAL(
"AFL_FRIDA_STALKER_ADJACENT_BLOCKS and AFL_FRIDA_INST_COVERAGE_FILE "
"are incompatible");
+ } else {
+
+ stalker_adjacent_blocks = 0;
+
}
}
diff --git a/frida_mode/src/stats/stats.c b/frida_mode/src/stats/stats.c
index a61834d6..83ecf89a 100644
--- a/frida_mode/src/stats/stats.c
+++ b/frida_mode/src/stats/stats.c
@@ -323,7 +323,7 @@ static void stats_observer_init(GumStalkerObserver *observer) {
void stats_config(void) {
stats_filename = getenv("AFL_FRIDA_STATS_FILE");
- stats_interval = util_read_num("AFL_FRIDA_STATS_INTERVAL");
+ stats_interval = util_read_num("AFL_FRIDA_STATS_INTERVAL", 10);
}
@@ -332,7 +332,8 @@ void stats_init(void) {
FOKF("Stats - file [%s]", stats_filename);
FOKF("Stats - interval [%" G_GINT64_MODIFIER "u]", stats_interval);
- if (stats_interval != 0 && stats_filename == NULL) {
+ if (getenv("AFL_FRIDA_STATS_INTERVAL") != NULL &&
+ getenv("AFL_FRIDA_STATS_FILE") == NULL) {
FFATAL(
"AFL_FRIDA_STATS_FILE must be specified if "
@@ -340,7 +341,6 @@ void stats_init(void) {
}
- if (stats_interval == 0) { stats_interval = 10; }
stats_interval_us = stats_interval * MICRO_TO_SEC;
if (stats_filename == NULL) { return; }
diff --git a/frida_mode/src/util.c b/frida_mode/src/util.c
index d84b7065..6f52b6cb 100644
--- a/frida_mode/src/util.c
+++ b/frida_mode/src/util.c
@@ -1,10 +1,11 @@
#include "util.h"
-guint64 util_read_address(char *key) {
+guint64 util_read_address(char *key, guint64 default_value) {
char *value_str = getenv(key);
+ char *end_ptr;
- if (value_str == NULL) { return 0; }
+ if (value_str == NULL) { return default_value; }
if (!g_str_has_prefix(value_str, "0x")) {
@@ -25,8 +26,17 @@ guint64 util_read_address(char *key) {
}
- guint64 value = g_ascii_strtoull(value_str2, NULL, 16);
- if (value == 0) {
+ errno = 0;
+
+ guint64 value = g_ascii_strtoull(value_str2, &end_ptr, 16);
+
+ if (errno != 0) {
+
+ FATAL("Error (%d) during conversion: %s", errno, value_str);
+
+ }
+
+ if (value == 0 && end_ptr == value_str2) {
FATAL("Invalid address failed hex conversion: %s=%s\n", key, value_str2);
@@ -36,11 +46,12 @@ guint64 util_read_address(char *key) {
}
-guint64 util_read_num(char *key) {
+guint64 util_read_num(char *key, guint64 default_value) {
char *value_str = getenv(key);
+ char *end_ptr;
- if (value_str == NULL) { return 0; }
+ if (value_str == NULL) { return default_value; }
for (char *c = value_str; *c != '\0'; c++) {
@@ -53,8 +64,17 @@ guint64 util_read_num(char *key) {
}
+ errno = 0;
+
guint64 value = g_ascii_strtoull(value_str, NULL, 10);
- if (value == 0) {
+
+ if (errno != 0) {
+
+ FATAL("Error (%d) during conversion: %s", errno, value_str);
+
+ }
+
+ if (value == 0 && end_ptr == value_str) {
FATAL("Invalid address failed numeric conversion: %s=%s\n", key, value_str);
diff --git a/frida_mode/test/bloaty/GNUmakefile b/frida_mode/test/bloaty/GNUmakefile
new file mode 100644
index 00000000..7ef4fe81
--- /dev/null
+++ b/frida_mode/test/bloaty/GNUmakefile
@@ -0,0 +1,114 @@
+PWD:=$(shell pwd)/
+ROOT:=$(PWD)../../../
+BUILD_DIR:=$(PWD)build/
+
+AFLPP_FRIDA_DRIVER_HOOK_OBJ=$(ROOT)frida_mode/build/frida_hook.so
+AFLPP_QEMU_DRIVER_HOOK_OBJ=$(ROOT)frida_mode/build/qemu_hook.so
+
+# LIBFUZZER_LIB:=/usr/lib/llvm-12/lib/libFuzzer.a
+
+BLOATY_GIT_REPO:=https://github.com/google/bloaty.git
+BLOATY_DIR:=$(BUILD_DIR)bloaty/
+TEST_BIN:=$(BLOATY_DIR)fuzz_target
+
+ifeq "$(shell uname)" "Darwin"
+TEST_BIN_LDFLAGS:=-undefined dynamic_lookup -Wl,-no_pie
+endif
+
+TEST_DATA_DIR:=$(BUILD_DIR)in/
+TEST_DATA_SRC:=$(BLOATY_DIR)tests/testdata/fuzz_corpus/
+DUMMY_DATA_FILE:=$(BUILD_DIR)default_seed
+
+FRIDA_OUT:=$(BUILD_DIR)frida-out
+QEMU_OUT:=$(BUILD_DIR)qemu-out
+
+ifndef ARCH
+
+ARCH=$(shell uname -m)
+ifeq "$(ARCH)" "aarch64"
+ ARCH:=arm64
+endif
+
+ifeq "$(ARCH)" "i686"
+ ARCH:=x86
+endif
+endif
+
+GET_SYMBOL_ADDR:=$(ROOT)frida_mode/util/get_symbol_addr.sh
+
+AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000)
+
+ifeq "$(ARCH)" "aarch64"
+ AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000aaaaaaaaa000)
+endif
+
+ifeq "$(ARCH)" "x86_64"
+ AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000555555554000)
+endif
+
+ifeq "$(ARCH)" "x86"
+ AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x56555000)
+endif
+
+.PHONY: all clean frida hook
+
+all: $(TEST_BIN)
+ make -C $(ROOT)frida_mode/
+
+32:
+ CXXFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all
+
+$(BUILD_DIR):
+ mkdir -p $@
+
+########## BLOATY #######
+
+$(BLOATY_DIR): | $(BUILD_DIR)
+ git clone --depth 1 $(BLOATY_GIT_REPO) $@
+
+$(TEST_BIN): $(BLOATY_DIR)
+ cd $(BLOATY_DIR) && CC=clang CXX=clang++ CCC=clang++ LIB_FUZZING_ENGINE="-fsanitize=fuzzer" cmake -G Ninja -DBUILD_TESTING=false $(BLOATY_DIR)
+ cd $(BLOATY_DIR) && CC=clang CXX=clang++ CCC=clang++ ninja -j $(shell nproc)
+
+########## DUMMY #######
+
+$(TEST_DATA_DIR): | $(BLOATY_DIR) $(BUILD_DIR)
+ cp -av $(TEST_DATA_SRC) $@
+
+$(DUMMY_DATA_FILE): | $(TEST_DATA_DIR)
+ dd if=/dev/zero bs=1048576 count=1 of=$@
+
+###### TEST DATA #######
+
+clean:
+ rm -rf $(BUILD_DIR)
+
+frida: $(TEST_BIN) $(AFLPP_FRIDA_DRIVER_HOOK_OBJ) $(TEST_DATA_FILE) $(DUMMY_DATA_FILE)
+ AFL_FRIDA_PERSISTENT_CNT=1000000 \
+ AFL_FRIDA_PERSISTENT_HOOK=$(AFLPP_FRIDA_DRIVER_HOOK_OBJ) \
+ AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR) \
+ AFL_ENTRYPOINT=$(AFL_FRIDA_PERSISTENT_ADDR) \
+ $(ROOT)afl-fuzz \
+ -i $(TEST_DATA_DIR) \
+ -o $(FRIDA_OUT) \
+ -m none \
+ -d \
+ -O \
+ -V 30 \
+ -- \
+ $(TEST_BIN) $(DUMMY_DATA_FILE)
+
+qemu: $(TEST_BIN) $(AFLPP_QEMU_DRIVER_HOOK_OBJ) $(TEST_DATA_FILE) $(DUMMY_DATA_FILE)
+ AFL_QEMU_PERSISTENT_CNT=1000000 \
+ AFL_QEMU_PERSISTENT_HOOK=$(AFLPP_QEMU_DRIVER_HOOK_OBJ) \
+ AFL_QEMU_PERSISTENT_ADDR=$(AFL_QEMU_PERSISTENT_ADDR) \
+ AFL_ENTRYPOINT=$(AFL_QEMU_PERSISTENT_ADDR) \
+ $(ROOT)afl-fuzz \
+ -i $(TEST_DATA_DIR) \
+ -o $(QEMU_OUT) \
+ -m none \
+ -d \
+ -Q \
+ -V 30 \
+ -- \
+ $(TEST_BIN) $(DUMMY_DATA_FILE)
diff --git a/frida_mode/test/bloaty/Makefile b/frida_mode/test/bloaty/Makefile
new file mode 100644
index 00000000..07b139e9
--- /dev/null
+++ b/frida_mode/test/bloaty/Makefile
@@ -0,0 +1,13 @@
+all:
+ @echo trying to use GNU make...
+ @gmake all || echo please install GNUmake
+
+32:
+ @echo trying to use GNU make...
+ @gmake 32 || echo please install GNUmake
+
+clean:
+ @gmake clean
+
+frida:
+ @gmake frida
diff --git a/frida_mode/test/bloaty/get_symbol_addr.py b/frida_mode/test/bloaty/get_symbol_addr.py
new file mode 100755
index 00000000..1c46e010
--- /dev/null
+++ b/frida_mode/test/bloaty/get_symbol_addr.py
@@ -0,0 +1,36 @@
+#!/usr/bin/python3
+import argparse
+from elftools.elf.elffile import ELFFile
+
+def process_file(file, symbol, base):
+ with open(file, 'rb') as f:
+ elf = ELFFile(f)
+ symtab = elf.get_section_by_name('.symtab')
+ mains = symtab.get_symbol_by_name(symbol)
+ if len(mains) != 1:
+ print ("Failed to find main")
+ return 1
+
+ main_addr = mains[0]['st_value']
+ main = base + main_addr
+ print ("0x%016x" % main)
+ return 0
+
+def hex_value(x):
+ return int(x, 16)
+
+def main():
+ parser = argparse.ArgumentParser(description='Process some integers.')
+ parser.add_argument('-f', '--file', dest='file', type=str,
+ help='elf file name', required=True)
+ parser.add_argument('-s', '--symbol', dest='symbol', type=str,
+ help='symbol name', required=True)
+ parser.add_argument('-b', '--base', dest='base', type=hex_value,
+ help='elf base address', required=True)
+
+ args = parser.parse_args()
+ return process_file (args.file, args.symbol, args.base)
+
+if __name__ == "__main__":
+ ret = main()
+ exit(ret)