about summary refs log tree commit diff
diff options
context:
space:
mode:
authorWorksButNotTested <62701594+WorksButNotTested@users.noreply.github.com>2021-04-29 08:06:14 +0100
committerGitHub <noreply@github.com>2021-04-29 09:06:14 +0200
commit26b84e3521936ec11b7615bb833310d62795020e (patch)
tree21e3d9b6fd35f684b170c9c14141874719c85d4a
parentaeb68835328d52722e21c62e4a124f486378897e (diff)
downloadafl++-26b84e3521936ec11b7615bb833310d62795020e.tar.gz
Fixes for aarch64, OSX and other minor issues (#891)
Co-authored-by: Your Name <you@example.com>
-rw-r--r--frida_mode/GNUmakefile28
-rw-r--r--frida_mode/src/complog/complog.c5
-rw-r--r--frida_mode/src/complog/complog_arm.c6
-rw-r--r--frida_mode/src/complog/complog_arm64.c6
-rw-r--r--frida_mode/src/complog/complog_x86.c6
-rwxr-xr-xfrida_mode/src/lib/libbin0 -> 4144 bytes
-rw-r--r--frida_mode/src/lib/lib.c (renamed from frida_mode/src/lib.c)79
-rw-r--r--frida_mode/src/lib/lib_apple.c82
-rw-r--r--frida_mode/src/main.c4
-rw-r--r--frida_mode/src/persistent/persistent.c4
-rw-r--r--frida_mode/src/persistent/persistent_arm32.c2
-rw-r--r--frida_mode/src/persistent/persistent_arm64.c2
-rw-r--r--frida_mode/src/persistent/persistent_x86.c2
-rw-r--r--frida_mode/test/exe/GNUmakefile50
-rw-r--r--frida_mode/test/exe/Makefile12
-rw-r--r--frida_mode/test/exe/testinstr.c112
-rw-r--r--frida_mode/test/png/GNUmakefile4
17 files changed, 354 insertions, 50 deletions
diff --git a/frida_mode/GNUmakefile b/frida_mode/GNUmakefile
index 65a7a1c3..d2f5ba4b 100644
--- a/frida_mode/GNUmakefile
+++ b/frida_mode/GNUmakefile
@@ -10,16 +10,29 @@ OBJS:=$(foreach src,$(SOURCES),$(OBJ_DIR)$(notdir $(patsubst %.c, %.o, $(src))))
 CFLAGS+=-fPIC \
 		-D_GNU_SOURCE \
 		-D_FORTIFY_SOURCE=2 \
-		-Wno-pointer-arith \
 		-g \
 		-O3 \
 		-funroll-loops \
 
+RT_CFLAGS:=-Wno-unused-parameter \
+		   -Wno-sign-compare \
+		   -Wno-unused-function \
+		   -Wno-unused-result \
+
 LDFLAGS+=-shared \
 		 -lpthread \
 		 -lresolv \
 		 -ldl \
 
+ifdef DEBUG
+CFLAGS+=-Werror \
+		-Wall \
+		-Wextra \
+		-Wpointer-arith
+else
+CFLAGS+=-Wno-pointer-arith
+endif
+
 FRIDA_BUILD_DIR:=$(BUILD_DIR)frida/
 FRIDA_TRACE:=$(BUILD_DIR)afl-frida-trace.so
 FRIDA_TRACE_EMBEDDED:=$(BUILD_DIR)afl-frida-trace-embedded
@@ -31,7 +44,11 @@ endif
 
 ifeq "$(shell uname)" "Darwin"
  OS:=macos
- CFLAGS:=$(CFLAGS) -Wno-deprecated-declarations
+ RT_CFLAGS:=$(RT_CFLAGS) -Wno-deprecated-declarations
+else
+ifdef DEBUG
+ RT_CFLAGS:=$(RT_CFLAGS) -Wno-prio-ctor-dtor
+endif
 endif
 
 ifeq "$(shell uname)" "Linux"
@@ -81,17 +98,14 @@ $(GUM_DEVIT_HEADER): | $(GUM_DEVKIT_TARBALL)
 $(AFL_COMPILER_RT_OBJ): $(AFL_COMPILER_RT_SRC)
 	$(CC) \
 		$(CFLAGS) \
+		$(RT_CFLAGS) \
 		-I $(ROOT) \
 		-I $(ROOT)include \
-		-Wno-unused-parameter \
-		-Wno-sign-compare \
-		-Wno-unused-function \
-		-Wno-unused-result \
 		-o $@ \
 		-c $<
 
 
-define BUILD_SOURCE =
+define BUILD_SOURCE
 $(2): $(1) GNUmakefile | $(OBJ_DIR)
 	$(CC) \
 		$(CFLAGS) \
diff --git a/frida_mode/src/complog/complog.c b/frida_mode/src/complog/complog.c
index 1857ea3b..ce8a3f62 100644
--- a/frida_mode/src/complog/complog.c
+++ b/frida_mode/src/complog/complog.c
@@ -36,8 +36,9 @@ void complog_init(void) {
   for (guint i = 0; i < complog_ranges->len; i++) {
 
     GumMemoryRange *range = &g_array_index(complog_ranges, GumMemoryRange, i);
-    OKF("CompLog Range - 0x%016lX - 0x%016lX", range->base_address,
-        range->base_address + range->size);
+    OKF("CompLog Range - 0x%016" G_GINT64_MODIFIER
+        "X - 0x%016" G_GINT64_MODIFIER "X",
+        range->base_address, range->base_address + range->size);
 
   }
 
diff --git a/frida_mode/src/complog/complog_arm.c b/frida_mode/src/complog/complog_arm.c
index 82cc2557..1b8eb8f1 100644
--- a/frida_mode/src/complog/complog_arm.c
+++ b/frida_mode/src/complog/complog_arm.c
@@ -3,10 +3,14 @@
 #include "debug.h"
 
 #include "complog.h"
+#include "util.h"
 
-#if defined(__arm64__)
+#if defined(__arm__)
 void complog_instrument(const cs_insn *instr, GumStalkerIterator *iterator) {
 
+  UNUSED_PARAMETER(instr);
+  UNUSED_PARAMETER(iterator);
+  if (__afl_cmp_map == NULL) { return; }
   FATAL("Complog mode not supported on this architecture");
 
 }
diff --git a/frida_mode/src/complog/complog_arm64.c b/frida_mode/src/complog/complog_arm64.c
index e4dbf322..ce62f6fd 100644
--- a/frida_mode/src/complog/complog_arm64.c
+++ b/frida_mode/src/complog/complog_arm64.c
@@ -3,10 +3,14 @@
 #include "debug.h"
 
 #include "complog.h"
+#include "util.h"
 
-#if defined(__i386__)
+#if defined(__aarch64__)
 void complog_instrument(const cs_insn *instr, GumStalkerIterator *iterator) {
 
+  UNUSED_PARAMETER(instr);
+  UNUSED_PARAMETER(iterator);
+  if (__afl_cmp_map == NULL) { return; }
   FATAL("Complog mode not supported on this architecture");
 
 }
diff --git a/frida_mode/src/complog/complog_x86.c b/frida_mode/src/complog/complog_x86.c
index df7b7cc1..b2e5ddcf 100644
--- a/frida_mode/src/complog/complog_x86.c
+++ b/frida_mode/src/complog/complog_x86.c
@@ -3,10 +3,14 @@
 #include "debug.h"
 
 #include "complog.h"
+#include "util.h"
 
-#if defined(__arm__)
+#if defined(__i386__)
 void complog_instrument(const cs_insn *instr, GumStalkerIterator *iterator) {
 
+  UNUSED_PARAMETER(instr);
+  UNUSED_PARAMETER(iterator);
+  if (__afl_cmp_map == NULL) { return; }
   FATAL("Complog mode not supported on this architecture");
 
 }
diff --git a/frida_mode/src/lib/lib b/frida_mode/src/lib/lib
new file mode 100755
index 00000000..8f09a3b1
--- /dev/null
+++ b/frida_mode/src/lib/lib
Binary files differdiff --git a/frida_mode/src/lib.c b/frida_mode/src/lib/lib.c
index e50163ac..c5045533 100644
--- a/frida_mode/src/lib.c
+++ b/frida_mode/src/lib/lib.c
@@ -1,29 +1,32 @@
-#include <elf.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <stdio.h>
-#include <sys/mman.h>
-#include <unistd.h>
+#ifndef __APPLE__
+  #include <elf.h>
+  #include <fcntl.h>
+  #include <limits.h>
+  #include <stdio.h>
+  #include <sys/mman.h>
+  #include <unistd.h>
 
-#include "frida-gum.h"
+  #include "frida-gum.h"
 
-#include "debug.h"
+  #include "debug.h"
 
-#include "lib.h"
+  #include "lib.h"
 
-#if defined(__arm__) || defined(__i386__)
-  #define ELFCLASS ELFCLASS32
+  #if defined(__arm__) || defined(__i386__)
+    #define ELFCLASS ELFCLASS32
 typedef Elf32_Ehdr Elf_Ehdr;
 typedef Elf32_Phdr Elf_Phdr;
 typedef Elf32_Shdr Elf_Shdr;
-#elif defined(__aarch64__) || defined(__x86_64__)
-  #define ELFCLASS ELFCLASS64
+typedef Elf32_Addr Elf_Addr;
+  #elif defined(__aarch64__) || defined(__x86_64__)
+    #define ELFCLASS ELFCLASS64
 typedef Elf64_Ehdr Elf_Ehdr;
 typedef Elf64_Phdr Elf_Phdr;
 typedef Elf64_Shdr Elf_Shdr;
-#else
-  #error "Unsupported platform"
-#endif
+typedef Elf64_Addr Elf_Addr;
+  #else
+    #error "Unsupported platform"
+  #endif
 
 typedef struct {
 
@@ -50,13 +53,6 @@ static gboolean lib_find_exe(const GumModuleDetails *details,
 
 }
 
-static gboolean lib_is_little_endian(void) {
-
-  int probe = 1;
-  return *(char *)&probe;
-
-}
-
 static void lib_validate_hdr(Elf_Ehdr *hdr) {
 
   if (hdr->e_ident[0] != ELFMAG0) FATAL("Invalid e_ident[0]");
@@ -64,22 +60,14 @@ static void lib_validate_hdr(Elf_Ehdr *hdr) {
   if (hdr->e_ident[2] != ELFMAG2) FATAL("Invalid e_ident[2]");
   if (hdr->e_ident[3] != ELFMAG3) FATAL("Invalid e_ident[3]");
   if (hdr->e_ident[4] != ELFCLASS) FATAL("Invalid class");
-/*
-  if (hdr->e_ident[5] != (lib_is_little_endian() ? ELFDATA2LSB : ELFDATA2MSB))
-    FATAL("Invalid endian");
-  if (hdr->e_ident[6] != EV_CURRENT) FATAL("Invalid version");
-  if (hdr->e_type != ET_DYN) FATAL("Invalid type");
-  if (hdr->e_version != EV_CURRENT) FATAL("Invalid e_version");
-  if (hdr->e_phoff != sizeof(Elf_Ehdr)) FATAL("Invalid e_phoff");
-  if (hdr->e_ehsize != sizeof(Elf_Ehdr)) FATAL("Invalid e_ehsize");
-  if (hdr->e_phentsize != sizeof(Elf_Phdr)) FATAL("Invalid e_phentsize");
-  if (hdr->e_shentsize != sizeof(Elf_Shdr)) FATAL("Invalid e_shentsize");
-*/
 
 }
 
 static void lib_read_text_section(lib_details_t *lib_details, Elf_Ehdr *hdr) {
 
+  Elf_Phdr *phdr;
+  gboolean  found_preferred_base = FALSE;
+  Elf_Addr  preferred_base;
   Elf_Shdr *shdr;
   Elf_Shdr *shstrtab;
   char *    shstr;
@@ -87,6 +75,23 @@ static void lib_read_text_section(lib_details_t *lib_details, Elf_Ehdr *hdr) {
   Elf_Shdr *curr;
   char      text_name[] = ".text";
 
+  phdr = (Elf_Phdr *)((char *)hdr + hdr->e_phoff);
+  for (size_t i = 0; i < hdr->e_phnum; i++) {
+
+    if (phdr[i].p_type == PT_LOAD) {
+
+      preferred_base = phdr[i].p_vaddr;
+      found_preferred_base = TRUE;
+      break;
+
+    }
+
+  }
+
+  if (!found_preferred_base) { FATAL("Failed to find preferred load address"); }
+
+  OKF("Image preferred load address 0x%016lx", preferred_base);
+
   shdr = (Elf_Shdr *)((char *)hdr + hdr->e_shoff);
   shstrtab = &shdr[hdr->e_shstrndx];
   shstr = (char *)hdr + shstrtab->sh_offset;
@@ -107,8 +112,8 @@ static void lib_read_text_section(lib_details_t *lib_details, Elf_Ehdr *hdr) {
     if (memcmp(section_name, text_name, sizeof(text_name)) == 0 &&
         text_base == 0) {
 
-      text_base = lib_details->base_address + curr->sh_addr;
-      text_limit = lib_details->base_address + curr->sh_addr + curr->sh_size;
+      text_base = lib_details->base_address + curr->sh_addr - preferred_base;
+      text_limit = text_base + curr->sh_size;
       OKF("> text_addr: 0x%016lX", text_base);
       OKF("> text_limit: 0x%016lX", text_limit);
 
@@ -167,3 +172,5 @@ guint64 lib_get_text_limit(void) {
 
 }
 
+#endif
+
diff --git a/frida_mode/src/lib/lib_apple.c b/frida_mode/src/lib/lib_apple.c
new file mode 100644
index 00000000..8f863861
--- /dev/null
+++ b/frida_mode/src/lib/lib_apple.c
@@ -0,0 +1,82 @@
+#ifdef __APPLE__
+  #include "frida-gum.h"
+
+  #include "debug.h"
+
+  #include "lib.h"
+  #include "util.h"
+
+extern mach_port_t mach_task_self();
+extern void        gum_darwin_enumerate_modules(mach_port_t        task,
+                                                GumFoundModuleFunc func,
+                                                gpointer           user_data);
+
+static guint64 text_base = 0;
+static guint64 text_limit = 0;
+
+static gboolean lib_get_main_module(const GumModuleDetails *details,
+                                    gpointer                user_data) {
+
+  GumDarwinModule **ret = (GumDarwinModule **)user_data;
+  GumDarwinModule * module = gum_darwin_module_new_from_memory(
+      details->path, mach_task_self(), details->range->base_address,
+      GUM_DARWIN_MODULE_FLAGS_NONE, NULL);
+
+  OKF("Found main module: %s", module->name);
+
+  *ret = module;
+
+  return FALSE;
+
+}
+
+gboolean lib_get_text_section(const GumDarwinSectionDetails *details,
+                              gpointer                       user_data) {
+
+  UNUSED_PARAMETER(user_data);
+  static size_t idx = 0;
+  char          text_name[] = "__text";
+
+  OKF("Section: %2lu - base: 0x%016" G_GINT64_MODIFIER
+      "X size: 0x%016" G_GINT64_MODIFIER "X %s",
+      idx++, details->vm_address, details->vm_address + details->size,
+      details->section_name);
+
+  if (memcmp(details->section_name, text_name, sizeof(text_name)) == 0 &&
+      text_base == 0) {
+
+    text_base = details->vm_address;
+    text_limit = details->vm_address + details->size;
+    OKF("> text_addr: 0x%016" G_GINT64_MODIFIER "X", text_base);
+    OKF("> text_limit: 0x%016" G_GINT64_MODIFIER "X", text_limit);
+
+  }
+
+  return TRUE;
+
+}
+
+void lib_init(void) {
+
+  GumDarwinModule *module = NULL;
+  gum_darwin_enumerate_modules(mach_task_self(), lib_get_main_module, &module);
+  gum_darwin_module_enumerate_sections(module, lib_get_text_section, NULL);
+
+}
+
+guint64 lib_get_text_base(void) {
+
+  if (text_base == 0) FATAL("Lib not initialized");
+  return text_base;
+
+}
+
+guint64 lib_get_text_limit(void) {
+
+  if (text_limit == 0) FATAL("Lib not initialized");
+  return text_limit;
+
+}
+
+#endif
+
diff --git a/frida_mode/src/main.c b/frida_mode/src/main.c
index 11cf041c..5c64d192 100644
--- a/frida_mode/src/main.c
+++ b/frida_mode/src/main.c
@@ -49,6 +49,10 @@ static int on_fork(void) {
 #ifdef __APPLE__
 static void on_main_os(int argc, char **argv, char **envp) {
 
+  UNUSED_PARAMETER(argc);
+  UNUSED_PARAMETER(argv);
+  UNUSED_PARAMETER(envp);
+
 }
 
 #else
diff --git a/frida_mode/src/persistent/persistent.c b/frida_mode/src/persistent/persistent.c
index 5aad3724..918ff153 100644
--- a/frida_mode/src/persistent/persistent.c
+++ b/frida_mode/src/persistent/persistent.c
@@ -33,9 +33,9 @@ void persistent_init(void) {
   if (persistent_start != 0 && !persistent_is_supported())
     FATAL("Persistent mode not supported on this architecture");
 
-  OKF("Instrumentation - persistent mode [%c] (0x%016lX)",
+  OKF("Instrumentation - persistent mode [%c] (0x%016" G_GINT64_MODIFIER "X)",
       persistent_start == 0 ? ' ' : 'X', persistent_start);
-  OKF("Instrumentation - persistent count [%c] (%ld)",
+  OKF("Instrumentation - persistent count [%c] (%" G_GINT64_MODIFIER "d)",
       persistent_start == 0 ? ' ' : 'X', persistent_count);
   OKF("Instrumentation - hook [%s]", hook_name);
 
diff --git a/frida_mode/src/persistent/persistent_arm32.c b/frida_mode/src/persistent/persistent_arm32.c
index 10dab3b2..bc021ff3 100644
--- a/frida_mode/src/persistent/persistent_arm32.c
+++ b/frida_mode/src/persistent/persistent_arm32.c
@@ -3,6 +3,7 @@
 #include "debug.h"
 
 #include "persistent.h"
+#include "util.h"
 
 #if defined(__arm__)
 
@@ -62,6 +63,7 @@ gboolean persistent_is_supported(void) {
 
 void persistent_prologue(GumStalkerOutput *output) {
 
+  UNUSED_PARAMETER(output);
   FATAL("Persistent mode not supported on this architecture");
 
 }
diff --git a/frida_mode/src/persistent/persistent_arm64.c b/frida_mode/src/persistent/persistent_arm64.c
index 5a18ac2c..c198da69 100644
--- a/frida_mode/src/persistent/persistent_arm64.c
+++ b/frida_mode/src/persistent/persistent_arm64.c
@@ -4,6 +4,7 @@
 #include "debug.h"
 
 #include "instrument.h"
+#include "util.h"
 
 #if defined(__aarch64__)
 
@@ -105,6 +106,7 @@ gboolean persistent_is_supported(void) {
 
 void persistent_prologue(GumStalkerOutput *output) {
 
+  UNUSED_PARAMETER(output);
   FATAL("Persistent mode not supported on this architecture");
 
 }
diff --git a/frida_mode/src/persistent/persistent_x86.c b/frida_mode/src/persistent/persistent_x86.c
index 4daa61a9..9d39c4e9 100644
--- a/frida_mode/src/persistent/persistent_x86.c
+++ b/frida_mode/src/persistent/persistent_x86.c
@@ -3,6 +3,7 @@
 #include "debug.h"
 
 #include "persistent.h"
+#include "util.h"
 
 #if defined(__i386__)
 
@@ -45,6 +46,7 @@ gboolean persistent_is_supported(void) {
 
 void persistent_prologue(GumStalkerOutput *output) {
 
+  UNUSED_PARAMETER(output);
   FATAL("Persistent mode not supported on this architecture");
 
 }
diff --git a/frida_mode/test/exe/GNUmakefile b/frida_mode/test/exe/GNUmakefile
new file mode 100644
index 00000000..7719ad2b
--- /dev/null
+++ b/frida_mode/test/exe/GNUmakefile
@@ -0,0 +1,50 @@
+PWD:=$(shell pwd)/
+ROOT:=$(shell realpath $(PWD)../../..)/
+BUILD_DIR:=$(PWD)build/
+TESTINSTR_DATA_DIR:=$(BUILD_DIR)in/
+TESTINSTR_DATA_FILE:=$(TESTINSTR_DATA_DIR)in
+
+TESTINSTBIN:=$(BUILD_DIR)testinstr
+TESTINSTSRC:=$(PWD)testinstr.c
+
+QEMU_OUT:=$(BUILD_DIR)qemu-out
+FRIDA_OUT:=$(BUILD_DIR)frida-out
+
+.PHONY: all clean qemu frida
+
+all: $(TESTINSTBIN)
+	make -C $(ROOT)frida_mode/
+
+$(BUILD_DIR):
+	mkdir -p $@
+
+$(TESTINSTR_DATA_DIR): | $(BUILD_DIR)
+	mkdir -p $@
+
+$(TESTINSTR_DATA_FILE): | $(TESTINSTR_DATA_DIR)
+	echo -n "000" > $@
+
+$(TESTINSTBIN): $(TESTINSTSRC) | $(BUILD_DIR)
+	$(CC) -o $@ $< -no-pie
+
+clean:
+	rm -rf $(BUILD_DIR)
+
+
+qemu: $(TESTINSTBIN) $(TESTINSTR_DATA_FILE)
+	$(ROOT)afl-fuzz \
+		-D \
+		-Q \
+		-i $(TESTINSTR_DATA_DIR) \
+		-o $(QEMU_OUT) \
+		-- \
+			$(TESTINSTBIN) @@
+
+frida: $(FRIDA_TRACE) $(TESTINSTBIN) $(TESTINSTR_DATA_FILE)
+	$(ROOT)afl-fuzz \
+		-D \
+		-O \
+		-i $(TESTINSTR_DATA_DIR) \
+		-o $(FRIDA_OUT) \
+		-- \
+			$(TESTINSTBIN) @@
\ No newline at end of file
diff --git a/frida_mode/test/exe/Makefile b/frida_mode/test/exe/Makefile
new file mode 100644
index 00000000..f322d1f5
--- /dev/null
+++ b/frida_mode/test/exe/Makefile
@@ -0,0 +1,12 @@
+all:
+	@echo trying to use GNU make...
+	@gmake all || echo please install GNUmake
+
+clean:
+	@gmake clean
+
+qemu:
+	@gmake qemu
+
+frida:
+	@gmake frida
\ No newline at end of file
diff --git a/frida_mode/test/exe/testinstr.c b/frida_mode/test/exe/testinstr.c
new file mode 100644
index 00000000..5e26fc46
--- /dev/null
+++ b/frida_mode/test/exe/testinstr.c
@@ -0,0 +1,112 @@
+/*
+   american fuzzy lop++ - a trivial program to test the build
+   --------------------------------------------------------
+   Originally written by Michal Zalewski
+   Copyright 2014 Google Inc. All rights reserved.
+   Copyright 2019-2020 AFLplusplus Project. All rights reserved.
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at:
+     http://www.apache.org/licenses/LICENSE-2.0
+ */
+
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#ifdef __APPLE__
+  #define TESTINSTR_SECTION
+#else
+  #define TESTINSTR_SECTION __attribute__((section(".testinstr")))
+#endif
+
+void testinstr(char *buf, int len) {
+
+  if (len < 1) return;
+  buf[len] = 0;
+
+  // we support three input cases
+  if (buf[0] == '0')
+    printf("Looks like a zero to me!\n");
+  else if (buf[0] == '1')
+    printf("Pretty sure that is a one!\n");
+  else
+    printf("Neither one or zero? How quaint!\n");
+
+}
+
+TESTINSTR_SECTION int main(int argc, char **argv) {
+
+  char * file;
+  int    fd = -1;
+  off_t  len;
+  char * buf = NULL;
+  size_t n_read;
+  int    result = -1;
+
+  if (argc != 2) { return 1; }
+
+  do {
+
+    file = argv[1];
+
+    dprintf(STDERR_FILENO, "Running: %s\n", file);
+
+    fd = open(file, O_RDONLY);
+    if (fd < 0) {
+
+      perror("open");
+      break;
+
+    }
+
+    len = lseek(fd, 0, SEEK_END);
+    if (len < 0) {
+
+      perror("lseek (SEEK_END)");
+      break;
+
+    }
+
+    if (lseek(fd, 0, SEEK_SET) != 0) {
+
+      perror("lseek (SEEK_SET)");
+      break;
+
+    }
+
+    buf = malloc(len);
+    if (buf == NULL) {
+
+      perror("malloc");
+      break;
+
+    }
+
+    n_read = read(fd, buf, len);
+    if (n_read != len) {
+
+      perror("read");
+      break;
+
+    }
+
+    dprintf(STDERR_FILENO, "Running:    %s: (%zd bytes)\n", file, n_read);
+
+    testinstr(buf, len);
+    dprintf(STDERR_FILENO, "Done:    %s: (%zd bytes)\n", file, n_read);
+
+    result = 0;
+
+  } while (false);
+
+  if (buf != NULL) { free(buf); }
+
+  if (fd != -1) { close(fd); }
+
+  return result;
+
+}
+
diff --git a/frida_mode/test/png/GNUmakefile b/frida_mode/test/png/GNUmakefile
index 7de3e85a..515728c4 100644
--- a/frida_mode/test/png/GNUmakefile
+++ b/frida_mode/test/png/GNUmakefile
@@ -21,6 +21,9 @@ PNGTEST_OBJ:=$(PNGTEST_BUILD_DIR)target.o
 PNGTEST_URL:="https://raw.githubusercontent.com/google/fuzzbench/master/benchmarks/libpng-1.2.56/target.cc"
 
 TEST_BIN:=$(BUILD_DIR)test
+ifeq "$(shell uname)" "Darwin"
+TEST_BIN_LDFLAGS:=-undefined dynamic_lookup
+endif
 
 TEST_DATA_DIR:=$(LIBPNG_DIR)contrib/pngsuite/
 
@@ -80,6 +83,7 @@ $(TEST_BIN): $(HARNESS_OBJ) $(PNGTEST_OBJ) $(LIBPNG_LIB)
 		-o $@ \
 		$(HARNESS_OBJ) $(PNGTEST_OBJ) $(LIBPNG_LIB) \
 		-lz \
+		$(TEST_BIN_LDFLAGS) \
 
 clean:
 	rm -rf $(BUILD_DIR)