Merge branch 'dev' into docs_edit_readme_fix_links

This commit is contained in:
Dominik Maier 2021-10-18 13:38:46 +02:00
commit edaa25a48c
34 changed files with 419 additions and 382 deletions

@ -1 +1 @@
Subproject commit eedf07ddb0fb1f437f5e76b77cfd4064cf6a5d63
Subproject commit b79d51a8daccbd7a693f9b6765c81ead14f28e26

View File

@ -16,11 +16,16 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
- fix a regression introduced in 3.10 that resulted in less
coverage being detected. thanks to Collin May for reporting!
- fix -n dumb mode (nobody should use this)
- fix stability issue with LTO and cmplog
- better banner
- frida_mode: David Carlier added Android support :)
- afl-showmap, afl-tmin and afl-analyze now honor persistent mode
for more speed. thanks to dloffre-snl for reporting!
- Prevent accidently killing non-afl/fuzz services when aborting
afl-showmap and other tools.
- afl-cc:
- fix for shared linking on MacOS
- llvm and LTO mode verified to work with new llvm 14-dev
- llvm and LTO mode modified to work with new llvm 14-dev (again)
- added the very good grammar mutator "GramaTron" to the
custom_mutators
- added optimin, a faster and better corpus minimizer by
@ -32,6 +37,7 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
- fix AFL_PRELOAD issues on MacOS
- removed utils/afl_frida because frida_mode/ is now so much better
- added uninstall target to makefile (todo: update new readme!)
- removed indirections in rust callbacks for unicornafl
### Version ++3.14c (release)

View File

@ -1,87 +0,0 @@
# AFL "Life Pro Tips"
Bite-sized advice for those who understand the basics, but can't be bothered
to read or memorize every other piece of documentation for AFL.
## Get more bang for your buck by using fuzzing dictionaries.
See [dictionaries/README.md](../dictionaries/README.md) to learn how.
## You can get the most out of your hardware by parallelizing AFL jobs.
See [parallel_fuzzing.md](parallel_fuzzing.md) for step-by-step tips.
## Improve the odds of spotting memory corruption bugs with libdislocator.so!
It's easy. Consult [utils/libdislocator/README.md](../utils/libdislocator/README.md) for usage tips.
## Want to understand how your target parses a particular input file?
Try the bundled `afl-analyze` tool; it's got colors and all!
## You can visually monitor the progress of your fuzzing jobs.
Run the bundled `afl-plot` utility to generate browser-friendly graphs.
## Need to monitor AFL jobs programmatically?
Check out the `fuzzer_stats` file in the AFL output dir or try `afl-whatsup`.
## Puzzled by something showing up in red or purple in the AFL UI?
It could be important - consult [status_screen.md](status_screen.md) right away!
## Know your target? Convert it to persistent mode for a huge performance gain!
Consult section #5 in [instrumentation/README.llvm.md](../instrumentation/README.llvm.md) for tips.
## Using clang?
Check out [instrumentation/](../instrumentation/) for a faster alternative to afl-gcc!
## Did you know that AFL can fuzz closed-source or cross-platform binaries?
Check out [qemu_mode/README.md](../qemu_mode/README.md) and [unicorn_mode/README.md](../unicorn_mode/README.md) for more.
## Did you know that afl-fuzz can minimize any test case for you?
Try the bundled `afl-tmin` tool - and get small repro files fast!
## Not sure if a crash is exploitable? AFL can help you figure it out. Specify
`-C` to enable the peruvian were-rabbit mode.
## Trouble dealing with a machine uprising? Relax, we've all been there.
Find essential survival tips at [http://lcamtuf.coredump.cx/prep/](http://lcamtuf.coredump.cx/prep/).
## Want to automatically spot non-crashing memory handling bugs?
Try running an AFL-generated corpus through ASAN, MSAN, or Valgrind.
## Good selection of input files is critical to a successful fuzzing job.
See [perf_tips.md](perf_tips.md) for pro tips.
## You can improve the odds of automatically spotting stack corruption issues.
Specify `AFL_HARDEN=1` in the environment to enable hardening flags.
## Bumping into problems with non-reproducible crashes?
It happens, but usually
isn't hard to diagnose. See section #7 in README.md for tips.
## Fuzzing is not just about memory corruption issues in the codebase.
Add some
sanity-checking `assert()` / `abort()` statements to effortlessly catch logic bugs.
## Hey kid... pssst... want to figure out how AFL really works?
Check out [technical_details.md](technical_details.md) for all the gory details in one place!
## There's a ton of third-party helper tools designed to work with AFL!
Be sure to check out [sister_projects.md](sister_projects.md) before writing your own.
## Need to fuzz the command-line arguments of a particular program?
You can find a simple solution in [utils/argv_fuzzing](../utils/argv_fuzzing/).
## Attacking a format that uses checksums?
Remove the checksum-checking code or use a postprocessor!
See `afl_custom_post_process` in [custom_mutators/examples/example.c](../custom_mutators/examples/example.c) for more.

View File

@ -30,8 +30,7 @@ AFL_CFLAGS:=-Wno-unused-parameter \
LDFLAGS+=-shared \
-lpthread \
-lresolv \
-ldl
-lresolv
ifdef DEBUG
CFLAGS+=-Werror \
@ -71,7 +70,9 @@ ifdef DEBUG
endif
LDFLAGS+= -z noexecstack \
-Wl,--gc-sections \
-Wl,--exclude-libs,ALL
-Wl,--exclude-libs,ALL \
-ldl \
-lrt
LDSCRIPT:=-Wl,--version-script=$(PWD)frida.map
endif
@ -79,6 +80,22 @@ ifeq "$(shell uname)" "Linux"
OS:=linux
endif
ifneq "$(findstring android, $(shell $(CC) --version 2>/dev/null))" ""
OS:=android
ifneq "$(findstring aarch64, $(shell $(CC) --version 2>/dev/null))" ""
ARCH:=arm64
endif
ifneq "$(findstring arm, $(shell $(CC) --version 2>/dev/null))" ""
ARCH:=arm
endif
ifneq "$(findstring x86_64, $(shell $(CC) --version 2>/dev/null))" ""
ARCH:=x86_64
endif
ifneq "$(findstring i686, $(shell $(CC) --version 2>/dev/null))" ""
ARCH:=x86
endif
endif
ifndef OS
$(error "Operating system unsupported")
endif

View File

@ -55,6 +55,20 @@ tests in 32-bit mode, run `make ARCH=x86 frida`. When switching between
architectures it may be necessary to run `make clean` first for a given build
target to remove previously generated binaries for a different architecture.
### Android
In order to build, you need to download the Android SDK.
```
https://developer.android.com/ndk/downloads
```
Then creating locally a standalone chain as follow.
```
https://developer.android.com/ndk/guides/standalone_toolchain
```
## Usage
FRIDA mode added some small modifications to `afl-fuzz` and similar tools

View File

@ -29,6 +29,7 @@ GumStalkerTransformer *instrument_get_transformer(void);
/* Functions to be implemented by the different architectures */
gboolean instrument_is_coverage_optimize_supported(void);
void instrument_coverage_optimize_init(void);
void instrument_coverage_optimize(const cs_insn * instr,
GumStalkerOutput *output);

View File

@ -10,6 +10,8 @@ extern gboolean ranges_inst_jit;
void ranges_config(void);
void ranges_init(void);
void ranges_print_debug_maps(void);
gboolean range_is_excluded(GumAddress address);
void ranges_exclude();

View File

@ -356,6 +356,7 @@ void instrument_init(void) {
instrument_hash_seed);
instrument_hash_zero = instrument_get_offset_hash(0);
instrument_coverage_optimize_init();
instrument_debug_init();
instrument_coverage_init();
asan_init();

View File

@ -22,6 +22,10 @@ void instrument_coverage_optimize(const cs_insn * instr,
}
void instrument_coverage_optimize_init(void) {
WARNF("Optimized coverage not supported on this architecture");
}
void instrument_flush(GumStalkerOutput *output) {
gum_arm_writer_flush(output->writer.arm);

View File

@ -95,6 +95,9 @@ void instrument_coverage_optimize(const cs_insn * instr,
}
void instrument_coverage_optimize_init(void) {
}
void instrument_flush(GumStalkerOutput *output) {
gum_arm64_writer_flush(output->writer.arm64);

View File

@ -1,4 +1,16 @@
#include <fcntl.h>
#include <stddef.h>
#include <sys/mman.h>
#include <sys/shm.h>
#if defined(__linux__)
#if !defined(__ANDROID__)
#include <asm/prctl.h>
#include <sys/syscall.h>
#else
#include <linux/ashmem.h>
#endif
#endif
#include "frida-gumjs.h"
@ -6,125 +18,17 @@
#include "debug.h"
#include "instrument.h"
#include "ranges.h"
#if defined(__x86_64__)
static GumAddress current_log_impl = GUM_ADDRESS(0);
#pragma pack(push, 1)
typedef struct {
/*
* pushfq
* push rdx
* mov rdx, [&previouspc] (rip relative addr)
* xor rdx, rdi (current_pc)
* shr rdi. 1
* mov [&previouspc], rdi
* lea rsi, [&_afl_area_ptr] (rip relative)
* add rdx, rsi
* add byte ptr [rdx], 1
* adc byte ptr [rdx], 0
* pop rdx
* popfq
*/
uint8_t push_fq;
uint8_t push_rdx;
uint8_t mov_rdx_rip_off[7];
uint8_t xor_rdx_rdi[3];
uint8_t shr_rdi[3];
uint8_t mov_rip_off_rdi[7];
uint8_t lea_rdi_rip_off[7];
uint8_t add_rdx_rdi[3];
uint8_t add_byte_ptr_rdx[3];
uint8_t adc_byte_ptr_rdx[3];
uint8_t pop_rdx;
uint8_t pop_fq;
uint8_t ret;
} afl_log_code_asm_t;
#pragma pack(pop)
#pragma pack(push, 8)
typedef struct {
afl_log_code_asm_t assembly;
uint64_t current_pc;
} afl_log_code_t;
#pragma pack(pop)
typedef union {
afl_log_code_t data;
uint8_t bytes[0];
} afl_log_code;
static const afl_log_code_asm_t template = {
.push_fq = 0x9c,
.push_rdx = 0x52,
.mov_rdx_rip_off =
{
0x48, 0x8b, 0x15,
/* TBC */
},
.xor_rdx_rdi =
{
0x48,
0x31,
0xfa,
},
.shr_rdi = {0x48, 0xd1, 0xef},
.mov_rip_off_rdi = {0x48, 0x89, 0x3d},
.lea_rdi_rip_off =
{
0x48,
0x8d,
0x3d,
},
.add_rdx_rdi = {0x48, 0x01, 0xfA},
.add_byte_ptr_rdx =
{
0x80,
0x02,
0x01,
},
.adc_byte_ptr_rdx =
{
0x80,
0x12,
0x00,
},
.pop_rdx = 0x5a,
.pop_fq = 0x9d,
.ret = 0xc3};
static guint8 align_pad[] = {0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90};
#ifndef MAP_FIXED_NOREPLACE
#ifdef MAP_EXCL
#define MAP_FIXED_NOREPLACE MAP_EXCL | MAP_FIXED
#else
#define MAP_FIXED_NOREPLACE MAP_FIXED
#endif
#endif
gboolean instrument_is_coverage_optimize_supported(void) {
@ -138,113 +42,266 @@ static gboolean instrument_coverage_in_range(gssize offset) {
}
static void instrument_coverate_write_function(GumStalkerOutput *output) {
#pragma pack(push, 1)
typedef struct {
guint64 misalign = 0;
GumX86Writer *cw = output->writer.x86;
GumAddress code_addr = 0;
afl_log_code code = {0};
/*guint64 instrument_hash_zero = 0;*/
// cur_location = (block_address >> 4) ^ (block_address << 8);
// shared_mem[cur_location ^ prev_location]++;
// prev_location = cur_location >> 1;
if (current_log_impl == 0 ||
!gum_x86_writer_can_branch_directly_between(cw->pc, current_log_impl) ||
!gum_x86_writer_can_branch_directly_between(cw->pc + 128,
current_log_impl)) {
// => 0x7ffff6cfb086: lea rsp,[rsp-0x80]
// 0x7ffff6cfb08b: pushf
// 0x7ffff6cfb08c: push rsi
// 0x7ffff6cfb08d: mov rsi,0x228
// 0x7ffff6cfb094: xchg QWORD PTR [rip+0x3136a5],rsi # 0x7ffff700e740
// 0x7ffff6cfb09b: xor rsi,0x451
// 0x7ffff6cfb0a2: add BYTE PTR [rsi+0x10000],0x1
// 0x7ffff6cfb0a9: adc BYTE PTR [rsi+0x10000],0x0
// 0x7ffff6cfb0b0: pop rsi
// 0x7ffff6cfb0b1: popf
// 0x7ffff6cfb0b2: lea rsp,[rsp+0x80]
gconstpointer after_log_impl = cw->code + 1;
gum_x86_writer_put_jmp_near_label(cw, after_log_impl);
uint8_t lea_rsp_rsp_sub_rz[5];
uint8_t push_fq;
uint8_t push_rsi;
misalign = (cw->pc & 0x7);
if (misalign != 0) {
uint8_t mov_rsi_curr_loc_shr_1[7];
uint8_t xchg_rsi_prev_loc_curr_loc[7];
uint8_t xor_rsi_curr_loc[7];
gum_x86_writer_put_bytes(cw, align_pad, 8 - misalign);
uint8_t add_rsi_1[7];
uint8_t adc_rsi_0[7];
}
uint8_t pop_rsi;
uint8_t pop_fq;
uint8_t lsa_rsp_rsp_add_rz[8];
current_log_impl = cw->pc;
// gum_x86_writer_put_breakpoint(cw);
code_addr = cw->pc;
} afl_log_code_asm_t;
code.data.assembly = template;
code.data.current_pc = instrument_get_offset_hash(0);
#pragma pack(pop)
gssize current_pc_value1 =
GPOINTER_TO_SIZE(&instrument_previous_pc) -
(code_addr + offsetof(afl_log_code, data.assembly.mov_rdx_rip_off) +
sizeof(code.data.assembly.mov_rdx_rip_off));
gssize patch_offset1 =
offsetof(afl_log_code, data.assembly.mov_rdx_rip_off) +
sizeof(code.data.assembly.mov_rdx_rip_off) - sizeof(gint);
if (!instrument_coverage_in_range(current_pc_value1)) {
typedef union {
FATAL("Patch out of range (current_pc_value1): 0x%016lX",
current_pc_value1);
afl_log_code_asm_t code;
uint8_t bytes[0];
}
} afl_log_code;
gint *dst_pc_value = (gint *)&code.bytes[patch_offset1];
*dst_pc_value = (gint)current_pc_value1;
static const afl_log_code_asm_t template =
{
gssize current_pc_value2 =
GPOINTER_TO_SIZE(&instrument_previous_pc) -
(code_addr + offsetof(afl_log_code, data.assembly.mov_rip_off_rdi) +
sizeof(code.data.assembly.mov_rip_off_rdi));
gssize patch_offset2 =
offsetof(afl_log_code, data.assembly.mov_rip_off_rdi) +
sizeof(code.data.assembly.mov_rip_off_rdi) - sizeof(gint);
.lea_rsp_rsp_sub_rz = {0x48, 0x8D, 0x64, 0x24, 0x80},
.push_fq = 0x9c,
.push_rsi = 0x56,
if (!instrument_coverage_in_range(current_pc_value2)) {
.mov_rsi_curr_loc_shr_1 = {0x48, 0xC7, 0xC6},
.xchg_rsi_prev_loc_curr_loc = {0x48, 0x87, 0x35},
.xor_rsi_curr_loc = {0x48, 0x81, 0xF6},
FATAL("Patch out of range (current_pc_value2): 0x%016lX",
current_pc_value2);
.add_rsi_1 = {0x80, 0x86, 0x00, 0x00, 0x00, 0x00, 0x01},
.adc_rsi_0 = {0x80, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00},
}
.pop_rsi = 0x5E,
.pop_fq = 0x9D,
.lsa_rsp_rsp_add_rz = {0x48, 0x8D, 0xA4, 0x24, 0x80, 0x00, 0x00, 0x00},
dst_pc_value = (gint *)&code.bytes[patch_offset2];
*dst_pc_value = (gint)current_pc_value2;
}
gsize afl_area_ptr_value =
GPOINTER_TO_SIZE(__afl_area_ptr) -
(code_addr + offsetof(afl_log_code, data.assembly.lea_rdi_rip_off) +
sizeof(code.data.assembly.lea_rdi_rip_off));
gssize afl_area_ptr_offset =
offsetof(afl_log_code, data.assembly.lea_rdi_rip_off) +
sizeof(code.data.assembly.lea_rdi_rip_off) - sizeof(gint);
;
if (!instrument_coverage_in_range(afl_area_ptr_value)) {
static gboolean instrument_coverage_find_low(const GumRangeDetails *details,
gpointer user_data) {
FATAL("Patch out of range (afl_area_ptr_value): 0x%016lX",
afl_area_ptr_value);
static GumAddress last_limit = (64ULL << 10);
gpointer * address = (gpointer *)user_data;
}
if ((details->range->base_address - last_limit) > __afl_map_size) {
gint *dst_afl_area_ptr_value = (gint *)&code.bytes[afl_area_ptr_offset];
*dst_afl_area_ptr_value = (gint)afl_area_ptr_value;
gum_x86_writer_put_bytes(cw, code.bytes, sizeof(afl_log_code));
gum_x86_writer_put_label(cw, after_log_impl);
*address = GSIZE_TO_POINTER(last_limit);
return FALSE;
}
if (details->range->base_address > ((2ULL << 20) - __afl_map_size)) {
return FALSE;
}
last_limit = details->range->base_address + details->range->size;
return TRUE;
}
static void instrument_coverage_optimize_map_mmap_anon(gpointer address) {
__afl_area_ptr =
mmap(address, __afl_map_size, PROT_READ | PROT_WRITE,
MAP_FIXED_NOREPLACE | MAP_SHARED | MAP_ANONYMOUS, -1, 0);
if (__afl_area_ptr != address) {
FATAL("Failed to map mmap __afl_area_ptr: %d", errno);
}
}
static void instrument_coverage_optimize_map_mmap(char * shm_file_path,
gpointer address) {
int shm_fd = -1;
if (munmap(__afl_area_ptr, __afl_map_size) != 0) {
FATAL("Failed to unmap previous __afl_area_ptr");
}
__afl_area_ptr = NULL;
#if !defined(__ANDROID__)
shm_fd = shm_open(shm_file_path, O_RDWR, DEFAULT_PERMISSION);
if (shm_fd == -1) { FATAL("shm_open() failed\n"); }
#else
shm_fd = open("/dev/ashmem", O_RDWR);
if (shm_fd == -1) { FATAL("open() failed\n"); }
if (ioctl(shm_fd, ASHMEM_SET_NAME, shm_file_path) == -1) { FATAL("ioctl(ASHMEM_SET_NAME) failed"); }
if (ioctl(shm_fd, ASHMEM_SET_SIZE, __afl_map_size) == -1) { FATAL("ioctl(ASHMEM_SET_SIZE) failed"); }
#endif
__afl_area_ptr = mmap(address, __afl_map_size, PROT_READ | PROT_WRITE,
MAP_FIXED_NOREPLACE | MAP_SHARED, shm_fd, 0);
if (__afl_area_ptr != address) {
FATAL("Failed to map mmap __afl_area_ptr: %d", errno);
}
if (close(shm_fd) != 0) { FATAL("Failed to close shm_fd"); }
}
static void instrument_coverage_optimize_map_shm(guint64 shm_env_val,
gpointer address) {
if (shmdt(__afl_area_ptr) != 0) {
FATAL("Failed to detach previous __afl_area_ptr");
}
__afl_area_ptr = shmat(shm_env_val, address, 0);
if (__afl_area_ptr != address) {
FATAL("Failed to map shm __afl_area_ptr: %d", errno);
}
}
void instrument_coverage_optimize_init(void) {
gpointer low_address = NULL;
gum_process_enumerate_ranges(GUM_PAGE_NO_ACCESS, instrument_coverage_find_low,
&low_address);
OKF("Low address: %p", low_address);
if (low_address == 0 ||
GPOINTER_TO_SIZE(low_address) > ((2UL << 20) - __afl_map_size)) {
FATAL("Invalid low_address: %p", low_address);
}
ranges_print_debug_maps();
char *shm_env = getenv(SHM_ENV_VAR);
OKF("SHM_ENV_VAR: %s", shm_env);
if (shm_env == NULL) {
WARNF("SHM_ENV_VAR not set, using anonymous map for debugging purposes");
instrument_coverage_optimize_map_mmap_anon(low_address);
} else {
guint64 shm_env_val = g_ascii_strtoull(shm_env, NULL, 10);
if (shm_env_val == 0) {
instrument_coverage_optimize_map_mmap(shm_env, low_address);
} else {
instrument_coverage_optimize_map_shm(shm_env_val, low_address);
}
}
OKF("__afl_area_ptr: %p", __afl_area_ptr);
OKF("instrument_previous_pc: %p", &instrument_previous_pc);
}
void instrument_coverage_optimize(const cs_insn * instr,
GumStalkerOutput *output) {
afl_log_code code = {0};
GumX86Writer *cw = output->writer.x86;
guint64 area_offset = instrument_get_offset_hash(GUM_ADDRESS(instr->address));
instrument_coverate_write_function(output);
GumAddress code_addr = 0;
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, area_offset);
gum_x86_writer_put_call_address(cw, 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);
// gum_x86_writer_put_breakpoint(cw);
code_addr = cw->pc;
code.code = template;
gssize curr_loc_shr_1_offset =
offsetof(afl_log_code, code.mov_rsi_curr_loc_shr_1) +
sizeof(code.code.mov_rsi_curr_loc_shr_1) - sizeof(guint32);
*((guint32 *)&code.bytes[curr_loc_shr_1_offset]) =
(guint32)(area_offset >> 1);
gssize prev_loc_value =
GPOINTER_TO_SIZE(&instrument_previous_pc) -
(code_addr + offsetof(afl_log_code, code.xchg_rsi_prev_loc_curr_loc) +
sizeof(code.code.xchg_rsi_prev_loc_curr_loc));
gssize prev_loc_value_offset =
offsetof(afl_log_code, code.xchg_rsi_prev_loc_curr_loc) +
sizeof(code.code.xchg_rsi_prev_loc_curr_loc) - sizeof(gint);
if (!instrument_coverage_in_range(prev_loc_value)) {
FATAL("Patch out of range (current_pc_value1): 0x%016lX", prev_loc_value);
}
*((gint *)&code.bytes[prev_loc_value_offset]) = (gint)prev_loc_value;
gssize xor_curr_loc_offset = offsetof(afl_log_code, code.xor_rsi_curr_loc) +
sizeof(code.code.xor_rsi_curr_loc) -
sizeof(guint32);
*((guint32 *)&code.bytes[xor_curr_loc_offset]) = (guint32)(area_offset);
gssize add_rsi_1_offset = offsetof(afl_log_code, code.add_rsi_1) +
sizeof(code.code.add_rsi_1) - sizeof(guint32) - 1;
*((guint32 *)&code.bytes[add_rsi_1_offset]) =
(guint32)GPOINTER_TO_SIZE(__afl_area_ptr);
gssize adc_rsi_0_ffset = offsetof(afl_log_code, code.adc_rsi_0) +
sizeof(code.code.adc_rsi_0) - sizeof(guint32) - 1;
*((guint32 *)&code.bytes[adc_rsi_0_ffset]) =
(guint32)GPOINTER_TO_SIZE(__afl_area_ptr);
gum_x86_writer_put_bytes(cw, code.bytes, sizeof(afl_log_code));
}

View File

@ -83,6 +83,9 @@ void instrument_coverage_optimize(const cs_insn * instr,
}
void instrument_coverage_optimize_init(void) {
}
void instrument_flush(GumStalkerOutput *output) {
gum_x86_writer_flush(output->writer.x86);

View File

@ -549,18 +549,19 @@ static GArray *merge_ranges(GArray *a) {
}
void ranges_print_debug_maps(void) {
gum_process_enumerate_ranges(GUM_PAGE_NO_ACCESS, print_ranges_callback, NULL);
}
void ranges_config(void) {
if (getenv("AFL_FRIDA_DEBUG_MAPS") != NULL) { ranges_debug_maps = TRUE; }
if (getenv("AFL_INST_LIBS") != NULL) { ranges_inst_libs = TRUE; }
if (getenv("AFL_FRIDA_INST_JIT") != NULL) { ranges_inst_jit = TRUE; }
if (ranges_debug_maps) {
gum_process_enumerate_ranges(GUM_PAGE_NO_ACCESS, print_ranges_callback,
NULL);
}
if (ranges_debug_maps) { ranges_print_debug_maps(); }
include_ranges = collect_ranges("AFL_FRIDA_INST_RANGES");
exclude_ranges = collect_ranges("AFL_FRIDA_EXCLUDE_RANGES");

View File

@ -1,4 +1,4 @@
#ifndef __APPLE__
#if defined(__linux__) && !defined(__ANDROID__)
#include <stdbool.h>
#include <stdio.h>

View File

@ -1,4 +1,4 @@
#ifndef __APPLE__
#if defined(__linux__) && !defined(__ANDROID__)
#include <execinfo.h>
#include <fcntl.h>

View File

@ -1,4 +1,4 @@
#ifndef __APPLE__
#if defined(__linux__) && !defined(__ANDROID__)
#include <fcntl.h>
#include <sched.h>

View File

@ -1,4 +1,4 @@
#ifndef __APPLE__
#if defined(__linux__) && !defined(__ANDROID__)
#include <stdint.h>
#include <stdio.h>

View File

@ -1,4 +1,4 @@
#ifndef __APPLE__
#if defined(__linux__) && !defined(__ANDROID__)
#include <alloca.h>
#include <errno.h>

View File

@ -1,4 +1,4 @@
#ifndef __APPLE__
#if defined(__linux__) && !defined(__ANDROID__)
#include <stdarg.h>

View File

@ -1,4 +1,4 @@
#ifndef __APPLE__
#if defined(__linux__) && !defined(__ANDROID__)
#include <stdio.h>
#include <string.h>

View File

@ -1,4 +1,4 @@
#ifndef __APPLE__
#if defined(__linux__) && !defined(__ANDROID__)
#include <limits.h>
#include <stdio.h>

View File

@ -1130,7 +1130,6 @@ void get_core_count(afl_state_t *);
void fix_up_sync(afl_state_t *);
void check_asan_opts(afl_state_t *);
void check_binary(afl_state_t *, u8 *);
void fix_up_banner(afl_state_t *, u8 *);
void check_if_tty(afl_state_t *);
void setup_signal_handlers(void);
void save_cmdline(afl_state_t *, u32, char **);

View File

@ -881,8 +881,6 @@ void ModuleSanitizerCoverage::InjectCoverageForIndirectCalls(
Function &F, ArrayRef<Instruction *> IndirCalls) {
if (IndirCalls.empty()) return;
assert(Options.TracePC || Options.TracePCGuard ||
Options.Inline8bitCounters /*|| Options.InlineBoolFlag*/);
for (auto I : IndirCalls) {
IRBuilder<> IRB(I);

View File

@ -244,7 +244,11 @@ bool AFLLTOPass::runOnModule(Module &M) {
// the instrument file list check
AttributeList Attrs = F.getAttributes();
#if LLVM_VERSION_MAJOR < 14
if (Attrs.hasAttribute(-1, StringRef("skipinstrument"))) {
#else
if (Attrs.hasFnAttr(StringRef("skipinstrument"))) {
#endif
if (debug)
fprintf(stderr,

View File

@ -116,10 +116,15 @@ bool AFLcheckIfInstrument::runOnModule(Module &M) {
auto & Ctx = F.getContext();
AttributeList Attrs = F.getAttributes();
#if LLVM_VERSION_MAJOR < 14
AttrBuilder NewAttrs;
NewAttrs.addAttribute("skipinstrument");
F.setAttributes(
Attrs.addAttributes(Ctx, AttributeList::FunctionIndex, NewAttrs));
#else
AttributeList NewAttrs = Attrs.addFnAttribute(Ctx, "skipinstrument");
F.setAttributes(NewAttrs);
#endif
}

View File

@ -610,12 +610,12 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
if (!time_ms) {
kill(fsrv->fsrv_pid, fsrv->kill_signal);
if (fsrv->fsrv_pid > 0) { kill(fsrv->fsrv_pid, fsrv->kill_signal); }
} else if (time_ms > fsrv->init_tmout) {
fsrv->last_run_timed_out = 1;
kill(fsrv->fsrv_pid, fsrv->kill_signal);
if (fsrv->fsrv_pid > 0) { kill(fsrv->fsrv_pid, fsrv->kill_signal); }
} else {
@ -1248,7 +1248,7 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
/* If there was no response from forkserver after timeout seconds,
we kill the child. The forkserver should inform us afterwards */
kill(fsrv->child_pid, fsrv->kill_signal);
if (fsrv->child_pid > 0) { kill(fsrv->child_pid, fsrv->kill_signal); }
fsrv->last_run_timed_out = 1;
if (read(fsrv->fsrv_st_fd, &fsrv->child_status, 4) < 4) { exec_ms = 0; }

View File

@ -2815,43 +2815,6 @@ void check_binary(afl_state_t *afl, u8 *fname) {
}
/* Trim and possibly create a banner for the run. */
void fix_up_banner(afl_state_t *afl, u8 *name) {
if (!afl->use_banner) {
if (afl->sync_id) {
afl->use_banner = afl->sync_id;
} else {
u8 *trim = strrchr(name, '/');
if (!trim) {
afl->use_banner = name;
} else {
afl->use_banner = trim + 1;
}
}
}
if (strlen(afl->use_banner) > 32) {
u8 *tmp = ck_alloc(36);
sprintf(tmp, "%.32s...", afl->use_banner);
afl->use_banner = tmp;
}
}
/* Check if we're on TTY. */
void check_if_tty(afl_state_t *afl) {

View File

@ -291,8 +291,6 @@ static void write_with_gap(afl_state_t *afl, u8 *mem, u32 len, u32 skip_at,
u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
u32 handicap, u8 from_queue) {
if (unlikely(afl->shm.cmplog_mode)) { q->exec_cksum = 0; }
u8 fault = 0, new_bits = 0, var_detected = 0, hnb = 0,
first_run = (q->exec_cksum == 0);
u64 start_us, stop_us, diff_us;
@ -300,6 +298,8 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
u32 use_tmout = afl->fsrv.exec_tmout;
u8 *old_sn = afl->stage_name;
if (unlikely(afl->shm.cmplog_mode)) { q->exec_cksum = 0; }
/* Be a bit more generous about timeouts when resuming sessions, or when
trying to calibrate already-added finds. This helps avoid trouble due
to intermittent latency. */
@ -343,6 +343,32 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
}
/* we need a dummy run if this is LTO + cmplog */
if (unlikely(afl->shm.cmplog_mode)) {
write_to_testcase(afl, use_mem, q->len);
fault = fuzz_run_target(afl, &afl->fsrv, use_tmout);
/* afl->stop_soon is set by the handler for Ctrl+C. When it's pressed,
we want to bail out quickly. */
if (afl->stop_soon || fault != afl->crash_mode) { goto abort_calibration; }
if (!afl->non_instrumented_mode && !afl->stage_cur &&
!count_bytes(afl, afl->fsrv.trace_bits)) {
fault = FSRV_RUN_NOINST;
goto abort_calibration;
}
#ifdef INTROSPECTION
if (unlikely(!q->bitsmap_size)) q->bitsmap_size = afl->bitsmap_size;
#endif
}
if (q->exec_cksum) {
memcpy(afl->first_trace, afl->fsrv.trace_bits, afl->fsrv.map_size);

View File

@ -441,9 +441,10 @@ void show_stats(afl_state_t *afl) {
u64 cur_ms;
u32 t_bytes, t_bits;
u32 banner_len, banner_pad;
u8 tmp[256];
u8 time_tmp[64];
static u8 banner[128];
u32 banner_len, banner_pad;
u8 tmp[256];
u8 time_tmp[64];
u8 val_buf[8][STRINGIFY_VAL_SIZE_MAX];
#define IB(i) (val_buf[(i)])
@ -656,26 +657,34 @@ void show_stats(afl_state_t *afl) {
}
/* Let's start by drawing a centered banner. */
if (unlikely(!banner[0])) {
banner_len = (afl->crash_mode ? 24 : 22) + strlen(VERSION) +
strlen(afl->use_banner) + strlen(afl->power_name) + 3 + 5;
banner_pad = (79 - banner_len) / 2;
memset(tmp, ' ', banner_pad);
char *si = "";
if (afl->sync_id) { si = afl->sync_id; }
memset(banner, 0, sizeof(banner));
banner_len = (afl->crash_mode ? 20 : 18) + strlen(VERSION) + strlen(si) +
strlen(afl->power_name) + 4 + 6;
#ifdef HAVE_AFFINITY
sprintf(
tmp + banner_pad,
"%s " cLCY VERSION cLGN " (%s) " cPIN "[%s]" cBLU " {%d}",
afl->crash_mode ? cPIN "peruvian were-rabbit" : cYEL "american fuzzy lop",
afl->use_banner, afl->power_name, afl->cpu_aff);
#else
sprintf(
tmp + banner_pad, "%s " cLCY VERSION cLGN " (%s) " cPIN "[%s]",
afl->crash_mode ? cPIN "peruvian were-rabbit" : cYEL "american fuzzy lop",
afl->use_banner, afl->power_name);
#endif /* HAVE_AFFINITY */
if (strlen(afl->use_banner) + banner_len > 75) {
SAYF("\n%s\n", tmp);
afl->use_banner += (strlen(afl->use_banner) + banner_len) - 76;
memset(afl->use_banner, '.', 3);
}
banner_len += strlen(afl->use_banner);
banner_pad = (79 - banner_len) / 2;
memset(banner, ' ', banner_pad);
sprintf(banner + banner_pad,
"%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s]",
afl->crash_mode ? cPIN "peruvian were-rabbit"
: cYEL "american fuzzy lop",
si, afl->use_banner, afl->power_name);
}
SAYF("\n%s\n", banner);
/* "Handy" shortcuts for drawing boxes... */

View File

@ -1189,7 +1189,17 @@ int main(int argc, char **argv_orig, char **envp) {
}
if (afl->sync_id) { fix_up_sync(afl); }
if (afl->sync_id) {
if (strlen(afl->sync_id) > 24) {
FATAL("sync_id max length is 24 characters");
}
fix_up_sync(afl);
}
if (!strcmp(afl->in_dir, afl->out_dir)) {
@ -1218,6 +1228,8 @@ int main(int argc, char **argv_orig, char **envp) {
if (unlikely(afl->afl_env.afl_statsd)) { statsd_setup_format(afl); }
if (!afl->use_banner) { afl->use_banner = argv[optind]; }
if (strchr(argv[optind], '/') == NULL && !afl->unicorn_mode) {
WARNF(cLRD
@ -1486,9 +1498,6 @@ int main(int argc, char **argv_orig, char **envp) {
}
save_cmdline(afl, argc, argv);
fix_up_banner(afl, argv[optind]);
check_if_tty(afl);
if (afl->afl_env.afl_force_ui) { afl->not_on_tty = 0; }

View File

@ -242,9 +242,14 @@ static u32 write_results_to_file(afl_forkserver_t *fsrv, u8 *outfile) {
if (cmin_mode &&
(fsrv->last_run_timed_out || (!caa && child_crashed != cco))) {
// create empty file to prevent error messages in afl-cmin
fd = open(outfile, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
close(fd);
if (strcmp(outfile, "-")) {
// create empty file to prevent error messages in afl-cmin
fd = open(outfile, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
close(fd);
}
return ret;
}

View File

@ -1 +1 @@
f1c853648a74b0157d233a2ef9f1693cfee78c11
d4915053d477dd827b3fe4b494173d3fbf9f456e

View File

@ -12,11 +12,11 @@ use std::{
use unicornafl::{
unicorn_const::{uc_error, Arch, Mode, Permission},
RegisterX86::{self, *},
Unicorn, UnicornHandle,
RegisterX86::*,
Unicorn,
};
const BINARY: &str = &"../target";
const BINARY: &str = "../target";
// Memory map for the code to be tested
// Arbitrary address where code to test will be loaded
@ -47,7 +47,7 @@ fn read_file(filename: &str) -> Result<Vec<u8>, io::Error> {
fn parse_locs(loc_name: &str) -> Result<Vec<u64>, io::Error> {
let contents = &read_file(&format!("../target.offsets.{}", loc_name))?;
//println!("Read: {:?}", contents);
Ok(str_from_u8_unchecked(&contents)
Ok(str_from_u8_unchecked(contents)
.split('\n')
.map(|x| {
//println!("Trying to convert {}", &x[2..]);
@ -87,8 +87,7 @@ fn main() {
}
fn fuzz(input_file: &str) -> Result<(), uc_error> {
let mut unicorn = Unicorn::new(Arch::X86, Mode::MODE_64, 0)?;
let mut uc: UnicornHandle<'_, _> = unicorn.borrow();
let mut uc = Unicorn::new(Arch::X86, Mode::MODE_64, 0)?;
let binary =
read_file(BINARY).unwrap_or_else(|_| panic!("Could not read modem image: {}", BINARY));
@ -133,7 +132,7 @@ fn fuzz(input_file: &str) -> Result<(), uc_error> {
let already_allocated_malloc = already_allocated.clone();
// We use a very simple malloc/free stub here,
// that only works for exactly one allocation at a time.
let hook_malloc = move |mut uc: UnicornHandle<'_, _>, addr: u64, size: u32| {
let hook_malloc = move |uc: &mut Unicorn<'_, _>, addr: u64, size: u32| {
if already_allocated_malloc.get() {
println!("Double malloc, not supported right now!");
abort();
@ -154,7 +153,7 @@ fn fuzz(input_file: &str) -> Result<(), uc_error> {
let already_allocated_free = already_allocated;
// No real free, just set the "used"-flag to false.
let hook_free = move |mut uc: UnicornHandle<'_, _>, addr, size| {
let hook_free = move |uc: &mut Unicorn<'_, _>, addr, size| {
if already_allocated_free.get() {
println!("Double free detected. Real bug?");
abort();
@ -177,7 +176,7 @@ fn fuzz(input_file: &str) -> Result<(), uc_error> {
*/
// This is a fancy print function that we're just going to skip for fuzzing.
let hook_magicfn = move |mut uc: UnicornHandle<'_, _>, addr, size| {
let hook_magicfn = move |uc: &mut Unicorn<'_, _>, addr, size| {
uc.reg_write(RIP, addr + size as u64).unwrap();
};
@ -195,7 +194,7 @@ fn fuzz(input_file: &str) -> Result<(), uc_error> {
}
let place_input_callback =
|uc: &mut UnicornHandle<'_, _>, afl_input: &mut [u8], _persistent_round| {
|uc: &mut Unicorn<'_, _>, afl_input: &mut [u8], _persistent_round| {
// apply constraints to the mutated input
if afl_input.len() > INPUT_MAX as usize {
//println!("Skipping testcase with leng {}", afl_input.len());
@ -209,9 +208,7 @@ fn fuzz(input_file: &str) -> Result<(), uc_error> {
// return true if the last run should be counted as crash
let crash_validation_callback =
|_uc: &mut UnicornHandle<'_, _>, result, _input: &[u8], _persistent_round| {
result != uc_error::OK
};
|_uc: &mut Unicorn<'_, _>, result, _input: &[u8], _persistent_round| result != uc_error::OK;
let end_addrs = parse_locs("main_ends").unwrap();

@ -1 +1 @@
Subproject commit f1c853648a74b0157d233a2ef9f1693cfee78c11
Subproject commit d4915053d477dd827b3fe4b494173d3fbf9f456e