aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWorksButNotTested <62701594+WorksButNotTested@users.noreply.github.com>2021-09-22 23:05:54 +0100
committerGitHub <noreply@github.com>2021-09-23 00:05:54 +0200
commitc8f6a313110db8db033bfbfc4eb3d7043daa430d (patch)
tree866110e47464ab809824ab07d56c13b025419fda
parenta88f6d3b06a7024a1b7b0789e993975cdafa878b (diff)
downloadafl++-c8f6a313110db8db033bfbfc4eb3d7043daa430d.tar.gz
Performance improvements (#1094)
-rw-r--r--frida_mode/src/instrument/instrument_x64.c202
-rw-r--r--frida_mode/test/freetype2/GNUmakefile192
-rw-r--r--frida_mode/test/freetype2/Makefile13
-rwxr-xr-xfrida_mode/test/freetype2/get_symbol_addr.py36
4 files changed, 413 insertions, 30 deletions
diff --git a/frida_mode/src/instrument/instrument_x64.c b/frida_mode/src/instrument/instrument_x64.c
index fec8afbb..8948c4df 100644
--- a/frida_mode/src/instrument/instrument_x64.c
+++ b/frida_mode/src/instrument/instrument_x64.c
@@ -1,6 +1,9 @@
+#include <stddef.h>
+
#include "frida-gumjs.h"
#include "config.h"
+#include "debug.h"
#include "instrument.h"
@@ -8,38 +11,120 @@
static GumAddress current_log_impl = GUM_ADDRESS(0);
-static const guint8 afl_log_code[] = {
+ #pragma pack(push, 1)
+
+typedef struct {
+
+ /*
+ * pushfq
+ * push rdx
+ * mov rdx, [&previouspc] (rip relative addr)
+ * xor rdx, rdi (current_pc)
+ * shr rdi. 1
+ * mov [&previouspc], rdi
+ * lea rsi, [&_afl_area_ptr] (rip relative)
+ * add rdx, rsi
+ * add byte ptr [rdx], 1
+ * adc byte ptr [rdx], 0
+
+ * pop rdx
+ * popfq
+ */
+ uint8_t push_fq;
+ uint8_t push_rdx;
+ uint8_t mov_rdx_rip_off[7];
+ uint8_t xor_rdx_rdi[3];
+ uint8_t shr_rdi[3];
+ uint8_t mov_rip_off_rdi[7];
+
+ uint8_t lea_rdi_rip_off[7];
+ uint8_t add_rdx_rdi[3];
+ uint8_t add_byte_ptr_rdx[3];
+ uint8_t adc_byte_ptr_rdx[3];
+
+ uint8_t pop_rdx;
+ uint8_t pop_fq;
+ uint8_t ret;
+
+} afl_log_code_asm_t;
+
+ #pragma pack(pop)
+
+ #pragma pack(push, 8)
+typedef struct {
+
+ afl_log_code_asm_t assembly;
+ uint64_t current_pc;
+
+} afl_log_code_t;
+
+ #pragma pack(pop)
+
+typedef union {
+
+ afl_log_code_t data;
+ uint8_t bytes[0];
+
+} afl_log_code;
+
+static const afl_log_code_asm_t template = {
+
+ .push_fq = 0x9c,
+ .push_rdx = 0x52,
+ .mov_rdx_rip_off =
+ {
+
+ 0x48, 0x8b, 0x15,
+ /* TBC */
+
+ },
+
+ .xor_rdx_rdi =
+ {
+
+ 0x48,
+ 0x31,
+ 0xfa,
+
+ },
+
+ .shr_rdi = {0x48, 0xd1, 0xef},
+ .mov_rip_off_rdi = {0x48, 0x89, 0x3d},
+
+ .lea_rdi_rip_off =
+ {
+
+ 0x48,
+ 0x8d,
+ 0x3d,
- 0x9c, /* pushfq */
- 0x51, /* push rcx */
- 0x52, /* push rdx */
+ },
- 0x48, 0x8b, 0x0d, 0x26,
- 0x00, 0x00, 0x00, /* mov rcx, sym.&previous_pc */
- 0x48, 0x8b, 0x11, /* mov rdx, qword [rcx] */
- 0x48, 0x31, 0xfa, /* xor rdx, rdi */
+ .add_rdx_rdi = {0x48, 0x01, 0xfA},
- 0x48, 0x03, 0x15, 0x11,
- 0x00, 0x00, 0x00, /* add rdx, sym._afl_area_ptr_ptr */
+ .add_byte_ptr_rdx =
+ {
- 0x80, 0x02, 0x01, /* add byte ptr [rdx], 1 */
- 0x80, 0x12, 0x00, /* adc byte ptr [rdx], 0 */
- 0x66, 0xd1, 0xcf, /* ror di, 1 */
- 0x48, 0x89, 0x39, /* mov qword [rcx], rdi */
+ 0x80,
+ 0x02,
+ 0x01,
- 0x5a, /* pop rdx */
- 0x59, /* pop rcx */
- 0x9d, /* popfq */
+ },
- 0xc3, /* ret */
+ .adc_byte_ptr_rdx =
+ {
- 0x90
+ 0x80,
+ 0x12,
+ 0x00,
- /* Read-only data goes here: */
- /* uint8_t* __afl_area_ptr */
- /* uint64_t* &previous_pc */
+ },
-};
+ .pop_rdx = 0x5a,
+ .pop_fq = 0x9d,
+ .ret = 0xc3};
+
+static guint8 align_pad[] = {0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90};
gboolean instrument_is_coverage_optimize_supported(void) {
@@ -47,12 +132,19 @@ gboolean instrument_is_coverage_optimize_supported(void) {
}
-static guint8 align_pad[] = {0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90};
+static gboolean instrument_coverage_in_range(gssize offset) {
+
+ return (offset >= G_MININT32 && offset <= G_MAXINT32);
+
+}
static void instrument_coverate_write_function(GumStalkerOutput *output) {
guint64 misalign = 0;
GumX86Writer *cw = output->writer.x86;
+ GumAddress code_addr = 0;
+ afl_log_code code = {0};
+ guint64 instrument_hash_zero = 0;
if (current_log_impl == 0 ||
!gum_x86_writer_can_branch_directly_between(cw->pc, current_log_impl) ||
@@ -71,13 +163,63 @@ static void instrument_coverate_write_function(GumStalkerOutput *output) {
}
current_log_impl = cw->pc;
- gum_x86_writer_put_bytes(cw, afl_log_code, sizeof(afl_log_code));
+ // gum_x86_writer_put_breakpoint(cw);
+ code_addr = cw->pc;
+
+ code.data.assembly = template;
+ code.data.current_pc = instrument_get_offset_hash(0);
+
+ gssize current_pc_value1 =
+ GPOINTER_TO_SIZE(&instrument_previous_pc) -
+ (code_addr + offsetof(afl_log_code, data.assembly.mov_rdx_rip_off) +
+ sizeof(code.data.assembly.mov_rdx_rip_off));
+ gssize patch_offset1 =
+ offsetof(afl_log_code, data.assembly.mov_rdx_rip_off) +
+ sizeof(code.data.assembly.mov_rdx_rip_off) - sizeof(gint);
+ if (!instrument_coverage_in_range(current_pc_value1)) {
+
+ FATAL("Patch out of range (current_pc_value1): 0x%016lX",
+ current_pc_value1);
+
+ }
+
+ *((gint *)&code.bytes[patch_offset1]) = (gint)current_pc_value1;
+
+ gssize current_pc_value2 =
+ GPOINTER_TO_SIZE(&instrument_previous_pc) -
+ (code_addr + offsetof(afl_log_code, data.assembly.mov_rip_off_rdi) +
+ sizeof(code.data.assembly.mov_rip_off_rdi));
+ gssize patch_offset2 =
+ offsetof(afl_log_code, data.assembly.mov_rip_off_rdi) +
+ sizeof(code.data.assembly.mov_rip_off_rdi) - sizeof(gint);
+
+ if (!instrument_coverage_in_range(current_pc_value2)) {
+
+ FATAL("Patch out of range (current_pc_value2): 0x%016lX",
+ current_pc_value2);
+
+ }
+
+ *((gint *)&code.bytes[patch_offset2]) = (gint)current_pc_value2;
+
+ gsize afl_area_ptr_value =
+ GPOINTER_TO_SIZE(__afl_area_ptr) -
+ (code_addr + offsetof(afl_log_code, data.assembly.lea_rdi_rip_off) +
+ sizeof(code.data.assembly.lea_rdi_rip_off));
+ gssize afl_area_ptr_offset =
+ offsetof(afl_log_code, data.assembly.lea_rdi_rip_off) +
+ sizeof(code.data.assembly.lea_rdi_rip_off) - sizeof(gint);
+
+ if (!instrument_coverage_in_range(afl_area_ptr_value)) {
+
+ FATAL("Patch out of range (afl_area_ptr_value): 0x%016lX",
+ afl_area_ptr_value);
+
+ }
+
+ *((gint *)&code.bytes[afl_area_ptr_offset]) = (gint)afl_area_ptr_value;
- uint64_t *afl_prev_loc_ptr = &instrument_previous_pc;
- gum_x86_writer_put_bytes(cw, (const guint8 *)&__afl_area_ptr,
- sizeof(__afl_area_ptr));
- gum_x86_writer_put_bytes(cw, (const guint8 *)&afl_prev_loc_ptr,
- sizeof(afl_prev_loc_ptr));
+ gum_x86_writer_put_bytes(cw, code.bytes, sizeof(afl_log_code));
gum_x86_writer_put_label(cw, after_log_impl);
diff --git a/frida_mode/test/freetype2/GNUmakefile b/frida_mode/test/freetype2/GNUmakefile
new file mode 100644
index 00000000..891660ca
--- /dev/null
+++ b/frida_mode/test/freetype2/GNUmakefile
@@ -0,0 +1,192 @@
+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
+
+# git clone git://git.sv.nongnu.org/freetype/freetype2.git
+# git clone https://github.com/unicode-org/text-rendering-tests.git TRT
+# wget https://github.com/libarchive/libarchive/releases/download/v3.4.3/libarchive-3.4.3.tar.xz
+
+# cp TRT/fonts/TestKERNOne.otf $OUT/seeds/
+# cp TRT/fonts/TestGLYFOne.ttf $OUT/seeds/
+
+# $CXX $CXXFLAGS -std=c++11 -I include -I . src/tools/ftfuzzer/ftfuzzer.cc \
+# objs/.libs/libfreetype.a $FUZZER_LIB -L /usr/local/lib -larchive \
+# -o $OUT/ftfuzzer
+
+LIBARCHIVE_URL:=https://github.com/libarchive/libarchive/releases/download/v3.4.3/libarchive-3.4.3.tar.xz
+LIBARCHIVE_BUILD_DIR:=$(BUILD_DIR)libarchive/
+LIBARCHIVE_TARBALL:=$(LIBARCHIVE_BUILD_DIR)libarchive-3.4.3.tar.xz
+LIBARCHIVE_DIR:=$(LIBARCHIVE_BUILD_DIR)libarchive-3.4.3/
+LIBARCHIVE_LIB:=$(LIBARCHIVE_DIR).libs/libarchive.a
+
+FREETYPE2_GIT_REPO:=git://git.sv.nongnu.org/freetype/freetype2.git
+FREETYPE2_BUILD_DIR:=$(BUILD_DIR)freetype2/
+FREETYPE2_DIR:=$(FREETYPE2_BUILD_DIR)freetype2/
+FREETYPE2_LIB:=$(FREETYPE2_DIR)objs/.libs/libfreetype.a
+
+HARNESS_URL:=https://raw.githubusercontent.com/llvm/llvm-project/main/compiler-rt/lib/fuzzer/standalone/StandaloneFuzzTargetMain.c
+HARNESS_SRC:=$(BUILD_DIR)StandaloneFuzzTargetMain.c
+HARNESS_OBJ:=$(BUILD_DIR)StandaloneFuzzTargetMain.o
+
+TRT_GIT_REPO:=https://github.com/unicode-org/text-rendering-tests.git
+TRT_DIR:=$(BUILD_DIR)TRT/
+
+FUZZER_SRC:=$(FREETYPE2_DIR)src/tools/ftfuzzer/ftfuzzer.cc
+
+
+LDFLAGS += -lpthread
+
+TEST_BIN:=$(BUILD_DIR)test
+ifeq "$(shell uname)" "Darwin"
+TEST_BIN_LDFLAGS:=-undefined dynamic_lookup -Wl,-no_pie
+endif
+
+TEST_DATA_DIR:=$(BUILD_DIR)in/
+TEST_DATA_FILE:=$(TEST_DATA_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 $@
+
+########## LIBARCHIVE #######
+
+$(LIBARCHIVE_BUILD_DIR): | $(BUILD_DIR)
+ mkdir -p $@
+
+$(LIBARCHIVE_TARBALL): | $(LIBARCHIVE_BUILD_DIR)
+ wget -O $@ $(LIBARCHIVE_URL)
+
+$(LIBARCHIVE_DIR): | $(LIBARCHIVE_TARBALL)
+ tar Jxvf $(LIBARCHIVE_TARBALL) -C $(LIBARCHIVE_BUILD_DIR)
+
+$(LIBARCHIVE_DIR)Makefile: | $(LIBARCHIVE_DIR)
+ cd $(LIBARCHIVE_DIR) && ./configure --disable-shared
+
+$(LIBARCHIVE_LIB): $(LIBARCHIVE_DIR)Makefile
+ make -C $(LIBARCHIVE_DIR) clean all
+
+########## FREETYPE2 #######
+
+$(FREETYPE2_BUILD_DIR): | $(BUILD_DIR)
+ mkdir -p $@
+
+$(FREETYPE2_DIR): | $(FREETYPE2_BUILD_DIR)
+ git clone $(FREETYPE2_GIT_REPO) $@
+ git -C $(FREETYPE2_DIR) checkout cd02d359a6d0455e9d16b87bf9665961c4699538
+
+$(FREETYPE2_LIB): | $(FREETYPE2_DIR)
+ cd $(FREETYPE2_DIR) && ./autogen.sh
+ cd $(FREETYPE2_DIR) && ./configure --with-harfbuzz=no --with-bzip2=no --with-png=no --without-zlib
+ make -C $(FREETYPE2_DIR) all
+
+########## HARNESS #######
+
+$(HARNESS_SRC):
+ wget -O $@ $(HARNESS_URL)
+
+$(HARNESS_OBJ): $(HARNESS_SRC)
+ $(CC) -o $@ -c $<
+
+########## TEST #######
+
+$(TEST_BIN): $(LIBARCHIVE_LIB) $(FREETYPE2_LIB) $(HARNESS_OBJ)
+ $(CXX) \
+ $(CXXFLAGS) \
+ -std=c++11 \
+ -I $(FREETYPE2_DIR)include \
+ -I $(FREETYPE2_DIR) \
+ -I $(LIBARCHIVE_DIR)/libarchive \
+ $(FUZZER_SRC) \
+ $(FREETYPE2_LIB) \
+ $(LIBARCHIVE_LIB) \
+ $(HARNESS_OBJ) \
+ -o $@
+
+########## DUMMY #######
+
+$(TRT_DIR): | $(BUILD_DIR)
+ git clone $(TRT_GIT_REPO) $@
+
+$(TEST_DATA_DIR): | $(TRT_DIR)
+ mkdir -p $@
+ cp $(TRT_DIR)fonts/TestKERNOne.otf $@
+ cp $(TRT_DIR)fonts/TestGLYFOne.ttf $@
+
+$(TEST_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)
+ 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) $(TEST_DATA_FILE)
+
+qemu: $(TEST_BIN) $(AFLPP_QEMU_DRIVER_HOOK_OBJ) $(TEST_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) $(TEST_DATA_FILE)
diff --git a/frida_mode/test/freetype2/Makefile b/frida_mode/test/freetype2/Makefile
new file mode 100644
index 00000000..07b139e9
--- /dev/null
+++ b/frida_mode/test/freetype2/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/freetype2/get_symbol_addr.py b/frida_mode/test/freetype2/get_symbol_addr.py
new file mode 100755
index 00000000..1c46e010
--- /dev/null
+++ b/frida_mode/test/freetype2/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)