AFLplusplus: Patch out of range in frida mode

I build the AFL++ to use frida mode in Android phone pixel 5

COMMAND: AFL_DEBUG=1 AFL_DEBUG_CHILD=1 ./afl-fuzz -O -G 256 -i inF -o outF ./fuzz

The following error : `
[+] Enabled environment variable AFL_DEBUG with value 1 [+] Enabled environment variable AFL_DEBUG with value 1 [+] Enabled environment variable AFL_DEBUG_CHILD with value 1 afl-fuzz++4.06c based on afl by Michal Zalewski and a large online community [+] afl++ is maintained by Marc “van Hauser” Heuse, Heiko “hexcoder” Eißfeldt, Andrea Fioraldi and Dominik Maier [+] afl++ is open source, get it at https://github.com/AFLplusplus/AFLplusplus [+] NOTE: afl++ >= v3 has changed defaults and behaviours - see README.md [+] No -M/-S set, autoconfiguring for “-S default” [] Getting to work… [+] Using exponential power schedule (FAST) [+] Enabled testcache with 50 MB [+] Generating fuzz data with a length of min=1 max=256 [] Checking core_pattern… [] Checking CPU scaling governor… [+] Injecting ./afl-frida-trace.so … [+] You have 8 CPU cores and 3 runnable tasks (utilization: 38%). [+] Try parallel jobs - see docs/fuzzing_in_depth.md#c-using-multiple-cores [] Setting up output directories… [+] Output directory exists but deemed OK to reuse. [] Deleting old session data… [+] Output dir cleanup successful. [] Checking CPU core loadout… [+] Found a free CPU core, try binding to #7. [] Scanning ‘inF’… [+] Loaded a total of 1 seeds. [] Creating hard links for all input files… [] Validating target binary… [+] Deferred forkserver binary detected. [] No auto-generated dictionary tokens to reuse. [] Attempting dry run with ‘id:000000,time:0,execs:0,orig:sample.bin’… [] Spinning up the fork server… DEBUG: debug enabled DEBUG: (1) id_str 9, __afl_area_ptr 0x7f16b1a4e0, __afl_area_initial 0x7f16b1a4e0, __afl_area_ptr_dummy 0x7f16b1a4e0, __afl_map_addr 0x0, MAP_SIZE 65536, __afl_final_loc 0, __afl_map_size 65536, max_size_forkserver 8388608/0x800000 DEBUG: (2) id_str 9, __afl_area_ptr 0x7f18a74000, __afl_area_initial 0x7f16b1a4e0, __afl_area_ptr_dummy 0x7f16b1a4e0, __afl_map_addr 0x0, MAP_SIZE 65536, __afl_final_loc 0, __afl_map_size 65536, max_size_forkserver 8388608/0x800000 DEBUG: cmplog id_str <null> DEBUG: debug enabled DEBUG: (1) id_str 9, __afl_area_ptr 0x7ff1c5c4e0, __afl_area_initial 0x7ff1c5c4e0, __afl_area_ptr_dummy 0x7ff1c5c4e0, __afl_map_addr 0x0, MAP_SIZE 65536, __afl_final_loc 0, __afl_map_size 65536, max_size_forkserver 8388608/0x800000 DEBUG: (2) id_str 9, __afl_area_ptr 0x7ff6bfc000, __afl_area_initial 0x7ff1c5c4e0, __afl_area_ptr_dummy 0x7ff1c5c4e0, __afl_map_addr 0x0, MAP_SIZE 65536, __afl_final_loc 0, __afl_map_size 65536, max_size_forkserver 8388608/0x800000 DEBUG: cmplog id_str <null> [F] ********************** [F] * ****************** * [F] * * ************** * * [F] * * * FRIDA MODE * * * [F] * * ************** * * [F] * ****************** * [F] ********************** [F] Javascript - script: [/data/local/tmp/afl.js] [F] Javascript - size: 762 bytes [] Starting FRIDA config for PID: 6082 [] Starting FRIDA config for PID: 0x555555688c [F] Output - stdout: [ ] [F] Output - stderr: [ ] [F] Instrumentation - optimize: [X] [F] Instrumentation - tracing: [ ] [F] Instrumentation - unique: [ ] [F] Instrumentation - fixed seed: [ ] [0x0000000000000000] [F] Instrumentation - unstable coverage: [ ] [F] Instrumentation - instructions: [ ] [F] Instrumentation - suppression: [X] [F] Instrumentation - seed: [0x000017e82c860671] [F] Instrumentation - regs: [ ] [F] Instrumentation - asan: [ ] [F] Instrumentation - cmplog: [ ] [F] Instrumentation - coverage: [ ] [F] Instrumentation - unstable coverage: [ ] [F] Instrumentation - debugging: [ ] [F] Module - [X] [F] Instrumentation - persistent mode: [X] (0x000000555555688C) [F] Instrumentation - persistent count: [X] (0) [F] Instrumentation - hook: [(null)] [F] Instrumentation - persistent ret: [ ] (0x0000000000000000) [F] Instrumentation - prefetch: [X] [F] Instrumentation - prefetch_backpatch: [X] [F] Seccomp - file: [ ] [F] Stalker - backpatch: [X] [F] Stalker - ic_entries: [32] [F] Stalker - adjacent_blocks: [32] [F] Ranges - instrument jit: [ ] [F] Ranges - instrument libraries: [ ] [F] Stats - file: [ ] [F] Stats - interval: [10]

[-] PROGRAM ABORT : Patch out of range 0x0000007D5B07A644->0x0000007FF6BFC000 = 0x000000029BB82000 Location : instrument_patch_ardp(), /opt/AFLplusplus-4.06c/frida_mode/src/instrument/instrument_arm64.c:278

[-] Hmm, looks like the target binary terminated before we could complete a handshake with the injected code. You can try the following:

- The target binary crashes because necessary runtime conditions it needs
  are not met. Try to:
  1. Run again with AFL_DEBUG=1 set and check the output of the target
     binary for clues.
  2. Run again with AFL_DEBUG=1 and 'ulimit -c unlimited' and analyze the
     generated core dump.

- Possibly the target requires a huge coverage map and has CTORS.
  Retry with setting AFL_MAP_SIZE=10000000.

Otherwise there is a horrible bug in the fuzzer. Poke afl-users@googlegroups.com for troubleshooting tips.

[-] PROGRAM ABORT : Fork server handshake failed Location : afl_fsrv_start(), /opt/AFLplusplus-4.06c/src/afl-forkserver.c:1385 `


The afl.js file as follow:

Afl.print([*] Starting FRIDA config for PID: ${Process.id}`);

const cm = new CModule(` #include <string.h> #include <gum/gumdefs.h>

#define BUF_LEN 256

void afl_persistent_hook(GumCpuContext *regs, uint8_t *input_buf, uint32_t input_buf_len) {

uint32_t length = (input_buf_len > BUF_LEN) ? BUF_LEN : input_buf_len;
memcpy((void *)regs->x[0], input_buf, length);
regs->x[1] = length;

} `, { memcpy: Module.getExportByName(null, “memcpy”) } );

const pStartAddr = DebugSymbol.fromName(“fuzz_one_input”).address;

Afl.setPersistentHook(cm.afl_persistent_hook); Afl.setPersistentAddress(pStartAddr); Afl.setEntryPoint(pStartAddr); Afl.setInMemoryFuzzing(); Afl.setInstrumentLibraries();

Afl.done(); Afl.print(“[*] All done!”);

`


The harrness is as follow: NOTE: _Z6fuzzMePKai function is just to test the fuzzer

` #include <errno.h> #include <stdint.h> #include <stdio.h>

#define BUFFER_SIZE 256

/* Target function / extern void _Z6fuzzMePKai(const uint8_t, uint64_t);

/* Persistent loop */ void fuzz_one_input(const uint8_t *buf, int len) { _Z6fuzzMePKai(buf, len); }

int main(void) { const uint8_t buffer[BUFFER_SIZE];

ssize_t rlength = fread((void*) buffer, 1, BUFFER_SIZE, stdin); if (rlength == -1) return errno;

fuzz_one_input(buffer, rlength);

return 0; }

`

I was trying with this blogpost from quarkslab: https://blog.quarkslab.com/android-greybox-fuzzing-with-afl-frida-mode.html

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Comments: 17 (14 by maintainers)

Most upvoted comments

I don’t think so, but it might be useful if you could test a branch with the fix before it is merged.

When stalker instruments each basic block, we need to add some inline assembly code to update the coverage map (a minor variation of lcamtuf’s original algorithm).

cur_location = (block_address >> 4) ^ (block_address << 8);
shared_mem[cur_location ^ prev_location]++;
prev_location = cur_location >> 1;

This code needs to access the shared_mem array as well as be able to read and store prev_location. Accordingly, the inline assembly must be able to read and write data there. Obviously given that this snippet of assembly is run on every basic block, it is hugely performance critical. In the default case (which is what was causing the issues you encountered), we align these data structures on a 4Kb boundary, and then use the AARCH64 instruction adrp which allows you to load any address which is 4Kb aligned, provided it is within 4Gb of the instruction itself.

I made the assumption that this would always be plenty of range, but it turns out this was incorrect. Therefore, rather than panicing when encountering an address which is out of range, I changed the implementation to instead write an alternatve (but equivalent) instrumentation at the start of each block. This form, includes the required address inline in the code (and uses the b instruction to skip over them), it can then use the ldr/str instructions as necessary to access this data. It is similar to how GCC generates position independent code.