mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-14 19:08:08 +00:00
Added JS support (#992)
* Added JS support * Added some documentation Co-authored-by: Your Name <you@example.com>
This commit is contained in:
committed by
GitHub
parent
4057134d3c
commit
f348a35ec6
@ -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) \
|
||||
|
@ -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
240
frida_mode/Scripting.md
Normal 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()
|
||||
```
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
11
frida_mode/include/intercept.h
Normal file
11
frida_mode/include/intercept.h
Normal 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
|
||||
|
@ -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
18
frida_mode/include/js.h
Normal 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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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, ...);
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "frida-gum.h"
|
||||
#include "frida-gumjs.h"
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include <dlfcn.h>
|
||||
#include "frida-gum.h"
|
||||
#include "frida-gumjs.h"
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include <dlfcn.h>
|
||||
#include "frida-gum.h"
|
||||
#include "frida-gumjs.h"
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include <dlfcn.h>
|
||||
#include "frida-gum.h"
|
||||
#include "frida-gumjs.h"
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
|
@ -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");
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "frida-gum.h"
|
||||
#include "frida-gumjs.h"
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "frida-gum.h"
|
||||
#include "frida-gumjs.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include "cmplog.h"
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "frida-gum.h"
|
||||
#include "frida-gumjs.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include "cmplog.h"
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "frida-gum.h"
|
||||
#include "frida-gumjs.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include "cmplog.h"
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "frida-gum.h"
|
||||
#include "frida-gumjs.h"
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "frida-gum.h"
|
||||
#include "frida-gumjs.h"
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "frida-gum.h"
|
||||
#include "frida-gumjs.h"
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "frida-gum.h"
|
||||
#include "frida-gumjs.h"
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
|
@ -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(); }
|
||||
|
||||
}
|
||||
|
||||
|
@ -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); }
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "frida-gum.h"
|
||||
#include "frida-gumjs.h"
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
201
frida_mode/src/js/api.js
Normal 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
113
frida_mode/src/js/js.c
Normal 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
142
frida_mode/src/js/js_api.c
Normal 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",
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "frida-gum.h"
|
||||
#include "frida-gumjs.h"
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "frida-gum.h"
|
||||
#include "frida-gumjs.h"
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "frida-gum.h"
|
||||
#include "frida-gumjs.h"
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "frida-gum.h"
|
||||
#include "frida-gumjs.h"
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include "frida-gum.h"
|
||||
#include "frida-gumjs.h"
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
|
@ -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/
|
||||
|
44
frida_mode/test/js/GNUmakefile
Normal file
44
frida_mode/test/js/GNUmakefile
Normal 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) @@
|
16
frida_mode/test/js/Makefile
Normal file
16
frida_mode/test/js/Makefile
Normal 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
|
20
frida_mode/test/js/test.js
Normal file
20
frida_mode/test/js/test.js
Normal 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");
|
121
frida_mode/test/js/testinstr.c
Normal file
121
frida_mode/test/js/testinstr.c
Normal 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]);
|
||||
|
||||
}
|
||||
|
@ -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)' \
|
||||
|
38
frida_mode/test/persistent_ret/test.js
Normal file
38
frida_mode/test/persistent_ret/test.js
Normal 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");
|
@ -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",
|
||||
|
Reference in New Issue
Block a user