Push to stable (#927)

* sync (#886)

* Create FUNDING.yml

* Update FUNDING.yml

* moved custom_mutator examples

* unicorn speedtest makefile cleanup

* fixed example location

* fix qdbi

* update util readme

* Frida persistent (#880)

* Added x64 support for persistent mode (function call only), in-memory teest cases and complog

* Review changes, fix NeverZero and code to parse the .text section of the main executable. Excluded ranges TBC

* Various minor fixes and finished support for AFL_INST_LIBS

* Review changes

Co-authored-by: Your Name <you@example.com>

* nits

* fix frida mode

* Integer overflow/underflow fixes in libdislocator (#889)

* libdislocator: fixing integer overflow in 'max_mem' variable and setting 'max_mem' type to 'size_t'

* libdislocator: fixing potential integer underflow in 'total_mem' variable due to its different values in different threads

* Bumped warnings up to the max and fixed remaining issues (#890)

Co-authored-by: Your Name <you@example.com>

* nits

* frida mode - support non-pie

* nits

* nit

* update grammar mutator

* Fixes for aarch64, OSX and other minor issues (#891)

Co-authored-by: Your Name <you@example.com>

* nits

* nits

* fix PCGUARD, build aflpp_driver with fPIC

* Added representative fuzzbench test and test for libxml (#893)

* Added representative fuzzbench test and test for libxml

* Added support for building FRIDA from source with FRIDA_SOURCE=1

Co-authored-by: Your Name <you@example.com>

* nits

* update changelog

* typos

* fixed potential double free in custom trim (#881)

* error handling, freeing mem

* frida: complog -> cmplog

* fix statsd writing

* let aflpp_qemu_driver_hook.so build fail gracefully

* fix stdin trimming

* Support for AFL_ENTRYPOINT (#898)

Co-authored-by: Your Name <you@example.com>

* remove the input file .cur_input at the end of the fuzzing, if AFL_TMPDIR is used

* reverse push (#901)

* Create FUNDING.yml

* Update FUNDING.yml

* disable QEMU static pie

Co-authored-by: Andrea Fioraldi <andreafioraldi@gmail.com>

* clarify that no modifications are required.

* add new test for frida_mode (please review)

* typos

* fix persistent mode (64-bit)

* set ARCH for linux intel 32-bit for frida-gum-devkit

* prepare for 32-bit support (later)

* not on qemu 3 anymore

* unicorn mips fixes

* instrumentation further move to C++11 (#900)

* unicorn fixes

* more unicorn fixes

* Fix memory errors when trim causes testcase growth (#881) (#903)

* Revert "fixed potential double free in custom trim (#881)"

This reverts commit e9d2f72382.

* Revert "fix custom trim for increasing data"

This reverts commit 86a8ef168d.

* Fix memory errors when trim causes testcase growth

Modify trim_case_custom to avoid writing into in_buf because
some custom mutators can cause the testcase to grow rather than
shrink.

Instead of modifying in_buf directly, we write the update out
to the disk when trimming is complete, and then the caller is
responsible for refreshing the in-memory buffer from the file.

This is still a bit sketchy because it does need to modify q->len in
order to notify the upper layers that something changed, and it could
end up telling upper layer code that the q->len is *bigger* than
the buffer (q->testcase_buf) that contains it, which is asking
for trouble down the line somewhere...

* Fix an unlikely situation

Put back some `unlikely()` calls that were in
the e9d2f72382 commit that was
reverted.

* typo

* Exit on time (#904)

* Variable AFL_EXIT_ON_TIME description has been added.
Variables AFL_EXIT_ON_TIME and afl_exit_on_time has been added.
afl->exit_on_time variable initialization has been added.
The asignment of a value to the afl->afl_env.afl_exit_on_time variable from
environment variables has been added.
Code to exit on timeout if new path not found has been added.

* Type of afl_exit_on_time variable has been changed.
Variable exit_on_time has been added to the afl_state_t structure.

* Command `export AFL_EXIT_WHEN_DONE=1` has been added.

* Millisecond to second conversion has been added.
Call get_cur_time() has been added.

* Revert to using the saved current time value.

* Useless check has been removed.

* fix new path to custom-mutators

* ensure crashes/README.txt exists

* fix

* Changes to bump FRIDA version and to clone FRIDA repo in to build directory rather than use a submodule as the FRIDA build scripts don't like it (#906)

Co-authored-by: Your Name <you@example.com>

* Fix numeric overflow in cmplog implementation (#907)

Co-authored-by: Your Name <you@example.com>

* testcase fixes for unicorn

* remove merge conflict artifacts

* fix afl-plot

* Changes to remove binaries from frida_mode (#913)

Co-authored-by: Your Name <you@example.com>

* Frida cmplog fail fast (#914)

* Changes to remove binaries from frida_mode

* Changes to make cmplog fail fast

Co-authored-by: Your Name <you@example.com>

* afl-plot: relative time

* arch linux and mac os support for afl-system-config

* typo

* code-format

* update documentation

* github workflow for qemu

* OSX-specific improvements (#912)

* Fix afl-cc to work correctly by default on OSX using xcode

- CLANG_ENV_VAR must be set for afl-as to work
- Use clang mode by default if no specific compiler selected

* Add OSX-specific documentation for configuring shared memory

* Fixes to memory operands for complog (#916)

Co-authored-by: Your Name <you@example.com>

* fix a few cur_time uses

* added bounds check to pivot_inputs (fixes #921)

* additional safety checks for restarts

* restrict afl-showmap in_file size

* fix seed crash disable

* add warning for afl-showmap partial read

* no core dumps

* AFL_PRINT_FILENAMES added

* more documentation for AFL_EXIT_ON_TIME

* Flushing for AFL_PRINT_FILENAMES

* FASAN Support (#918)

* FASAN Support

* Fix handling of Address Sanitizer DSO

* Changes to identification of Address Sanitizer DSO

Co-authored-by: Your Name <you@example.com>

* Support for x86 (#920)

Co-authored-by: Your Name <you@example.com>

* Update frida_mode readme (#925)

* libqasan: use syscalls for read and write

* update readme

* Minor integration tweaks (#926)

Co-authored-by: Your Name <you@example.com>

* merge

* fix afl-fuzz.c frida preload

* cleaned up AFL_PRINT_FILENAMES env

Co-authored-by: Dominik Maier <domenukk@gmail.com>
Co-authored-by: WorksButNotTested <62701594+WorksButNotTested@users.noreply.github.com>
Co-authored-by: Your Name <you@example.com>
Co-authored-by: Dmitry Zheregelya <zheregelya.d@gmail.com>
Co-authored-by: hexcoder <hexcoder-@users.noreply.github.com>
Co-authored-by: hexcoder- <heiko@hexco.de>
Co-authored-by: Andrea Fioraldi <andreafioraldi@gmail.com>
Co-authored-by: David CARLIER <devnexen@gmail.com>
Co-authored-by: realmadsci <71108352+realmadsci@users.noreply.github.com>
Co-authored-by: Roman M. Iudichev <SecNotice@ya.ru>
Co-authored-by: Dustin Spicuzza <dustin@virtualroadside.com>
This commit is contained in:
van Hauser
2021-05-20 11:14:46 +02:00
committed by GitHub
parent 8b7a7b29c6
commit da2d4d8258
61 changed files with 2126 additions and 311 deletions

View File

@ -19,7 +19,7 @@ jobs:
- name: update - name: update
run: sudo apt-get update && sudo apt-get upgrade -y run: sudo apt-get update && sudo apt-get upgrade -y
- name: install packages - name: install packages
run: sudo apt-get install -y -m -f --install-suggests build-essential git libtool libtool-bin automake bison libglib2.0-0 clang llvm-dev libc++-dev findutils libcmocka-dev python3-dev python3-setuptools run: sudo apt-get install -y -m -f --install-suggests build-essential git libtool libtool-bin automake bison libglib2.0-0 clang llvm-dev libc++-dev findutils libcmocka-dev python3-dev python3-setuptools ninja-build
- name: compiler installed - name: compiler installed
run: gcc -v ; echo ; clang -v run: gcc -v ; echo ; clang -v
- name: install gcc plugin - name: install gcc plugin

View File

@ -90,16 +90,17 @@ behaviours and defaults:
| Feature/Instrumentation | afl-gcc | llvm | gcc_plugin | frida_mode | qemu_mode |unicorn_mode | | Feature/Instrumentation | afl-gcc | llvm | gcc_plugin | frida_mode | qemu_mode |unicorn_mode |
| -------------------------|:-------:|:---------:|:----------:|:----------:|:----------------:|:------------:| | -------------------------|:-------:|:---------:|:----------:|:----------:|:----------------:|:------------:|
| NeverZero | x86[_64]| x(1) | x | | x | x | | NeverZero | x86[_64]| x(1) | x | x | x | x |
| Persistent Mode | | x | x | x | x86[_64]/arm[64] | x | | Persistent Mode | | x | x | x86[_64] | x86[_64]/arm[64] | x |
| LAF-Intel / CompCov | | x | | | x86[_64]/arm[64] | x86[_64]/arm | | LAF-Intel / CompCov | | x | | | x86[_64]/arm[64] | x86[_64]/arm |
| CmpLog | | x | | x | x86[_64]/arm[64] | | | CmpLog | | x | | x86[_64] | x86[_64]/arm[64] | |
| Selective Instrumentation| | x | x | x | x | | | Selective Instrumentation| | x | x | x | x | |
| Non-Colliding Coverage | | x(4) | | | (x)(5) | | | Non-Colliding Coverage | | x(4) | | | (x)(5) | |
| Ngram prev_loc Coverage | | x(6) | | | | | | Ngram prev_loc Coverage | | x(6) | | | | |
| Context Coverage | | x(6) | | | | | | Context Coverage | | x(6) | | | | |
| Auto Dictionary | | x(7) | | | | | | Auto Dictionary | | x(7) | | | | |
| Snapshot LKM Support | | (x)(8) | (x)(8) | | (x)(5) | | | Snapshot LKM Support | | (x)(8) | (x)(8) | | (x)(5) | |
| Shared Memory Testcases | | x | x | x | x | x |
1. default for LLVM >= 9.0, env var for older version due an efficiency bug in previous llvm versions 1. default for LLVM >= 9.0, env var for older version due an efficiency bug in previous llvm versions
2. GCC creates non-performant code, hence it is disabled in gcc_plugin 2. GCC creates non-performant code, hence it is disabled in gcc_plugin

View File

@ -123,6 +123,8 @@ function usage() {
"AFL_KEEP_TRACES: leave the temporary <out_dir>/.traces directory\n" \ "AFL_KEEP_TRACES: leave the temporary <out_dir>/.traces directory\n" \
"AFL_KILL_SIGNAL: Signal ID delivered to child processes on timeout, etc. (default: SIGKILL)\n" "AFL_KILL_SIGNAL: Signal ID delivered to child processes on timeout, etc. (default: SIGKILL)\n"
"AFL_PATH: path for the afl-showmap binary if not found anywhere else\n" \ "AFL_PATH: path for the afl-showmap binary if not found anywhere else\n" \
"AFL_PRINT_FILENAMES: If set, the filename currently processed will be " \
"printed to stdout\n" \
"AFL_SKIP_BIN_CHECK: skip check for target binary\n" "AFL_SKIP_BIN_CHECK: skip check for target binary\n"
exit 1 exit 1
} }

View File

@ -9,6 +9,7 @@ Want to stay in the loop on major new features? Join our mailing list by
sending a mail to <afl-users+subscribe@googlegroups.com>. sending a mail to <afl-users+subscribe@googlegroups.com>.
### Version ++3.13a (development) ### Version ++3.13a (development)
- Note: plot_data switched to relative time from unix time in 3.10
- frida_mode - new mode that uses frida to fuzz binary-only targets, - frida_mode - new mode that uses frida to fuzz binary-only targets,
it currently supports persistent mode and cmplog. it currently supports persistent mode and cmplog.
thanks to @WorksButNotTested! thanks to @WorksButNotTested!
@ -28,9 +29,12 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
- ensure one fuzzer sync per cycle - ensure one fuzzer sync per cycle
- fix afl_custom_queue_new_entry original file name when syncing - fix afl_custom_queue_new_entry original file name when syncing
from fuzzers from fuzzers
- on a crashing seed potentially the wrong input was disabled
- added AFL_EXIT_ON_SEED_ISSUES env that will exit if a seed in - added AFL_EXIT_ON_SEED_ISSUES env that will exit if a seed in
-i dir crashes the target or results in a timeout. By default -i dir crashes the target or results in a timeout. By default
afl++ ignores these and uses them for splicing instead. afl++ ignores these and uses them for splicing instead.
- added AFL_EXIT_ON_TIME env that will make afl-fuzz exit fuzzing after
no new paths have been found for n seconds
- afl-cc: - afl-cc:
- We do not support llvm versions prior 6.0 anymore - We do not support llvm versions prior 6.0 anymore
- Fix for -pie compiled binaries with default afl-clang-fast PCGUARD - Fix for -pie compiled binaries with default afl-clang-fast PCGUARD
@ -48,6 +52,7 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
MacOS shared memory MacOS shared memory
- updated the grammar custom mutator to the newest version - updated the grammar custom mutator to the newest version
- add -d (add dead fuzzer stats) to afl-whatsup - add -d (add dead fuzzer stats) to afl-whatsup
- added AFL_PRINT_FILENAMES to afl-showmap/cmin to print the current filename
### Version ++3.12c (release) ### Version ++3.12c (release)
- afl-fuzz: - afl-fuzz:

View File

@ -103,6 +103,41 @@ The llvm instrumentation requires a fully-operational installation of clang. The
comes with Xcode is missing some of the essential headers and helper tools. comes with Xcode is missing some of the essential headers and helper tools.
See README.llvm.md for advice on how to build the compiler from scratch. See README.llvm.md for advice on how to build the compiler from scratch.
MacOS X supports SYSV shared memory used by AFL's instrumentation, but the
default settings aren't usable with AFL++. The default settings on 10.14 seem
to be:
```bash
$ ipcs -M
IPC status from <running system> as of XXX
shminfo:
shmmax: 4194304 (max shared memory segment size)
shmmin: 1 (min shared memory segment size)
shmmni: 32 (max number of shared memory identifiers)
shmseg: 8 (max shared memory segments per process)
shmall: 1024 (max amount of shared memory in pages)
```
To temporarily change your settings to something minimally usable with AFL++,
run these commands as root:
```bash
sysctl kern.sysv.shmmax=8388608
sysctl kern.sysv.shmall=4096
```
If you're running more than one instance of AFL you likely want to make `shmall`
bigger and increase `shmseg` as well:
```bash
sysctl kern.sysv.shmmax=8388608
sysctl kern.sysv.shmseg=48
sysctl kern.sysv.shmall=98304
```
See http://www.spy-hill.com/help/apple/SharedMemory.html for documentation for
these settings and how to make them permanent.
## 4. Linux or *BSD on non-x86 systems ## 4. Linux or *BSD on non-x86 systems
Standard build will fail on non-x86 systems, but you should be able to Standard build will fail on non-x86 systems, but you should be able to

View File

@ -285,8 +285,8 @@ checks or alter some of the more exotic semantics of the tool:
convenient for some types of automated jobs. convenient for some types of automated jobs.
- `AFL_EXIT_ON_TIME` Causes afl-fuzz to terminate if no new paths were - `AFL_EXIT_ON_TIME` Causes afl-fuzz to terminate if no new paths were
found within a specified period of time. May be convenient for some found within a specified period of time (in seconds). May be convenient
types of automated jobs. for some types of automated jobs.
- `AFL_EXIT_ON_SEED_ISSUES` will restore the vanilla afl-fuzz behaviour - `AFL_EXIT_ON_SEED_ISSUES` will restore the vanilla afl-fuzz behaviour
which does not allow crashes or timeout seeds in the initial -i corpus. which does not allow crashes or timeout seeds in the initial -i corpus.
@ -567,6 +567,9 @@ The corpus minimization script offers very little customization:
a modest security risk on multi-user systems with rogue users, but should a modest security risk on multi-user systems with rogue users, but should
be safe on dedicated fuzzing boxes. be safe on dedicated fuzzing boxes.
- `AFL_PRINT_FILENAMES` prints each filename to stdout, as it gets processed.
This can help when embedding `afl-cmin` or `afl-showmap` in other scripts scripting.
## 7) Settings for afl-tmin ## 7) Settings for afl-tmin
Virtually nothing to play with. Well, in QEMU mode (`-Q`), `AFL_PATH` will be Virtually nothing to play with. Well, in QEMU mode (`-Q`), `AFL_PATH` will be

View File

@ -19,11 +19,13 @@ RT_CFLAGS:=-Wno-unused-parameter \
-Wno-sign-compare \ -Wno-sign-compare \
-Wno-unused-function \ -Wno-unused-function \
-Wno-unused-result \ -Wno-unused-result \
-Wno-int-to-pointer-cast \
LDFLAGS+=-shared \ LDFLAGS+=-shared \
-lpthread \ -lpthread \
-lresolv \ -lresolv \
-ldl \ -ldl \
-z noexecstack \
ifdef DEBUG ifdef DEBUG
CFLAGS+=-Werror \ CFLAGS+=-Werror \
@ -38,6 +40,8 @@ FRIDA_BUILD_DIR:=$(BUILD_DIR)frida/
FRIDA_TRACE:=$(BUILD_DIR)afl-frida-trace.so FRIDA_TRACE:=$(BUILD_DIR)afl-frida-trace.so
FRIDA_TRACE_EMBEDDED:=$(BUILD_DIR)afl-frida-trace-embedded FRIDA_TRACE_EMBEDDED:=$(BUILD_DIR)afl-frida-trace-embedded
ifndef ARCH
ARCH=$(shell uname -m) ARCH=$(shell uname -m)
ifeq "$(ARCH)" "aarch64" ifeq "$(ARCH)" "aarch64"
ARCH:=arm64 ARCH:=arm64
@ -46,6 +50,7 @@ endif
ifeq "$(ARCH)" "i686" ifeq "$(ARCH)" "i686"
ARCH:=x86 ARCH:=x86
endif endif
endif
ifeq "$(shell uname)" "Darwin" ifeq "$(shell uname)" "Darwin"
OS:=macos OS:=macos
@ -83,13 +88,16 @@ 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_SRC:=$(ROOT)instrumentation/afl-compiler-rt.o.c
AFL_COMPILER_RT_OBJ:=$(OBJ_DIR)afl-compiler-rt.o AFL_COMPILER_RT_OBJ:=$(OBJ_DIR)afl-compiler-rt.o
.PHONY: all clean format $(FRIDA_GUM) .PHONY: all 32 clean format $(FRIDA_GUM)
############################## ALL ############################################# ############################## ALL #############################################
all: $(FRIDA_TRACE) all: $(FRIDA_TRACE)
make -C $(ROOT) make -C $(ROOT)
32:
CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all
$(BUILD_DIR): $(BUILD_DIR):
mkdir -p $(BUILD_DIR) mkdir -p $(BUILD_DIR)
@ -161,11 +169,11 @@ $(foreach src,$(SOURCES),$(eval $(call BUILD_SOURCE,$(src),$(OBJ_DIR)$(notdir $(
$(FRIDA_TRACE): $(GUM_DEVIT_LIBRARY) $(GUM_DEVIT_HEADER) $(OBJS) $(AFL_COMPILER_RT_OBJ) GNUmakefile | $(BUILD_DIR) $(FRIDA_TRACE): $(GUM_DEVIT_LIBRARY) $(GUM_DEVIT_HEADER) $(OBJS) $(AFL_COMPILER_RT_OBJ) GNUmakefile | $(BUILD_DIR)
$(CC) \ $(CC) \
-o $@ \
$(OBJS) \ $(OBJS) \
$(GUM_DEVIT_LIBRARY) \ $(GUM_DEVIT_LIBRARY) \
$(AFL_COMPILER_RT_OBJ) \ $(AFL_COMPILER_RT_OBJ) \
$(LDFLAGS) \ $(LDFLAGS) \
-o $@ \
cp -v $(FRIDA_TRACE) $(ROOT) cp -v $(FRIDA_TRACE) $(ROOT)

View File

@ -2,6 +2,10 @@ all:
@echo trying to use GNU make... @echo trying to use GNU make...
@gmake all || echo please install GNUmake @gmake all || echo please install GNUmake
32:
@echo trying to use GNU make...
@gmake 32 || echo please install GNUmake
clean: clean:
@gmake clean @gmake clean

View File

@ -19,18 +19,18 @@ should be possible to add these features in a similar manner to QEMU mode and
perhaps leverage some of its design and implementation. perhaps leverage some of its design and implementation.
| Feature/Instrumentation | frida-mode | Notes | | Feature/Instrumentation | frida-mode | Notes |
| -------------------------|:----------:|:---------------------------------------:| | -------------------------|:----------:|:--------------------------------------------:|
| NeverZero | x | | | NeverZero | x | |
| Persistent Mode | x | (x64 only)(Only on function boundaries) | | Persistent Mode | x | (x86/x64 only)(Only on function boundaries) |
| LAF-Intel / CompCov | - | (CMPLOG is better 90% of the time) | | LAF-Intel / CompCov | - | (CMPLOG is better 90% of the time) |
| CMPLOG | x | (x64 only) | | CMPLOG | x | (x86/x64 only) |
| Selective Instrumentation| x | | | Selective Instrumentation| x | |
| Non-Colliding Coverage | - | | | Non-Colliding Coverage | - | (Not possible in binary-only instrumentation |
| Ngram prev_loc Coverage | - | | | Ngram prev_loc Coverage | - | |
| Context Coverage | - | | | Context Coverage | - | |
| Auto Dictionary | - | | | Auto Dictionary | - | |
| Snapshot LKM Support | - | | | Snapshot LKM Support | - | |
| In-Memory Test Cases | x | (x64 only) | | In-Memory Test Cases | x | (x86/x64 only) |
## Compatibility ## Compatibility
Currently FRIDA mode supports Linux and macOS targets on both x86/x64 Currently FRIDA mode supports Linux and macOS targets on both x86/x64
@ -43,11 +43,17 @@ system does not support cross compilation.
## Getting Started ## Getting Started
To build everything run `make`. To build everything run `make`. To build for x86 run `make 32`. Note that in
x86 bit mode, it is not necessary for afl-fuzz to be built for 32-bit. However,
the shared library for frida_mode must be since it is injected into the target
process.
Various tests can be found in subfolders within the `test/` directory. To use Various tests can be found in subfolders within the `test/` directory. To use
these, first run `make` to build any dependencies. Then run `make qemu` or these, first run `make` to build any dependencies. Then run `make qemu` or
`make frida` to run on either QEMU of FRIDA mode respectively. `make frida` to run on either QEMU of FRIDA mode respectively. To run frida
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.
## Usage ## Usage
@ -130,9 +136,47 @@ them and they be inherited by the next child on fork.
* `AFL_FRIDA_INST_TRACE` - Generate some logging when running instrumented code. * `AFL_FRIDA_INST_TRACE` - Generate some logging when running instrumented code.
Requires `AFL_FRIDA_INST_NO_OPTIMIZE`. Requires `AFL_FRIDA_INST_NO_OPTIMIZE`.
## FASAN - Frida Address Sanitizer Mode
Frida mode also supports FASAN. The design of this is actually quite simple and
very similar to that used when instrumenting applications compiled from source.
### Address Sanitizer Basics
When Address Sanitizer is used to instrument programs built from source, the
compiler first adds a dependency (`DT_NEEDED` entry) for the Address Sanitizer
dynamic shared object (DSO). This shared object contains the main logic for Address
Sanitizer, including setting and managing up the shadow memory. It also provides
replacement implementations for a number of functions in standard libraries.
These replacements include things like `malloc` and `free` which allows for those
allocations to be marked in the shadow memory, but also a number of other fuctions.
Consider `memcpy` for example, this is instrumented to validate the paramters
(test the source and destination buffers against the shadow memory. This is much
easier than instrumenting those standard libraries since, first it would require
you to re-compile them and secondly it would mean that the instrumentation would
be applied at a more expensive granular level. Lastly, load-widening (typically
found in highy optimized code) can also make this instrumentation more difficult.
Since the DSO is loaded before all of the standard libraries (in fact it insists
on being first), the dynamic loader will use it to resolve imports from other
modules which depend on it.
### FASAN Implementation
FASAN takes a similar approach. It requires the user to add the Address Sanitizer
DSO to the `AFL_PRELOAD` environment variable such that it is loaded into the target.
Again, it must be first in the list. This means that it is not necessary to
instrument the standard libraries to detect when an application has provided an
incorrect argument to `memcpy` for example. This avoids issues with load-widening
and should also mean a huge improvement in performance.
FASAN then adds instrumentation for any instrucutions which use memory operands and
then calls into the `__asan_loadN` and `__asan_storeN` functions provided by the DSO
to validate memory accesses against the shadow memory.
## TODO ## TODO
The next features to be added are x86 support, integration with FuzzBench and The next features to be added are Aarch64 and Aarch32 support as well as looking at
support for ASAN. The intention is to achieve feature parity with QEMU mode in potential performance improvements. The intention is to achieve feature parity with
due course. Contributions are welcome, but please get in touch to ensure that QEMU mode in due course. Contributions are welcome, but please get in touch to
efforts are deconflicted. ensure that efforts are deconflicted.

13
frida_mode/include/asan.h Normal file
View File

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

11
frida_mode/include/ctx.h Normal file
View File

@ -0,0 +1,11 @@
#ifndef _CTX_H
#define _CTX_H
#include "frida-gum.h"
#if defined(__x86_64__) || defined(__i386__)
gsize ctx_read_reg(GumCpuContext *ctx, x86_reg reg);
#endif
#endif

View File

@ -8,7 +8,7 @@ void cmplog_init(void);
/* Functions to be implemented by the different architectures */ /* Functions to be implemented by the different architectures */
void cmplog_instrument(const cs_insn *instr, GumStalkerIterator *iterator); void cmplog_instrument(const cs_insn *instr, GumStalkerIterator *iterator);
gboolean cmplog_is_readable(void *addr, size_t size); gboolean cmplog_is_readable(guint64 addr, size_t size);
#endif #endif

View File

@ -0,0 +1,24 @@
#include "frida-gum.h"
#include "debug.h"
#include "asan.h"
gboolean asan_initialized = FALSE;
void asan_init(void) {
if (getenv("AFL_USE_FASAN") != NULL) {
OKF("Frida ASAN mode enabled");
asan_arch_init();
asan_initialized = TRUE;
} else {
OKF("Frida ASAN mode disabled");
}
}

View File

@ -0,0 +1,28 @@
#include "frida-gum.h"
#include "debug.h"
#include "asan.h"
#include "util.h"
#if defined(__arm__)
void asan_instrument(const cs_insn *instr, GumStalkerIterator *iterator) {
UNUSED_PARAMETER(instr);
UNUSED_PARAMETER(iterator);
if (asan_initialized) {
FATAL("ASAN mode not supported on this architecture");
}
}
void asan_arch_init(void) {
FATAL("ASAN mode not supported on this architecture");
}
#endif

View File

@ -0,0 +1,28 @@
#include "frida-gum.h"
#include "debug.h"
#include "asan.h"
#include "util.h"
#if defined(__aarch64__)
void asan_instrument(const cs_insn *instr, GumStalkerIterator *iterator) {
UNUSED_PARAMETER(instr);
UNUSED_PARAMETER(iterator);
if (asan_initialized) {
FATAL("ASAN mode not supported on this architecture");
}
}
void asan_arch_init(void) {
FATAL("ASAN mode not supported on this architecture");
}
#endif

View File

@ -0,0 +1,93 @@
#include <dlfcn.h>
#include "frida-gum.h"
#include "debug.h"
#include "asan.h"
#include "ctx.h"
#include "util.h"
#if defined(__x86_64__)
typedef void (*asan_loadN_t)(uint64_t address, uint8_t size);
typedef void (*asan_storeN_t)(uint64_t address, uint8_t size);
asan_loadN_t asan_loadN = NULL;
asan_storeN_t asan_storeN = NULL;
static void asan_callout(GumCpuContext *ctx, gpointer user_data) {
UNUSED_PARAMETER(user_data);
cs_x86_op * operand = (cs_x86_op *)user_data;
x86_op_mem *mem = &operand->mem;
gsize base = 0;
gsize index = 0;
gsize address;
uint8_t size;
if (mem->base != X86_REG_INVALID) { base = ctx_read_reg(ctx, mem->base); }
if (mem->index != X86_REG_INVALID) { index = ctx_read_reg(ctx, mem->index); }
address = base + (mem->scale * index) + mem->disp;
size = operand->size;
if (operand->access == CS_AC_READ) {
asan_loadN(address, size);
} else if (operand->access == CS_AC_WRITE) {
asan_storeN(address, size);
}
}
void asan_instrument(const cs_insn *instr, GumStalkerIterator *iterator) {
UNUSED_PARAMETER(iterator);
cs_x86 x86 = instr->detail->x86;
cs_x86_op * operand;
x86_op_mem *mem;
cs_x86_op * ctx;
if (!asan_initialized) return;
if (instr->id == X86_INS_LEA) return;
if (instr->id == X86_INS_NOP) return;
for (uint8_t i = 0; i < x86.op_count; i++) {
operand = &x86.operands[i];
if (operand->type != X86_OP_MEM) { continue; }
mem = &operand->mem;
if (mem->segment != X86_REG_INVALID) { continue; }
ctx = g_malloc0(sizeof(cs_x86_op));
memcpy(ctx, operand, sizeof(cs_x86_op));
gum_stalker_iterator_put_callout(iterator, asan_callout, ctx, g_free);
}
}
void asan_arch_init(void) {
asan_loadN = (asan_loadN_t)dlsym(RTLD_DEFAULT, "__asan_loadN");
asan_storeN = (asan_loadN_t)dlsym(RTLD_DEFAULT, "__asan_storeN");
if (asan_loadN == NULL || asan_storeN == NULL) {
FATAL("Frida ASAN failed to find '__asan_loadN' or '__asan_storeN'");
}
}
#endif

View File

@ -0,0 +1,93 @@
#include <dlfcn.h>
#include "frida-gum.h"
#include "debug.h"
#include "asan.h"
#include "ctx.h"
#include "util.h"
#if defined(__i386__)
typedef void (*asan_loadN_t)(gsize address, uint8_t size);
typedef void (*asan_storeN_t)(gsize address, uint8_t size);
asan_loadN_t asan_loadN = NULL;
asan_storeN_t asan_storeN = NULL;
static void asan_callout(GumCpuContext *ctx, gpointer user_data) {
UNUSED_PARAMETER(user_data);
cs_x86_op * operand = (cs_x86_op *)user_data;
x86_op_mem *mem = &operand->mem;
gsize base = 0;
gsize index = 0;
gsize address;
uint8_t size;
if (mem->base != X86_REG_INVALID) { base = ctx_read_reg(ctx, mem->base); }
if (mem->index != X86_REG_INVALID) { index = ctx_read_reg(ctx, mem->index); }
address = base + (mem->scale * index) + mem->disp;
size = operand->size;
if (operand->access == CS_AC_READ) {
asan_loadN(address, size);
} else if (operand->access == CS_AC_WRITE) {
asan_storeN(address, size);
}
}
void asan_instrument(const cs_insn *instr, GumStalkerIterator *iterator) {
UNUSED_PARAMETER(iterator);
cs_x86 x86 = instr->detail->x86;
cs_x86_op * operand;
x86_op_mem *mem;
cs_x86_op * ctx;
if (!asan_initialized) return;
if (instr->id == X86_INS_LEA) return;
if (instr->id == X86_INS_NOP) return;
for (uint8_t i = 0; i < x86.op_count; i++) {
operand = &x86.operands[i];
if (operand->type != X86_OP_MEM) { continue; }
mem = &operand->mem;
if (mem->segment != X86_REG_INVALID) { continue; }
ctx = g_malloc0(sizeof(cs_x86_op));
memcpy(ctx, operand, sizeof(cs_x86_op));
gum_stalker_iterator_put_callout(iterator, asan_callout, ctx, g_free);
}
}
void asan_arch_init(void) {
asan_loadN = (asan_loadN_t)dlsym(RTLD_DEFAULT, "__asan_loadN");
asan_storeN = (asan_loadN_t)dlsym(RTLD_DEFAULT, "__asan_storeN");
if (asan_loadN == NULL || asan_storeN == NULL) {
FATAL("Frida ASAN failed to find '__asan_loadN' or '__asan_storeN'");
}
}
#endif

View File

@ -53,7 +53,7 @@ static gboolean cmplog_contains(GumAddress inner_base, GumAddress inner_limit,
} }
gboolean cmplog_is_readable(void *addr, size_t size) { gboolean cmplog_is_readable(guint64 addr, size_t size) {
if (cmplog_ranges == NULL) FATAL("CMPLOG not initialized"); if (cmplog_ranges == NULL) FATAL("CMPLOG not initialized");
@ -65,9 +65,9 @@ gboolean cmplog_is_readable(void *addr, size_t size) {
* is lower than this. This should avoid some overhead when functions are * is lower than this. This should avoid some overhead when functions are
* called where one of the parameters is a size, or a some other small value. * called where one of the parameters is a size, or a some other small value.
*/ */
if (GPOINTER_TO_SIZE(addr) < DEFAULT_MMAP_MIN_ADDR) { return false; } if (addr < DEFAULT_MMAP_MIN_ADDR) { return false; }
GumAddress inner_base = GUM_ADDRESS(addr); GumAddress inner_base = addr;
GumAddress inner_limit = inner_base + size; GumAddress inner_limit = inner_base + size;
for (guint i = 0; i < cmplog_ranges->len; i++) { for (guint i = 0; i < cmplog_ranges->len; i++) {

View File

@ -3,46 +3,12 @@
#include "debug.h" #include "debug.h"
#include "cmplog.h" #include "cmplog.h"
#include "ctx.h"
#include "frida_cmplog.h" #include "frida_cmplog.h"
#include "util.h" #include "util.h"
#if defined(__x86_64__) #if defined(__x86_64__)
#define X86_REG_8L(LABEL, REG) \
case LABEL: { \
\
return REG & GUM_INT8_MASK; \
\
}
#define X86_REG_8H(LABEL, REG) \
case LABEL: { \
\
return (REG & GUM_INT16_MASK) >> 8; \
\
}
#define X86_REG_16(LABEL, REG) \
case LABEL: { \
\
return (REG & GUM_INT16_MASK); \
\
}
#define X86_REG_32(LABEL, REG) \
case LABEL: { \
\
return (REG & GUM_INT32_MASK); \
\
}
#define X86_REG_64(LABEL, REG) \
case LABEL: { \
\
return (REG); \
\
}
typedef struct { typedef struct {
x86_op_type type; x86_op_type type;
@ -65,123 +31,81 @@ typedef struct {
} cmplog_pair_ctx_t; } cmplog_pair_ctx_t;
static guint64 cmplog_read_reg(GumX64CpuContext *ctx, x86_reg reg) { static gboolean cmplog_read_mem(GumCpuContext *ctx, uint8_t size,
x86_op_mem *mem, gsize *val) {
switch (reg) { gsize base = 0;
gsize index = 0;
gsize address;
X86_REG_8L(X86_REG_AL, ctx->rax) if (mem->base != X86_REG_INVALID) base = ctx_read_reg(ctx, mem->base);
X86_REG_8L(X86_REG_BL, ctx->rbx)
X86_REG_8L(X86_REG_CL, ctx->rcx)
X86_REG_8L(X86_REG_DL, ctx->rdx)
X86_REG_8L(X86_REG_BPL, ctx->rbp)
X86_REG_8L(X86_REG_SIL, ctx->rsi)
X86_REG_8L(X86_REG_DIL, ctx->rdi)
X86_REG_8H(X86_REG_AH, ctx->rax) if (mem->index != X86_REG_INVALID) index = ctx_read_reg(ctx, mem->index);
X86_REG_8H(X86_REG_BH, ctx->rbx)
X86_REG_8H(X86_REG_CH, ctx->rcx)
X86_REG_8H(X86_REG_DH, ctx->rdx)
X86_REG_16(X86_REG_AX, ctx->rax) address = base + (index * mem->scale) + mem->disp;
X86_REG_16(X86_REG_BX, ctx->rbx)
X86_REG_16(X86_REG_CX, ctx->rcx)
X86_REG_16(X86_REG_DX, ctx->rdx)
X86_REG_16(X86_REG_DI, ctx->rdi)
X86_REG_16(X86_REG_SI, ctx->rsi)
X86_REG_16(X86_REG_BP, ctx->rbp)
X86_REG_32(X86_REG_EAX, ctx->rax) if (!cmplog_is_readable(address, size)) { return FALSE; }
X86_REG_32(X86_REG_ECX, ctx->rcx)
X86_REG_32(X86_REG_EDX, ctx->rdx)
X86_REG_32(X86_REG_EBX, ctx->rbx)
X86_REG_32(X86_REG_ESP, ctx->rsp)
X86_REG_32(X86_REG_EBP, ctx->rbp)
X86_REG_32(X86_REG_ESI, ctx->rsi)
X86_REG_32(X86_REG_EDI, ctx->rdi)
X86_REG_32(X86_REG_R8D, ctx->r8)
X86_REG_32(X86_REG_R9D, ctx->r9)
X86_REG_32(X86_REG_R10D, ctx->r10)
X86_REG_32(X86_REG_R11D, ctx->r11)
X86_REG_32(X86_REG_R12D, ctx->r12)
X86_REG_32(X86_REG_R13D, ctx->r13)
X86_REG_32(X86_REG_R14D, ctx->r14)
X86_REG_32(X86_REG_R15D, ctx->r15)
X86_REG_32(X86_REG_EIP, ctx->rip)
X86_REG_64(X86_REG_RAX, ctx->rax) switch (size) {
X86_REG_64(X86_REG_RCX, ctx->rcx)
X86_REG_64(X86_REG_RDX, ctx->rdx)
X86_REG_64(X86_REG_RBX, ctx->rbx)
X86_REG_64(X86_REG_RSP, ctx->rsp)
X86_REG_64(X86_REG_RBP, ctx->rbp)
X86_REG_64(X86_REG_RSI, ctx->rsi)
X86_REG_64(X86_REG_RDI, ctx->rdi)
X86_REG_64(X86_REG_R8, ctx->r8)
X86_REG_64(X86_REG_R9, ctx->r9)
X86_REG_64(X86_REG_R10, ctx->r10)
X86_REG_64(X86_REG_R11, ctx->r11)
X86_REG_64(X86_REG_R12, ctx->r12)
X86_REG_64(X86_REG_R13, ctx->r13)
X86_REG_64(X86_REG_R14, ctx->r14)
X86_REG_64(X86_REG_R15, ctx->r15)
X86_REG_64(X86_REG_RIP, ctx->rip)
case 1:
*val = *((guint8 *)GSIZE_TO_POINTER(address));
return TRUE;
case 2:
*val = *((guint16 *)GSIZE_TO_POINTER(address));
return TRUE;
case 4:
*val = *((guint32 *)GSIZE_TO_POINTER(address));
return TRUE;
case 8:
*val = *((guint64 *)GSIZE_TO_POINTER(address));
return TRUE;
default: default:
FATAL("Failed to read register: %d", reg); FATAL("Invalid operand size: %d\n", size);
return 0;
} }
} return FALSE;
static guint64 cmplog_read_mem(GumX64CpuContext *ctx, x86_op_mem *mem) {
guint64 base = 0;
guint64 index = 0;
guint64 address;
if (mem->base != X86_REG_INVALID) base = cmplog_read_reg(ctx, mem->base);
if (mem->index != X86_REG_INVALID) index = cmplog_read_reg(ctx, mem->index);
address = base + (index * mem->scale) + mem->disp;
return address;
} }
static guint64 cmplog_get_operand_value(GumCpuContext *context, static gboolean cmplog_get_operand_value(GumCpuContext *context,
cmplog_ctx_t * ctx) { cmplog_ctx_t *ctx, gsize *val) {
switch (ctx->type) { switch (ctx->type) {
case X86_OP_REG: case X86_OP_REG:
return cmplog_read_reg(context, ctx->reg); *val = ctx_read_reg(context, ctx->reg);
return TRUE;
case X86_OP_IMM: case X86_OP_IMM:
return ctx->imm; *val = ctx->imm;
return TRUE;
case X86_OP_MEM: case X86_OP_MEM:
return cmplog_read_mem(context, &ctx->mem); return cmplog_read_mem(context, ctx->size, &ctx->mem, val);
default: default:
FATAL("Invalid operand type: %d\n", ctx->type); FATAL("Invalid operand type: %d\n", ctx->type);
} }
return FALSE;
} }
static void cmplog_call_callout(GumCpuContext *context, gpointer user_data) { static void cmplog_call_callout(GumCpuContext *context, gpointer user_data) {
UNUSED_PARAMETER(user_data); UNUSED_PARAMETER(user_data);
guint64 address = cmplog_read_reg(context, X86_REG_RIP); gsize address = ctx_read_reg(context, X86_REG_RIP);
guint64 rdi = cmplog_read_reg(context, X86_REG_RDI); gsize rdi = ctx_read_reg(context, X86_REG_RDI);
guint64 rsi = cmplog_read_reg(context, X86_REG_RSI); gsize rsi = ctx_read_reg(context, X86_REG_RSI);
if (((G_MAXULONG - rdi) < 32) || ((G_MAXULONG - rsi) < 32)) return; if (((G_MAXULONG - rdi) < 32) || ((G_MAXULONG - rsi) < 32)) return;
if (!cmplog_is_readable(rdi, 32) || !cmplog_is_readable(rsi, 32)) return;
void *ptr1 = GSIZE_TO_POINTER(rdi); void *ptr1 = GSIZE_TO_POINTER(rdi);
void *ptr2 = GSIZE_TO_POINTER(rsi); void *ptr2 = GSIZE_TO_POINTER(rsi);
if (!cmplog_is_readable(ptr1, 32) || !cmplog_is_readable(ptr2, 32)) return;
uintptr_t k = address; uintptr_t k = address;
k = (k >> 4) ^ (k << 8); k = (k >> 4) ^ (k << 8);
@ -245,10 +169,10 @@ static void cmplog_instrument_call(const cs_insn * instr,
} }
static void cmplog_handle_cmp_sub(GumCpuContext *context, guint64 operand1, static void cmplog_handle_cmp_sub(GumCpuContext *context, gsize operand1,
guint64 operand2, uint8_t size) { gsize operand2, uint8_t size) {
guint64 address = cmplog_read_reg(context, X86_REG_RIP); gsize address = ctx_read_reg(context, X86_REG_RIP);
register uintptr_t k = (uintptr_t)address; register uintptr_t k = (uintptr_t)address;
@ -271,11 +195,13 @@ static void cmplog_handle_cmp_sub(GumCpuContext *context, guint64 operand1,
static void cmplog_cmp_sub_callout(GumCpuContext *context, gpointer user_data) { static void cmplog_cmp_sub_callout(GumCpuContext *context, gpointer user_data) {
cmplog_pair_ctx_t *ctx = (cmplog_pair_ctx_t *)user_data; cmplog_pair_ctx_t *ctx = (cmplog_pair_ctx_t *)user_data;
gsize operand1;
gsize operand2;
if (ctx->operand1.size != ctx->operand2.size) FATAL("Operand size mismatch"); if (ctx->operand1.size != ctx->operand2.size) FATAL("Operand size mismatch");
guint64 operand1 = cmplog_get_operand_value(context, &ctx->operand1); if (!cmplog_get_operand_value(context, &ctx->operand1, &operand1)) { return; }
guint64 operand2 = cmplog_get_operand_value(context, &ctx->operand2); if (!cmplog_get_operand_value(context, &ctx->operand2, &operand2)) { return; }
cmplog_handle_cmp_sub(context, operand1, operand2, ctx->operand1.size); cmplog_handle_cmp_sub(context, operand1, operand2, ctx->operand1.size);

View File

@ -1,17 +1,275 @@
#include "frida-gum.h" #include "frida-gum.h"
#include "debug.h" #include "debug.h"
#include "cmplog.h"
#include "ctx.h"
#include "frida_cmplog.h" #include "frida_cmplog.h"
#include "util.h" #include "util.h"
#if defined(__i386__) #if defined(__i386__)
typedef struct {
x86_op_type type;
uint8_t size;
union {
x86_op_mem mem;
x86_reg reg;
int64_t imm;
};
} cmplog_ctx_t;
typedef struct {
cmplog_ctx_t operand1;
cmplog_ctx_t operand2;
} cmplog_pair_ctx_t;
static gboolean cmplog_read_mem(GumCpuContext *ctx, uint8_t size,
x86_op_mem *mem, gsize *val) {
gsize base = 0;
gsize index = 0;
gsize address;
if (mem->base != X86_REG_INVALID) base = ctx_read_reg(ctx, mem->base);
if (mem->index != X86_REG_INVALID) index = ctx_read_reg(ctx, mem->index);
address = base + (index * mem->scale) + mem->disp;
if (!cmplog_is_readable(address, size)) { return FALSE; }
switch (size) {
case 1:
*val = *((guint8 *)GSIZE_TO_POINTER(address));
return TRUE;
case 2:
*val = *((guint16 *)GSIZE_TO_POINTER(address));
return TRUE;
case 4:
*val = *((guint32 *)GSIZE_TO_POINTER(address));
return TRUE;
default:
FATAL("Invalid operand size: %d\n", size);
}
return FALSE;
}
static gboolean cmplog_get_operand_value(GumCpuContext *context,
cmplog_ctx_t *ctx, gsize *val) {
switch (ctx->type) {
case X86_OP_REG:
*val = ctx_read_reg(context, ctx->reg);
return TRUE;
case X86_OP_IMM:
*val = ctx->imm;
return TRUE;
case X86_OP_MEM:
return cmplog_read_mem(context, ctx->size, &ctx->mem, val);
default:
FATAL("Invalid operand type: %d\n", ctx->type);
}
return FALSE;
}
static void cmplog_call_callout(GumCpuContext *context, gpointer user_data) {
UNUSED_PARAMETER(user_data);
gsize address = ctx_read_reg(context, X86_REG_EIP);
gsize *esp = (gsize *)ctx_read_reg(context, X86_REG_ESP);
if (!cmplog_is_readable(GPOINTER_TO_SIZE(esp), 12)) return;
/*
* This callout is place immediately before the call instruction, and hence
* the return address is not yet pushed on the top of the stack.
*/
gsize arg1 = esp[0];
gsize arg2 = esp[1];
if (((G_MAXULONG - arg1) < 32) || ((G_MAXULONG - arg2) < 32)) return;
if (!cmplog_is_readable(arg1, 32) || !cmplog_is_readable(arg2, 32)) return;
void *ptr1 = GSIZE_TO_POINTER(arg1);
void *ptr2 = GSIZE_TO_POINTER(arg2);
uintptr_t k = address;
k = (k >> 4) ^ (k << 8);
k &= CMP_MAP_W - 1;
__afl_cmp_map->headers[k].type = CMP_TYPE_RTN;
u32 hits = __afl_cmp_map->headers[k].hits;
__afl_cmp_map->headers[k].hits = hits + 1;
__afl_cmp_map->headers[k].shape = 31;
hits &= CMP_MAP_RTN_H - 1;
gum_memcpy(((struct cmpfn_operands *)__afl_cmp_map->log[k])[hits].v0, ptr1,
32);
gum_memcpy(((struct cmpfn_operands *)__afl_cmp_map->log[k])[hits].v1, ptr2,
32);
}
static void cmplog_instrument_put_operand(cmplog_ctx_t *ctx,
cs_x86_op * operand) {
ctx->type = operand->type;
ctx->size = operand->size;
switch (operand->type) {
case X86_OP_REG:
gum_memcpy(&ctx->reg, &operand->reg, sizeof(x86_reg));
break;
case X86_OP_IMM:
gum_memcpy(&ctx->imm, &operand->imm, sizeof(int64_t));
break;
case X86_OP_MEM:
gum_memcpy(&ctx->mem, &operand->mem, sizeof(x86_op_mem));
break;
default:
FATAL("Invalid operand type: %d\n", operand->type);
}
}
static void cmplog_instrument_call(const cs_insn * instr,
GumStalkerIterator *iterator) {
cs_x86 x86 = instr->detail->x86;
cs_x86_op *operand;
if (instr->id != X86_INS_CALL) return;
if (x86.op_count != 1) return;
operand = &x86.operands[0];
if (operand->type == X86_OP_INVALID) return;
if (operand->type == X86_OP_MEM && operand->mem.segment != X86_REG_INVALID)
return;
gum_stalker_iterator_put_callout(iterator, cmplog_call_callout, NULL, NULL);
}
static void cmplog_handle_cmp_sub(GumCpuContext *context, gsize operand1,
gsize operand2, uint8_t size) {
gsize address = ctx_read_reg(context, X86_REG_EIP);
register uintptr_t k = (uintptr_t)address;
k = (k >> 4) ^ (k << 8);
k &= CMP_MAP_W - 1;
__afl_cmp_map->headers[k].type = CMP_TYPE_INS;
u32 hits = __afl_cmp_map->headers[k].hits;
__afl_cmp_map->headers[k].hits = hits + 1;
__afl_cmp_map->headers[k].shape = (size - 1);
hits &= CMP_MAP_H - 1;
__afl_cmp_map->log[k][hits].v0 = operand1;
__afl_cmp_map->log[k][hits].v1 = operand2;
}
static void cmplog_cmp_sub_callout(GumCpuContext *context, gpointer user_data) {
cmplog_pair_ctx_t *ctx = (cmplog_pair_ctx_t *)user_data;
gsize operand1;
gsize operand2;
if (ctx->operand1.size != ctx->operand2.size) FATAL("Operand size mismatch");
if (!cmplog_get_operand_value(context, &ctx->operand1, &operand1)) { return; }
if (!cmplog_get_operand_value(context, &ctx->operand2, &operand2)) { return; }
cmplog_handle_cmp_sub(context, operand1, operand2, ctx->operand1.size);
}
static void cmplog_instrument_cmp_sub_put_callout(GumStalkerIterator *iterator,
cs_x86_op * operand1,
cs_x86_op *operand2) {
cmplog_pair_ctx_t *ctx = g_malloc(sizeof(cmplog_pair_ctx_t));
if (ctx == NULL) return;
cmplog_instrument_put_operand(&ctx->operand1, operand1);
cmplog_instrument_put_operand(&ctx->operand2, operand2);
gum_stalker_iterator_put_callout(iterator, cmplog_cmp_sub_callout, ctx,
g_free);
}
static void cmplog_instrument_cmp_sub(const cs_insn * instr,
GumStalkerIterator *iterator) {
cs_x86 x86 = instr->detail->x86;
cs_x86_op *operand1;
cs_x86_op *operand2;
switch (instr->id) {
case X86_INS_CMP:
case X86_INS_SUB:
break;
default:
return;
}
if (x86.op_count != 2) return;
operand1 = &x86.operands[0];
operand2 = &x86.operands[1];
if (operand1->type == X86_OP_INVALID) return;
if (operand2->type == X86_OP_INVALID) return;
if ((operand1->type == X86_OP_MEM) &&
(operand1->mem.segment != X86_REG_INVALID))
return;
if ((operand2->type == X86_OP_MEM) &&
(operand2->mem.segment != X86_REG_INVALID))
return;
cmplog_instrument_cmp_sub_put_callout(iterator, operand1, operand2);
}
void cmplog_instrument(const cs_insn *instr, GumStalkerIterator *iterator) { void cmplog_instrument(const cs_insn *instr, GumStalkerIterator *iterator) {
UNUSED_PARAMETER(instr); if (__afl_cmp_map == NULL) return;
UNUSED_PARAMETER(iterator);
if (__afl_cmp_map == NULL) { return; } cmplog_instrument_call(instr, iterator);
FATAL("CMPLOG mode not supported on this architecture"); cmplog_instrument_cmp_sub(instr, iterator);
} }

View File

@ -0,0 +1,114 @@
#include "frida-gum.h"
#include "debug.h"
#include "ctx.h"
#if defined(__x86_64__)
#define X86_REG_8L(LABEL, REG) \
case LABEL: { \
\
return REG & GUM_INT8_MASK; \
\
}
#define X86_REG_8H(LABEL, REG) \
case LABEL: { \
\
return (REG & GUM_INT16_MASK) >> 8; \
\
}
#define X86_REG_16(LABEL, REG) \
case LABEL: { \
\
return (REG & GUM_INT16_MASK); \
\
}
#define X86_REG_32(LABEL, REG) \
case LABEL: { \
\
return (REG & GUM_INT32_MASK); \
\
}
#define X86_REG_64(LABEL, REG) \
case LABEL: { \
\
return (REG); \
\
}
gsize ctx_read_reg(GumX64CpuContext *ctx, x86_reg reg) {
switch (reg) {
X86_REG_8L(X86_REG_AL, ctx->rax)
X86_REG_8L(X86_REG_BL, ctx->rbx)
X86_REG_8L(X86_REG_CL, ctx->rcx)
X86_REG_8L(X86_REG_DL, ctx->rdx)
X86_REG_8L(X86_REG_BPL, ctx->rbp)
X86_REG_8L(X86_REG_SIL, ctx->rsi)
X86_REG_8L(X86_REG_DIL, ctx->rdi)
X86_REG_8H(X86_REG_AH, ctx->rax)
X86_REG_8H(X86_REG_BH, ctx->rbx)
X86_REG_8H(X86_REG_CH, ctx->rcx)
X86_REG_8H(X86_REG_DH, ctx->rdx)
X86_REG_16(X86_REG_AX, ctx->rax)
X86_REG_16(X86_REG_BX, ctx->rbx)
X86_REG_16(X86_REG_CX, ctx->rcx)
X86_REG_16(X86_REG_DX, ctx->rdx)
X86_REG_16(X86_REG_DI, ctx->rdi)
X86_REG_16(X86_REG_SI, ctx->rsi)
X86_REG_16(X86_REG_BP, ctx->rbp)
X86_REG_32(X86_REG_EAX, ctx->rax)
X86_REG_32(X86_REG_ECX, ctx->rcx)
X86_REG_32(X86_REG_EDX, ctx->rdx)
X86_REG_32(X86_REG_EBX, ctx->rbx)
X86_REG_32(X86_REG_ESP, ctx->rsp)
X86_REG_32(X86_REG_EBP, ctx->rbp)
X86_REG_32(X86_REG_ESI, ctx->rsi)
X86_REG_32(X86_REG_EDI, ctx->rdi)
X86_REG_32(X86_REG_R8D, ctx->r8)
X86_REG_32(X86_REG_R9D, ctx->r9)
X86_REG_32(X86_REG_R10D, ctx->r10)
X86_REG_32(X86_REG_R11D, ctx->r11)
X86_REG_32(X86_REG_R12D, ctx->r12)
X86_REG_32(X86_REG_R13D, ctx->r13)
X86_REG_32(X86_REG_R14D, ctx->r14)
X86_REG_32(X86_REG_R15D, ctx->r15)
X86_REG_32(X86_REG_EIP, ctx->rip)
X86_REG_64(X86_REG_RAX, ctx->rax)
X86_REG_64(X86_REG_RCX, ctx->rcx)
X86_REG_64(X86_REG_RDX, ctx->rdx)
X86_REG_64(X86_REG_RBX, ctx->rbx)
X86_REG_64(X86_REG_RSP, ctx->rsp)
X86_REG_64(X86_REG_RBP, ctx->rbp)
X86_REG_64(X86_REG_RSI, ctx->rsi)
X86_REG_64(X86_REG_RDI, ctx->rdi)
X86_REG_64(X86_REG_R8, ctx->r8)
X86_REG_64(X86_REG_R9, ctx->r9)
X86_REG_64(X86_REG_R10, ctx->r10)
X86_REG_64(X86_REG_R11, ctx->r11)
X86_REG_64(X86_REG_R12, ctx->r12)
X86_REG_64(X86_REG_R13, ctx->r13)
X86_REG_64(X86_REG_R14, ctx->r14)
X86_REG_64(X86_REG_R15, ctx->r15)
X86_REG_64(X86_REG_RIP, ctx->rip)
default:
FATAL("Failed to read register: %d", reg);
return 0;
}
}
#endif

View File

@ -0,0 +1,81 @@
#include "frida-gum.h"
#include "debug.h"
#include "ctx.h"
#if defined(__i386__)
#define X86_REG_8L(LABEL, REG) \
case LABEL: { \
\
return REG & GUM_INT8_MASK; \
\
}
#define X86_REG_8H(LABEL, REG) \
case LABEL: { \
\
return (REG & GUM_INT16_MASK) >> 8; \
\
}
#define X86_REG_16(LABEL, REG) \
case LABEL: { \
\
return (REG & GUM_INT16_MASK); \
\
}
#define X86_REG_32(LABEL, REG) \
case LABEL: { \
\
return (REG & GUM_INT32_MASK); \
\
}
gsize ctx_read_reg(GumIA32CpuContext *ctx, x86_reg reg) {
switch (reg) {
X86_REG_8L(X86_REG_AL, ctx->eax)
X86_REG_8L(X86_REG_BL, ctx->ebx)
X86_REG_8L(X86_REG_CL, ctx->ecx)
X86_REG_8L(X86_REG_DL, ctx->edx)
X86_REG_8L(X86_REG_BPL, ctx->ebp)
X86_REG_8L(X86_REG_SIL, ctx->esi)
X86_REG_8L(X86_REG_DIL, ctx->edi)
X86_REG_8H(X86_REG_AH, ctx->eax)
X86_REG_8H(X86_REG_BH, ctx->ebx)
X86_REG_8H(X86_REG_CH, ctx->ecx)
X86_REG_8H(X86_REG_DH, ctx->edx)
X86_REG_16(X86_REG_AX, ctx->eax)
X86_REG_16(X86_REG_BX, ctx->ebx)
X86_REG_16(X86_REG_CX, ctx->ecx)
X86_REG_16(X86_REG_DX, ctx->edx)
X86_REG_16(X86_REG_DI, ctx->edi)
X86_REG_16(X86_REG_SI, ctx->esi)
X86_REG_16(X86_REG_BP, ctx->ebp)
X86_REG_32(X86_REG_EAX, ctx->eax)
X86_REG_32(X86_REG_ECX, ctx->ecx)
X86_REG_32(X86_REG_EDX, ctx->edx)
X86_REG_32(X86_REG_EBX, ctx->ebx)
X86_REG_32(X86_REG_ESP, ctx->esp)
X86_REG_32(X86_REG_EBP, ctx->ebp)
X86_REG_32(X86_REG_ESI, ctx->esi)
X86_REG_32(X86_REG_EDI, ctx->edi)
X86_REG_32(X86_REG_EIP, ctx->eip)
default:
FATAL("Failed to read register: %d", reg);
return 0;
}
}
#endif

View File

@ -5,6 +5,7 @@
#include "config.h" #include "config.h"
#include "debug.h" #include "debug.h"
#include "asan.h"
#include "entry.h" #include "entry.h"
#include "frida_cmplog.h" #include "frida_cmplog.h"
#include "instrument.h" #include "instrument.h"
@ -33,7 +34,7 @@ __attribute__((hot)) static void on_basic_block(GumCpuContext *context,
*/ */
static char buffer[200]; static char buffer[200];
int len; int len;
guint64 current_pc = (guint64)user_data; GumAddress current_pc = GUM_ADDRESS(user_data);
uint8_t * cursor; uint8_t * cursor;
uint64_t value; uint64_t value;
if (unlikely(tracing)) { if (unlikely(tracing)) {
@ -85,8 +86,8 @@ static void instr_basic_block(GumStalkerIterator *iterator,
if (begin) { if (begin) {
prefetch_write((void *)instr->address); prefetch_write(GSIZE_TO_POINTER(instr->address));
if (!range_is_excluded((void *)instr->address)) { if (!range_is_excluded(GSIZE_TO_POINTER(instr->address))) {
if (optimize) { if (optimize) {
@ -94,8 +95,8 @@ static void instr_basic_block(GumStalkerIterator *iterator,
} else { } else {
gum_stalker_iterator_put_callout(iterator, on_basic_block, gum_stalker_iterator_put_callout(
(gpointer)instr->address, NULL); iterator, on_basic_block, GSIZE_TO_POINTER(instr->address), NULL);
} }
@ -105,8 +106,9 @@ static void instr_basic_block(GumStalkerIterator *iterator,
} }
if (!range_is_excluded((void *)instr->address)) { if (!range_is_excluded(GSIZE_TO_POINTER(instr->address))) {
asan_instrument(instr, iterator);
cmplog_instrument(instr, iterator); cmplog_instrument(instr, iterator);
} }
@ -142,6 +144,7 @@ void instrument_init(void) {
transformer = transformer =
gum_stalker_transformer_make_from_callback(instr_basic_block, NULL, NULL); gum_stalker_transformer_make_from_callback(instr_basic_block, NULL, NULL);
asan_init();
cmplog_init(); cmplog_init();
} }

View File

@ -3,6 +3,7 @@
#include "debug.h" #include "debug.h"
#include "instrument.h" #include "instrument.h"
#include "util.h"
#if defined(__arm__) #if defined(__arm__)
@ -15,6 +16,8 @@ gboolean instrument_is_coverage_optimize_supported(void) {
void instrument_coverage_optimize(const cs_insn * instr, void instrument_coverage_optimize(const cs_insn * instr,
GumStalkerOutput *output) { GumStalkerOutput *output) {
UNUSED_PARAMETER(instr);
UNUSED_PARAMETER(output);
FATAL("Optimized coverage not supported on this architecture"); FATAL("Optimized coverage not supported on this architecture");
} }

View File

@ -3,19 +3,81 @@
#include "debug.h" #include "debug.h"
#include "instrument.h" #include "instrument.h"
#include "util.h"
#if defined(__i386__) #if defined(__i386__)
static GumAddress current_log_impl = GUM_ADDRESS(0);
static void instrument_coverage_function(GumX86Writer *cw) {
gum_x86_writer_put_pushfx(cw);
gum_x86_writer_put_push_reg(cw, GUM_REG_ECX);
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_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);
gum_x86_writer_put_add_reg_imm(cw, GUM_REG_EDX, GUM_ADDRESS(__afl_area_ptr));
/* add byte ptr [edx], 1 */
uint8_t add_byte_ptr_edx_1[] = {0x80, 0x02, 0x01};
gum_x86_writer_put_bytes(cw, add_byte_ptr_edx_1, sizeof(add_byte_ptr_edx_1));
/* adc byte ptr [edx], 0 */
uint8_t adc_byte_ptr_edx_0[] = {0x80, 0x12, 0x00};
gum_x86_writer_put_bytes(cw, adc_byte_ptr_edx_0, sizeof(adc_byte_ptr_edx_0));
gum_x86_writer_put_shr_reg_u8(cw, GUM_REG_EDI, 1);
gum_x86_writer_put_mov_reg_ptr_reg(cw, GUM_REG_ECX, GUM_REG_EDI);
gum_x86_writer_put_pop_reg(cw, GUM_REG_EDX);
gum_x86_writer_put_pop_reg(cw, GUM_REG_ECX);
gum_x86_writer_put_popfx(cw);
gum_x86_writer_put_ret(cw);
}
gboolean instrument_is_coverage_optimize_supported(void) { gboolean instrument_is_coverage_optimize_supported(void) {
return false; return true;
} }
void instrument_coverage_optimize(const cs_insn * instr, void instrument_coverage_optimize(const cs_insn * instr,
GumStalkerOutput *output) { GumStalkerOutput *output) {
FATAL("Optimized coverage not supported on this architecture"); UNUSED_PARAMETER(instr);
UNUSED_PARAMETER(output);
guint64 current_pc = instr->address;
guint64 area_offset = (current_pc >> 4) ^ (current_pc << 8);
area_offset &= MAP_SIZE - 1;
GumX86Writer *cw = output->writer.x86;
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)) {
gconstpointer after_log_impl = cw->code + 1;
gum_x86_writer_put_jmp_near_label(cw, after_log_impl);
current_log_impl = cw->pc;
instrument_coverage_function(cw);
gum_x86_writer_put_label(cw, after_log_impl);
}
// gum_x86_writer_put_breakpoint(cw);
gum_x86_writer_put_push_reg(cw, GUM_REG_EDI);
gum_x86_writer_put_mov_reg_address(cw, GUM_REG_EDI, area_offset);
gum_x86_writer_put_call_address(cw, current_log_impl);
gum_x86_writer_put_pop_reg(cw, GUM_REG_EDI);
} }

View File

@ -90,7 +90,8 @@ static void lib_read_text_section(lib_details_t *lib_details, Elf_Ehdr *hdr) {
if (!found_preferred_base) { FATAL("Failed to find preferred load address"); } if (!found_preferred_base) { FATAL("Failed to find preferred load address"); }
OKF("Image preferred load address 0x%016lx", preferred_base); OKF("Image preferred load address 0x%016" G_GSIZE_MODIFIER "x",
preferred_base);
shdr = (Elf_Shdr *)((char *)hdr + hdr->e_shoff); shdr = (Elf_Shdr *)((char *)hdr + hdr->e_shoff);
shstrtab = &shdr[hdr->e_shstrndx]; shstrtab = &shdr[hdr->e_shstrndx];
@ -107,15 +108,16 @@ static void lib_read_text_section(lib_details_t *lib_details, Elf_Ehdr *hdr) {
if (curr->sh_name == 0) continue; if (curr->sh_name == 0) continue;
section_name = &shstr[curr->sh_name]; section_name = &shstr[curr->sh_name];
OKF("Section: %2lu - base: 0x%016lX size: 0x%016lX %s", i, curr->sh_addr, OKF("Section: %2" G_GSIZE_MODIFIER "u - base: 0x%016" G_GSIZE_MODIFIER
curr->sh_size, section_name); "X size: 0x%016" G_GSIZE_MODIFIER "X %s",
i, curr->sh_addr, curr->sh_size, section_name);
if (memcmp(section_name, text_name, sizeof(text_name)) == 0 && if (memcmp(section_name, text_name, sizeof(text_name)) == 0 &&
text_base == 0) { text_base == 0) {
text_base = lib_details->base_address + curr->sh_addr - preferred_base; text_base = lib_details->base_address + curr->sh_addr - preferred_base;
text_limit = text_base + curr->sh_size; text_limit = text_base + curr->sh_size;
OKF("> text_addr: 0x%016lX", text_base); OKF("> text_addr: 0x%016" G_GINT64_MODIFIER "X", text_base);
OKF("> text_limit: 0x%016lX", text_limit); OKF("> text_limit: 0x%016" G_GINT64_MODIFIER "X", text_limit);
} }
@ -153,7 +155,8 @@ void lib_init(void) {
lib_details_t lib_details; lib_details_t lib_details;
gum_process_enumerate_modules(lib_find_exe, &lib_details); gum_process_enumerate_modules(lib_find_exe, &lib_details);
OKF("Executable: 0x%016lx - %s", lib_details.base_address, lib_details.path); OKF("Executable: 0x%016" G_GINT64_MODIFIER "x - %s", lib_details.base_address,
lib_details.path);
lib_get_text_section(&lib_details); lib_get_text_section(&lib_details);
} }

View File

@ -75,16 +75,22 @@ static void on_main_os(int argc, char **argv, char **envp) {
#endif #endif
static int *on_main(int argc, char **argv, char **envp) { static void embedded_init() {
void *fork_addr; static gboolean initialized = false;
if (!initialized) {
on_main_os(argc, argv, envp); gum_init_embedded();
initialized = true;
unintercept_self(); }
}
void afl_frida_start() {
embedded_init();
stalker_init(); stalker_init();
lib_init(); lib_init();
entry_init(); entry_init();
instrument_init(); instrument_init();
@ -92,12 +98,23 @@ static int *on_main(int argc, char **argv, char **envp) {
prefetch_init(); prefetch_init();
ranges_init(); ranges_init();
fork_addr = GSIZE_TO_POINTER(gum_module_find_export_by_name(NULL, "fork")); void *fork_addr =
GSIZE_TO_POINTER(gum_module_find_export_by_name(NULL, "fork"));
intercept(fork_addr, on_fork, NULL); intercept(fork_addr, on_fork, NULL);
stalker_start(); stalker_start();
entry_run(); entry_run();
}
static int *on_main(int argc, char **argv, char **envp) {
on_main_os(argc, argv, envp);
unintercept_self();
afl_frida_start();
return main_fn(argc, argv, envp); return main_fn(argc, argv, envp);
} }
@ -149,13 +166,7 @@ static void intercept_main(void) {
__attribute__((constructor)) static void init(void) { __attribute__((constructor)) static void init(void) {
gum_init_embedded(); embedded_init();
if (!gum_stalker_is_supported()) {
gum_deinit_embedded();
FATAL("Failed to initialize embedded");
}
intercept_main(); intercept_main();

View File

@ -1,9 +1,9 @@
#include "frida-gum.h" #include "frida-gum.h"
#include "debug.h" #include "config.h"
#include "instrument.h"
#include "persistent.h" #include "persistent.h"
#include "util.h"
#if defined(__i386__) #if defined(__i386__)
@ -38,16 +38,239 @@ struct x86_regs {
typedef struct x86_regs arch_api_regs; typedef struct x86_regs arch_api_regs;
static arch_api_regs saved_regs = {0};
static void * saved_return = NULL;
gboolean persistent_is_supported(void) { gboolean persistent_is_supported(void) {
return false; return true;
}
static void instrument_persitent_save_regs(GumX86Writer * cw,
struct x86_regs *regs) {
GumAddress regs_address = GUM_ADDRESS(regs);
/* Should be pushing FPU here, but meh */
gum_x86_writer_put_pushfx(cw);
gum_x86_writer_put_push_reg(cw, GUM_REG_EAX);
gum_x86_writer_put_mov_reg_address(cw, GUM_REG_EAX, regs_address);
gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_EAX, (0x4 * 1),
GUM_REG_EBX);
gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_EAX, (0x4 * 2),
GUM_REG_ECX);
gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_EAX, (0x4 * 3),
GUM_REG_EDX);
gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_EAX, (0x4 * 4),
GUM_REG_EDI);
gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_EAX, (0x4 * 5),
GUM_REG_ESI);
gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_EAX, (0x4 * 6),
GUM_REG_EBP);
/* Store RIP */
gum_x86_writer_put_mov_reg_address(cw, GUM_REG_EBX,
GUM_ADDRESS(persistent_start));
gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_EAX, (0x4 * 7),
GUM_REG_EBX);
/* Store adjusted RSP */
gum_x86_writer_put_mov_reg_reg(cw, GUM_REG_EBX, GUM_REG_ESP);
/* RED_ZONE + Saved flags, RAX */
gum_x86_writer_put_add_reg_imm(cw, GUM_REG_EBX, (0x4 * 2));
gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_EAX, (0x4 * 8),
GUM_REG_EBX);
/* Save the flags */
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EBX, GUM_REG_ESP, 0x4);
gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_EAX, (0x4 * 9),
GUM_REG_EBX);
/* Save the RAX */
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EBX, GUM_REG_ESP, 0x0);
gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_EAX, (0x4 * 0),
GUM_REG_EBX);
/* Pop the saved values */
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_ESP, GUM_REG_ESP, 0x8);
}
static void instrument_persitent_restore_regs(GumX86Writer * cw,
struct x86_regs *regs) {
GumAddress regs_address = GUM_ADDRESS(regs);
gum_x86_writer_put_mov_reg_address(cw, GUM_REG_EAX, regs_address);
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_ECX, GUM_REG_EAX,
(0x4 * 2));
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EDX, GUM_REG_EAX,
(0x4 * 3));
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EDI, GUM_REG_EAX,
(0x4 * 4));
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_ESI, GUM_REG_EAX,
(0x4 * 5));
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EBP, GUM_REG_EAX,
(0x4 * 6));
/* Don't restore RIP or RSP */
/* Restore RBX, RAX & Flags */
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EBX, GUM_REG_EAX,
(0x4 * 1));
gum_x86_writer_put_push_reg(cw, GUM_REG_EBX);
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EBX, GUM_REG_EAX,
(0x4 * 0));
gum_x86_writer_put_push_reg(cw, GUM_REG_EBX);
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EBX, GUM_REG_EAX,
(0x4 * 9));
gum_x86_writer_put_push_reg(cw, GUM_REG_EBX);
gum_x86_writer_put_popfx(cw);
gum_x86_writer_put_pop_reg(cw, GUM_REG_EAX);
gum_x86_writer_put_pop_reg(cw, GUM_REG_EBX);
}
static void instrument_save_ret(GumX86Writer *cw, void **saved_return_ptr) {
GumAddress saved_return_address = GUM_ADDRESS(saved_return_ptr);
gum_x86_writer_put_push_reg(cw, GUM_REG_EAX);
gum_x86_writer_put_push_reg(cw, GUM_REG_EBX);
gum_x86_writer_put_mov_reg_address(cw, GUM_REG_EAX, saved_return_address);
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EBX, GUM_REG_ESP, 0x8);
gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_EAX, 0, GUM_REG_EBX);
gum_x86_writer_put_pop_reg(cw, GUM_REG_EBX);
gum_x86_writer_put_pop_reg(cw, GUM_REG_EAX);
}
static void instrument_jump_ret(GumX86Writer *cw, void **saved_return_ptr) {
GumAddress saved_return_address = GUM_ADDRESS(saved_return_ptr);
/* Place holder for ret */
gum_x86_writer_put_push_reg(cw, GUM_REG_EAX);
gum_x86_writer_put_push_reg(cw, GUM_REG_EAX);
gum_x86_writer_put_mov_reg_address(cw, GUM_REG_EAX, saved_return_address);
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EAX, GUM_REG_EAX, 0);
gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_ESP, 0x4, GUM_REG_EAX);
gum_x86_writer_put_pop_reg(cw, GUM_REG_EAX);
gum_x86_writer_put_ret(cw);
}
static int instrument_afl_persistent_loop_func(void) {
int ret = __afl_persistent_loop(persistent_count);
previous_pc = 0;
return ret;
}
static void instrument_afl_persistent_loop(GumX86Writer *cw) {
gum_x86_writer_put_call_address_with_arguments(
cw, GUM_CALL_CAPI, GUM_ADDRESS(instrument_afl_persistent_loop_func), 0);
gum_x86_writer_put_test_reg_reg(cw, GUM_REG_EAX, GUM_REG_EAX);
}
static void persistent_prologue_hook(GumX86Writer *cw, struct x86_regs *regs) {
if (hook == NULL) return;
gum_x86_writer_put_mov_reg_address(cw, GUM_REG_ECX,
GUM_ADDRESS(&__afl_fuzz_len));
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_ECX, GUM_REG_ECX, 0);
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_ECX, GUM_REG_ECX, 0);
gum_x86_writer_put_mov_reg_address(cw, GUM_REG_EDX,
GUM_ADDRESS(&__afl_fuzz_ptr));
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EDX, GUM_REG_EDX, 0);
/* 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,
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);
} }
void persistent_prologue(GumStalkerOutput *output) { void persistent_prologue(GumStalkerOutput *output) {
UNUSED_PARAMETER(output); /*
FATAL("Persistent mode not supported on this architecture"); * SAVE REGS
* SAVE RET
* POP RET
* loop:
* CALL instrument_afl_persistent_loop
* TEST EAX, EAX
* JZ end:
* call hook (optionally)
* RESTORE REGS
* call original
* jmp loop:
*
* end:
* JMP SAVED RET
*
* original:
* INSTRUMENTED PERSISTENT FUNC
*/
GumX86Writer *cw = output->writer.x86;
gconstpointer loop = cw->code + 1;
/* Stack must be 16-byte aligned per ABI */
instrument_persitent_save_regs(cw, &saved_regs);
/* Stash and pop the return value */
instrument_save_ret(cw, &saved_return);
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_ESP, GUM_REG_ESP, (4));
/* loop: */
gum_x86_writer_put_label(cw, loop);
/* call instrument_prologue_func */
instrument_afl_persistent_loop(cw);
/* jz done */
gconstpointer done = cw->code + 1;
gum_x86_writer_put_jcc_near_label(cw, X86_INS_JE, done, GUM_UNLIKELY);
/* Optionally call the persistent hook */
persistent_prologue_hook(cw, &saved_regs);
instrument_persitent_restore_regs(cw, &saved_regs);
gconstpointer original = cw->code + 1;
/* call original */
gum_x86_writer_put_call_near_label(cw, original);
/* jmp loop */
gum_x86_writer_put_jmp_near_label(cw, loop);
/* done: */
gum_x86_writer_put_label(cw, done);
instrument_jump_ret(cw, &saved_return);
/* original: */
gum_x86_writer_put_label(cw, original);
gum_x86_writer_flush(cw);
} }

View File

@ -7,6 +7,8 @@ static GumStalker *stalker = NULL;
void stalker_init(void) { void stalker_init(void) {
if (!gum_stalker_is_supported()) { FATAL("Failed to initialize embedded"); }
stalker = gum_stalker_new(); stalker = gum_stalker_new();
if (stalker == NULL) { FATAL("Failed to initialize stalker"); } if (stalker == NULL) { FATAL("Failed to initialize stalker"); }

View File

@ -2,8 +2,8 @@ PWD:=$(shell pwd)/
ROOT:=$(shell realpath $(PWD)../../../)/ ROOT:=$(shell realpath $(PWD)../../../)/
BUILD_DIR:=$(PWD)build/ BUILD_DIR:=$(PWD)build/
TEST_CMPLOG_DIR:=$(ROOT)qemu_mode/libcompcov/ TEST_CMPLOG_SRC=$(PWD)cmplog.c
TEST_CMPLOG_OBJ=$(TEST_CMPLOG_DIR)compcovtest TEST_CMPLOG_OBJ=$(BUILD_DIR)compcovtest
TEST_BIN:=$(PWD)../../build/test TEST_BIN:=$(PWD)../../build/test
@ -13,20 +13,14 @@ CMP_LOG_INPUT:=$(TEST_DATA_DIR)in
QEMU_OUT:=$(BUILD_DIR)qemu-out QEMU_OUT:=$(BUILD_DIR)qemu-out
FRIDA_OUT:=$(BUILD_DIR)frida-out FRIDA_OUT:=$(BUILD_DIR)frida-out
ARCH=$(shell uname -m) .PHONY: all 32 clean qemu frida format
ifeq "$(ARCH)" "aarch64"
AFL_FRIDA_INST_RANGES=$(shell $(PWD)get_section_addrs.py -f $(TEST_CMPLOG_OBJ) -s .text -b 0x0000aaaaaaaaa000)
endif
ifeq "$(ARCH)" "x86_64" all: $(TEST_CMPLOG_OBJ)
AFL_FRIDA_INST_RANGES=$(shell $(PWD)get_section_addrs.py -f $(TEST_CMPLOG_OBJ) -s .text -b 0x0000555555554000)
endif
.PHONY: all clean qemu frida
all:
make -C $(ROOT)frida_mode/ make -C $(ROOT)frida_mode/
32:
CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all
$(BUILD_DIR): $(BUILD_DIR):
mkdir -p $@ mkdir -p $@
@ -34,33 +28,42 @@ $(TEST_DATA_DIR): | $(BUILD_DIR)
mkdir -p $@ mkdir -p $@
$(CMP_LOG_INPUT): | $(TEST_DATA_DIR) $(CMP_LOG_INPUT): | $(TEST_DATA_DIR)
truncate -s 64 $@ echo -n "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" > $@
$(TEST_CMPLOG_OBJ): $(TEST_CMPLOG_DIR)compcovtest.cc $(TEST_CMPLOG_OBJ): $(TEST_CMPLOG_SRC) | $(BUILD_DIR)
make -C $(TEST_CMPLOG_DIR) compcovtest $(CXX) -std=c++11 -g $(CFLAGS) $(LDFLAGS) $< -o $@
qemu: $(TEST_CMPLOG_OBJ) $(CMP_LOG_INPUT) qemu: $(TEST_CMPLOG_OBJ) $(CMP_LOG_INPUT)
$(ROOT)afl-fuzz \ $(ROOT)afl-fuzz \
-D \
-Q \ -Q \
-i $(TEST_DATA_DIR) \ -i $(TEST_DATA_DIR) \
-o $(QEMU_OUT) \ -o $(QEMU_OUT) \
-c 0 \ -c 0 \
-l 3AT \ -l 3AT \
-Z \
-- \ -- \
$(TEST_CMPLOG_OBJ) @@ $(TEST_CMPLOG_OBJ) @@
frida: $(TEST_CMPLOG_OBJ) $(CMP_LOG_INPUT) frida: $(TEST_CMPLOG_OBJ) $(CMP_LOG_INPUT)
XAFL_FRIDA_INST_RANGES=$(AFL_FRIDA_INST_RANGES) \
$(ROOT)afl-fuzz \ $(ROOT)afl-fuzz \
-D \
-O \ -O \
-i $(TEST_DATA_DIR) \ -i $(TEST_DATA_DIR) \
-o $(FRIDA_OUT) \ -o $(FRIDA_OUT) \
-c 0 \ -c 0 \
-l 3AT \ -l 3AT \
-Z \
-- \ -- \
$(TEST_CMPLOG_OBJ) @@ $(TEST_CMPLOG_OBJ) @@
debug: $(TEST_CMPLOG_OBJ) $(CMP_LOG_INPUT)
gdb \
--ex 'set environment LD_PRELOAD=$(ROOT)afl-frida-trace.so' \
--ex 'set disassembly-flavor intel' \
--ex 'r $(CMP_LOG_INPUT)' \
--args $(TEST_CMPLOG_OBJ) $(CMP_LOG_INPUT)
clean: clean:
rm -rf $(BUILD_DIR) rm -rf $(BUILD_DIR)
format:
cd $(ROOT) && echo $(TEST_CMPLOG_SRC) | xargs -L1 ./.custom-format.py -i

View File

@ -2,6 +2,10 @@ all:
@echo trying to use GNU make... @echo trying to use GNU make...
@gmake all || echo please install GNUmake @gmake all || echo please install GNUmake
32:
@echo trying to use GNU make...
@gmake 32 || echo please install GNUmake
clean: clean:
@gmake clean @gmake clean
@ -10,3 +14,9 @@ qemu:
frida: frida:
@gmake frida @gmake frida
format:
@gmake format
debug:
@gmake debug

View File

@ -0,0 +1,100 @@
/////////////////////////////////////////////////////////////////////////
//
// Author: Mateusz Jurczyk (mjurczyk@google.com)
//
// Copyright 2019-2020 Google LLC
//
// 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
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// solution: echo -ne 'The quick brown fox jumps over the lazy
// dog\xbe\xba\xfe\xca\xbe\xba\xfe\xca\xde\xc0\xad\xde\xef\xbe' | ./compcovtest
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv) {
char buffer[44] = {/* zero padding */};
FILE *file = stdin;
if (argc > 1) {
if ((file = fopen(argv[1], "r")) == NULL) {
perror(argv[1]);
exit(-1);
}
}
fread(buffer, 1, sizeof(buffer) - 1, file);
if (memcmp(&buffer[0], "The quick brown fox ", 20) != 0 ||
strncmp(&buffer[20], "jumps over ", 11) != 0 ||
strcmp(&buffer[31], "the lazy dog") != 0) {
if (argc > 1) { fclose(file); }
return 1;
}
#if defined(__x86_64__)
uint64_t x = 0;
fread(&x, sizeof(x), 1, file);
if (x != 0xCAFEBABECAFEBABE) {
if (argc > 1) { fclose(file); }
return 2;
}
#endif
uint32_t y = 0;
fread(&y, sizeof(y), 1, file);
if (y != 0xDEADC0DE) {
if (argc > 1) { fclose(file); }
return 3;
}
uint16_t z = 0;
fread(&z, sizeof(z), 1, file);
switch (z) {
case 0xBEEF:
break;
default:
if (argc > 1) { fclose(file); }
return 4;
}
printf("Puzzle solved, congrats!\n");
abort();
if (argc > 1) { fclose(file); }
return 0;
}

View File

@ -12,6 +12,18 @@ FRIDA_OUT:=$(BUILD_DIR)frida-out
GET_SYMBOL_ADDR:=$(ROOT)frida_mode/test/png/persistent/get_symbol_addr.py GET_SYMBOL_ADDR:=$(ROOT)frida_mode/test/png/persistent/get_symbol_addr.py
ifndef ARCH
ARCH=$(shell uname -m)
ifeq "$(ARCH)" "aarch64"
ARCH:=arm64
endif
ifeq "$(ARCH)" "i686"
ARCH:=x86
endif
endif
ARCH=$(shell uname -m) ARCH=$(shell uname -m)
ifeq "$(ARCH)" "aarch64" ifeq "$(ARCH)" "aarch64"
AFL_ENTRYPOINT=$(shell $(GET_SYMBOL_ADDR) -f $(TESTINSTBIN) -s run -b 0x0000aaaaaaaaa000) AFL_ENTRYPOINT=$(shell $(GET_SYMBOL_ADDR) -f $(TESTINSTBIN) -s run -b 0x0000aaaaaaaaa000)
@ -21,11 +33,18 @@ ifeq "$(ARCH)" "x86_64"
AFL_ENTRYPOINT=$(shell $(GET_SYMBOL_ADDR) -f $(TESTINSTBIN) -s run -b 0x0000555555554000) AFL_ENTRYPOINT=$(shell $(GET_SYMBOL_ADDR) -f $(TESTINSTBIN) -s run -b 0x0000555555554000)
endif endif
ifeq "$(ARCH)" "x86"
AFL_ENTRYPOINT=$(shell $(GET_SYMBOL_ADDR) -f $(TESTINSTBIN) -s run -b 0x56555000)
endif
.PHONY: all clean qemu frida .PHONY: all clean qemu frida
all: $(TESTINSTBIN) all: $(TESTINSTBIN)
make -C $(ROOT)frida_mode/ make -C $(ROOT)frida_mode/
32:
CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all
$(BUILD_DIR): $(BUILD_DIR):
mkdir -p $@ mkdir -p $@
@ -36,7 +55,7 @@ $(TESTINSTR_DATA_FILE): | $(TESTINSTR_DATA_DIR)
echo -n "000" > $@ echo -n "000" > $@
$(TESTINSTBIN): $(TESTINSTSRC) | $(BUILD_DIR) $(TESTINSTBIN): $(TESTINSTSRC) | $(BUILD_DIR)
$(CC) -o $@ $< $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<
clean: clean:
rm -rf $(BUILD_DIR) rm -rf $(BUILD_DIR)

View File

@ -2,6 +2,10 @@ all:
@echo trying to use GNU make... @echo trying to use GNU make...
@gmake all || echo please install GNUmake @gmake all || echo please install GNUmake
32:
@echo trying to use GNU make...
@gmake 32 || echo please install GNUmake
clean: clean:
@gmake clean @gmake clean

View File

@ -106,7 +106,9 @@ int run(char *file) {
} }
void slow() { void slow() {
usleep(100000); usleep(100000);
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {

View File

@ -10,11 +10,14 @@ TESTINSTSRC:=$(PWD)testinstr.c
QEMU_OUT:=$(BUILD_DIR)qemu-out QEMU_OUT:=$(BUILD_DIR)qemu-out
FRIDA_OUT:=$(BUILD_DIR)frida-out FRIDA_OUT:=$(BUILD_DIR)frida-out
.PHONY: all clean qemu frida .PHONY: all 32 clean qemu frida
all: $(TESTINSTBIN) all: $(TESTINSTBIN)
make -C $(ROOT)frida_mode/ make -C $(ROOT)frida_mode/
32:
CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all
$(BUILD_DIR): $(BUILD_DIR):
mkdir -p $@ mkdir -p $@
@ -25,7 +28,7 @@ $(TESTINSTR_DATA_FILE): | $(TESTINSTR_DATA_DIR)
echo -n "000" > $@ echo -n "000" > $@
$(TESTINSTBIN): $(TESTINSTSRC) | $(BUILD_DIR) $(TESTINSTBIN): $(TESTINSTSRC) | $(BUILD_DIR)
$(CC) -o $@ $< -no-pie $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< -no-pie
clean: clean:
rm -rf $(BUILD_DIR) rm -rf $(BUILD_DIR)

View File

@ -2,6 +2,10 @@ all:
@echo trying to use GNU make... @echo trying to use GNU make...
@gmake all || echo please install GNUmake @gmake all || echo please install GNUmake
32:
@echo trying to use GNU make...
@gmake 32 || echo please install GNUmake
clean: clean:
@gmake clean @gmake clean

View File

@ -0,0 +1,159 @@
PWD:=$(shell pwd)/
ROOT:=$(shell realpath $(PWD)../../..)/
BUILD_DIR:=$(PWD)build/
TEST_DATA_DIR:=$(BUILD_DIR)in/
TEST_DATA_FILE:=$(TEST_DATA_DIR)in
FRIDA_OUT:=$(BUILD_DIR)frida-out
TEST_SRC:=$(PWD)/test.c
TEST_BIN:=$(BUILD_DIR)test
CFLAGS+=-fPIC \
-D_GNU_SOURCE \
-g \
-fno-omit-frame-pointer \
-Wno-stringop-overflow \
LDFLAGS+=-ldl \
ifdef DEBUG
CFLAGS+=-Werror \
-Wall \
-Wextra \
-Wpointer-arith
else
CFLAGS+=-Wno-pointer-arith
endif
ifndef ARCH
ARCH=$(shell uname -m)
ifeq "$(ARCH)" "aarch64"
ARCH:=arm64
endif
ifeq "$(ARCH)" "i686"
ARCH:=x86
endif
endif
ifeq "$(ARCH)" "x86"
LIBASAN_FILE:=libclang_rt.asan-i386.so
endif
ifeq "$(ARCH)" "x86_64"
LIBASAN_FILE:=libclang_rt.asan-x86_64.so
endif
ifeq "$(ARCH)" "aarch64"
LIBASAN_FILE:=libclang_rt.asan-aarch64.so
endif
# LIBASAN:=/usr/lib/llvm-10/lib/clang/10.0.0/lib/linux/libclang_rt.asan-x86_64.so
# LIBASAN:=/usr/lib/x86_64-linux-gnu/libasan.so.6.0.0
LLVM_CONFIG ?= llvm-config
ifeq "$(shell test -e '$(shell which $(LLVM_CONFIG))' && echo 1)" "1"
$(info Found llvm-config: '$(shell which $(LLVM_CONFIG))')
else
$(warning Cannot find llvm-config)
endif
LLVM_BINDIR = $(shell $(LLVM_CONFIG) --bindir 2>/dev/null)/
$(info LLVM_BINDIR: $(LLVM_BINDIR))
CLANG ?= $(LLVM_BINDIR)clang
ifeq "$(shell test -e '$(CLANG)' && echo 1)" "1"
$(info Found clang: '$(CLANG)')
else
$(warning Cannot find clang)
endif
CLANGVER = $(shell $(CLANG) --version | sed -E -ne '/^.*version\ (1?[0-9]\.[0-9]\.[0-9]).*/s//\1/p')
$(info Clang version $(CLANGVER))
LLVM_LIBDIR = $(shell $(LLVM_CONFIG) --libdir 2>/dev/null)
$(info LLVM_LIBDIR: $(LLVM_LIBDIR))
LIBASAN:=$(LLVM_LIBDIR)/clang/$(CLANGVER)/lib/linux/$(LIBASAN_FILE)
ifeq "$(shell test -e '$(LIBASAN)' && echo 1)" "1"
$(info Found Address Sanitizer DSO: '$(LIBASAN)')
else
$(error Error cannot find Address Sanitizer DSO)
endif
.PHONY: all 32 clean format frida-noasan frida debug run
############################## ALL #############################################
all: $(TEST_BIN)
32:
CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all
$(TEST_BIN): $(TEST_SRC) GNUmakefile | $(BUILD_DIR)
$(CC) \
$(CFLAGS) \
$(LDFLAGS) \
-o $@ \
$<
$(BUILD_DIR):
mkdir -p $(BUILD_DIR)
############################# TESTS ############################################
$(TEST_DATA_DIR): | $(BUILD_DIR)
mkdir -p $@
$(TEST_DATA_FILE): | $(TEST_DATA_DIR)
echo -n "TUODATM" > $@
frida-noasan: $(TEST_BIN) $(TEST_DATA_FILE)
$(ROOT)afl-fuzz \
-D \
-O \
-i $(TEST_DATA_DIR) \
-o $(FRIDA_OUT) \
-- \
$(TEST_BIN)
frida: $(TEST_BIN) $(TEST_DATA_FILE)
AFL_PRELOAD=$(LIBASAN) \
AFL_USE_FASAN=1 \
$(ROOT)afl-fuzz \
-D \
-O \
-i $(TEST_DATA_DIR) \
-o $(FRIDA_OUT) \
-- \
$(TEST_BIN)
debug: $(TEST_BIN) $(TEST_DATA_FILE)
gdb \
--ex 'set environment LD_PRELOAD=$(LIBASAN):$(ROOT)afl-frida-trace.so' \
--ex 'set environment ASAN_OPTIONS=detect_leaks=false,halt_on_error=0' \
--ex 'set environment AFL_USE_FASAN=1' \
--ex 'set disassembly-flavor intel' \
--ex 'r < $(TEST_DATA_FILE)' \
--args $(TEST_BIN) \
run: $(TEST_BIN) $(TEST_DATA_FILE)
LD_PRELOAD=$(LIBASAN):$(ROOT)afl-frida-trace.so \
ASAN_OPTIONS=detect_leaks=false \
AFL_USE_FASAN=1 \
$(TEST_BIN) < $(TEST_DATA_FILE)
############################# CLEAN ############################################
clean:
rm -rf $(BUILD_DIR)
############################# FORMAT ###########################################
format:
cd $(ROOT) && echo $(TEST_SRC) | xargs -L1 ./.custom-format.py -i
############################# RUN #############################################

View File

@ -0,0 +1,22 @@
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-noasan:
@gmake frida-noasan
frida:
@gmake frida
debug:
@gmake debug
run:
@gmake run

View File

@ -0,0 +1,90 @@
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#define UNUSED_PARAMETER(x) (void)(x)
#define LOG(x) \
do { \
\
char buf[] = x; \
write(STDOUT_FILENO, buf, sizeof(buf)); \
\
} while (false);
void test(char data) {
char *buf = malloc(10);
if (buf == NULL) return;
switch (data) {
/* Underflow */
case 'U':
LOG("Underflow\n");
buf[-1] = '\0';
free(buf);
break;
/* Overflow */
case 'O':
LOG("Overflow\n");
buf[10] = '\0';
free(buf);
break;
/* Double free */
case 'D':
LOG("Double free\n");
free(buf);
free(buf);
break;
/* Use after free */
case 'A':
LOG("Use after free\n");
free(buf);
buf[0] = '\0';
break;
/* Test Limits (OK) */
case 'T':
LOG("Test-Limits - No Error\n");
buf[0] = 'A';
buf[9] = 'I';
free(buf);
break;
case 'M':
LOG("Memset too many\n");
memset(buf, '\0', 11);
free(buf);
break;
default:
LOG("Nop - No Error\n");
break;
}
}
int main(int argc, char **argv) {
UNUSED_PARAMETER(argc);
UNUSED_PARAMETER(argv);
char input = '\0';
if (read(STDIN_FILENO, &input, 1) < 0) {
LOG("Failed to read stdin\n");
return 1;
}
test(input);
LOG("DONE\n");
return 0;
}

View File

@ -35,6 +35,9 @@ FRIDA_OUT:=$(BUILD_DIR)frida-out
all: $(TEST_BIN) all: $(TEST_BIN)
make -C $(ROOT)frida_mode/ make -C $(ROOT)frida_mode/
32:
CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all
$(BUILD_DIR): $(BUILD_DIR):
mkdir -p $@ mkdir -p $@
@ -46,7 +49,7 @@ $(HARNESS_FILE): | $(HARNESS_BUILD_DIR)
wget -O $@ $(HARNESS_URL) wget -O $@ $(HARNESS_URL)
$(HARNESS_OBJ): $(HARNESS_FILE) $(HARNESS_OBJ): $(HARNESS_FILE)
$(CC) -o $@ -c $< $(CC) $(CFLAGS) $(LDFLAGS) -o $@ -c $<
######### PNGTEST ######## ######### PNGTEST ########
@ -57,7 +60,7 @@ $(PNGTEST_FILE): | $(PNGTEST_BUILD_DIR)
wget -O $@ $(PNGTEST_URL) wget -O $@ $(PNGTEST_URL)
$(PNGTEST_OBJ): $(PNGTEST_FILE) | $(LIBPNG_DIR) $(PNGTEST_OBJ): $(PNGTEST_FILE) | $(LIBPNG_DIR)
$(CXX) -std=c++11 -I $(LIBPNG_DIR) -o $@ -c $< $(CXX) $(CFLAGS) $(LDFLAGS) -std=c++11 -I $(LIBPNG_DIR) -o $@ -c $<
######### LIBPNG ######## ######### LIBPNG ########
@ -80,6 +83,8 @@ $(LIBPNG_LIB): $(LIBPNG_MAKEFILE)
$(TEST_BIN): $(HARNESS_OBJ) $(PNGTEST_OBJ) $(LIBPNG_LIB) $(TEST_BIN): $(HARNESS_OBJ) $(PNGTEST_OBJ) $(LIBPNG_LIB)
$(CXX) \ $(CXX) \
$(CFLAGS) \
$(LDFLAGS) \
-o $@ \ -o $@ \
$(HARNESS_OBJ) $(PNGTEST_OBJ) $(LIBPNG_LIB) \ $(HARNESS_OBJ) $(PNGTEST_OBJ) $(LIBPNG_LIB) \
-lz \ -lz \

View File

@ -2,6 +2,10 @@ all:
@echo trying to use GNU make... @echo trying to use GNU make...
@gmake all || echo please install GNUmake @gmake all || echo please install GNUmake
32:
@echo trying to use GNU make...
@gmake 32 || echo please install GNUmake
clean: clean:
@gmake clean @gmake clean

View File

@ -8,6 +8,18 @@ TEST_DATA_DIR:=../build/libpng/libpng-1.2.56/contrib/pngsuite/
QEMU_OUT:=$(BUILD_DIR)qemu-out QEMU_OUT:=$(BUILD_DIR)qemu-out
FRIDA_OUT:=$(BUILD_DIR)frida-out FRIDA_OUT:=$(BUILD_DIR)frida-out
ifndef ARCH
ARCH=$(shell uname -m)
ifeq "$(ARCH)" "aarch64"
ARCH:=arm64
endif
ifeq "$(ARCH)" "i686"
ARCH:=x86
endif
endif
AFL_QEMU_PERSISTENT_ADDR=$(shell $(PWD)get_symbol_addr.py -f $(TEST_BIN) -s main -b 0x4000000000) AFL_QEMU_PERSISTENT_ADDR=$(shell $(PWD)get_symbol_addr.py -f $(TEST_BIN) -s main -b 0x4000000000)
ARCH=$(shell uname -m) ARCH=$(shell uname -m)
@ -19,11 +31,18 @@ ifeq "$(ARCH)" "x86_64"
AFL_FRIDA_PERSISTENT_ADDR=$(shell $(PWD)get_symbol_addr.py -f $(TEST_BIN) -s main -b 0x0000555555554000) AFL_FRIDA_PERSISTENT_ADDR=$(shell $(PWD)get_symbol_addr.py -f $(TEST_BIN) -s main -b 0x0000555555554000)
endif endif
.PHONY: all clean qemu qemu_entry frida frida_entry ifeq "$(ARCH)" "x86"
AFL_FRIDA_PERSISTENT_ADDR=$(shell $(PWD)get_symbol_addr.py -f $(TEST_BIN) -s main -b 0x56555000)
endif
.PHONY: all 32 clean qemu qemu_entry frida frida_entry
all: all:
make -C $(ROOT)frida_mode/test/png/ make -C $(ROOT)frida_mode/test/png/
32:
CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all
$(BUILD_DIR): $(BUILD_DIR):
mkdir -p $@ mkdir -p $@

View File

@ -2,6 +2,10 @@ all:
@echo trying to use GNU make... @echo trying to use GNU make...
@gmake all || echo please install GNUmake @gmake all || echo please install GNUmake
32:
@echo trying to use GNU make...
@gmake 32 || echo please install GNUmake
clean: clean:
@gmake clean @gmake clean

View File

@ -2,8 +2,16 @@ PWD:=$(shell pwd)/
ROOT:=$(shell realpath $(PWD)../../../../..)/ ROOT:=$(shell realpath $(PWD)../../../../..)/
BUILD_DIR:=$(PWD)build/ BUILD_DIR:=$(PWD)build/
AFLPP_DRIVER_HOOK_DIR=$(ROOT)utils/aflpp_driver/ AFLPP_DRIVER_HOOK_SRC=$(PWD)aflpp_qemu_driver_hook.c
AFLPP_DRIVER_HOOK_OBJ=$(AFLPP_DRIVER_HOOK_DIR)aflpp_qemu_driver_hook.so AFLPP_DRIVER_HOOK_OBJ=$(BUILD_DIR)aflpp_qemu_driver_hook.so
CFLAGS+=-O3 \
-funroll-loops \
-g \
-fPIC \
-funroll-loops \
LDFLAGS+=-shared \
TEST_BIN:=$(PWD)../../build/test TEST_BIN:=$(PWD)../../build/test
TEST_DATA_DIR:=../../build/libpng/libpng-1.2.56/contrib/pngsuite/ TEST_DATA_DIR:=../../build/libpng/libpng-1.2.56/contrib/pngsuite/
@ -12,9 +20,20 @@ AFLPP_DRIVER_DUMMY_INPUT:=$(BUILD_DIR)in
QEMU_OUT:=$(BUILD_DIR)qemu-out QEMU_OUT:=$(BUILD_DIR)qemu-out
FRIDA_OUT:=$(BUILD_DIR)frida-out FRIDA_OUT:=$(BUILD_DIR)frida-out
AFL_QEMU_PERSISTENT_ADDR=$(shell $(PWD)../get_symbol_addr.py -f $(TEST_BIN) -s LLVMFuzzerTestOneInput -b 0x4000000000) ifndef ARCH
ARCH=$(shell uname -m) ARCH=$(shell uname -m)
ifeq "$(ARCH)" "aarch64"
ARCH:=arm64
endif
ifeq "$(ARCH)" "i686"
ARCH:=x86
endif
endif
AFL_QEMU_PERSISTENT_ADDR=$(shell $(PWD)../get_symbol_addr.py -f $(TEST_BIN) -s LLVMFuzzerTestOneInput -b 0x4000000000)
ifeq "$(ARCH)" "aarch64" ifeq "$(ARCH)" "aarch64"
AFL_FRIDA_PERSISTENT_ADDR=$(shell $(PWD)../get_symbol_addr.py -f $(TEST_BIN) -s LLVMFuzzerTestOneInput -b 0x0000aaaaaaaaa000) AFL_FRIDA_PERSISTENT_ADDR=$(shell $(PWD)../get_symbol_addr.py -f $(TEST_BIN) -s LLVMFuzzerTestOneInput -b 0x0000aaaaaaaaa000)
endif endif
@ -23,6 +42,18 @@ ifeq "$(ARCH)" "x86_64"
AFL_FRIDA_PERSISTENT_ADDR=$(shell $(PWD)../get_symbol_addr.py -f $(TEST_BIN) -s LLVMFuzzerTestOneInput -b 0x0000555555554000) AFL_FRIDA_PERSISTENT_ADDR=$(shell $(PWD)../get_symbol_addr.py -f $(TEST_BIN) -s LLVMFuzzerTestOneInput -b 0x0000555555554000)
endif endif
ifeq "$(ARCH)" "x86"
AFL_FRIDA_PERSISTENT_ADDR=$(shell $(PWD)../get_symbol_addr.py -f $(TEST_BIN) -s LLVMFuzzerTestOneInput -b 0x56555000)
endif
.PHONY: all 32 clean format qemu qemu_entry frida frida_entry debug
all: $(AFLPP_DRIVER_HOOK_OBJ)
make -C $(ROOT)frida_mode/test/png/persistent/
32:
CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all
.PHONY: all clean qemu qemu_entry frida frida_entry .PHONY: all clean qemu qemu_entry frida frida_entry
all: all:
@ -37,8 +68,8 @@ $(TEST_DATA_DIR): | $(BUILD_DIR)
$(AFLPP_DRIVER_DUMMY_INPUT): | $(BUILD_DIR) $(AFLPP_DRIVER_DUMMY_INPUT): | $(BUILD_DIR)
truncate -s 1M $@ truncate -s 1M $@
$(AFLPP_DRIVER_HOOK_OBJ): | $(AFLPP_DRIVER_HOOK_DIR) $(AFLPP_DRIVER_HOOK_OBJ): $(AFLPP_DRIVER_HOOK_SRC) | $(BUILD_DIR)
make -C $(AFLPP_DRIVER_HOOK_DIR) $(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
qemu: $(AFLPP_DRIVER_DUMMY_INPUT) $(AFLPP_DRIVER_HOOK_OBJ) | $(BUILD_DIR) qemu: $(AFLPP_DRIVER_DUMMY_INPUT) $(AFLPP_DRIVER_HOOK_OBJ) | $(BUILD_DIR)
AFL_QEMU_PERSISTENT_HOOK=$(AFLPP_DRIVER_HOOK_OBJ) \ AFL_QEMU_PERSISTENT_HOOK=$(AFLPP_DRIVER_HOOK_OBJ) \
@ -93,6 +124,18 @@ frida_entry: $(AFLPP_DRIVER_DUMMY_INPUT) $(AFLPP_DRIVER_HOOK_OBJ) | $(BUILD_DIR)
-- \ -- \
$(TEST_BIN) $(AFLPP_DRIVER_DUMMY_INPUT) $(TEST_BIN) $(AFLPP_DRIVER_DUMMY_INPUT)
debug:
echo $(AFL_FRIDA_PERSISTENT_ADDR)
gdb \
--ex 'set environment LD_PRELOAD=$(ROOT)afl-frida-trace.so' \
--ex 'set environment AFL_FRIDA_PERSISTENT_HOOK=$(AFLPP_DRIVER_HOOK_OBJ)' \
--ex 'set environment AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR)' \
--ex 'set disassembly-flavor intel' \
--args $(TEST_BIN) $(AFLPP_DRIVER_DUMMY_INPUT)
clean: clean:
rm -rf $(BUILD_DIR) rm -rf $(BUILD_DIR)
format:
cd $(ROOT) && echo $(AFLPP_DRIVER_HOOK_SRC) | xargs -L1 ./.custom-format.py -i

View File

@ -2,9 +2,16 @@ all:
@echo trying to use GNU make... @echo trying to use GNU make...
@gmake all || echo please install GNUmake @gmake all || echo please install GNUmake
32:
@echo trying to use GNU make...
@gmake 32 || echo please install GNUmake
clean: clean:
@gmake clean @gmake clean
format:
@gmake format
qemu: qemu:
@gmake qemu @gmake qemu
@ -16,3 +23,6 @@ frida:
frida_entry: frida_entry:
@gmake frida_entry @gmake frida_entry
debug:
@gmake debug

View File

@ -0,0 +1,97 @@
#include <stdint.h>
#include <string.h>
#if defined(__x86_64__)
struct x86_64_regs {
uint64_t rax, rbx, rcx, rdx, rdi, rsi, rbp, r8, r9, r10, r11, r12, r13, r14,
r15;
union {
uint64_t rip;
uint64_t pc;
};
union {
uint64_t rsp;
uint64_t sp;
};
union {
uint64_t rflags;
uint64_t flags;
};
uint8_t zmm_regs[32][64];
};
void afl_persistent_hook(struct x86_64_regs *regs, uint64_t guest_base,
uint8_t *input_buf, uint32_t input_buf_len) {
memcpy((void *)regs->rdi, input_buf, input_buf_len);
regs->rsi = input_buf_len;
}
#elif defined(__i386__)
struct x86_regs {
uint32_t eax, ebx, ecx, edx, edi, esi, ebp;
union {
uint32_t eip;
uint32_t pc;
};
union {
uint32_t esp;
uint32_t sp;
};
union {
uint32_t eflags;
uint32_t flags;
};
uint8_t xmm_regs[8][16];
};
void afl_persistent_hook(struct x86_regs *regs, uint64_t guest_base,
uint8_t *input_buf, uint32_t input_buf_len) {
void **esp = (void **)regs->esp;
void * arg1 = esp[1];
void **arg2 = &esp[2];
memcpy(arg1, input_buf, input_buf_len);
*arg2 = (void *)input_buf_len;
}
#else
#pragma error "Unsupported architecture"
#endif
int afl_persistent_hook_init(void) {
// 1 for shared memory input (faster), 0 for normal input (you have to use
// read(), input_buf will be NULL)
return 1;
}

View File

@ -10,11 +10,14 @@ TESTINSTSRC:=$(PWD)testinstr.c
QEMU_OUT:=$(BUILD_DIR)qemu-out QEMU_OUT:=$(BUILD_DIR)qemu-out
FRIDA_OUT:=$(BUILD_DIR)frida-out FRIDA_OUT:=$(BUILD_DIR)frida-out
.PHONY: all clean qemu frida .PHONY: all 32 clean qemu frida
all: $(TESTINSTBIN) all: $(TESTINSTBIN)
make -C $(ROOT)frida_mode/ make -C $(ROOT)frida_mode/
32:
CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all
$(BUILD_DIR): $(BUILD_DIR):
mkdir -p $@ mkdir -p $@
@ -25,7 +28,7 @@ $(TESTINSTR_DATA_FILE): | $(TESTINSTR_DATA_DIR)
echo -n "000" > $@ echo -n "000" > $@
$(TESTINSTBIN): $(TESTINSTSRC) | $(BUILD_DIR) $(TESTINSTBIN): $(TESTINSTSRC) | $(BUILD_DIR)
$(CC) -o $@ $< $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<
clean: clean:
rm -rf $(BUILD_DIR) rm -rf $(BUILD_DIR)
@ -48,3 +51,9 @@ frida: $(TESTINSTBIN) $(TESTINSTR_DATA_FILE)
-o $(FRIDA_OUT) \ -o $(FRIDA_OUT) \
-- \ -- \
$(TESTINSTBIN) @@ $(TESTINSTBIN) @@
debug:
gdb \
--ex 'set environment LD_PRELOAD=$(ROOT)afl-frida-trace.so' \
--ex 'set disassembly-flavor intel' \
--args $(TESTINSTBIN) $(TESTINSTR_DATA_FILE)

View File

@ -2,6 +2,10 @@ all:
@echo trying to use GNU make... @echo trying to use GNU make...
@gmake all || echo please install GNUmake @gmake all || echo please install GNUmake
32:
@echo trying to use GNU make...
@gmake 32 || echo please install GNUmake
clean: clean:
@gmake clean @gmake clean
@ -10,3 +14,6 @@ qemu:
frida: frida:
@gmake frida @gmake frida
debug:
@gmake debug

View File

@ -191,7 +191,9 @@ static char *afl_environment_variables[] = {
"AFL_WINE_PATH", "AFL_WINE_PATH",
"AFL_NO_SNAPSHOT", "AFL_NO_SNAPSHOT",
"AFL_EXPAND_HAVOC_NOW", "AFL_EXPAND_HAVOC_NOW",
"AFL_USE_FASAN",
"AFL_USE_QASAN", "AFL_USE_QASAN",
"AFL_PRINT_FILENAMES",
NULL NULL
}; };

View File

@ -79,6 +79,8 @@ typedef struct afl_forkserver {
bool frida_mode; /* if running in frida mode or not */ bool frida_mode; /* if running in frida mode or not */
bool frida_asan; /* if running with asan in frida mode */
bool use_stdin; /* use stdin for sending data */ bool use_stdin; /* use stdin for sending data */
bool no_unlink; /* do not unlink cur_input */ bool no_unlink; /* do not unlink cur_input */

View File

@ -25,9 +25,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "libqasan.h" #include "libqasan.h"
#include "map_macro.h" #include "map_macro.h"
#include <unistd.h>
#include <sys/syscall.h>
ssize_t (*__lq_libc_write)(int, const void *, size_t);
ssize_t (*__lq_libc_read)(int, void *, size_t);
char *(*__lq_libc_fgets)(char *, int, FILE *); char *(*__lq_libc_fgets)(char *, int, FILE *);
int (*__lq_libc_atoi)(const char *); int (*__lq_libc_atoi)(const char *);
long (*__lq_libc_atol)(const char *); long (*__lq_libc_atol)(const char *);
@ -37,8 +37,6 @@ void __libqasan_init_hooks(void) {
__libqasan_init_malloc(); __libqasan_init_malloc();
__lq_libc_write = ASSERT_DLSYM(write);
__lq_libc_read = ASSERT_DLSYM(read);
__lq_libc_fgets = ASSERT_DLSYM(fgets); __lq_libc_fgets = ASSERT_DLSYM(fgets);
__lq_libc_atoi = ASSERT_DLSYM(atoi); __lq_libc_atoi = ASSERT_DLSYM(atoi);
__lq_libc_atol = ASSERT_DLSYM(atol); __lq_libc_atol = ASSERT_DLSYM(atol);
@ -52,7 +50,7 @@ ssize_t write(int fd, const void *buf, size_t count) {
QASAN_DEBUG("%14p: write(%d, %p, %zu)\n", rtv, fd, buf, count); QASAN_DEBUG("%14p: write(%d, %p, %zu)\n", rtv, fd, buf, count);
QASAN_LOAD(buf, count); QASAN_LOAD(buf, count);
ssize_t r = __lq_libc_write(fd, buf, count); ssize_t r = syscall(SYS_write, fd, buf, count);
QASAN_DEBUG("\t\t = %zd\n", r); QASAN_DEBUG("\t\t = %zd\n", r);
return r; return r;
@ -65,7 +63,7 @@ ssize_t read(int fd, void *buf, size_t count) {
QASAN_DEBUG("%14p: read(%d, %p, %zu)\n", rtv, fd, buf, count); QASAN_DEBUG("%14p: read(%d, %p, %zu)\n", rtv, fd, buf, count);
QASAN_STORE(buf, count); QASAN_STORE(buf, count);
ssize_t r = __lq_libc_read(fd, buf, count); ssize_t r = syscall(SYS_read, fd, buf, count);
QASAN_DEBUG("\t\t = %zd\n", r); QASAN_DEBUG("\t\t = %zd\n", r);
return r; return r;

View File

@ -61,10 +61,18 @@ void __libqasan_print_maps(void) {
} }
/*__attribute__((constructor))*/ void __libqasan_init() { int __libqasan_is_initialized = 0;
__attribute__((constructor)) void __libqasan_init() {
if (__libqasan_is_initialized) return;
__libqasan_is_initialized = 1;
__libqasan_init_hooks(); __libqasan_init_hooks();
if (getenv("AFL_INST_LIBS") || getenv("QASAN_HOTPACH"))
__libqasan_hotpatch();
#ifdef DEBUG #ifdef DEBUG
__qasan_debug = getenv("QASAN_DEBUG") != NULL; __qasan_debug = getenv("QASAN_DEBUG") != NULL;
#endif #endif
@ -86,7 +94,6 @@ int __libc_start_main(int (*main)(int, char **, char **), int argc, char **argv,
typeof(&__libc_start_main) orig = dlsym(RTLD_NEXT, "__libc_start_main"); typeof(&__libc_start_main) orig = dlsym(RTLD_NEXT, "__libc_start_main");
__libqasan_init(); __libqasan_init();
if (getenv("AFL_INST_LIBS")) __libqasan_hotpatch();
return orig(main, argc, argv, init, fini, rtld_fini, stack_end); return orig(main, argc, argv, init, fini, rtld_fini, stack_end);

View File

@ -1574,7 +1574,12 @@ int main(int argc, char **argv, char **envp) {
else if (have_gcc_plugin) else if (have_gcc_plugin)
compiler_mode = GCC_PLUGIN; compiler_mode = GCC_PLUGIN;
else if (have_gcc) else if (have_gcc)
#ifdef __APPLE__
// on OSX clang masquerades as GCC
compiler_mode = CLANG;
#else
compiler_mode = GCC; compiler_mode = GCC;
#endif
else if (have_lto) else if (have_lto)
compiler_mode = LTO; compiler_mode = LTO;
else else
@ -1596,7 +1601,12 @@ int main(int argc, char **argv, char **envp) {
} }
if (compiler_mode == CLANG) { instrument_mode = INSTRUMENT_CLANG; } if (compiler_mode == CLANG) {
instrument_mode = INSTRUMENT_CLANG;
setenv(CLANG_ENV_VAR, "1", 1); // used by afl-as
}
if (argc < 2 || strncmp(argv[1], "-h", 2) == 0) { if (argc < 2 || strncmp(argv[1], "-h", 2) == 0) {

View File

@ -451,8 +451,12 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
/* Dumping cores is slow and can lead to anomalies if SIGKILL is delivered /* Dumping cores is slow and can lead to anomalies if SIGKILL is delivered
before the dump is complete. */ before the dump is complete. */
// r.rlim_max = r.rlim_cur = 0; if (!fsrv->debug) {
// setrlimit(RLIMIT_CORE, &r); /* Ignore errors */
r.rlim_max = r.rlim_cur = 0;
setrlimit(RLIMIT_CORE, &r); /* Ignore errors */
}
/* Isolate the process and configure standard descriptors. If out_file is /* Isolate the process and configure standard descriptors. If out_file is
specified, stdin is /dev/null; otherwise, out_fd is cloned instead. */ specified, stdin is /dev/null; otherwise, out_fd is cloned instead. */

View File

@ -1044,18 +1044,16 @@ void perform_dry_run(afl_state_t *afl) {
/* Remove from fuzzing queue but keep for splicing */ /* Remove from fuzzing queue but keep for splicing */
struct queue_entry *p = afl->queue; if (!q->was_fuzzed) {
if (!p->was_fuzzed) { q->was_fuzzed = 1;
p->was_fuzzed = 1;
--afl->pending_not_fuzzed; --afl->pending_not_fuzzed;
--afl->active_paths; --afl->active_paths;
} }
p->disabled = 1; q->disabled = 1;
p->perf_score = 0; q->perf_score = 0;
u32 i = 0; u32 i = 0;
while (unlikely(i < afl->queued_paths && afl->queue_buf[i] && while (unlikely(i < afl->queued_paths && afl->queue_buf[i] &&
@ -1294,10 +1292,14 @@ void pivot_inputs(afl_state_t *afl) {
if (src_str && sscanf(src_str + 1, "%06u", &src_id) == 1) { if (src_str && sscanf(src_str + 1, "%06u", &src_id) == 1) {
if (src_id < afl->queued_paths) {
struct queue_entry *s = afl->queue_buf[src_id]; struct queue_entry *s = afl->queue_buf[src_id];
if (s) { q->depth = s->depth + 1; } if (s) { q->depth = s->depth + 1; }
}
if (afl->max_depth < q->depth) { afl->max_depth = q->depth; } if (afl->max_depth < q->depth) { afl->max_depth = q->depth; }
} }

View File

@ -562,7 +562,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
if (afl->cmplog_lvl == 3 || if (afl->cmplog_lvl == 3 ||
(afl->cmplog_lvl == 2 && afl->queue_cur->tc_ref) || (afl->cmplog_lvl == 2 && afl->queue_cur->tc_ref) ||
!(afl->fsrv.total_execs % afl->queued_paths) || !(afl->fsrv.total_execs % afl->queued_paths) ||
get_cur_time() - afl->last_path_time > 300000) { get_cur_time() - afl->last_path_time > 300000) { // 300 seconds
if (input_to_state_stage(afl, in_buf, out_buf, len)) { if (input_to_state_stage(afl, in_buf, out_buf, len)) {
@ -2013,7 +2013,7 @@ havoc_stage:
} }
if (unlikely(get_cur_time() - afl->last_path_time > 5000 && if (unlikely(get_cur_time() - afl->last_path_time > 5000 /* 5 seconds */ &&
afl->ready_for_splicing_count > 1)) { afl->ready_for_splicing_count > 1)) {
/* add expensive havoc cases here if there is no findings in the last 5s */ /* add expensive havoc cases here if there is no findings in the last 5s */
@ -3060,7 +3060,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
if (afl->cmplog_lvl == 3 || if (afl->cmplog_lvl == 3 ||
(afl->cmplog_lvl == 2 && afl->queue_cur->tc_ref) || (afl->cmplog_lvl == 2 && afl->queue_cur->tc_ref) ||
!(afl->fsrv.total_execs % afl->queued_paths) || !(afl->fsrv.total_execs % afl->queued_paths) ||
get_cur_time() - afl->last_path_time > 300000) { get_cur_time() - afl->last_path_time > 300000) { // 300 seconds
if (input_to_state_stage(afl, in_buf, out_buf, len)) { if (input_to_state_stage(afl, in_buf, out_buf, len)) {

View File

@ -368,7 +368,8 @@ void maybe_update_plot_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
afl->plot_prev_uh == afl->unique_hangs && afl->plot_prev_uh == afl->unique_hangs &&
afl->plot_prev_md == afl->max_depth && afl->plot_prev_md == afl->max_depth &&
afl->plot_prev_ed == afl->fsrv.total_execs) || afl->plot_prev_ed == afl->fsrv.total_execs) ||
!afl->queue_cycle || get_cur_time() - afl->start_time <= 60))) { !afl->queue_cycle ||
get_cur_time() - afl->start_time <= 60000))) {
return; return;
@ -393,7 +394,7 @@ void maybe_update_plot_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
fprintf(afl->fsrv.plot_file, fprintf(afl->fsrv.plot_file,
"%llu, %llu, %u, %u, %u, %u, %0.02f%%, %llu, %llu, %u, %0.02f, %llu, " "%llu, %llu, %u, %u, %u, %u, %0.02f%%, %llu, %llu, %u, %0.02f, %llu, "
"%u\n", "%u\n",
(afl->prev_run_time + get_cur_time() - afl->start_time), ((afl->prev_run_time + get_cur_time() - afl->start_time) / 1000),
afl->queue_cycle - 1, afl->current_entry, afl->queued_paths, afl->queue_cycle - 1, afl->current_entry, afl->queued_paths,
afl->pending_not_fuzzed, afl->pending_favored, bitmap_cvg, afl->pending_not_fuzzed, afl->pending_favored, bitmap_cvg,
afl->unique_crashes, afl->unique_hangs, afl->max_depth, eps, afl->unique_crashes, afl->unique_hangs, afl->max_depth, eps,

View File

@ -328,11 +328,55 @@ static int stricmp(char const *a, char const *b) {
} }
static void fasan_check_afl_preload(char *afl_preload) {
char first_preload[PATH_MAX + 1] = {0};
char * separator = strchr(afl_preload, ':');
size_t first_preload_len = PATH_MAX;
char * basename;
char clang_runtime_prefix[] = "libclang_rt.asan-";
if (separator != NULL && (separator - afl_preload) < PATH_MAX) {
first_preload_len = separator - afl_preload;
}
strncpy(first_preload, afl_preload, first_preload_len);
basename = strrchr(first_preload, '/');
if (basename == NULL) {
basename = first_preload;
} else {
basename = basename + 1;
}
if (strncmp(basename, clang_runtime_prefix,
sizeof(clang_runtime_prefix) - 1) != 0) {
FATAL("Address Sanitizer DSO must be the first DSO in AFL_PRELOAD");
}
if (access(first_preload, R_OK) != 0) {
FATAL("Address Sanitizer DSO not found");
}
OKF("Found ASAN DSO: %s", first_preload);
}
/* Main entry point */ /* Main entry point */
int main(int argc, char **argv_orig, char **envp) { int main(int argc, char **argv_orig, char **envp) {
s32 opt, i, auto_sync = 0 /*, user_set_cache = 0*/; s32 opt, auto_sync = 0 /*, user_set_cache = 0*/;
u64 prev_queued = 0; u64 prev_queued = 0;
u32 sync_interval_cnt = 0, seek_to = 0, show_help = 0, u32 sync_interval_cnt = 0, seek_to = 0, show_help = 0,
map_size = get_map_size(); map_size = get_map_size();
@ -785,6 +829,7 @@ int main(int argc, char **argv_orig, char **envp) {
} }
afl->fsrv.frida_mode = 1; afl->fsrv.frida_mode = 1;
if (get_afl_env("AFL_USE_FASAN")) { afl->fsrv.frida_asan = 1; }
break; break;
@ -1369,19 +1414,27 @@ int main(int argc, char **argv_orig, char **envp) {
OKF("Injecting %s ...", frida_binary); OKF("Injecting %s ...", frida_binary);
if (afl_preload) { if (afl_preload) {
frida_afl_preload = alloc_printf("%s:%s", afl_preload, frida_binary); if (afl->fsrv.frida_asan) {
} else { OKF("Using Frida Address Sanitizer Mode");
frida_afl_preload = alloc_printf("%s", frida_binary); fasan_check_afl_preload(afl_preload);
setenv("ASAN_OPTIONS", "detect_leaks=false", 1);
} }
u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so");
OKF("Injecting %s ...", frida_binary);
frida_afl_preload = alloc_printf("%s:%s", afl_preload, frida_binary);
ck_free(frida_binary); ck_free(frida_binary);
setenv("LD_PRELOAD", frida_afl_preload, 1); setenv("LD_PRELOAD", frida_afl_preload, 1);
setenv("DYLD_INSERT_LIBRARIES", frida_afl_preload, 1); setenv("DYLD_INSERT_LIBRARIES", frida_afl_preload, 1);
}
} else { } else {
setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1); setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
@ -1391,6 +1444,15 @@ int main(int argc, char **argv_orig, char **envp) {
} else if (afl->fsrv.frida_mode) { } else if (afl->fsrv.frida_mode) {
if (afl->fsrv.frida_asan) {
OKF("Using Frida Address Sanitizer Mode");
FATAL(
"Address Sanitizer DSO must be loaded using AFL_PRELOAD in Frida "
"Address Sanitizer Mode");
} else {
u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so"); u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so");
OKF("Injecting %s ...", frida_binary); OKF("Injecting %s ...", frida_binary);
setenv("LD_PRELOAD", frida_binary, 1); setenv("LD_PRELOAD", frida_binary, 1);
@ -1399,6 +1461,8 @@ int main(int argc, char **argv_orig, char **envp) {
} }
}
if (getenv("AFL_LD_PRELOAD")) { if (getenv("AFL_LD_PRELOAD")) {
FATAL("Use AFL_PRELOAD instead of AFL_LD_PRELOAD"); FATAL("Use AFL_PRELOAD instead of AFL_LD_PRELOAD");
@ -1770,7 +1834,7 @@ int main(int argc, char **argv_orig, char **envp) {
if (extras_dir_cnt) { if (extras_dir_cnt) {
for (i = 0; i < extras_dir_cnt; i++) { for (u8 i = 0; i < extras_dir_cnt; i++) {
load_extras(afl, extras_dir[i]); load_extras(afl, extras_dir[i]);
@ -1922,6 +1986,13 @@ int main(int argc, char **argv_orig, char **envp) {
if (unlikely(seek_to)) { if (unlikely(seek_to)) {
if (unlikely(seek_to >= afl->queued_paths)) {
// This should never happen.
FATAL("BUG: seek_to location out of bounds!\n");
}
afl->current_entry = seek_to; afl->current_entry = seek_to;
afl->queue_cur = afl->queue_buf[seek_to]; afl->queue_cur = afl->queue_buf[seek_to];
seek_to = 0; seek_to = 0;
@ -1940,8 +2011,10 @@ int main(int argc, char **argv_orig, char **envp) {
/* If we had a full queue cycle with no new finds, try /* If we had a full queue cycle with no new finds, try
recombination strategies next. */ recombination strategies next. */
if (unlikely(afl->queued_paths == prev_queued && if (unlikely(afl->queued_paths == prev_queued
(get_cur_time() - afl->start_time) >= 3600)) { /* FIXME TODO BUG: && (get_cur_time() - afl->start_time) >=
3600 */
)) {
if (afl->use_splicing) { if (afl->use_splicing) {
@ -2059,7 +2132,7 @@ int main(int argc, char **argv_orig, char **envp) {
} }
// we must recalculate the scores of all queue entries // we must recalculate the scores of all queue entries
for (i = 0; i < (s32)afl->queued_paths; i++) { for (u32 i = 0; i < afl->queued_paths; i++) {
if (likely(!afl->queue_buf[i]->disabled)) { if (likely(!afl->queue_buf[i]->disabled)) {

View File

@ -76,17 +76,18 @@ static u32 in_len; /* Input data length */
static u32 map_size = MAP_SIZE; static u32 map_size = MAP_SIZE;
static u8 quiet_mode, /* Hide non-essential messages? */ static bool quiet_mode, /* Hide non-essential messages? */
edges_only, /* Ignore hit counts? */ edges_only, /* Ignore hit counts? */
raw_instr_output, /* Do not apply AFL filters */ raw_instr_output, /* Do not apply AFL filters */
cmin_mode, /* Generate output in afl-cmin mode? */ cmin_mode, /* Generate output in afl-cmin mode? */
binary_mode, /* Write output as a binary map */ binary_mode, /* Write output as a binary map */
keep_cores, /* Allow coredumps? */ keep_cores, /* Allow coredumps? */
remove_shm = 1, /* remove shmem? */ remove_shm = true, /* remove shmem? */
collect_coverage, /* collect coverage */ collect_coverage, /* collect coverage */
have_coverage, /* have coverage? */ have_coverage, /* have coverage? */
no_classify, /* do not classify counts */ no_classify, /* do not classify counts */
debug; /* debug mode */ debug, /* debug mode */
print_filenames; /* print the current filename */
static volatile u8 stop_soon, /* Ctrl-C pressed? */ static volatile u8 stop_soon, /* Ctrl-C pressed? */
child_crashed; /* Child crashed? */ child_crashed; /* Child crashed? */
@ -320,11 +321,11 @@ static void showmap_run_target_forkserver(afl_forkserver_t *fsrv, u8 *mem,
if (fsrv->trace_bits[0] == 1) { if (fsrv->trace_bits[0] == 1) {
fsrv->trace_bits[0] = 0; fsrv->trace_bits[0] = 0;
have_coverage = 1; have_coverage = true;
} else { } else {
have_coverage = 0; have_coverage = false;
} }
@ -335,11 +336,11 @@ static void showmap_run_target_forkserver(afl_forkserver_t *fsrv, u8 *mem,
if (!fsrv->last_run_timed_out && !stop_soon && if (!fsrv->last_run_timed_out && !stop_soon &&
WIFSIGNALED(fsrv->child_status)) { WIFSIGNALED(fsrv->child_status)) {
child_crashed = 1; child_crashed = true;
} else { } else {
child_crashed = 0; child_crashed = false;
} }
@ -375,6 +376,13 @@ static void showmap_run_target_forkserver(afl_forkserver_t *fsrv, u8 *mem,
static u32 read_file(u8 *in_file) { static u32 read_file(u8 *in_file) {
if (print_filenames) {
SAYF("Processing %s\n", in_file);
fflush(stdout);
}
struct stat st; struct stat st;
s32 fd = open(in_file, O_RDONLY); s32 fd = open(in_file, O_RDONLY);
@ -386,7 +394,18 @@ static u32 read_file(u8 *in_file) {
} }
if (st.st_size > MAX_FILE) {
WARNF("Input file '%s' is too large, only reading %u bytes.", in_file,
MAX_FILE);
in_len = MAX_FILE;
} else {
in_len = st.st_size; in_len = st.st_size;
}
in_data = ck_alloc_nozero(in_len); in_data = ck_alloc_nozero(in_len);
ck_read(fd, in_data, in_len, in_file); ck_read(fd, in_data, in_len, in_file);
@ -504,11 +523,11 @@ static void showmap_run_target(afl_forkserver_t *fsrv, char **argv) {
if (fsrv->trace_bits[0] == 1) { if (fsrv->trace_bits[0] == 1) {
fsrv->trace_bits[0] = 0; fsrv->trace_bits[0] = 0;
have_coverage = 1; have_coverage = true;
} else { } else {
have_coverage = 0; have_coverage = false;
} }
@ -518,7 +537,7 @@ static void showmap_run_target(afl_forkserver_t *fsrv, char **argv) {
if (!fsrv->last_run_timed_out && !stop_soon && WIFSIGNALED(status)) { if (!fsrv->last_run_timed_out && !stop_soon && WIFSIGNALED(status)) {
child_crashed = 1; child_crashed = true;
} }
@ -548,7 +567,7 @@ static void showmap_run_target(afl_forkserver_t *fsrv, char **argv) {
static void handle_stop_sig(int sig) { static void handle_stop_sig(int sig) {
(void)sig; (void)sig;
stop_soon = 1; stop_soon = true;
afl_fsrv_killall(); afl_fsrv_killall();
} }
@ -731,6 +750,8 @@ static void usage(u8 *argv0) {
"AFL_MAP_SIZE: the shared memory size for that target. must be >= the " "AFL_MAP_SIZE: the shared memory size for that target. must be >= the "
"size the target was compiled for\n" "size the target was compiled for\n"
"AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n" "AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n"
"AFL_PRINT_FILENAMES: If set, the filename currently processed will be "
"printed to stdout\n"
"AFL_QUIET: do not print extra informational output\n", "AFL_QUIET: do not print extra informational output\n",
argv0, MEM_LIMIT, doc_path); argv0, MEM_LIMIT, doc_path);
@ -745,13 +766,16 @@ int main(int argc, char **argv_orig, char **envp) {
// TODO: u64 mem_limit = MEM_LIMIT; /* Memory limit (MB) */ // TODO: u64 mem_limit = MEM_LIMIT; /* Memory limit (MB) */
s32 opt, i; s32 opt, i;
u8 mem_limit_given = 0, timeout_given = 0, unicorn_mode = 0, use_wine = 0; bool mem_limit_given = false, timeout_given = false, unicorn_mode = false,
use_wine = false;
char **use_argv; char **use_argv;
char **argv = argv_cpy_dup(argc, argv_orig); char **argv = argv_cpy_dup(argc, argv_orig);
afl_forkserver_t fsrv_var = {0}; afl_forkserver_t fsrv_var = {0};
if (getenv("AFL_DEBUG")) { debug = 1; } if (getenv("AFL_DEBUG")) { debug = true; }
if (get_afl_env("AFL_PRINT_FILENAMES")) { print_filenames = true; }
fsrv = &fsrv_var; fsrv = &fsrv_var;
afl_fsrv_init(fsrv); afl_fsrv_init(fsrv);
map_size = get_map_size(); map_size = get_map_size();
@ -759,19 +783,19 @@ int main(int argc, char **argv_orig, char **envp) {
doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH; doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH;
if (getenv("AFL_QUIET") != NULL) { be_quiet = 1; } if (getenv("AFL_QUIET") != NULL) { be_quiet = true; }
while ((opt = getopt(argc, argv, "+i:o:f:m:t:A:eqCZOQUWbcrsh")) > 0) { while ((opt = getopt(argc, argv, "+i:o:f:m:t:A:eqCZOQUWbcrsh")) > 0) {
switch (opt) { switch (opt) {
case 's': case 's':
no_classify = 1; no_classify = true;
break; break;
case 'C': case 'C':
collect_coverage = 1; collect_coverage = true;
quiet_mode = 1; quiet_mode = true;
break; break;
case 'i': case 'i':
@ -790,7 +814,7 @@ int main(int argc, char **argv_orig, char **envp) {
u8 suffix = 'M'; u8 suffix = 'M';
if (mem_limit_given) { FATAL("Multiple -m options not supported"); } if (mem_limit_given) { FATAL("Multiple -m options not supported"); }
mem_limit_given = 1; mem_limit_given = true;
if (!optarg) { FATAL("Wrong usage of -m"); } if (!optarg) { FATAL("Wrong usage of -m"); }
@ -851,7 +875,7 @@ int main(int argc, char **argv_orig, char **envp) {
case 't': case 't':
if (timeout_given) { FATAL("Multiple -t options not supported"); } if (timeout_given) { FATAL("Multiple -t options not supported"); }
timeout_given = 1; timeout_given = true;
if (!optarg) { FATAL("Wrong usage of -t"); } if (!optarg) { FATAL("Wrong usage of -t"); }
@ -873,12 +897,12 @@ int main(int argc, char **argv_orig, char **envp) {
if (edges_only) { FATAL("Multiple -e options not supported"); } if (edges_only) { FATAL("Multiple -e options not supported"); }
if (raw_instr_output) { FATAL("-e and -r are mutually exclusive"); } if (raw_instr_output) { FATAL("-e and -r are mutually exclusive"); }
edges_only = 1; edges_only = true;
break; break;
case 'q': case 'q':
quiet_mode = 1; quiet_mode = true;
break; break;
case 'Z': case 'Z':
@ -886,8 +910,8 @@ int main(int argc, char **argv_orig, char **envp) {
/* This is an undocumented option to write data in the syntax expected /* This is an undocumented option to write data in the syntax expected
by afl-cmin. Nobody else should have any use for this. */ by afl-cmin. Nobody else should have any use for this. */
cmin_mode = 1; cmin_mode = true;
quiet_mode = 1; quiet_mode = true;
break; break;
case 'A': case 'A':
@ -899,7 +923,7 @@ int main(int argc, char **argv_orig, char **envp) {
if (fsrv->frida_mode) { FATAL("Multiple -O options not supported"); } if (fsrv->frida_mode) { FATAL("Multiple -O options not supported"); }
fsrv->frida_mode = 1; fsrv->frida_mode = true;
break; break;
@ -907,21 +931,21 @@ int main(int argc, char **argv_orig, char **envp) {
if (fsrv->qemu_mode) { FATAL("Multiple -Q options not supported"); } if (fsrv->qemu_mode) { FATAL("Multiple -Q options not supported"); }
fsrv->qemu_mode = 1; fsrv->qemu_mode = true;
break; break;
case 'U': case 'U':
if (unicorn_mode) { FATAL("Multiple -U options not supported"); } if (unicorn_mode) { FATAL("Multiple -U options not supported"); }
unicorn_mode = 1; unicorn_mode = true;
break; break;
case 'W': /* Wine+QEMU mode */ case 'W': /* Wine+QEMU mode */
if (use_wine) { FATAL("Multiple -W options not supported"); } if (use_wine) { FATAL("Multiple -W options not supported"); }
fsrv->qemu_mode = 1; fsrv->qemu_mode = true;
use_wine = 1; use_wine = true;
break; break;
@ -930,20 +954,20 @@ int main(int argc, char **argv_orig, char **envp) {
/* Secret undocumented mode. Writes output in raw binary format /* Secret undocumented mode. Writes output in raw binary format
similar to that dumped by afl-fuzz in <out_dir/queue/fuzz_bitmap. */ similar to that dumped by afl-fuzz in <out_dir/queue/fuzz_bitmap. */
binary_mode = 1; binary_mode = true;
break; break;
case 'c': case 'c':
if (keep_cores) { FATAL("Multiple -c options not supported"); } if (keep_cores) { FATAL("Multiple -c options not supported"); }
keep_cores = 1; keep_cores = true;
break; break;
case 'r': case 'r':
if (raw_instr_output) { FATAL("Multiple -r options not supported"); } if (raw_instr_output) { FATAL("Multiple -r options not supported"); }
if (edges_only) { FATAL("-e and -r are mutually exclusive"); } if (edges_only) { FATAL("-e and -r are mutually exclusive"); }
raw_instr_output = 1; raw_instr_output = true;
break; break;
case 'h': case 'h':
@ -1053,7 +1077,7 @@ int main(int argc, char **argv_orig, char **envp) {
/* initialize cmplog_mode */ /* initialize cmplog_mode */
shm_fuzz->cmplog_mode = 0; shm_fuzz->cmplog_mode = 0;
u8 *map = afl_shm_init(shm_fuzz, MAX_FILE + sizeof(u32), 1); u8 *map = afl_shm_init(shm_fuzz, MAX_FILE + sizeof(u32), 1);
shm_fuzz->shmemfuzz_mode = 1; shm_fuzz->shmemfuzz_mode = true;
if (!map) { FATAL("BUG: Zero return from afl_shm_init."); } if (!map) { FATAL("BUG: Zero return from afl_shm_init."); }
#ifdef USEMMAP #ifdef USEMMAP
setenv(SHM_FUZZ_ENV_VAR, shm_fuzz->g_shm_file_path, 1); setenv(SHM_FUZZ_ENV_VAR, shm_fuzz->g_shm_file_path, 1);
@ -1062,7 +1086,7 @@ int main(int argc, char **argv_orig, char **envp) {
setenv(SHM_FUZZ_ENV_VAR, shm_str, 1); setenv(SHM_FUZZ_ENV_VAR, shm_str, 1);
ck_free(shm_str); ck_free(shm_str);
#endif #endif
fsrv->support_shmem_fuzz = 1; fsrv->support_shmem_fuzz = true;
fsrv->shmem_fuzz_len = (u32 *)map; fsrv->shmem_fuzz_len = (u32 *)map;
fsrv->shmem_fuzz = map + sizeof(u32); fsrv->shmem_fuzz = map + sizeof(u32);
@ -1114,7 +1138,7 @@ int main(int argc, char **argv_orig, char **envp) {
struct stat statbuf; struct stat statbuf;
#endif #endif
if (getenv("AFL_DEBUG_GDB")) wait_for_gdb = 1; if (getenv("AFL_DEBUG_GDB")) wait_for_gdb = true;
fsrv->dev_null_fd = open("/dev/null", O_RDWR); fsrv->dev_null_fd = open("/dev/null", O_RDWR);
if (fsrv->dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); } if (fsrv->dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); }
@ -1153,8 +1177,8 @@ int main(int argc, char **argv_orig, char **envp) {
if ((coverage_map = (u8 *)malloc(map_size)) == NULL) if ((coverage_map = (u8 *)malloc(map_size)) == NULL)
FATAL("coult not grab memory"); FATAL("coult not grab memory");
edges_only = 0; edges_only = false;
raw_instr_output = 1; raw_instr_output = true;
} }