Compare commits
258 Commits
Author | SHA1 | Date | |
---|---|---|---|
143c9d175e | |||
b0758ac8db | |||
77c06408c3 | |||
6bf52c1434 | |||
eebc2f4f1e | |||
016bdc36bb | |||
ed72b9ec1d | |||
615a8ff986 | |||
026096ccf3 | |||
87f2789e98 | |||
d9ed784298 | |||
0fd6315dfb | |||
28a1765781 | |||
0b5ad8ee84 | |||
3a78db2ade | |||
605b0e6465 | |||
7270cbe756 | |||
a790bf6cc2 | |||
86983f4060 | |||
319c7457ff | |||
e9be58b69c | |||
61d79f85c5 | |||
9baa402344 | |||
04e3b5a6d3 | |||
227b42b1d0 | |||
ac169c3087 | |||
3609912f41 | |||
6d2b8e3ed2 | |||
06ee6b1986 | |||
0090b3a3f0 | |||
452a4cf5be | |||
f63d2b0f55 | |||
29235a7935 | |||
ac0e855907 | |||
f7a5ea667b | |||
fce512db40 | |||
b427a53a6b | |||
2bb86863e6 | |||
26a3d1b53b | |||
2a0f082723 | |||
22da04f077 | |||
5933e787f9 | |||
6ce736aa91 | |||
830dcacc07 | |||
74d9da7203 | |||
9d3e6a869e | |||
1a15e98fff | |||
a594182314 | |||
9d87f408dd | |||
b4c2fc9416 | |||
ecf8db0014 | |||
ec7b14a3d6 | |||
c74686e20d | |||
4902bb91d2 | |||
237a475d9b | |||
686a595df3 | |||
1529bd070e | |||
29f8040f09 | |||
029bfc386f | |||
88905c65af | |||
492418ebd6 | |||
a9d549ca07 | |||
4721d869ad | |||
7aced239e8 | |||
d1de12d617 | |||
5deae7924f | |||
1d9d5936d9 | |||
7afad147d1 | |||
550ba4d772 | |||
25c8336c0c | |||
4bcb177f62 | |||
409a6517c1 | |||
d9fefafae7 | |||
16bd6aad7c | |||
5b06078a41 | |||
a3cf7c1224 | |||
6de9b37b2a | |||
1e5699ccaa | |||
bdec40ae5d | |||
56ce081ac7 | |||
861bd5e04b | |||
c5117b42ca | |||
0e2c832499 | |||
34caf7d781 | |||
c8061e5b35 | |||
a45cdb240c | |||
2b82492457 | |||
d51ec57d91 | |||
751e09f47b | |||
c1415b816a | |||
4217a6606c | |||
20177151e6 | |||
9a4552d6c4 | |||
8c58bdb504 | |||
f42c0047c8 | |||
1ca3317425 | |||
630ba07054 | |||
27ab84fbf1 | |||
4c07e37eae | |||
8f7e584b82 | |||
f6c08c3a1c | |||
9e38c43686 | |||
c8e6a59e7d | |||
bedd812e7b | |||
110cc27632 | |||
21ebfec79c | |||
8701cdcc2c | |||
e7ddd15fa5 | |||
5e47829462 | |||
e663897a8a | |||
b7ddde636b | |||
8764375357 | |||
657c1e9b9b | |||
0ed1cb4d31 | |||
741dcabd5d | |||
2342c85db4 | |||
091fa09e5e | |||
d8920e31f8 | |||
6a7f184c4e | |||
30666cb81e | |||
9242e0db8a | |||
add85f34d1 | |||
c7dbeb8568 | |||
179b118bc9 | |||
7884e0f449 | |||
10dae419d6 | |||
d2715336a5 | |||
41b07983f1 | |||
ef77d552e9 | |||
85f3ebc714 | |||
b7d741b18e | |||
da5ff0df0a | |||
7ae90a66c4 | |||
ee295801a6 | |||
03ba344e6d | |||
cc94e37ae1 | |||
8c1015ac39 | |||
dc7b607080 | |||
511ffc06d2 | |||
3b96c8ae13 | |||
226450600c | |||
845c32b5fb | |||
ee57053be1 | |||
a010d356de | |||
3b3ba08daa | |||
72cebac42e | |||
e1082f2548 | |||
128413690e | |||
b6b81a687d | |||
b8e61da8ab | |||
cda84594cc | |||
fd9f61a8c5 | |||
8b75680c7a | |||
09c4d9ed75 | |||
02082bcd2e | |||
fa6a0aba61 | |||
dbc62dbe56 | |||
1a25ccb618 | |||
0792cab566 | |||
b5cb99f6fe | |||
0a18bf8db5 | |||
48ad95f0e5 | |||
fd99ddb1d6 | |||
7e8a491500 | |||
8b8aaa93bd | |||
f511ebd125 | |||
83bf876255 | |||
41291d8c72 | |||
f9d4dcdd85 | |||
8a681bc163 | |||
53fa703755 | |||
51d6f863f5 | |||
be00dbc2ac | |||
65ffa4b472 | |||
7bd2899f2e | |||
43b162c222 | |||
5d9134d6ad | |||
6c8a47f7dc | |||
89c4fa3051 | |||
81aae9b54c | |||
54eca027a5 | |||
8fe6282164 | |||
8588becf47 | |||
a91d445b5f | |||
2d9e0f56b0 | |||
146eb32c31 | |||
550dc989b3 | |||
251264fde5 | |||
649076600d | |||
8521eb8413 | |||
699c16c7e0 | |||
6b50a001b0 | |||
24dd35ef96 | |||
8217b5ff81 | |||
7b3b707ae6 | |||
60b0c38022 | |||
17d4ae9a16 | |||
71621bbc52 | |||
ddc90e1176 | |||
47488dcd02 | |||
185d7f2ede | |||
376d1736a8 | |||
edeaf72ea8 | |||
c76dc73c7a | |||
964819d3fc | |||
68436b277b | |||
6106efa301 | |||
d59a76261d | |||
db19116ce6 | |||
a3421f8099 | |||
fd1d162149 | |||
5a28157ffd | |||
e3106e6f52 | |||
b3a0ecfd48 | |||
641a943d95 | |||
74a8f145e0 | |||
3cb7319ccd | |||
5f70bc5404 | |||
ee10461f48 | |||
9f911bf0bd | |||
88814be474 | |||
a2314fc37f | |||
176ede3fc8 | |||
d89fa8c7ad | |||
63087d9bd9 | |||
fad8a3feb8 | |||
02fba1cc7e | |||
2564eb6f8c | |||
495348261d | |||
7a939a6c59 | |||
425cbb9025 | |||
ab699bbeea | |||
bf8e07d168 | |||
ae958acc83 | |||
088aae7c25 | |||
75ac9c013c | |||
22e2362f0f | |||
c6bad07d75 | |||
83487415b1 | |||
9de3de6cdf | |||
aceb1af908 | |||
3a60f6a251 | |||
52dd5d479d | |||
ece717c424 | |||
57bc3c0701 | |||
630272bac5 | |||
5590d1836a | |||
e41ac9564b | |||
2c144e88fb | |||
5c7e84c5c8 | |||
52cae6d132 | |||
6eb752a65c | |||
ed3eb61610 | |||
0993bcdc4e | |||
d28bb47a38 | |||
9d7dd5a69f | |||
77ce31c8ba | |||
08ca4d54a5 |
@ -6,7 +6,7 @@
|
||||
# Written and maintaned by Andrea Fioraldi <andreafioraldi@gmail.com>
|
||||
#
|
||||
# Copyright 2015, 2016, 2017 Google Inc. All rights reserved.
|
||||
# Copyright 2019-2020 AFLplusplus Project. All rights reserved.
|
||||
# Copyright 2019-2022 AFLplusplus Project. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
31
.github/workflows/ci.yml
vendored
@ -7,24 +7,47 @@ on:
|
||||
branches: [ stable, dev ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
linux:
|
||||
runs-on: '${{ matrix.os }}'
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-20.04, ubuntu-18.04]
|
||||
env:
|
||||
AFL_SKIP_CPUFREQ: 1
|
||||
AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES: 1
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: debug
|
||||
run: apt-cache search plugin-dev | grep gcc- ; echo ; apt-cache search clang-format- | grep clang-format-
|
||||
run: apt-cache search plugin-dev | grep gcc-; echo; apt-cache search clang-format- | grep clang-format-
|
||||
- name: update
|
||||
run: sudo apt-get update && sudo apt-get upgrade -y
|
||||
- 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 ninja-build
|
||||
- name: compiler installed
|
||||
run: gcc -v ; echo ; clang -v
|
||||
run: gcc -v; echo; clang -v
|
||||
- name: install gcc plugin
|
||||
run: sudo apt-get install -y -m -f --install-suggests $(readlink /usr/bin/gcc)-plugin-dev
|
||||
- name: build afl++
|
||||
run: make distrib ASAN_BUILD=1
|
||||
- name: run tests
|
||||
run: sudo -E ./afl-system-config ; export AFL_SKIP_CPUFREQ=1 ; make tests
|
||||
run: sudo -E ./afl-system-config; make tests
|
||||
macos:
|
||||
runs-on: macOS-latest
|
||||
env:
|
||||
AFL_MAP_SIZE: 65536
|
||||
AFL_SKIP_CPUFREQ: 1
|
||||
AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES: 1
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: install
|
||||
run: brew install make gcc
|
||||
- name: fix install
|
||||
run: cd /usr/local/bin; ln -s gcc-11 gcc; ln -s g++-11 g++; which gcc; gcc -v
|
||||
- name: build
|
||||
run: export PATH=/usr/local/Cellar/llvm/*/":$PATH"; export CC=/usr/local/Cellar/llvm/*/bin/clang; export CXX="$CC"++; export LLVM_CONFIG=/usr/local/Cellar/llvm/*/bin/llvm-config; sudo -E ./afl-system-config; gmake ASAN_BUILD=1
|
||||
- name: frida
|
||||
run: export CC=/usr/local/Cellar/llvm/*/bin/clang; export CXX="$CC"++; cd frida_mode; gmake
|
||||
- name: run tests
|
||||
run: sudo -E ./afl-system-config; export CC=/usr/local/Cellar/llvm/*/bin/clang; export CXX="$CC"++; export PATH=/usr/local/Cellar/llvm/*/":/usr/local/bin:$PATH"; export LLVM_CONFIG=/usr/local/Cellar/llvm/*/bin/llvm-config; gmake tests
|
||||
- name: force frida test for MacOS
|
||||
run: export AFL_PATH=`pwd`; /usr/local/bin/gcc -o test-instr test-instr.c; mkdir in; echo > in/in; AFL_NO_UI=1 ./afl-fuzz -O -i in -o out -V 5 -- ./test-instr
|
||||
|
9
.gitmodules
vendored
@ -19,3 +19,12 @@
|
||||
[submodule "coresight_mode/coresight-trace"]
|
||||
path = coresight_mode/coresight-trace
|
||||
url = https://github.com/RICSecLab/coresight-trace.git
|
||||
[submodule "nyx_mode/libnyx"]
|
||||
path = nyx_mode/libnyx
|
||||
url = https://github.com/nyx-fuzz/libnyx.git
|
||||
[submodule "nyx_mode/QEMU-Nyx"]
|
||||
path = nyx_mode/QEMU-Nyx
|
||||
url = https://github.com/nyx-fuzz/qemu-nyx.git
|
||||
[submodule "nyx_mode/packer"]
|
||||
path = nyx_mode/packer
|
||||
url = https://github.com/nyx-fuzz/packer.git
|
||||
|
18
Android.bp
@ -1,3 +1,11 @@
|
||||
//
|
||||
// NOTE: This file is outdated. None of the AFL++ team uses Android hence
|
||||
// we need users to keep this updated.
|
||||
// In the current state it will likely fail, please send fixes!
|
||||
// Also, this should build frida_mode.
|
||||
//
|
||||
|
||||
|
||||
cc_defaults {
|
||||
name: "afl-defaults",
|
||||
|
||||
@ -175,7 +183,7 @@ cc_binary_host {
|
||||
}
|
||||
|
||||
cc_library_static {
|
||||
name: "afl-llvm-rt",
|
||||
name: "afl-compiler-rt",
|
||||
compile_multilib: "64",
|
||||
vendor_available: true,
|
||||
host_supported: true,
|
||||
@ -225,6 +233,7 @@ cc_library_headers {
|
||||
],
|
||||
}
|
||||
|
||||
/*
|
||||
cc_prebuilt_library_static {
|
||||
name: "libfrida-gum",
|
||||
compile_multilib: "64",
|
||||
@ -272,7 +281,7 @@ cc_binary {
|
||||
],
|
||||
|
||||
static_libs: [
|
||||
"afl-llvm-rt",
|
||||
"afl-compiler-rt",
|
||||
"libfrida-gum",
|
||||
],
|
||||
|
||||
@ -290,6 +299,7 @@ cc_binary {
|
||||
"utils/afl_frida/android",
|
||||
],
|
||||
}
|
||||
*/
|
||||
|
||||
cc_binary {
|
||||
name: "afl-fuzz-32",
|
||||
@ -346,7 +356,7 @@ cc_binary_host {
|
||||
}
|
||||
|
||||
cc_library_static {
|
||||
name: "afl-llvm-rt-32",
|
||||
name: "afl-compiler-rt-32",
|
||||
compile_multilib: "32",
|
||||
vendor_available: true,
|
||||
host_supported: true,
|
||||
@ -385,6 +395,7 @@ cc_library_static {
|
||||
],
|
||||
}
|
||||
|
||||
/*
|
||||
cc_prebuilt_library_static {
|
||||
name: "libfrida-gum-32",
|
||||
compile_multilib: "32",
|
||||
@ -400,6 +411,7 @@ cc_prebuilt_library_static {
|
||||
"utils/afl_frida/android/arm",
|
||||
],
|
||||
}
|
||||
*/
|
||||
|
||||
subdirs = [
|
||||
"custom_mutators",
|
||||
|
31
CITATION.cff
Normal file
@ -0,0 +1,31 @@
|
||||
cff-version: 1.2.0
|
||||
message: "If you use this software, please cite it as below."
|
||||
authors:
|
||||
- given-names: Marc
|
||||
family-names: Heuse
|
||||
email: mh@mh-sec.de
|
||||
- given-names: Heiko
|
||||
family-names: Eißfeldt
|
||||
email: heiko.eissfeldt@hexco.de
|
||||
- given-names: Andrea
|
||||
family-names: Fioraldi
|
||||
email: andreafioraldi@gmail.com
|
||||
- given-names: Dominik
|
||||
family-names: Meier
|
||||
email: mail@dmnk.co
|
||||
title: "AFL++"
|
||||
version: 3.14
|
||||
type: software
|
||||
date-released: 2021-07-19
|
||||
url: "https://github.com/AFLplusplus/AFLplusplus"
|
||||
keywords:
|
||||
- fuzzing
|
||||
- fuzzer
|
||||
- fuzz-testing
|
||||
- instrumentation
|
||||
- afl-fuzz
|
||||
- qemu
|
||||
- llvm
|
||||
- unicorn-emulator
|
||||
- securiy
|
||||
license: AGPL-3.0-or-later
|
69
GNUmakefile
@ -345,9 +345,9 @@ performance-test: source-only
|
||||
help:
|
||||
@echo "HELP --- the following make targets exist:"
|
||||
@echo "=========================================="
|
||||
@echo "all: just the main afl++ binaries"
|
||||
@echo "binary-only: everything for binary-only fuzzing: qemu_mode, frida_mode, unicorn_mode, coresight_mode, libdislocator, libtokencap"
|
||||
@echo "source-only: everything for source code fuzzing: gcc_plugin, libdislocator, libtokencap"
|
||||
@echo "all: the main afl++ binaries and llvm/gcc instrumentation"
|
||||
@echo "binary-only: everything for binary-only fuzzing: frida_mode, nyx_mode, qemu_mode, frida_mode, unicorn_mode, coresight_mode, libdislocator, libtokencap"
|
||||
@echo "source-only: everything for source code fuzzing: nyx_mode, libdislocator, libtokencap"
|
||||
@echo "distrib: everything (for both binary-only and source code fuzzing)"
|
||||
@echo "man: creates simple man pages from the help option of the programs"
|
||||
@echo "install: installs everything you have compiled with the build option above"
|
||||
@ -564,24 +564,26 @@ all_done: test_build
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf $(PROGS) libradamsa.so afl-fuzz-document afl-as as afl-g++ afl-clang afl-clang++ *.o src/*.o *~ a.out core core.[1-9][0-9]* *.stackdump .test .test1 .test2 test-instr .test-instr0 .test-instr1 afl-cs-proxy afl-qemu-trace afl-gcc-fast afl-gcc-pass.so afl-g++-fast ld *.so *.8 test/unittests/*.o test/unittests/unit_maybe_alloc test/unittests/preallocable .afl-* afl-gcc afl-g++ afl-clang afl-clang++ test/unittests/unit_hash test/unittests/unit_rand *.dSYM
|
||||
rm -rf $(PROGS) afl-fuzz-document afl-as as afl-g++ afl-clang afl-clang++ *.o src/*.o *~ a.out core core.[1-9][0-9]* *.stackdump .test .test1 .test2 test-instr .test-instr0 .test-instr1 afl-cs-proxy afl-qemu-trace afl-gcc-fast afl-g++-fast ld *.so *.8 test/unittests/*.o test/unittests/unit_maybe_alloc test/unittests/preallocable .afl-* afl-gcc afl-g++ afl-clang afl-clang++ test/unittests/unit_hash test/unittests/unit_rand *.dSYM
|
||||
-$(MAKE) -f GNUmakefile.llvm clean
|
||||
-$(MAKE) -f GNUmakefile.gcc_plugin clean
|
||||
$(MAKE) -C utils/libdislocator clean
|
||||
$(MAKE) -C utils/libtokencap clean
|
||||
-$(MAKE) -C utils/libdislocator clean
|
||||
-$(MAKE) -C utils/libtokencap clean
|
||||
$(MAKE) -C utils/aflpp_driver clean
|
||||
$(MAKE) -C utils/afl_network_proxy clean
|
||||
$(MAKE) -C utils/socket_fuzzing clean
|
||||
$(MAKE) -C utils/argv_fuzzing clean
|
||||
-$(MAKE) -C utils/afl_network_proxy clean
|
||||
-$(MAKE) -C utils/socket_fuzzing clean
|
||||
-$(MAKE) -C utils/argv_fuzzing clean
|
||||
-$(MAKE) -C utils/plot_ui clean
|
||||
$(MAKE) -C qemu_mode/unsigaction clean
|
||||
$(MAKE) -C qemu_mode/libcompcov clean
|
||||
$(MAKE) -C qemu_mode/libqasan clean
|
||||
-$(MAKE) -C qemu_mode/unsigaction clean
|
||||
-$(MAKE) -C qemu_mode/libcompcov clean
|
||||
-$(MAKE) -C qemu_mode/libqasan clean
|
||||
-$(MAKE) -C frida_mode clean
|
||||
rm -rf nyx_mode/packer/linux_initramfs/init.cpio.gz nyx_mode/libnyx/libnyx/target/release/* nyx_mode/QEMU-Nyx/x86_64-softmmu/qemu-system-x86_64
|
||||
ifeq "$(IN_REPO)" "1"
|
||||
-test -e coresight_mode/coresight-trace/Makefile && $(MAKE) -C coresight_mode/coresight-trace clean || true
|
||||
-test -e qemu_mode/qemuafl/Makefile && $(MAKE) -C qemu_mode/qemuafl clean || true
|
||||
test -e unicorn_mode/unicornafl/Makefile && $(MAKE) -C unicorn_mode/unicornafl clean || true
|
||||
-test -e unicorn_mode/unicornafl/Makefile && $(MAKE) -C unicorn_mode/unicornafl clean || true
|
||||
-test -e nyx_mode/QEMU-Nyx/Makefile && $(MAKE) -C nyx_mode/QEMU-Nyx clean || true
|
||||
else
|
||||
rm -rf coresight_mode/coresight_trace
|
||||
rm -rf qemu_mode/qemuafl
|
||||
@ -593,11 +595,14 @@ deepclean: clean
|
||||
rm -rf coresight_mode/coresight-trace
|
||||
rm -rf unicorn_mode/unicornafl
|
||||
rm -rf qemu_mode/qemuafl
|
||||
rm -rf nyx_mode/libnyx nyx_mode/packer nyx_mode/QEMU-Nyx
|
||||
ifeq "$(IN_REPO)" "1"
|
||||
# NEVER EVER ACTIVATE THAT!!!!! git reset --hard >/dev/null 2>&1 || true
|
||||
git checkout coresight_mode/coresight-trace
|
||||
git checkout unicorn_mode/unicornafl
|
||||
git checkout qemu_mode/qemuafl
|
||||
git checkout nyx_mode/libnyx
|
||||
git checkout nyx_mode/packer
|
||||
git checkout nyx_mode/QEMU-Nyx
|
||||
endif
|
||||
|
||||
.PHONY: distrib
|
||||
@ -606,16 +611,19 @@ distrib: all
|
||||
ifneq "$(SYS)" "Darwin"
|
||||
-$(MAKE) -f GNUmakefile.gcc_plugin
|
||||
endif
|
||||
$(MAKE) -C utils/libdislocator
|
||||
$(MAKE) -C utils/libtokencap
|
||||
$(MAKE) -C utils/afl_network_proxy
|
||||
$(MAKE) -C utils/socket_fuzzing
|
||||
$(MAKE) -C utils/argv_fuzzing
|
||||
-$(MAKE) -C utils/libdislocator
|
||||
-$(MAKE) -C utils/libtokencap
|
||||
-$(MAKE) -C utils/afl_network_proxy
|
||||
-$(MAKE) -C utils/socket_fuzzing
|
||||
-$(MAKE) -C utils/argv_fuzzing
|
||||
# -$(MAKE) -C utils/plot_ui
|
||||
-$(MAKE) -C frida_mode
|
||||
ifneq "$(SYS)" "Darwin"
|
||||
ifeq "$(ARCH)" "aarch64"
|
||||
-$(MAKE) -C coresight_mode
|
||||
endif
|
||||
ifeq "$(SYS)" "Linux"
|
||||
-cd nyx_mode && ./build_nyx_support.sh
|
||||
endif
|
||||
-cd qemu_mode && sh ./build_qemu_support.sh
|
||||
-cd unicorn_mode && unset CFLAGS && sh ./build_unicorn_support.sh
|
||||
@ -623,16 +631,19 @@ endif
|
||||
|
||||
.PHONY: binary-only
|
||||
binary-only: test_shm test_python ready $(PROGS)
|
||||
$(MAKE) -C utils/libdislocator
|
||||
$(MAKE) -C utils/libtokencap
|
||||
$(MAKE) -C utils/afl_network_proxy
|
||||
$(MAKE) -C utils/socket_fuzzing
|
||||
$(MAKE) -C utils/argv_fuzzing
|
||||
-$(MAKE) -C utils/libdislocator
|
||||
-$(MAKE) -C utils/libtokencap
|
||||
-$(MAKE) -C utils/afl_network_proxy
|
||||
-$(MAKE) -C utils/socket_fuzzing
|
||||
-$(MAKE) -C utils/argv_fuzzing
|
||||
# -$(MAKE) -C utils/plot_ui
|
||||
-$(MAKE) -C frida_mode
|
||||
ifneq "$(SYS)" "Darwin"
|
||||
ifeq "$(ARCH)" "aarch64"
|
||||
-$(MAKE) -C coresight_mode
|
||||
endif
|
||||
ifeq "$(SYS)" "Linux"
|
||||
-cd nyx_mode && ./build_nyx_support.sh
|
||||
endif
|
||||
-cd qemu_mode && sh ./build_qemu_support.sh
|
||||
-cd unicorn_mode && unset CFLAGS && sh ./build_unicorn_support.sh
|
||||
@ -644,9 +655,12 @@ source-only: all
|
||||
ifneq "$(SYS)" "Darwin"
|
||||
-$(MAKE) -f GNUmakefile.gcc_plugin
|
||||
endif
|
||||
$(MAKE) -C utils/libdislocator
|
||||
$(MAKE) -C utils/libtokencap
|
||||
-$(MAKE) -C utils/libdislocator
|
||||
-$(MAKE) -C utils/libtokencap
|
||||
# -$(MAKE) -C utils/plot_ui
|
||||
ifeq "$(SYS)" "Linux"
|
||||
-cd nyx_mode && ./build_nyx_support.sh
|
||||
endif
|
||||
|
||||
%.8: %
|
||||
@echo .TH $* 8 $(BUILD_DATE) "afl++" > $@
|
||||
@ -684,6 +698,7 @@ install: all $(MANPAGES)
|
||||
@if [ -f socketfuzz32.so -o -f socketfuzz64.so ]; then $(MAKE) -C utils/socket_fuzzing install; fi
|
||||
@if [ -f argvfuzz32.so -o -f argvfuzz64.so ]; then $(MAKE) -C utils/argv_fuzzing install; fi
|
||||
@if [ -f afl-frida-trace.so ]; then install -m 755 afl-frida-trace.so $${DESTDIR}$(HELPER_PATH); fi
|
||||
@if [ -f libnyx.so ]; then install -m 755 libnyx.so $${DESTDIR}$(HELPER_PATH); fi
|
||||
@if [ -f utils/afl_network_proxy/afl-network-server ]; then $(MAKE) -C utils/afl_network_proxy install; fi
|
||||
@if [ -f utils/aflpp_driver/libAFLDriver.a ]; then set -e; install -m 644 utils/aflpp_driver/libAFLDriver.a $${DESTDIR}$(HELPER_PATH); fi
|
||||
@if [ -f utils/aflpp_driver/libAFLQemuDriver.a ]; then set -e; install -m 644 utils/aflpp_driver/libAFLQemuDriver.a $${DESTDIR}$(HELPER_PATH); fi
|
||||
@ -706,7 +721,7 @@ endif
|
||||
.PHONY: uninstall
|
||||
uninstall:
|
||||
-cd $${DESTDIR}$(BIN_PATH) && rm -f $(PROGS) $(SH_PROGS) afl-cs-proxy afl-qemu-trace afl-plot-ui afl-fuzz-document afl-network-server afl-g* afl-plot.sh afl-as afl-ld-lto afl-c* afl-lto*
|
||||
-cd $${DESTDIR}$(HELPER_PATH) && rm -f afl-g*.*o afl-llvm-*.*o afl-compiler-*.*o libdislocator.so libtokencap.so libcompcov.so libqasan.so afl-frida-trace.so socketfuzz*.so argvfuzz*.so libAFLDriver.a libAFLQemuDriver.a as afl-as SanitizerCoverage*.so compare-transform-pass.so cmplog-*-pass.so split-*-pass.so dynamic_list.txt
|
||||
-cd $${DESTDIR}$(HELPER_PATH) && rm -f afl-g*.*o afl-llvm-*.*o afl-compiler-*.*o libdislocator.so libtokencap.so libcompcov.so libqasan.so afl-frida-trace.so libnyx.so socketfuzz*.so argvfuzz*.so libAFLDriver.a libAFLQemuDriver.a as afl-as SanitizerCoverage*.so compare-transform-pass.so cmplog-*-pass.so split-*-pass.so dynamic_list.txt
|
||||
-rm -rf $${DESTDIR}$(MISC_PATH)/testcases $${DESTDIR}$(MISC_PATH)/dictionaries
|
||||
-sh -c "ls docs/*.md | sed 's|^docs/|$${DESTDIR}$(DOC_PATH)/|' | xargs rm -f"
|
||||
-cd $${DESTDIR}$(MAN_PATH) && rm -f $(MANPAGES)
|
||||
|
@ -11,7 +11,7 @@
|
||||
# from Laszlo Szekeres.
|
||||
#
|
||||
# Copyright 2015 Google Inc. All rights reserved.
|
||||
# Copyright 2019-2020 AFLplusplus Project. All rights reserved.
|
||||
# Copyright 2019-2022 AFLplusplus Project. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
47
README.md
@ -1,20 +1,21 @@
|
||||
# American Fuzzy Lop plus plus (AFL++)
|
||||
|
||||
<img align="right" src="https://raw.githubusercontent.com/andreafioraldi/AFLplusplus-website/master/static/logo_256x256.png" alt="AFL++ logo">
|
||||
<img align="right" src="https://raw.githubusercontent.com/AFLplusplus/Website/master/static/aflpp_bg.svg" alt="AFL++ logo" width="250" heigh="250">
|
||||
|
||||
Release version: [3.14c](https://github.com/AFLplusplus/AFLplusplus/releases)
|
||||
Release version: [4.00c](https://github.com/AFLplusplus/AFLplusplus/releases)
|
||||
|
||||
GitHub version: 3.15a
|
||||
GitHub version: 4.00c
|
||||
|
||||
Repository:
|
||||
[https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus)
|
||||
|
||||
AFL++ is maintained by:
|
||||
|
||||
* Marc "van Hauser" Heuse <mh@mh-sec.de>,
|
||||
* Heiko "hexcoder-" Eißfeldt <heiko.eissfeldt@hexco.de>,
|
||||
* Andrea Fioraldi <andreafioraldi@gmail.com> and
|
||||
* Dominik Maier <mail@dmnk.co>.
|
||||
* Marc "van Hauser" Heuse <mh@mh-sec.de>
|
||||
* Heiko "hexcoder-" Eißfeldt <heiko.eissfeldt@hexco.de>
|
||||
* Andrea Fioraldi <andreafioraldi@gmail.com>
|
||||
* Dominik Maier <mail@dmnk.co>
|
||||
* Documentation: Jana Aydinbas <jana.aydinbas@gmail.com>
|
||||
|
||||
Originally developed by Michał "lcamtuf" Zalewski.
|
||||
|
||||
@ -28,9 +29,14 @@ terms of the Apache-2.0 License. See the [LICENSE](LICENSE) for details.
|
||||
|
||||
Here is some information to get you started:
|
||||
|
||||
* For an overview of the AFL++ documentation and a very helpful graphical guide,
|
||||
please visit [docs/README.md](docs/README.md).
|
||||
* To get you started with tutorials, go to
|
||||
[docs/tutorials.md](docs/tutorials.md).
|
||||
* For releases, see the
|
||||
[Releases tab](https://github.com/AFLplusplus/AFLplusplus/releases) and
|
||||
[branches](#branches). Also take a look at the list of
|
||||
[branches](#branches). The best branches to use are, however, `stable` or
|
||||
`dev` - depending on your risk appetite. Also take a look at the list of
|
||||
[important changes in AFL++](docs/important_changes.md) and the list of
|
||||
[features](docs/features.md).
|
||||
* If you want to use AFL++ for your academic work, check the
|
||||
@ -40,8 +46,6 @@ Here is some information to get you started:
|
||||
`afl-clang-fast` with `AFL_LLVM_CMPLOG=1`. You can find the `aflplusplus`
|
||||
default configuration on Google's
|
||||
[fuzzbench](https://github.com/google/fuzzbench/tree/master/fuzzers/aflplusplus).
|
||||
* To get you started with tutorials, go to
|
||||
[docs/tutorials.md](docs/tutorials.md).
|
||||
|
||||
## Building and installing AFL++
|
||||
|
||||
@ -57,7 +61,8 @@ This image is automatically generated when a push to the stable repo happens
|
||||
(see [branches](#branches)). You will find your target source code in `/src` in
|
||||
the container.
|
||||
|
||||
To build AFL++ yourself, continue at [docs/INSTALL.md](docs/INSTALL.md).
|
||||
To build AFL++ yourself - which we recommend - continue at
|
||||
[docs/INSTALL.md](docs/INSTALL.md).
|
||||
|
||||
## Quick start: Fuzzing with AFL++
|
||||
|
||||
@ -115,20 +120,24 @@ Step-by-step quick start:
|
||||
|
||||
You can generate cores or use gdb directly to follow up the crashes.
|
||||
|
||||
6. We cannot stress this enough - if you want to fuzz effectively, read the
|
||||
[docs/fuzzing_in_depth.md](docs/fuzzing_in_depth.md) document!
|
||||
|
||||
## Contact
|
||||
|
||||
Questions? Concerns? Bug reports?
|
||||
|
||||
* The contributors can be reached via
|
||||
* The contributors can be reached via (e.g., by creating an issue):
|
||||
[https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus).
|
||||
* Take a look at our [FAQ](docs/FAQ.md). If you find an interesting or important
|
||||
question missing, submit it via
|
||||
[https://github.com/AFLplusplus/AFLplusplus/discussions](https://github.com/AFLplusplus/AFLplusplus/discussions).
|
||||
* There is a mailing list for the AFL/AFL++ project
|
||||
* Best: join the [Awesome Fuzzing](https://discord.gg/gCraWct) Discord server.
|
||||
* There is a (not really used) mailing list for the AFL/AFL++ project
|
||||
([browse archive](https://groups.google.com/group/afl-users)). To compare
|
||||
notes with other users or to get notified about major new features, send an
|
||||
email to <afl-users+subscribe@googlegroups.com>.
|
||||
* Or join the [Awesome Fuzzing](https://discord.gg/gCraWct) Discord server.
|
||||
email to <afl-users+subscribe@googlegroups.com>, but note that this is not
|
||||
managed by us.
|
||||
|
||||
## Branches
|
||||
|
||||
@ -141,7 +150,7 @@ The following branches exist:
|
||||
stability
|
||||
* [dev](https://github.com/AFLplusplus/AFLplusplus/tree/dev): development state
|
||||
of AFL++ - bleeding edge and you might catch a checkout which does not compile
|
||||
or has a bug. *We only accept PRs in dev!!*
|
||||
or has a bug. **We only accept PRs (pull requests) for the 'dev' branch!**
|
||||
* (any other): experimental branches to work on specific features or testing new
|
||||
functionality or changes.
|
||||
|
||||
@ -155,7 +164,7 @@ This can be your way to support and contribute to AFL++ - extend it to do
|
||||
something cool.
|
||||
|
||||
For everyone who wants to contribute (and send pull requests), please read our
|
||||
[contributing guidelines](CONTRIBUTING.md) before your submit.
|
||||
[contributing guidelines](CONTRIBUTING.md) before you submit.
|
||||
|
||||
## Special thanks
|
||||
|
||||
@ -215,7 +224,7 @@ Thank you! (For people sending pull requests - please add yourself to this list
|
||||
Josephine Calliotte Konrad Welc
|
||||
Thomas Rooijakkers David Carlier
|
||||
Ruben ten Hove Joey Jiao
|
||||
fuzzah
|
||||
fuzzah @intrigus-lgtm
|
||||
```
|
||||
|
||||
</details>
|
||||
@ -243,4 +252,4 @@ presented at WOOT'20:
|
||||
}
|
||||
```
|
||||
|
||||
</details>
|
||||
</details>
|
||||
|
38
afl-whatsup
@ -6,7 +6,7 @@
|
||||
# Originally written by Michal Zalewski
|
||||
#
|
||||
# Copyright 2015 Google Inc. All rights reserved.
|
||||
# Copyright 2019-2020 AFLplusplus Project. All rights reserved.
|
||||
# Copyright 2019-2022 AFLplusplus Project. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@ -91,9 +91,9 @@ TOTAL_CRASHES=0
|
||||
TOTAL_PFAV=0
|
||||
TOTAL_PENDING=0
|
||||
|
||||
# Time since last path / crash / hang, formatted as string
|
||||
# Time since last find / crash / hang, formatted as string
|
||||
FMT_TIME="0 days 0 hours"
|
||||
FMT_PATH="${RED}none seen yet${NC}"
|
||||
FMT_FIND="${RED}none seen yet${NC}"
|
||||
FMT_CRASH="none seen yet"
|
||||
FMT_HANG="none seen yet"
|
||||
|
||||
@ -135,7 +135,7 @@ fmt_duration()
|
||||
|
||||
FIRST=true
|
||||
TOTAL_WCOP=
|
||||
TOTAL_LAST_PATH=0
|
||||
TOTAL_LAST_FIND=0
|
||||
|
||||
for i in `find . -maxdepth 2 -iname fuzzer_stats | sort`; do
|
||||
|
||||
@ -169,7 +169,7 @@ for i in `find . -maxdepth 2 -iname fuzzer_stats | sort`; do
|
||||
fi
|
||||
|
||||
DEAD_CNT=$((DEAD_CNT + 1))
|
||||
last_path=0
|
||||
last_find=0
|
||||
|
||||
if [ "$PROCESS_DEAD" = "" ]; then
|
||||
|
||||
@ -183,17 +183,17 @@ for i in `find . -maxdepth 2 -iname fuzzer_stats | sort`; do
|
||||
|
||||
EXEC_SEC=0
|
||||
test -z "$RUN_UNIX" -o "$RUN_UNIX" = 0 || EXEC_SEC=$((execs_done / RUN_UNIX))
|
||||
PATH_PERC=$((cur_path * 100 / paths_total))
|
||||
PATH_PERC=$((cur_item * 100 / corpus_count))
|
||||
|
||||
TOTAL_TIME=$((TOTAL_TIME + RUN_UNIX))
|
||||
TOTAL_EPS=$((TOTAL_EPS + EXEC_SEC))
|
||||
TOTAL_EXECS=$((TOTAL_EXECS + execs_done))
|
||||
TOTAL_CRASHES=$((TOTAL_CRASHES + unique_crashes))
|
||||
TOTAL_CRASHES=$((TOTAL_CRASHES + saved_crashes))
|
||||
TOTAL_PENDING=$((TOTAL_PENDING + pending_total))
|
||||
TOTAL_PFAV=$((TOTAL_PFAV + pending_favs))
|
||||
|
||||
if [ "$last_path" -gt "$TOTAL_LAST_PATH" ]; then
|
||||
TOTAL_LAST_PATH=$last_path
|
||||
if [ "$last_find" -gt "$TOTAL_LAST_FIND" ]; then
|
||||
TOTAL_LAST_FIND=$last_find
|
||||
fi
|
||||
|
||||
if [ "$SUMMARY_ONLY" = "" ]; then
|
||||
@ -210,7 +210,7 @@ for i in `find . -maxdepth 2 -iname fuzzer_stats | sort`; do
|
||||
echo " ${RED}slow execution, $EXEC_SEC execs/sec${NC}"
|
||||
fi
|
||||
|
||||
fmt_duration $last_path && FMT_PATH=$DUR_STRING
|
||||
fmt_duration $last_find && FMT_FIND=$DUR_STRING
|
||||
fmt_duration $last_crash && FMT_CRASH=$DUR_STRING
|
||||
fmt_duration $last_hang && FMT_HANG=$DUR_STRING
|
||||
FMT_CWOP="not available"
|
||||
@ -220,7 +220,7 @@ for i in `find . -maxdepth 2 -iname fuzzer_stats | sort`; do
|
||||
test "$cycles_wo_finds" -gt 50 && FMT_CWOP="${RED}$cycles_wo_finds${NC}"
|
||||
}
|
||||
|
||||
echo " last_path : $FMT_PATH"
|
||||
echo " last_find : $FMT_FIND"
|
||||
echo " last_crash : $FMT_CRASH"
|
||||
echo " last_hang : $FMT_HANG"
|
||||
echo " cycles_wo_finds : $FMT_CWOP"
|
||||
@ -229,12 +229,12 @@ for i in `find . -maxdepth 2 -iname fuzzer_stats | sort`; do
|
||||
MEM_USAGE=$(ps aux | grep $fuzzer_pid | grep -v grep | awk '{print $4}')
|
||||
|
||||
echo " cpu usage $CPU_USAGE%, memory usage $MEM_USAGE%"
|
||||
echo " cycle $((cycles_done + 1)), lifetime speed $EXEC_SEC execs/sec, path $cur_path/$paths_total (${PATH_PERC}%)"
|
||||
echo " cycles $((cycles_done + 1)), lifetime speed $EXEC_SEC execs/sec, items $cur_item/$corpus_count (${PATH_PERC}%)"
|
||||
|
||||
if [ "$unique_crashes" = "0" ]; then
|
||||
if [ "$saved_crashes" = "0" ]; then
|
||||
echo " pending $pending_favs/$pending_total, coverage $bitmap_cvg, no crashes yet"
|
||||
else
|
||||
echo " pending $pending_favs/$pending_total, coverage $bitmap_cvg, crash count $unique_crashes (!)"
|
||||
echo " pending $pending_favs/$pending_total, coverage $bitmap_cvg, crashes saved $saved_crashes (!)"
|
||||
fi
|
||||
|
||||
echo
|
||||
@ -243,7 +243,7 @@ for i in `find . -maxdepth 2 -iname fuzzer_stats | sort`; do
|
||||
|
||||
done
|
||||
|
||||
# Formatting for total time, time since last path, crash, and hang
|
||||
# Formatting for total time, time since last find, crash, and hang
|
||||
fmt_duration $((CUR_TIME - TOTAL_TIME)) && FMT_TIME=$DUR_STRING
|
||||
# Formatting for total execution
|
||||
FMT_EXECS="0 millions"
|
||||
@ -263,7 +263,7 @@ TOTAL_DAYS=$((TOTAL_TIME / 60 / 60 / 24))
|
||||
TOTAL_HRS=$(((TOTAL_TIME / 60 / 60) % 24))
|
||||
|
||||
test -z "$TOTAL_WCOP" && TOTAL_WCOP="not available"
|
||||
fmt_duration $TOTAL_LAST_PATH && TOTAL_LAST_PATH=$DUR_STRING
|
||||
fmt_duration $TOTAL_LAST_FIND && TOTAL_LAST_FIND=$DUR_STRING
|
||||
|
||||
test "$TOTAL_TIME" = "0" && TOTAL_TIME=1
|
||||
|
||||
@ -293,15 +293,15 @@ echo " Cumulative speed : $TOTAL_EPS execs/sec"
|
||||
if [ "$ALIVE_CNT" -gt "0" ]; then
|
||||
echo " Average speed : $((TOTAL_EPS / ALIVE_CNT)) execs/sec"
|
||||
fi
|
||||
echo " Pending paths : $TOTAL_PFAV faves, $TOTAL_PENDING total"
|
||||
echo " Pending items : $TOTAL_PFAV faves, $TOTAL_PENDING total"
|
||||
|
||||
if [ "$ALIVE_CNT" -gt "1" ]; then
|
||||
echo " Pending per fuzzer : $((TOTAL_PFAV/ALIVE_CNT)) faves, $((TOTAL_PENDING/ALIVE_CNT)) total (on average)"
|
||||
fi
|
||||
|
||||
echo " Crashes found : $TOTAL_CRASHES locally unique"
|
||||
echo " Crashes saved : $TOTAL_CRASHES"
|
||||
echo "Cycles without finds : $TOTAL_WCOP"
|
||||
echo " Time without finds : $TOTAL_LAST_PATH"
|
||||
echo " Time without finds : $TOTAL_LAST_FIND"
|
||||
echo
|
||||
|
||||
exit 0
|
||||
|
@ -11,7 +11,7 @@
|
||||
# Adapted for AFLplusplus by Dominik Maier <mail@dmnk.co>
|
||||
#
|
||||
# Copyright 2017 Battelle Memorial Institute. All rights reserved.
|
||||
# Copyright 2019-2020 AFLplusplus Project. All rights reserved.
|
||||
# Copyright 2019-2022 AFLplusplus Project. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -1 +1 @@
|
||||
eedf07d
|
||||
cbe5e32
|
||||
|
@ -14,7 +14,7 @@
|
||||
# <andreafioraldi@gmail.com>
|
||||
#
|
||||
# Copyright 2017 Battelle Memorial Institute. All rights reserved.
|
||||
# Copyright 2019-2020 AFLplusplus Project. All rights reserved.
|
||||
# Copyright 2019-2022 AFLplusplus Project. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
|
@ -100,8 +100,8 @@ extern "C" size_t afl_custom_fuzz(MyMutator *mutator, // return value from afl_c
|
||||
// Copy to a new buffer ( mutated_out )
|
||||
size_t mutated_size = s.size() <= max_size ? s.size() : max_size; // check if raw data's size is larger than max_size
|
||||
|
||||
delete mutator->mutated_out;
|
||||
mutator->mutated_out = new uint8_t[mutated_size+1];
|
||||
delete[] mutator->mutated_out;
|
||||
mutator->mutated_out = new uint8_t[mutated_size];
|
||||
memcpy(mutator->mutated_out, s.c_str(), mutated_size); // copy the mutated data
|
||||
// Assign the mutated data and return mutated_size
|
||||
*out_buf = mutator->mutated_out;
|
||||
|
@ -4,4 +4,7 @@
|
||||
class MyMutator : public protobuf_mutator::Mutator {
|
||||
public:
|
||||
uint8_t *mutated_out = nullptr;
|
||||
~MyMutator() {
|
||||
delete[] mutated_out;
|
||||
}
|
||||
};
|
||||
|
@ -4473,6 +4473,10 @@ static word prim_sys(word op, word a, word b, word c) {
|
||||
FD_CLOEXEC,
|
||||
F_DUPFD,
|
||||
F_DUPFD_CLOEXEC,
|
||||
#if defined(F_DUP2FD)
|
||||
F_DUP2FD,
|
||||
F_DUP2FD_CLOEXEC,
|
||||
#endif
|
||||
F_GETFD,
|
||||
F_SETFD,
|
||||
F_GETFL,
|
||||
|
@ -1,6 +1,6 @@
|
||||
# AFL++ dictionaries
|
||||
|
||||
(See [../README.md](../README.md) for the general instruction manual.)
|
||||
For the general instruction manual, see [docs/README.md](../docs/README.md).
|
||||
|
||||
This subdirectory contains a set of dictionaries that can be used in conjunction
|
||||
with the -x option to allow the fuzzer to effortlessly explore the grammar of
|
||||
|
@ -1,24 +1,31 @@
|
||||
# Changelog
|
||||
|
||||
This is the list of all noteworthy changes made in every public release of
|
||||
the tool. See README.md for the general instruction manual.
|
||||
This is the list of all noteworthy changes made in every public
|
||||
release of the tool. See README.md for the general instruction manual.
|
||||
|
||||
## Staying informed
|
||||
|
||||
Want to stay in the loop on major new features? Join our mailing list by
|
||||
sending a mail to <afl-users+subscribe@googlegroups.com>.
|
||||
|
||||
### Version ++3.15a (dev)
|
||||
- documentation restructuring, made possible by Google Season of Docs
|
||||
### Version ++4.00c (release)
|
||||
- complete documentation restructuring, made possible by Google Season
|
||||
of Docs :) thank you Jana!
|
||||
- we renamed several UI and fuzzer_stat entries to be more precise,
|
||||
e.g. "unique crashes" -> "saved crashes", "total paths" ->
|
||||
"corpus count", "current path" -> "current item".
|
||||
This might need changing custom scripting!
|
||||
- Nyx mode (full system emulation with snapshot capability) has been
|
||||
added - thanks to @schumilo and @eqv!
|
||||
- unicorn_mode:
|
||||
- Moved to unicorn2! by Ziqiao Kong (@lazymio)
|
||||
- Faster, more accurate emulation (newer QEMU base), risc-v support
|
||||
- removed indirections in rust callbacks
|
||||
- new binary-only fuzzing mode: coresight_mode for aarch64 CPUs :)
|
||||
thanks to RICSecLab submitting!
|
||||
- if instrumented libaries are dlopen()'ed after the forkserver you
|
||||
will now see crashes. before you would have colliding coverage.
|
||||
we changed this to force fixing a broken setup rather then allowing
|
||||
will now see a crash. Before you would have colliding coverage.
|
||||
We changed this to force fixing a broken setup rather then allowing
|
||||
ineffective fuzzing.
|
||||
See docs/best_practices.md how to fix such setups.
|
||||
- afl-fuzz:
|
||||
@ -26,14 +33,17 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
|
||||
(it is better!)
|
||||
- fix a regression introduced in 3.10 that resulted in less
|
||||
coverage being detected. thanks to Collin May for reporting!
|
||||
- ensure all spawned targets are killed on exit
|
||||
- added AFL_IGNORE_PROBLEMS, plus checks to identify and abort on
|
||||
incorrect LTO usage setups and enhanced the READMEs for better
|
||||
information on how to deal with instrumenting libraries
|
||||
- fix -n dumb mode (nobody should use this)
|
||||
- fix -n dumb mode (nobody should use this mode though)
|
||||
- fix stability issue with LTO and cmplog
|
||||
- better banner
|
||||
- more effective cmplog mode
|
||||
- more often update the UI when in input2stage mode
|
||||
- qemu_mode/unicorn_mode: fixed OOB write when using libcompcov,
|
||||
thanks to kotee4ko for reporting!
|
||||
- frida_mode:
|
||||
- better performance, bug fixes
|
||||
- David Carlier added Android support :)
|
||||
@ -43,16 +53,22 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
|
||||
- fix bug where targets are not killed on timeouts
|
||||
- moved hidden afl-showmap -A option to -H to be used for
|
||||
coresight_mode
|
||||
- Prevent accidently killing non-afl/fuzz services when aborting
|
||||
- Prevent accidentaly killing non-afl/fuzz services when aborting
|
||||
afl-showmap and other tools.
|
||||
- afl-cc:
|
||||
- detect overflow reads on initial input buffer for asan
|
||||
- new cmplog mode (incompatible with older afl++ versions)
|
||||
- support llvm IR select instrumentation for default PCGUARD and LTO
|
||||
- fix for shared linking on MacOS
|
||||
- better selective instrumentation AFL_LLVM_{ALLOW|DENY}LIST
|
||||
on filename matching (requires llvm 11 or newer)
|
||||
- fixed a potential crash in targets for LAF string handling
|
||||
- fixed a bad assert in LAF split switches
|
||||
- added AFL_USE_TSAN thread sanitizer support
|
||||
- llvm and LTO mode modified to work with new llvm 14-dev (again. again.)
|
||||
- llvm and LTO mode modified to work with new llvm 14-dev (again.)
|
||||
- fix for AFL_REAL_LD
|
||||
- more -z defs filtering
|
||||
- make -v without options work
|
||||
- added the very good grammar mutator "GramaTron" to the
|
||||
custom_mutators
|
||||
- added optimin, a faster and better corpus minimizer by
|
||||
@ -60,11 +76,10 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
|
||||
- added afl-persistent-config script to set perform permanent system
|
||||
configuration settings for fuzzing, for Linux and Macos.
|
||||
thanks to jhertz!
|
||||
- added xml, curl and exotic string functions to llvm dictionary features
|
||||
- added xml, curl & exotic string functions to llvm dictionary feature
|
||||
- fix AFL_PRELOAD issues on MacOS
|
||||
- removed utils/afl_frida because frida_mode/ is now so much better
|
||||
- added uninstall target to makefile (todo: update new readme!)
|
||||
- removed indirections in rust callbacks for unicornafl
|
||||
|
||||
### Version ++3.14c (release)
|
||||
- afl-fuzz:
|
||||
@ -84,7 +99,7 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
|
||||
- Fix to instrument global namespace functions in c++
|
||||
- Fix for llvm 13
|
||||
- support partial linking
|
||||
- do honor AFL_LLVM_{ALLOW/DENY}LIST for LTO autodictionary and DICT2FILE
|
||||
- do honor AFL_LLVM_{ALLOW/DENY}LIST for LTO autodictionary andDICT2FILE
|
||||
- We do support llvm versions from 3.8 to 5.0 again
|
||||
- frida_mode:
|
||||
- several fixes for cmplog
|
||||
|
60
docs/FAQ.md
@ -58,10 +58,10 @@ If you find an interesting or important question missing, submit it via
|
||||
|
||||
A program contains `functions`, `functions` contain the compiled machine code.
|
||||
The compiled machine code in a `function` can be in a single or many `basic
|
||||
blocks`. A `basic block` is the largest possible number of subsequent machine
|
||||
code instructions that has exactly one entry point (which can be be entered by
|
||||
multiple other basic blocks) and runs linearly without branching or jumping to
|
||||
other addresses (except at the end).
|
||||
blocks`. A `basic block` is the **largest possible number of subsequent machine
|
||||
code instructions** that has **exactly one entry point** (which can be be entered by
|
||||
multiple other basic blocks) and runs linearly **without branching or jumping to
|
||||
other addresses** (except at the end).
|
||||
|
||||
```
|
||||
function() {
|
||||
@ -180,8 +180,58 @@ If you find an interesting or important question missing, submit it via
|
||||
[best_practices.md#improving-stability](best_practices.md#improving-stability).
|
||||
</p></details>
|
||||
|
||||
<details>
|
||||
<summary id="what-are-power-schedules">What are power schedules?</summary><p>
|
||||
|
||||
Not every item in our queue/corpus is the same, some are more interesting,
|
||||
others provide little value.
|
||||
A power schedule measures how "interesting" a value is, and depending on
|
||||
the calculated value spends more or less time mutating it.
|
||||
|
||||
AFL++ comes with several power schedules, initially ported from
|
||||
[AFLFast](https://github.com/mboehme/aflfast), however, modified to be more
|
||||
effective and several more modes added.
|
||||
|
||||
The most effective modes are `-p fast` (default) and `-p explore`.
|
||||
|
||||
If you fuzz with several parallel afl-fuzz instances, then it is beneficial
|
||||
to assign a different schedule to each instance, however the majority should
|
||||
be `fast` and `explore`.
|
||||
|
||||
It does not make sense to explain the details of the calculation and
|
||||
reasoning behind all of the schedules. If you are interested, read the source
|
||||
code and the AFLFast paper.
|
||||
</p></details>
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
<details>
|
||||
<summary id="fatal-forkserver-is-already-up-but-an-instrumented-dlopen-library-loaded-afterwards">FATAL: forkserver is already up but an instrumented dlopen library loaded afterwards</summary><p>
|
||||
|
||||
It can happen that you see this error on startup when fuzzing a target:
|
||||
|
||||
```
|
||||
[-] FATAL: forkserver is already up, but an instrumented dlopen() library
|
||||
loaded afterwards. You must AFL_PRELOAD such libraries to be able
|
||||
to fuzz them or LD_PRELOAD to run outside of afl-fuzz.
|
||||
To ignore this set AFL_IGNORE_PROBLEMS=1.
|
||||
```
|
||||
|
||||
As the error describes, a dlopen() call is happening in the target that is
|
||||
loading an instrumented library after the forkserver is already in place. This
|
||||
is a problem for afl-fuzz because when the forkserver is started, we must know
|
||||
the map size already and it can't be changed later.
|
||||
|
||||
The best solution is to simply set `AFL_PRELOAD=foo.so` to the libraries that
|
||||
are dlopen'ed (e.g., use `strace` to see which), or to set a manual forkserver
|
||||
after the final dlopen().
|
||||
|
||||
If this is not a viable option, you can set `AFL_IGNORE_PROBLEMS=1` but then
|
||||
the existing map will be used also for the newly loaded libraries, which
|
||||
allows it to work, however, the efficiency of the fuzzing will be partially
|
||||
degraded.
|
||||
</p></details>
|
||||
|
||||
<details>
|
||||
<summary id="i-got-a-weird-compile-error-from-clang">I got a weird compile error from clang.</summary><p>
|
||||
|
||||
@ -204,4 +254,4 @@ If you find an interesting or important question missing, submit it via
|
||||
package and because of that the AFL++ llvm plugins do not match anymore.
|
||||
|
||||
Solution: `git pull ; make clean install` of AFL++.
|
||||
</p></details>
|
||||
</p></details>
|
||||
|
@ -12,7 +12,7 @@ docker run -ti -v /location/of/your/target:/src aflplusplus/aflplusplus
|
||||
```
|
||||
|
||||
This image is automatically generated when a push to the stable repo happens.
|
||||
You will find your target source code in /src in the container.
|
||||
You will find your target source code in `/src` in the container.
|
||||
|
||||
If you want to build AFL++ yourself, you have many options. The easiest choice
|
||||
is to build and install everything:
|
||||
@ -33,10 +33,10 @@ sudo make install
|
||||
It is recommended to install the newest available gcc, clang and llvm-dev
|
||||
possible in your distribution!
|
||||
|
||||
Note that "make distrib" also builds instrumentation, QEMU mode, unicorn_mode
|
||||
and more. If you just want plain AFL++, then do "make all". However, compiling
|
||||
and using at least instrumentation is highly recommended for much better results
|
||||
- hence in this case choose:
|
||||
Note that `make distrib` also builds FRIDA mode, QEMU mode, unicorn_mode, and
|
||||
more. If you just want plain AFL++, then do `make all`. If you want some
|
||||
assisting tooling compiled but are not interested in binary-only targets, then
|
||||
instead choose:
|
||||
|
||||
```shell
|
||||
make source-only
|
||||
@ -44,11 +44,12 @@ make source-only
|
||||
|
||||
These build targets exist:
|
||||
|
||||
* all: just the main AFL++ binaries
|
||||
* binary-only: everything for binary-only fuzzing: qemu_mode, unicorn_mode,
|
||||
libdislocator, libtokencap
|
||||
* source-only: everything for source code fuzzing: instrumentation,
|
||||
libdislocator, libtokencap
|
||||
* all: the main afl++ binaries and llvm/gcc instrumentation
|
||||
* binary-only: everything for binary-only fuzzing: frida_mode, nyx_mode,
|
||||
qemu_mode, frida_mode, unicorn_mode, coresight_mode, libdislocator,
|
||||
libtokencap
|
||||
* source-only: everything for source code fuzzing: nyx_mode, libdislocator,
|
||||
libtokencap
|
||||
* distrib: everything (for both binary-only and source code fuzzing)
|
||||
* man: creates simple man pages from the help option of the programs
|
||||
* install: installs everything you have compiled with the build options above
|
||||
@ -86,32 +87,39 @@ e.g.: `make ASAN_BUILD=1`
|
||||
|
||||
## MacOS X on x86 and arm64 (M1)
|
||||
|
||||
MacOS X should work, but there are some gotchas due to the idiosyncrasies of the
|
||||
platform. On top of this, we have limited release testing capabilities and
|
||||
depend mostly on user feedback.
|
||||
MacOS has some gotchas due to the idiosyncrasies of the platform.
|
||||
|
||||
To build AFL, install llvm (and perhaps gcc) from brew and follow the general
|
||||
instructions for Linux. If possible, avoid Xcode at all cost.
|
||||
|
||||
`brew install wget git make cmake llvm gdb`
|
||||
```shell
|
||||
brew install wget git make cmake llvm gdb coreutils
|
||||
```
|
||||
|
||||
Be sure to setup `PATH` to point to the correct clang binaries and use the
|
||||
freshly installed clang, clang++ and gmake, e.g.:
|
||||
freshly installed clang, clang++, llvm-config, gmake and coreutils, e.g.:
|
||||
|
||||
```
|
||||
export PATH="/usr/local/Cellar/llvm/12.0.1/bin/:$PATH"
|
||||
```shell
|
||||
# Depending on your MacOS system + brew version it is either
|
||||
export PATH="/opt/homebrew/opt/llvm/bin:$PATH"
|
||||
# or
|
||||
export PATH="/usr/local/opt/llvm/bin:$PATH"
|
||||
# you can check with "brew info llvm"
|
||||
|
||||
export PATH="/usr/local/opt/coreutils/libexec/gnubin:/usr/local/bin:$PATH"
|
||||
export CC=clang
|
||||
export CXX=clang++
|
||||
gmake
|
||||
cd frida_mode
|
||||
gmake
|
||||
cd ..
|
||||
gmake install
|
||||
sudo gmake install
|
||||
```
|
||||
|
||||
`afl-gcc` will fail unless you have GCC installed, but that is using outdated
|
||||
instrumentation anyway. You don't want that. Note that `afl-clang-lto`,
|
||||
`afl-gcc-fast` and `qemu_mode` are not working on MacOS.
|
||||
instrumentation anyway. `afl-clang` might fail too depending on your PATH setup.
|
||||
But you don't want neither, you want `afl-clang-fast` anyway :) Note that
|
||||
`afl-clang-lto`, `afl-gcc-fast` and `qemu_mode` are not working on MacOS.
|
||||
|
||||
The crash reporting daemon that comes by default with MacOS X will cause
|
||||
problems with fuzzing. You need to turn it off:
|
||||
@ -133,7 +141,7 @@ and definitely don't look POSIX-compliant. This means two things:
|
||||
|
||||
User emulation mode of QEMU does not appear to be supported on MacOS X, so
|
||||
black-box instrumentation mode (`-Q`) will not work. However, Frida mode (`-O`)
|
||||
should work on x86 and arm64 MacOS boxes.
|
||||
works on both x86 and arm64 MacOS boxes.
|
||||
|
||||
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
|
||||
@ -169,4 +177,4 @@ sysctl kern.sysv.shmall=98304
|
||||
|
||||
See
|
||||
[http://www.spy-hill.com/help/apple/SharedMemory.html](http://www.spy-hill.com/help/apple/SharedMemory.html)
|
||||
for documentation for these settings and how to make them permanent.
|
||||
for documentation for these settings and how to make them permanent.
|
||||
|
65
docs/README.md
Normal file
@ -0,0 +1,65 @@
|
||||
# AFL++ documentation
|
||||
|
||||
This is the overview of the AFL++ docs content.
|
||||
|
||||
For general information on AFL++, see the
|
||||
[README.md of the repository](../README.md).
|
||||
|
||||
Also take a look at our [FAQ.md](FAQ.md) and
|
||||
[best_practices.md](best_practices.md).
|
||||
|
||||
## Fuzzing targets with the source code available
|
||||
|
||||
You can find a quickstart for fuzzing targets with the source code available in
|
||||
the [README.md of the repository](../README.md#quick-start-fuzzing-with-afl).
|
||||
|
||||
For in-depth information on the steps of the fuzzing process, see
|
||||
[fuzzing_in_depth.md](fuzzing_in_depth.md) or click on the following
|
||||
image and select a step.
|
||||
|
||||

|
||||
|
||||
For further information on instrumentation, see the
|
||||
[READMEs in the instrumentation/ folder](../instrumentation/).
|
||||
|
||||
### Instrumenting the target
|
||||
|
||||
For more information, click on the following image and select a step.
|
||||
|
||||

|
||||
|
||||
### Preparing the fuzzing campaign
|
||||
|
||||
For more information, click on the following image and select a step.
|
||||
|
||||

|
||||
|
||||
### Fuzzing the target
|
||||
|
||||
For more information, click on the following image and select a step.
|
||||
|
||||

|
||||
|
||||
### Managing the fuzzing campaign
|
||||
|
||||
For more information, click on the following image and select a step.
|
||||
|
||||

|
||||
|
||||
## Fuzzing other targets
|
||||
|
||||
To learn about fuzzing other targets, see:
|
||||
|
||||
* Binary-only: [fuzzing_binary-only_targets.md](fuzzing_binary-only_targets.md)
|
||||
* GUI programs:
|
||||
[best_practices.md#fuzzing-a-gui-program](best_practices.md#fuzzing-a-gui-program)
|
||||
* Libraries: [frida_mode/README.md](../frida_mode/README.md)
|
||||
* Network services:
|
||||
[best_practices.md#fuzzing-a-network-service](best_practices.md#fuzzing-a-network-service)
|
||||
* Non-linux: [unicorn_mode/README.md](../unicorn_mode/README.md)
|
||||
|
||||
## Additional information
|
||||
|
||||
* Tools that help fuzzing with AFL++:
|
||||
[third_party_tools.md](third_party_tools.md)
|
||||
* Tutorials: [tutorials.md](tutorials.md)
|
@ -40,7 +40,7 @@ superior to blind fuzzing or coverage-only tools.
|
||||
This section provides an overview of the status screen - plus tips for
|
||||
troubleshooting any warnings and red text shown in the UI.
|
||||
|
||||
For the general instruction manual, see [README.md](../README.md).
|
||||
For the general instruction manual, see [README.md](README.md).
|
||||
|
||||
### A note about colors
|
||||
|
||||
|
@ -116,7 +116,7 @@ allows you to define network state with different type of data packets.
|
||||
|
||||
### Improving stability
|
||||
|
||||
For fuzzing a 100% stable target that covers all edges is the best case. A 90%
|
||||
For fuzzing, a 100% stable target that covers all edges is the best case. A 90%
|
||||
stable target that covers all edges is, however, better than a 100% stable
|
||||
target that ignores 10% of the edges.
|
||||
|
||||
@ -189,4 +189,4 @@ coding and/or disassembly and is effectively possible only with `afl-clang-fast`
|
||||
Recompile, fuzz it, be happy :)
|
||||
|
||||
This link explains this process for
|
||||
[Fuzzbench](https://github.com/google/fuzzbench/issues/677).
|
||||
[Fuzzbench](https://github.com/google/fuzzbench/issues/677).
|
||||
|
122
docs/docs.md
@ -1,122 +0,0 @@
|
||||
# Restructure AFL++'s documentation
|
||||
|
||||
## About us
|
||||
|
||||
We are dedicated to everything around fuzzing, our main and most well known
|
||||
contribution is the fuzzer `AFL++` which is part of all major Unix
|
||||
distributions (e.g. Debian, Arch, FreeBSD, etc.) and is deployed on Google's
|
||||
oss-fuzz and clusterfuzz. It is rated the top fuzzer on Google's fuzzbench.
|
||||
|
||||
We are four individuals from Europe supported by a large community.
|
||||
|
||||
All our tools are open source.
|
||||
|
||||
## About the AFL++ fuzzer project
|
||||
|
||||
AFL++ inherited it's documentation from the original Google AFL project.
|
||||
Since then it has been massively improved - feature and performance wise -
|
||||
and although the documenation has likewise been continued it has grown out
|
||||
of proportion.
|
||||
The documentation is done by non-natives to the English language, plus
|
||||
none of us has a writer background.
|
||||
|
||||
We see questions on AFL++ usage on mailing lists (e.g. afl-users), discord
|
||||
channels, web forums and as issues in our repository.
|
||||
|
||||
This only increases as AFL++ has been on the top of Google's fuzzbench
|
||||
statistics (which measures the performance of fuzzers) and is now being
|
||||
integrated in Google's oss-fuzz and clusterfuzz - and is in many Unix
|
||||
packaging repositories, e.g. Debian, FreeBSD, etc.
|
||||
|
||||
AFL++ now has 44 (!) documentation files with 13k total lines of content.
|
||||
This is way too much.
|
||||
|
||||
Hence AFL++ needs a complete overhaul of it's documentation, both on a
|
||||
organisation/structural level as well as the content.
|
||||
|
||||
Overall the following actions have to be performed:
|
||||
* Create a better structure of documentation so it is easier to find the
|
||||
information that is being looked for, combining and/or splitting up the
|
||||
existing documents as needed.
|
||||
* Rewrite some documentation to remove duplication. Several information is
|
||||
present several times in the documentation. These should be removed to
|
||||
where needed so that we have as little bloat as possible.
|
||||
* The documents have been written and modified by a lot of different people,
|
||||
most of them non-native English speaker. Hence an overall review where
|
||||
parts should be rewritten has to be performed and then the rewrite done.
|
||||
* Create a cheat-sheet for a very short best-setup build and run of AFL++
|
||||
* Pictures explain more than 1000 words. We need at least 4 images that
|
||||
explain the workflow with AFL++:
|
||||
- the build workflow
|
||||
- the fuzzing workflow
|
||||
- the fuzzing campaign management workflow
|
||||
- the overall workflow that is an overview of the above
|
||||
- maybe more? where the technical writes seems it necessary for
|
||||
understanding.
|
||||
|
||||
Requirements:
|
||||
* Documentation has to be in Markdown format
|
||||
* Images have to be either in SVG or PNG format.
|
||||
* All documentation should be (moved) in(to) docs/
|
||||
|
||||
The project does not require writing new documentation or tutorials beside the
|
||||
cheat sheet. The technical information for the cheat sheet will be provided by
|
||||
us.
|
||||
|
||||
## Metrics
|
||||
|
||||
AFL++ is a the highest performant fuzzer publicly available - but is also the
|
||||
most feature rich and complex. With the publicity of AFL++' success and
|
||||
deployment in Google projects internally and externally and availability as
|
||||
a package on most Linux distributions we see more and more issues being
|
||||
created and help requests on our Discord channel that would not be
|
||||
necessary if people would have read through all our documentation - which
|
||||
is unrealistic.
|
||||
|
||||
We expect the the new documenation after this project to be cleaner, easier
|
||||
accessible and lighter to digest by our users, resulting in much less
|
||||
help requests. On the other hand the amount of users using AFL++ should
|
||||
increase as well as it will be more accessible which would also increase
|
||||
questions again - but overall resulting in a reduction of help requests.
|
||||
|
||||
In numbers: we currently have per week on average 5 issues on Github,
|
||||
10 questions on discord and 1 on mailing lists that would not be necessary
|
||||
with perfect documentation and perfect people.
|
||||
|
||||
We would consider this project a success if afterwards we only have
|
||||
2 issues on Github and 3 questions on discord anymore that would be answered
|
||||
by reading the documentation. The mailing list is usually used by the most
|
||||
novice users and we don't expect any less questions there.
|
||||
|
||||
## Project Budget
|
||||
|
||||
We have zero experience with technical writers, so this is very hard for us
|
||||
to calculate. We expect it to be a lot of work though because of the amount
|
||||
of documentation we have that needs to be restructured and partially rewritten
|
||||
(44 documents with 13k total lines of content).
|
||||
|
||||
We assume the daily rate of a very good and experienced technical writer in
|
||||
times of a pandemic to be ~500$ (according to web research), and calculate
|
||||
the overall amout of work to be around 20 days for everything incl. the
|
||||
graphics (but again - this is basically just guessing).
|
||||
|
||||
Technical Writer 10000$
|
||||
Volunteer stipends 0$ (waved)
|
||||
T-Shirts for the top 10 contributors and helpers to this documentation project:
|
||||
10 AFL++ logo t-shirts 20$ each 200$
|
||||
10 shipping cost of t-shirts 10$ each 100$
|
||||
|
||||
Total: 10.300$
|
||||
(in the submission form 10.280$ was entered)
|
||||
|
||||
## Additional Information
|
||||
|
||||
We have participated in Google Summer of Code in 2020 and hope to be selected
|
||||
again in 2021.
|
||||
|
||||
We have no experience with a technical writer, but we will support that person
|
||||
with video calls, chats, emails and messaging, provide all necessary information
|
||||
and write technical contents that is required for the success of this project.
|
||||
It is clear to us that a technical writer knows how to write, but cannot know
|
||||
the technical details in a complex tooling like in AFL++. This guidance, input,
|
||||
etc. has to come from us.
|
124
docs/docs2.md
@ -1,124 +0,0 @@
|
||||
# Restructure AFL++'s documentation - Case Study
|
||||
|
||||
## Problem statement
|
||||
|
||||
AFL++ inherited it's documentation from the original Google AFL project.
|
||||
Since then it has been massively improved - feature and performance wise -
|
||||
and although the documenation has likewise been continued it has grown out
|
||||
of proportion.
|
||||
The documentation is done by non-natives to the English language, plus
|
||||
none of us has a writer background.
|
||||
|
||||
We see questions on AFL++ usage on mailing lists (e.g. afl-users), discord
|
||||
channels, web forums and as issues in our repository.
|
||||
Most of them could be answered if people would read through all the
|
||||
documentation.
|
||||
|
||||
This only increases as AFL++ has been on the top of Google's fuzzbench
|
||||
statistics (which measures the performance of fuzzers) and has been
|
||||
integrated in Google's oss-fuzz and clusterfuzz - and is in many Unix
|
||||
packaging repositories, e.g. Debian, FreeBSD, etc.
|
||||
|
||||
AFL++ had 44 (!) documentation files with 13k total lines of content.
|
||||
This was way too much.
|
||||
|
||||
## Proposal abstract
|
||||
|
||||
AFL++'s documentatin needs a complete overhaul, both on a
|
||||
organisation/structural level as well as the content.
|
||||
|
||||
Overall the following actions have to be performed:
|
||||
* Create a better structure of documentation so it is easier to find the
|
||||
information that is being looked for, combining and/or splitting up the
|
||||
existing documents as needed.
|
||||
* Rewrite some documentation to remove duplication. Several information is
|
||||
present several times in the documentation. These should be removed to
|
||||
where needed so that we have as little bloat as possible.
|
||||
* The documents have been written and modified by a lot of different people,
|
||||
most of them non-native English speaker. Hence an overall review where
|
||||
parts should be rewritten has to be performed and then the rewrite done.
|
||||
* Create a cheat-sheet for a very short best-setup build and run of AFL++
|
||||
* Pictures explain more than 1000 words. We need at least 4 images that
|
||||
explain the workflow with AFL++:
|
||||
- the build workflow
|
||||
- the fuzzing workflow
|
||||
- the fuzzing campaign management workflow
|
||||
- the overall workflow that is an overview of the above
|
||||
- maybe more? where the technical writes seems it necessary for
|
||||
understanding.
|
||||
|
||||
Requirements:
|
||||
* Documentation has to be in Markdown format
|
||||
* Images have to be either in SVG or PNG format.
|
||||
* All documentation should be (moved) in(to) docs/
|
||||
|
||||
## Project description
|
||||
|
||||
We created our proposal by discussing in the team what the issues are and
|
||||
what was needed to fix it.
|
||||
This resulted in the [project proposal](https://github.com/AFLplusplus/AFLplusplus/blob/stable/docs/docs.md).
|
||||
|
||||
We did not want to be selected by a writer but select a writer ourselves, so
|
||||
we combed through the list and reviewed every single one of them.
|
||||
We were not looking for coders writing technical documentation, but rather
|
||||
someone who is an experienced writer and has documented experience with
|
||||
structuring documentation.
|
||||
Few fit that profile and we sent out messages to 6 people.
|
||||
We finally decided on Jana because she had a strong background in technical
|
||||
documentation and structuring information.
|
||||
She had no technical experience in fuzzing whatsoever, but we saw that as
|
||||
a plus - of course this made the whole process longer to explain details,
|
||||
but overall ensured that the documentation can be read by (mostly) everyone.
|
||||
|
||||
We communicated via video calls every few weeks and she kept a public kanban
|
||||
board about her todos, additional we used a Signal channel.
|
||||
Her changes were imported via PRs where we discussed details.
|
||||
|
||||
The project was off to a good start, but then Jana got pregnant with serious
|
||||
side effects that made working impossible for her for a longer time, hence
|
||||
the schedule was thrown back.
|
||||
She offered to rescind the payment and we select a new writer, but we saw
|
||||
little opportunity in that, as that would mean a new selection of a writer,
|
||||
someone else with a different vision on how the result should look like so
|
||||
basically a full restart of the project and a large impact on our own time.
|
||||
So we agreed on - after discussion with the Google GSoD team - that she
|
||||
continues the project after the GSoD completion deadline as best as she can.
|
||||
|
||||
End of November she took one week off from work and fully dedicated her time
|
||||
for the documenation which brought the project a big step forward.
|
||||
|
||||
Originally the project should have been ended begin of October, but now - at
|
||||
nearing the end of November, we are at about 85% completion, with the end
|
||||
being expected around mid of December.
|
||||
|
||||
## Metrics
|
||||
|
||||
We merged most of the changes in our development branch and are getting
|
||||
close to a state where the user documentation part is completed and we
|
||||
can create a new release. Only then the new documentatin is actually visible
|
||||
to users. Therefore no metrics could be collected so far.
|
||||
|
||||
We plan on a user-assisted QA review end of November/begin of December.
|
||||
|
||||
The documentation was reviewed by a few test users so far however who gave
|
||||
it a thumbs up.
|
||||
|
||||
## Summary
|
||||
|
||||
The GSoD project itself is great. It helps to get the documentation back in
|
||||
line.
|
||||
It was and is a larger time investment from our side, but we expected that.
|
||||
When the project is done, the documentation will be more accessible by users
|
||||
and also need less maintenance by us.
|
||||
There is still follow-up work to be done by us afterwards (web site for the
|
||||
docs, etc.).
|
||||
|
||||
Not sure what we would do differently next time. I think we prepared best as
|
||||
possible and reacted best as possible to the unexpected.
|
||||
|
||||
Recommendations for other organizations who would like to participate in GSoD:
|
||||
- expect the process to take a larger part of your time. the writer needs
|
||||
your full support.
|
||||
- have someone dedicated from the dev/org side to support, educate and
|
||||
supervice the writer
|
||||
- set clear goals and expectations
|
@ -105,7 +105,8 @@ fairly broad use of environment variables instead:
|
||||
within your program at a certain point (such as at the end of an
|
||||
`__AFL_LOOP()`), you can run the macro `__AFL_LEAK_CHECK();` which will
|
||||
cause an abort if any memory is leaked (you can combine this with the
|
||||
`LSAN_OPTIONS=...` suppression option to suppress some known leaks).
|
||||
`__AFL_LSAN_OFF();` and `__AFL_LSAN_ON();` macros to avoid checking for
|
||||
memory leaks from memory allocated between these two calls.
|
||||
- `AFL_USE_MSAN=1` - activates the memory sanitizer (uninitialized memory)
|
||||
- `AFL_USE_TSAN=1` - activates the thread sanitizer to find thread race
|
||||
conditions
|
||||
@ -283,12 +284,24 @@ mode.
|
||||
TMPDIR=$PWD/assembly_here AFL_KEEP_ASSEMBLY=1 make clean all
|
||||
```
|
||||
|
||||
- GCC_PLUGIN mode only: Setting `AFL_GCC_INSTRUMENT_FILE` with a filename will
|
||||
only instrument those files that match the names listed in this file (one
|
||||
filename per line). See
|
||||
- GCC_PLUGIN mode only: Setting `AFL_GCC_INSTRUMENT_FILE` or
|
||||
`AFL_GCC_ALLOWLIST` with a filename will only instrument those files that
|
||||
match the names listed in this file (one filename per line).
|
||||
|
||||
Setting `AFL_GCC_DENYLIST` or `AFL_GCC_BLOCKLIST` with a file name and/or
|
||||
function will only skip those files that match the names listed in the
|
||||
specified file. See
|
||||
[instrumentation/README.instrument_list.md](../instrumentation/README.instrument_list.md)
|
||||
for more information.
|
||||
|
||||
Setting `AFL_GCC_OUT_OF_LINE=1` will instruct afl-gcc-fast to instrument the
|
||||
code with calls to an injected subroutine instead of the much more efficient
|
||||
inline instrumentation.
|
||||
|
||||
Setting `AFL_GCC_SKIP_NEVERZERO=1` will not implement the skip zero test. If
|
||||
the target performs only a few loops, then this will give a small
|
||||
performance boost.
|
||||
|
||||
## 4) Settings for afl-fuzz
|
||||
|
||||
The main fuzzer binary accepts several options that disable a couple of sanity
|
||||
@ -397,7 +410,7 @@ checks or alter some of the more exotic semantics of the tool:
|
||||
target. This must be equal or larger than the size the target was compiled
|
||||
with.
|
||||
|
||||
- Setting `AFL_MAX_DET_EXRAS` will change the threshold at what number of
|
||||
- Setting `AFL_MAX_DET_EXTRAS` will change the threshold at what number of
|
||||
elements in the `-x` dictionary and LTO autodict (combined) the
|
||||
probabilistic mode will kick off. In probabilistic mode, not all dictionary
|
||||
entries will be used all of the time for fuzzing mutations to not slow down
|
||||
|
103
docs/features.md
@ -1,39 +1,96 @@
|
||||
# Important features of AFL++
|
||||
|
||||
AFL++ supports llvm from 3.8 up to version 12, very fast binary fuzzing with
|
||||
QEMU 5.1 with laf-intel and redqueen, FRIDA mode, unicorn mode, gcc plugin, full
|
||||
QEMU 5.1 with laf-intel and Redqueen, FRIDA mode, unicorn mode, gcc plugin, full
|
||||
*BSD, Mac OS, Solaris and Android support and much, much, much more.
|
||||
|
||||
| Feature/Instrumentation | afl-gcc | llvm | gcc_plugin | FRIDA mode(9) | QEMU mode(10) |unicorn_mode(10) |coresight_mode(11)|
|
||||
| -------------------------|:-------:|:---------:|:----------:|:----------------:|:----------------:|:----------------:|:----------------:|
|
||||
| Threadsafe counters | | x(3) | | | | | |
|
||||
| NeverZero | x86[_64]| x(1) | x | x | x | x | |
|
||||
| Persistent Mode | | x | x | x86[_64]/arm64 | x86[_64]/arm[64] | x | |
|
||||
| LAF-Intel / CompCov | | x | | | x86[_64]/arm[64] | x86[_64]/arm[64] | |
|
||||
| CmpLog | | x | | x86[_64]/arm64 | x86[_64]/arm[64] | | |
|
||||
| Selective Instrumentation| | x | x | x | x | | |
|
||||
| Non-Colliding Coverage | | x(4) | | | (x)(5) | | |
|
||||
| Ngram prev_loc Coverage | | x(6) | | | | | |
|
||||
| Context Coverage | | x(6) | | | | | |
|
||||
| Auto Dictionary | | x(7) | | | | | |
|
||||
| Snapshot LKM Support | | (x)(8) | (x)(8) | | (x)(5) | | |
|
||||
| Shared Memory Test cases | | x | x | x86[_64]/arm64 | x | x | |
|
||||
## Features and instrumentation
|
||||
|
||||
1. default for LLVM >= 9.0, environment variable for older version due an
|
||||
| Feature/Instrumentation | afl-gcc | llvm | gcc_plugin | FRIDA mode(9) | QEMU mode(10) | unicorn_mode(10) | nyx_mode(12) | coresight_mode(11) |
|
||||
| ------------------------------|:--------:|:---------:|:----------:|:--------------:|:----------------:|:----------------:|:------------:|:------------------:|
|
||||
| Threadsafe counters [A] | | x(3) | | | | | x | |
|
||||
| NeverZero [B] | x86[_64] | x(1) | x | x | x | x | | |
|
||||
| Persistent Mode [C] | | x | x | x86[_64]/arm64 | x86[_64]/arm[64] | x | | |
|
||||
| LAF-Intel / CompCov [D] | | x | | | x86[_64]/arm[64] | x86[_64]/arm[64] | x86[_64] | |
|
||||
| CmpLog [E] | | x | | x86[_64]/arm64 | x86[_64]/arm[64] | | | |
|
||||
| Selective Instrumentation [F] | | x | x | x | x | | | |
|
||||
| Non-Colliding Coverage [G] | | x(4) | | | (x)(5) | | | |
|
||||
| Ngram prev_loc Coverage [H] | | x(6) | | | | | | |
|
||||
| Context Coverage [I] | | x(6) | | | | | | |
|
||||
| Auto Dictionary [J] | | x(7) | | | | | | |
|
||||
| Snapshot Support [K] | | (x)(8) | (x)(8) | | (x)(5) | | x | |
|
||||
| Shared Memory Test cases [L] | | x | x | x86[_64]/arm64 | x | x | x | |
|
||||
|
||||
## More information about features
|
||||
|
||||
A. Default is not thread-safe coverage counter updates for better performance,
|
||||
see [instrumentation/README.llvm.md](../instrumentation/README.llvm.md)
|
||||
|
||||
B. On wrapping coverage counters (255 + 1), skip the 0 value and jump to 1
|
||||
instead. This has shown to give better coverage data and is the default; see
|
||||
[instrumentation/README.llvm.md](../instrumentation/README.llvm.md).
|
||||
|
||||
C. Instead of forking, reiterate the fuzz target function in a loop (like
|
||||
`LLVMFuzzerTestOneInput`. Great speed increase but only works with target
|
||||
functions that do not keep state, leak memory, or exit; see
|
||||
[instrumentation/README.persistent_mode.md](../instrumentation/README.persistent_mode.md)
|
||||
|
||||
D. Split any non-8-bit comparison to 8-bit comparison; see
|
||||
[instrumentation/README.laf-intel.md](../instrumentation/README.laf-intel.md)
|
||||
|
||||
E. CmpLog is our enhanced
|
||||
[Redqueen](https://www.ndss-symposium.org/ndss-paper/redqueen-fuzzing-with-input-to-state-correspondence/)
|
||||
implementation, see
|
||||
[instrumentation/README.cmplog.md](../instrumentation/README.cmplog.md)
|
||||
|
||||
F. Similar and compatible to clang 13+ sancov sanitize-coverage-allow/deny but
|
||||
for all llvm versions and all our compile modes, only instrument what should
|
||||
be instrumented, for more speed, directed fuzzing and less instability; see
|
||||
[instrumentation/README.instrument_list.md](../instrumentation/README.instrument_list.md)
|
||||
|
||||
G. Vanilla AFL uses coverage where edges could collide to the same coverage
|
||||
bytes the larger the target is. Our default instrumentation in LTO and
|
||||
afl-clang-fast (PCGUARD) uses non-colliding coverage that also makes it
|
||||
faster. Vanilla AFL style is available with `AFL_LLVM_INSTRUMENT=AFL`; see
|
||||
[instrumentation/README.llvm.md](../instrumentation/README.llvm.md).
|
||||
|
||||
H.+I. Alternative coverage based on previous edges (NGRAM) or depending on the
|
||||
caller (CTX), based on
|
||||
[https://www.usenix.org/system/files/raid2019-wang-jinghan.pdf](https://www.usenix.org/system/files/raid2019-wang-jinghan.pdf);
|
||||
see [instrumentation/README.llvm.md](../instrumentation/README.llvm.md).
|
||||
|
||||
J. An LTO feature that creates a fuzzing dictionary based on comparisons found
|
||||
during compilation/instrumentation. Automatic feature :) See
|
||||
[instrumentation/README.lto.md](../instrumentation/README.lto.md)
|
||||
|
||||
K. The snapshot feature requires a kernel module that was a lot of work to get
|
||||
right and maintained so it is no longer supported. We have
|
||||
[nyx_mode](../nyx_mode/README.md) instead.
|
||||
|
||||
L. Faster fuzzing and less kernel syscall overhead by in-memory fuzz testcase
|
||||
delivery, see
|
||||
[instrumentation/README.persistent_mode.md](../instrumentation/README.persistent_mode.md)
|
||||
|
||||
## More information about instrumentation
|
||||
|
||||
1. Default for LLVM >= 9.0, environment variable for older version due an
|
||||
efficiency bug in previous llvm versions
|
||||
2. GCC creates non-performant code, hence it is disabled in gcc_plugin
|
||||
3. with `AFL_LLVM_THREADSAFE_INST`, disables NeverZero
|
||||
4. with pcguard mode and LTO mode for LLVM 11 and newer
|
||||
5. upcoming, development in the branch
|
||||
6. not compatible with LTO instrumentation and needs at least LLVM v4.1
|
||||
7. automatic in LTO mode with LLVM 11 and newer, an extra pass for all LLVM
|
||||
3. With `AFL_LLVM_THREADSAFE_INST`, disables NeverZero
|
||||
4. With pcguard mode and LTO mode for LLVM 11 and newer
|
||||
5. Upcoming, development in the branch
|
||||
6. Not compatible with LTO instrumentation and needs at least LLVM v4.1
|
||||
7. Automatic in LTO mode with LLVM 11 and newer, an extra pass for all LLVM
|
||||
versions that write to a file to use with afl-fuzz' `-x`
|
||||
8. the snapshot LKM is currently unmaintained due to too many kernel changes
|
||||
8. The snapshot LKM is currently unmaintained due to too many kernel changes
|
||||
coming too fast :-(
|
||||
9. FRIDA mode is supported on Linux and MacOS for Intel and ARM
|
||||
10. QEMU/Unicorn is only supported on Linux
|
||||
11. Coresight mode is only available on AARCH64 Linux with a CPU with Coresight
|
||||
extension
|
||||
12. Nyx mode is only supported on Linux and currently restricted to x86_x64
|
||||
|
||||
## Integrated features and patches
|
||||
|
||||
Among others, the following features and patches have been integrated:
|
||||
|
||||
@ -43,7 +100,7 @@ Among others, the following features and patches have been integrated:
|
||||
* Unicorn mode which allows fuzzing of binaries from completely different
|
||||
platforms (integration provided by domenukk)
|
||||
* The new CmpLog instrumentation for LLVM and QEMU inspired by
|
||||
[Redqueen](https://www.syssec.ruhr-uni-bochum.de/media/emma/veroeffentlichungen/2018/12/17/NDSS19-Redqueen.pdf)
|
||||
[Redqueen](https://github.com/RUB-SysSec/redqueen)
|
||||
* Win32 PE binary-only fuzzing with QEMU and Wine
|
||||
* AFLfast's power schedules by Marcel Böhme:
|
||||
[https://github.com/mboehme/aflfast](https://github.com/mboehme/aflfast)
|
||||
|
@ -12,11 +12,11 @@ fuzzed with AFL++.
|
||||
|
||||
## TL;DR:
|
||||
|
||||
QEMU mode in persistent mode is the fastest - if the stability is high enough.
|
||||
Otherwise, try RetroWrite, Dyninst, and if these fail, too, then try standard
|
||||
QEMU mode with `AFL_ENTRYPOINT` to where you need it.
|
||||
FRIDA mode and QEMU mode in persistent mode are the fastest - if persistent mode
|
||||
is possible and the stability is high enough.
|
||||
|
||||
If your target is a library, then use FRIDA mode.
|
||||
Otherwise, try Zafl, RetroWrite, Dyninst, and if these fail, too, then try
|
||||
standard FRIDA/QEMU mode with `AFL_ENTRYPOINT` to where you need it.
|
||||
|
||||
If your target is non-linux, then use unicorn_mode.
|
||||
|
||||
@ -92,7 +92,7 @@ For more information, see
|
||||
### FRIDA mode
|
||||
|
||||
In FRIDA mode, you can fuzz binary-only targets as easily as with QEMU mode.
|
||||
FRIDA mode is sometimes faster and sometimes slower than QEMU mode. It is also
|
||||
FRIDA mode is most of the times slightly faster than QEMU mode. It is also
|
||||
newer, lacks COMPCOV, and has the advantage that it works on MacOS (both intel
|
||||
and M1).
|
||||
|
||||
@ -100,7 +100,7 @@ To build FRIDA mode:
|
||||
|
||||
```shell
|
||||
cd frida_mode
|
||||
make
|
||||
gmake
|
||||
```
|
||||
|
||||
For additional instructions and caveats, see
|
||||
@ -126,6 +126,16 @@ to check out our sister project libafl which supports Frida, too:
|
||||
[https://github.com/AFLplusplus/LibAFL](https://github.com/AFLplusplus/LibAFL).
|
||||
Working examples already exist :-)
|
||||
|
||||
### Nyx mode
|
||||
|
||||
Nyx is a full system emulation fuzzing environment with snapshot support that is
|
||||
built upon KVM and QEMU. It is only available on Linux and currently restricted
|
||||
to x86_x64.
|
||||
|
||||
For binary-only fuzzing a special 5.10 kernel is required.
|
||||
|
||||
See [nyx_mode/README.md](../nyx_mode/README.md).
|
||||
|
||||
### Unicorn
|
||||
|
||||
Unicorn is a fork of QEMU. The instrumentation is, therefore, very similar. In
|
||||
@ -189,12 +199,15 @@ afl-clang-fast's.
|
||||
|
||||
### RetroWrite
|
||||
|
||||
If you have an x86/x86_64 binary that still has its symbols, is compiled with
|
||||
position independent code (PIC/PIE), and does not use most of the C++ features,
|
||||
then the RetroWrite solution might be for you. It decompiles to ASM files which
|
||||
can then be instrumented with afl-gcc.
|
||||
RetroWrite is a static binary rewriter that can be combined with AFL++. If you
|
||||
have an x86_64 binary that still has its symbols (i.e., not stripped binary), is
|
||||
compiled with position independent code (PIC/PIE), and does not contain C++
|
||||
exceptions, then the RetroWrite solution might be for you. It decompiles to ASM
|
||||
files which can then be instrumented with afl-gcc.
|
||||
|
||||
It is at about 80-85% performance.
|
||||
Binaries that are statically instrumented for fuzzing using RetroWrite are close
|
||||
in performance to compiler-instrumented binaries and outperform the QEMU-based
|
||||
instrumentation.
|
||||
|
||||
[https://github.com/HexHive/retrowrite](https://github.com/HexHive/retrowrite)
|
||||
|
||||
@ -293,4 +306,4 @@ some are very hard to set-up...
|
||||
|
||||
## Closing words
|
||||
|
||||
That's it! News, corrections, updates? Send an email to vh@thc.org.
|
||||
That's it! News, corrections, updates? Send an email to vh@thc.org.
|
||||
|
@ -55,7 +55,7 @@ tasks, fuzzing may put a strain on your hardware and on the OS. In particular:
|
||||
### a) Selecting the best AFL++ compiler for instrumenting the target
|
||||
|
||||
AFL++ comes with a central compiler `afl-cc` that incorporates various different
|
||||
kinds of compiler targets and and instrumentation options. The following
|
||||
kinds of compiler targets and instrumentation options. The following
|
||||
evaluation flow will help you to select the best possible.
|
||||
|
||||
It is highly recommended to have the newest llvm version possible installed,
|
||||
@ -95,38 +95,43 @@ Clickable README links for the chosen compiler:
|
||||
* GCC/CLANG modes (afl-gcc/afl-clang) have no README as they have no own
|
||||
features
|
||||
|
||||
You can select the mode for the afl-cc compiler by:
|
||||
1. use a symlink to afl-cc: afl-gcc, afl-g++, afl-clang, afl-clang++,
|
||||
afl-clang-fast, afl-clang-fast++, afl-clang-lto, afl-clang-lto++,
|
||||
afl-gcc-fast, afl-g++-fast (recommended!)
|
||||
2. using the environment variable AFL_CC_COMPILER with MODE
|
||||
3. passing --afl-MODE command line options to the compiler via
|
||||
CFLAGS/CXXFLAGS/CPPFLAGS
|
||||
You can select the mode for the afl-cc compiler by one of the following methods:
|
||||
|
||||
MODE can be one of: LTO (afl-clang-lto*), LLVM (afl-clang-fast*), GCC_PLUGIN
|
||||
(afl-g*-fast) or GCC (afl-gcc/afl-g++) or CLANG(afl-clang/afl-clang++).
|
||||
* Using a symlink to afl-cc: afl-gcc, afl-g++, afl-clang, afl-clang++,
|
||||
afl-clang-fast, afl-clang-fast++, afl-clang-lto, afl-clang-lto++,
|
||||
afl-gcc-fast, afl-g++-fast (recommended!).
|
||||
* Using the environment variable `AFL_CC_COMPILER` with `MODE`.
|
||||
* Passing --afl-`MODE` command line options to the compiler via
|
||||
`CFLAGS`/`CXXFLAGS`/`CPPFLAGS`.
|
||||
|
||||
`MODE` can be one of the following:
|
||||
|
||||
* LTO (afl-clang-lto*)
|
||||
* LLVM (afl-clang-fast*)
|
||||
* GCC_PLUGIN (afl-g*-fast) or GCC (afl-gcc/afl-g++)
|
||||
* CLANG(afl-clang/afl-clang++)
|
||||
|
||||
Because no AFL++ specific command-line options are accepted (beside the
|
||||
--afl-MODE command), the compile-time tools make fairly broad use of environment
|
||||
variables, which can be listed with `afl-cc -hh` or by reading
|
||||
variables, which can be listed with `afl-cc -hh` or looked up in
|
||||
[env_variables.md](env_variables.md).
|
||||
|
||||
### b) Selecting instrumentation options
|
||||
|
||||
The following options are available when you instrument with LTO mode
|
||||
(afl-clang-fast/afl-clang-lto):
|
||||
If you instrument with LTO mode (afl-clang-fast/afl-clang-lto), the following
|
||||
options are available:
|
||||
|
||||
* Splitting integer, string, float and switch comparisons so AFL++ can easier
|
||||
* Splitting integer, string, float, and switch comparisons so AFL++ can easier
|
||||
solve these. This is an important option if you do not have a very good and
|
||||
large input corpus. This technique is called laf-intel or COMPCOV. To use this
|
||||
set the following environment variable before compiling the target: `export
|
||||
AFL_LLVM_LAF_ALL=1` You can read more about this in
|
||||
large input corpus. This technique is called laf-intel or COMPCOV. To use
|
||||
this, set the following environment variable before compiling the target:
|
||||
`export AFL_LLVM_LAF_ALL=1`. You can read more about this in
|
||||
[instrumentation/README.laf-intel.md](../instrumentation/README.laf-intel.md).
|
||||
* A different technique (and usually a better one than laf-intel) is to
|
||||
instrument the target so that any compare values in the target are sent to
|
||||
AFL++ which then tries to put these values into the fuzzing data at different
|
||||
locations. This technique is very fast and good - if the target does not
|
||||
transform input data before comparison. Therefore this technique is called
|
||||
transform input data before comparison. Therefore, this technique is called
|
||||
`input to state` or `redqueen`. If you want to use this technique, then you
|
||||
have to compile the target twice, once specifically with/for this mode by
|
||||
setting `AFL_LLVM_CMPLOG=1`, and pass this binary to afl-fuzz via the `-c`
|
||||
@ -135,24 +140,49 @@ The following options are available when you instrument with LTO mode
|
||||
about this in
|
||||
[instrumentation/README.cmplog.md](../instrumentation/README.cmplog.md).
|
||||
|
||||
If you use LTO, LLVM or GCC_PLUGIN mode
|
||||
(afl-clang-fast/afl-clang-lto/afl-gcc-fast) you have the option to selectively
|
||||
only instrument parts of the target that you are interested in:
|
||||
If you use LTO, LLVM, or GCC_PLUGIN mode
|
||||
(afl-clang-fast/afl-clang-lto/afl-gcc-fast), you have the option to selectively
|
||||
instrument _parts_ of the target that you are interested in. For afl-clang-fast,
|
||||
you have to use an llvm version newer than 10.0.0 or a mode other than
|
||||
DEFAULT/PCGUARD.
|
||||
|
||||
* To instrument only those parts of the target that you are interested in create
|
||||
a file with all the filenames of the source code that should be instrumented.
|
||||
For afl-clang-lto and afl-gcc-fast - or afl-clang-fast if a mode other than
|
||||
DEFAULT/PCGUARD is used or you have llvm > 10.0.0 - just put one filename or
|
||||
function per line (no directory information necessary for filenames9, and
|
||||
either set `export AFL_LLVM_ALLOWLIST=allowlist.txt` **or** `export
|
||||
AFL_LLVM_DENYLIST=denylist.txt` - depending on if you want per default to
|
||||
instrument unless noted (DENYLIST) or not perform instrumentation unless
|
||||
requested (ALLOWLIST). **NOTE:** During optimization functions might be
|
||||
inlined and then would not match! See
|
||||
[instrumentation/README.instrument_list.md](../instrumentation/README.instrument_list.md)
|
||||
This step can be done either by explicitly including parts to be instrumented or
|
||||
by explicitly excluding parts from instrumentation.
|
||||
|
||||
* To instrument _only specified parts_, create a file (e.g., `allowlist.txt`)
|
||||
with all the filenames and/or functions of the source code that should be
|
||||
instrumented and then:
|
||||
|
||||
1. Just put one filename or function (prefixing with `fun: `) per line (no
|
||||
directory information necessary for filenames) in the file `allowlist.txt`.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
foo.cpp # will match foo/foo.cpp, bar/foo.cpp, barfoo.cpp etc.
|
||||
fun: foo_func # will match the function foo_func
|
||||
```
|
||||
|
||||
2. Set `export AFL_LLVM_ALLOWLIST=allowlist.txt` to enable selective positive
|
||||
instrumentation.
|
||||
|
||||
* Similarly to _exclude_ specified parts from instrumentation, create a file
|
||||
(e.g., `denylist.txt`) with all the filenames of the source code that should
|
||||
be skipped during instrumentation and then:
|
||||
|
||||
1. Same as above. Just put one filename or function per line in the file
|
||||
`denylist.txt`.
|
||||
|
||||
2. Set `export AFL_LLVM_DENYLIST=denylist.txt` to enable selective negative
|
||||
instrumentation.
|
||||
|
||||
**NOTE:** During optimization functions might be
|
||||
inlined and then would not match the list! See
|
||||
[instrumentation/README.instrument_list.md](../instrumentation/README.instrument_list.md).
|
||||
|
||||
There are many more options and modes available, however, these are most of the
|
||||
time less effective. See:
|
||||
|
||||
* [instrumentation/README.llvm.md#6) AFL++ Context Sensitive Branch Coverage](../instrumentation/README.llvm.md#6-afl-context-sensitive-branch-coverage)
|
||||
* [instrumentation/README.llvm.md#7) AFL++ N-Gram Branch Coverage](../instrumentation/README.llvm.md#7-afl-n-gram-branch-coverage)
|
||||
|
||||
@ -166,26 +196,27 @@ It is possible to use sanitizers when instrumenting targets for fuzzing, which
|
||||
allows you to find bugs that would not necessarily result in a crash.
|
||||
|
||||
Note that sanitizers have a huge impact on CPU (= less executions per second)
|
||||
and RAM usage. Also you should only run one afl-fuzz instance per sanitizer
|
||||
type. This is enough because a use-after-free bug will be picked up, e.g., by
|
||||
ASAN (address sanitizer) anyway when syncing to other fuzzing instances, so not
|
||||
all fuzzing instances need to be instrumented with ASAN.
|
||||
and RAM usage. Also, you should only run one afl-fuzz instance per sanitizer
|
||||
type. This is enough because e.g. a use-after-free bug will be picked up by ASAN
|
||||
(address sanitizer) anyway after syncing test cases from other fuzzing
|
||||
instances, so running more than one address sanitized target would be a waste.
|
||||
|
||||
The following sanitizers have built-in support in AFL++:
|
||||
|
||||
* ASAN = Address SANitizer, finds memory corruption vulnerabilities like
|
||||
use-after-free, NULL pointer dereference, buffer overruns, etc. Enabled with
|
||||
`export AFL_USE_ASAN=1` before compiling.
|
||||
* MSAN = Memory SANitizer, finds read access to uninitialized memory, e.g., a
|
||||
* MSAN = Memory SANitizer, finds read accesses to uninitialized memory, e.g., a
|
||||
local variable that is defined and read before it is even set. Enabled with
|
||||
`export AFL_USE_MSAN=1` before compiling.
|
||||
* UBSAN = Undefined Behavior SANitizer, finds instances where - by the C and C++
|
||||
standards - undefined behavior happens, e.g., adding two signed integers
|
||||
together where the result is larger than a signed integer can hold. Enabled
|
||||
with `export AFL_USE_UBSAN=1` before compiling.
|
||||
standards - undefined behavior happens, e.g., adding two signed integers where
|
||||
the result is larger than what a signed integer can hold. Enabled with `export
|
||||
AFL_USE_UBSAN=1` before compiling.
|
||||
* CFISAN = Control Flow Integrity SANitizer, finds instances where the control
|
||||
flow is found to be illegal. Originally this was rather to prevent return
|
||||
oriented programming exploit chains from functioning, in fuzzing this is
|
||||
mostly reduced to detecting type confusion vulnerabilities - which is,
|
||||
oriented programming (ROP) exploit chains from functioning. In fuzzing, this
|
||||
is mostly reduced to detecting type confusion vulnerabilities - which is,
|
||||
however, one of the most important and dangerous C++ memory corruption
|
||||
classes! Enabled with `export AFL_USE_CFISAN=1` before compiling.
|
||||
* TSAN = Thread SANitizer, finds thread race conditions. Enabled with `export
|
||||
@ -194,7 +225,10 @@ The following sanitizers have built-in support in AFL++:
|
||||
security issue, but for developers this can be very valuable. Note that unlike
|
||||
the other sanitizers above this needs `__AFL_LEAK_CHECK();` added to all areas
|
||||
of the target source code where you find a leak check necessary! Enabled with
|
||||
`export AFL_USE_LSAN=1` before compiling.
|
||||
`export AFL_USE_LSAN=1` before compiling. To ignore the memory-leaking check
|
||||
for certain allocations, `__AFL_LSAN_OFF();` can be used before memory is
|
||||
allocated, and `__AFL_LSAN_ON();` afterwards. Memory allocated between these
|
||||
two macros will not be checked for memory leaks.
|
||||
|
||||
It is possible to further modify the behavior of the sanitizers at run-time by
|
||||
setting `ASAN_OPTIONS=...`, `LSAN_OPTIONS` etc. - the available parameters can
|
||||
@ -227,20 +261,20 @@ All AFL++ compilers will set this preprocessor definition automatically.
|
||||
|
||||
### e) Instrumenting the target
|
||||
|
||||
In this step the target source code is compiled so that it can be fuzzed.
|
||||
In this step, the target source code is compiled so that it can be fuzzed.
|
||||
|
||||
Basically you have to tell the target build system that the selected AFL++
|
||||
Basically, you have to tell the target build system that the selected AFL++
|
||||
compiler is used. Also - if possible - you should always configure the build
|
||||
system such that the target is compiled statically and not dynamically. How to
|
||||
do this is described below.
|
||||
system in such way that the target is compiled statically and not dynamically.
|
||||
How to do this is described below.
|
||||
|
||||
The #1 rule when instrumenting a target is: avoid instrumenting shared libraries
|
||||
at all cost. You would need to set LD_LIBRARY_PATH to point to these, you could
|
||||
accidentally type "make install" and install them system wide - so don't. Really
|
||||
don't. **Always compile libraries you want to have instrumented as static and
|
||||
link these to the target program!**
|
||||
at all cost. You would need to set `LD_LIBRARY_PATH` to point to these, you
|
||||
could accidentally type "make install" and install them system wide - so don't.
|
||||
Really don't. **Always compile libraries you want to have instrumented as static
|
||||
and link these to the target program!**
|
||||
|
||||
Then build the target. (Usually with `make`)
|
||||
Then build the target. (Usually with `make`.)
|
||||
|
||||
**NOTES**
|
||||
|
||||
@ -254,45 +288,54 @@ Then build the target. (Usually with `make`)
|
||||
|
||||
3. In case the configure/build system complains about AFL++'s compiler and
|
||||
aborts, then set `export AFL_NOOPT=1` which will then just behave like the
|
||||
real compiler. This option has to be unset again before building the target!
|
||||
real compiler and run the configure step separately. For building the target
|
||||
afterwards this option has to be unset again!
|
||||
|
||||
#### configure
|
||||
|
||||
For `configure` build systems this is usually done by:
|
||||
For `configure` build systems, this is usually done by:
|
||||
|
||||
`CC=afl-clang-fast CXX=afl-clang-fast++ ./configure --disable-shared`
|
||||
```
|
||||
CC=afl-clang-fast CXX=afl-clang-fast++ ./configure --disable-shared
|
||||
```
|
||||
|
||||
Note that if you are using the (better) afl-clang-lto compiler, you also have to
|
||||
set `AR` to llvm-ar[-VERSION] and `RANLIB` to llvm-ranlib[-VERSION] - as is
|
||||
described in [instrumentation/README.lto.md](../instrumentation/README.lto.md).
|
||||
|
||||
#### CMake
|
||||
|
||||
For CMake build systems, this is usually done by:
|
||||
|
||||
```
|
||||
mkdir build; cd build; cmake -DCMAKE_C_COMPILER=afl-cc -DCMAKE_CXX_COMPILER=afl-c++ ..
|
||||
```
|
||||
|
||||
Note that if you are using the (better) afl-clang-lto compiler you also have to
|
||||
set AR to llvm-ar[-VERSION] and RANLIB to llvm-ranlib[-VERSION] - as is
|
||||
described in [instrumentation/README.lto.md](../instrumentation/README.lto.md).
|
||||
|
||||
#### cmake
|
||||
#### Meson Build System
|
||||
|
||||
For `cmake` build systems this is usually done by:
|
||||
For the Meson Build System, you have to set the AFL++ compiler with the very
|
||||
first command!
|
||||
|
||||
`mkdir build; cd build; cmake -DCMAKE_C_COMPILER=afl-cc -DCMAKE_CXX_COMPILER=afl-c++ ..`
|
||||
```
|
||||
CC=afl-cc CXX=afl-c++ meson
|
||||
```
|
||||
|
||||
Note that if you are using the (better) afl-clang-lto compiler you also have to
|
||||
set AR to llvm-ar[-VERSION] and RANLIB to llvm-ranlib[-VERSION] - as is
|
||||
described in [instrumentation/README.lto.md](../instrumentation/README.lto.md).
|
||||
#### Other build systems or if configure/cmake didn't work
|
||||
|
||||
#### meson
|
||||
|
||||
For meson you have to set the AFL++ compiler with the very first command!
|
||||
`CC=afl-cc CXX=afl-c++ meson`
|
||||
|
||||
#### other build systems or if configure/cmake didn't work
|
||||
|
||||
Sometimes cmake and configure do not pick up the AFL++ compiler, or the
|
||||
ranlib/ar that is needed - because this was just not foreseen by the developer
|
||||
of the target. Or they have non-standard options. Figure out if there is a
|
||||
non-standard way to set this, otherwise set up the build normally and edit the
|
||||
generated build environment afterwards manually to point it to the right
|
||||
compiler (and/or ranlib and ar).
|
||||
Sometimes `cmake` and `configure` do not pick up the AFL++ compiler or the
|
||||
`RANLIB`/`AR` that is needed - because this was just not foreseen by the
|
||||
developer of the target. Or they have non-standard options. Figure out if there
|
||||
is a non-standard way to set this, otherwise set up the build normally and edit
|
||||
the generated build environment afterwards manually to point it to the right
|
||||
compiler (and/or `RANLIB` and `AR`).
|
||||
|
||||
### f) Better instrumentation
|
||||
|
||||
If you just fuzz a target program as-is you are wasting a great opportunity for
|
||||
If you just fuzz a target program as-is, you are wasting a great opportunity for
|
||||
much more fuzzing speed.
|
||||
|
||||
This variant requires the usage of afl-clang-lto, afl-clang-fast or
|
||||
@ -304,7 +347,7 @@ that you want to fuzz, plus a few specific AFL++ functions around it. See
|
||||
[instrumentation/README.persistent_mode.md](../instrumentation/README.persistent_mode.md)
|
||||
for details.
|
||||
|
||||
Basically if you do not fuzz a target in persistent mode, then you are just
|
||||
Basically, if you do not fuzz a target in persistent mode, then you are just
|
||||
doing it for a hobby and not professionally :-).
|
||||
|
||||
### g) libfuzzer fuzzer harnesses with LLVMFuzzerTestOneInput()
|
||||
@ -319,7 +362,7 @@ afl-clang-fast++ -fsanitize=fuzzer -o harness harness.cpp targetlib.a
|
||||
```
|
||||
|
||||
You can even use advanced libfuzzer features like `FuzzedDataProvider`,
|
||||
`LLVMFuzzerMutate()` etc. and they will work!
|
||||
`LLVMFuzzerInitialize()` etc. and they will work!
|
||||
|
||||
The generated binary is fuzzed with afl-fuzz like any other fuzz target.
|
||||
|
||||
@ -354,22 +397,28 @@ You can find many good examples of starting files in the
|
||||
### b) Making the input corpus unique
|
||||
|
||||
Use the AFL++ tool `afl-cmin` to remove inputs from the corpus that do not
|
||||
produce a new path/coverage in the target.
|
||||
produce a new path/coverage in the target:
|
||||
|
||||
Put all files from step a) into one directory, e.g., INPUTS.
|
||||
1. Put all files from [step a](#a-collecting-inputs) into one directory, e.g.,
|
||||
`INPUTS`.
|
||||
2. Run afl-cmin:
|
||||
* If the target program is to be called by fuzzing as `bin/target INPUTFILE`,
|
||||
replace the INPUTFILE argument that the target program would read from with
|
||||
`@@`:
|
||||
|
||||
If the target program is to be called by fuzzing as `bin/target -d INPUTFILE`
|
||||
the run afl-cmin like this:
|
||||
```
|
||||
afl-cmin -i INPUTS -o INPUTS_UNIQUE -- bin/target -someopt @@
|
||||
```
|
||||
|
||||
`afl-cmin -i INPUTS -o INPUTS_UNIQUE -- bin/target -d @@`
|
||||
* If the target reads from stdin (standard input) instead, just omit the `@@`
|
||||
as this is the default:
|
||||
|
||||
Note that the INPUTFILE argument that the target program would read from has to
|
||||
be set as `@@`.
|
||||
```
|
||||
afl-cmin -i INPUTS -o INPUTS_UNIQUE -- bin/target -someopt
|
||||
```
|
||||
|
||||
If the target reads from stdin instead, just omit the `@@` as this is the
|
||||
default.
|
||||
|
||||
This step is highly recommended!
|
||||
This step is highly recommended, because afterwards the testcase corpus is not
|
||||
bloated with duplicates anymore, which would slow down the fuzzing progress!
|
||||
|
||||
### c) Minimizing all corpus files
|
||||
|
||||
@ -381,18 +430,20 @@ however, it is a long process as this has to be done for every file:
|
||||
mkdir input
|
||||
cd INPUTS_UNIQUE
|
||||
for i in *; do
|
||||
afl-tmin -i "$i" -o "../input/$i" -- bin/target -d @@
|
||||
afl-tmin -i "$i" -o "../input/$i" -- bin/target -someopt @@
|
||||
done
|
||||
```
|
||||
|
||||
This step can also be parallelized, e.g., with `parallel`. Note that this step
|
||||
is rather optional though.
|
||||
This step can also be parallelized, e.g., with `parallel`.
|
||||
|
||||
Note that this step is rather optional though.
|
||||
|
||||
### Done!
|
||||
|
||||
The INPUTS_UNIQUE/ directory from step b) - or even better the directory input/
|
||||
if you minimized the corpus in step c) - is the resulting input corpus directory
|
||||
to be used in fuzzing! :-)
|
||||
The INPUTS_UNIQUE/ directory from [step b](#b-making-the-input-corpus-unique) -
|
||||
or even better the directory input/ if you minimized the corpus in
|
||||
[step c](#c-minimizing-all-corpus-files) - is the resulting input corpus
|
||||
directory to be used in fuzzing! :-)
|
||||
|
||||
## 3. Fuzzing the target
|
||||
|
||||
@ -400,77 +451,90 @@ In this final step, fuzz the target. There are not that many important options
|
||||
to run the target - unless you want to use many CPU cores/threads for the
|
||||
fuzzing, which will make the fuzzing much more useful.
|
||||
|
||||
If you just use one CPU for fuzzing, then you are fuzzing just for fun and not
|
||||
seriously :-)
|
||||
If you just use one instance for fuzzing, then you are fuzzing just for fun and
|
||||
not seriously :-)
|
||||
|
||||
### a) Running afl-fuzz
|
||||
|
||||
Before you do even a test run of afl-fuzz execute `sudo afl-system-config` (on
|
||||
the host if you execute afl-fuzz in a docker container). This reconfigures the
|
||||
Before you do even a test run of afl-fuzz, execute `sudo afl-system-config` (on
|
||||
the host if you execute afl-fuzz in a Docker container). This reconfigures the
|
||||
system for optimal speed - which afl-fuzz checks and bails otherwise. Set
|
||||
`export AFL_SKIP_CPUFREQ=1` for afl-fuzz to skip this check if you cannot run
|
||||
afl-system-config with root privileges on the host for whatever reason.
|
||||
|
||||
Note there is also `sudo afl-persistent-config` which sets additional permanent
|
||||
boot options for a much better fuzzing performance.
|
||||
Note:
|
||||
|
||||
Note that both scripts improve your fuzzing performance but also decrease your
|
||||
system protection against attacks! So set strong firewall rules and only expose
|
||||
SSH as a network service if you use these (which is highly recommended).
|
||||
* There is also `sudo afl-persistent-config` which sets additional permanent
|
||||
boot options for a much better fuzzing performance.
|
||||
* Both scripts improve your fuzzing performance but also decrease your system
|
||||
protection against attacks! So set strong firewall rules and only expose SSH
|
||||
as a network service if you use these (which is highly recommended).
|
||||
|
||||
If you have an input corpus from step 2, then specify this directory with the
|
||||
`-i` option. Otherwise, create a new directory and create a file with any
|
||||
content as test data in there.
|
||||
If you have an input corpus from [step 2](#2-preparing-the-fuzzing-campaign),
|
||||
then specify this directory with the `-i` option. Otherwise, create a new
|
||||
directory and create a file with any content as test data in there.
|
||||
|
||||
If you do not want anything special, the defaults are already usually best,
|
||||
hence all you need is to specify the seed input directory with the result of
|
||||
step [2a) Collect inputs](#a-collect-inputs):
|
||||
step [2a) Collecting inputs](#a-collecting-inputs):
|
||||
|
||||
`afl-fuzz -i input -o output -- bin/target -d @@`
|
||||
```
|
||||
afl-fuzz -i input -o output -- bin/target -someopt @@
|
||||
```
|
||||
|
||||
Note that the directory specified with `-o` will be created if it does not
|
||||
exist.
|
||||
|
||||
It can be valuable to run afl-fuzz in a screen or tmux shell so you can log off,
|
||||
or afl-fuzz is not aborted if you are running it in a remote ssh session where
|
||||
the connection fails in between. Only do that though once you have verified that
|
||||
your fuzzing setup works! Run it like `screen -dmS afl-main -- afl-fuzz -M
|
||||
main-$HOSTNAME -i ...` and it will start away in a screen session. To enter this
|
||||
session, type `screen -r afl-main`. You see - it makes sense to name the screen
|
||||
session same as the afl-fuzz -M/-S naming :-) For more information on screen or
|
||||
tmux, check their documentation.
|
||||
It can be valuable to run afl-fuzz in a `screen` or `tmux` shell so you can log
|
||||
off, or afl-fuzz is not aborted if you are running it in a remote ssh session
|
||||
where the connection fails in between. Only do that though once you have
|
||||
verified that your fuzzing setup works! Run it like `screen -dmS afl-main --
|
||||
afl-fuzz -M main-$HOSTNAME -i ...` and it will start away in a screen session.
|
||||
To enter this session, type `screen -r afl-main`. You see - it makes sense to
|
||||
name the screen session same as the afl-fuzz `-M`/`-S` naming :-) For more
|
||||
information on screen or tmux, check their documentation.
|
||||
|
||||
If you need to stop and re-start the fuzzing, use the same command line options
|
||||
(or even change them by selecting a different power schedule or another mutation
|
||||
mode!) and switch the input directory with a dash (`-`):
|
||||
|
||||
`afl-fuzz -i - -o output -- bin/target -d @@`
|
||||
```
|
||||
afl-fuzz -i - -o output -- bin/target -someopt @@
|
||||
```
|
||||
|
||||
Adding a dictionary is helpful. See the directory
|
||||
[dictionaries/](../dictionaries/) if something is already included for your data
|
||||
format, and tell afl-fuzz to load that dictionary by adding `-x
|
||||
dictionaries/FORMAT.dict`. With afl-clang-lto, you have an autodictionary
|
||||
generation for which you need to do nothing except to use afl-clang-lto as the
|
||||
compiler. You also have the option to generate a dictionary yourself, see
|
||||
[utils/libtokencap/README.md](../utils/libtokencap/README.md).
|
||||
Adding a dictionary is helpful. You have to following options:
|
||||
|
||||
* See the directory
|
||||
[dictionaries/](../dictionaries/), if something is already included for your
|
||||
data format, and tell afl-fuzz to load that dictionary by adding `-x
|
||||
dictionaries/FORMAT.dict`.
|
||||
* With `afl-clang-lto`, you have an autodictionary generation for which you need
|
||||
to do nothing except to use afl-clang-lto as the compiler.
|
||||
* With `afl-clang-fast`, you can set
|
||||
`AFL_LLVM_DICT2FILE=/full/path/to/new/file.dic` to automatically generate a
|
||||
dictionary during target compilation.
|
||||
* You also have the option to generate a dictionary yourself during an
|
||||
independent run of the target, see
|
||||
[utils/libtokencap/README.md](../utils/libtokencap/README.md).
|
||||
* Finally, you can also write a dictionary file manually, of course.
|
||||
|
||||
afl-fuzz has a variety of options that help to workaround target quirks like
|
||||
specific locations for the input file (`-f`), performing deterministic fuzzing
|
||||
(`-D`) and many more. Check out `afl-fuzz -h`.
|
||||
very specific locations for the input file (`-f`), performing deterministic
|
||||
fuzzing (`-D`) and many more. Check out `afl-fuzz -h`.
|
||||
|
||||
We highly recommend that you set a memory limit for running the target with `-m`
|
||||
which defines the maximum memory in MB. This prevents a potential out-of-memory
|
||||
problem for your system plus helps you detect missing `malloc()` failure
|
||||
handling in the target. Play around with various -m values until you find one
|
||||
handling in the target. Play around with various `-m` values until you find one
|
||||
that safely works for all your input seeds (if you have good ones and then
|
||||
double or quadruple that.
|
||||
double or quadruple that).
|
||||
|
||||
By default, afl-fuzz never stops fuzzing. To terminate AFL++, press Control-C or
|
||||
send a signal SIGINT. You can limit the number of executions or approximate
|
||||
runtime in seconds with options also.
|
||||
|
||||
When you start afl-fuzz you will see a user interface that shows what the status
|
||||
is:
|
||||
When you start afl-fuzz, you will see a user interface that shows what the
|
||||
status is:
|
||||
|
||||

|
||||
|
||||
@ -514,8 +578,8 @@ can set the cache size (in MB) by setting the environment variable
|
||||
|
||||
There should be one main fuzzer (`-M main-$HOSTNAME` option) and as many
|
||||
secondary fuzzers (e.g., `-S variant1`) as you have cores that you use. Every
|
||||
-M/-S entry needs a unique name (that can be whatever), however, the same -o
|
||||
output directory location has to be used for all instances.
|
||||
`-M`/`-S` entry needs a unique name (that can be whatever), however, the same
|
||||
`-o` output directory location has to be used for all instances.
|
||||
|
||||
For every secondary fuzzer there should be a variation, e.g.:
|
||||
* one should fuzz the target that was compiled differently: with sanitizers
|
||||
@ -530,9 +594,10 @@ For every secondary fuzzer there should be a variation, e.g.:
|
||||
|
||||
All other secondaries should be used like this:
|
||||
* a quarter to a third with the MOpt mutator enabled: `-L 0`
|
||||
* run with a different power schedule, recommended are:
|
||||
`fast (default), explore, coe, lin, quad, exploit and rare` which you can set
|
||||
with, e.g., `-p explore`
|
||||
* run with a different power schedule, recommended are: `fast` (default),
|
||||
`explore`, `coe`, `lin`, `quad`, `exploit`, and `rare` which you can set with
|
||||
the `-p` option, e.g., `-p explore`. See the
|
||||
[FAQ](FAQ.md#what-are-power-schedules) for details.
|
||||
* a few instances should use the old queue cycling with `-Z`
|
||||
|
||||
Also, it is recommended to set `export AFL_IMPORT_FIRST=1` to load test cases
|
||||
@ -556,7 +621,7 @@ A long list can be found at
|
||||
[https://github.com/Microsvuln/Awesome-AFL](https://github.com/Microsvuln/Awesome-AFL).
|
||||
|
||||
However, you can also sync AFL++ with honggfuzz, libfuzzer with `-entropic=1`,
|
||||
etc. Just show the main fuzzer (-M) with the `-F` option where the queue/work
|
||||
etc. Just show the main fuzzer (`-M`) with the `-F` option where the queue/work
|
||||
directory of a different fuzzer is, e.g., `-F /src/target/honggfuzz`. Using
|
||||
honggfuzz (with `-n 1` or `-n 2`) and libfuzzer in parallel is highly
|
||||
recommended!
|
||||
@ -575,7 +640,7 @@ Now there are three strategies on how you can sync between the servers:
|
||||
* regularly (~4h): this ensures that all fuzzing campaigns on the servers "see"
|
||||
the same thing. It is like fuzzing on a huge server.
|
||||
* in intervals of 1/10th of the overall expected runtime of the fuzzing you
|
||||
sync. This tries a bit to combine both. have some individuality of the paths
|
||||
sync. This tries a bit to combine both. Have some individuality of the paths
|
||||
each campaign on a server explores, on the other hand if one gets stuck where
|
||||
another found progress this is handed over making it unstuck.
|
||||
|
||||
@ -596,7 +661,8 @@ done
|
||||
```
|
||||
|
||||
You can run this manually, per cron job - as you need it. There is a more
|
||||
complex and configurable script in `utils/distributed_fuzzing`.
|
||||
complex and configurable script in
|
||||
[utils/distributed_fuzzing](../utils/distributed_fuzzing).
|
||||
|
||||
### e) The status of the fuzz campaign
|
||||
|
||||
@ -612,7 +678,7 @@ If you have multiple servers, then use the command after a sync or you have to
|
||||
execute this script per server.
|
||||
|
||||
Another tool to inspect the current state and history of a specific instance is
|
||||
afl-plot, which generates an index.html file and a graphs that show how the
|
||||
afl-plot, which generates an index.html file and graphs that show how the
|
||||
fuzzing instance is performing. The syntax is `afl-plot instance_dir web_dir`,
|
||||
e.g., `afl-plot out/default /srv/www/htdocs/plot`.
|
||||
|
||||
@ -623,7 +689,7 @@ To stop an afl-fuzz run, press Control-C.
|
||||
To restart an afl-fuzz run, just reuse the same command line but replace the `-i
|
||||
directory` with `-i -` or set `AFL_AUTORESUME=1`.
|
||||
|
||||
If you want to add new seeds to a fuzzing campaign you can run a temporary
|
||||
If you want to add new seeds to a fuzzing campaign, you can run a temporary
|
||||
fuzzing instance, e.g., when your main fuzzer is using `-o out` and the new
|
||||
seeds are in `newseeds/` directory:
|
||||
|
||||
@ -686,21 +752,21 @@ or honggfuzz.
|
||||
### i) Improve the speed!
|
||||
|
||||
* Use [persistent mode](../instrumentation/README.persistent_mode.md) (x2-x20
|
||||
speed increase)
|
||||
speed increase).
|
||||
* If you do not use shmem persistent mode, use `AFL_TMPDIR` to point the input
|
||||
file on a tempfs location, see [env_variables.md](env_variables.md)
|
||||
file on a tempfs location, see [env_variables.md](env_variables.md).
|
||||
* Linux: Improve kernel performance: modify `/etc/default/grub`, set
|
||||
`GRUB_CMDLINE_LINUX_DEFAULT="ibpb=off ibrs=off kpti=off l1tf=off mds=off
|
||||
mitigations=off no_stf_barrier noibpb noibrs nopcid nopti
|
||||
nospec_store_bypass_disable nospectre_v1 nospectre_v2 pcid=off pti=off
|
||||
spec_store_bypass_disable=off spectre_v2=off stf_barrier=off"`; then
|
||||
`update-grub` and `reboot` (warning: makes the system more insecure) - you can
|
||||
also just run `sudo afl-persistent-config`
|
||||
also just run `sudo afl-persistent-config`.
|
||||
* Linux: Running on an `ext2` filesystem with `noatime` mount option will be a
|
||||
bit faster than on any other journaling filesystem
|
||||
* Use your cores! [3c) Using multiple cores](#c-using-multiple-cores)
|
||||
bit faster than on any other journaling filesystem.
|
||||
* Use your cores! See [3c) Using multiple cores](#c-using-multiple-cores).
|
||||
* Run `sudo afl-system-config` before starting the first afl-fuzz instance after
|
||||
a reboot
|
||||
a reboot.
|
||||
|
||||
### j) Going beyond crashes
|
||||
|
||||
@ -774,7 +840,7 @@ making it easier to diagnose faults.
|
||||
Having said that, it's important to acknowledge that some fuzzing crashes can be
|
||||
difficult to quickly evaluate for exploitability without a lot of debugging and
|
||||
code analysis work. To assist with this task, afl-fuzz supports a very unique
|
||||
"crash exploration" mode enabled with the -C flag.
|
||||
"crash exploration" mode enabled with the `-C` flag.
|
||||
|
||||
In this mode, the fuzzer takes one or more crashing test cases as the input and
|
||||
uses its feedback-driven fuzzing strategies to very quickly enumerate all code
|
||||
@ -800,30 +866,30 @@ mode, it will happily accept instrumented and non-instrumented binaries. In the
|
||||
non-crashing mode, the minimizer relies on standard AFL++ instrumentation to
|
||||
make the file simpler without altering the execution path.
|
||||
|
||||
The minimizer accepts the -m, -t, -f and @@ syntax in a manner compatible with
|
||||
afl-fuzz.
|
||||
The minimizer accepts the `-m`, `-t`, `-f`, and `@@` syntax in a manner
|
||||
compatible with afl-fuzz.
|
||||
|
||||
Another tool in AFL++ is the afl-analyze tool. It takes an input file, attempts
|
||||
to sequentially flip bytes, and observes the behavior of the tested program. It
|
||||
then color-codes the input based on which sections appear to be critical, and
|
||||
to sequentially flip bytes and observes the behavior of the tested program. It
|
||||
then color-codes the input based on which sections appear to be critical and
|
||||
which are not; while not bulletproof, it can often offer quick insights into
|
||||
complex file formats.
|
||||
|
||||
## 5. CI fuzzing
|
||||
|
||||
Some notes on CI fuzzing - this fuzzing is different to normal fuzzing campaigns
|
||||
as these are much shorter runnings.
|
||||
Some notes on continuous integration (CI) fuzzing - this fuzzing is different to
|
||||
normal fuzzing campaigns as these are much shorter runnings.
|
||||
|
||||
1. Always:
|
||||
* LTO has a much longer compile time which is diametrical to short fuzzing -
|
||||
hence use afl-clang-fast instead.
|
||||
* If you compile with CMPLOG, then you can save fuzzing time and reuse that
|
||||
compiled target for both the `-c` option and the main fuzz target. This
|
||||
will impact the speed by ~15% though.
|
||||
* `AFL_FAST_CAL` - Enable fast calibration, this halves the time the
|
||||
* If you compile with CMPLOG, then you can save compilation time and reuse
|
||||
that compiled target with the `-c` option and as the main fuzz target.
|
||||
This will impact the speed by ~15% though.
|
||||
* `AFL_FAST_CAL` - enables fast calibration, this halves the time the
|
||||
saturated corpus needs to be loaded.
|
||||
* `AFL_CMPLOG_ONLY_NEW` - only perform cmplog on new finds, not the
|
||||
initial corpus as this very likely has been done for them already.
|
||||
* `AFL_CMPLOG_ONLY_NEW` - only perform cmplog on new finds, not the initial
|
||||
corpus as this very likely has been done for them already.
|
||||
* Keep the generated corpus, use afl-cmin and reuse it every time!
|
||||
|
||||
2. Additionally randomize the AFL++ compilation options, e.g.:
|
||||
@ -849,8 +915,8 @@ and
|
||||
|
||||
## The End
|
||||
|
||||
Check out the [FAQ](FAQ.md) if it maybe answers your question (that you might
|
||||
not even have known you had ;-) ).
|
||||
Check out the [FAQ](FAQ.md). Maybe it answers your question (that you might not
|
||||
even have known you had ;-) ).
|
||||
|
||||
This is basically all you need to know to professionally run fuzzing campaigns.
|
||||
If you want to know more, the tons of texts in [docs/](./) will have you
|
||||
@ -858,4 +924,4 @@ covered.
|
||||
|
||||
Note that there are also a lot of tools out there that help fuzzing with AFL++
|
||||
(some might be deprecated or unsupported), see
|
||||
[third_party_tools.md](third_party_tools.md).
|
||||
[third_party_tools.md](third_party_tools.md).
|
||||
|
@ -19,17 +19,17 @@ Mentor: vanhauser-thc
|
||||
## WASM Instrumentation
|
||||
|
||||
Currently, AFL++ can be used for source code fuzzing and traditional binaries.
|
||||
With the rise of WASM as compile target, however, a novel way of instrumentation
|
||||
With the rise of WASM as a compile target, however, a novel way of instrumentation
|
||||
needs to be implemented for binaries compiled to Webassembly. This can either be
|
||||
done by inserting instrumentation directly into the WASM AST, or by patching
|
||||
feedback into a WASM VMs of choice, similar to the current Unicorn
|
||||
feedback into a WASM VM of choice, similar to the current Unicorn
|
||||
instrumentation.
|
||||
|
||||
Mentor: any
|
||||
|
||||
## Support other programming languages
|
||||
|
||||
Other programming languages also use llvm hence they could (easily?) supported
|
||||
Other programming languages also use llvm hence they could be (easily?) supported
|
||||
for fuzzing, e.g., mono, swift, go, kotlin native, fortran, ...
|
||||
|
||||
GCC also supports: Objective-C, Fortran, Ada, Go, and D (according to
|
||||
@ -54,4 +54,4 @@ Mentor: domenukk
|
||||
## Your idea!
|
||||
|
||||
Finally, we are open to proposals! Create an issue at
|
||||
https://github.com/AFLplusplus/AFLplusplus/issues and let's discuss :-)
|
||||
https://github.com/AFLplusplus/AFLplusplus/issues and let's discuss :-)
|
||||
|
@ -5,24 +5,25 @@ changes.
|
||||
|
||||
## From version 3.00 onwards
|
||||
|
||||
With AFL++ 3.13-3.20, we introduce FRIDA mode (`-O`) to have an alternative for
|
||||
binary-only fuzzing. It is slower than QEMU mode but works on MacOS, Android,
|
||||
iOS etc.
|
||||
With AFL++ 4.00, we introduced the following changes from previous behaviors:
|
||||
* the complete documentation was overhauled and restructured thanks to @llzmb!
|
||||
* a new CMPLOG target format requires recompiling CMPLOG targets for use with
|
||||
AFL++ 4.0 onwards
|
||||
* better naming for several fields in the UI
|
||||
|
||||
With AFL++ 3.15, we introduced the following changes from previous behaviors:
|
||||
* Also -M main mode does not do deterministic fuzzing by default anymore
|
||||
* afl-cmin and afl-showmap -Ci now descent into subdirectories like afl-fuzz
|
||||
-i does (but note that afl-cmin.bash does not)
|
||||
* afl-cmin and afl-showmap `-Ci` now descend into subdirectories like afl-fuzz
|
||||
`-i` does (but note that afl-cmin.bash does not)
|
||||
|
||||
With AFL++ 3.14, we introduced the following changes from previous behaviors:
|
||||
* afl-fuzz: deterministic fuzzing it not a default for -M main anymore
|
||||
* afl-fuzz: deterministic fuzzing is not a default for `-M main` anymore
|
||||
* afl-cmin/afl-showmap -i now descends into subdirectories (afl-cmin.bash,
|
||||
however, does not)
|
||||
|
||||
With AFL++ 3.10, we introduced the following changes from previous behaviors:
|
||||
* The '+' feature of the '-t' option now means to auto-calculate the timeout
|
||||
* The '+' feature of the `-t` option now means to auto-calculate the timeout
|
||||
with the value given being the maximum timeout. The original meaning of
|
||||
"skipping timeouts instead of abort" is now inherent to the -t option.
|
||||
"skipping timeouts instead of abort" is now inherent to the `-t` option.
|
||||
|
||||
With AFL++ 3.00, we introduced changes that break some previous AFL and AFL++
|
||||
behaviors and defaults:
|
||||
@ -40,19 +41,20 @@ behaviors and defaults:
|
||||
if any were given. This allows to fuzz targets build regularly like those
|
||||
for debug or release versions.
|
||||
* afl-fuzz:
|
||||
* if neither -M or -S is specified, `-S default` is assumed, so more fuzzers
|
||||
can easily be added later
|
||||
* if neither `-M` or `-S` is specified, `-S default` is assumed, so more
|
||||
fuzzers can easily be added later
|
||||
* `-i` input directory option now descends into subdirectories. It also does
|
||||
not fatal on crashes and too large files, instead it skips them and uses
|
||||
not fail on crashes and too large files, instead it skips them and uses
|
||||
them for splicing mutations
|
||||
* -m none is now default, set memory limits (in MB) with, e.g., -m 250
|
||||
* deterministic fuzzing is now disabled by default (unless using -M) and can
|
||||
be enabled with -D
|
||||
* `-m` none is now the default, set memory limits (in MB) with, e.g., `-m
|
||||
250`
|
||||
* deterministic fuzzing is now disabled by default (unless using `-M`) and
|
||||
can be enabled with `-D`
|
||||
* a caching of test cases can now be performed and can be modified by
|
||||
editing config.h for TESTCASE_CACHE or by specifying the environment
|
||||
editing config.h for `TESTCASE_CACHE` or by specifying the environment
|
||||
variable `AFL_TESTCACHE_SIZE` (in MB). Good values are between 50-500
|
||||
(default: 50).
|
||||
* -M mains do not perform trimming
|
||||
* examples/ got renamed to utils/
|
||||
* libtokencap/ libdislocator/ and qdbi_mode/ were moved to utils/
|
||||
* afl-cmin/afl-cmin.bash now search first in PATH and last in AFL_PATH
|
||||
* `-M` mains do not perform trimming
|
||||
* `examples/` got renamed to `utils/`
|
||||
* `libtokencap/`, `libdislocator/`, and `qdbi_mode/` were moved to `utils/`
|
||||
* afl-cmin/afl-cmin.bash now search first in `PATH` and last in `AFL_PATH`
|
||||
|
4
docs/resources/0_fuzzing_process_overview.drawio.svg
Normal file
After Width: | Height: | Size: 32 KiB |
4
docs/resources/1_instrument_target.drawio.svg
Normal file
After Width: | Height: | Size: 14 KiB |
4
docs/resources/2_prepare_campaign.drawio.svg
Normal file
After Width: | Height: | Size: 10 KiB |
4
docs/resources/3_fuzz_target.drawio.svg
Normal file
After Width: | Height: | Size: 11 KiB |
4
docs/resources/4_manage_campaign.drawio.svg
Normal file
After Width: | Height: | Size: 13 KiB |
@ -424,7 +424,7 @@
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"expr": "fuzzing{type=\"unique_crashes\"}",
|
||||
"expr": "fuzzing{type=\"saved_crashes\"}",
|
||||
"interval": "",
|
||||
"legendFormat": "",
|
||||
"refId": "A"
|
||||
@ -519,7 +519,7 @@
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"expr": "fuzzing{type=\"unique_hangs\"}",
|
||||
"expr": "fuzzing{type=\"saved_hangs\"}",
|
||||
"interval": "",
|
||||
"legendFormat": "",
|
||||
"refId": "A"
|
||||
|
Before Width: | Height: | Size: 114 KiB After Width: | Height: | Size: 141 KiB |
@ -45,6 +45,8 @@ Deployment, management, monitoring, reporting
|
||||
parallelize afl-tmin, startup, and data collection.
|
||||
|
||||
Crash processing
|
||||
* [AFLTriage](https://github.com/quic/AFLTriage) -
|
||||
triage crashing input files using gdb.
|
||||
* [afl-crash-analyzer](https://github.com/floyd-fuh/afl-crash-analyzer) -
|
||||
another crash analyzer for AFL.
|
||||
* [fuzzer-utils](https://github.com/ThePatrickStar/fuzzer-utils) - a set of
|
||||
@ -54,4 +56,4 @@ Crash processing
|
||||
* [AFLize](https://github.com/d33tah/aflize) - a tool that automatically
|
||||
generates builds of debian packages suitable for AFL.
|
||||
* [afl-fid](https://github.com/FoRTE-Research/afl-fid) - a set of tools for
|
||||
working with input data.
|
||||
working with input data.
|
||||
|
@ -9,6 +9,7 @@ Here are some good write-ups to show how to effectively use AFL++:
|
||||
* [https://securitylab.github.com/research/fuzzing-sockets-FTP](https://securitylab.github.com/research/fuzzing-sockets-FTP)
|
||||
* [https://securitylab.github.com/research/fuzzing-sockets-FreeRDP](https://securitylab.github.com/research/fuzzing-sockets-FreeRDP)
|
||||
* [https://securitylab.github.com/research/fuzzing-apache-1](https://securitylab.github.com/research/fuzzing-apache-1)
|
||||
* [https://mmmds.pl/fuzzing-map-parser-part-1-teeworlds/](https://mmmds.pl/fuzzing-map-parser-part-1-teeworlds/)
|
||||
|
||||
If you do not want to follow a tutorial but rather try an exercise type of
|
||||
training, then we can highly recommend the following:
|
||||
@ -18,13 +19,22 @@ training, then we can highly recommend the following:
|
||||
If you are interested in fuzzing structured data (where you define what the
|
||||
structure is), these links have you covered:
|
||||
|
||||
* Superion for AFL++:
|
||||
[https://github.com/adrian-rt/superion-mutator](https://github.com/adrian-rt/superion-mutator)
|
||||
* libprotobuf for AFL++:
|
||||
[https://github.com/P1umer/AFLplusplus-protobuf-mutator](https://github.com/P1umer/AFLplusplus-protobuf-mutator)
|
||||
* libprotobuf raw:
|
||||
[https://github.com/bruce30262/libprotobuf-mutator_fuzzing_learning/tree/master/4_libprotobuf_aflpp_custom_mutator](https://github.com/bruce30262/libprotobuf-mutator_fuzzing_learning/tree/master/4_libprotobuf_aflpp_custom_mutator)
|
||||
* libprotobuf for old AFL++ API:
|
||||
[https://github.com/thebabush/afl-libprotobuf-mutator](https://github.com/thebabush/afl-libprotobuf-mutator)
|
||||
* Superion for AFL++:
|
||||
[https://github.com/adrian-rt/superion-mutator](https://github.com/adrian-rt/superion-mutator)
|
||||
|
||||
If you find other good ones, please send them to us :-)
|
||||
## Video Tutorials
|
||||
* [Install AFL++ Ubuntu](https://www.youtube.com/watch?v=5dCvhkbi3RA)
|
||||
* [[Fuzzing with AFLplusplus] Installing AFLPlusplus and fuzzing a simple C program](https://www.youtube.com/watch?v=9wRVo0kYSlc)
|
||||
* [[Fuzzing with AFLplusplus] How to fuzz a binary with no source code on Linux in persistent mode](https://www.youtube.com/watch?v=LGPJdEO02p4)
|
||||
* [Blackbox Fuzzing #1: Start Binary-Only Fuzzing using AFL++ QEMU mode](https://www.youtube.com/watch?v=sjLFf9q2NRc)
|
||||
* [HOPE 2020 (2020): Hunting Bugs in Your Sleep - How to Fuzz (Almost) Anything With AFL/AFL++](https://www.youtube.com/watch?v=A8ex1hqaQ7E)
|
||||
* [How Fuzzing with AFL works!](https://www.youtube.com/watch?v=COHUWuLTbdk)
|
||||
* [WOOT '20 - AFL++ : Combining Incremental Steps of Fuzzing Research](https://www.youtube.com/watch?v=cZidm6I7KWU)
|
||||
|
||||
If you find other good ones, please send them to us :-)
|
||||
|
@ -118,16 +118,15 @@ GUM_DEVKIT_FILENAME=frida-gumjs-devkit-$(GUM_DEVKIT_VERSION)-$(OS)-$(ARCH).tar.x
|
||||
GUM_DEVKIT_URL="https://github.com/frida/frida/releases/download/$(GUM_DEVKIT_VERSION)/$(GUM_DEVKIT_FILENAME)"
|
||||
|
||||
GUM_DEVKIT_TARBALL:=$(FRIDA_BUILD_DIR)$(GUM_DEVKIT_FILENAME)
|
||||
ifdef FRIDA_SOURCE
|
||||
GUM_DEVIT_LIBRARY=$(FRIDA_DIR)build/frida-linux-$(ARCH)/lib/libfrida-gumjs-1.0.a
|
||||
else
|
||||
GUM_DEVIT_LIBRARY=$(FRIDA_BUILD_DIR)libfrida-gumjs.a
|
||||
endif
|
||||
GUM_DEVIT_HEADER=$(FRIDA_BUILD_DIR)frida-gumjs.h
|
||||
|
||||
FRIDA_DIR:=$(PWD)build/frida-source/
|
||||
FRIDA_MAKEFILE:=$(FRIDA_DIR)Makefile
|
||||
FRIDA_GUM:=$(FRIDA_DIR)build/frida-linux-x86_64/lib/libfrida-gumjs-1.0.a
|
||||
FRIDA_GUM_DEVKIT_DIR:=$(FRIDA_DIR)build/gum-devkit/
|
||||
FRIDA_GUM_DEVKIT_HEADER:=$(FRIDA_GUM_DEVKIT_DIR)frida-gumjs.h
|
||||
FRIDA_GUM_DEVKIT_TARBALL:=$(FRIDA_DIR)build/frida-gumjs-devkit-$(GUM_DEVKIT_VERSION)-$(OS)-$(ARCH).tar
|
||||
FRIDA_GUM_DEVKIT_COMPRESSED_TARBALL:=$(FRIDA_DIR)build/$(GUM_DEVKIT_FILENAME)
|
||||
|
||||
AFL_COMPILER_RT_SRC:=$(ROOT)instrumentation/afl-compiler-rt.o.c
|
||||
AFL_COMPILER_RT_OBJ:=$(OBJ_DIR)afl-compiler-rt.o
|
||||
@ -142,14 +141,20 @@ AFLPP_FRIDA_DRIVER_HOOK_OBJ=$(BUILD_DIR)frida_hook.so
|
||||
AFLPP_QEMU_DRIVER_HOOK_SRC:=$(HOOK_DIR)qemu_hook.c
|
||||
AFLPP_QEMU_DRIVER_HOOK_OBJ:=$(BUILD_DIR)qemu_hook.so
|
||||
|
||||
ifneq "$(shell uname)" "Darwin"
|
||||
ADDR_DIR:=$(PWD)addr/
|
||||
ADDR_SRC:=$(ADDR_DIR)addr.c
|
||||
ADDR_BIN:=$(BUILD_DIR)addr
|
||||
endif
|
||||
|
||||
BIN2C:=$(BUILD_DIR)bin2c
|
||||
BIN2C_SRC:=$(PWD)util/bin2c.c
|
||||
|
||||
.PHONY: all 32 clean format hook $(FRIDA_GUM)
|
||||
.PHONY: all 32 clean format hook addr $(FRIDA_GUM)
|
||||
|
||||
############################## ALL #############################################
|
||||
|
||||
all: $(FRIDA_TRACE) $(AFLPP_FRIDA_DRIVER_HOOK_OBJ) $(AFLPP_QEMU_DRIVER_HOOK_OBJ)
|
||||
all: $(FRIDA_TRACE) $(AFLPP_FRIDA_DRIVER_HOOK_OBJ) $(AFLPP_QEMU_DRIVER_HOOK_OBJ) $(ADDR_BIN)
|
||||
|
||||
32:
|
||||
CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all
|
||||
@ -160,44 +165,101 @@ $(BUILD_DIR):
|
||||
$(OBJ_DIR): | $(BUILD_DIR)
|
||||
mkdir -p $@
|
||||
|
||||
############################# FRIDA ############################################
|
||||
|
||||
$(FRIDA_MAKEFILE): | $(BUILD_DIR)
|
||||
git clone --recursive https://github.com/frida/frida.git $(FRIDA_DIR)
|
||||
|
||||
$(FRIDA_GUM): $(FRIDA_MAKEFILE)
|
||||
cd $(FRIDA_DIR) && make gum-linux-$(ARCH)
|
||||
|
||||
$(FRIDA_GUM_DEVKIT_HEADER): $(FRIDA_GUM)
|
||||
$(FRIDA_DIR)releng/devkit.py frida-gumjs linux-$(ARCH) $(FRIDA_DIR)build/gum-devkit/
|
||||
|
||||
$(FRIDA_GUM_DEVKIT_TARBALL): $(FRIDA_GUM_DEVKIT_HEADER)
|
||||
cd $(FRIDA_GUM_DEVKIT_DIR) && tar cvf $(FRIDA_GUM_DEVKIT_TARBALL) .
|
||||
|
||||
$(FRIDA_GUM_DEVKIT_COMPRESSED_TARBALL): $(FRIDA_GUM_DEVKIT_TARBALL)
|
||||
xz -k -f -0 $(FRIDA_GUM_DEVKIT_TARBALL)
|
||||
|
||||
############################# DEVKIT ###########################################
|
||||
|
||||
$(FRIDA_BUILD_DIR): | $(BUILD_DIR)
|
||||
mkdir -p $@
|
||||
|
||||
ifdef FRIDA_SOURCE
|
||||
$(GUM_DEVKIT_TARBALL): $(FRIDA_GUM_DEVKIT_COMPRESSED_TARBALL)| $(FRIDA_BUILD_DIR)
|
||||
cp -v $< $@
|
||||
$(FRIDA_MAKEFILE): | $(BUILD_DIR)
|
||||
git clone --recursive https://github.com/frida/frida.git $(FRIDA_DIR)
|
||||
|
||||
.PHONY: $(GUM_DEVIT_LIBRARY)
|
||||
|
||||
$(GUM_DEVIT_LIBRARY): $(FRIDA_MAKEFILE)
|
||||
cd $(FRIDA_DIR) && make gum-linux-$(ARCH)
|
||||
|
||||
$(GUM_DEVIT_HEADER): $(FRIDA_MAKEFILE) | $(FRIDA_BUILD_DIR)
|
||||
echo "#include <stdio.h>" > $@
|
||||
echo "#include <unistd.h>" >> $@
|
||||
echo "#include <gum/gumreturnaddress.h>" >> $@
|
||||
echo "#include <gum/gumbacktracer.h>" >> $@
|
||||
echo "#include <gum/gumsymbolutil.h>" >> $@
|
||||
echo "#include <gum/gumstalker.h>" >> $@
|
||||
echo "#include <gum/gumlibc.h>" >> $@
|
||||
echo "#include <gumjs/gumscriptbackend.h>" >> $@
|
||||
|
||||
ifeq "$(ARCH)" "arm64"
|
||||
|
||||
CFLAGS+=-I $(FRIDA_DIR)build/frida_thin-linux-$(ARCH)/include/frida-1.0 \
|
||||
-I $(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/include/glib-2.0/ \
|
||||
-I $(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/glib-2.0/include/ \
|
||||
-I $(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/include/capstone/ \
|
||||
-I $(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/include/json-glib-1.0/ \
|
||||
|
||||
TRACE_LDFLAGS+=$(FRIDA_DIR)build/frida-linux-$(ARCH)/lib/libfrida-gum-1.0.a \
|
||||
$(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libsoup-2.4.a \
|
||||
$(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libsqlite3.a \
|
||||
$(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libtcc.a \
|
||||
$(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libjson-glib-1.0.a \
|
||||
$(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libquickjs.a \
|
||||
$(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libcapstone.a \
|
||||
$(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libunwind-*.a \
|
||||
$(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libunwind.a \
|
||||
$(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libffi.a \
|
||||
$(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libdwarf.a \
|
||||
$(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libelf.a \
|
||||
$(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libgio-2.0.a \
|
||||
$(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libgobject-2.0.a \
|
||||
$(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libglib-2.0.a \
|
||||
$(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/liblzma.a \
|
||||
$(FRIDA_DIR)build/frida_thin-sdk-linux-$(ARCH)/lib/libz.a \
|
||||
|
||||
else
|
||||
|
||||
CFLAGS+=-I $(FRIDA_DIR)build/frida-linux-$(ARCH)/include/frida-1.0 \
|
||||
-I $(FRIDA_DIR)build/sdk-linux-$(ARCH)/include/glib-2.0/ \
|
||||
-I $(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/glib-2.0/include/ \
|
||||
-I $(FRIDA_DIR)build/sdk-linux-$(ARCH)/include/capstone/ \
|
||||
-I $(FRIDA_DIR)build/sdk-linux-$(ARCH)/include/json-glib-1.0/ \
|
||||
|
||||
TRACE_LDFLAGS+=$(FRIDA_DIR)build/frida-linux-$(ARCH)/lib/libfrida-gum-1.0.a \
|
||||
$(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libsoup-2.4.a \
|
||||
$(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libsqlite3.a \
|
||||
$(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libtcc.a \
|
||||
$(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libjson-glib-1.0.a \
|
||||
$(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libquickjs.a \
|
||||
$(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libcapstone.a \
|
||||
$(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libunwind-*.a \
|
||||
$(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libunwind.a \
|
||||
$(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libffi.a \
|
||||
$(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libdwarf.a \
|
||||
$(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libelf.a \
|
||||
$(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libgio-2.0.a \
|
||||
$(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libgobject-2.0.a \
|
||||
$(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libglib-2.0.a \
|
||||
$(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/liblzma.a \
|
||||
$(FRIDA_DIR)build/sdk-linux-$(ARCH)/lib/libz.a \
|
||||
|
||||
endif
|
||||
|
||||
|
||||
|
||||
else
|
||||
$(GUM_DEVKIT_TARBALL): | $(FRIDA_BUILD_DIR)
|
||||
wget -O $@ $(GUM_DEVKIT_URL) || curl -L -o $@ $(GUM_DEVKIT_URL)
|
||||
endif
|
||||
|
||||
$(GUM_DEVIT_LIBRARY): $(GUM_DEVKIT_TARBALL)
|
||||
tar Jxvfm $(GUM_DEVKIT_TARBALL) -C $(FRIDA_BUILD_DIR)
|
||||
|
||||
$(GUM_DEVIT_HEADER): $(GUM_DEVKIT_TARBALL)
|
||||
tar Jxvfm $(GUM_DEVKIT_TARBALL) -C $(FRIDA_BUILD_DIR)
|
||||
endif
|
||||
|
||||
|
||||
|
||||
############################## AFL #############################################
|
||||
$(AFL_COMPILER_RT_OBJ): $(AFL_COMPILER_RT_SRC)
|
||||
$(AFL_COMPILER_RT_OBJ): $(AFL_COMPILER_RT_SRC) $(ROOT)include/config.h
|
||||
$(TARGET_CC) \
|
||||
$(CFLAGS) \
|
||||
$(AFL_CFLAGS) \
|
||||
@ -235,7 +297,7 @@ $(JS_OBJ): $(JS_SRC) GNUmakefile
|
||||
############################# SOURCE ###########################################
|
||||
|
||||
define BUILD_SOURCE
|
||||
$(2): $(1) $(INCLUDES) GNUmakefile | $(OBJ_DIR)
|
||||
$(2): $(1) $(INCLUDES) $(GUM_DEVIT_HEADER) | $(OBJ_DIR)
|
||||
$(TARGET_CC) \
|
||||
$(CFLAGS) \
|
||||
-I $(ROOT)include \
|
||||
@ -256,6 +318,7 @@ $(FRIDA_TRACE): $(GUM_DEVIT_LIBRARY) $(GUM_DEVIT_HEADER) $(OBJS) $(JS_OBJ) $(AFL
|
||||
$(GUM_DEVIT_LIBRARY) \
|
||||
$(AFL_COMPILER_RT_OBJ) \
|
||||
$(AFL_PERFORMANCE_OBJ) \
|
||||
$(TRACE_LDFLAGS) \
|
||||
$(LDFLAGS) \
|
||||
$(LDSCRIPT) \
|
||||
-o $@ \
|
||||
@ -272,13 +335,30 @@ $(AFLPP_QEMU_DRIVER_HOOK_OBJ): $(AFLPP_QEMU_DRIVER_HOOK_SRC) | $(BUILD_DIR)
|
||||
|
||||
hook: $(AFLPP_FRIDA_DRIVER_HOOK_OBJ) $(AFLPP_QEMU_DRIVER_HOOK_OBJ)
|
||||
|
||||
############################# ADDR #############################################
|
||||
$(ADDR_BIN): $(ADDR_SRC) | $(BUILD_DIR)
|
||||
-$(TARGET_CC) \
|
||||
$(CFLAGS) \
|
||||
-Werror \
|
||||
-Wall \
|
||||
-Wextra \
|
||||
-Wpointer-arith \
|
||||
-z noexecstack \
|
||||
-Wl,--gc-sections \
|
||||
-Wl,--exclude-libs,ALL \
|
||||
-ldl \
|
||||
-lrt \
|
||||
$< -o $@
|
||||
|
||||
addr: $(ADDR_BIN)
|
||||
|
||||
############################# CLEAN ############################################
|
||||
clean:
|
||||
rm -rf $(BUILD_DIR)
|
||||
|
||||
############################# FORMAT ###########################################
|
||||
format:
|
||||
cd $(ROOT) && echo $(SOURCES) $(AFLPP_FRIDA_DRIVER_HOOK_SRC) $(BIN2C_SRC) | xargs -L1 ./.custom-format.py -i
|
||||
cd $(ROOT) && echo $(SOURCES) $(AFLPP_FRIDA_DRIVER_HOOK_SRC) $(BIN2C_SRC) $(ADDR_BIN ) | xargs -L1 ./.custom-format.py -i
|
||||
cd $(ROOT) && echo $(INCLUDES) | xargs -L1 ./.custom-format.py -i
|
||||
|
||||
############################# RUN #############################################
|
||||
|
@ -176,9 +176,6 @@ instances run CMPLOG mode and instrumentation of the binary is less frequent
|
||||
* `AFL_FRIDA_INST_NO_OPTIMIZE` - Don't use optimized inline assembly coverage
|
||||
instrumentation (the default where available). Required to use
|
||||
`AFL_FRIDA_INST_TRACE`.
|
||||
* `AFL_FRIDA_INST_NO_BACKPATCH` - Disable backpatching. At the end of executing
|
||||
each block, control will return to FRIDA to identify the next block to
|
||||
execute.
|
||||
* `AFL_FRIDA_INST_NO_PREFETCH` - Disable prefetching. By default, the child will
|
||||
report instrumented blocks back to the parent so that it can also instrument
|
||||
them and they be inherited by the next child on fork, implies
|
||||
@ -227,6 +224,9 @@ instances run CMPLOG mode and instrumentation of the binary is less frequent
|
||||
* `AFL_FRIDA_STALKER_IC_ENTRIES` - Configure the number of inline cache entries
|
||||
stored along-side branch instructions which provide a cache to avoid having to
|
||||
call back into FRIDA to find the next block. Default is 32.
|
||||
* `AFL_FRIDA_STALKER_NO_BACKPATCH` - Disable backpatching. At the end of executing
|
||||
each block, control will return to FRIDA to identify the next block to
|
||||
execute.
|
||||
* `AFL_FRIDA_STATS_FILE` - Write statistics information about the code being
|
||||
instrumented to the given file name. The statistics are written only for the
|
||||
child process when new block is instrumented (when the
|
||||
@ -307,6 +307,7 @@ instances run CMPLOG mode and instrumentation of the binary is less frequent
|
||||
core dump of the instrumented target. Note that in order to capture the core
|
||||
dump you must set a sufficient timeout (using `-t`) to avoid `afl-fuzz`
|
||||
killing the process whilst it is being dumped.
|
||||
* `AFL_FRIDA_VERBOSE` - Enable verbose output from FRIDA mode.
|
||||
|
||||
## FASAN - FRIDA Address Sanitizer mode
|
||||
|
||||
@ -376,4 +377,4 @@ Should you encounter problems with FRIDA mode, refer to
|
||||
The next features to be added are Aarch32 support as well as looking at
|
||||
potential performance improvements. The intention is to achieve feature parity
|
||||
with QEMU mode in due course. Contributions are welcome, but please get in touch
|
||||
to ensure that efforts are deconflicted.
|
||||
to ensure that efforts are deconflicted.
|
||||
|
@ -390,7 +390,7 @@ Consider the [following](test/js/test2.c) test code...
|
||||
--------------------------------------------------------
|
||||
Originally written by Michal Zalewski
|
||||
Copyright 2014 Google Inc. All rights reserved.
|
||||
Copyright 2019-2020 AFLplusplus Project. All rights reserved.
|
||||
Copyright 2019-2022 AFLplusplus Project. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
@ -782,7 +782,7 @@ class Afl {
|
||||
Afl.jsApiWrite(STDOUT_FILENO, buf, log.length);
|
||||
}
|
||||
/**
|
||||
* See `AFL_FRIDA_INST_NO_BACKPATCH`.
|
||||
* See `AFL_FRIDA_STALKER_NO_BACKPATCH`.
|
||||
*/
|
||||
static setBackpatchDisable() {
|
||||
Afl.jsApiSetBackpatchDisable();
|
||||
@ -995,4 +995,4 @@ class Afl {
|
||||
return Afl.module.getExportByName(name);
|
||||
}
|
||||
}
|
||||
```
|
||||
```
|
||||
|
39
frida_mode/addr/addr.c
Normal file
@ -0,0 +1,39 @@
|
||||
#include <errno.h>
|
||||
#include <link.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/personality.h>
|
||||
|
||||
#define UNUSED_PARAMETER(x) (void)(x)
|
||||
|
||||
int phdr_callback(struct dl_phdr_info *info, size_t size, void *data)
|
||||
{
|
||||
UNUSED_PARAMETER (size);
|
||||
|
||||
ElfW(Addr) * base = data;
|
||||
|
||||
if (info->dlpi_name[0] == 0) { *base = info->dlpi_addr; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main (int argc, char** argv, char** envp) {
|
||||
UNUSED_PARAMETER (argc);
|
||||
|
||||
ElfW(Addr) base = 0;
|
||||
|
||||
int persona = personality(ADDR_NO_RANDOMIZE);
|
||||
if (persona == -1) {
|
||||
|
||||
printf("Failed to set ADDR_NO_RANDOMIZE: %d", errno);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((persona & ADDR_NO_RANDOMIZE) == 0) { execvpe(argv[0], argv, envp); }
|
||||
|
||||
dl_iterate_phdr(phdr_callback, &base);
|
||||
|
||||
printf("%p\n", (void *)base);
|
||||
if (base == 0) { return 1; }
|
||||
|
||||
return 0;
|
||||
}
|
@ -37,6 +37,7 @@
|
||||
js_api_set_stderr;
|
||||
js_api_set_stdout;
|
||||
js_api_set_traceable;
|
||||
js_api_set_verbose;
|
||||
|
||||
local:
|
||||
*;
|
||||
|
@ -5,14 +5,13 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
extern char * instrument_debug_filename;
|
||||
extern char * instrument_coverage_filename;
|
||||
extern gboolean instrument_tracing;
|
||||
extern gboolean instrument_optimize;
|
||||
extern gboolean instrument_unique;
|
||||
extern __thread guint64 instrument_previous_pc;
|
||||
extern guint64 instrument_hash_zero;
|
||||
extern char * instrument_coverage_unstable_filename;
|
||||
extern char * instrument_debug_filename;
|
||||
extern char * instrument_coverage_filename;
|
||||
extern gboolean instrument_tracing;
|
||||
extern gboolean instrument_optimize;
|
||||
extern gboolean instrument_unique;
|
||||
extern guint64 instrument_hash_zero;
|
||||
extern char * instrument_coverage_unstable_filename;
|
||||
|
||||
extern gboolean instrument_use_fixed_seed;
|
||||
extern guint64 instrument_fixed_seed;
|
||||
@ -20,6 +19,8 @@ extern guint64 instrument_fixed_seed;
|
||||
extern uint8_t *__afl_area_ptr;
|
||||
extern uint32_t __afl_map_size;
|
||||
|
||||
extern __thread guint64 *instrument_previous_pc_addr;
|
||||
|
||||
void instrument_config(void);
|
||||
|
||||
void instrument_init(void);
|
||||
@ -51,7 +52,7 @@ void instrument_coverage_unstable(guint64 edge, guint64 previous_rip,
|
||||
guint64 previous_end, guint64 current_rip,
|
||||
guint64 current_end);
|
||||
|
||||
void instrument_on_fork();
|
||||
void instrument_on_fork(void);
|
||||
|
||||
guint64 instrument_get_offset_hash(GumAddress current_rip);
|
||||
|
||||
|
@ -8,9 +8,12 @@
|
||||
#define UNUSED_PARAMETER(x) (void)(x)
|
||||
#define IGNORED_RETURN(x) (void)!(x)
|
||||
|
||||
extern gboolean util_verbose;
|
||||
|
||||
guint64 util_read_address(char *key, guint64 default_value);
|
||||
guint64 util_read_num(char *key, guint64 default_value);
|
||||
gboolean util_output_enabled(void);
|
||||
gboolean util_verbose_enabled(void);
|
||||
gsize util_rotate(gsize val, gsize shift, gsize size);
|
||||
gsize util_log2(gsize val);
|
||||
|
||||
@ -19,7 +22,8 @@ gsize util_log2(gsize val);
|
||||
\
|
||||
if (!util_output_enabled()) { break; } \
|
||||
\
|
||||
OKF(x); \
|
||||
SAYF(cLGN "[F] " cRST x); \
|
||||
SAYF(cRST "\n"); \
|
||||
\
|
||||
} while (0)
|
||||
|
||||
@ -37,5 +41,15 @@ gsize util_log2(gsize val);
|
||||
\
|
||||
} while (0)
|
||||
|
||||
#define FVERBOSE(x...) \
|
||||
do { \
|
||||
\
|
||||
if (!util_verbose_enabled()) { break; } \
|
||||
\
|
||||
SAYF(cGRA "[F] " x); \
|
||||
SAYF(cRST "\n"); \
|
||||
\
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -9,21 +9,15 @@ gboolean asan_initialized = FALSE;
|
||||
|
||||
void asan_config(void) {
|
||||
|
||||
if (getenv("AFL_USE_FASAN") != NULL) {
|
||||
|
||||
FOKF("Frida ASAN mode enabled");
|
||||
asan_enabled = TRUE;
|
||||
|
||||
} else {
|
||||
|
||||
FOKF("Frida ASAN mode disabled");
|
||||
|
||||
}
|
||||
if (getenv("AFL_USE_FASAN") != NULL) { asan_enabled = TRUE; }
|
||||
|
||||
}
|
||||
|
||||
void asan_init(void) {
|
||||
|
||||
FOKF(cBLU "Instrumentation" cRST " - " cGRN "asan:" cYEL " [%c]",
|
||||
asan_enabled ? 'X' : ' ');
|
||||
|
||||
if (asan_enabled) {
|
||||
|
||||
asan_arch_init();
|
||||
|
@ -54,7 +54,7 @@ static gint cmplog_sort(gconstpointer a, gconstpointer b) {
|
||||
|
||||
static void cmplog_get_ranges(void) {
|
||||
|
||||
FOKF("CMPLOG - Collecting ranges");
|
||||
FVERBOSE("CMPLOG - Collecting ranges");
|
||||
|
||||
cmplog_ranges = g_array_sized_new(false, false, sizeof(GumMemoryRange), 100);
|
||||
gum_process_enumerate_ranges(GUM_PAGE_READ, cmplog_range, cmplog_ranges);
|
||||
@ -68,18 +68,21 @@ void cmplog_config(void) {
|
||||
|
||||
void cmplog_init(void) {
|
||||
|
||||
FOKF("CMPLOG - Enabled [%c]", __afl_cmp_map == NULL ? ' ' : 'X');
|
||||
FOKF(cBLU "Instrumentation" cRST " - " cGRN "cmplog:" cYEL " [%c]",
|
||||
__afl_cmp_map == NULL ? ' ' : 'X');
|
||||
|
||||
if (__afl_cmp_map == NULL) { return; }
|
||||
|
||||
cmplog_get_ranges();
|
||||
|
||||
FVERBOSE("Cmplog Ranges");
|
||||
|
||||
for (guint i = 0; i < cmplog_ranges->len; i++) {
|
||||
|
||||
GumMemoryRange *range = &g_array_index(cmplog_ranges, GumMemoryRange, i);
|
||||
FOKF("CMPLOG Range - %3u: 0x%016" G_GINT64_MODIFIER
|
||||
"X - 0x%016" G_GINT64_MODIFIER "X",
|
||||
i, range->base_address, range->base_address + range->size);
|
||||
FVERBOSE("\t%3u: 0x%016" G_GINT64_MODIFIER "X - 0x%016" G_GINT64_MODIFIER
|
||||
"X",
|
||||
i, range->base_address, range->base_address + range->size);
|
||||
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ gboolean entry_run = FALSE;
|
||||
|
||||
static void entry_launch(void) {
|
||||
|
||||
FOKF("Entry point reached");
|
||||
FVERBOSE("Entry point reached");
|
||||
__afl_manual_init();
|
||||
|
||||
/* Child here */
|
||||
@ -69,8 +69,8 @@ void entry_config(void) {
|
||||
|
||||
void entry_init(void) {
|
||||
|
||||
FOKF("entry_point: 0x%016" G_GINT64_MODIFIER "X", entry_point);
|
||||
FOKF("dumpable: [%c]", traceable ? 'X' : ' ');
|
||||
FVERBOSE("Entry Point: 0x%016" G_GINT64_MODIFIER "X", entry_point);
|
||||
FVERBOSE("Dumpable: [%c]", traceable ? 'X' : ' ');
|
||||
|
||||
if (dlopen(NULL, RTLD_NOW) == NULL) { FFATAL("Failed to dlopen: %d", errno); }
|
||||
|
||||
@ -94,7 +94,7 @@ static void entry_callout(GumCpuContext *cpu_context, gpointer user_data) {
|
||||
void entry_prologue(GumStalkerIterator *iterator, GumStalkerOutput *output) {
|
||||
|
||||
UNUSED_PARAMETER(output);
|
||||
FOKF("AFL_ENTRYPOINT reached");
|
||||
FVERBOSE("AFL_ENTRYPOINT reached");
|
||||
|
||||
if (persistent_start == 0) {
|
||||
|
||||
|
@ -32,12 +32,13 @@ char * instrument_coverage_unstable_filename = NULL;
|
||||
|
||||
static GumStalkerTransformer *transformer = NULL;
|
||||
|
||||
__thread guint64 instrument_previous_pc = 0;
|
||||
|
||||
static GumAddress previous_rip = 0;
|
||||
static GumAddress previous_end = 0;
|
||||
static u8 * edges_notified = NULL;
|
||||
|
||||
__thread guint64 instrument_previous_pc;
|
||||
__thread guint64 *instrument_previous_pc_addr = NULL;
|
||||
|
||||
typedef struct {
|
||||
|
||||
GumAddress address;
|
||||
@ -105,8 +106,14 @@ __attribute__((hot)) static void on_basic_block(GumCpuContext *context,
|
||||
guint16 current_end = ctx->end;
|
||||
guint64 current_pc = instrument_get_offset_hash(current_rip);
|
||||
guint64 edge;
|
||||
if (instrument_previous_pc_addr == NULL) {
|
||||
|
||||
edge = current_pc ^ instrument_previous_pc;
|
||||
instrument_previous_pc_addr = &instrument_previous_pc;
|
||||
*instrument_previous_pc_addr = instrument_hash_zero;
|
||||
|
||||
}
|
||||
|
||||
edge = current_pc ^ *instrument_previous_pc_addr;
|
||||
|
||||
instrument_increment_map(edge);
|
||||
|
||||
@ -136,7 +143,7 @@ __attribute__((hot)) static void on_basic_block(GumCpuContext *context,
|
||||
previous_end = current_end;
|
||||
|
||||
gsize map_size_pow2 = util_log2(__afl_map_size);
|
||||
instrument_previous_pc = util_rotate(current_pc, 1, map_size_pow2);
|
||||
*instrument_previous_pc_addr = util_rotate(current_pc, 1, map_size_pow2);
|
||||
|
||||
}
|
||||
|
||||
@ -274,14 +281,19 @@ void instrument_init(void) {
|
||||
|
||||
if (!instrument_is_coverage_optimize_supported()) instrument_optimize = false;
|
||||
|
||||
FOKF("Instrumentation - optimize [%c]", instrument_optimize ? 'X' : ' ');
|
||||
FOKF("Instrumentation - tracing [%c]", instrument_tracing ? 'X' : ' ');
|
||||
FOKF("Instrumentation - unique [%c]", instrument_unique ? 'X' : ' ');
|
||||
FOKF("Instrumentation - fixed seed [%c] [0x%016" G_GINT64_MODIFIER "x]",
|
||||
FOKF(cBLU "Instrumentation" cRST " - " cGRN "optimize:" cYEL " [%c]",
|
||||
instrument_optimize ? 'X' : ' ');
|
||||
FOKF(cBLU "Instrumentation" cRST " - " cGRN "tracing:" cYEL " [%c]",
|
||||
instrument_tracing ? 'X' : ' ');
|
||||
FOKF(cBLU "Instrumentation" cRST " - " cGRN "unique:" cYEL " [%c]",
|
||||
instrument_unique ? 'X' : ' ');
|
||||
FOKF(cBLU "Instrumentation" cRST " - " cGRN "fixed seed:" cYEL
|
||||
" [%c] [0x%016" G_GINT64_MODIFIER "x]",
|
||||
instrument_use_fixed_seed ? 'X' : ' ', instrument_fixed_seed);
|
||||
FOKF("Instrumentation - unstable coverage [%c] [%s]",
|
||||
instrument_coverage_unstable_filename == NULL ? ' ' : 'X',
|
||||
instrument_coverage_unstable_filename);
|
||||
FOKF(cBLU "Instrumentation" cRST " - " cGRN "unstable coverage:" cYEL " [%s]",
|
||||
instrument_coverage_unstable_filename == NULL
|
||||
? " "
|
||||
: instrument_coverage_unstable_filename);
|
||||
|
||||
if (instrument_tracing && instrument_optimize) {
|
||||
|
||||
@ -306,12 +318,6 @@ void instrument_init(void) {
|
||||
|
||||
if (instrument_unique) { instrument_tracing = TRUE; }
|
||||
|
||||
if (__afl_map_size != 0x10000) {
|
||||
|
||||
FATAL("Bad map size: 0x%08x", __afl_map_size);
|
||||
|
||||
}
|
||||
|
||||
transformer = gum_stalker_transformer_make_from_callback(
|
||||
instrument_basic_block, NULL, NULL);
|
||||
|
||||
@ -366,15 +372,16 @@ void instrument_init(void) {
|
||||
|
||||
}
|
||||
|
||||
FOKF("Instrumentation - seed [0x%016" G_GINT64_MODIFIER "x]",
|
||||
FOKF(cBLU "Instrumentation" cRST " - " cGRN "seed:" cYEL
|
||||
" [0x%016" G_GINT64_MODIFIER "x]",
|
||||
instrument_hash_seed);
|
||||
instrument_hash_zero = instrument_get_offset_hash(0);
|
||||
|
||||
instrument_coverage_optimize_init();
|
||||
instrument_debug_init();
|
||||
instrument_coverage_init();
|
||||
asan_init();
|
||||
cmplog_init();
|
||||
instrument_coverage_init();
|
||||
instrument_coverage_optimize_init();
|
||||
instrument_debug_init();
|
||||
|
||||
}
|
||||
|
||||
@ -387,7 +394,11 @@ GumStalkerTransformer *instrument_get_transformer(void) {
|
||||
|
||||
void instrument_on_fork() {
|
||||
|
||||
instrument_previous_pc = instrument_hash_zero;
|
||||
if (instrument_previous_pc_addr != NULL) {
|
||||
|
||||
*instrument_previous_pc_addr = instrument_hash_zero;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -1,50 +1,118 @@
|
||||
#include <stddef.h>
|
||||
|
||||
#include "frida-gumjs.h"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "instrument.h"
|
||||
#include "ranges.h"
|
||||
#include "stalker.h"
|
||||
#include "util.h"
|
||||
|
||||
#define G_MININT33 ((gssize)0xffffffff00000000)
|
||||
#define G_MAXINT33 ((gssize)0x00000000ffffffff)
|
||||
|
||||
#define PAGE_MASK (~(GUM_ADDRESS(0xfff)))
|
||||
#define PAGE_ALIGNED(x) ((GUM_ADDRESS(x) & PAGE_MASK) == GUM_ADDRESS(x))
|
||||
|
||||
#if defined(__aarch64__)
|
||||
|
||||
static GumAddress current_log_impl = GUM_ADDRESS(0);
|
||||
__attribute__((aligned(0x1000))) static guint8 area_ptr_dummy[MAP_SIZE];
|
||||
|
||||
static const guint8 afl_log_code[] = {
|
||||
#pragma pack(push, 1)
|
||||
typedef struct {
|
||||
|
||||
// __afl_area_ptr[current_pc ^ previous_pc]++;
|
||||
// previous_pc = current_pc ROR 1;
|
||||
0xE1, 0x0B, 0xBF, 0xA9, // stp x1, x2, [sp, -0x10]!
|
||||
0xE3, 0x13, 0xBF, 0xA9, // stp x3, x4, [sp, -0x10]!
|
||||
// cur_location = (block_address >> 4) ^ (block_address << 8);
|
||||
// shared_mem[cur_location ^ prev_location]++;
|
||||
// prev_location = cur_location >> 1;
|
||||
|
||||
// x0 = current_pc
|
||||
0x21, 0x02, 0x00, 0x58, // ldr x1, #0x44, =&__afl_area_ptr
|
||||
0x21, 0x00, 0x40, 0xf9, // ldr x1, [x1] (=__afl_area_ptr)
|
||||
// stp x0, x1, [sp, #-160]
|
||||
// adrp x0, 0x7fb7738000
|
||||
// ldr x1, [x0]
|
||||
// mov x0, #0x18b8
|
||||
// eor x0, x1, x0
|
||||
// adrp x1, 0x7fb7d73000
|
||||
// add x0, x1, x0
|
||||
// ldrb w1, [x0]
|
||||
// add w1, w1, #0x1
|
||||
// add x1, x1, x1, lsr #8
|
||||
// strb w1, [x0]
|
||||
// adrp x0, 0x7fb7738000
|
||||
// mov x1, #0xc5c
|
||||
// str x1, [x0]
|
||||
// ldp x0, x1, [sp, #-160]
|
||||
// b 0x7fb6f0dee4
|
||||
// ldp x16, x17, [sp], #144
|
||||
|
||||
0x22, 0x02, 0x00, 0x58, // ldr x2, #0x44, =&previous_pc
|
||||
0x42, 0x00, 0x40, 0xf9, // ldr x2, [x2] (=previous_pc)
|
||||
uint32_t stp_x0_x1; /* stp x0, x1, [sp, #-0xa0] */
|
||||
|
||||
// __afl_area_ptr[current_pc ^ previous_pc]++;
|
||||
0x42, 0x00, 0x00, 0xca, // eor x2, x2, x0
|
||||
0x23, 0x68, 0x62, 0xf8, // ldr x3, [x1, x2]
|
||||
0x63, 0x04, 0x00, 0x91, // add x3, x3, #1
|
||||
0x63, 0x00, 0x1f, 0x9a, // adc x3, x3, xzr
|
||||
0x23, 0x68, 0x22, 0xf8, // str x3, [x1, x2]
|
||||
uint32_t adrp_x0_prev_loc1; /* adrp x0, #0xXXXX */
|
||||
uint32_t ldr_x1_ptr_x0; /* ldr x1, [x0] */
|
||||
|
||||
// previous_pc = current_pc ROR 1;
|
||||
0xe4, 0x07, 0x40, 0x8b, // add x4, xzr, x0, LSR #1
|
||||
0xe0, 0xff, 0x00, 0x8b, // add x0, xzr, x0, LSL #63
|
||||
0x80, 0xc0, 0x40, 0x8b, // add x0, x4, x0, LSR #48
|
||||
uint32_t mov_x0_curr_loc; /* movz x0, #0xXXXX */
|
||||
uint32_t eor_x0_x1_x0; /* eor x0, x1, x0 */
|
||||
uint32_t adrp_x1_area_ptr; /* adrp x1, #0xXXXX */
|
||||
uint32_t add_x0_x1_x0; /* add x0, x1, x0 */
|
||||
|
||||
0xe2, 0x00, 0x00, 0x58, // ldr x2, #0x1c, =&previous_pc
|
||||
0x40, 0x00, 0x00, 0xf9, // str x0, [x2]
|
||||
uint32_t ldrb_w1_x0; /* ldrb w1, [x0] */
|
||||
uint32_t add_w1_w1_1; /* add w1, w1, #1 */
|
||||
uint32_t add_w1_w1_w1_lsr_8; /* add x1, x1, x1, lsr #8 */
|
||||
|
||||
0xE3, 0x13, 0xc1, 0xA8, // ldp x3, x4, [sp], #0x10
|
||||
0xE1, 0x0B, 0xc1, 0xA8, // ldp x1, x2, [sp], #0x10
|
||||
0xC0, 0x03, 0x5F, 0xD6, // ret
|
||||
uint32_t strb_w1_ptr_x0; /* strb w1, [x0] */
|
||||
|
||||
// &afl_area_ptr_ptr
|
||||
// &afl_prev_loc_ptr
|
||||
uint32_t adrp_x0_prev_loc2; /* adrp x0, #0xXXXX */
|
||||
uint32_t mov_x1_curr_loc_shr_1; /* movz x1, #0xXXXX */
|
||||
uint32_t str_x1_ptr_x0; /* str x1, [x0] */
|
||||
|
||||
};
|
||||
uint32_t ldp_x0_x1; /* ldp x0, x1, [sp, #-0xa0] */
|
||||
|
||||
uint32_t b_imm8; /* br #8 */
|
||||
uint32_t restoration_prolog; /* ldp x16, x17, [sp], #0x90 */
|
||||
|
||||
} afl_log_code_asm_t;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
typedef union {
|
||||
|
||||
afl_log_code_asm_t code;
|
||||
uint8_t bytes[0];
|
||||
|
||||
} afl_log_code;
|
||||
|
||||
static const afl_log_code_asm_t template =
|
||||
{
|
||||
|
||||
.stp_x0_x1 = 0xa93607e0,
|
||||
|
||||
.adrp_x0_prev_loc1 = 0x90000000,
|
||||
.ldr_x1_ptr_x0 = 0xf9400001,
|
||||
|
||||
.mov_x0_curr_loc = 0xd2800000,
|
||||
.eor_x0_x1_x0 = 0xca000020,
|
||||
|
||||
.adrp_x1_area_ptr = 0x90000001,
|
||||
.add_x0_x1_x0 = 0x8b000020,
|
||||
|
||||
.ldrb_w1_x0 = 0x39400001,
|
||||
|
||||
.add_w1_w1_1 = 0x11000421,
|
||||
.add_w1_w1_w1_lsr_8 = 0x8b412021,
|
||||
|
||||
.strb_w1_ptr_x0 = 0x39000001,
|
||||
|
||||
.adrp_x0_prev_loc2 = 0x90000000,
|
||||
.mov_x1_curr_loc_shr_1 = 0xd2800001,
|
||||
.str_x1_ptr_x0 = 0xf9000001,
|
||||
|
||||
.ldp_x0_x1 = 0xa97607e0,
|
||||
|
||||
.b_imm8 = 0x14000002,
|
||||
.restoration_prolog = 0xa8c947f0,
|
||||
|
||||
}
|
||||
|
||||
;
|
||||
|
||||
gboolean instrument_is_coverage_optimize_supported(void) {
|
||||
|
||||
@ -52,50 +120,111 @@ gboolean instrument_is_coverage_optimize_supported(void) {
|
||||
|
||||
}
|
||||
|
||||
void instrument_coverage_optimize(const cs_insn * instr,
|
||||
GumStalkerOutput *output) {
|
||||
static gboolean instrument_coverage_in_range(gssize offset) {
|
||||
|
||||
guint64 current_pc = instr->address;
|
||||
guint64 area_offset = instrument_get_offset_hash(GUM_ADDRESS(instr->address));
|
||||
GumArm64Writer *cw = output->writer.arm64;
|
||||
return (offset >= G_MININT33 && offset <= G_MAXINT33);
|
||||
|
||||
if (current_log_impl == 0 ||
|
||||
!gum_arm64_writer_can_branch_directly_between(cw, cw->pc,
|
||||
current_log_impl) ||
|
||||
!gum_arm64_writer_can_branch_directly_between(cw, cw->pc + 128,
|
||||
current_log_impl)) {
|
||||
}
|
||||
|
||||
gconstpointer after_log_impl = cw->code + 1;
|
||||
static void instrument_patch_ardp(guint32 *patch, GumAddress insn,
|
||||
GumAddress target) {
|
||||
|
||||
gum_arm64_writer_put_b_label(cw, after_log_impl);
|
||||
if (!PAGE_ALIGNED(target)) { FATAL("Target not page aligned"); }
|
||||
|
||||
current_log_impl = cw->pc;
|
||||
gum_arm64_writer_put_bytes(cw, afl_log_code, sizeof(afl_log_code));
|
||||
gssize distance = target - (GUM_ADDRESS(insn) & PAGE_MASK);
|
||||
if (!instrument_coverage_in_range(distance)) {
|
||||
|
||||
uint8_t **afl_area_ptr_ptr = &__afl_area_ptr;
|
||||
uint64_t *afl_prev_loc_ptr = &instrument_previous_pc;
|
||||
gum_arm64_writer_put_bytes(cw, (const guint8 *)&afl_area_ptr_ptr,
|
||||
sizeof(afl_area_ptr_ptr));
|
||||
gum_arm64_writer_put_bytes(cw, (const guint8 *)&afl_prev_loc_ptr,
|
||||
sizeof(afl_prev_loc_ptr));
|
||||
|
||||
gum_arm64_writer_put_label(cw, after_log_impl);
|
||||
FATAL("Patch out of range 0x%016lX->0x%016lX = 0x%016lX", insn, target,
|
||||
distance);
|
||||
|
||||
}
|
||||
|
||||
gum_arm64_writer_put_stp_reg_reg_reg_offset(
|
||||
cw, ARM64_REG_LR, ARM64_REG_X0, ARM64_REG_SP, -(16 + GUM_RED_ZONE_SIZE),
|
||||
GUM_INDEX_PRE_ADJUST);
|
||||
gum_arm64_writer_put_ldr_reg_u64(cw, ARM64_REG_X0, area_offset);
|
||||
gum_arm64_writer_put_bl_imm(cw, current_log_impl);
|
||||
gum_arm64_writer_put_ldp_reg_reg_reg_offset(
|
||||
cw, ARM64_REG_LR, ARM64_REG_X0, ARM64_REG_SP, 16 + GUM_RED_ZONE_SIZE,
|
||||
GUM_INDEX_POST_ADJUST);
|
||||
guint32 imm_low = ((distance >> 12) & 0x3) << 29;
|
||||
guint32 imm_high = ((distance >> 14) & 0x7FFFF) << 5;
|
||||
*patch |= imm_low;
|
||||
*patch |= imm_high;
|
||||
|
||||
}
|
||||
|
||||
void instrument_coverage_optimize(const cs_insn * instr,
|
||||
GumStalkerOutput *output) {
|
||||
|
||||
afl_log_code code = {0};
|
||||
GumArm64Writer *cw = output->writer.arm64;
|
||||
guint64 area_offset = instrument_get_offset_hash(GUM_ADDRESS(instr->address));
|
||||
gsize map_size_pow2;
|
||||
gsize area_offset_ror;
|
||||
GumAddress code_addr = 0;
|
||||
|
||||
if (instrument_previous_pc_addr == NULL) {
|
||||
|
||||
GumAddressSpec spec = {.near_address = cw->code,
|
||||
.max_distance = 1ULL << 30};
|
||||
|
||||
instrument_previous_pc_addr = gum_memory_allocate_near(
|
||||
&spec, sizeof(guint64), 0x1000, GUM_PAGE_READ | GUM_PAGE_WRITE);
|
||||
*instrument_previous_pc_addr = instrument_hash_zero;
|
||||
FVERBOSE("instrument_previous_pc_addr: %p", instrument_previous_pc_addr);
|
||||
FVERBOSE("code_addr: %p", cw->code);
|
||||
|
||||
}
|
||||
|
||||
// gum_arm64_writer_put_brk_imm(cw, 0x0);
|
||||
|
||||
code_addr = cw->pc;
|
||||
|
||||
code.code = template;
|
||||
|
||||
/*
|
||||
* Given our map is allocated on a 64KB boundary and our map is a multiple of
|
||||
* 64KB in size, then it should also end on a 64 KB boundary. It is followed
|
||||
* by our previous_pc, so this too should be 64KB aligned.
|
||||
*/
|
||||
g_assert(PAGE_ALIGNED(instrument_previous_pc_addr));
|
||||
g_assert(PAGE_ALIGNED(__afl_area_ptr));
|
||||
|
||||
instrument_patch_ardp(
|
||||
&code.code.adrp_x0_prev_loc1,
|
||||
code_addr + offsetof(afl_log_code, code.adrp_x0_prev_loc1),
|
||||
GUM_ADDRESS(instrument_previous_pc_addr));
|
||||
|
||||
code.code.mov_x0_curr_loc |= area_offset << 5;
|
||||
|
||||
instrument_patch_ardp(
|
||||
&code.code.adrp_x1_area_ptr,
|
||||
code_addr + offsetof(afl_log_code, code.adrp_x1_area_ptr),
|
||||
GUM_ADDRESS(__afl_area_ptr));
|
||||
|
||||
map_size_pow2 = util_log2(__afl_map_size);
|
||||
area_offset_ror = util_rotate(area_offset, 1, map_size_pow2);
|
||||
|
||||
instrument_patch_ardp(
|
||||
&code.code.adrp_x0_prev_loc2,
|
||||
code_addr + offsetof(afl_log_code, code.adrp_x0_prev_loc2),
|
||||
GUM_ADDRESS(instrument_previous_pc_addr));
|
||||
|
||||
code.code.mov_x1_curr_loc_shr_1 |= (area_offset_ror << 5);
|
||||
|
||||
gum_arm64_writer_put_bytes(cw, code.bytes, sizeof(afl_log_code));
|
||||
|
||||
}
|
||||
|
||||
void instrument_coverage_optimize_init(void) {
|
||||
|
||||
char *shm_env = getenv(SHM_ENV_VAR);
|
||||
FVERBOSE("SHM_ENV_VAR: %s", shm_env);
|
||||
|
||||
if (shm_env == NULL) {
|
||||
|
||||
FWARNF("SHM_ENV_VAR not set, using dummy for debugging purposes");
|
||||
|
||||
__afl_area_ptr = area_ptr_dummy;
|
||||
memset(area_ptr_dummy, '\0', sizeof(area_ptr_dummy));
|
||||
|
||||
}
|
||||
|
||||
FVERBOSE("__afl_area_ptr: %p", __afl_area_ptr);
|
||||
|
||||
}
|
||||
|
||||
void instrument_flush(GumStalkerOutput *output) {
|
||||
|
@ -659,17 +659,17 @@ void instrument_coverage_config(void) {
|
||||
|
||||
void instrument_coverage_normal_init(void) {
|
||||
|
||||
FOKF("Coverage - enabled [%c]",
|
||||
instrument_coverage_filename == NULL ? ' ' : 'X');
|
||||
FOKF(cBLU "Instrumentation" cRST " - " cGRN "coverage:" cYEL " [%s]",
|
||||
instrument_coverage_filename == NULL ? " "
|
||||
: instrument_coverage_filename);
|
||||
|
||||
if (instrument_coverage_filename == NULL) { return; }
|
||||
|
||||
FOKF("Coverage - file [%s]", instrument_coverage_filename);
|
||||
|
||||
char *path = g_canonicalize_filename(instrument_coverage_filename,
|
||||
g_get_current_dir());
|
||||
|
||||
FOKF("Coverage - path [%s]", path);
|
||||
FOKF(cBLU "Instrumentation" cRST " - " cGRN "coverage path:" cYEL " [%s]",
|
||||
path);
|
||||
|
||||
normal_coverage_fd = open(path, O_RDWR | O_CREAT | O_TRUNC,
|
||||
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
|
||||
@ -718,7 +718,7 @@ void instrument_coverage_unstable_find_output(void) {
|
||||
|
||||
GDir *dir = g_dir_open(fds_name, 0, NULL);
|
||||
|
||||
FOKF("Coverage Unstable - fds: %s", fds_name);
|
||||
FVERBOSE("Coverage Unstable - fds: %s", fds_name);
|
||||
|
||||
for (const gchar *filename = g_dir_read_name(dir); filename != NULL;
|
||||
filename = g_dir_read_name(dir)) {
|
||||
@ -782,18 +782,24 @@ void instrument_coverage_unstable_find_output(void) {
|
||||
|
||||
}
|
||||
|
||||
FOKF("Fuzzer stats: %s", unstable_coverage_fuzzer_stats);
|
||||
FVERBOSE("Fuzzer stats: %s", unstable_coverage_fuzzer_stats);
|
||||
|
||||
}
|
||||
|
||||
void instrument_coverage_unstable_init(void) {
|
||||
|
||||
FOKF(cBLU "Instrumentation" cRST " - " cGRN "unstable coverage:" cYEL " [%s]",
|
||||
instrument_coverage_unstable_filename == NULL
|
||||
? " "
|
||||
: instrument_coverage_unstable_filename);
|
||||
if (instrument_coverage_unstable_filename == NULL) { return; }
|
||||
|
||||
char *path = g_canonicalize_filename(instrument_coverage_unstable_filename,
|
||||
g_get_current_dir());
|
||||
|
||||
FOKF("Coverage - unstable path [%s]", instrument_coverage_unstable_filename);
|
||||
FOKF(cBLU "Instrumentation" cRST " - " cGRN "unstable coverage path:" cYEL
|
||||
" [%s]",
|
||||
path == NULL ? " " : path);
|
||||
|
||||
unstable_coverage_fd = open(path, O_RDWR | O_CREAT | O_TRUNC,
|
||||
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
|
||||
|
@ -35,6 +35,10 @@ static void instrument_debug(char *format, ...) {
|
||||
static void instrument_disasm(guint8 *start, guint8 *end,
|
||||
GumStalkerOutput *output) {
|
||||
|
||||
#if !defined(__arm__)
|
||||
UNUSED_PARAMETER(output);
|
||||
#endif
|
||||
|
||||
csh capstone;
|
||||
cs_err err;
|
||||
cs_mode mode;
|
||||
@ -50,9 +54,7 @@ static void instrument_disasm(guint8 *start, guint8 *end,
|
||||
if (output->encoding == GUM_INSTRUCTION_SPECIAL) { mode |= CS_MODE_THUMB; }
|
||||
#endif
|
||||
|
||||
err = cs_open(GUM_DEFAULT_CS_ARCH,
|
||||
CS_MODE_THUMB | GUM_DEFAULT_CS_MODE | GUM_DEFAULT_CS_ENDIAN,
|
||||
&capstone);
|
||||
err = cs_open(GUM_DEFAULT_CS_ARCH, mode, &capstone);
|
||||
g_assert(err == CS_ERR_OK);
|
||||
|
||||
size = GPOINTER_TO_SIZE(end) - GPOINTER_TO_SIZE(start);
|
||||
@ -96,19 +98,15 @@ void instrument_debug_config(void) {
|
||||
|
||||
void instrument_debug_init(void) {
|
||||
|
||||
FOKF("Instrumentation debugging - enabled [%c]",
|
||||
instrument_debug_filename == NULL ? ' ' : 'X');
|
||||
|
||||
if (instrument_debug_filename == NULL) { return; }
|
||||
|
||||
FOKF("Instrumentation debugging - file [%s]", instrument_debug_filename);
|
||||
FOKF(cBLU "Instrumentation" cRST " - " cGRN "debugging:" cYEL " [%s]",
|
||||
instrument_debug_filename == NULL ? " " : instrument_debug_filename);
|
||||
|
||||
if (instrument_debug_filename == NULL) { return; }
|
||||
|
||||
char *path =
|
||||
g_canonicalize_filename(instrument_debug_filename, g_get_current_dir());
|
||||
|
||||
FOKF("Instrumentation debugging - path [%s]", path);
|
||||
FOKF(cBLU "Instrumentation" cRST " - " cGRN "path:" cYEL " [%s]", path);
|
||||
|
||||
debugging_fd = open(path, O_RDWR | O_CREAT | O_TRUNC,
|
||||
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
|
||||
|
@ -216,6 +216,8 @@ static gboolean instrument_coverage_find_low(const GumRangeDetails *details,
|
||||
static GumAddress last_limit = (64ULL << 10);
|
||||
gpointer * address = (gpointer *)user_data;
|
||||
|
||||
last_limit = GUM_ALIGN_SIZE(last_limit, __afl_map_size);
|
||||
|
||||
if ((details->range->base_address - last_limit) > __afl_map_size) {
|
||||
|
||||
*address = GSIZE_TO_POINTER(last_limit);
|
||||
@ -235,7 +237,7 @@ static gboolean instrument_coverage_find_low(const GumRangeDetails *details,
|
||||
* current block ID.
|
||||
*/
|
||||
last_limit = GUM_ALIGN_SIZE(
|
||||
details->range->base_address + details->range->size, (64ULL << 10));
|
||||
details->range->base_address + details->range->size, __afl_map_size);
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
@ -323,10 +325,10 @@ void instrument_coverage_optimize_init(void) {
|
||||
gum_process_enumerate_ranges(GUM_PAGE_NO_ACCESS, instrument_coverage_find_low,
|
||||
&low_address);
|
||||
|
||||
FOKF("Low address: %p", low_address);
|
||||
FVERBOSE("Low address: %p", low_address);
|
||||
|
||||
if (low_address == 0 ||
|
||||
GPOINTER_TO_SIZE(low_address) > ((2UL << 20) - __afl_map_size)) {
|
||||
GPOINTER_TO_SIZE(low_address) > ((2UL << 30) - __afl_map_size)) {
|
||||
|
||||
FATAL("Invalid low_address: %p", low_address);
|
||||
|
||||
@ -335,7 +337,7 @@ void instrument_coverage_optimize_init(void) {
|
||||
ranges_print_debug_maps();
|
||||
|
||||
char *shm_env = getenv(SHM_ENV_VAR);
|
||||
FOKF("SHM_ENV_VAR: %s", shm_env);
|
||||
FVERBOSE("SHM_ENV_VAR: %s", shm_env);
|
||||
|
||||
if (shm_env == NULL) {
|
||||
|
||||
@ -359,8 +361,7 @@ void instrument_coverage_optimize_init(void) {
|
||||
|
||||
}
|
||||
|
||||
FOKF("__afl_area_ptr: %p", __afl_area_ptr);
|
||||
FOKF("instrument_previous_pc: %p", &instrument_previous_pc);
|
||||
FVERBOSE("__afl_area_ptr: %p", __afl_area_ptr);
|
||||
|
||||
}
|
||||
|
||||
@ -439,6 +440,18 @@ void instrument_coverage_optimize(const cs_insn * instr,
|
||||
gsize map_size_pow2;
|
||||
gsize area_offset_ror;
|
||||
GumAddress code_addr = 0;
|
||||
if (instrument_previous_pc_addr == NULL) {
|
||||
|
||||
GumAddressSpec spec = {.near_address = cw->code,
|
||||
.max_distance = 1ULL << 30};
|
||||
|
||||
instrument_previous_pc_addr = gum_memory_allocate_near(
|
||||
&spec, sizeof(guint64), 0x1000, GUM_PAGE_READ | GUM_PAGE_WRITE);
|
||||
*instrument_previous_pc_addr = instrument_hash_zero;
|
||||
FVERBOSE("instrument_previous_pc_addr: %p", instrument_previous_pc_addr);
|
||||
FVERBOSE("code_addr: %p", cw->code);
|
||||
|
||||
}
|
||||
|
||||
instrument_coverage_suppress_init();
|
||||
|
||||
@ -462,7 +475,7 @@ void instrument_coverage_optimize(const cs_insn * instr,
|
||||
*((guint32 *)&code.bytes[curr_loc_shr_1_offset]) = (guint32)(area_offset_ror);
|
||||
|
||||
gssize prev_loc_value =
|
||||
GPOINTER_TO_SIZE(&instrument_previous_pc) -
|
||||
GPOINTER_TO_SIZE(instrument_previous_pc_addr) -
|
||||
(code_addr + offsetof(afl_log_code, code.mov_prev_loc_curr_loc_shr1) +
|
||||
sizeof(code.code.mov_prev_loc_curr_loc_shr1));
|
||||
gssize prev_loc_value_offset =
|
||||
@ -478,7 +491,7 @@ void instrument_coverage_optimize(const cs_insn * instr,
|
||||
*((gint *)&code.bytes[prev_loc_value_offset]) = (gint)prev_loc_value;
|
||||
|
||||
gssize prev_loc_value2 =
|
||||
GPOINTER_TO_SIZE(&instrument_previous_pc) -
|
||||
GPOINTER_TO_SIZE(instrument_previous_pc_addr) -
|
||||
(code_addr + offsetof(afl_log_code, code.mov_eax_prev_loc) +
|
||||
sizeof(code.code.mov_eax_prev_loc));
|
||||
gssize prev_loc_value_offset2 =
|
||||
|
@ -153,6 +153,19 @@ void instrument_coverage_optimize(const cs_insn * instr,
|
||||
gsize map_size_pow2;
|
||||
gsize area_offset_ror;
|
||||
|
||||
if (instrument_previous_pc_addr == NULL) {
|
||||
|
||||
GumAddressSpec spec = {.near_address = cw->code,
|
||||
.max_distance = 1ULL << 30};
|
||||
|
||||
instrument_previous_pc_addr = gum_memory_allocate_near(
|
||||
&spec, sizeof(guint64), 0x1000, GUM_PAGE_READ | GUM_PAGE_WRITE);
|
||||
*instrument_previous_pc_addr = instrument_hash_zero;
|
||||
FVERBOSE("instrument_previous_pc_addr: %p", instrument_previous_pc_addr);
|
||||
FVERBOSE("code_addr: %p", cw->code);
|
||||
|
||||
}
|
||||
|
||||
code.code = template;
|
||||
|
||||
instrument_coverage_suppress_init();
|
||||
@ -170,7 +183,7 @@ void instrument_coverage_optimize(const cs_insn * instr,
|
||||
sizeof(code.code.mov_eax_prev_loc) - sizeof(gint);
|
||||
|
||||
*((gint *)&code.bytes[prev_loc_value_offset2]) =
|
||||
(gint)GPOINTER_TO_SIZE(&instrument_previous_pc);
|
||||
(gint)GPOINTER_TO_SIZE(instrument_previous_pc_addr);
|
||||
|
||||
gssize curr_loc_shr_1_offset =
|
||||
offsetof(afl_log_code, code.mov_prev_loc_curr_loc_shr1) +
|
||||
@ -187,7 +200,7 @@ void instrument_coverage_optimize(const cs_insn * instr,
|
||||
sizeof(guint32);
|
||||
|
||||
*((gint *)&code.bytes[prev_loc_value_offset]) =
|
||||
(gint)GPOINTER_TO_SIZE(&instrument_previous_pc);
|
||||
(gint)GPOINTER_TO_SIZE(instrument_previous_pc_addr);
|
||||
|
||||
gssize xor_curr_loc_offset = offsetof(afl_log_code, code.xor_eax_curr_loc) +
|
||||
sizeof(code.code.xor_eax_curr_loc) -
|
||||
|
@ -63,7 +63,7 @@ class Afl {
|
||||
Afl.jsApiWrite(STDOUT_FILENO, buf, log.length);
|
||||
}
|
||||
/**
|
||||
* See `AFL_FRIDA_INST_NO_BACKPATCH`.
|
||||
* See `AFL_FRIDA_STALKER_NO_BACKPATCH`.
|
||||
*/
|
||||
static setBackpatchDisable() {
|
||||
Afl.jsApiSetBackpatchDisable();
|
||||
@ -268,6 +268,12 @@ class Afl {
|
||||
static setTraceable() {
|
||||
Afl.jsApiSetTraceable();
|
||||
}
|
||||
/**
|
||||
* See `AFL_FRIDA_VERBOSE`
|
||||
*/
|
||||
static setVerbose() {
|
||||
Afl.jsApiSetVerbose();
|
||||
}
|
||||
static jsApiGetFunction(name, retType, argTypes) {
|
||||
const addr = Afl.module.getExportByName(name);
|
||||
return new NativeFunction(addr, retType, argTypes);
|
||||
@ -315,6 +321,7 @@ Afl.jsApiSetStatsInterval = Afl.jsApiGetFunction("js_api_set_stats_interval", "v
|
||||
Afl.jsApiSetStdErr = Afl.jsApiGetFunction("js_api_set_stderr", "void", ["pointer"]);
|
||||
Afl.jsApiSetStdOut = Afl.jsApiGetFunction("js_api_set_stdout", "void", ["pointer"]);
|
||||
Afl.jsApiSetTraceable = Afl.jsApiGetFunction("js_api_set_traceable", "void", []);
|
||||
Afl.jsApiSetVerbose = Afl.jsApiGetFunction("js_api_set_verbose", "void", []);
|
||||
Afl.jsApiWrite = new NativeFunction(
|
||||
/* tslint:disable-next-line:no-null-keyword */
|
||||
Module.getExportByName(null, "write"), "int", ["int", "pointer", "int"]);
|
||||
|
@ -55,7 +55,10 @@ static gchar *js_get_script() {
|
||||
|
||||
} else {
|
||||
|
||||
FOKF("Loaded AFL script: %s, %" G_GSIZE_MODIFIER "d bytes", filename,
|
||||
FOKF(cBLU "Javascript" cRST " - " cGRN "script:" cYEL " [%s]",
|
||||
filename == NULL ? " " : filename);
|
||||
FOKF(cBLU "Javascript" cRST " - " cGRN "size: " cYEL "%" G_GSIZE_MODIFIER
|
||||
"d bytes",
|
||||
length);
|
||||
|
||||
gchar *source = g_malloc0(api_js_len + length + 1);
|
||||
@ -74,7 +77,7 @@ static void js_print_script(gchar *source) {
|
||||
|
||||
for (size_t i = 0; split[i] != NULL; i++) {
|
||||
|
||||
FOKF("%3" G_GSIZE_MODIFIER "d. %s", i + 1, split[i]);
|
||||
FVERBOSE("%3" G_GSIZE_MODIFIER "d. %s", i + 1, split[i]);
|
||||
|
||||
}
|
||||
|
||||
|
@ -262,3 +262,9 @@ __attribute__((visibility("default"))) void js_api_set_js_main_hook(
|
||||
|
||||
}
|
||||
|
||||
__attribute__((visibility("default"))) void js_api_set_verbose(void) {
|
||||
|
||||
util_verbose = TRUE;
|
||||
|
||||
}
|
||||
|
||||
|
@ -93,17 +93,18 @@ static void lib_read_text_section(lib_details_t *lib_details, Elf_Ehdr *hdr) {
|
||||
|
||||
}
|
||||
|
||||
FOKF("Image preferred load address 0x%016" G_GSIZE_MODIFIER "x",
|
||||
preferred_base);
|
||||
FVERBOSE("\tpreferred load address: 0x%016" G_GSIZE_MODIFIER "x",
|
||||
preferred_base);
|
||||
|
||||
shdr = (Elf_Shdr *)((char *)hdr + hdr->e_shoff);
|
||||
shstrtab = &shdr[hdr->e_shstrndx];
|
||||
shstr = (char *)hdr + shstrtab->sh_offset;
|
||||
|
||||
FOKF("shdr: %p", shdr);
|
||||
FOKF("shstrtab: %p", shstrtab);
|
||||
FOKF("shstr: %p", shstr);
|
||||
FVERBOSE("\tshdr: %p", shdr);
|
||||
FVERBOSE("\tshstrtab: %p", shstrtab);
|
||||
FVERBOSE("\tshstr: %p", shstr);
|
||||
|
||||
FVERBOSE("Sections:");
|
||||
for (size_t i = 0; i < hdr->e_shnum; i++) {
|
||||
|
||||
curr = &shdr[i];
|
||||
@ -111,21 +112,23 @@ static void lib_read_text_section(lib_details_t *lib_details, Elf_Ehdr *hdr) {
|
||||
if (curr->sh_name == 0) continue;
|
||||
|
||||
section_name = &shstr[curr->sh_name];
|
||||
FOKF("Section: %2" G_GSIZE_MODIFIER "u - base: 0x%016" G_GSIZE_MODIFIER
|
||||
"X size: 0x%016" G_GSIZE_MODIFIER "X %s",
|
||||
i, curr->sh_addr, curr->sh_size, section_name);
|
||||
FVERBOSE("\t%2" G_GSIZE_MODIFIER "u - base: 0x%016" G_GSIZE_MODIFIER
|
||||
"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 &&
|
||||
text_base == 0) {
|
||||
|
||||
text_base = lib_details->base_address + curr->sh_addr - preferred_base;
|
||||
text_limit = text_base + curr->sh_size;
|
||||
FOKF("> text_addr: 0x%016" G_GINT64_MODIFIER "X", text_base);
|
||||
FOKF("> text_limit: 0x%016" G_GINT64_MODIFIER "X", text_limit);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
FVERBOSE(".text\n");
|
||||
FVERBOSE("\taddr: 0x%016" G_GINT64_MODIFIER "X", text_base);
|
||||
FVERBOSE("\tlimit: 0x%016" G_GINT64_MODIFIER "X", text_limit);
|
||||
|
||||
}
|
||||
|
||||
static void lib_get_text_section(lib_details_t *details) {
|
||||
@ -141,7 +144,7 @@ static void lib_get_text_section(lib_details_t *details) {
|
||||
|
||||
if (len == (off_t)-1) { FFATAL("Failed to lseek %s", details->path); }
|
||||
|
||||
FOKF("len: %ld", len);
|
||||
FVERBOSE("\tlength: %ld", len);
|
||||
|
||||
hdr = (Elf_Ehdr *)mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
if (hdr == MAP_FAILED) { FFATAL("Failed to map %s", details->path); }
|
||||
@ -162,8 +165,10 @@ void lib_init(void) {
|
||||
|
||||
lib_details_t lib_details;
|
||||
gum_process_enumerate_modules(lib_find_exe, &lib_details);
|
||||
FOKF("Executable: 0x%016" G_GINT64_MODIFIER "x - %s",
|
||||
lib_details.base_address, lib_details.path);
|
||||
FVERBOSE("Image");
|
||||
FVERBOSE("\tbase: 0x%016" G_GINT64_MODIFIER "x",
|
||||
lib_details.base_address);
|
||||
FVERBOSE("\tpath: %s", lib_details.path);
|
||||
lib_get_text_section(&lib_details);
|
||||
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ static gboolean lib_get_main_module(const GumModuleDetails *details,
|
||||
details->path, mach_task_self(), details->range->base_address,
|
||||
GUM_DARWIN_MODULE_FLAGS_NONE, NULL);
|
||||
|
||||
FOKF("Found main module: %s", module->name);
|
||||
FVERBOSE("Found main module: %s", module->name);
|
||||
|
||||
*ret = module;
|
||||
|
||||
@ -35,21 +35,23 @@ gboolean lib_get_text_section(const GumDarwinSectionDetails *details,
|
||||
static size_t idx = 0;
|
||||
char text_name[] = "__text";
|
||||
|
||||
FOKF("Section: %2lu - base: 0x%016" G_GINT64_MODIFIER
|
||||
"X size: 0x%016" G_GINT64_MODIFIER "X %s",
|
||||
idx++, details->vm_address, details->vm_address + details->size,
|
||||
details->section_name);
|
||||
FVERBOSE("\t%2lu - base: 0x%016" G_GINT64_MODIFIER
|
||||
"X size: 0x%016" G_GINT64_MODIFIER "X %s",
|
||||
idx++, details->vm_address, details->vm_address + details->size,
|
||||
details->section_name);
|
||||
|
||||
if (memcmp(details->section_name, text_name, sizeof(text_name)) == 0 &&
|
||||
text_base == 0) {
|
||||
|
||||
text_base = details->vm_address;
|
||||
text_limit = details->vm_address + details->size;
|
||||
FOKF("> text_addr: 0x%016" G_GINT64_MODIFIER "X", text_base);
|
||||
FOKF("> text_limit: 0x%016" G_GINT64_MODIFIER "X", text_limit);
|
||||
|
||||
}
|
||||
|
||||
FVERBOSE(".text\n");
|
||||
FVERBOSE("\taddr: 0x%016" G_GINT64_MODIFIER "X", text_base);
|
||||
FVERBOSE("\tlimit: 0x%016" G_GINT64_MODIFIER "X", text_limit);
|
||||
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
@ -62,6 +64,8 @@ void lib_init(void) {
|
||||
|
||||
GumDarwinModule *module = NULL;
|
||||
gum_darwin_enumerate_modules(mach_task_self(), lib_get_main_module, &module);
|
||||
|
||||
FVERBOSE("Sections:");
|
||||
gum_darwin_module_enumerate_sections(module, lib_get_text_section, NULL);
|
||||
|
||||
}
|
||||
|
@ -111,11 +111,13 @@ static void afl_print_cmdline(void) {
|
||||
|
||||
int idx = 0;
|
||||
|
||||
FVERBOSE("Command Line");
|
||||
|
||||
for (ssize_t i = 0; i < bytes_read; i++) {
|
||||
|
||||
if (i == 0 || buffer[i - 1] == '\0') {
|
||||
|
||||
FOKF("AFL - COMMANDLINE: argv[%d] = %s", idx++, &buffer[i]);
|
||||
FVERBOSE("\targv[%d] = %s", idx++, &buffer[i]);
|
||||
|
||||
}
|
||||
|
||||
@ -131,7 +133,7 @@ static void afl_print_cmdline(void) {
|
||||
|
||||
for (idx = 0; idx < nargv; idx++) {
|
||||
|
||||
FOKF("AFL - COMMANDLINE: argv[%d] = %s", idx, argv[idx]);
|
||||
FVERBOSE("\targv[%d] = %s", idx, argv[idx]);
|
||||
|
||||
}
|
||||
|
||||
@ -161,11 +163,12 @@ static void afl_print_env(void) {
|
||||
|
||||
int idx = 0;
|
||||
|
||||
FVERBOSE("ENVIRONMENT");
|
||||
for (ssize_t i = 0; i < bytes_read; i++) {
|
||||
|
||||
if (i == 0 || buffer[i - 1] == '\0') {
|
||||
|
||||
FOKF("AFL - ENVIRONMENT %3d: %s", idx++, &buffer[i]);
|
||||
FVERBOSE("\t%3d: %s", idx++, &buffer[i]);
|
||||
|
||||
}
|
||||
|
||||
@ -179,6 +182,13 @@ static void afl_print_env(void) {
|
||||
|
||||
__attribute__((visibility("default"))) void afl_frida_start(void) {
|
||||
|
||||
FOKF(cRED "**********************");
|
||||
FOKF(cRED "* " cYEL "******************" cRED " *");
|
||||
FOKF(cRED "* " cYEL "* " cGRN "**************" cYEL " *" cRED " *");
|
||||
FOKF(cRED "* " cYEL "* " cGRN "* FRIDA MODE *" cYEL " *" cRED " *");
|
||||
FOKF(cRED "* " cYEL "* " cGRN "**************" cYEL " *" cRED " *");
|
||||
FOKF(cRED "* " cYEL "******************" cRED " *");
|
||||
FOKF(cRED "**********************");
|
||||
afl_print_cmdline();
|
||||
afl_print_env();
|
||||
|
||||
@ -255,9 +265,9 @@ static void intercept_main(void) {
|
||||
static void intercept_main(void) {
|
||||
|
||||
mach_port_t task = mach_task_self();
|
||||
FOKF("Task Id: %u", task);
|
||||
FVERBOSE("Task Id: %u", task);
|
||||
GumAddress entry = gum_darwin_find_entrypoint(task);
|
||||
FOKF("Entry Point: 0x%016" G_GINT64_MODIFIER "x", entry);
|
||||
FVERBOSE("Entry Point: 0x%016" G_GINT64_MODIFIER "x", entry);
|
||||
void *main = GSIZE_TO_POINTER(entry);
|
||||
main_fn = main;
|
||||
intercept_hook(main, on_main, NULL);
|
||||
|
@ -18,7 +18,7 @@ static void output_redirect(int fd, char *filename) {
|
||||
|
||||
path = g_canonicalize_filename(filename, g_get_current_dir());
|
||||
|
||||
FOKF("Redirect %d -> '%s'", fd, path);
|
||||
FVERBOSE("Redirect %d -> '%s'", fd, path);
|
||||
|
||||
int output_fd = open(path, O_RDWR | O_CREAT | O_TRUNC,
|
||||
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
|
||||
@ -46,8 +46,10 @@ void output_config(void) {
|
||||
|
||||
void output_init(void) {
|
||||
|
||||
FOKF("Output - StdOut: %s", output_stdout);
|
||||
FOKF("Output - StdErr: %s", output_stderr);
|
||||
FOKF(cBLU "Output" cRST " - " cGRN "stdout:" cYEL " [%s]",
|
||||
output_stdout == NULL ? " " : output_stdout);
|
||||
FOKF(cBLU "Output" cRST " - " cGRN "stderr:" cYEL " [%s]",
|
||||
output_stderr == NULL ? " " : output_stderr);
|
||||
|
||||
output_redirect(STDOUT_FILENO, output_stdout);
|
||||
output_redirect(STDERR_FILENO, output_stderr);
|
||||
|
@ -72,13 +72,16 @@ void persistent_config(void) {
|
||||
|
||||
void persistent_init(void) {
|
||||
|
||||
FOKF("Instrumentation - persistent mode [%c] (0x%016" G_GINT64_MODIFIER "X)",
|
||||
FOKF(cBLU "Instrumentation" cRST " - " cGRN "persistent mode:" cYEL
|
||||
" [%c] (0x%016" G_GINT64_MODIFIER "X)",
|
||||
persistent_start == 0 ? ' ' : 'X', persistent_start);
|
||||
FOKF("Instrumentation - persistent count [%c] (%" G_GINT64_MODIFIER "d)",
|
||||
FOKF(cBLU "Instrumentation" cRST " - " cGRN "persistent count:" cYEL
|
||||
" [%c] (%" G_GINT64_MODIFIER "d)",
|
||||
persistent_start == 0 ? ' ' : 'X', persistent_count);
|
||||
FOKF("Instrumentation - hook [%s]", hook_name);
|
||||
FOKF(cBLU "Instrumentation" cRST " - " cGRN "hook:" cYEL " [%s]", hook_name);
|
||||
|
||||
FOKF("Instrumentation - persistent ret [%c] (0x%016" G_GINT64_MODIFIER "X)",
|
||||
FOKF(cBLU "Instrumentation" cRST " - " cGRN "persistent ret:" cYEL
|
||||
" [%c] (0x%016" G_GINT64_MODIFIER "X)",
|
||||
persistent_ret == 0 ? ' ' : 'X', persistent_ret);
|
||||
|
||||
if (persistent_hook != NULL) { __afl_sharedmem_fuzzing = 1; }
|
||||
@ -87,7 +90,7 @@ void persistent_init(void) {
|
||||
|
||||
void persistent_prologue(GumStalkerOutput *output) {
|
||||
|
||||
FOKF("AFL_FRIDA_PERSISTENT_ADDR reached");
|
||||
FVERBOSE("AFL_FRIDA_PERSISTENT_ADDR reached");
|
||||
entry_compiled = TRUE;
|
||||
ranges_exclude();
|
||||
stalker_trust();
|
||||
@ -97,7 +100,7 @@ void persistent_prologue(GumStalkerOutput *output) {
|
||||
|
||||
void persistent_epilogue(GumStalkerOutput *output) {
|
||||
|
||||
FOKF("AFL_FRIDA_PERSISTENT_RET reached");
|
||||
FVERBOSE("AFL_FRIDA_PERSISTENT_RET reached");
|
||||
persistent_epilogue_arch(output);
|
||||
|
||||
}
|
||||
|
@ -89,7 +89,7 @@ static void instrument_persitent_save_regs(GumArm64Writer * cw,
|
||||
|
||||
/* LR (x30) */
|
||||
gum_arm64_writer_put_str_reg_reg_offset(cw, ARM64_REG_X30, ARM64_REG_X0,
|
||||
offsetof(GumCpuContext, x[30]));
|
||||
offsetof(GumCpuContext, lr));
|
||||
|
||||
/* PC & Adjusted SP (31) */
|
||||
gum_arm64_writer_put_ldr_reg_address(cw, ARM64_REG_X2,
|
||||
@ -189,7 +189,7 @@ static void instrument_persitent_restore_regs(GumArm64Writer * cw,
|
||||
|
||||
/* LR (x30) */
|
||||
gum_arm64_writer_put_ldr_reg_reg_offset(cw, ARM64_REG_X30, ARM64_REG_X0,
|
||||
offsetof(GumCpuContext, x[30]));
|
||||
offsetof(GumCpuContext, lr));
|
||||
|
||||
/* Adjusted SP (31) (use x1 as clobber)*/
|
||||
gum_arm64_writer_put_ldr_reg_reg_offset(cw, ARM64_REG_X1, ARM64_REG_X0,
|
||||
@ -236,7 +236,13 @@ static void instrument_exit(GumArm64Writer *cw) {
|
||||
static int instrument_afl_persistent_loop_func(void) {
|
||||
|
||||
int ret = __afl_persistent_loop(persistent_count);
|
||||
instrument_previous_pc = instrument_hash_zero;
|
||||
if (instrument_previous_pc_addr == NULL) {
|
||||
|
||||
FATAL("instrument_previous_pc_addr uninitialized");
|
||||
|
||||
}
|
||||
|
||||
*instrument_previous_pc_addr = instrument_hash_zero;
|
||||
return ret;
|
||||
|
||||
}
|
||||
@ -264,8 +270,7 @@ static void persistent_prologue_hook(GumArm64Writer * cw,
|
||||
gum_arm64_writer_put_ldr_reg_reg_offset(cw, ARM64_REG_X2, ARM64_REG_X2, 0);
|
||||
gum_arm64_writer_put_ldr_reg_reg_offset(cw, ARM64_REG_X2, ARM64_REG_X2, 0);
|
||||
|
||||
gum_arm64_writer_put_and_reg_reg_imm(cw, ARM64_REG_X2, ARM64_REG_X2,
|
||||
G_MAXULONG);
|
||||
gum_arm64_writer_put_mov_reg_reg(cw, ARM64_REG_W2, ARM64_REG_W2);
|
||||
|
||||
gum_arm64_writer_put_ldr_reg_address(cw, ARM64_REG_X1,
|
||||
GUM_ADDRESS(&__afl_fuzz_ptr));
|
||||
@ -324,7 +329,7 @@ void persistent_prologue_arch(GumStalkerOutput *output) {
|
||||
|
||||
gconstpointer loop = cw->code + 1;
|
||||
|
||||
FOKF("Persistent loop reached");
|
||||
FVERBOSE("Persistent loop reached");
|
||||
|
||||
instrument_persitent_save_regs(cw, &saved_regs);
|
||||
|
||||
|
@ -173,7 +173,13 @@ static void instrument_exit(GumX86Writer *cw) {
|
||||
static int instrument_afl_persistent_loop_func(void) {
|
||||
|
||||
int ret = __afl_persistent_loop(persistent_count);
|
||||
instrument_previous_pc = instrument_hash_zero;
|
||||
if (instrument_previous_pc_addr == NULL) {
|
||||
|
||||
FATAL("instrument_previous_pc_addr uninitialized");
|
||||
|
||||
}
|
||||
|
||||
*instrument_previous_pc_addr = instrument_hash_zero;
|
||||
return ret;
|
||||
|
||||
}
|
||||
@ -269,7 +275,7 @@ void persistent_prologue_arch(GumStalkerOutput *output) {
|
||||
|
||||
gconstpointer loop = cw->code + 1;
|
||||
|
||||
FOKF("Persistent loop reached");
|
||||
FVERBOSE("Persistent loop reached");
|
||||
|
||||
/* Pop the return value */
|
||||
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, 8);
|
||||
|
@ -130,7 +130,13 @@ static void instrument_exit(GumX86Writer *cw) {
|
||||
static int instrument_afl_persistent_loop_func(void) {
|
||||
|
||||
int ret = __afl_persistent_loop(persistent_count);
|
||||
instrument_previous_pc = instrument_hash_zero;
|
||||
if (instrument_previous_pc_addr == NULL) {
|
||||
|
||||
FATAL("instrument_previous_pc_addr uninitialized");
|
||||
|
||||
}
|
||||
|
||||
*instrument_previous_pc_addr = instrument_hash_zero;
|
||||
return ret;
|
||||
|
||||
}
|
||||
@ -210,7 +216,7 @@ void persistent_prologue_arch(GumStalkerOutput *output) {
|
||||
|
||||
gconstpointer loop = cw->code + 1;
|
||||
|
||||
FOKF("Persistent loop reached");
|
||||
FVERBOSE("Persistent loop reached");
|
||||
|
||||
/* Pop the return value */
|
||||
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_ESP, GUM_REG_ESP, 4);
|
||||
|
@ -178,8 +178,10 @@ static void prefetch_hook_fork(void) {
|
||||
|
||||
void prefetch_init(void) {
|
||||
|
||||
FOKF("Instrumentation - prefetch [%c]", prefetch_enable ? 'X' : ' ');
|
||||
FOKF("Instrumentation - prefetch_backpatch [%c]",
|
||||
FOKF(cBLU "Instrumentation" cRST " - " cGRN "prefetch:" cYEL " [%c]",
|
||||
prefetch_enable ? 'X' : ' ');
|
||||
FOKF(cBLU "Instrumentation" cRST " - " cGRN "prefetch_backpatch:" cYEL
|
||||
" [%c]",
|
||||
prefetch_backpatch ? 'X' : ' ');
|
||||
|
||||
if (!prefetch_enable) { return; }
|
||||
|
@ -122,10 +122,10 @@ static gboolean convert_name_token_for_module(const GumModuleDetails *details,
|
||||
|
||||
if (!g_str_has_suffix(details->path, ctx->suffix)) { return true; };
|
||||
|
||||
FOKF("Found module - prefix: %s, 0x%016" G_GINT64_MODIFIER
|
||||
"x-0x%016" G_GINT64_MODIFIER "x %s",
|
||||
ctx->suffix, details->range->base_address,
|
||||
details->range->base_address + details->range->size, details->path);
|
||||
FVERBOSE("Found module - prefix: %s, 0x%016" G_GINT64_MODIFIER
|
||||
"x-0x%016" G_GINT64_MODIFIER "x %s",
|
||||
ctx->suffix, details->range->base_address,
|
||||
details->range->base_address + details->range->size, details->path);
|
||||
|
||||
*ctx->range = *details->range;
|
||||
ctx->done = true;
|
||||
@ -158,9 +158,9 @@ static void convert_token(gchar *token, GumMemoryRange *range) {
|
||||
|
||||
}
|
||||
|
||||
FOKF("Converted token: %s -> 0x%016" G_GINT64_MODIFIER
|
||||
"x-0x%016" G_GINT64_MODIFIER "x\n",
|
||||
token, range->base_address, range->base_address + range->size);
|
||||
FVERBOSE("Converted token: %s -> 0x%016" G_GINT64_MODIFIER
|
||||
"x-0x%016" G_GINT64_MODIFIER "x\n",
|
||||
token, range->base_address, range->base_address + range->size);
|
||||
|
||||
}
|
||||
|
||||
@ -192,24 +192,24 @@ static gboolean print_ranges_callback(const GumRangeDetails *details,
|
||||
|
||||
if (details->file == NULL) {
|
||||
|
||||
FOKF("MAP - 0x%016" G_GINT64_MODIFIER "x - 0x%016" G_GINT64_MODIFIER
|
||||
"X %c%c%c",
|
||||
details->range->base_address,
|
||||
details->range->base_address + details->range->size,
|
||||
details->protection & GUM_PAGE_READ ? 'R' : '-',
|
||||
details->protection & GUM_PAGE_WRITE ? 'W' : '-',
|
||||
details->protection & GUM_PAGE_EXECUTE ? 'X' : '-');
|
||||
FVERBOSE("\t0x%016" G_GINT64_MODIFIER "x-0x%016" G_GINT64_MODIFIER
|
||||
"X %c%c%c",
|
||||
details->range->base_address,
|
||||
details->range->base_address + details->range->size,
|
||||
details->protection & GUM_PAGE_READ ? 'R' : '-',
|
||||
details->protection & GUM_PAGE_WRITE ? 'W' : '-',
|
||||
details->protection & GUM_PAGE_EXECUTE ? 'X' : '-');
|
||||
|
||||
} else {
|
||||
|
||||
FOKF("MAP - 0x%016" G_GINT64_MODIFIER "x - 0x%016" G_GINT64_MODIFIER
|
||||
"X %c%c%c %s(0x%016" G_GINT64_MODIFIER "x)",
|
||||
details->range->base_address,
|
||||
details->range->base_address + details->range->size,
|
||||
details->protection & GUM_PAGE_READ ? 'R' : '-',
|
||||
details->protection & GUM_PAGE_WRITE ? 'W' : '-',
|
||||
details->protection & GUM_PAGE_EXECUTE ? 'X' : '-',
|
||||
details->file->path, details->file->offset);
|
||||
FVERBOSE("\t0x%016" G_GINT64_MODIFIER "x-0x%016" G_GINT64_MODIFIER
|
||||
"X %c%c%c %s(0x%016" G_GINT64_MODIFIER "x)",
|
||||
details->range->base_address,
|
||||
details->range->base_address + details->range->size,
|
||||
details->protection & GUM_PAGE_READ ? 'R' : '-',
|
||||
details->protection & GUM_PAGE_WRITE ? 'W' : '-',
|
||||
details->protection & GUM_PAGE_EXECUTE ? 'X' : '-',
|
||||
details->file->path, details->file->offset);
|
||||
|
||||
}
|
||||
|
||||
@ -219,14 +219,14 @@ static gboolean print_ranges_callback(const GumRangeDetails *details,
|
||||
|
||||
static void print_ranges(char *key, GArray *ranges) {
|
||||
|
||||
FOKF("Range: %s Length: %d", key, ranges->len);
|
||||
FVERBOSE("Range: [%s], Length: %d", key, ranges->len);
|
||||
for (guint i = 0; i < ranges->len; i++) {
|
||||
|
||||
GumMemoryRange *curr = &g_array_index(ranges, GumMemoryRange, i);
|
||||
GumAddress curr_limit = curr->base_address + curr->size;
|
||||
FOKF("Range: %s Idx: %3d - 0x%016" G_GINT64_MODIFIER
|
||||
"x-0x%016" G_GINT64_MODIFIER "x",
|
||||
key, i, curr->base_address, curr_limit);
|
||||
FVERBOSE("\t%3d - 0x%016" G_GINT64_MODIFIER "x-0x%016" G_GINT64_MODIFIER
|
||||
"x",
|
||||
i, curr->base_address, curr_limit);
|
||||
|
||||
}
|
||||
|
||||
@ -248,7 +248,7 @@ static GArray *collect_module_ranges(void) {
|
||||
result = g_array_new(false, false, sizeof(GumMemoryRange));
|
||||
gum_process_enumerate_ranges(GUM_PAGE_NO_ACCESS,
|
||||
collect_module_ranges_callback, result);
|
||||
print_ranges("Modules", result);
|
||||
print_ranges("modules", result);
|
||||
return result;
|
||||
|
||||
}
|
||||
@ -348,7 +348,7 @@ static GArray *collect_libs_ranges(void) {
|
||||
|
||||
g_array_append_val(result, range);
|
||||
|
||||
print_ranges("AFL_INST_LIBS", result);
|
||||
print_ranges("libs", result);
|
||||
|
||||
return result;
|
||||
|
||||
@ -382,7 +382,7 @@ static GArray *collect_jit_ranges(void) {
|
||||
|
||||
}
|
||||
|
||||
print_ranges("JIT", result);
|
||||
print_ranges("jit", result);
|
||||
return result;
|
||||
|
||||
}
|
||||
@ -564,6 +564,7 @@ static GArray *merge_ranges(GArray *a) {
|
||||
|
||||
void ranges_print_debug_maps(void) {
|
||||
|
||||
FVERBOSE("Maps");
|
||||
gum_process_enumerate_ranges(GUM_PAGE_NO_ACCESS, print_ranges_callback, NULL);
|
||||
|
||||
}
|
||||
@ -590,16 +591,15 @@ void ranges_init(void) {
|
||||
GArray * step4;
|
||||
GArray * step5;
|
||||
|
||||
FOKF("Ranges - Instrument jit [%c]", ranges_inst_jit ? 'X' : ' ');
|
||||
FOKF("Ranges - Instrument libraries [%c]", ranges_inst_libs ? 'X' : ' ');
|
||||
FOKF(cBLU "Ranges" cRST " - " cGRN "instrument jit:" cYEL " [%c]",
|
||||
ranges_inst_jit ? 'X' : ' ');
|
||||
FOKF(cBLU "Ranges" cRST " - " cGRN "instrument libraries:" cYEL " [%c]",
|
||||
ranges_inst_libs ? 'X' : ' ');
|
||||
FOKF(cBLU "Ranges" cRST " - " cGRN "instrument libraries:" cYEL " [%c]",
|
||||
ranges_inst_libs ? 'X' : ' ');
|
||||
|
||||
print_ranges("AFL_FRIDA_INST_RANGES", include_ranges);
|
||||
print_ranges("AFL_FRIDA_EXCLUDE_RANGES", exclude_ranges);
|
||||
|
||||
FOKF("Ranges - Instrument libraries [%c]", ranges_inst_libs ? 'X' : ' ');
|
||||
|
||||
print_ranges("AFL_FRIDA_INST_RANGES", include_ranges);
|
||||
print_ranges("AFL_FRIDA_EXCLUDE_RANGES", exclude_ranges);
|
||||
print_ranges("include", include_ranges);
|
||||
print_ranges("exclude", exclude_ranges);
|
||||
|
||||
module_ranges = collect_module_ranges();
|
||||
libs_ranges = collect_libs_ranges();
|
||||
@ -673,7 +673,7 @@ void ranges_exclude() {
|
||||
GumMemoryRange *r;
|
||||
GumStalker * stalker = stalker_get();
|
||||
|
||||
FOKF("Excluding ranges");
|
||||
FVERBOSE("Excluding ranges");
|
||||
|
||||
for (guint i = 0; i < ranges->len; i++) {
|
||||
|
||||
|
@ -25,7 +25,8 @@ void seccomp_config(void) {
|
||||
|
||||
void seccomp_init(void) {
|
||||
|
||||
FOKF("Seccomp - file [%s]", seccomp_filename);
|
||||
FOKF(cBLU "Seccomp" cRST " - " cGRN "file:" cYEL " [%s]",
|
||||
seccomp_filename == NULL ? " " : seccomp_filename);
|
||||
|
||||
if (seccomp_filename == NULL) { return; }
|
||||
|
||||
|
@ -124,7 +124,7 @@ void seccomp_callback_initialize(void) {
|
||||
|
||||
path = g_canonicalize_filename(seccomp_filename, g_get_current_dir());
|
||||
|
||||
FOKF("Seccomp - path [%s]", path);
|
||||
FVERBOSE("Seccomp - path [%s]", path);
|
||||
|
||||
fd = open(path, O_RDWR | O_CREAT | O_TRUNC,
|
||||
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
|
||||
|
@ -258,7 +258,7 @@ void seccomp_filter_run(int fd, seccomp_filter_callback_t callback) {
|
||||
if (ioctl(fd, SECCOMP_IOCTL_NOTIF_SEND, resp) < 0) {
|
||||
|
||||
if (errno == ENOENT) { continue; }
|
||||
FOKF("SECCOMP_IOCTL_NOTIF_SEND");
|
||||
FVERBOSE("SECCOMP_IOCTL_NOTIF_SEND");
|
||||
continue;
|
||||
|
||||
}
|
||||
|
@ -93,10 +93,12 @@ static gboolean stalker_exclude_self(const GumRangeDetails *details,
|
||||
|
||||
void stalker_init(void) {
|
||||
|
||||
FOKF("Instrumentation - backpatch [%c]", backpatch_enable ? 'X' : ' ');
|
||||
|
||||
FOKF("Stalker - ic_entries [%u]", stalker_ic_entries);
|
||||
FOKF("Stalker - adjacent_blocks [%u]", stalker_adjacent_blocks);
|
||||
FOKF(cBLU "Stalker" cRST " - " cGRN "backpatch:" cYEL " [%c]",
|
||||
backpatch_enable ? 'X' : ' ');
|
||||
FOKF(cBLU "Stalker" cRST " - " cGRN "ic_entries:" cYEL " [%u]",
|
||||
stalker_ic_entries);
|
||||
FOKF(cBLU "Stalker" cRST " - " cGRN "adjacent_blocks:" cYEL " [%u]",
|
||||
stalker_adjacent_blocks);
|
||||
|
||||
#if !(defined(__x86_64__) || defined(__i386__))
|
||||
if (getenv("AFL_FRIDA_STALKER_IC_ENTRIES") != NULL) {
|
||||
|
@ -329,8 +329,11 @@ void stats_config(void) {
|
||||
|
||||
void stats_init(void) {
|
||||
|
||||
FOKF("Stats - file [%s]", stats_filename);
|
||||
FOKF("Stats - interval [%" G_GINT64_MODIFIER "u]", stats_interval);
|
||||
FOKF(cBLU "Stats" cRST " - " cGRN "file:" cYEL " [%s]",
|
||||
stats_filename == NULL ? " " : stats_filename);
|
||||
FOKF(cBLU "Stats" cRST " - " cGRN "interval:" cYEL " [%" G_GINT64_MODIFIER
|
||||
"u]",
|
||||
stats_interval);
|
||||
|
||||
if (getenv("AFL_FRIDA_STATS_INTERVAL") != NULL &&
|
||||
getenv("AFL_FRIDA_STATS_FILE") == NULL) {
|
||||
@ -347,7 +350,8 @@ void stats_init(void) {
|
||||
|
||||
char *path = g_canonicalize_filename(stats_filename, g_get_current_dir());
|
||||
|
||||
FOKF("Stats - path [%s]", path);
|
||||
FOKF(cBLU "Stats" cRST " - " cGRN "path:" cYEL " [%s]",
|
||||
path == NULL ? " " : path);
|
||||
|
||||
stats_fd = open(path, O_RDWR | O_CREAT | O_TRUNC,
|
||||
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "util.h"
|
||||
|
||||
gboolean util_verbose = FALSE;
|
||||
|
||||
guint64 util_read_address(char *key, guint64 default_value) {
|
||||
|
||||
char *value_str = getenv(key);
|
||||
@ -66,7 +68,7 @@ guint64 util_read_num(char *key, guint64 default_value) {
|
||||
|
||||
errno = 0;
|
||||
|
||||
guint64 value = g_ascii_strtoull(value_str, NULL, 10);
|
||||
guint64 value = g_ascii_strtoull(value_str, &end_ptr, 10);
|
||||
|
||||
if (errno != 0) {
|
||||
|
||||
@ -87,12 +89,13 @@ guint64 util_read_num(char *key, guint64 default_value) {
|
||||
gboolean util_output_enabled(void) {
|
||||
|
||||
static gboolean initialized = FALSE;
|
||||
static gboolean enabled = TRUE;
|
||||
static gboolean enabled = FALSE;
|
||||
|
||||
if (!initialized) {
|
||||
|
||||
initialized = TRUE;
|
||||
if (getenv("AFL_DEBUG_CHILD") == NULL) { enabled = FALSE; }
|
||||
if (getenv("AFL_DEBUG_CHILD") != NULL) { enabled = TRUE; }
|
||||
if (util_verbose_enabled()) { enabled = TRUE; }
|
||||
|
||||
}
|
||||
|
||||
@ -100,6 +103,21 @@ gboolean util_output_enabled(void) {
|
||||
|
||||
}
|
||||
|
||||
gboolean util_verbose_enabled(void) {
|
||||
|
||||
static gboolean initialized = FALSE;
|
||||
|
||||
if (!initialized) {
|
||||
|
||||
initialized = TRUE;
|
||||
if (getenv("AFL_FRIDA_VERBOSE") != NULL) { util_verbose = TRUE; }
|
||||
|
||||
}
|
||||
|
||||
return util_verbose;
|
||||
|
||||
}
|
||||
|
||||
gsize util_rotate(gsize val, gsize shift, gsize size) {
|
||||
|
||||
if (shift == 0) { return val; }
|
||||
|
@ -34,20 +34,22 @@ ifeq "$(ARCH)" "i686"
|
||||
endif
|
||||
endif
|
||||
|
||||
ADDR_BIN:=$(ROOT)frida_mode/build/addr
|
||||
GET_SYMBOL_ADDR:=$(ROOT)frida_mode/util/get_symbol_addr.sh
|
||||
|
||||
AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000)
|
||||
AFL_FRIDA_BASE_ADDR:=$(shell $(ADDR_BIN))
|
||||
AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput $(AFL_FRIDA_BASE_ADDR))
|
||||
|
||||
ifeq "$(ARCH)" "aarch64"
|
||||
AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000aaaaaaaaa000)
|
||||
ifeq "$(ARCH)" "arm64"
|
||||
AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x5500000000)
|
||||
endif
|
||||
|
||||
ifeq "$(ARCH)" "x86_64"
|
||||
AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000555555554000)
|
||||
AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000)
|
||||
endif
|
||||
|
||||
ifeq "$(ARCH)" "x86"
|
||||
AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x56555000)
|
||||
AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000)
|
||||
endif
|
||||
|
||||
.PHONY: all clean frida hook
|
||||
|
@ -1,36 +0,0 @@
|
||||
#!/usr/bin/python3
|
||||
import argparse
|
||||
from elftools.elf.elffile import ELFFile
|
||||
|
||||
def process_file(file, symbol, base):
|
||||
with open(file, 'rb') as f:
|
||||
elf = ELFFile(f)
|
||||
symtab = elf.get_section_by_name('.symtab')
|
||||
mains = symtab.get_symbol_by_name(symbol)
|
||||
if len(mains) != 1:
|
||||
print ("Failed to find main")
|
||||
return 1
|
||||
|
||||
main_addr = mains[0]['st_value']
|
||||
main = base + main_addr
|
||||
print ("0x%016x" % main)
|
||||
return 0
|
||||
|
||||
def hex_value(x):
|
||||
return int(x, 16)
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description='Process some integers.')
|
||||
parser.add_argument('-f', '--file', dest='file', type=str,
|
||||
help='elf file name', required=True)
|
||||
parser.add_argument('-s', '--symbol', dest='symbol', type=str,
|
||||
help='symbol name', required=True)
|
||||
parser.add_argument('-b', '--base', dest='base', type=hex_value,
|
||||
help='elf base address', required=True)
|
||||
|
||||
args = parser.parse_args()
|
||||
return process_file (args.file, args.symbol, args.base)
|
||||
|
||||
if __name__ == "__main__":
|
||||
ret = main()
|
||||
exit(ret)
|
@ -2,7 +2,7 @@
|
||||
//
|
||||
// Author: Mateusz Jurczyk (mjurczyk@google.com)
|
||||
//
|
||||
// Copyright 2019-2020 Google LLC
|
||||
// Copyright 2019-2022 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
@ -3,7 +3,7 @@
|
||||
--------------------------------------------------------
|
||||
Originally written by Michal Zalewski
|
||||
Copyright 2014 Google Inc. All rights reserved.
|
||||
Copyright 2019-2020 AFLplusplus Project. All rights reserved.
|
||||
Copyright 2019-2022 AFLplusplus Project. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
@ -3,7 +3,7 @@
|
||||
--------------------------------------------------------
|
||||
Originally written by Michal Zalewski
|
||||
Copyright 2014 Google Inc. All rights reserved.
|
||||
Copyright 2019-2020 AFLplusplus Project. All rights reserved.
|
||||
Copyright 2019-2022 AFLplusplus Project. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
@ -3,7 +3,7 @@
|
||||
--------------------------------------------------------
|
||||
Originally written by Michal Zalewski
|
||||
Copyright 2014 Google Inc. All rights reserved.
|
||||
Copyright 2019-2020 AFLplusplus Project. All rights reserved.
|
||||
Copyright 2019-2022 AFLplusplus Project. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
@ -47,6 +47,7 @@ endif
|
||||
TEST_DATA_DIR:=$(BUILD_DIR)in/
|
||||
TEST_DATA_FILE:=$(TEST_DATA_DIR)default_seed
|
||||
|
||||
AFLPP_DRIVER_DUMMY_INPUT:=$(BUILD_DIR)dummy.dat
|
||||
FRIDA_OUT:=$(BUILD_DIR)frida-out
|
||||
QEMU_OUT:=$(BUILD_DIR)qemu-out
|
||||
|
||||
@ -62,20 +63,22 @@ ifeq "$(ARCH)" "i686"
|
||||
endif
|
||||
endif
|
||||
|
||||
ADDR_BIN:=$(ROOT)frida_mode/build/addr
|
||||
GET_SYMBOL_ADDR:=$(ROOT)frida_mode/util/get_symbol_addr.sh
|
||||
|
||||
AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000)
|
||||
AFL_FRIDA_BASE_ADDR:=$(shell $(ADDR_BIN))
|
||||
AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput $(AFL_FRIDA_BASE_ADDR))
|
||||
|
||||
ifeq "$(ARCH)" "aarch64"
|
||||
AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000aaaaaaaaa000)
|
||||
ifeq "$(ARCH)" "arm64"
|
||||
AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x5500000000)
|
||||
endif
|
||||
|
||||
ifeq "$(ARCH)" "x86_64"
|
||||
AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000555555554000)
|
||||
AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000)
|
||||
endif
|
||||
|
||||
ifeq "$(ARCH)" "x86"
|
||||
AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x56555000)
|
||||
AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000)
|
||||
endif
|
||||
|
||||
.PHONY: all clean frida hook
|
||||
@ -154,6 +157,9 @@ $(TEST_DATA_DIR): | $(TRT_DIR)
|
||||
cp $(TRT_DIR)fonts/TestGLYFOne.ttf $@
|
||||
|
||||
$(TEST_DATA_FILE): | $(TEST_DATA_DIR)
|
||||
echo "hi" > $@
|
||||
|
||||
$(AFLPP_DRIVER_DUMMY_INPUT): | $(BUILD_DIR)
|
||||
dd if=/dev/zero bs=1048576 count=1 of=$@
|
||||
|
||||
###### TEST DATA #######
|
||||
@ -161,7 +167,7 @@ $(TEST_DATA_FILE): | $(TEST_DATA_DIR)
|
||||
clean:
|
||||
rm -rf $(BUILD_DIR)
|
||||
|
||||
frida: $(TEST_BIN) $(AFLPP_FRIDA_DRIVER_HOOK_OBJ) $(TEST_DATA_FILE)
|
||||
frida: $(TEST_BIN) $(AFLPP_FRIDA_DRIVER_HOOK_OBJ) $(TEST_DATA_FILE) $(AFLPP_DRIVER_DUMMY_INPUT)
|
||||
AFL_FRIDA_PERSISTENT_CNT=1000000 \
|
||||
AFL_FRIDA_PERSISTENT_HOOK=$(AFLPP_FRIDA_DRIVER_HOOK_OBJ) \
|
||||
AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR) \
|
||||
@ -174,9 +180,9 @@ frida: $(TEST_BIN) $(AFLPP_FRIDA_DRIVER_HOOK_OBJ) $(TEST_DATA_FILE)
|
||||
-O \
|
||||
-V 30 \
|
||||
-- \
|
||||
$(TEST_BIN) $(TEST_DATA_FILE)
|
||||
$(TEST_BIN) $(AFLPP_DRIVER_DUMMY_INPUT)
|
||||
|
||||
qemu: $(TEST_BIN) $(AFLPP_QEMU_DRIVER_HOOK_OBJ) $(TEST_DATA_FILE)
|
||||
qemu: $(TEST_BIN) $(AFLPP_QEMU_DRIVER_HOOK_OBJ) $(TEST_DATA_FILE) $(AFLPP_DRIVER_DUMMY_INPUT)
|
||||
AFL_QEMU_PERSISTENT_CNT=1000000 \
|
||||
AFL_QEMU_PERSISTENT_HOOK=$(AFLPP_QEMU_DRIVER_HOOK_OBJ) \
|
||||
AFL_QEMU_PERSISTENT_ADDR=$(AFL_QEMU_PERSISTENT_ADDR) \
|
||||
@ -189,4 +195,4 @@ qemu: $(TEST_BIN) $(AFLPP_QEMU_DRIVER_HOOK_OBJ) $(TEST_DATA_FILE)
|
||||
-Q \
|
||||
-V 30 \
|
||||
-- \
|
||||
$(TEST_BIN) $(TEST_DATA_FILE)
|
||||
$(TEST_BIN) $(AFLPP_DRIVER_DUMMY_INPUT)
|
||||
|
@ -1,36 +0,0 @@
|
||||
#!/usr/bin/python3
|
||||
import argparse
|
||||
from elftools.elf.elffile import ELFFile
|
||||
|
||||
def process_file(file, symbol, base):
|
||||
with open(file, 'rb') as f:
|
||||
elf = ELFFile(f)
|
||||
symtab = elf.get_section_by_name('.symtab')
|
||||
mains = symtab.get_symbol_by_name(symbol)
|
||||
if len(mains) != 1:
|
||||
print ("Failed to find main")
|
||||
return 1
|
||||
|
||||
main_addr = mains[0]['st_value']
|
||||
main = base + main_addr
|
||||
print ("0x%016x" % main)
|
||||
return 0
|
||||
|
||||
def hex_value(x):
|
||||
return int(x, 16)
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description='Process some integers.')
|
||||
parser.add_argument('-f', '--file', dest='file', type=str,
|
||||
help='elf file name', required=True)
|
||||
parser.add_argument('-s', '--symbol', dest='symbol', type=str,
|
||||
help='symbol name', required=True)
|
||||
parser.add_argument('-b', '--base', dest='base', type=hex_value,
|
||||
help='elf base address', required=True)
|
||||
|
||||
args = parser.parse_args()
|
||||
return process_file (args.file, args.symbol, args.base)
|
||||
|
||||
if __name__ == "__main__":
|
||||
ret = main()
|
||||
exit(ret)
|
@ -46,19 +46,11 @@ ifeq "$(ARCH)" "i686"
|
||||
endif
|
||||
endif
|
||||
|
||||
ADDR_BIN:=$(ROOT)frida_mode/build/addr
|
||||
GET_SYMBOL_ADDR:=$(ROOT)frida_mode/util/get_symbol_addr.sh
|
||||
|
||||
ifeq "$(ARCH)" "aarch64"
|
||||
AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000aaaaaaaaa000)
|
||||
endif
|
||||
|
||||
ifeq "$(ARCH)" "x86_64"
|
||||
AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000555555554000)
|
||||
endif
|
||||
|
||||
ifeq "$(ARCH)" "x86"
|
||||
AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x56555000)
|
||||
endif
|
||||
AFL_FRIDA_BASE_ADDR:=$(shell $(ADDR_BIN))
|
||||
AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput $(AFL_FRIDA_BASE_ADDR))
|
||||
|
||||
.PHONY: all clean frida hook
|
||||
|
||||
|
@ -1,36 +0,0 @@
|
||||
#!/usr/bin/python3
|
||||
import argparse
|
||||
from elftools.elf.elffile import ELFFile
|
||||
|
||||
def process_file(file, symbol, base):
|
||||
with open(file, 'rb') as f:
|
||||
elf = ELFFile(f)
|
||||
symtab = elf.get_section_by_name('.symtab')
|
||||
mains = symtab.get_symbol_by_name(symbol)
|
||||
if len(mains) != 1:
|
||||
print ("Failed to find main")
|
||||
return 1
|
||||
|
||||
main_addr = mains[0]['st_value']
|
||||
main = base + main_addr
|
||||
print ("0x%016x" % main)
|
||||
return 0
|
||||
|
||||
def hex_value(x):
|
||||
return int(x, 16)
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description='Process some integers.')
|
||||
parser.add_argument('-f', '--file', dest='file', type=str,
|
||||
help='elf file name', required=True)
|
||||
parser.add_argument('-s', '--symbol', dest='symbol', type=str,
|
||||
help='symbol name', required=True)
|
||||
parser.add_argument('-b', '--base', dest='base', type=hex_value,
|
||||
help='elf base address', required=True)
|
||||
|
||||
args = parser.parse_args()
|
||||
return process_file (args.file, args.symbol, args.base)
|
||||
|
||||
if __name__ == "__main__":
|
||||
ret = main()
|
||||
exit(ret)
|
@ -3,7 +3,7 @@
|
||||
--------------------------------------------------------
|
||||
Originally written by Michal Zalewski
|
||||
Copyright 2014 Google Inc. All rights reserved.
|
||||
Copyright 2019-2020 AFLplusplus Project. All rights reserved.
|
||||
Copyright 2019-2022 AFLplusplus Project. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
@ -3,7 +3,7 @@
|
||||
--------------------------------------------------------
|
||||
Originally written by Michal Zalewski
|
||||
Copyright 2014 Google Inc. All rights reserved.
|
||||
Copyright 2019-2020 AFLplusplus Project. All rights reserved.
|
||||
Copyright 2019-2022 AFLplusplus Project. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
@ -55,20 +55,22 @@ ifeq "$(ARCH)" "i686"
|
||||
endif
|
||||
endif
|
||||
|
||||
ADDR_BIN:=$(ROOT)frida_mode/build/addr
|
||||
GET_SYMBOL_ADDR:=$(ROOT)frida_mode/util/get_symbol_addr.sh
|
||||
|
||||
AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000)
|
||||
AFL_FRIDA_BASE_ADDR:=$(shell $(ADDR_BIN))
|
||||
AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput $(AFL_FRIDA_BASE_ADDR))
|
||||
|
||||
ifeq "$(ARCH)" "arm64"
|
||||
AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000aaaaaaaaa000)
|
||||
AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x5500000000)
|
||||
endif
|
||||
|
||||
ifeq "$(ARCH)" "x86_64"
|
||||
AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000555555554000)
|
||||
AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000)
|
||||
endif
|
||||
|
||||
ifeq "$(ARCH)" "x86"
|
||||
AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x56555000)
|
||||
AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000)
|
||||
endif
|
||||
|
||||
.PHONY: all clean qemu frida hook
|
||||
|
@ -42,21 +42,11 @@ ifeq "$(ARCH)" "i686"
|
||||
endif
|
||||
endif
|
||||
|
||||
ADDR_BIN:=$(ROOT)frida_mode/build/addr
|
||||
GET_SYMBOL_ADDR:=$(ROOT)frida_mode/util/get_symbol_addr.sh
|
||||
|
||||
AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000)
|
||||
|
||||
ifeq "$(ARCH)" "aarch64"
|
||||
AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000aaaaaaaaa000)
|
||||
endif
|
||||
|
||||
ifeq "$(ARCH)" "x86_64"
|
||||
AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000555555554000)
|
||||
endif
|
||||
|
||||
ifeq "$(ARCH)" "x86"
|
||||
AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x56555000)
|
||||
endif
|
||||
AFL_FRIDA_BASE_ADDR:=$(shell $(ADDR_BIN))
|
||||
AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput $(AFL_FRIDA_BASE_ADDR))
|
||||
|
||||
.PHONY: all clean frida hook
|
||||
|
||||
@ -134,7 +124,7 @@ $(TEST_DATA_DIR): | $(BUILD_DIR)
|
||||
mkdir -p $@
|
||||
|
||||
$(TEST_DATA_FILE): | $(TEST_DATA_DIR)
|
||||
dd if=/dev/zero bs=1048576 count=1 of=$@
|
||||
echo "hi" > $@
|
||||
|
||||
###### #######
|
||||
|
||||
|
@ -1,36 +0,0 @@
|
||||
#!/usr/bin/python3
|
||||
import argparse
|
||||
from elftools.elf.elffile import ELFFile
|
||||
|
||||
def process_file(file, symbol, base):
|
||||
with open(file, 'rb') as f:
|
||||
elf = ELFFile(f)
|
||||
symtab = elf.get_section_by_name('.symtab')
|
||||
mains = symtab.get_symbol_by_name(symbol)
|
||||
if len(mains) != 1:
|
||||
print ("Failed to find main")
|
||||
return 1
|
||||
|
||||
main_addr = mains[0]['st_value']
|
||||
main = base + main_addr
|
||||
print ("0x%016x" % main)
|
||||
return 0
|
||||
|
||||
def hex_value(x):
|
||||
return int(x, 16)
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description='Process some integers.')
|
||||
parser.add_argument('-f', '--file', dest='file', type=str,
|
||||
help='elf file name', required=True)
|
||||
parser.add_argument('-s', '--symbol', dest='symbol', type=str,
|
||||
help='symbol name', required=True)
|
||||
parser.add_argument('-b', '--base', dest='base', type=hex_value,
|
||||
help='elf base address', required=True)
|
||||
|
||||
args = parser.parse_args()
|
||||
return process_file (args.file, args.symbol, args.base)
|
||||
|
||||
if __name__ == "__main__":
|
||||
ret = main()
|
||||
exit(ret)
|
177
frida_mode/test/libxslt/GNUmakefile
Normal file
@ -0,0 +1,177 @@
|
||||
PWD:=$(shell pwd)/
|
||||
ROOT:=$(PWD)../../../
|
||||
BUILD_DIR:=$(PWD)build/
|
||||
|
||||
AFLPP_FRIDA_DRIVER_HOOK_OBJ=$(ROOT)frida_mode/build/frida_hook.so
|
||||
AFLPP_QEMU_DRIVER_HOOK_OBJ=$(ROOT)frida_mode/build/qemu_hook.so
|
||||
|
||||
LIBFUZZER_LIB:=/usr/lib/llvm-12/lib/libFuzzer.a
|
||||
|
||||
LIBXSLT_GIT_REPO:=https://gitlab.gnome.org/GNOME/libxslt.git
|
||||
LIBXSLT_DIR:=$(BUILD_DIR)libxslt/
|
||||
LIBXSLT_LIB:=$(LIBXSLT_DIR)libxslt/.libs/libxslt.a
|
||||
|
||||
LIBZXML2_GIT_REPO:=https://gitlab.gnome.org/GNOME/libxml2.git
|
||||
LIBXML2_DIR:=$(BUILD_DIR)libxml2/
|
||||
LIBXML2_LIB:=$(LIBXML2_DIR).libs/libxml2.a
|
||||
|
||||
TEST_BIN:=$(BUILD_DIR)test
|
||||
XPATH_XML:=$(BUILD_DIR)xpath.xml
|
||||
|
||||
ifeq "$(shell uname)" "Darwin"
|
||||
TEST_BIN_LDFLAGS:=-undefined dynamic_lookup -Wl,-no_pie
|
||||
endif
|
||||
|
||||
TEST_DATA_DIR:=$(BUILD_DIR)in/
|
||||
TEST_DATA_SRC:=$(LIBXSLT_DIR)tests/testdata/fuzz_corpus/
|
||||
DUMMY_DATA_FILE:=$(BUILD_DIR)default_seed
|
||||
|
||||
FRIDA_OUT:=$(BUILD_DIR)frida-out
|
||||
QEMU_OUT:=$(BUILD_DIR)qemu-out
|
||||
|
||||
ifndef ARCH
|
||||
|
||||
ARCH=$(shell uname -m)
|
||||
ifeq "$(ARCH)" "aarch64"
|
||||
ARCH:=arm64
|
||||
endif
|
||||
|
||||
ifeq "$(ARCH)" "i686"
|
||||
ARCH:=x86
|
||||
endif
|
||||
endif
|
||||
|
||||
ADDR_BIN:=$(ROOT)frida_mode/build/addr
|
||||
GET_SYMBOL_ADDR:=$(ROOT)frida_mode/util/get_symbol_addr.sh
|
||||
|
||||
AFL_FRIDA_BASE_ADDR:=$(shell $(ADDR_BIN))
|
||||
AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput $(AFL_FRIDA_BASE_ADDR))
|
||||
|
||||
ifeq "$(ARCH)" "arm64"
|
||||
AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x5500000000)
|
||||
endif
|
||||
|
||||
ifeq "$(ARCH)" "x86_64"
|
||||
AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000)
|
||||
endif
|
||||
|
||||
ifeq "$(ARCH)" "x86"
|
||||
AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000)
|
||||
endif
|
||||
|
||||
.PHONY: all clean frida hook
|
||||
|
||||
all: $(TEST_BIN)
|
||||
make -C $(ROOT)frida_mode/
|
||||
|
||||
32:
|
||||
CXXFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all
|
||||
|
||||
$(BUILD_DIR):
|
||||
mkdir -p $@
|
||||
|
||||
########## LIBXML2 #######
|
||||
|
||||
$(LIBXML2_DIR): | $(BUILD_DIR)
|
||||
git clone --depth 1 $(LIBZXML2_GIT_REPO) $@
|
||||
|
||||
$(LIBXML2_LIB): | $(LIBXML2_DIR)
|
||||
cd $(LIBXML2_DIR) && ./autogen.sh \
|
||||
--disable-shared \
|
||||
--without-c14n \
|
||||
--without-legacy \
|
||||
--without-push \
|
||||
--without-python \
|
||||
--without-reader \
|
||||
--without-regexps \
|
||||
--without-sax1 \
|
||||
--without-schemas \
|
||||
--without-schematron \
|
||||
--without-valid \
|
||||
--without-writer \
|
||||
--without-zlib \
|
||||
--without-lzma
|
||||
cd $(LIBXML2_DIR) && make -j$(nproc) V=1
|
||||
|
||||
libxml2: $(LIBXML2_LIB)
|
||||
|
||||
########## LIBZXSLT #######
|
||||
|
||||
$(LIBXSLT_DIR): | $(BUILD_DIR)
|
||||
git clone --depth 1 $(LIBXSLT_GIT_REPO) $@
|
||||
|
||||
$(LIBXSLT_LIB): | $(LIBXSLT_DIR) $(LIBXML2_DIR)
|
||||
cd $(LIBXSLT_DIR) && ./autogen.sh \
|
||||
--with-libxml-src=../libxml2 \
|
||||
--disable-shared \
|
||||
--without-python \
|
||||
--with-crypto \
|
||||
--without-debug \
|
||||
--without-debugger \
|
||||
--without-profiler
|
||||
cd $(LIBXSLT_DIR) && make -j$(nproc) V=1
|
||||
|
||||
libxslt: $(LIBXSLT_LIB)
|
||||
|
||||
$(TEST_BIN): $(LIBXSLT_LIB) $(LIBXML2_LIB)
|
||||
clang \
|
||||
-o $@ \
|
||||
-fsanitize=fuzzer \
|
||||
-I $(LIBXSLT_DIR) \
|
||||
-I $(LIBXML2_DIR)include \
|
||||
$(LIBXSLT_DIR)tests/fuzz/xpath.c \
|
||||
$(LIBXSLT_DIR)tests/fuzz/fuzz.c \
|
||||
$(LIBXSLT_DIR)libxslt/.libs/libxslt.a \
|
||||
$(LIBXSLT_DIR)libexslt/.libs/libexslt.a \
|
||||
$(LIBXML2_LIB) \
|
||||
-lgcrypt
|
||||
|
||||
test: $(TEST_BIN)
|
||||
|
||||
|
||||
########## DUMMY #######
|
||||
|
||||
$(DUMMY_DATA_FILE): | $(TEST_DATA_DIR)
|
||||
dd if=/dev/zero bs=1048576 count=1 of=$@
|
||||
|
||||
###### TEST DATA #######
|
||||
|
||||
$(TEST_DATA_DIR): | $(LIBXSLT_DIR) $(BUILD_DIR)
|
||||
cp -av $(LIBXSLT_DIR)tests/fuzz/seed/* $@
|
||||
|
||||
$(XPATH_XML): | $(LIBXSLT_DIR)
|
||||
cp $(LIBXSLT_DIR)tests/fuzz/xpath.xml $@
|
||||
|
||||
|
||||
clean:
|
||||
rm -rf $(BUILD_DIR)
|
||||
|
||||
frida: $(TEST_BIN) $(AFLPP_FRIDA_DRIVER_HOOK_OBJ) $(TEST_DATA_FILE) $(DUMMY_DATA_FILE) $(XPATH_XML)
|
||||
AFL_FRIDA_PERSISTENT_CNT=1000000 \
|
||||
AFL_FRIDA_PERSISTENT_HOOK=$(AFLPP_FRIDA_DRIVER_HOOK_OBJ) \
|
||||
AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR) \
|
||||
AFL_ENTRYPOINT=$(AFL_FRIDA_PERSISTENT_ADDR) \
|
||||
$(ROOT)afl-fuzz \
|
||||
-i $(TEST_DATA_DIR) \
|
||||
-o $(FRIDA_OUT) \
|
||||
-m none \
|
||||
-d \
|
||||
-O \
|
||||
-V 30 \
|
||||
-- \
|
||||
$(TEST_BIN) $(DUMMY_DATA_FILE)
|
||||
|
||||
qemu: $(TEST_BIN) $(AFLPP_QEMU_DRIVER_HOOK_OBJ) $(TEST_DATA_FILE) $(DUMMY_DATA_FILE) $(XPATH_XML)
|
||||
AFL_QEMU_PERSISTENT_CNT=1000000 \
|
||||
AFL_QEMU_PERSISTENT_HOOK=$(AFLPP_QEMU_DRIVER_HOOK_OBJ) \
|
||||
AFL_QEMU_PERSISTENT_ADDR=$(AFL_QEMU_PERSISTENT_ADDR) \
|
||||
AFL_ENTRYPOINT=$(AFL_QEMU_PERSISTENT_ADDR) \
|
||||
$(ROOT)afl-fuzz \
|
||||
-i $(TEST_DATA_DIR) \
|
||||
-o $(QEMU_OUT) \
|
||||
-m none \
|
||||
-d \
|
||||
-Q \
|
||||
-V 30 \
|
||||
-- \
|
||||
$(TEST_BIN) $(DUMMY_DATA_FILE)
|
13
frida_mode/test/libxslt/Makefile
Normal file
@ -0,0 +1,13 @@
|
||||
all:
|
||||
@echo trying to use GNU make...
|
||||
@gmake all || echo please install GNUmake
|
||||
|
||||
32:
|
||||
@echo trying to use GNU make...
|
||||
@gmake 32 || echo please install GNUmake
|
||||
|
||||
clean:
|
||||
@gmake clean
|
||||
|
||||
frida:
|
||||
@gmake frida
|
@ -3,7 +3,7 @@
|
||||
--------------------------------------------------------
|
||||
Originally written by Michal Zalewski
|
||||
Copyright 2014 Google Inc. All rights reserved.
|
||||
Copyright 2019-2020 AFLplusplus Project. All rights reserved.
|
||||
Copyright 2019-2022 AFLplusplus Project. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
@ -14,6 +14,10 @@ FRIDA_OUT:=$(BUILD_DIR)frida-out
|
||||
AFLPP_FRIDA_DRIVER_HOOK_OBJ=$(ROOT)frida_mode/build/frida_hook.so
|
||||
AFLPP_QEMU_DRIVER_HOOK_OBJ=$(ROOT)frida_mode/build/qemu_hook.so
|
||||
|
||||
AFLPP_DRIVER_DUMMY_INPUT:=$(BUILD_DIR)dummy.dat
|
||||
QEMU_OUT:=$(BUILD_DIR)qemu-out
|
||||
FRIDA_OUT:=$(BUILD_DIR)frida-out
|
||||
|
||||
ifndef ARCH
|
||||
|
||||
ARCH=$(shell uname -m)
|
||||
@ -26,20 +30,22 @@ ifeq "$(ARCH)" "i686"
|
||||
endif
|
||||
endif
|
||||
|
||||
ADDR_BIN:=$(ROOT)frida_mode/build/addr
|
||||
GET_SYMBOL_ADDR:=$(ROOT)frida_mode/util/get_symbol_addr.sh
|
||||
|
||||
AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000)
|
||||
AFL_FRIDA_BASE_ADDR:=$(shell $(ADDR_BIN))
|
||||
AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput $(AFL_FRIDA_BASE_ADDR))
|
||||
|
||||
ifeq "$(ARCH)" "arm64"
|
||||
AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000aaaaaaaaa000)
|
||||
AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x5500000000)
|
||||
endif
|
||||
|
||||
ifeq "$(ARCH)" "x86_64"
|
||||
AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000555555554000)
|
||||
AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000)
|
||||
endif
|
||||
|
||||
ifeq "$(ARCH)" "x86"
|
||||
AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x56555000)
|
||||
AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000)
|
||||
endif
|
||||
|
||||
|
||||
@ -70,10 +76,13 @@ $(TEST_DATA_DIR): | $(BUILD_DIR)
|
||||
mkdir -p $@
|
||||
|
||||
$(TEST_DATA_FILE): | $(TEST_DATA_DIR)
|
||||
echo "hi" > $@
|
||||
|
||||
$(AFLPP_DRIVER_DUMMY_INPUT): | $(BUILD_DIR)
|
||||
dd if=/dev/zero bs=1048576 count=1 of=$@
|
||||
|
||||
|
||||
qemu: $(TEST_BIN) $(TEST_DATA_FILE)
|
||||
qemu: $(TEST_BIN) $(TEST_DATA_FILE) $(AFLPP_DRIVER_DUMMY_INPUT)
|
||||
AFL_QEMU_PERSISTENT_CNT=1000000 \
|
||||
AFL_QEMU_PERSISTENT_HOOK=$(AFLPP_QEMU_DRIVER_HOOK_OBJ) \
|
||||
AFL_QEMU_PERSISTENT_ADDR=$(AFL_QEMU_PERSISTENT_ADDR) \
|
||||
@ -86,9 +95,9 @@ qemu: $(TEST_BIN) $(TEST_DATA_FILE)
|
||||
-o $(QEMU_OUT) \
|
||||
-V 10 \
|
||||
-- \
|
||||
$(TEST_BIN) $(TEST_DATA_FILE)
|
||||
$(TEST_BIN) $(AFLPP_DRIVER_DUMMY_INPUT)
|
||||
|
||||
frida: $(TEST_BIN) $(TEST_DATA_FILE)
|
||||
frida: $(TEST_BIN) $(TEST_DATA_FILE) $(AFLPP_DRIVER_DUMMY_INPUT)
|
||||
AFL_FRIDA_PERSISTENT_CNT=1000000 \
|
||||
AFL_FRIDA_PERSISTENT_HOOK=$(AFLPP_FRIDA_DRIVER_HOOK_OBJ) \
|
||||
AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR) \
|
||||
@ -98,9 +107,9 @@ frida: $(TEST_BIN) $(TEST_DATA_FILE)
|
||||
-O \
|
||||
-i $(TEST_DATA_DIR) \
|
||||
-o $(FRIDA_OUT) \
|
||||
-V 10 \
|
||||
-t 1000+ \
|
||||
-- \
|
||||
$(TEST_BIN) $(TEST_DATA_FILE)
|
||||
$(TEST_BIN) $(AFLPP_DRIVER_DUMMY_INPUT)
|
||||
|
||||
debug:
|
||||
echo $(AFL_FRIDA_PERSISTENT_ADDR)
|
||||
|
@ -3,7 +3,7 @@
|
||||
--------------------------------------------------------
|
||||
Originally written by Michal Zalewski
|
||||
Copyright 2014 Google Inc. All rights reserved.
|
||||
Copyright 2019-2020 AFLplusplus Project. All rights reserved.
|
||||
Copyright 2019-2022 AFLplusplus Project. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
@ -22,27 +22,16 @@ ifeq "$(ARCH)" "i686"
|
||||
endif
|
||||
endif
|
||||
|
||||
ADDR_BIN:=$(ROOT)frida_mode/build/addr
|
||||
GET_SYMBOL_ADDR:=$(ROOT)frida_mode/util/get_symbol_addr.sh
|
||||
|
||||
ifeq "$(shell uname)" "Darwin"
|
||||
TEST_BIN_LDFLAGS:=-Wl,-no_pie
|
||||
endif
|
||||
|
||||
ARCH=$(shell uname -m)
|
||||
ifeq "$(ARCH)" "aarch64"
|
||||
AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TESTINSTBIN) main 0x0000aaaaaaaaa000)
|
||||
AFL_FRIDA_PERSISTENT_RET=$(shell $(GET_SYMBOL_ADDR) $(TESTINSTBIN) slow 0x0000aaaaaaaaa000)
|
||||
endif
|
||||
|
||||
ifeq "$(ARCH)" "x86_64"
|
||||
AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TESTINSTBIN) main 0x0000555555554000)
|
||||
AFL_FRIDA_PERSISTENT_RET=$(shell $(GET_SYMBOL_ADDR) $(TESTINSTBIN) slow 0x0000555555554000)
|
||||
endif
|
||||
|
||||
ifeq "$(ARCH)" "x86"
|
||||
AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TESTINSTBIN) main 0x56555000)
|
||||
AFL_FRIDA_PERSISTENT_RET=$(shell $(GET_SYMBOL_ADDR) $(TESTINSTBIN) slow 0x56555000)
|
||||
endif
|
||||
AFL_FRIDA_BASE_ADDR:=$(shell $(ADDR_BIN))
|
||||
AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TESTINSTBIN) main $(AFL_FRIDA_BASE_ADDR))
|
||||
AFL_FRIDA_PERSISTENT_RET=$(shell $(GET_SYMBOL_ADDR) $(TESTINSTBIN) slow $(AFL_FRIDA_BASE_ADDR))
|
||||
|
||||
ifeq "$(shell uname)" "Darwin"
|
||||
AFL_PRELOAD=/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation
|
||||
|
@ -3,7 +3,7 @@
|
||||
--------------------------------------------------------
|
||||
Originally written by Michal Zalewski
|
||||
Copyright 2014 Google Inc. All rights reserved.
|
||||
Copyright 2019-2020 AFLplusplus Project. All rights reserved.
|
||||
Copyright 2019-2022 AFLplusplus Project. All rights reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
@ -21,20 +21,22 @@ ifeq "$(ARCH)" "i686"
|
||||
endif
|
||||
endif
|
||||
|
||||
ADDR_BIN:=$(ROOT)frida_mode/build/addr
|
||||
GET_SYMBOL_ADDR:=$(ROOT)frida_mode/util/get_symbol_addr.sh
|
||||
|
||||
AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) main 0x4000000000)
|
||||
AFL_FRIDA_BASE_ADDR:=$(shell $(ADDR_BIN))
|
||||
AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput $(AFL_FRIDA_BASE_ADDR))
|
||||
|
||||
ifeq "$(ARCH)" "arm64"
|
||||
AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) main 0x0000aaaaaaaaa000)
|
||||
AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x5500000000)
|
||||
endif
|
||||
|
||||
ifeq "$(ARCH)" "x86_64"
|
||||
AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) main 0x0000555555554000)
|
||||
AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000)
|
||||
endif
|
||||
|
||||
ifeq "$(ARCH)" "x86"
|
||||
AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) main 0x56555000)
|
||||
AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000)
|
||||
endif
|
||||
|
||||
.PHONY: all 32 clean qemu qemu_entry frida frida_entry
|
||||
|
@ -32,20 +32,22 @@ ifeq "$(ARCH)" "i686"
|
||||
endif
|
||||
endif
|
||||
|
||||
ADDR_BIN:=$(ROOT)frida_mode/build/addr
|
||||
GET_SYMBOL_ADDR:=$(ROOT)frida_mode/util/get_symbol_addr.sh
|
||||
|
||||
AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000)
|
||||
AFL_FRIDA_BASE_ADDR:=$(shell $(ADDR_BIN))
|
||||
AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput $(AFL_FRIDA_BASE_ADDR))
|
||||
|
||||
ifeq "$(ARCH)" "arm64"
|
||||
AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000aaaaaaaaa000)
|
||||
AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x5500000000)
|
||||
endif
|
||||
|
||||
ifeq "$(ARCH)" "x86_64"
|
||||
AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000555555554000)
|
||||
AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000)
|
||||
endif
|
||||
|
||||
ifeq "$(ARCH)" "x86"
|
||||
AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x56555000)
|
||||
AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000)
|
||||
endif
|
||||
|
||||
ifeq "$(shell uname)" "Darwin"
|
||||
|