Added JS support (#992)

* Added JS support

* Added some documentation

Co-authored-by: Your Name <you@example.com>
This commit is contained in:
WorksButNotTested
2021-06-24 18:46:08 +01:00
committed by GitHub
parent 4057134d3c
commit f348a35ec6
69 changed files with 1432 additions and 277 deletions

View File

@ -6,6 +6,11 @@ INCLUDES:=$(wildcard $(INC_DIR)*.h)
BUILD_DIR:=$(PWD)build/
OBJ_DIR:=$(BUILD_DIR)obj/
JS_DIR:=$(SRC_DIR)js/
JS_NAME:=api.js
JS:=$(JS_DIR)$(JS_NAME)
JS_SRC:=$(BUILD_DIR)api.c
JS_OBJ:=$(BUILD_DIR)api.o
SOURCES:=$(wildcard $(SRC_DIR)**/*.c) $(wildcard $(SRC_DIR)*.c)
OBJS:=$(foreach src,$(SOURCES),$(OBJ_DIR)$(notdir $(patsubst %.c, %.o, $(src))))
CFLAGS+=-fPIC \
@ -71,25 +76,25 @@ ifndef OS
endif
GUM_DEVKIT_VERSION=14.2.18
GUM_DEVKIT_FILENAME=frida-gum-devkit-$(GUM_DEVKIT_VERSION)-$(OS)-$(ARCH).tar.xz
GUM_DEVKIT_FILENAME=frida-gumjs-devkit-$(GUM_DEVKIT_VERSION)-$(OS)-$(ARCH).tar.xz
GUM_DEVKIT_URL="https://github.com/frida/frida/releases/download/$(GUM_DEVKIT_VERSION)/$(GUM_DEVKIT_FILENAME)"
GUM_DEVKIT_TARBALL:=$(FRIDA_BUILD_DIR)$(GUM_DEVKIT_FILENAME)
GUM_DEVIT_LIBRARY=$(FRIDA_BUILD_DIR)libfrida-gum.a
GUM_DEVIT_HEADER=$(FRIDA_BUILD_DIR)frida-gum.h
GUM_DEVIT_LIBRARY=$(FRIDA_BUILD_DIR)libfrida-gumjs.a
GUM_DEVIT_HEADER=$(FRIDA_BUILD_DIR)frida-gumjs.h
FRIDA_DIR:=$(PWD)build/frida-source/
FRIDA_MAKEFILE:=$(FRIDA_DIR)Makefile
FRIDA_GUM:=$(FRIDA_DIR)build/frida-linux-x86_64/lib/libfrida-gum-1.0.a
FRIDA_GUM:=$(FRIDA_DIR)build/frida-linux-x86_64/lib/libfrida-gumjs-1.0.a
FRIDA_GUM_DEVKIT_DIR:=$(FRIDA_DIR)build/gum-devkit/
FRIDA_GUM_DEVKIT_HEADER:=$(FRIDA_GUM_DEVKIT_DIR)frida-gum.h
FRIDA_GUM_DEVKIT_TARBALL:=$(FRIDA_DIR)build/frida-gum-devkit-$(GUM_DEVKIT_VERSION)-$(OS)-$(ARCH).tar
FRIDA_GUM_DEVKIT_HEADER:=$(FRIDA_GUM_DEVKIT_DIR)frida-gumjs.h
FRIDA_GUM_DEVKIT_TARBALL:=$(FRIDA_DIR)build/frida-gumjs-devkit-$(GUM_DEVKIT_VERSION)-$(OS)-$(ARCH).tar
FRIDA_GUM_DEVKIT_COMPRESSED_TARBALL:=$(FRIDA_DIR)build/$(GUM_DEVKIT_FILENAME)
AFL_COMPILER_RT_SRC:=$(ROOT)instrumentation/afl-compiler-rt.o.c
AFL_COMPILER_RT_OBJ:=$(OBJ_DIR)afl-compiler-rt.o
.PHONY: all 32 clean format $(FRIDA_GUM)
.PHONY: all 32 clean format $(FRIDA_GUM) quickjs
############################## ALL #############################################
@ -113,7 +118,7 @@ $(FRIDA_GUM): $(FRIDA_MAKEFILE)
cd $(FRIDA_DIR) && make gum-linux-$(ARCH)
$(FRIDA_GUM_DEVKIT_HEADER): $(FRIDA_GUM)
$(FRIDA_DIR)releng/devkit.py frida-gum linux-$(ARCH) $(FRIDA_DIR)build/gum-devkit/
$(FRIDA_DIR)releng/devkit.py frida-gumjs linux-$(ARCH) $(FRIDA_DIR)build/gum-devkit/
$(FRIDA_GUM_DEVKIT_TARBALL): $(FRIDA_GUM_DEVKIT_HEADER)
cd $(FRIDA_GUM_DEVKIT_DIR) && tar cvf $(FRIDA_GUM_DEVKIT_TARBALL) .
@ -150,6 +155,20 @@ $(AFL_COMPILER_RT_OBJ): $(AFL_COMPILER_RT_SRC)
-o $@ \
-c $<
############################### JS #############################################
$(JS_SRC): $(JS) | $(BUILD_DIR)
cd $(JS_DIR) && xxd -i $(JS_NAME) $@
$(JS_OBJ): $(JS_SRC)
$(CC) \
$(CFLAGS) \
-I $(ROOT)include \
-I $(FRIDA_BUILD_DIR) \
-I $(INC_DIR) \
-c $< \
-o $@
############################# SOURCE ###########################################
define BUILD_SOURCE
@ -167,9 +186,10 @@ $(foreach src,$(SOURCES),$(eval $(call BUILD_SOURCE,$(src),$(OBJ_DIR)$(notdir $(
######################## AFL-FRIDA-TRACE #######################################
$(FRIDA_TRACE): $(GUM_DEVIT_LIBRARY) $(GUM_DEVIT_HEADER) $(OBJS) $(AFL_COMPILER_RT_OBJ) GNUmakefile | $(BUILD_DIR)
$(CC) \
$(FRIDA_TRACE): $(GUM_DEVIT_LIBRARY) $(GUM_DEVIT_HEADER) $(OBJS) $(JS_OBJ) $(AFL_COMPILER_RT_OBJ) GNUmakefile | $(BUILD_DIR)
$(CXX) \
$(OBJS) \
$(JS_OBJ) \
$(GUM_DEVIT_LIBRARY) \
$(AFL_COMPILER_RT_OBJ) \
$(LDFLAGS) \

View File

@ -78,6 +78,10 @@ following options are currently supported:
To enable the powerful CMPLOG mechanism, set `-c 0` for `afl-fuzz`.
## Scripting
One of the more powerful features of FRIDA mode is it's support for configuration by JavaScript, rather than using environment variables. For details of how this works see [here](Scripting.md).
## Performance
Additionally, the intention is to be able to make a direct performance

240
frida_mode/Scripting.md Normal file
View File

@ -0,0 +1,240 @@
# Scripting
FRIDA now supports the ability to configure itself using JavaScript. This allows
the user to make use of the convenience of FRIDA's scripting engine (along with
it's support for debug symbols and exports) to configure all of the things which
were traditionally configured using environment variables.
By default FRIDA mode will look for the file `afl.js` in the current working
directory of the target. Alternatively, a script file can be configured using
the environment variable `AFL_FRIDA_JS_SCRIPT`.
This script can make use of all of the standard [frida api functions](https://frida.re/docs/javascript-api/), but FRIDA mode adds some additional functions to allow
you to interact with FRIDA mode itself. These can all be accessed via the global
`Afl` parameter. e.g. `Afl.print("HELLO WORLD");`,
If you encounter a problem with your script, then you should set the environment
variable `AFL_DEBUG_CHILD=1` to view any diagnostic information.
# Example
Most of the time, users will likely be wanting to call the functions which configure an address (e.g. for the entry point, or the persistent address).
The example below uses the API [`DebugSymbol.fromName()`](https://frida.re/docs/javascript-api/#debugsymbol). Another use API is [`Module.getExportByName()`](https://frida.re/docs/javascript-api/#module).
```js
/* Use Afl.print instead of console.log */
Afl.print('******************');
Afl.print('* AFL FRIDA MODE *');
Afl.print('******************');
Afl.print('');
/* Print some useful diagnostics stuff */
Afl.print(`PID: ${Process.id}`);
new ModuleMap().values().forEach(m => {
Afl.print(`${m.base}-${m.base.add(m.size)} ${m.name}`);
});
/*
* Configure entry-point, persistence etc. This will be what most
* people want to do.
*/
const persistent_addr = DebugSymbol.fromName('main');
Afl.print(`persistent_addr: ${persistent_addr.address}`);
if (persistent_addr.address.equals(ptr(0))) {
Afl.error('Cannot find symbol main');
}
const persistent_ret = DebugSymbol.fromName('slow');
Afl.print(`persistent_ret: ${persistent_ret.address}`);
if (persistent_ret.address.equals(ptr(0))) {
Afl.error('Cannot find symbol slow');
}
Afl.setPersistentAddress(persistent_addr.address);
Afl.setPersistentReturn(persistent_ret.address);
Afl.setPersistentCount(1000000);
/* Control instrumentation, you may want to do this too */
Afl.setInstrumentLibraries();
const mod = Process.findModuleByName("libc-2.31.so")
Afl.addExcludedRange(mod.base, mod.size);
/* Some useful options to configure logging */
Afl.setStdOut("/tmp/stdout.txt");
Afl.setStdErr("/tmp/stderr.txt");
/* Show the address layout. Sometimes helpful */
Afl.setDebugMaps();
/*
* If you are using these options, then things aren't going
* very well for you.
*/
Afl.setInstrumentDebugFile("/tmp/instr.log");
Afl.setPrefetchDisable();
Afl.setInstrumentNoOptimize();
Afl.setInstrumentEnableTracing();
Afl.setInstrumentTracingUnique();
Afl.setStatsFile("/tmp/stats.txt");
Afl.setStatsInterval(1);
Afl.setStatsTransitions();
/* *ALWAYS* call this when you have finished all your configuration */
Afl.done();
Afl.print("done");
```
# Stripped Binaries
Lastly, if the binary you attempting to fuzz has no symbol information, and no
exports, then the following approach can be used.
```js
const module = Process.getModuleByName('target.exe');
/* Hardcoded offset within the target image */
const address = module.base.add(0xdeadface);
Afl.setPersistentAddress(address);
```
# API
```js
/*
* Print a message to the STDOUT. This should be preferred to
* FRIDA's `console.log` since FRIDA will queue it's log messages.
* If `console.log` is used in a callback in particular, then there
* may no longer be a thread running to service this queue.
*/
Afl.print(msg);
/*
* This must always be called at the end of your script. This lets
* FRIDA mode know that your configuration is finished and that
* execution has reached the end of your script. Failure to call
* this will result in a fatal error.
*/
Afl.done();
/*
* This function can be called within your script to cause FRIDA
* mode to trigger a fatal error. This is useful if for example you
* discover a problem you weren't expecting and want everything to
* stop. The user will need to enable `AFL_DEBUG_CHILD=1` to view
* this error message.
*/
Afl.error();
/*
* This has the same effect as setting `AFL_ENTRYPOINT`, but has the
* convenience of allowing you to use FRIDAs APIs to determine the
* address you would like to configure, rather than having to grep
* the output of `readelf` or something similarly ugly. This
* function should be called with a `NativePointer` as its
* argument.
*/
Afl.setEntryPoint(address);
/*
* This is equivalent to setting `AFL_FRIDA_PERSISTENT_ADDR`, again a
* `NativePointer` should be provided as it's argument.
*/
Afl.setPersistentAddress(address);
/*
* This is equivalent to setting `AFL_FRIDA_PERSISTENT_RET`, again a
* `NativePointer` should be provided as it's argument.
*/
Afl.setPersistentReturn(address);
/*
* This is equivalent to setting `AFL_FRIDA_PERSISTENT_CNT`, a
* `number` should be provided as it's argument.
*/
Afl.setPersistentCount(count);
/*
* See `AFL_FRIDA_PERSISTENT_DEBUG`.
*/
Afl.setPersistentDebug();
/*
* See `AFL_FRIDA_DEBUG_MAPS`.
*/
Afl.setDebugMaps();
/*
* This is equivalent to setting a value in `AFL_FRIDA_INST_RANGES`,
* it takes as arguments a `NativePointer` and a `number`. It can be
* called multiple times to include several ranges.
*/
Afl.addIncludedRange(address, size);
/*
* This is equivalent to setting a value in `AFL_FRIDA_EXCLUDE_RANGES`,
* it takes as arguments a `NativePointer` and a `number`. It can be
* called multiple times to exclude several ranges.
*/
Afl.addExcludedRange(address, size);
/*
* See `AFL_INST_LIBS`.
*/
Afl.setInstrumentLibraries();
/*
* See `AFL_FRIDA_INST_DEBUG_FILE`. This function takes a single `string` as
* an argument.
*/
Afl.setInstrumentDebugFile(file);
/*
* See `AFL_FRIDA_INST_NO_PREFETCH`.
*/
Afl.setPrefetchDisable();
/*
* See `AFL_FRIDA_INST_NO_OPTIMIZE`
*/
Afl.setInstrumentNoOptimize();
/*
* See `AFL_FRIDA_INST_TRACE`.
*/
Afl.setInstrumentEnableTracing();
/*
* See `AFL_FRIDA_INST_TRACE_UNIQUE`.
*/
Afl.setInstrumentTracingUnique()
/*
* See `AFL_FRIDA_OUTPUT_STDOUT`. This function takes a single `string` as
* an argument.
*/
Afl.setStdOut(file);
/*
* See `AFL_FRIDA_OUTPUT_STDERR`. This function takes a single `string` as
* an argument.
*/
Afl.setStdErr(file);
/*
* See `AFL_FRIDA_STATS_FILE`. This function takes a single `string` as
* an argument.
*/
Afl.setStatsFile(file);
/*
* See `AFL_FRIDA_STATS_INTERVAL`. This function takes a `number` as an
* argument
*/
Afl.setStatsInterval(interval);
/*
* See `AFL_FRIDA_STATS_TRANSITIONS`
*/
Afl.setStatsTransitions()
```

View File

@ -1,10 +1,11 @@
#ifndef _ASAN_H
#define _ASAN_H
#include "frida-gum.h"
#include "frida-gumjs.h"
extern gboolean asan_initialized;
void asan_config(void);
void asan_init(void);
void asan_arch_init(void);
void asan_instrument(const cs_insn *instr, GumStalkerIterator *iterator);

View File

@ -1,7 +1,7 @@
#ifndef _CTX_H
#define _CTX_H
#include "frida-gum.h"
#include "frida-gumjs.h"
#if defined(__x86_64__)
gsize ctx_read_reg(GumX64CpuContext *ctx, x86_reg reg);

View File

@ -1,13 +1,15 @@
#ifndef _ENTRY_H
#define _ENTRY_H
#include "frida-gum.h"
#include "frida-gumjs.h"
extern guint64 entry_start;
extern guint64 entry_point;
void entry_config(void);
void entry_init(void);
void entry_run(void);
void entry_start(void);
void entry_prologue(GumStalkerIterator *iterator, GumStalkerOutput *output);

View File

@ -3,6 +3,7 @@
extern struct cmp_map *__afl_cmp_map;
void cmplog_config(void);
void cmplog_init(void);
/* Functions to be implemented by the different architectures */

View File

@ -1,14 +1,21 @@
#ifndef _INSTRUMENT_H
#define _INSTRUMENT_H
#include "frida-gum.h"
#include "frida-gumjs.h"
#include "config.h"
extern __thread uint64_t previous_pc;
extern char * instrument_debug_filename;
extern gboolean instrument_tracing;
extern gboolean instrument_optimize;
extern gboolean instrument_unique;
extern __thread uint64_t instrument_previous_pc;
extern uint8_t *__afl_area_ptr;
extern uint32_t __afl_map_size;
void instrument_config(void);
void instrument_init(void);
GumStalkerTransformer *instrument_get_transformer(void);
@ -19,6 +26,7 @@ gboolean instrument_is_coverage_optimize_supported(void);
void instrument_coverage_optimize(const cs_insn * instr,
GumStalkerOutput *output);
void instrument_debug_config(void);
void instrument_debug_init(void);
void instrument_debug_start(uint64_t address, GumStalkerOutput *output);
void instrument_debug_instruction(uint64_t address, uint16_t size);

View File

@ -0,0 +1,11 @@
#ifndef _INTERCEPTOR_H
#define _INTERCEPTOR_H
#include "frida-gumjs.h"
void intercept_hook(void *address, gpointer replacement, gpointer user_data);
void intercept_unhook(void *address);
void intercept_unhook_self(void);
#endif

View File

@ -1,11 +0,0 @@
#ifndef _INTERCEPTOR_H
#define _INTERCEPTOR_H
#include "frida-gum.h"
void intercept(void *address, gpointer replacement, gpointer user_data);
void unintercept(void *address);
void unintercept_self(void);
#endif

18
frida_mode/include/js.h Normal file
View File

@ -0,0 +1,18 @@
#ifndef _JS_H
#define _JS_H
#include "frida-gumjs.h"
extern unsigned char api_js[];
extern unsigned int api_js_len;
extern gboolean js_done;
/* Frida Mode */
void js_config(void);
void js_start(void);
#endif

View File

@ -1,7 +1,9 @@
#ifndef _LIB_H
#define _LIB_H
#include "frida-gum.h"
#include "frida-gumjs.h"
void lib_config(void);
void lib_init(void);

View File

@ -1,8 +1,12 @@
#ifndef _OUTPUT_H
#define _OUTPUT_H
#include "frida-gum.h"
#include "frida-gumjs.h"
extern char *output_stdout;
extern char *output_stderr;
void output_config(void);
void output_init(void);
#endif

View File

@ -2,7 +2,7 @@
#ifndef _PERSISTENT_H
#define _PERSISTENT_H
#include "frida-gum.h"
#include "frida-gumjs.h"
#include "config.h"
typedef struct arch_api_regs api_regs;
@ -19,9 +19,10 @@ extern unsigned char *__afl_fuzz_ptr;
extern guint64 persistent_start;
extern guint64 persistent_count;
extern guint64 persistent_ret;
extern guint64 persistent_ret_offset;
extern gboolean persistent_debug;
extern afl_persistent_hook_fn hook;
extern afl_persistent_hook_fn persistent_hook;
void persistent_config(void);
void persistent_init(void);

View File

@ -1,8 +1,11 @@
#ifndef _PREFETCH_H
#define _PREFETCH_H
#include "frida-gum.h"
#include "frida-gumjs.h"
extern gboolean prefetch_enable;
void prefetch_config(void);
void prefetch_init(void);
void prefetch_write(void *addr);
void prefetch_read(void);

View File

@ -1,13 +1,20 @@
#ifndef _RANGES_H
#define _RANGES_H
#include "frida-gum.h"
#include "frida-gumjs.h"
extern gboolean ranges_debug_maps;
extern gboolean ranges_inst_libs;
void ranges_config(void);
void ranges_init(void);
gboolean range_is_excluded(gpointer address);
void ranges_exclude();
void ranges_add_include(GumMemoryRange *range);
void ranges_add_exclude(GumMemoryRange *range);
#endif

View File

@ -1,8 +1,9 @@
#ifndef _STALKER_H
#define _STALKER_H
#include "frida-gum.h"
#include "frida-gumjs.h"
void stalker_config(void);
void stalker_init(void);
GumStalker *stalker_get(void);
void stalker_start(void);

View File

@ -1,7 +1,7 @@
#ifndef _STATS_H
#define _STATS_H
#include "frida-gum.h"
#include "frida-gumjs.h"
typedef struct {
@ -15,6 +15,11 @@ typedef struct {
extern stats_data_header_t *stats_data;
extern char * stats_filename;
extern guint64 stats_interval;
extern gboolean stats_transitions;
void stats_config(void);
void stats_init(void);
void stats_collect(const cs_insn *instr, gboolean begin);
void stats_print(char *format, ...);

View File

@ -1,7 +1,7 @@
#ifndef _UTIL_H
#define _UTIL_H
#include "frida-gum.h"
#include "frida-gumjs.h"
#define UNUSED_PARAMETER(x) (void)(x)
#define IGNORED_RETURN(x) (void)!(x)

View File

@ -1,18 +1,18 @@
#include "frida-gum.h"
#include "frida-gumjs.h"
#include "debug.h"
#include "asan.h"
static gboolean asan_enabled = FALSE;
gboolean asan_initialized = FALSE;
void asan_init(void) {
void asan_config(void) {
if (getenv("AFL_USE_FASAN") != NULL) {
OKF("Frida ASAN mode enabled");
asan_arch_init();
asan_initialized = TRUE;
asan_enabled = TRUE;
} else {
@ -22,3 +22,14 @@ void asan_init(void) {
}
void asan_init(void) {
if (asan_enabled) {
asan_arch_init();
asan_initialized = TRUE;
}
}

View File

@ -1,4 +1,4 @@
#include "frida-gum.h"
#include "frida-gumjs.h"
#include "debug.h"

View File

@ -1,5 +1,5 @@
#include <dlfcn.h>
#include "frida-gum.h"
#include "frida-gumjs.h"
#include "debug.h"

View File

@ -1,5 +1,5 @@
#include <dlfcn.h>
#include "frida-gum.h"
#include "frida-gumjs.h"
#include "debug.h"

View File

@ -1,5 +1,5 @@
#include <dlfcn.h>
#include "frida-gum.h"
#include "frida-gumjs.h"
#include "debug.h"

View File

@ -5,7 +5,7 @@
#include <sys/syscall.h>
#include <unistd.h>
#include "frida-gum.h"
#include "frida-gumjs.h"
#include "debug.h"
@ -50,6 +50,10 @@ static void cmplog_get_ranges(void) {
}
void cmplog_config(void) {
}
void cmplog_init(void) {
if (__afl_cmp_map != NULL) { OKF("CMPLOG mode enabled"); }
@ -94,10 +98,10 @@ static gboolean cmplog_contains(GumAddress inner_base, GumAddress inner_limit,
gboolean cmplog_test_addr(guint64 addr, size_t size) {
if (g_hash_table_contains(hash_yes, (gpointer)addr)) { return true; }
if (g_hash_table_contains(hash_no, (gpointer)addr)) { return false; }
if (g_hash_table_contains(hash_yes, GSIZE_TO_POINTER(addr))) { return true; }
if (g_hash_table_contains(hash_no, GSIZE_TO_POINTER(addr))) { return false; }
void * page_addr = (void *)(addr & page_mask);
void * page_addr = GSIZE_TO_POINTER(addr & page_mask);
size_t page_offset = addr & page_offset_mask;
/* If it spans a page, then bail */
@ -109,7 +113,7 @@ gboolean cmplog_test_addr(guint64 addr, size_t size) {
*/
if (msync(page_addr, page_offset + size, MS_ASYNC) < 0) {
if (!g_hash_table_add(hash_no, (gpointer)addr)) {
if (!g_hash_table_add(hash_no, GSIZE_TO_POINTER(addr))) {
FATAL("Failed - g_hash_table_add");
@ -119,7 +123,7 @@ gboolean cmplog_test_addr(guint64 addr, size_t size) {
} else {
if (!g_hash_table_add(hash_yes, (gpointer)addr)) {
if (!g_hash_table_add(hash_yes, GSIZE_TO_POINTER(addr))) {
FATAL("Failed - g_hash_table_add");

View File

@ -1,4 +1,4 @@
#include "frida-gum.h"
#include "frida-gumjs.h"
#include "debug.h"

View File

@ -1,4 +1,4 @@
#include "frida-gum.h"
#include "frida-gumjs.h"
#include "debug.h"
#include "cmplog.h"

View File

@ -1,4 +1,4 @@
#include "frida-gum.h"
#include "frida-gumjs.h"
#include "debug.h"
#include "cmplog.h"

View File

@ -1,4 +1,4 @@
#include "frida-gum.h"
#include "frida-gumjs.h"
#include "debug.h"
#include "cmplog.h"

View File

@ -1,4 +1,4 @@
#include "frida-gum.h"
#include "frida-gumjs.h"
#include "debug.h"

View File

@ -1,4 +1,4 @@
#include "frida-gum.h"
#include "frida-gumjs.h"
#include "debug.h"

View File

@ -1,4 +1,4 @@
#include "frida-gum.h"
#include "frida-gumjs.h"
#include "debug.h"

View File

@ -1,4 +1,4 @@
#include "frida-gum.h"
#include "frida-gumjs.h"
#include "debug.h"

View File

@ -1,4 +1,4 @@
#include "frida-gum.h"
#include "frida-gumjs.h"
#include "debug.h"
@ -9,27 +9,32 @@
extern void __afl_manual_init();
guint64 entry_start = 0;
guint64 entry_point = 0;
static void entry_launch(void) {
__afl_manual_init();
/* Child here */
previous_pc = 0;
instrument_previous_pc = 0;
}
void entry_config(void) {
entry_point = util_read_address("AFL_ENTRYPOINT");
}
void entry_init(void) {
entry_start = util_read_address("AFL_ENTRYPOINT");
OKF("entry_point: 0x%016" G_GINT64_MODIFIER "X", entry_start);
OKF("entry_point: 0x%016" G_GINT64_MODIFIER "X", entry_point);
}
void entry_run(void) {
void entry_start(void) {
if (entry_start == 0) { entry_launch(); }
if (entry_point == 0) { entry_launch(); }
}

View File

@ -2,7 +2,7 @@
#include <sys/shm.h>
#include <sys/mman.h>
#include "frida-gum.h"
#include "frida-gumjs.h"
#include "config.h"
#include "debug.h"
@ -18,12 +18,13 @@
#include "stats.h"
#include "util.h"
static gboolean tracing = false;
static gboolean optimize = false;
static gboolean unique = false;
gboolean instrument_tracing = false;
gboolean instrument_optimize = false;
gboolean instrument_unique = false;
static GumStalkerTransformer *transformer = NULL;
__thread uint64_t previous_pc = 0;
__thread uint64_t instrument_previous_pc = 0;
static GumAddress previous_rip = 0;
static u8 * edges_notified = NULL;
@ -61,7 +62,7 @@ __attribute__((hot)) static void on_basic_block(GumCpuContext *context,
current_pc = (current_rip >> 4) ^ (current_rip << 8);
current_pc &= MAP_SIZE - 1;
edge = current_pc ^ previous_pc;
edge = current_pc ^ instrument_previous_pc;
cursor = &__afl_area_ptr[edge];
value = *cursor;
@ -77,11 +78,11 @@ __attribute__((hot)) static void on_basic_block(GumCpuContext *context,
}
*cursor = value;
previous_pc = current_pc >> 1;
instrument_previous_pc = current_pc >> 1;
if (unlikely(tracing)) {
if (unlikely(instrument_tracing)) {
if (!unique || edges_notified[edge] == 0) {
if (!instrument_unique || edges_notified[edge] == 0) {
trace_debug("TRACE: edge: %10" G_GINT64_MODIFIER
"d, current_rip: 0x%016" G_GINT64_MODIFIER
@ -90,7 +91,7 @@ __attribute__((hot)) static void on_basic_block(GumCpuContext *context,
}
if (unique) { edges_notified[edge] = 1; }
if (instrument_unique) { edges_notified[edge] = 1; }
previous_rip = current_rip;
@ -98,8 +99,9 @@ __attribute__((hot)) static void on_basic_block(GumCpuContext *context,
}
static void instr_basic_block(GumStalkerIterator *iterator,
GumStalkerOutput *output, gpointer user_data) {
static void instrument_basic_block(GumStalkerIterator *iterator,
GumStalkerOutput * output,
gpointer user_data) {
UNUSED_PARAMETER(user_data);
@ -111,7 +113,7 @@ static void instr_basic_block(GumStalkerIterator *iterator,
if (unlikely(begin)) { instrument_debug_start(instr->address, output); }
if (instr->address == entry_start) { entry_prologue(iterator, output); }
if (instr->address == entry_point) { entry_prologue(iterator, output); }
if (instr->address == persistent_start) { persistent_prologue(output); }
if (instr->address == persistent_ret) { persistent_epilogue(output); }
@ -150,7 +152,7 @@ static void instr_basic_block(GumStalkerIterator *iterator,
if (likely(!excluded)) {
if (likely(optimize)) {
if (likely(instrument_optimize)) {
instrument_coverage_optimize(instr, output);
@ -185,31 +187,39 @@ static void instr_basic_block(GumStalkerIterator *iterator,
}
void instrument_config(void) {
instrument_optimize = (getenv("AFL_FRIDA_INST_NO_OPTIMIZE") == NULL);
instrument_tracing = (getenv("AFL_FRIDA_INST_TRACE") != NULL);
instrument_unique = (getenv("AFL_FRIDA_INST_TRACE_UNIQUE") != NULL);
instrument_debug_config();
asan_config();
cmplog_config();
}
void instrument_init(void) {
optimize = (getenv("AFL_FRIDA_INST_NO_OPTIMIZE") == NULL);
tracing = (getenv("AFL_FRIDA_INST_TRACE") != NULL);
unique = (getenv("AFL_FRIDA_INST_TRACE_UNIQUE") != NULL);
if (!instrument_is_coverage_optimize_supported()) instrument_optimize = false;
if (!instrument_is_coverage_optimize_supported()) optimize = false;
OKF("Instrumentation - optimize [%c]", instrument_optimize ? 'X' : ' ');
OKF("Instrumentation - tracing [%c]", instrument_tracing ? 'X' : ' ');
OKF("Instrumentation - unique [%c]", instrument_unique ? 'X' : ' ');
OKF("Instrumentation - optimize [%c]", optimize ? 'X' : ' ');
OKF("Instrumentation - tracing [%c]", tracing ? 'X' : ' ');
OKF("Instrumentation - unique [%c]", unique ? 'X' : ' ');
if (tracing && optimize) {
if (instrument_tracing && instrument_optimize) {
FATAL("AFL_FRIDA_INST_TRACE requires AFL_FRIDA_INST_NO_OPTIMIZE");
}
if (unique && optimize) {
if (instrument_unique && instrument_optimize) {
FATAL("AFL_FRIDA_INST_TRACE_UNIQUE requires AFL_FRIDA_INST_NO_OPTIMIZE");
}
if (unique) { tracing = TRUE; }
if (instrument_unique) { instrument_tracing = TRUE; }
if (__afl_map_size != 0x10000) {
@ -217,10 +227,10 @@ void instrument_init(void) {
}
transformer =
gum_stalker_transformer_make_from_callback(instr_basic_block, NULL, NULL);
transformer = gum_stalker_transformer_make_from_callback(
instrument_basic_block, NULL, NULL);
if (unique) {
if (instrument_unique) {
int shm_id = shmget(IPC_PRIVATE, MAP_SIZE, IPC_CREAT | IPC_EXCL | 0600);
if (shm_id < 0) { FATAL("shm_id < 0 - errno: %d\n", errno); }

View File

@ -1,4 +1,4 @@
#include "frida-gum.h"
#include "frida-gumjs.h"
#include "debug.h"

View File

@ -1,4 +1,4 @@
#include "frida-gum.h"
#include "frida-gumjs.h"
#include "config.h"
#include "debug.h"
@ -72,7 +72,7 @@ void instrument_coverage_optimize(const cs_insn * instr,
gum_arm64_writer_put_bytes(cw, afl_log_code, sizeof(afl_log_code));
uint8_t **afl_area_ptr_ptr = &__afl_area_ptr;
uint64_t *afl_prev_loc_ptr = &previous_pc;
uint64_t *afl_prev_loc_ptr = &instrument_previous_pc;
gum_arm64_writer_put_bytes(cw, (const guint8 *)&afl_area_ptr_ptr,
sizeof(afl_area_ptr_ptr));
gum_arm64_writer_put_bytes(cw, (const guint8 *)&afl_prev_loc_ptr,

View File

@ -3,7 +3,7 @@
#include <stdio.h>
#include <unistd.h>
#include "frida-gum.h"
#include "frida-gumjs.h"
#include "debug.h"
@ -13,6 +13,8 @@
static int debugging_fd = -1;
static gpointer instrument_gen_start = NULL;
char *instrument_debug_filename = NULL;
static void instrument_debug(char *format, ...) {
va_list ap;
@ -79,18 +81,25 @@ static void instrument_disasm(guint8 *start, guint8 *end) {
}
void instrument_debug_config(void) {
instrument_debug_filename = getenv("AFL_FRIDA_INST_DEBUG_FILE");
}
void instrument_debug_init(void) {
char *filename = getenv("AFL_FRIDA_INST_DEBUG_FILE");
OKF("Instrumentation debugging - enabled [%c]", filename == NULL ? ' ' : 'X');
OKF("Instrumentation debugging - enabled [%c]",
instrument_debug_filename == NULL ? ' ' : 'X');
if (filename == NULL) { return; }
if (instrument_debug_filename == NULL) { return; }
OKF("Instrumentation debugging - file [%s]", filename);
OKF("Instrumentation debugging - file [%s]", instrument_debug_filename);
if (filename == NULL) { return; }
if (instrument_debug_filename == NULL) { return; }
char *path = g_canonicalize_filename(filename, g_get_current_dir());
char *path =
g_canonicalize_filename(instrument_debug_filename, g_get_current_dir());
OKF("Instrumentation debugging - path [%s]", path);

View File

@ -1,4 +1,4 @@
#include "frida-gum.h"
#include "frida-gumjs.h"
#include "config.h"
@ -68,7 +68,7 @@ void instrument_coverage_optimize(const cs_insn * instr,
current_log_impl = cw->pc;
gum_x86_writer_put_bytes(cw, afl_log_code, sizeof(afl_log_code));
uint64_t *afl_prev_loc_ptr = &previous_pc;
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,

View File

@ -1,4 +1,4 @@
#include "frida-gum.h"
#include "frida-gumjs.h"
#include "debug.h"
@ -16,7 +16,7 @@ static void instrument_coverage_function(GumX86Writer *cw) {
gum_x86_writer_put_push_reg(cw, GUM_REG_EDX);
gum_x86_writer_put_mov_reg_address(cw, GUM_REG_ECX,
GUM_ADDRESS(&previous_pc));
GUM_ADDRESS(&instrument_previous_pc));
gum_x86_writer_put_mov_reg_reg_ptr(cw, GUM_REG_EDX, GUM_REG_ECX);
gum_x86_writer_put_xor_reg_reg(cw, GUM_REG_EDX, GUM_REG_EDI);

View File

@ -1,10 +1,10 @@
#include "frida-gum.h"
#include "frida-gumjs.h"
#include "debug.h"
#include "interceptor.h"
#include "intercept.h"
void intercept(void *address, gpointer replacement, gpointer user_data) {
void intercept_hook(void *address, gpointer replacement, gpointer user_data) {
GumInterceptor *interceptor = gum_interceptor_obtain();
gum_interceptor_begin_transaction(interceptor);
@ -15,7 +15,7 @@ void intercept(void *address, gpointer replacement, gpointer user_data) {
}
void unintercept(void *address) {
void intercept_unhook(void *address) {
GumInterceptor *interceptor = gum_interceptor_obtain();
@ -26,10 +26,10 @@ void unintercept(void *address) {
}
void unintercept_self(void) {
void intercept_unhook_self(void) {
GumInvocationContext *ctx = gum_interceptor_get_current_invocation();
unintercept(ctx->function);
intercept_unhook(ctx->function);
}

201
frida_mode/src/js/api.js Normal file
View File

@ -0,0 +1,201 @@
const write = new NativeFunction(
Module.getExportByName(null, 'write'),
'int',
['int', 'pointer', 'int']
);
const afl_frida_trace = Process.findModuleByName('afl-frida-trace.so');
function get_api(name, ret, args) {
const addr = afl_frida_trace.findExportByName(name);
return new NativeFunction(addr, ret, args);
}
const js_api_done = get_api(
'js_api_done',
'void',
[]);
const js_api_error = get_api(
'js_api_error',
'void',
['pointer']);
const js_api_set_entrypoint = get_api(
'js_api_set_entrypoint',
'void',
['pointer']);
const js_api_set_persistent_address = get_api(
'js_api_set_persistent_address',
'void',
['pointer']);
const js_api_set_persistent_return = get_api(
'js_api_set_persistent_return',
'void',
['pointer']);
const js_api_set_persistent_count = get_api(
'js_api_set_persistent_count',
'void',
['uint64']);
const js_api_set_persistent_debug = get_api(
'js_api_set_persistent_debug',
'void',
[]);
const js_api_set_debug_maps = get_api(
'js_api_set_debug_maps',
'void',
[]);
const js_api_add_include_range = get_api(
'js_api_add_include_range',
'void',
['pointer', 'size_t']);
const js_api_add_exclude_range = get_api(
'js_api_add_exclude_range',
'void',
['pointer', 'size_t']);
const js_api_set_instrument_libraries = get_api(
'js_api_set_instrument_libraries',
'void',
[]);
const js_api_set_instrument_debug_file = get_api(
'js_api_set_instrument_debug_file',
'void',
['pointer']);
const js_api_set_prefetch_disable = get_api(
'js_api_set_prefetch_disable',
'void',
[]);
const js_api_set_instrument_no_optimize = get_api(
'js_api_set_instrument_no_optimize',
'void',
[]);
const js_api_set_instrument_trace = get_api(
'js_api_set_instrument_trace',
'void',
[]);
const js_api_set_instrument_trace_unique = get_api(
'js_api_set_instrument_trace_unique',
'void',
[]);
const js_api_set_stdout = get_api(
'js_api_set_stdout',
'void',
['pointer']);
const js_api_set_stderr = get_api(
'js_api_set_stderr',
'void',
['pointer']);
const js_api_set_stats_file = get_api(
'js_api_set_stats_file',
'void',
['pointer']);
const js_api_set_stats_interval = get_api(
'js_api_set_stats_interval',
'void',
['uint64']);
const js_api_set_stats_transitions = get_api(
'js_api_set_stats_transitions',
'void',
[]);
const afl = {
print: function (msg) {
const STDOUT_FILENO = 2;
const log = `${msg}\n`;
const buf = Memory.allocUtf8String(log);
write(STDOUT_FILENO, buf, log.length);
},
done: function() {
js_api_done();
},
error: function(msg) {
const buf = Memory.allocUtf8String(msg);
js_api_error(buf);
},
setEntryPoint: function(addr) {
js_api_set_entrypoint(addr);
},
setPersistentAddress: function(addr) {
js_api_set_persistent_address(addr);
},
setPersistentReturn: function(addr) {
js_api_set_persistent_return(addr);
},
setPersistentCount: function(addr) {
js_api_set_persistent_count(addr);
},
setPersistentDebug: function() {
js_api_set_persistent_debug();
},
setDebugMaps: function() {
js_api_set_debug_maps();
},
addIncludedRange: function(address, size) {
js_api_add_include_range(address, size);
},
addExcludedRange: function(address, size) {
js_api_add_exclude_range(address, size);
},
setInstrumentLibraries: function() {
js_api_set_instrument_libraries();
},
setInstrumentDebugFile: function(file) {
const buf = Memory.allocUtf8String(file);
js_api_set_instrument_debug_file(buf)
},
setPrefetchDisable: function() {
js_api_set_prefetch_disable();
},
setInstrumentNoOptimize: function() {
js_api_set_instrument_no_optimize();
},
setInstrumentEnableTracing: function() {
js_api_set_instrument_trace();
},
setInstrumentTracingUnique: function() {
js_api_set_instrument_trace_unique();
},
setStdOut: function(file) {
const buf = Memory.allocUtf8String(file);
js_api_set_stdout(buf)
},
setStdErr: function(file) {
const buf = Memory.allocUtf8String(file);
js_api_set_stderr(buf)
},
setStatsFile: function(file) {
const buf = Memory.allocUtf8String(file);
js_api_set_stats_file(buf)
},
setStatsInterval: function(interval) {
js_api_set_stats_interval(interval);
},
setStatsTransitions: function() {
js_api_set_stats_transitions();
}
};
Object.defineProperty(global, 'Afl', {value: afl, writeable: false});
////////////////////////////////////////////////////////////////////////////////
// END OF API //
////////////////////////////////////////////////////////////////////////////////

113
frida_mode/src/js/js.c Normal file
View File

@ -0,0 +1,113 @@
#include "frida-gumjs.h"
#include "debug.h"
#include "js.h"
#include "util.h"
static char *js_script = NULL;
gboolean js_done = FALSE;
static gchar * filename = "afl.js";
static gchar * contents;
static GumScriptBackend *backend;
static GCancellable * cancellable = NULL;
static GError * error = NULL;
static GumScript * script;
static void js_msg(GumScript *script, const gchar *message, GBytes *data,
gpointer user_data) {
UNUSED_PARAMETER(script);
UNUSED_PARAMETER(data);
UNUSED_PARAMETER(user_data);
OKF("%s", message);
}
void js_config(void) {
js_script = getenv("AFL_FRIDA_JS_SCRIPT");
}
static gchar *js_get_script() {
gsize length;
if (js_script != NULL) { filename = js_script; }
filename = g_canonicalize_filename(filename, g_get_current_dir());
if (!g_file_get_contents(filename, &contents, &length, NULL)) {
if (js_script == NULL) {
return NULL;
} else {
FATAL("Could not load script file: %s", filename);
}
} else {
OKF("Loaded AFL script: %s, %" G_GSIZE_MODIFIER "d bytes", filename,
length);
gchar *source = g_malloc0(api_js_len + length + 1);
memcpy(source, api_js, api_js_len);
memcpy(&source[api_js_len], contents, length);
return source;
}
}
static void js_print_script(gchar *source) {
gchar **split = g_strsplit(source, "\n", 0);
for (size_t i = 0; split[i] != NULL; i++) {
OKF("%3" G_GSIZE_MODIFIER "d. %s", i + 1, split[i]);
}
g_strfreev(split);
}
void js_start(void) {
GMainContext *context;
gchar *source = js_get_script();
if (source == NULL) { return; }
js_print_script(source);
backend = gum_script_backend_obtain_qjs();
script = gum_script_backend_create_sync(backend, "example", source,
cancellable, &error);
if (error != NULL) {
g_printerr("%s\n", error->message);
FATAL("Error processing script");
}
gum_script_set_message_handler(script, js_msg, NULL, NULL);
gum_script_load_sync(script, cancellable);
context = g_main_context_get_thread_default();
while (g_main_context_pending(context))
g_main_context_iteration(context, FALSE);
if (!js_done) { FATAL("Script didn't call Afl.done()"); }
}

142
frida_mode/src/js/js_api.c Normal file
View File

@ -0,0 +1,142 @@
#include "debug.h"
#include "entry.h"
#include "instrument.h"
#include "js.h"
#include "output.h"
#include "persistent.h"
#include "prefetch.h"
#include "ranges.h"
#include "stats.h"
#include "util.h"
void js_api_done() {
js_done = TRUE;
}
void js_api_error(char *msg) {
FATAL("%s", msg);
}
void js_api_set_entrypoint(void *address) {
entry_point = GPOINTER_TO_SIZE(address);
}
void js_api_set_persistent_address(void *address) {
persistent_start = GPOINTER_TO_SIZE(address);
}
void js_api_set_persistent_return(void *address) {
persistent_ret = GPOINTER_TO_SIZE(address);
}
void js_api_set_persistent_count(uint64_t count) {
persistent_count = count;
}
void js_api_set_persistent_debug() {
persistent_debug = TRUE;
}
void js_api_set_debug_maps() {
ranges_debug_maps = TRUE;
}
void js_api_add_include_range(void *address, gsize size) {
GumMemoryRange range = {.base_address = GUM_ADDRESS(address), .size = size};
ranges_add_include(&range);
}
void js_api_add_exclude_range(void *address, gsize size) {
GumMemoryRange range = {.base_address = GUM_ADDRESS(address), .size = size};
ranges_add_exclude(&range);
}
void js_api_set_instrument_libraries() {
ranges_inst_libs = TRUE;
}
void js_api_set_instrument_debug_file(char *path) {
instrument_debug_filename = g_strdup(path);
}
void js_api_set_prefetch_disable(void) {
prefetch_enable = FALSE;
}
void js_api_set_instrument_no_optimize(void) {
instrument_optimize = FALSE;
}
void js_api_set_instrument_trace(void) {
instrument_tracing = TRUE;
}
void js_api_set_instrument_trace_unique(void) {
instrument_unique = TRUE;
}
void js_api_set_stdout(char *file) {
output_stdout = g_strdup(file);
}
void js_api_set_stderr(char *file) {
output_stderr = g_strdup(file);
}
void js_api_set_stats_file(char *file) {
stats_filename = g_strdup(file);
}
void js_api_set_stats_interval(uint64_t interval) {
stats_interval = interval;
}
void js_api_set_stats_transitions() {
stats_transitions = TRUE;
}
// "AFL_FRIDA_PERSISTENT_HOOK",

View File

@ -6,7 +6,7 @@
#include <sys/mman.h>
#include <unistd.h>
#include "frida-gum.h"
#include "frida-gumjs.h"
#include "debug.h"
@ -151,6 +151,10 @@ static void lib_get_text_section(lib_details_t *details) {
}
void lib_config(void) {
}
void lib_init(void) {
lib_details_t lib_details;

View File

@ -1,5 +1,5 @@
#ifdef __APPLE__
#include "frida-gum.h"
#include "frida-gumjs.h"
#include "debug.h"
@ -56,6 +56,10 @@ gboolean lib_get_text_section(const GumDarwinSectionDetails *details,
}
void lib_config(void) {
}
void lib_init(void) {
GumDarwinModule *module = NULL;

View File

@ -11,14 +11,15 @@
#include <sys/personality.h>
#endif
#include "frida-gum.h"
#include "frida-gumjs.h"
#include "config.h"
#include "debug.h"
#include "entry.h"
#include "instrument.h"
#include "interceptor.h"
#include "intercept.h"
#include "js.h"
#include "lib.h"
#include "output.h"
#include "persistent.h"
@ -44,13 +45,6 @@ typedef int *(*main_fn_t)(int argc, char **argv, char **envp);
static main_fn_t main_fn = NULL;
static int on_fork(void) {
prefetch_read();
return fork();
}
#ifdef __APPLE__
static void on_main_os(int argc, char **argv, char **envp) {
@ -174,23 +168,36 @@ void afl_frida_start(void) {
afl_print_cmdline();
afl_print_env();
/* Configure */
entry_config();
instrument_config();
js_config();
lib_config();
output_config();
persistent_config();
prefetch_config();
ranges_config();
stalker_config();
stats_config();
js_start();
/* Initialize */
output_init();
embedded_init();
stalker_init();
lib_init();
entry_init();
instrument_init();
output_init();
lib_init();
persistent_init();
prefetch_init();
stalker_init();
ranges_init();
stats_init();
void *fork_addr =
GSIZE_TO_POINTER(gum_module_find_export_by_name(NULL, "fork"));
intercept(fork_addr, on_fork, NULL);
/* Start */
stalker_start();
entry_run();
entry_start();
}
@ -198,7 +205,7 @@ static int *on_main(int argc, char **argv, char **envp) {
on_main_os(argc, argv, envp);
unintercept_self();
intercept_unhook_self();
afl_frida_start();
@ -212,7 +219,7 @@ extern int *main(int argc, char **argv, char **envp);
static void intercept_main(void) {
main_fn = main;
intercept(main, on_main, NULL);
intercept_hook(main, on_main, NULL);
}
@ -225,7 +232,7 @@ static void intercept_main(void) {
OKF("Entry Point: 0x%016" G_GINT64_MODIFIER "x", entry);
void *main = GSIZE_TO_POINTER(entry);
main_fn = main;
intercept(main, on_main, NULL);
intercept_hook(main, on_main, NULL);
}
@ -236,8 +243,8 @@ static int on_libc_start_main(int *(main)(int, char **, char **), int argc,
void(*stack_end)) {
main_fn = main;
unintercept_self();
intercept(main, on_main, NULL);
intercept_unhook_self();
intercept_hook(main, on_main, NULL);
return __libc_start_main(main, argc, ubp_av, init, fini, rtld_fini,
stack_end);
@ -245,7 +252,7 @@ static int on_libc_start_main(int *(main)(int, char **, char **), int argc,
static void intercept_main(void) {
intercept(__libc_start_main, on_libc_start_main, NULL);
intercept_hook(__libc_start_main, on_libc_start_main, NULL);
}

View File

@ -2,17 +2,17 @@
#include <fcntl.h>
#include <unistd.h>
#include "frida-gum.h"
#include "frida-gumjs.h"
#include "debug.h"
#include "output.h"
static int output_fd = -1;
char *output_stdout = NULL;
char *output_stderr = NULL;
static void output_redirect(int fd, char *variable) {
static void output_redirect(int fd, char *filename) {
char *filename = getenv(variable);
char *path = NULL;
if (filename == NULL) { return; }
@ -21,7 +21,7 @@ static void output_redirect(int fd, char *variable) {
OKF("Redirect %d -> '%s'", fd, path);
output_fd = open(path, O_RDWR | O_CREAT | O_TRUNC,
int output_fd = open(path, O_RDWR | O_CREAT | O_TRUNC,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
g_free(path);
@ -34,12 +34,24 @@ static void output_redirect(int fd, char *variable) {
}
close(output_fd);
}
void output_config(void) {
output_stdout = getenv("AFL_FRIDA_OUTPUT_STDOUT");
output_stderr = getenv("AFL_FRIDA_OUTPUT_STDERR");
}
void output_init(void) {
output_redirect(STDOUT_FILENO, "AFL_FRIDA_OUTPUT_STDOUT");
output_redirect(STDERR_FILENO, "AFL_FRIDA_OUTPUT_STDERR");
OKF("Output - StdOut: %s", output_stdout);
OKF("Output - StdErr: %s", output_stderr);
output_redirect(STDOUT_FILENO, output_stdout);
output_redirect(STDERR_FILENO, output_stderr);
}

View File

@ -1,6 +1,6 @@
#include <dlfcn.h>
#include "frida-gum.h"
#include "frida-gumjs.h"
#include "config.h"
#include "debug.h"
@ -9,16 +9,17 @@
#include "util.h"
int __afl_sharedmem_fuzzing = 0;
afl_persistent_hook_fn hook = NULL;
static char *hook_name = NULL;
afl_persistent_hook_fn persistent_hook = NULL;
guint64 persistent_start = 0;
guint64 persistent_count = 0;
guint64 persistent_ret = 0;
gboolean persistent_debug = FALSE;
void persistent_init(void) {
char *hook_name = getenv("AFL_FRIDA_PERSISTENT_HOOK");
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");
@ -33,6 +34,11 @@ void persistent_init(void) {
}
if (persistent_start != 0 && persistent_count == 0) persistent_count = 1000;
if (persistent_start != 0 && !persistent_is_supported())
FATAL("Persistent mode not supported on this architecture");
if (persistent_ret != 0 && persistent_start == 0) {
FATAL(
@ -41,13 +47,9 @@ void persistent_init(void) {
}
if (persistent_start != 0 && persistent_count == 0) persistent_count = 1000;
}
if (persistent_count != 0 && persistent_count < 100)
WARNF("Persistent count out of recommended range (<100)");
if (persistent_start != 0 && !persistent_is_supported())
FATAL("Persistent mode not supported on this architecture");
void persistent_init(void) {
OKF("Instrumentation - persistent mode [%c] (0x%016" G_GINT64_MODIFIER "X)",
persistent_start == 0 ? ' ' : 'X', persistent_start);
@ -58,7 +60,7 @@ void persistent_init(void) {
OKF("Instrumentation - persistent ret [%c] (0x%016" G_GINT64_MODIFIER "X)",
persistent_ret == 0 ? ' ' : 'X', persistent_ret);
if (hook_name != NULL) {
if (hook_name == NULL) { return; }
void *hook_obj = dlopen(hook_name, RTLD_NOW);
if (hook_obj == NULL)
@ -72,13 +74,12 @@ void persistent_init(void) {
if (afl_persistent_hook_init_ptr() == 0)
FATAL("afl_persistent_hook_init returned a failure");
hook = (afl_persistent_hook_fn)dlsym(hook_obj, "afl_persistent_hook");
if (hook == NULL)
persistent_hook =
(afl_persistent_hook_fn)dlsym(hook_obj, "afl_persistent_hook");
if (persistent_hook == NULL)
FATAL("Failed to find afl_persistent_hook in %s", hook_name);
__afl_sharedmem_fuzzing = 1;
}
}

View File

@ -1,4 +1,4 @@
#include "frida-gum.h"
#include "frida-gumjs.h"
#include "debug.h"

View File

@ -1,5 +1,5 @@
#include <unistd.h>
#include "frida-gum.h"
#include "frida-gumjs.h"
#include "config.h"
#include "debug.h"
@ -318,7 +318,7 @@ static void instrument_exit(GumArm64Writer *cw) {
static int instrument_afl_persistent_loop_func(void) {
int ret = __afl_persistent_loop(persistent_count);
previous_pc = 0;
instrument_previous_pc = 0;
return ret;
}
@ -337,7 +337,7 @@ static void instrument_afl_persistent_loop(GumArm64Writer *cw) {
static void persistent_prologue_hook(GumArm64Writer * cw,
struct arm64_regs *regs) {
if (hook == NULL) return;
if (persistent_hook == NULL) return;
gum_arm64_writer_put_sub_reg_reg_imm(cw, ARM64_REG_SP, ARM64_REG_SP,
GUM_RED_ZONE_SIZE);
@ -354,7 +354,7 @@ static void persistent_prologue_hook(GumArm64Writer * cw,
gum_arm64_writer_put_ldr_reg_reg_offset(cw, ARM64_REG_X2, ARM64_REG_X2, 0);
gum_arm64_writer_put_call_address_with_arguments(
cw, GUM_ADDRESS(hook), 4, GUM_ARG_ADDRESS, GUM_ADDRESS(regs),
cw, GUM_ADDRESS(persistent_hook), 4, GUM_ARG_ADDRESS, GUM_ADDRESS(regs),
GUM_ARG_ADDRESS, GUM_ADDRESS(0), GUM_ARG_REGISTER, ARM64_REG_X2,
GUM_ARG_REGISTER, ARM64_REG_X3);

View File

@ -1,5 +1,5 @@
#include <unistd.h>
#include "frida-gum.h"
#include "frida-gumjs.h"
#include "config.h"
#include "debug.h"
@ -199,7 +199,7 @@ static void instrument_exit(GumX86Writer *cw) {
static int instrument_afl_persistent_loop_func(void) {
int ret = __afl_persistent_loop(persistent_count);
previous_pc = 0;
instrument_previous_pc = 0;
return ret;
}
@ -220,7 +220,7 @@ static void instrument_afl_persistent_loop(GumX86Writer *cw) {
static void persistent_prologue_hook(GumX86Writer * cw,
struct x86_64_regs *regs) {
if (hook == NULL) return;
if (persistent_hook == NULL) return;
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP,
-(GUM_RED_ZONE_SIZE));
@ -236,7 +236,7 @@ static void persistent_prologue_hook(GumX86Writer * cw,
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RDX, GUM_REG_RDX, 0);
gum_x86_writer_put_call_address_with_arguments(
cw, GUM_CALL_CAPI, GUM_ADDRESS(hook), 4, GUM_ARG_ADDRESS,
cw, GUM_CALL_CAPI, GUM_ADDRESS(persistent_hook), 4, GUM_ARG_ADDRESS,
GUM_ADDRESS(regs), GUM_ARG_ADDRESS, GUM_ADDRESS(0), GUM_ARG_REGISTER,
GUM_REG_RDX, GUM_ARG_REGISTER, GUM_REG_RCX);

View File

@ -1,4 +1,4 @@
#include "frida-gum.h"
#include "frida-gumjs.h"
#include "config.h"
@ -152,7 +152,7 @@ static void instrument_exit(GumX86Writer *cw) {
static int instrument_afl_persistent_loop_func(void) {
int ret = __afl_persistent_loop(persistent_count);
previous_pc = 0;
instrument_previous_pc = 0;
return ret;
}
@ -167,7 +167,7 @@ static void instrument_afl_persistent_loop(GumX86Writer *cw) {
static void persistent_prologue_hook(GumX86Writer *cw, struct x86_regs *regs) {
if (hook == NULL) return;
if (persistent_hook == NULL) return;
gum_x86_writer_put_mov_reg_address(cw, GUM_REG_ECX,
GUM_ADDRESS(&__afl_fuzz_len));
@ -180,7 +180,7 @@ static void persistent_prologue_hook(GumX86Writer *cw, struct x86_regs *regs) {
/* Base address is 64-bits (hence two zero arguments) */
gum_x86_writer_put_call_address_with_arguments(
cw, GUM_CALL_CAPI, GUM_ADDRESS(hook), 5, GUM_ARG_ADDRESS,
cw, GUM_CALL_CAPI, GUM_ADDRESS(persistent_hook), 5, GUM_ARG_ADDRESS,
GUM_ADDRESS(regs), GUM_ARG_ADDRESS, GUM_ADDRESS(0), GUM_ARG_ADDRESS,
GUM_ADDRESS(0), GUM_ARG_REGISTER, GUM_REG_EDX, GUM_ARG_REGISTER,
GUM_REG_ECX);

View File

@ -2,10 +2,11 @@
#include <sys/shm.h>
#include <sys/mman.h>
#include "frida-gum.h"
#include "frida-gumjs.h"
#include "debug.h"
#include "intercept.h"
#include "prefetch.h"
#include "stalker.h"
@ -20,8 +21,9 @@ typedef struct {
} prefetch_data_t;
static prefetch_data_t *prefetch_data = NULL;
gboolean prefetch_enable = TRUE;
static prefetch_data_t *prefetch_data = NULL;
static int prefetch_shm_id = -1;
/*
@ -72,14 +74,33 @@ void prefetch_read(void) {
}
void prefetch_config(void) {
prefetch_enable = (getenv("AFL_FRIDA_INST_NO_PREFETCH") == NULL);
}
static int prefetch_on_fork(void) {
prefetch_read();
return fork();
}
static void prefetch_hook_fork(void) {
void *fork_addr =
GSIZE_TO_POINTER(gum_module_find_export_by_name(NULL, "fork"));
intercept_hook(fork_addr, prefetch_on_fork, NULL);
}
void prefetch_init(void) {
g_assert_cmpint(sizeof(prefetch_data_t), ==, PREFETCH_SIZE);
gboolean prefetch = (getenv("AFL_FRIDA_INST_NO_PREFETCH") == NULL);
OKF("Instrumentation - prefetch [%c]", prefetch_enable ? 'X' : ' ');
OKF("Instrumentation - prefetch [%c]", prefetch ? 'X' : ' ');
if (!prefetch) { return; }
if (!prefetch_enable) { return; }
/*
* Make our shared memory, we can attach before we fork, just like AFL does
* with the coverage bitmap region and fork will take care of ensuring both
@ -108,5 +129,7 @@ void prefetch_init(void) {
/* Clear it, not sure it's necessary, just seems like good practice */
memset(prefetch_data, '\0', sizeof(prefetch_data_t));
prefetch_hook_fork();
}

View File

@ -1,4 +1,4 @@
#include "frida-gum.h"
#include "frida-gumjs.h"
#include "debug.h"
@ -17,11 +17,14 @@ typedef struct {
} convert_name_ctx_t;
GArray *module_ranges = NULL;
GArray *libs_ranges = NULL;
GArray *include_ranges = NULL;
GArray *exclude_ranges = NULL;
GArray *ranges = NULL;
gboolean ranges_debug_maps = FALSE;
gboolean ranges_inst_libs = FALSE;
static GArray *module_ranges = NULL;
static GArray *libs_ranges = NULL;
static GArray *include_ranges = NULL;
static GArray *exclude_ranges = NULL;
static GArray *ranges = NULL;
static void convert_address_token(gchar *token, GumMemoryRange *range) {
@ -225,6 +228,43 @@ static GArray *collect_module_ranges(void) {
}
static void check_for_overlaps(GArray *array) {
for (guint i = 1; i < array->len; i++) {
GumMemoryRange *prev = &g_array_index(array, GumMemoryRange, i - 1);
GumMemoryRange *curr = &g_array_index(array, GumMemoryRange, i);
GumAddress prev_limit = prev->base_address + prev->size;
GumAddress curr_limit = curr->base_address + curr->size;
if (prev_limit > curr->base_address) {
FATAL("OVerlapping ranges 0x%016" G_GINT64_MODIFIER
"x-0x%016" G_GINT64_MODIFIER "x 0x%016" G_GINT64_MODIFIER
"x-0x%016" G_GINT64_MODIFIER "x",
prev->base_address, prev_limit, curr->base_address, curr_limit);
}
}
}
void ranges_add_include(GumMemoryRange *range) {
g_array_append_val(include_ranges, *range);
g_array_sort(include_ranges, range_sort);
check_for_overlaps(include_ranges);
}
void ranges_add_exclude(GumMemoryRange *range) {
g_array_append_val(exclude_ranges, *range);
g_array_sort(exclude_ranges, range_sort);
check_for_overlaps(exclude_ranges);
}
static GArray *collect_ranges(char *env_key) {
char * env_val;
@ -253,23 +293,7 @@ static GArray *collect_ranges(char *env_key) {
g_array_sort(result, range_sort);
/* Check for overlaps */
for (i = 1; i < token_count; i++) {
GumMemoryRange *prev = &g_array_index(result, GumMemoryRange, i - 1);
GumMemoryRange *curr = &g_array_index(result, GumMemoryRange, i);
GumAddress prev_limit = prev->base_address + prev->size;
GumAddress curr_limit = curr->base_address + curr->size;
if (prev_limit > curr->base_address) {
FATAL("OVerlapping ranges 0x%016" G_GINT64_MODIFIER
"x-0x%016" G_GINT64_MODIFIER "x 0x%016" G_GINT64_MODIFIER
"x-0x%016" G_GINT64_MODIFIER "x",
prev->base_address, prev_limit, curr->base_address, curr_limit);
}
}
check_for_overlaps(result);
print_ranges(env_key, result);
@ -285,16 +309,16 @@ static GArray *collect_libs_ranges(void) {
GumMemoryRange range;
result = g_array_new(false, false, sizeof(GumMemoryRange));
if (getenv("AFL_INST_LIBS") == NULL) {
range.base_address = lib_get_text_base();
range.size = lib_get_text_limit() - lib_get_text_base();
} else {
if (ranges_inst_libs) {
range.base_address = 0;
range.size = G_MAXULONG;
} else {
range.base_address = lib_get_text_base();
range.size = lib_get_text_limit() - lib_get_text_base();
}
g_array_append_val(result, range);
@ -480,30 +504,13 @@ static GArray *merge_ranges(GArray *a) {
}
static gboolean exclude_ranges_callback(const GumRangeDetails *details,
gpointer user_data) {
void ranges_config(void) {
UNUSED_PARAMETER(user_data);
gchar * name;
gboolean found;
GumStalker *stalker;
if (details->file == NULL) { return TRUE; }
name = g_path_get_basename(details->file->path);
if (getenv("AFL_FRIDA_DEBUG_MAPS") != NULL) { ranges_debug_maps = TRUE; }
if (getenv("AFL_INST_LIBS") != NULL) { ranges_inst_libs = TRUE; }
found = (g_strcmp0(name, "afl-frida-trace.so") == 0);
g_free(name);
if (!found) { return TRUE; }
stalker = stalker_get();
gum_stalker_exclude(stalker, details->range);
return FALSE;
}
static void ranges_exclude_self(void) {
gum_process_enumerate_ranges(GUM_PAGE_EXECUTE, exclude_ranges_callback, NULL);
include_ranges = collect_ranges("AFL_FRIDA_INST_RANGES");
exclude_ranges = collect_ranges("AFL_FRIDA_EXCLUDE_RANGES");
}
@ -515,16 +522,20 @@ void ranges_init(void) {
GArray * step3;
GArray * step4;
if (getenv("AFL_FRIDA_DEBUG_MAPS") != NULL) {
if (ranges_debug_maps) {
gum_process_enumerate_ranges(GUM_PAGE_NO_ACCESS, print_ranges_callback,
NULL);
}
OKF("Ranges - Instrument libraries [%c]", ranges_inst_libs ? 'X' : ' ');
print_ranges("AFL_FRIDA_INST_RANGES", include_ranges);
print_ranges("AFL_FRIDA_EXCLUDE_RANGES", exclude_ranges);
module_ranges = collect_module_ranges();
libs_ranges = collect_libs_ranges();
include_ranges = collect_ranges("AFL_FRIDA_INST_RANGES");
/* If include ranges is empty, then assume everything is included */
if (include_ranges->len == 0) {
@ -535,8 +546,6 @@ void ranges_init(void) {
}
exclude_ranges = collect_ranges("AFL_FRIDA_EXCLUDE_RANGES");
/* Intersect with .text section of main executable unless AFL_INST_LIBS */
step1 = intersect_ranges(module_ranges, libs_ranges);
print_ranges("step1", step1);
@ -565,9 +574,6 @@ void ranges_init(void) {
g_array_free(step2, TRUE);
g_array_free(step1, TRUE);
/* *NEVER* stalk the stalker, only bad things will ever come of this! */
ranges_exclude_self();
ranges_exclude();
}

View File

@ -2,18 +2,47 @@
#include "instrument.h"
#include "stalker.h"
#include "util.h"
static GumStalker *stalker = NULL;
void stalker_init(void) {
void stalker_config(void) {
if (!gum_stalker_is_supported()) { FATAL("Failed to initialize embedded"); }
}
static gboolean stalker_exclude_self(const GumRangeDetails *details,
gpointer user_data) {
UNUSED_PARAMETER(user_data);
gchar * name;
gboolean found;
GumStalker *stalker;
if (details->file == NULL) { return TRUE; }
name = g_path_get_basename(details->file->path);
found = (g_strcmp0(name, "afl-frida-trace.so") == 0);
g_free(name);
if (!found) { return TRUE; }
stalker = stalker_get();
gum_stalker_exclude(stalker, details->range);
return FALSE;
}
void stalker_init(void) {
stalker = gum_stalker_new();
if (stalker == NULL) { FATAL("Failed to initialize stalker"); }
gum_stalker_set_trust_threshold(stalker, 0);
/* *NEVER* stalk the stalker, only bad things will ever come of this! */
gum_process_enumerate_ranges(GUM_PAGE_EXECUTE, stalker_exclude_self, NULL);
}
GumStalker *stalker_get(void) {

View File

@ -5,7 +5,7 @@
#include <sys/shm.h>
#include <sys/mman.h>
#include "frida-gum.h"
#include "frida-gumjs.h"
#include "config.h"
#include "debug.h"
@ -19,13 +19,14 @@ stats_data_header_t *stats_data = NULL;
static int stats_parent_pid = -1;
static int stats_fd = -1;
static gboolean stats_transitions = FALSE;
static guint64 stats_interval = 0;
void stats_init(void) {
char * stats_filename = NULL;
guint64 stats_interval = 0;
gboolean stats_transitions = FALSE;
stats_parent_pid = getpid();
char *filename = getenv("AFL_FRIDA_STATS_FILE");
void stats_config(void) {
stats_filename = getenv("AFL_FRIDA_STATS_FILE");
stats_interval = util_read_num("AFL_FRIDA_STATS_INTERVAL");
if (getenv("AFL_FRIDA_STATS_TRANSITIONS") != NULL) {
@ -33,10 +34,16 @@ void stats_init(void) {
}
OKF("Stats - file [%s]", filename);
}
void stats_init(void) {
stats_parent_pid = getpid();
OKF("Stats - file [%s]", stats_filename);
OKF("Stats - interval [%" G_GINT64_MODIFIER "u]", stats_interval);
if (stats_interval != 0 && filename == NULL) {
if (stats_interval != 0 && stats_filename == NULL) {
FATAL(
"AFL_FRIDA_STATS_FILE must be specified if "
@ -46,7 +53,7 @@ void stats_init(void) {
if (stats_interval == 0) { stats_interval = 10; }
if (filename == NULL) { return; }
if (stats_filename == NULL) { return; }
if (!stats_is_supported_arch()) {
@ -56,11 +63,11 @@ void stats_init(void) {
char *path = NULL;
if (filename == NULL) { return; }
if (stats_filename == NULL) { return; }
if (stats_transitions) { gum_stalker_set_counters_enabled(TRUE); }
path = g_canonicalize_filename(filename, g_get_current_dir());
path = g_canonicalize_filename(stats_filename, g_get_current_dir());
OKF("Stats - path [%s]", path);

View File

@ -1,4 +1,4 @@
#include "frida-gum.h"
#include "frida-gumjs.h"
#include "debug.h"

View File

@ -1,4 +1,4 @@
#include "frida-gum.h"
#include "frida-gumjs.h"
#include "debug.h"

View File

@ -1,4 +1,4 @@
#include "frida-gum.h"
#include "frida-gumjs.h"
#include "debug.h"

View File

@ -1,4 +1,4 @@
#include "frida-gum.h"
#include "frida-gumjs.h"
#include "debug.h"

View File

@ -37,7 +37,7 @@ ifeq "$(ARCH)" "x86"
AFL_ENTRYPOINT=$(shell $(GET_SYMBOL_ADDR) -f $(TESTINSTBIN) -s run -b 0x56555000)
endif
.PHONY: all clean qemu frida
.PHONY: all clean frida
all: $(TESTINSTBIN)
make -C $(ROOT)frida_mode/

View File

@ -0,0 +1,44 @@
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 32 clean qemu frida
all: $(TESTINSTBIN)
make -C $(ROOT)frida_mode/
32:
CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all
$(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) $(CFLAGS) $(LDFLAGS) -o $@ $<
clean:
rm -rf $(BUILD_DIR)
frida: $(TESTINSTBIN) $(TESTINSTR_DATA_FILE)
AFL_FRIDA_JS_SCRIPT=test.js \
$(ROOT)afl-fuzz \
-D \
-O \
-i $(TESTINSTR_DATA_DIR) \
-o $(FRIDA_OUT) \
-- \
$(TESTINSTBIN) @@

View File

@ -0,0 +1,16 @@
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
debug:
@gmake debug

View File

@ -0,0 +1,20 @@
Afl.print('******************');
Afl.print('* AFL FRIDA MODE *');
Afl.print('******************');
Afl.print('');
Afl.print(`PID: ${Process.id}`);
new ModuleMap().values().forEach(m => {
Afl.print(`${m.base}-${m.base.add(m.size)} ${m.name}`);
});
const entry_point = DebugSymbol.fromName('run');
Afl.print(`entry_point: ${entry_point.address}`);
Afl.setEntryPoint(entry_point.address);
// Afl.error('HARD NOPE');
Afl.done();
Afl.print("done");

View File

@ -0,0 +1,121 @@
/*
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");
}
int run(char *file) {
int fd = -1;
off_t len;
char * buf = NULL;
size_t n_read;
int result = -1;
do {
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;
}
void slow() {
usleep(100000);
}
int main(int argc, char **argv) {
if (argc != 2) { return 1; }
slow();
return run(argv[1]);
}

View File

@ -82,6 +82,16 @@ frida_ret: $(TESTINSTBIN) $(TESTINSTR_DATA_FILE)
-- \
$(TESTINSTBIN) @@
frida_js: $(TESTINSTBIN) $(TESTINSTR_DATA_FILE)
AFL_FRIDA_JS_SCRIPT=test.js \
$(ROOT)afl-fuzz \
-D \
-O \
-i $(TESTINSTR_DATA_DIR) \
-o $(FRIDA_OUT) \
-- \
$(TESTINSTBIN) @@
debug: $(TESTINSTBIN) $(TESTINSTR_DATA_FILE)
gdb \
--ex 'set environment AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR)' \

View File

@ -0,0 +1,38 @@
Afl.print('******************');
Afl.print('* AFL FRIDA MODE *');
Afl.print('******************');
Afl.print('');
Afl.print(`PID: ${Process.id}`);
new ModuleMap().values().forEach(m => {
Afl.print(`${m.base}-${m.base.add(m.size)} ${m.name}`);
});
const persistent_addr = DebugSymbol.fromName('main');
Afl.print(`persistent_addr: ${persistent_addr.address}`);
const persistent_ret = DebugSymbol.fromName('slow');
Afl.print(`persistent_ret: ${persistent_ret.address}`);
Afl.setPersistentAddress(persistent_addr.address);
Afl.setPersistentReturn(persistent_ret.address);
Afl.setPersistentCount(1000000);
Afl.setDebugMaps();
const mod = Process.findModuleByName("libc-2.31.so")
Afl.addExcludedRange(mod.base, mod.size);
Afl.setInstrumentLibraries();
Afl.setInstrumentDebugFile("/tmp/instr.log");
Afl.setPrefetchDisable();
Afl.setInstrumentNoOptimize();
Afl.setInstrumentEnableTracing();
Afl.setInstrumentTracingUnique();
Afl.setStdOut("/tmp/stdout.txt");
Afl.setStdErr("/tmp/stderr.txt");
Afl.setStatsFile("/tmp/stats.txt");
Afl.setStatsInterval(1);
Afl.setStatsTransitions();
Afl.done();
Afl.print("done");

View File

@ -60,7 +60,8 @@ static char *afl_environment_variables[] = {
"AFL_FRIDA_INST_NO_PREFETCH",
"AFL_FRIDA_INST_RANGES",
"AFL_FRIDA_INST_TRACE",
"AFL_FRIDA_INST_UNSTABLE",
"AFL_FRIDA_INST_TRACE_UNIQUE",
"AFL_FRIDA_JS_SCRIPT",
"AFL_FRIDA_OUTPUT_STDOUT",
"AFL_FRIDA_OUTPUT_STDERR",
"AFL_FRIDA_PERSISTENT_ADDR",