about summary refs log tree commit diff
path: root/frida_mode
diff options
context:
space:
mode:
Diffstat (limited to 'frida_mode')
-rw-r--r--frida_mode/include/seccomp.h111
-rw-r--r--frida_mode/many-linux/Dockerfile4
-rw-r--r--frida_mode/many-linux/GNUmakefile15
-rwxr-xr-xfrida_mode/many-linux/realpath2
-rw-r--r--frida_mode/src/instrument/instrument.c8
-rw-r--r--frida_mode/src/instrument/instrument_coverage.c1
-rw-r--r--frida_mode/src/instrument/instrument_x64.c205
-rw-r--r--frida_mode/src/prefetch.c8
-rw-r--r--frida_mode/src/seccomp/seccomp.c136
-rw-r--r--frida_mode/src/seccomp/seccomp_atomic.c10
-rw-r--r--frida_mode/src/seccomp/seccomp_callback.c124
-rw-r--r--frida_mode/src/seccomp/seccomp_child.c28
-rw-r--r--frida_mode/src/seccomp/seccomp_event.c18
-rw-r--r--frida_mode/src/seccomp/seccomp_filter.c59
-rw-r--r--frida_mode/src/seccomp/seccomp_print.c30
-rw-r--r--frida_mode/src/seccomp/seccomp_socket.c16
-rw-r--r--frida_mode/src/seccomp/seccomp_syscall.c12
-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
-rw-r--r--frida_mode/test/libpcap/GNUmakefile2
-rw-r--r--frida_mode/ub1804/Dockerfile6
-rw-r--r--frida_mode/ub1804/GNUmakefile37
-rw-r--r--frida_mode/ub1804/Makefile9
24 files changed, 838 insertions, 244 deletions
diff --git a/frida_mode/include/seccomp.h b/frida_mode/include/seccomp.h
index 2c037ff7..7e8a7d25 100644
--- a/frida_mode/include/seccomp.h
+++ b/frida_mode/include/seccomp.h
@@ -1,15 +1,95 @@
 #ifndef _SECCOMP_H
 #define _SECCOMP_H
 
-#include <linux/seccomp.h>
+#ifndef __APPLE__
 
-#include "frida-gumjs.h"
+  #include <stdint.h>
+  #include <linux/filter.h>
 
-#define SECCOMP_SOCKET_SEND_FD 0x1D3
-#define SECCOMP_SOCKET_RECV_FD 0x1D4
+  #include "frida-gumjs.h"
 
-#define SECCOMP_OUTPUT_FILE_FD 0x1D5
-#define SECCOMP_PARENT_EVENT_FD 0x1D6
+  /******************************************************************************/
+  #define PR_SET_NO_NEW_PRIVS 38
+
+  #define SECCOMP_SET_MODE_STRICT 0
+  #define SECCOMP_SET_MODE_FILTER 1
+  #define SECCOMP_GET_ACTION_AVAIL 2
+  #define SECCOMP_GET_NOTIF_SIZES 3
+
+  #define SECCOMP_IOC_MAGIC '!'
+  #define SECCOMP_IO(nr) _IO(SECCOMP_IOC_MAGIC, nr)
+  #define SECCOMP_IOR(nr, type) _IOR(SECCOMP_IOC_MAGIC, nr, type)
+  #define SECCOMP_IOW(nr, type) _IOW(SECCOMP_IOC_MAGIC, nr, type)
+  #define SECCOMP_IOWR(nr, type) _IOWR(SECCOMP_IOC_MAGIC, nr, type)
+
+  /* Flags for seccomp notification fd ioctl. */
+  #define SECCOMP_IOCTL_NOTIF_RECV SECCOMP_IOWR(0, struct seccomp_notif)
+  #define SECCOMP_IOCTL_NOTIF_SEND SECCOMP_IOWR(1, struct seccomp_notif_resp)
+  #define SECCOMP_IOCTL_NOTIF_ID_VALID SECCOMP_IOW(2, __u64)
+
+  #define SECCOMP_FILTER_FLAG_NEW_LISTENER (1UL << 3)
+  #define SECCOMP_RET_ALLOW 0x7fff0000U
+  #define SECCOMP_RET_USER_NOTIF 0x7fc00000U
+
+  #define SYS_seccomp __NR_seccomp
+  #ifndef __NR_seccomp
+    #if defined(__arm__)
+      #define __NR_seccomp 383
+    #elif defined(__aarch64__)
+      #define __NR_seccomp 277
+    #elif defined(__x86_64__)
+      #define __NR_seccomp 317
+    #elif defined(__i386__)
+      #define __NR_seccomp 354
+    #else
+      #pragma error "Unsupported architecture"
+    #endif
+  #endif
+
+  #define SECCOMP_USER_NOTIF_FLAG_CONTINUE (1UL << 0)
+
+struct seccomp_notif_resp {
+
+  __u64 id;
+  __s64 val;
+  __s32 error;
+  __u32 flags;
+
+};
+
+struct seccomp_data {
+
+  int   nr;
+  __u32 arch;
+  __u64 instruction_pointer;
+  __u64 args[6];
+
+};
+
+struct seccomp_notif {
+
+  __u64               id;
+  __u32               pid;
+  __u32               flags;
+  struct seccomp_data data;
+
+};
+
+struct seccomp_notif_sizes {
+
+  __u16 seccomp_notif;
+  __u16 seccomp_notif_resp;
+  __u16 seccomp_data;
+
+};
+
+  /******************************************************************************/
+
+  #define SECCOMP_SOCKET_SEND_FD 0x1D3
+  #define SECCOMP_SOCKET_RECV_FD 0x1D4
+
+  #define SECCOMP_OUTPUT_FILE_FD 0x1D5
+  #define SECCOMP_PARENT_EVENT_FD 0x1D6
 
 enum {
 
@@ -319,23 +399,19 @@ enum {
 
 };
 
-extern char *seccomp_filename;
-
 typedef void (*seccomp_child_func_t)(int event_fd, void *ctx);
 
 typedef void (*seccomp_filter_callback_t)(struct seccomp_notif *     req,
                                           struct seccomp_notif_resp *resp,
                                           GumReturnAddressArray *    frames);
 
-void seccomp_config(void);
-void seccomp_init(void);
-void seccomp_on_fork(void);
-void seccomp_print(char *format, ...);
-
 void seccomp_atomic_set(volatile bool *ptr, bool val);
 bool seccomp_atomic_try_set(volatile bool *ptr, bool val);
 void seccomp_atomic_wait(volatile bool *ptr, bool val);
 
+void seccomp_callback_parent(void);
+void seccomp_callback_initialize(void);
+
 void seccomp_child_run(seccomp_child_func_t child_func, void *ctx, pid_t *child,
                        int *event_fd);
 void seccomp_child_wait(int event_fd);
@@ -349,6 +425,8 @@ int  seccomp_filter_install(pid_t child);
 void seccomp_filter_child_install(void);
 void seccomp_filter_run(int fd, seccomp_filter_callback_t callback);
 
+void seccomp_print(char *format, ...);
+
 void seccomp_socket_create(int *sock);
 void seccomp_socket_send(int sockfd, int fd);
 int  seccomp_socket_recv(int sockfd);
@@ -356,4 +434,11 @@ int  seccomp_socket_recv(int sockfd);
 char *seccomp_syscall_lookup(int id);
 
 #endif
+extern char *seccomp_filename;
+
+void seccomp_config(void);
+void seccomp_init(void);
+void seccomp_on_fork(void);
+
+#endif
 
diff --git a/frida_mode/many-linux/Dockerfile b/frida_mode/many-linux/Dockerfile
index 170f0757..6d077dad 100644
--- a/frida_mode/many-linux/Dockerfile
+++ b/frida_mode/many-linux/Dockerfile
@@ -1,10 +1,6 @@
 FROM fridadotre/manylinux-x86_64
 
-COPY realpath /bin/realpath
-RUN chmod +x /bin/realpath
-
 RUN yum -y install xz
-RUN yum -y install vim-common
 
 WORKDIR /AFLplusplus
 ENV CFLAGS="\
diff --git a/frida_mode/many-linux/GNUmakefile b/frida_mode/many-linux/GNUmakefile
index 03b619f6..9992d4fe 100644
--- a/frida_mode/many-linux/GNUmakefile
+++ b/frida_mode/many-linux/GNUmakefile
@@ -2,17 +2,22 @@ PWD:=$(shell pwd)/
 ROOT:=$(PWD)../../
 BUILD_DIR:=$(PWD)build/
 
-.PHONY: all clean shell
+.PHONY: all build docker clean shell
 
-all:
-	docker build --tag many-afl-frida .
+all: docker
 	docker run --rm \
 		-v $(ROOT):/AFLplusplus \
 		many-afl-frida \
 		make -C /AFLplusplus/frida_mode clean all
 
-$(BUILD_DIR):
-	mkdir -p $@
+build:
+	docker run --rm \
+		-v $(ROOT):/AFLplusplus \
+		many-afl-frida \
+		make -C /AFLplusplus/frida_mode
+
+docker:
+	docker build --tag many-afl-frida .
 
 clean:
 	docker images --filter 'dangling=true' -q --no-trunc | xargs -L1 docker rmi --force
diff --git a/frida_mode/many-linux/realpath b/frida_mode/many-linux/realpath
deleted file mode 100755
index 1fdc49a7..00000000
--- a/frida_mode/many-linux/realpath
+++ /dev/null
@@ -1,2 +0,0 @@
-#!/bin/sh
-readlink -f -- "$@"
diff --git a/frida_mode/src/instrument/instrument.c b/frida_mode/src/instrument/instrument.c
index fd0982f8..71d9bdf6 100644
--- a/frida_mode/src/instrument/instrument.c
+++ b/frida_mode/src/instrument/instrument.c
@@ -341,8 +341,14 @@ void instrument_init(void) {
      * parallel fuzzing. The seed itself, doesn't have to be random, it
      * just needs to be different for each instance.
      */
+    guint64 tid;
+#if defined(__APPLE__)
+    pthread_threadid_np(NULL, &tid);
+#else
+    tid = syscall(SYS_gettid);
+#endif
     instrument_hash_seed = g_get_monotonic_time() ^
-                           (((guint64)getpid()) << 32) ^ syscall(SYS_gettid);
+                           (((guint64)getpid()) << 32) ^ tid;
 
   }
 
diff --git a/frida_mode/src/instrument/instrument_coverage.c b/frida_mode/src/instrument/instrument_coverage.c
index 46c816bc..513df29a 100644
--- a/frida_mode/src/instrument/instrument_coverage.c
+++ b/frida_mode/src/instrument/instrument_coverage.c
@@ -711,7 +711,6 @@ void instrument_coverage_normal_init(void) {
 
 void instrument_coverage_unstable_find_output(void) {
 
-  pid_t  parent = getpid();
   gchar *fds_name = g_strdup_printf("/proc/%d/fd/", getppid());
 
   gchar *root = g_file_read_link("/proc/self/root", NULL);
diff --git a/frida_mode/src/instrument/instrument_x64.c b/frida_mode/src/instrument/instrument_x64.c
index fec8afbb..1c2cf113 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,66 @@ 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 *dst_pc_value = (gint *)&code.bytes[patch_offset1];
+    *dst_pc_value = (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);
+
+    }
+
+    dst_pc_value = (gint *)&code.bytes[patch_offset2];
+    *dst_pc_value = (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 *dst_afl_area_ptr_value = (gint *)&code.bytes[afl_area_ptr_offset];
+    *dst_afl_area_ptr_value = (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/src/prefetch.c b/frida_mode/src/prefetch.c
index 0efbc9bf..c30ca65c 100644
--- a/frida_mode/src/prefetch.c
+++ b/frida_mode/src/prefetch.c
@@ -44,8 +44,9 @@ static void gum_afl_stalker_backpatcher_notify(GumStalkerObserver *self,
       sizeof(prefetch_data->backpatch_data) - prefetch_data->backpatch_size;
   if (sizeof(gsize) + size > remaining) { return; }
 
-  *(gsize *)(&prefetch_data->backpatch_data[prefetch_data->backpatch_size]) =
-      size;
+  gsize *dst_backpatch_size = (gsize *)
+      &prefetch_data->backpatch_data[prefetch_data->backpatch_size];
+  *dst_backpatch_size = size;
   prefetch_data->backpatch_size += sizeof(gsize);
 
   memcpy(&prefetch_data->backpatch_data[prefetch_data->backpatch_size],
@@ -115,7 +116,8 @@ static void prefetch_read_patches(void) {
        remaining > sizeof(gsize);
        remaining = prefetch_data->backpatch_size - offset) {
 
-    gsize size = *(gsize *)(&prefetch_data->backpatch_data[offset]);
+    gsize *src_backpatch_data = (gsize *)&prefetch_data->backpatch_data[offset];
+    gsize size = *src_backpatch_data;
     offset += sizeof(gsize);
 
     if (prefetch_data->backpatch_size - offset < size) {
diff --git a/frida_mode/src/seccomp/seccomp.c b/frida_mode/src/seccomp/seccomp.c
index 7683cd71..99111591 100644
--- a/frida_mode/src/seccomp/seccomp.c
+++ b/frida_mode/src/seccomp/seccomp.c
@@ -1,9 +1,3 @@
-#include <execinfo.h>
-#include <fcntl.h>
-#include <linux/seccomp.h>
-#include <stdio.h>
-#include <unistd.h>
-
 #include "frida-gumjs.h"
 
 #include "debug.h"
@@ -13,111 +7,15 @@
 
 char *seccomp_filename = NULL;
 
-static void seccomp_vprint(int fd, char *format, va_list ap) {
-
-  char buffer[4096] = {0};
-  int  len;
-
-  if (vsnprintf(buffer, sizeof(buffer) - 1, format, ap) < 0) { return; }
-
-  len = strnlen(buffer, sizeof(buffer));
-  IGNORED_RETURN(write(fd, buffer, len));
-
-}
-
-void seccomp_print(char *format, ...) {
-
-  va_list ap;
-  va_start(ap, format);
-  seccomp_vprint(SECCOMP_OUTPUT_FILE_FD, format, ap);
-  va_end(ap);
-
-}
-
-static void seccomp_filter_callback(struct seccomp_notif *     req,
-                                    struct seccomp_notif_resp *resp,
-                                    GumReturnAddressArray *    frames) {
-
-  GumDebugSymbolDetails details = {0};
-  if (req->data.nr == SYS_OPENAT) {
-
-    seccomp_print("SYS_OPENAT: (%s)\n", (char *)req->data.args[1]);
-
-  }
-
-  seccomp_print(
-      "\nID (%#llx) for PID %d - %d (%s) [0x%llx 0x%llx 0x%llx 0x%llx 0x%llx "
-      "0x%llx ]\n",
-      req->id, req->pid, req->data.nr, seccomp_syscall_lookup(req->data.nr),
-      req->data.args[0], req->data.args[1], req->data.args[2],
-      req->data.args[3], req->data.args[4], req->data.args[5]);
-
-  seccomp_print("FRAMES: (%u)\n", frames->len);
-  char **syms = backtrace_symbols(frames->items, frames->len);
-  if (syms == NULL) { FATAL("Failed to get symbols"); }
-
-  for (guint i = 0; i < frames->len; i++) {
-
-    if (gum_symbol_details_from_address(frames->items[i], &details)) {
-
-      seccomp_print("\t%3d. %s!%s\n", i, details.module_name,
-                    details.symbol_name);
-
-    } else {
-
-      seccomp_print("\t%3d. %s\n", i, syms[i]);
-
-    }
-
-  }
-
-  free(syms);
-
-  resp->error = 0;
-  resp->val = 0;
-  resp->id = req->id;
-  resp->flags = SECCOMP_USER_NOTIF_FLAG_CONTINUE;
-
-}
-
-static void seccomp_child(int signal_parent, void *ctx) {
-
-  int sock_fd = *((int *)ctx);
-  int fd = seccomp_socket_recv(sock_fd);
-
-  if (close(sock_fd) < 0) { FATAL("child - close"); }
-
-  seccomp_event_signal(signal_parent);
-  seccomp_filter_child_install();
-  seccomp_filter_run(fd, seccomp_filter_callback);
-
-}
-
 void seccomp_on_fork(void) {
 
-  int   sock[2] = {-1, -1};
-  pid_t child = -1;
-  int   child_fd = -1;
-
   if (seccomp_filename == NULL) { return; }
 
-  seccomp_socket_create(sock);
-  seccomp_child_run(seccomp_child, sock, &child, &child_fd);
-
-  if (dup2(child_fd, SECCOMP_PARENT_EVENT_FD) < 0) { FATAL("dup2"); }
-
-  if (close(child_fd) < 0) { FATAL("seccomp_on_fork - close (1)"); }
-
-  if (close(sock[STDIN_FILENO]) < 0) { FATAL("grandparent - close (2)"); }
-
-  int fd = seccomp_filter_install(child);
-  seccomp_socket_send(sock[STDOUT_FILENO], fd);
-
-  if (close(sock[STDOUT_FILENO]) < 0) { FATAL("grandparent - close (3)"); }
-
-  if (close(fd) < 0) { FATAL("grandparent - close (4)"); }
-
-  seccomp_child_wait(SECCOMP_PARENT_EVENT_FD);
+#ifdef __APPLE__
+  FATAL("Seccomp not supported on OSX");
+#else
+  seccomp_callback_parent();
+#endif
 
 }
 
@@ -129,29 +27,15 @@ void seccomp_config(void) {
 
 void seccomp_init(void) {
 
-  char *path = NULL;
-  int   fd;
-
   OKF("Seccomp - file [%s]", seccomp_filename);
 
   if (seccomp_filename == NULL) { return; }
 
-  path = g_canonicalize_filename(seccomp_filename, g_get_current_dir());
-
-  OKF("Seccomp - path [%s]", path);
-
-  fd = open(path, O_RDWR | O_CREAT | O_TRUNC,
-            S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
-
-  if (dup2(fd, SECCOMP_OUTPUT_FILE_FD) < 0) {
-
-    FATAL("Failed to duplicate seccomp output file");
-
-  }
-
-  if (close(fd) < 0) { FATAL("Failed to close seccomp output file fd"); }
-
-  g_free(path);
+#ifdef __APPLE__
+  FATAL("Seccomp not supported on OSX");
+#else
+  seccomp_callback_initialize();
+#endif
 
 }
 
diff --git a/frida_mode/src/seccomp/seccomp_atomic.c b/frida_mode/src/seccomp/seccomp_atomic.c
index 1720a726..5097511a 100644
--- a/frida_mode/src/seccomp/seccomp_atomic.c
+++ b/frida_mode/src/seccomp/seccomp_atomic.c
@@ -1,7 +1,9 @@
-#include <stdbool.h>
-#include <stdio.h>
+#ifndef __APPLE__
 
-#include "debug.h"
+  #include <stdbool.h>
+  #include <stdio.h>
+
+  #include "debug.h"
 
 void seccomp_atomic_set(volatile bool *ptr, bool val) {
 
@@ -26,3 +28,5 @@ void seccomp_atomic_wait(volatile bool *ptr, bool val) {
 
 }
 
+#endif
+
diff --git a/frida_mode/src/seccomp/seccomp_callback.c b/frida_mode/src/seccomp/seccomp_callback.c
new file mode 100644
index 00000000..7e1e2070
--- /dev/null
+++ b/frida_mode/src/seccomp/seccomp_callback.c
@@ -0,0 +1,124 @@
+#ifndef __APPLE__
+
+  #include <execinfo.h>
+  #include <fcntl.h>
+
+  #include "seccomp.h"
+
+  #include "debug.h"
+
+static void seccomp_callback_filter(struct seccomp_notif *     req,
+                                    struct seccomp_notif_resp *resp,
+                                    GumReturnAddressArray *    frames) {
+
+  GumDebugSymbolDetails details = {0};
+  if (req->data.nr == SYS_OPENAT) {
+
+#if UINTPTR_MAX == 0xffffffffffffffffu
+    seccomp_print("SYS_OPENAT: (%s)\n", (char *)req->data.args[1]);
+#endif
+#if UINTPTR_MAX == 0xffffffff
+    seccomp_print("SYS_OPENAT: (%s)\n", (char *)(__u32)req->data.args[1]);
+#endif
+  }
+
+  seccomp_print(
+      "\nID (%#llx) for PID %d - %d (%s) [0x%llx 0x%llx 0x%llx 0x%llx 0x%llx "
+      "0x%llx ]\n",
+      req->id, req->pid, req->data.nr, seccomp_syscall_lookup(req->data.nr),
+      req->data.args[0], req->data.args[1], req->data.args[2],
+      req->data.args[3], req->data.args[4], req->data.args[5]);
+
+  seccomp_print("FRAMES: (%u)\n", frames->len);
+  char **syms = backtrace_symbols(frames->items, frames->len);
+  if (syms == NULL) { FATAL("Failed to get symbols"); }
+
+  for (guint i = 0; i < frames->len; i++) {
+
+    if (gum_symbol_details_from_address(frames->items[i], &details)) {
+
+      seccomp_print("\t%3d. %s!%s\n", i, details.module_name,
+                    details.symbol_name);
+
+    } else {
+
+      seccomp_print("\t%3d. %s\n", i, syms[i]);
+
+    }
+
+  }
+
+  free(syms);
+
+  resp->error = 0;
+  resp->val = 0;
+  resp->id = req->id;
+  resp->flags = SECCOMP_USER_NOTIF_FLAG_CONTINUE;
+
+}
+
+static void seccomp_callback_child(int signal_parent, void *ctx) {
+
+  int sock_fd = *((int *)ctx);
+  int fd = seccomp_socket_recv(sock_fd);
+
+  if (close(sock_fd) < 0) { FATAL("child - close"); }
+
+  seccomp_event_signal(signal_parent);
+  seccomp_filter_child_install();
+  seccomp_filter_run(fd, seccomp_callback_filter);
+
+}
+
+void seccomp_callback_parent(void) {
+
+  int   sock[2] = {-1, -1};
+  pid_t child = -1;
+  int   child_fd = -1;
+
+  seccomp_socket_create(sock);
+  seccomp_child_run(seccomp_callback_child, sock, &child, &child_fd);
+
+  if (dup2(child_fd, SECCOMP_PARENT_EVENT_FD) < 0) { FATAL("dup2"); }
+
+  if (close(child_fd) < 0) { FATAL("seccomp_on_fork - close (1)"); }
+
+  if (close(sock[STDIN_FILENO]) < 0) { FATAL("grandparent - close (2)"); }
+
+  int fd = seccomp_filter_install(child);
+  seccomp_socket_send(sock[STDOUT_FILENO], fd);
+
+  if (close(sock[STDOUT_FILENO]) < 0) { FATAL("grandparent - close (3)"); }
+
+  if (close(fd) < 0) { FATAL("grandparent - close (4)"); }
+
+  seccomp_child_wait(SECCOMP_PARENT_EVENT_FD);
+
+}
+
+void seccomp_callback_initialize(void) {
+
+  char *path = NULL;
+  int   fd;
+
+  path = g_canonicalize_filename(seccomp_filename, g_get_current_dir());
+
+  OKF("Seccomp - path [%s]", path);
+
+  fd = open(path, O_RDWR | O_CREAT | O_TRUNC,
+            S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+
+  if (dup2(fd, SECCOMP_OUTPUT_FILE_FD) < 0) {
+
+    FATAL("Failed to duplicate seccomp output file");
+
+  }
+
+  if (close(fd) < 0) { FATAL("Failed to close seccomp output file fd"); }
+
+  g_free(path);
+
+}
+
+#endif
+
diff --git a/frida_mode/src/seccomp/seccomp_child.c b/frida_mode/src/seccomp/seccomp_child.c
index 4d494137..f665f472 100644
--- a/frida_mode/src/seccomp/seccomp_child.c
+++ b/frida_mode/src/seccomp/seccomp_child.c
@@ -1,18 +1,20 @@
-#include <fcntl.h>
-#include <sched.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/mman.h>
-#include <sys/prctl.h>
-#include <sys/types.h>
-#include <unistd.h>
+#ifndef __APPLE__
 
-#include "debug.h"
+  #include <fcntl.h>
+  #include <sched.h>
+  #include <signal.h>
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <sys/mman.h>
+  #include <sys/prctl.h>
+  #include <sys/types.h>
+  #include <unistd.h>
 
-#include "seccomp.h"
+  #include "debug.h"
 
-#define SECCOMP_CHILD_STACK_SIZE (1UL << 20)
+  #include "seccomp.h"
+
+  #define SECCOMP_CHILD_STACK_SIZE (1UL << 20)
 
 typedef void (*seccomp_child_func_t)(int event_fd, void *ctx);
 
@@ -67,3 +69,5 @@ void seccomp_child_wait(int event_fd) {
 
 }
 
+#endif
+
diff --git a/frida_mode/src/seccomp/seccomp_event.c b/frida_mode/src/seccomp/seccomp_event.c
index ecb9be32..dd4abde7 100644
--- a/frida_mode/src/seccomp/seccomp_event.c
+++ b/frida_mode/src/seccomp/seccomp_event.c
@@ -1,15 +1,17 @@
-#include <stdint.h>
-#include <stdio.h>
-#include <sys/eventfd.h>
-#include <unistd.h>
+#ifndef __APPLE__
 
-#include "debug.h"
+  #include <stdint.h>
+  #include <stdio.h>
+  #include <sys/syscall.h>
+  #include <unistd.h>
 
-#include "seccomp.h"
+  #include "debug.h"
+
+  #include "seccomp.h"
 
 int seccomp_event_create(void) {
 
-  int fd = eventfd(0, 0);
+  int fd = syscall(SYS_eventfd, 0, 0);
   if (fd < 0) { FATAL("seccomp_event_create"); }
   return fd;
 
@@ -43,3 +45,5 @@ void seccomp_event_destroy(int fd) {
 
 }
 
+#endif
+
diff --git a/frida_mode/src/seccomp/seccomp_filter.c b/frida_mode/src/seccomp/seccomp_filter.c
index c16e7ebd..13ff7522 100644
--- a/frida_mode/src/seccomp/seccomp_filter.c
+++ b/frida_mode/src/seccomp/seccomp_filter.c
@@ -1,27 +1,28 @@
-#include <alloca.h>
-#include <errno.h>
-#include <execinfo.h>
-#include <linux/filter.h>
-#include <linux/seccomp.h>
-#include <sys/ioctl.h>
-#include <sys/prctl.h>
-#include <sys/syscall.h>
-#include <signal.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "debug.h"
-
-#include "frida-gumjs.h"
-
-#include "seccomp.h"
-#include "util.h"
-
-#define SECCOMP_FILTER_NUM_FRAMES 512
+#ifndef __APPLE__
+
+  #include <alloca.h>
+  #include <errno.h>
+  #include <execinfo.h>
+  #include <linux/filter.h>
+  #include <sys/ioctl.h>
+  #include <sys/prctl.h>
+  #include <sys/syscall.h>
+  #include <signal.h>
+  #include <stdbool.h>
+  #include <stddef.h>
+  #include <stdio.h>
+  #include <stdlib.h>
+  #include <string.h>
+  #include <unistd.h>
+
+  #include "debug.h"
+
+  #include "frida-gumjs.h"
+
+  #include "seccomp.h"
+  #include "util.h"
+
+  #define SECCOMP_FILTER_NUM_FRAMES 512
 
 extern void gum_linux_parse_ucontext(const ucontext_t *uc, GumCpuContext *ctx);
 
@@ -127,7 +128,10 @@ static GumBacktracer *       seccomp_filter_backtracer = NULL;
 static void seccomp_filter_child_handler(int sig, siginfo_t *info,
                                          void *ucontext) {
 
-  GumCpuContext cpu_context;
+  UNUSED_PARAMETER(sig);
+  UNUSED_PARAMETER(info);
+  UNUSED_PARAMETER(ucontext);
+
   if (seccomp_filter_backtracer == NULL) {
 
     seccomp_filter_backtracer = gum_backtracer_make_fuzzy();
@@ -150,7 +154,8 @@ static void seccomp_filter_parent_handler(int sig, siginfo_t *info,
   ucontext_t *uc = (ucontext_t *)ucontext;
   gum_linux_parse_ucontext(uc, &seccomp_filter_cpu_context);
 
-  if (tgkill(seccomp_filter_child, seccomp_filter_child, SIGUSR1) < 0) {
+  if (syscall(SYS_tgkill, seccomp_filter_child, seccomp_filter_child, SIGUSR1) <
+      0) {
 
     FATAL("kill");
 
@@ -256,3 +261,5 @@ void seccomp_filter_run(int fd, seccomp_filter_callback_t callback) {
 
 }
 
+#endif
+
diff --git a/frida_mode/src/seccomp/seccomp_print.c b/frida_mode/src/seccomp/seccomp_print.c
new file mode 100644
index 00000000..be4d80ce
--- /dev/null
+++ b/frida_mode/src/seccomp/seccomp_print.c
@@ -0,0 +1,30 @@
+#ifndef __APPLE__
+
+  #include <stdarg.h>
+
+  #include "seccomp.h"
+  #include "util.h"
+
+static void seccomp_print_v(int fd, char *format, va_list ap) {
+
+  char buffer[4096] = {0};
+  int  len;
+
+  if (vsnprintf(buffer, sizeof(buffer) - 1, format, ap) < 0) { return; }
+
+  len = strnlen(buffer, sizeof(buffer));
+  IGNORED_RETURN(write(fd, buffer, len));
+
+}
+
+void seccomp_print(char *format, ...) {
+
+  va_list ap;
+  va_start(ap, format);
+  seccomp_print_v(SECCOMP_OUTPUT_FILE_FD, format, ap);
+  va_end(ap);
+
+}
+
+#endif
+
diff --git a/frida_mode/src/seccomp/seccomp_socket.c b/frida_mode/src/seccomp/seccomp_socket.c
index ca42e158..fae95805 100644
--- a/frida_mode/src/seccomp/seccomp_socket.c
+++ b/frida_mode/src/seccomp/seccomp_socket.c
@@ -1,11 +1,13 @@
-#include <stdio.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <unistd.h>
+#ifndef __APPLE__
 
-#include "debug.h"
+  #include <stdio.h>
+  #include <string.h>
+  #include <sys/socket.h>
+  #include <unistd.h>
 
-#include "seccomp.h"
+  #include "debug.h"
+
+  #include "seccomp.h"
 
 union cmsg {
 
@@ -119,3 +121,5 @@ int seccomp_socket_recv(int sockfd) {
 
 }
 
+#endif
+
diff --git a/frida_mode/src/seccomp/seccomp_syscall.c b/frida_mode/src/seccomp/seccomp_syscall.c
index b2c084c8..e023c131 100644
--- a/frida_mode/src/seccomp/seccomp_syscall.c
+++ b/frida_mode/src/seccomp/seccomp_syscall.c
@@ -1,9 +1,11 @@
-#include <limits.h>
-#include <stdio.h>
+#ifndef __APPLE__
 
-#include "debug.h"
+  #include <limits.h>
+  #include <stdio.h>
 
-#include "seccomp.h"
+  #include "debug.h"
+
+  #include "seccomp.h"
 
 typedef struct {
 
@@ -333,3 +335,5 @@ char *seccomp_syscall_lookup(int id) {
 
 }
 
+#endif
+
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)
diff --git a/frida_mode/test/libpcap/GNUmakefile b/frida_mode/test/libpcap/GNUmakefile
index 6f2b58af..f8dc3db7 100644
--- a/frida_mode/test/libpcap/GNUmakefile
+++ b/frida_mode/test/libpcap/GNUmakefile
@@ -59,7 +59,7 @@ 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"
+ifeq "$(ARCH)" "arm64"
  AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000aaaaaaaaa000)
 endif
 
diff --git a/frida_mode/ub1804/Dockerfile b/frida_mode/ub1804/Dockerfile
new file mode 100644
index 00000000..e1f5a339
--- /dev/null
+++ b/frida_mode/ub1804/Dockerfile
@@ -0,0 +1,6 @@
+FROM ubuntu:xenial
+
+WORKDIR /AFLplusplus
+
+RUN apt-get update
+RUN apt-get install -y make gcc g++ xz-utils curl wget clang zlib1g-dev
\ No newline at end of file
diff --git a/frida_mode/ub1804/GNUmakefile b/frida_mode/ub1804/GNUmakefile
new file mode 100644
index 00000000..4247916e
--- /dev/null
+++ b/frida_mode/ub1804/GNUmakefile
@@ -0,0 +1,37 @@
+PWD:=$(shell pwd)/
+ROOT:=$(PWD)../../
+
+.PHONY: all build docker clean shell test
+
+all: docker
+	docker run --rm \
+		-v $(ROOT):/AFLplusplus \
+		ub1804-afl-frida \
+		/bin/sh -c \
+			'make -C /AFLplusplus/ clean all && \
+			make -C /AFLplusplus/frida_mode clean all'
+
+test:
+	docker run --rm \
+		-v $(ROOT):/AFLplusplus \
+		ub1804-afl-frida \
+		/bin/sh -c \
+			'make -C /AFLplusplus/frida_mode/test/png clean all && \
+			make -C /AFLplusplus/frida_mode/test/png/persistent/hook frida'
+
+build:
+	docker run --rm \
+		-v $(ROOT):/AFLplusplus \
+		ub1804-afl-frida \
+		/bin/sh -c \
+			'make -C /AFLplusplus/ all && \
+			make -C /AFLplusplus/frida_mode all'
+
+docker:
+	docker build --tag ub1804-afl-frida .
+
+clean:
+	docker images --filter 'dangling=true' -q --no-trunc | xargs -L1 docker rmi --force
+
+shell:
+	docker run -ti --rm ub1804-afl-frida /bin/bash
diff --git a/frida_mode/ub1804/Makefile b/frida_mode/ub1804/Makefile
new file mode 100644
index 00000000..f3c3cd55
--- /dev/null
+++ b/frida_mode/ub1804/Makefile
@@ -0,0 +1,9 @@
+all:
+	@echo trying to use GNU make...
+	@gmake all || echo please install GNUmake
+
+clean:
+	@gmake clean
+
+shell:
+	@gmake shell