aboutsummaryrefslogtreecommitdiff
path: root/utils/afl_frida
diff options
context:
space:
mode:
authorhexcoder- <heiko@hexco.de>2021-02-13 23:29:04 +0100
committerhexcoder- <heiko@hexco.de>2021-02-13 23:29:04 +0100
commite45333bcf96f86b5ef0b905a8e84fad7b7cb0427 (patch)
tree30deaa24dbcc759bf03df3b1043ef1ca69f89089 /utils/afl_frida
parentc906c042be926652aa2e2d9fb4886ee03f5d86c2 (diff)
parent9bd1e19d7f004b4da6a610b07e59f99d66bb7ec2 (diff)
downloadafl++-e45333bcf96f86b5ef0b905a8e84fad7b7cb0427.tar.gz
Merge branch 'dev' of https://github.com/AFLplusplus/AFLplusplus into dev
Diffstat (limited to 'utils/afl_frida')
-rw-r--r--utils/afl_frida/README.md2
-rw-r--r--utils/afl_frida/afl-frida.c256
-rw-r--r--utils/afl_frida/android/README.md1
-rw-r--r--utils/afl_frida/android/frida-gum-example.c130
4 files changed, 324 insertions, 65 deletions
diff --git a/utils/afl_frida/README.md b/utils/afl_frida/README.md
index 7743479b..68b62009 100644
--- a/utils/afl_frida/README.md
+++ b/utils/afl_frida/README.md
@@ -20,7 +20,7 @@ search and edit the `STEP 1`, `STEP 2` and `STEP 3` locations.
Example (after modifying afl-frida.c to your needs and compile it):
```
-LD_LIBRARY_PATH=/path/to/the/target/library afl-fuzz -i in -o out -- ./afl-frida
+LD_LIBRARY_PATH=/path/to/the/target/library/ afl-fuzz -i in -o out -- ./afl-frida
```
(or even remote via afl-network-proxy).
diff --git a/utils/afl_frida/afl-frida.c b/utils/afl_frida/afl-frida.c
index b5b8196d..711d8f33 100644
--- a/utils/afl_frida/afl-frida.c
+++ b/utils/afl_frida/afl-frida.c
@@ -78,11 +78,11 @@ extern unsigned int * __afl_fuzz_len;
extern unsigned char *__afl_fuzz_ptr;
// Notify AFL about persistent mode.
-static volatile char AFL_PERSISTENT[] = "##SIG_AFL_PERSISTENT##";
+static volatile char AFL_PERSISTENT[] = "##SIG_AFL_PERSISTENT##\0";
int __afl_persistent_loop(unsigned int);
// Notify AFL about deferred forkserver.
-static volatile char AFL_DEFER_FORKSVR[] = "##SIG_AFL_DEFER_FORKSRV##";
+static volatile char AFL_DEFER_FORKSVR[] = "##SIG_AFL_DEFER_FORKSRV##\0";
void __afl_manual_init();
// Because we do our own logging.
@@ -94,6 +94,8 @@ typedef struct {
GumAddress base_address;
guint64 code_start, code_end;
+ GumAddress current_log_impl;
+ uint64_t afl_prev_loc;
} range_t;
@@ -109,12 +111,58 @@ inline static void afl_maybe_log(guint64 current_pc) {
}
+#if GUM_NATIVE_CPU == GUM_CPU_AMD64
+
+static const guint8 afl_maybe_log_code[] = {
+
+ 0x9c, // pushfq
+ 0x50, // push rax
+ 0x51, // push rcx
+ 0x52, // push rdx
+ 0x56, // push rsi
+
+ 0x89, 0xf8, // mov eax, edi
+ 0xc1, 0xe0, 0x08, // shl eax, 8
+ 0xc1, 0xef, 0x04, // shr edi, 4
+ 0x31, 0xc7, // xor edi, eax
+ 0x0f, 0xb7, 0xc7, // movzx eax, di
+ 0x48, 0x8d, 0x0d, 0x30, 0x00, 0x00, 0x00, // lea rcx, sym._afl_area_ptr_ptr
+ 0x48, 0x8b, 0x09, // mov rcx, qword [rcx]
+ 0x48, 0x8b, 0x09, // mov rcx, qword [rcx]
+ 0x48, 0x8d, 0x15, 0x1b, 0x00, 0x00, 0x00, // lea rdx, sym._afl_prev_loc_ptr
+ 0x48, 0x8b, 0x32, // mov rsi, qword [rdx]
+ 0x48, 0x8b, 0x36, // mov rsi, qword [rsi]
+ 0x48, 0x31, 0xc6, // xor rsi, rax
+ 0xfe, 0x04, 0x31, // inc byte [rcx + rsi]
+
+ 0x48, 0xd1, 0xe8, // shr rax, 1
+ 0x48, 0x8b, 0x0a, // mov rcx, qword [rdx]
+ 0x48, 0x89, 0x01, // mov qword [rcx], rax
+
+ 0x5e, // pop rsi
+ 0x5a, // pop rdx
+ 0x59, // pop rcx
+ 0x58, // pop rax
+ 0x9d, // popfq
+
+ 0xc3, // ret
+ // Read-only data goes here:
+ // uint64_t* afl_prev_loc_ptr
+ // uint8_t** afl_area_ptr_ptr
+ // unsigned int afl_instr_rms
+
+};
+
+#else
+
static void on_basic_block(GumCpuContext *context, gpointer user_data) {
afl_maybe_log((guint64)user_data);
}
+#endif
+
void instr_basic_block(GumStalkerIterator *iterator, GumStalkerOutput *output,
gpointer user_data) {
@@ -129,8 +177,45 @@ void instr_basic_block(GumStalkerIterator *iterator, GumStalkerOutput *output,
if (instr->address >= range->code_start &&
instr->address <= range->code_end) {
+#if GUM_NATIVE_CPU == GUM_CPU_AMD64
+ GumX86Writer *cw = output->writer.x86;
+ if (range->current_log_impl == 0 ||
+ !gum_x86_writer_can_branch_directly_between(
+ cw->pc, range->current_log_impl) ||
+ !gum_x86_writer_can_branch_directly_between(
+ cw->pc + 128, range->current_log_impl)) {
+
+ gconstpointer after_log_impl = cw->code + 1;
+
+ gum_x86_writer_put_jmp_near_label(cw, after_log_impl);
+
+ range->current_log_impl = cw->pc;
+ gum_x86_writer_put_bytes(cw, afl_maybe_log_code,
+ sizeof(afl_maybe_log_code));
+
+ uint64_t *afl_prev_loc_ptr = &range->afl_prev_loc;
+ uint8_t **afl_area_ptr_ptr = &__afl_area_ptr;
+ gum_x86_writer_put_bytes(cw, (const guint8 *)&afl_prev_loc_ptr,
+ sizeof(afl_prev_loc_ptr));
+ gum_x86_writer_put_bytes(cw, (const guint8 *)&afl_area_ptr_ptr,
+ sizeof(afl_area_ptr_ptr));
+ gum_x86_writer_put_label(cw, after_log_impl);
+
+ }
+
+ gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP,
+ -GUM_RED_ZONE_SIZE);
+ gum_x86_writer_put_push_reg(cw, GUM_REG_RDI);
+ gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RDI,
+ GUM_ADDRESS(instr->address));
+ gum_x86_writer_put_call_address(cw, range->current_log_impl);
+ gum_x86_writer_put_pop_reg(cw, GUM_REG_RDI);
+ gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP,
+ GUM_RED_ZONE_SIZE);
+#else
gum_stalker_iterator_put_callout(iterator, on_basic_block,
(gpointer)instr->address, NULL);
+#endif
begin = FALSE;
}
@@ -153,7 +238,7 @@ static int enumerate_ranges(const GumRangeDetails *details,
}
-int main() {
+int main(int argc, char **argv) {
#ifndef __APPLE__
(void)personality(ADDR_NO_RANDOMIZE); // disable ASLR
@@ -164,104 +249,147 @@ int main() {
// If there is just one function, then there is nothing to change
// or add here.
- void *dl = dlopen(TARGET_LIBRARY, RTLD_LAZY);
- if (!dl) {
+ void *dl = NULL;
+ if (argc > 2) {
- fprintf(stderr, "Could not load %s\n", TARGET_LIBRARY);
- exit(-1);
+ dl = dlopen(argv[1], RTLD_LAZY);
+
+ } else {
+
+ dl = dlopen(TARGET_LIBRARY, RTLD_LAZY);
}
- if (!(o_function = dlsym(dl, TARGET_FUNCTION))) {
+ if (!dl) {
- fprintf(stderr, "Could not find function %s\n", TARGET_FUNCTION);
+ if (argc > 2)
+ fprintf(stderr, "Could not load %s\n", argv[1]);
+ else
+ fprintf(stderr, "Could not load %s\n", TARGET_LIBRARY);
exit(-1);
}
- // END STEP 2
-
- gum_init_embedded();
- if (!gum_stalker_is_supported()) {
+ if (argc > 2)
+ o_function = dlsym(dl, argv[2]);
+ else
+ o_function = dlsym(dl, TARGET_FUNCTION);
+ if (!o_function) {
- gum_deinit_embedded();
- return 1;
+ if (argc > 2)
+ fprintf(stderr, "Could not find function %s\n", argv[2]);
+ else
+ fprintf(stderr, "Could not find function %s\n", TARGET_FUNCTION);
+ exit(-1);
}
- GumStalker *stalker = gum_stalker_new();
+ // END STEP 2
- GumAddress base_address = gum_module_find_base_address(TARGET_LIBRARY);
- GumMemoryRange code_range;
- gum_module_enumerate_ranges(TARGET_LIBRARY, GUM_PAGE_RX, enumerate_ranges,
- &code_range);
+ if (!getenv("AFL_FRIDA_TEST_INPUT")) {
- guint64 code_start = code_range.base_address;
- guint64 code_end = code_range.base_address + code_range.size;
- range_t instr_range = {0, code_start, code_end};
+ gum_init_embedded();
+ if (!gum_stalker_is_supported()) {
- printf("Frida instrumentation: base=0x%lx instrumenting=0x%lx-%lx\n",
- base_address, code_start, code_end);
- if (!code_start || !code_end) {
+ gum_deinit_embedded();
+ return 1;
- fprintf(stderr, "Error: no valid memory address found for %s\n",
- TARGET_LIBRARY);
- exit(-1);
+ }
- }
+ GumStalker *stalker = gum_stalker_new();
+
+ GumAddress base_address;
+ if (argc > 2)
+ base_address = gum_module_find_base_address(argv[1]);
+ else
+ base_address = gum_module_find_base_address(TARGET_LIBRARY);
+ GumMemoryRange code_range;
+ if (argc > 2)
+ gum_module_enumerate_ranges(argv[1], GUM_PAGE_RX, enumerate_ranges,
+ &code_range);
+ else
+ gum_module_enumerate_ranges(TARGET_LIBRARY, GUM_PAGE_RX, enumerate_ranges,
+ &code_range);
+
+ guint64 code_start = code_range.base_address;
+ guint64 code_end = code_range.base_address + code_range.size;
+ range_t instr_range = {0, code_start, code_end, 0, 0};
+
+ printf("Frida instrumentation: base=0x%lx instrumenting=0x%lx-%lx\n",
+ base_address, code_start, code_end);
+ if (!code_start || !code_end) {
+
+ if (argc > 2)
+ fprintf(stderr, "Error: no valid memory address found for %s\n",
+ argv[1]);
+ else
+ fprintf(stderr, "Error: no valid memory address found for %s\n",
+ TARGET_LIBRARY);
+ exit(-1);
+
+ }
- GumStalkerTransformer *transformer =
- gum_stalker_transformer_make_from_callback(instr_basic_block,
- &instr_range, NULL);
+ GumStalkerTransformer *transformer =
+ gum_stalker_transformer_make_from_callback(instr_basic_block,
+ &instr_range, NULL);
- // to ensure that the signatures are not optimized out
- memcpy(__afl_area_ptr, (void *)AFL_PERSISTENT, sizeof(AFL_PERSISTENT) + 1);
- memcpy(__afl_area_ptr + 32, (void *)AFL_DEFER_FORKSVR,
- sizeof(AFL_DEFER_FORKSVR) + 1);
- __afl_manual_init();
+ // to ensure that the signatures are not optimized out
+ memcpy(__afl_area_ptr, (void *)AFL_PERSISTENT, sizeof(AFL_PERSISTENT));
+ memcpy(__afl_area_ptr + 32, (void *)AFL_DEFER_FORKSVR,
+ sizeof(AFL_DEFER_FORKSVR));
+ __afl_manual_init();
- //
- // any expensive target library initialization that has to be done just once
- // - put that here
- //
+ //
+ // any expensive target library initialization that has to be done just once
+ // - put that here
+ //
- gum_stalker_follow_me(stalker, transformer, NULL);
+ gum_stalker_follow_me(stalker, transformer, NULL);
- while (__afl_persistent_loop(UINT32_MAX) != 0) {
+ while (__afl_persistent_loop(UINT32_MAX) != 0) {
- previous_pc = 0; // Required!
+ previous_pc = 0; // Required!
#ifdef _DEBUG
- fprintf(stderr, "CLIENT crc: %016llx len: %u\n",
- hash64(__afl_fuzz_ptr, *__afl_fuzz_len), *__afl_fuzz_len);
- fprintf(stderr, "RECV:");
- for (int i = 0; i < *__afl_fuzz_len; i++)
- fprintf(stderr, "%02x", __afl_fuzz_ptr[i]);
- fprintf(stderr, "\n");
+ fprintf(stderr, "CLIENT crc: %016llx len: %u\n",
+ hash64(__afl_fuzz_ptr, *__afl_fuzz_len), *__afl_fuzz_len);
+ fprintf(stderr, "RECV:");
+ for (int i = 0; i < *__afl_fuzz_len; i++)
+ fprintf(stderr, "%02x", __afl_fuzz_ptr[i]);
+ fprintf(stderr, "\n");
#endif
- // STEP 3: ensure the minimum length is present and setup the target
- // function to fuzz.
+ // STEP 3: ensure the minimum length is present and setup the target
+ // function to fuzz.
- if (*__afl_fuzz_len > 0) {
+ if (*__afl_fuzz_len > 0) {
- __afl_fuzz_ptr[*__afl_fuzz_len] = 0; // if you need to null terminate
- (*o_function)(__afl_fuzz_ptr, *__afl_fuzz_len);
+ __afl_fuzz_ptr[*__afl_fuzz_len] = 0; // if you need to null terminate
+ (*o_function)(__afl_fuzz_ptr, *__afl_fuzz_len);
+
+ }
+
+ // END STEP 3
}
- // END STEP 3
+ gum_stalker_unfollow_me(stalker);
- }
+ while (gum_stalker_garbage_collect(stalker))
+ g_usleep(10000);
- gum_stalker_unfollow_me(stalker);
+ g_object_unref(stalker);
+ g_object_unref(transformer);
+ gum_deinit_embedded();
+
+ } else {
- while (gum_stalker_garbage_collect(stalker))
- g_usleep(10000);
+ char buf[8 * 1024] = {0};
+ int count = read(0, buf, sizeof(buf));
+ buf[8 * 1024 - 1] = '\0';
+ (*o_function)(buf, count);
- g_object_unref(stalker);
- g_object_unref(transformer);
- gum_deinit_embedded();
+ }
return 0;
diff --git a/utils/afl_frida/android/README.md b/utils/afl_frida/android/README.md
new file mode 100644
index 00000000..044b48a1
--- /dev/null
+++ b/utils/afl_frida/android/README.md
@@ -0,0 +1 @@
+For android, frida-gum package (ex. https://github.com/frida/frida/releases/download/14.2.6/frida-gum-devkit-14.2.6-android-arm64.tar.xz) is needed to be extracted in the directory.
diff --git a/utils/afl_frida/android/frida-gum-example.c b/utils/afl_frida/android/frida-gum-example.c
new file mode 100644
index 00000000..14d98248
--- /dev/null
+++ b/utils/afl_frida/android/frida-gum-example.c
@@ -0,0 +1,130 @@
+/*
+ * Compile with:
+ *
+ * clang -fPIC -DANDROID -ffunction-sections -fdata-sections -Os -pipe -g3 frida-gum-example.c -o frida-gum-example -L. -lfrida-gum -llog -ldl -lm -pthread -Wl,--gc-sections,-z,noexecstack,-z,relro,-z,now -fuse-ld=gold -fuse-ld=gold -Wl,--icf=all
+ *
+ * Visit https://frida.re to learn more about Frida.
+ */
+
+#include "frida-gum.h"
+
+#include <fcntl.h>
+#include <unistd.h>
+
+typedef struct _ExampleListener ExampleListener;
+typedef enum _ExampleHookId ExampleHookId;
+
+struct _ExampleListener
+{
+ GObject parent;
+
+ guint num_calls;
+};
+
+enum _ExampleHookId
+{
+ EXAMPLE_HOOK_OPEN,
+ EXAMPLE_HOOK_CLOSE
+};
+
+static void example_listener_iface_init (gpointer g_iface, gpointer iface_data);
+
+#define EXAMPLE_TYPE_LISTENER (example_listener_get_type ())
+G_DECLARE_FINAL_TYPE (ExampleListener, example_listener, EXAMPLE, LISTENER, GObject)
+G_DEFINE_TYPE_EXTENDED (ExampleListener,
+ example_listener,
+ G_TYPE_OBJECT,
+ 0,
+ G_IMPLEMENT_INTERFACE (GUM_TYPE_INVOCATION_LISTENER,
+ example_listener_iface_init))
+
+int
+main (int argc,
+ char * argv[])
+{
+ GumInterceptor * interceptor;
+ GumInvocationListener * listener;
+
+ gum_init_embedded ();
+
+ interceptor = gum_interceptor_obtain ();
+ listener = g_object_new (EXAMPLE_TYPE_LISTENER, NULL);
+
+ gum_interceptor_begin_transaction (interceptor);
+ gum_interceptor_attach (interceptor,
+ GSIZE_TO_POINTER (gum_module_find_export_by_name (NULL, "open")),
+ listener,
+ GSIZE_TO_POINTER (EXAMPLE_HOOK_OPEN));
+ gum_interceptor_attach (interceptor,
+ GSIZE_TO_POINTER (gum_module_find_export_by_name (NULL, "close")),
+ listener,
+ GSIZE_TO_POINTER (EXAMPLE_HOOK_CLOSE));
+ gum_interceptor_end_transaction (interceptor);
+
+ close (open ("/etc/hosts", O_RDONLY));
+ close (open ("/etc/fstab", O_RDONLY));
+
+ g_print ("[*] listener got %u calls\n", EXAMPLE_LISTENER (listener)->num_calls);
+
+ gum_interceptor_detach (interceptor, listener);
+
+ close (open ("/etc/hosts", O_RDONLY));
+ close (open ("/etc/fstab", O_RDONLY));
+
+ g_print ("[*] listener still has %u calls\n", EXAMPLE_LISTENER (listener)->num_calls);
+
+ g_object_unref (listener);
+ g_object_unref (interceptor);
+
+ gum_deinit_embedded ();
+
+ return 0;
+}
+
+static void
+example_listener_on_enter (GumInvocationListener * listener,
+ GumInvocationContext * ic)
+{
+ ExampleListener * self = EXAMPLE_LISTENER (listener);
+ ExampleHookId hook_id = GUM_IC_GET_FUNC_DATA (ic, ExampleHookId);
+
+ switch (hook_id)
+ {
+ case EXAMPLE_HOOK_OPEN:
+ g_print ("[*] open(\"%s\")\n", (const gchar *) gum_invocation_context_get_nth_argument (ic, 0));
+ break;
+ case EXAMPLE_HOOK_CLOSE:
+ g_print ("[*] close(%d)\n", GPOINTER_TO_INT (gum_invocation_context_get_nth_argument (ic, 0)));
+ break;
+ }
+
+ self->num_calls++;
+}
+
+static void
+example_listener_on_leave (GumInvocationListener * listener,
+ GumInvocationContext * ic)
+{
+}
+
+static void
+example_listener_class_init (ExampleListenerClass * klass)
+{
+ (void) EXAMPLE_IS_LISTENER;
+ (void) glib_autoptr_cleanup_ExampleListener;
+}
+
+static void
+example_listener_iface_init (gpointer g_iface,
+ gpointer iface_data)
+{
+ GumInvocationListenerInterface * iface = g_iface;
+
+ iface->on_enter = example_listener_on_enter;
+ iface->on_leave = example_listener_on_leave;
+}
+
+static void
+example_listener_init (ExampleListener * self)
+{
+}