aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvan Hauser <vh@thc.org>2020-11-18 21:25:35 +0100
committerGitHub <noreply@github.com>2020-11-18 21:25:35 +0100
commit4d9eb9bda147a26fc8cbe885b6193cf0c94c6314 (patch)
treec7a903633c7d1b0b5e373535188fd3a458a7f329
parent4c59c5234aec0469e4dd02561dbd84387bd53155 (diff)
parentcd0a25be5e9b05a2ab6a11592cd95e7f653bf42d (diff)
downloadafl++-4d9eb9bda147a26fc8cbe885b6193cf0c94c6314.tar.gz
Merge pull request #607 from AFLplusplus/dev
push to stable
-rw-r--r--.gitmodules2
-rw-r--r--CONTRIBUTING.md4
-rw-r--r--README.md11
-rw-r--r--custom_mutators/honggfuzz/honggfuzz.c1
-rw-r--r--custom_mutators/libfuzzer/FuzzerIO.cpp7
-rw-r--r--custom_mutators/libfuzzer/FuzzerLoop.cpp13
-rw-r--r--custom_mutators/libfuzzer/FuzzerMutate.cpp24
-rw-r--r--custom_mutators/libfuzzer/FuzzerMutate.h1
-rw-r--r--custom_mutators/libfuzzer/Makefile5
-rw-r--r--custom_mutators/libfuzzer/libfuzzer.cpp13
-rw-r--r--custom_mutators/radamsa/radamsa-mutator.c1
-rw-r--r--custom_mutators/symcc/symcc.c124
-rw-r--r--custom_mutators/symcc/test_examples/file_test.c36
-rw-r--r--custom_mutators/symcc/test_examples/stdin_test.c28
-rw-r--r--docs/Changelog.md13
-rw-r--r--docs/custom_mutators.md13
-rw-r--r--docs/env_variables.md21
-rw-r--r--examples/afl_frida/afl-frida.c7
-rw-r--r--examples/afl_network_proxy/afl-network-server.c15
-rw-r--r--examples/custom_mutators/custom_mutator_helpers.h2
-rw-r--r--examples/custom_mutators/post_library_gif.so.c8
-rw-r--r--examples/custom_mutators/post_library_png.so.c8
-rw-r--r--examples/custom_mutators/simple_example.c2
-rw-r--r--examples/defork/forking_target.c1
-rw-r--r--include/afl-fuzz.h41
-rw-r--r--include/alloc-inl.h22
-rw-r--r--include/envs.h3
-rw-r--r--instrumentation/SanitizerCoveragePCGUARD.so.cc8
-rw-r--r--instrumentation/afl-compiler-rt.o.c6
-rw-r--r--qemu_mode/QEMUAFL_VERSION2
-rw-r--r--qemu_mode/libcompcov/pmparser.h8
-rw-r--r--src/afl-cc.c130
-rw-r--r--src/afl-common.c2
-rw-r--r--src/afl-forkserver.c17
-rw-r--r--src/afl-fuzz-bitmap.c91
-rw-r--r--src/afl-fuzz-init.c11
-rw-r--r--src/afl-fuzz-mutators.c7
-rw-r--r--src/afl-fuzz-one.c14
-rw-r--r--src/afl-fuzz-python.c78
-rw-r--r--src/afl-fuzz-queue.c7
-rw-r--r--src/afl-fuzz-run.c4
-rw-r--r--src/afl-fuzz-state.c6
-rw-r--r--src/afl-fuzz.c56
-rw-r--r--src/afl-gotcpu.c1
-rw-r--r--src/afl-showmap.c6
-rw-r--r--src/afl-tmin.c7
-rwxr-xr-xtest/test-unicorn-mode.sh6
-rw-r--r--unicorn_mode/samples/persistent/simple_target_noncrashing.c16
m---------unicorn_mode/unicornafl0
49 files changed, 712 insertions, 197 deletions
diff --git a/.gitmodules b/.gitmodules
index 3ad6e10c..7c7613ac 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -7,4 +7,4 @@
url = https://github.com/AFLplusplus/Grammar-Mutator
[submodule "qemu_mode/qemuafl"]
path = qemu_mode/qemuafl
- url = https://github.com/AFLplusplus/qemuafl.git
+ url = https://github.com/AFLplusplus/qemuafl
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index ccacef5f..c36ed9d8 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -16,9 +16,9 @@ project, or added a file in a directory we already format, otherwise run:
```
Regarding the coding style, please follow the AFL style.
-No camel case at all and use the AFL's macros wherever possible
+No camel case at all and use AFL's macros wherever possible
(e.g. WARNF, FATAL, MAP_SIZE, ...).
Remember that AFLplusplus has to build and run on many platforms, so
generalize your Makefiles/GNUmakefile (or your patches to our pre-existing
-Makefiles) to be as much generic as possible.
+Makefiles) to be as generic as possible.
diff --git a/README.md b/README.md
index d7c5694e..494a6bb7 100644
--- a/README.md
+++ b/README.md
@@ -22,8 +22,8 @@
afl++ is a superior fork to Google's afl - more speed, more and better
mutations, more and better instrumentation, custom module support, etc.
- If you want to use afl++ for you academic work, check the [papers page](https://aflplus.plus/papers/)
- in the website.
+ If you want to use afl++ for your academic work, check the [papers page](https://aflplus.plus/papers/)
+ on the website.
## Major changes in afl++ 3.0
@@ -585,7 +585,10 @@ For every secondary fuzzer there should be a variation, e.g.:
activated (`export AFL_USE_ASAN=1 ; export AFL_USE_UBSAN=1 ;
export AFL_USE_CFISAN=1 ; `
* one should fuzz the target with CMPLOG/redqueen (see above)
- * one to three should fuzz a target compiled with laf-intel/COMPCOV (see above).
+ * one to three fuzzers should fuzz a target compiled with laf-intel/COMPCOV
+ (see above). Important note: If you run more than one laf-intel/COMPCOV
+ fuzzer and you want them to share their intermediate results, the main
+ fuzzer (`-M`) must be one of the them!
All other secondaries should be used like this:
* A third to a half with the MOpt mutator enabled: `-L 0`
@@ -597,11 +600,11 @@ You can also use different fuzzers.
If you are using afl spinoffs or afl conforming fuzzers, then just use the
same -o directory and give it a unique `-S` name.
Examples are:
- * [Angora](https://github.com/AngoraFuzzer/Angora)
* [Untracer](https://github.com/FoRTE-Research/UnTracer-AFL)
* [AFLsmart](https://github.com/aflsmart/aflsmart)
* [FairFuzz](https://github.com/carolemieux/afl-rb)
* [Neuzz](https://github.com/Dongdongshe/neuzz)
+ * [Angora](https://github.com/AngoraFuzzer/Angora)
A long list can be found at [https://github.com/Microsvuln/Awesome-AFL](https://github.com/Microsvuln/Awesome-AFL)
diff --git a/custom_mutators/honggfuzz/honggfuzz.c b/custom_mutators/honggfuzz/honggfuzz.c
index bde922c6..b4f07258 100644
--- a/custom_mutators/honggfuzz/honggfuzz.c
+++ b/custom_mutators/honggfuzz/honggfuzz.c
@@ -37,6 +37,7 @@ my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
if ((data->mutator_buf = malloc(MAX_FILE)) == NULL) {
+ free(data);
perror("mutator_buf alloc");
return NULL;
diff --git a/custom_mutators/libfuzzer/FuzzerIO.cpp b/custom_mutators/libfuzzer/FuzzerIO.cpp
index e0c15db4..d8d52b63 100644
--- a/custom_mutators/libfuzzer/FuzzerIO.cpp
+++ b/custom_mutators/libfuzzer/FuzzerIO.cpp
@@ -83,6 +83,8 @@ void WriteToFile(const std::string &Data, const std::string &Path) {
void WriteToFile(const uint8_t *Data, size_t Size, const std::string &Path) {
+ return;
+
// Use raw C interface because this function may be called from a sig handler.
FILE *Out = fopen(Path.c_str(), "wb");
if (!Out) return;
@@ -93,6 +95,8 @@ void WriteToFile(const uint8_t *Data, size_t Size, const std::string &Path) {
void AppendToFile(const std::string &Data, const std::string &Path) {
+ return;
+
AppendToFile(reinterpret_cast<const uint8_t *>(Data.data()), Data.size(),
Path);
@@ -100,6 +104,8 @@ void AppendToFile(const std::string &Data, const std::string &Path) {
void AppendToFile(const uint8_t *Data, size_t Size, const std::string &Path) {
+ return;
+
FILE *Out = fopen(Path.c_str(), "a");
if (!Out) return;
fwrite(Data, sizeof(Data[0]), Size, Out);
@@ -182,6 +188,7 @@ void Printf(const char *Fmt, ...) {
void VPrintf(bool Verbose, const char *Fmt, ...) {
+ return;
if (!Verbose) return;
va_list ap;
va_start(ap, Fmt);
diff --git a/custom_mutators/libfuzzer/FuzzerLoop.cpp b/custom_mutators/libfuzzer/FuzzerLoop.cpp
index 201883f0..08fda520 100644
--- a/custom_mutators/libfuzzer/FuzzerLoop.cpp
+++ b/custom_mutators/libfuzzer/FuzzerLoop.cpp
@@ -206,6 +206,8 @@ void Fuzzer::StaticDeathCallback() {
void Fuzzer::DumpCurrentUnit(const char *Prefix) {
+ return;
+
if (!CurrentUnitData) return; // Happens when running individual inputs.
ScopedDisableMsanInterceptorChecks S;
MD.PrintMutationSequence();
@@ -733,6 +735,7 @@ std::string Fuzzer::WriteToOutputCorpus(const Unit &U) {
void Fuzzer::WriteUnitToFileWithPrefix(const Unit &U, const char *Prefix) {
+ return;
if (!Options.SaveArtifacts) return;
std::string Path = Options.ArtifactPrefix + Prefix + Hash(U);
if (!Options.ExactArtifactPath.empty())
@@ -1073,13 +1076,21 @@ void Fuzzer::MinimizeCrashLoop(const Unit &U) {
} // namespace fuzzer
+#ifdef INTROSPECTION
+ extern const char *introspection_ptr;
+#endif
+
extern "C" {
ATTRIBUTE_INTERFACE size_t LLVMFuzzerMutate(uint8_t *Data, size_t Size,
size_t MaxSize) {
assert(fuzzer::F);
- return fuzzer::F->GetMD().DefaultMutate(Data, Size, MaxSize);
+ size_t r = fuzzer::F->GetMD().DefaultMutate(Data, Size, MaxSize);
+#ifdef INTROSPECTION
+ introspection_ptr = fuzzer::F->GetMD().WriteMutationSequence();
+#endif
+ return r;
}
diff --git a/custom_mutators/libfuzzer/FuzzerMutate.cpp b/custom_mutators/libfuzzer/FuzzerMutate.cpp
index eebae39b..edfe0455 100644
--- a/custom_mutators/libfuzzer/FuzzerMutate.cpp
+++ b/custom_mutators/libfuzzer/FuzzerMutate.cpp
@@ -14,6 +14,8 @@
#include "FuzzerMutate.h"
#include "FuzzerOptions.h"
#include "FuzzerTracePC.h"
+#include <random>
+#include <chrono>
namespace fuzzer {
@@ -100,15 +102,17 @@ size_t MutationDispatcher::Mutate_CustomCrossOver(uint8_t *Data, size_t Size,
}
+
size_t MutationDispatcher::Mutate_ShuffleBytes(uint8_t *Data, size_t Size,
size_t MaxSize) {
-
if (Size > MaxSize || Size == 0) return 0;
size_t ShuffleAmount =
Rand(std::min(Size, (size_t)8)) + 1; // [1,8] and <= Size.
size_t ShuffleStart = Rand(Size - ShuffleAmount);
assert(ShuffleStart + ShuffleAmount <= Size);
- std::shuffle(Data + ShuffleStart, Data + ShuffleStart + ShuffleAmount, Rand);
+ unsigned num = std::chrono::system_clock::now().time_since_epoch().count();
+ std::shuffle(Data + ShuffleStart, Data + ShuffleStart + ShuffleAmount, std::default_random_engine(num));
+ //std::shuffle(Data + ShuffleStart, Data + ShuffleStart + ShuffleAmount, Rand);
return Size;
}
@@ -609,8 +613,24 @@ void MutationDispatcher::PrintRecommendedDictionary() {
}
+const char *MutationDispatcher::WriteMutationSequence() {
+
+ static std::string buf;
+ buf = "";
+
+ for (size_t i = 0; i < CurrentMutatorSequence.size(); i++) {
+
+ buf = buf + " " + CurrentMutatorSequence[i].Name;
+
+ }
+
+ return buf.c_str();
+
+}
+
void MutationDispatcher::PrintMutationSequence(bool Verbose) {
+ return;
Printf("MS: %zd ", CurrentMutatorSequence.size());
size_t EntriesToPrint =
Verbose ? CurrentMutatorSequence.size()
diff --git a/custom_mutators/libfuzzer/FuzzerMutate.h b/custom_mutators/libfuzzer/FuzzerMutate.h
index 37fd6100..6252f265 100644
--- a/custom_mutators/libfuzzer/FuzzerMutate.h
+++ b/custom_mutators/libfuzzer/FuzzerMutate.h
@@ -26,6 +26,7 @@ public:
void StartMutationSequence();
/// Print the current sequence of mutations. Only prints the full sequence
/// when Verbose is true.
+ const char *WriteMutationSequence();
void PrintMutationSequence(bool Verbose = true);
/// Return the current sequence of mutations.
std::string MutationSequence();
diff --git a/custom_mutators/libfuzzer/Makefile b/custom_mutators/libfuzzer/Makefile
index 95402f6c..51263b89 100644
--- a/custom_mutators/libfuzzer/Makefile
+++ b/custom_mutators/libfuzzer/Makefile
@@ -3,6 +3,11 @@ CFLAGS = -g -O3 -funroll-loops -fPIC -fpermissive -std=c++11
#CFLAGS = -g -O0 -fPIC -fpermissive -std=c++11
CXX ?= clang++
+ifdef INTROSPECTION
+ $(info Compiling with introspection documentation)
+ CFLAGS += -DINTROSPECTION=1
+endif
+
all: libfuzzer-mutator.so
FuzzerCrossOver.o: FuzzerCrossOver.cpp
diff --git a/custom_mutators/libfuzzer/libfuzzer.cpp b/custom_mutators/libfuzzer/libfuzzer.cpp
index 5e37df66..dc1fbeb2 100644
--- a/custom_mutators/libfuzzer/libfuzzer.cpp
+++ b/custom_mutators/libfuzzer/libfuzzer.cpp
@@ -6,6 +6,10 @@
//#include "debug.h"
#include "afl-fuzz.h"
+#ifdef INTROSPECTION
+ const char *introspection_ptr;
+#endif
+
afl_state_t *afl_struct;
extern "C" size_t LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize);
@@ -46,6 +50,7 @@ extern "C" my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
if ((data->mutator_buf = (u8 *)malloc(MAX_FILE)) == NULL) {
+ free(data);
perror("mutator_buf alloc");
return NULL;
@@ -133,6 +138,14 @@ extern "C" size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf,
}
+#ifdef INTROSPECTION
+extern "C" const char* afl_custom_introspection(my_mutator_t *data) {
+
+ return introspection_ptr;
+
+}
+#endif
+
/**
* Deinitialize everything
*
diff --git a/custom_mutators/radamsa/radamsa-mutator.c b/custom_mutators/radamsa/radamsa-mutator.c
index 82d28001..624ace3d 100644
--- a/custom_mutators/radamsa/radamsa-mutator.c
+++ b/custom_mutators/radamsa/radamsa-mutator.c
@@ -33,6 +33,7 @@ my_mutator_t *afl_custom_init(afl_t *afl, unsigned int seed) {
if ((data->mutator_buf = malloc(MAX_FILE)) == NULL) {
+ free(data);
perror("mutator_buf alloc");
return NULL;
diff --git a/custom_mutators/symcc/symcc.c b/custom_mutators/symcc/symcc.c
index 18b475b8..a609dafb 100644
--- a/custom_mutators/symcc/symcc.c
+++ b/custom_mutators/symcc/symcc.c
@@ -1,7 +1,10 @@
+#define _GNU_SOURCE
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
#include "config.h"
#include "debug.h"
#include "afl-fuzz.h"
@@ -21,6 +24,7 @@ typedef struct my_mutator {
afl_state_t *afl;
u8 * mutator_buf;
u8 * out_dir;
+ u8 * tmp_dir;
u8 * target;
uint32_t seed;
@@ -41,6 +45,7 @@ my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
if ((data->mutator_buf = malloc(MAX_FILE)) == NULL) {
+ free(data);
perror("mutator_buf alloc");
return NULL;
@@ -54,10 +59,11 @@ my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
if (!(data->out_dir = getenv("SYMCC_OUTPUT_DIR"))) {
data->out_dir = alloc_printf("%s/symcc", afl->out_dir);
- setenv("SYMCC_OUTPUT_DIR", data->out_dir, 1);
}
+ data->tmp_dir = alloc_printf("%s/tmp", data->out_dir);
+ setenv("SYMCC_OUTPUT_DIR", data->tmp_dir, 1);
int pid = fork();
if (pid == -1) return NULL;
@@ -83,6 +89,10 @@ my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
if (mkdir(data->out_dir, 0755))
PFATAL("Could not create directory %s", data->out_dir);
+
+ if (mkdir(data->tmp_dir, 0755))
+ PFATAL("Could not create directory %s", data->tmp_dir);
+
DBG("out_dir=%s, target=%s\n", data->out_dir, data->target);
return data;
@@ -95,33 +105,119 @@ void afl_custom_queue_new_entry(my_mutator_t * data,
const uint8_t *filename_new_queue,
const uint8_t *filename_orig_queue) {
- int pid = fork();
+ int pipefd[2];
+ struct stat st;
+ ACTF("Queueing to symcc: %s", filename_new_queue);
+ u8 *fn = alloc_printf("%s", filename_new_queue);
+ if (!(stat(fn, &st) == 0 && S_ISREG(st.st_mode) && st.st_size)) {
- if (pid == -1) return;
+ ck_free(fn);
+ PFATAL("Couldn't find enqueued file: %s", fn);
- if (pid) pid = waitpid(pid, NULL, 0);
+ }
- if (pid == 0) {
+ if (afl_struct->fsrv.use_stdin) {
+
+ if (pipe(pipefd) == -1) {
+
+ ck_free(fn);
+ PFATAL("Couldn't create a pipe for interacting with symcc child process");
+
+ }
+
+ }
+
+ int pid = fork();
- setenv("SYMCC_INPUT_FILE", afl_struct->fsrv.out_file, 1);
+ if (pid == -1) return;
+
+ if (pid) {
if (afl_struct->fsrv.use_stdin) {
- u8 *fn = alloc_printf("%s/%s", afl_struct->out_dir, filename_new_queue);
+ close(pipefd[0]);
int fd = open(fn, O_RDONLY);
if (fd >= 0) {
ssize_t r = read(fd, data->mutator_buf, MAX_FILE);
- close(fd);
DBG("fn=%s, fd=%d, size=%ld\n", fn, fd, r);
- if (r <= 0) return;
- close(0);
- ck_write(0, data->mutator_buf, r, fn);
ck_free(fn);
+ close(fd);
+ if (r <= 0) {
+
+ close(pipefd[1]);
+ return;
+
+ }
+
+ if (r > fcntl(pipefd[1], F_GETPIPE_SZ))
+ fcntl(pipefd[1], F_SETPIPE_SZ, MAX_FILE);
+ ck_write(pipefd[1], data->mutator_buf, r, filename_new_queue);
+
+ } else {
+
+ ck_free(fn);
+ close(pipefd[1]);
+ PFATAL(
+ "Something happened to the enqueued file before sending its "
+ "contents to symcc binary");
}
+ close(pipefd[1]);
+
+ }
+
+ pid = waitpid(pid, NULL, 0);
+
+ // At this point we need to transfer files to output dir, since their names
+ // collide and symcc will just overwrite them
+
+ struct dirent **nl;
+ int32_t items = scandir(data->tmp_dir, &nl, NULL, NULL);
+ u8 * origin_name = basename(filename_new_queue);
+ int32_t i;
+ if (items > 0) {
+
+ for (i = 0; i < (u32)items; ++i) {
+
+ struct stat st;
+ u8 *source_name = alloc_printf("%s/%s", data->tmp_dir, nl[i]->d_name);
+ DBG("test=%s\n", fn);
+ if (stat(source_name, &st) == 0 && S_ISREG(st.st_mode) && st.st_size) {
+
+ u8 *destination_name =
+ alloc_printf("%s/%s.%s", data->out_dir, origin_name, nl[i]->d_name);
+ rename(source_name, destination_name);
+ ck_free(destination_name);
+ DBG("found=%s\n", source_name);
+
+ }
+
+ ck_free(source_name);
+ free(nl[i]);
+
+ }
+
+ free(nl);
+
+ }
+
+ }
+
+ if (pid == 0) {
+
+ if (afl_struct->fsrv.use_stdin) {
+
+ unsetenv("SYMCC_INPUT_FILE");
+ close(pipefd[1]);
+ dup2(pipefd[0], 0);
+
+ } else {
+
+ setenv("SYMCC_INPUT_FILE", afl_struct->fsrv.out_file, 1);
+
}
DBG("exec=%s\n", data->target);
@@ -129,6 +225,7 @@ void afl_custom_queue_new_entry(my_mutator_t * data,
close(2);
dup2(afl_struct->fsrv.dev_null_fd, 1);
dup2(afl_struct->fsrv.dev_null_fd, 2);
+
execvp(data->target, afl_struct->argv);
DBG("exec=FAIL\n");
exit(-1);
@@ -179,7 +276,7 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
struct dirent **nl;
int32_t i, done = 0, items = scandir(data->out_dir, &nl, NULL, NULL);
- size_t size = 0;
+ ssize_t size = 0;
if (items <= 0) return 0;
@@ -198,6 +295,7 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
size = read(fd, data->mutator_buf, max_size);
*out_buf = data->mutator_buf;
+
close(fd);
done = 1;
@@ -216,7 +314,7 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
free(nl);
DBG("FUZZ size=%lu\n", size);
- return size;
+ return (uint32_t)size;
}
diff --git a/custom_mutators/symcc/test_examples/file_test.c b/custom_mutators/symcc/test_examples/file_test.c
new file mode 100644
index 00000000..f2b92986
--- /dev/null
+++ b/custom_mutators/symcc/test_examples/file_test.c
@@ -0,0 +1,36 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+int main(int argc, char **argv) {
+
+ if (argc < 2) {
+
+ printf("Need a file argument\n");
+ return 1;
+
+ }
+
+ int fd = open(argv[1], O_RDONLY);
+ if (fd < 0) {
+
+ printf("Couldn't open file\n");
+ return 1;
+
+ }
+
+ uint32_t value = 0;
+
+ read(fd, &value, sizeof(value));
+ close(fd);
+
+ value = value ^ 0xffffffff;
+ if (value == 0x11223344) printf("Value one\n");
+ if (value == 0x44332211) printf("Value two\n");
+ if (value != 0x0) printf("Not zero\n");
+ return 0;
+
+}
+
diff --git a/custom_mutators/symcc/test_examples/stdin_test.c b/custom_mutators/symcc/test_examples/stdin_test.c
new file mode 100644
index 00000000..3acfc523
--- /dev/null
+++ b/custom_mutators/symcc/test_examples/stdin_test.c
@@ -0,0 +1,28 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+int main(int argc, char **argv) {
+
+ char input_buffer[16];
+ uint32_t comparisonValue;
+ size_t bytesRead;
+ bytesRead = read(STDIN_FILENO, input_buffer, sizeof(input_buffer));
+ if (bytesRead < 0) exit(-1);
+ comparisonValue = *(uint32_t *)input_buffer;
+ comparisonValue = comparisonValue ^ 0xff112233;
+ if (comparisonValue == 0x66554493) {
+
+ printf("First value\n");
+
+ } else {
+
+ if (comparisonValue == 0x84444415) printf("Second value\n");
+
+ }
+
+ return 0;
+
+}
+
diff --git a/docs/Changelog.md b/docs/Changelog.md
index 50c1d48a..9426ed54 100644
--- a/docs/Changelog.md
+++ b/docs/Changelog.md
@@ -38,22 +38,27 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
- added INTROSPECTION make target that writes all mutations to
out/NAME/introspection.txt
- print special compile time options used in help output
+ - somewhere we broke -n dumb fuzzing, fixed
- instrumentation
- We received an enhanced gcc_plugin module from AdaCore, thank you
very much!!
- not overriding -Ox or -fno-unroll-loops anymore
- we now have our own trace-pc-guard implementation. It is the same as
-fsanitize-coverage=trace-pc-guard from llvm 12, but: it is a) inline
- and b) works from llvm 10+ on :)
+ and b) works from llvm 10.0.1 + onwards :)
- new llvm pass: dict2file via AFL_LLVM_DICT2FILE, create afl-fuzz
-x dictionary of string comparisons found during compilation
- LTO autodict now also collects interesting cmp comparisons,
std::string compare + find + ==, bcmp
- fix crash in dict2file for integers > 64 bit
+ - custom mutators
+ - added a new custom mutator: symcc -> https://github.com/eurecom-s3/symcc/
+ - added a new custom mutator: libfuzzer that integrates libfuzzer mutations
+ - Our afl++ Grammar-Mutator is now better integrated into custom_mutators/
+ - added INTROSPECTION support for custom modules
+ - python fuzz function was not optional, fixed
- unicornafl synced with upstream (arm64 fix, better rust bindings)
- - added a new custom mutator: symcc -> https://github.com/eurecom-s3/symcc/
- - added a new custom mutator: libfuzzer that integrates libfuzzer mutations
- - Our afl++ Grammar-Mutator is now better integrated into custom_mutators/
+ - renamed AFL_DEBUG_CHILD_OUTPUT to AFL_DEBUG_CHILD
### Version ++2.68c (release)
diff --git a/docs/custom_mutators.md b/docs/custom_mutators.md
index 81ee9de4..53f783fe 100644
--- a/docs/custom_mutators.md
+++ b/docs/custom_mutators.md
@@ -42,6 +42,7 @@ size_t afl_custom_havoc_mutation(void *data, unsigned char *buf, size_t buf_size
unsigned char afl_custom_havoc_mutation_probability(void *data);
unsigned char afl_custom_queue_get(void *data, const unsigned char *filename);
void afl_custom_queue_new_entry(void *data, const unsigned char *filename_new_queue, const unsigned int *filename_orig_queue);
+const char* afl_custom_introspection(my_mutator_t *data);
void afl_custom_deinit(void *data);
```
@@ -81,6 +82,9 @@ def queue_new_entry(filename_new_queue, filename_orig_queue):
pass
```
+def introspection():
+ return string
+
### Custom Mutation
- `init`:
@@ -126,10 +130,19 @@ def queue_new_entry(filename_new_queue, filename_orig_queue):
`post_process` function. This function is then transforming the data into the
format expected by the API before executing the target.
+ This can return any python object that implements the buffer protocol and
+ supports PyBUF_SIMPLE. These include bytes, bytearray, etc.
+
- `queue_new_entry` (optional):
This methods is called after adding a new test case to the queue.
+- `introspection` (optional):
+
+ This method is called after a new queue entry, crash or timeout is
+ discovered if compiled with INTROSPECTION. The custom mutator can then
+ return a string (const char *) that reports the exact mutations used.
+
- `deinit`:
The last method to be called, deinitializing the state.
diff --git a/docs/env_variables.md b/docs/env_variables.md
index a36f2b4e..04ba032a 100644
--- a/docs/env_variables.md
+++ b/docs/env_variables.md
@@ -306,6 +306,14 @@ checks or alter some of the more exotic semantics of the tool:
don't want AFL++ to spend too much time classifying that stuff and just
rapidly put all timeouts in that bin.
+ - Setting `AFL_FORKSRV_INIT_TMOUT` allows you to specify a different timeout
+ to wait for the forkserver to spin up. The default is the `-t` value times
+ `FORK_WAIT_MULT` from `config.h` (usually 10), so for a `-t 100`, the
+ default would wait for `1000` milliseconds. Setting a different time here is useful
+ if the target has a very slow startup time, for example when doing
+ full-system fuzzing or emulation, but you don't want the actual runs
+ to wait too long for timeouts.
+
- `AFL_NO_ARITH` causes AFL++ to skip most of the deterministic arithmetics.
This can be useful to speed up the fuzzing of text-based file formats.
@@ -380,8 +388,12 @@ checks or alter some of the more exotic semantics of the tool:
processing the first queue entry; and `AFL_BENCH_UNTIL_CRASH` causes it to
exit soon after the first crash is found.
- - Setting `AFL_DEBUG_CHILD_OUTPUT` will not suppress the child output.
+ - Setting `AFL_DEBUG_CHILD` will not suppress the child output.
+ This lets you see all output of the child, making setup issues obvious.
+ For example, in an unicornafl harness, you might see python stacktraces.
+ You may also see other logs that way, indicating why the forkserver won't start.
Not pretty but good for debugging purposes.
+ Note that `AFL_DEBUG_CHILD_OUTPUT` is deprecated.
- Setting `AFL_NO_CPU_RED` will not display very high cpu usages in red color.
@@ -389,6 +401,13 @@ checks or alter some of the more exotic semantics of the tool:
for an existing out folder, even if a different `-i` was provided.
Without this setting, afl-fuzz will refuse execution for a long-fuzzed out dir.
+ - Setting `AFL_MAX_DET_EXRAS` 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 entires will be used all
+ of the times for fuzzing mutations to not slow down fuzzing.
+ The default count is `200` elements. So for the 200 + 1st element, there is a
+ 1 in 201 chance, that one of the dictionary entries will not be used directly.
+
- Setting `AFL_NO_FORKSRV` disables the forkserver optimization, reverting to
fork + execve() call for every tested input. This is useful mostly when
working with unruly libraries that create threads or do other crazy
diff --git a/examples/afl_frida/afl-frida.c b/examples/afl_frida/afl-frida.c
index 2ad5a72a..31bf8f25 100644
--- a/examples/afl_frida/afl-frida.c
+++ b/examples/afl_frida/afl-frida.c
@@ -6,7 +6,7 @@
Written mostly by meme -> https://github.com/meme/hotwax
- Modificationy by Marc Heuse <mh@mh-sec.de>
+ Modifications by Marc Heuse <mh@mh-sec.de>
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -504,11 +504,12 @@ int main() {
previous_pc = 0; // Required!
#ifdef _DEBUG
- fprintf(stderr, "CLIENT crc: %016llx len: %u\n", hash64(__afl_fuzz_ptr, *__a
+ fprintf(stderr, "CLIENT crc: %016llx len: %u\n",
+ hash64(__afl_fuzz_ptr, *__afl_fuzz_len), *__afl_fuzz_len);
fprintf(stderr, "RECV:");
for (int i = 0; i < *__afl_fuzz_len; i++)
fprintf(stderr, "%02x", __afl_fuzz_ptr[i]);
- fprintf(stderr,"\n");
+ fprintf(stderr, "\n");
#endif
// STEP 3: ensure the minimum length is present and setup the target
diff --git a/examples/afl_network_proxy/afl-network-server.c b/examples/afl_network_proxy/afl-network-server.c
index 75eb3d20..513dc8f2 100644
--- a/examples/afl_network_proxy/afl-network-server.c
+++ b/examples/afl_network_proxy/afl-network-server.c
@@ -358,8 +358,8 @@ int recv_testcase(int s, void **buf) {
if ((size & 0xff000000) != 0xff000000) {
- *buf = afl_realloc((void **)&buf, size);
- if (unlikely(!buf)) { PFATAL("Alloc"); }
+ *buf = afl_realloc(buf, size);
+ if (unlikely(!*buf)) { PFATAL("Alloc"); }
received = 0;
// fprintf(stderr, "unCOMPRESS (%u)\n", size);
while (received < size &&
@@ -371,8 +371,8 @@ int recv_testcase(int s, void **buf) {
#ifdef USE_DEFLATE
u32 clen;
size -= 0xff000000;
- *buf = afl_realloc((void **)&buf, size);
- if (unlikely(!buf)) { PFATAL("Alloc"); }
+ *buf = afl_realloc(buf, size);
+ if (unlikely(!*buf)) { PFATAL("Alloc"); }
received = 0;
while (received < 4 &&
(ret = recv(s, &clen + received, 4 - received, 0)) > 0)
@@ -636,8 +636,11 @@ int main(int argc, char **argv_orig, char **envp) {
if (listen(sock, 1) < 0) { PFATAL("listen() failed"); }
- afl_fsrv_start(fsrv, use_argv, &stop_soon,
- get_afl_env("AFL_DEBUG_CHILD_OUTPUT") ? 1 : 0);
+ afl_fsrv_start(
+ fsrv, use_argv, &stop_soon,
+ (get_afl_env("AFL_DEBUG_CHILD") || get_afl_env("AFL_DEBUG_CHILD_OUTPUT"))
+ ? 1
+ : 0);
#ifdef USE_DEFLATE
compressor = libdeflate_alloc_compressor(1);
diff --git a/examples/custom_mutators/custom_mutator_helpers.h b/examples/custom_mutators/custom_mutator_helpers.h
index ad5acb08..62e6efba 100644
--- a/examples/custom_mutators/custom_mutator_helpers.h
+++ b/examples/custom_mutators/custom_mutator_helpers.h
@@ -13,7 +13,7 @@
#define BUF_VAR(type, name) \
type * name##_buf; \
size_t name##_size;
-/* this filles in `&structptr->something_buf, &structptr->something_size`. */
+/* this fills in `&structptr->something_buf, &structptr->something_size`. */
#define BUF_PARAMS(struct, name) \
(void **)&struct->name##_buf, &struct->name##_size
diff --git a/examples/custom_mutators/post_library_gif.so.c b/examples/custom_mutators/post_library_gif.so.c
index 2d72400c..ac10f409 100644
--- a/examples/custom_mutators/post_library_gif.so.c
+++ b/examples/custom_mutators/post_library_gif.so.c
@@ -94,7 +94,13 @@ void *afl_custom_init(void *afl) {
}
state->buf = calloc(sizeof(unsigned char), 4096);
- if (!state->buf) { return NULL; }
+ if (!state->buf) {
+
+ free(state);
+ perror("calloc");
+ return NULL;
+
+ }
return state;
diff --git a/examples/custom_mutators/post_library_png.so.c b/examples/custom_mutators/post_library_png.so.c
index 7c1ea93e..941f7e55 100644
--- a/examples/custom_mutators/post_library_png.so.c
+++ b/examples/custom_mutators/post_library_png.so.c
@@ -54,7 +54,13 @@ void *afl_custom_init(void *afl) {
}
state->buf = calloc(sizeof(unsigned char), 4096);
- if (!state->buf) { return NULL; }
+ if (!state->buf) {
+
+ free(state);
+ perror("calloc");
+ return NULL;
+
+ }
return state;
diff --git a/examples/custom_mutators/simple_example.c b/examples/custom_mutators/simple_example.c
index a351d787..d888ec1f 100644
--- a/examples/custom_mutators/simple_example.c
+++ b/examples/custom_mutators/simple_example.c
@@ -8,7 +8,7 @@
#include <stdio.h>
#ifndef _FIXED_CHAR
- #define 0x41
+ #define _FIXED_CHAR 0x41
#endif
typedef struct my_mutator {
diff --git a/examples/defork/forking_target.c b/examples/defork/forking_target.c
index 98f6365a..628d23c9 100644
--- a/examples/defork/forking_target.c
+++ b/examples/defork/forking_target.c
@@ -26,6 +26,7 @@ int main(int argc, char **argv) {
FILE *f = fopen(argv[1], "r");
char buf[4096];
fread(buf, 1, 4096, f);
+ fclose(f);
uint32_t offset = buf[100] + (buf[101] << 8);
char test_val = buf[offset];
return test_val < 100;
diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h
index e59d5f90..933af65d 100644
--- a/include/afl-fuzz.h
+++ b/include/afl-fuzz.h
@@ -113,6 +113,7 @@
#include <kstat.h>
#include <sys/sysinfo.h>
#include <sys/pset.h>
+ #include <strings.h>
#endif
#endif /* __linux__ */
@@ -310,6 +311,7 @@ enum {
/* 09 */ PY_FUNC_HAVOC_MUTATION_PROBABILITY,
/* 10 */ PY_FUNC_QUEUE_GET,
/* 11 */ PY_FUNC_QUEUE_NEW_ENTRY,
+ /* 12 */ PY_FUNC_INTROSPECTION,
PY_FUNC_COUNT
};
@@ -324,8 +326,7 @@ typedef struct py_mutator {
u8 * fuzz_buf;
size_t fuzz_size;
- u8 * post_process_buf;
- size_t post_process_size;
+ Py_buffer post_process_buf;
u8 * trim_buf;
size_t trim_size;
@@ -361,8 +362,8 @@ typedef struct afl_env_vars {
u8 afl_skip_cpufreq, afl_exit_when_done, afl_no_affinity, afl_skip_bin_check,
afl_dumb_forksrv, afl_import_first, afl_custom_mutator_only, afl_no_ui,
afl_force_ui, afl_i_dont_care_about_missing_crashes, afl_bench_just_one,
- afl_bench_until_crash, afl_debug_child_output, afl_autoresume,
- afl_cal_fast, afl_cycle_schedules, afl_expand_havoc, afl_statsd;
+ afl_bench_until_crash, afl_debug_child, afl_autoresume, afl_cal_fast,
+ afl_cycle_schedules, afl_expand_havoc, afl_statsd;
u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path,
*afl_hang_tmout, *afl_forksrv_init_tmout, *afl_skip_crashes, *afl_preload,
@@ -684,6 +685,8 @@ typedef struct afl_state {
u32 custom_mutators_count;
+ struct custom_mutator *current_custom_fuzz;
+
list_t custom_mutator_list;
/* this is a fixed buffer of size map_size that can be used by any function if
@@ -748,6 +751,15 @@ struct custom_mutator {
void *(*afl_custom_init)(afl_state_t *afl, unsigned int seed);
/**
+ * When afl-fuzz was compiled with INTROSPECTION=1 then custom mutators can
+ * also give introspection information back with this function.
+ *
+ * @param data pointer returned in afl_custom_init for this fuzz case
+ * @return pointer to a text string (const char*)
+ */
+ const char *(*afl_custom_introspection)(void *data);
+
+ /**
* This method is called just before fuzzing a queue entry with the custom
* mutator, and receives the initial buffer. It should return the number of
* fuzzes to perform.
@@ -953,16 +965,17 @@ u8 trim_case_custom(afl_state_t *, struct queue_entry *q, u8 *in_buf,
struct custom_mutator *load_custom_mutator_py(afl_state_t *, char *);
void finalize_py_module(void *);
-u32 fuzz_count_py(void *, const u8 *, size_t);
-size_t post_process_py(void *, u8 *, size_t, u8 **);
-s32 init_trim_py(void *, u8 *, size_t);
-s32 post_trim_py(void *, u8);
-size_t trim_py(void *, u8 **);
-size_t havoc_mutation_py(void *, u8 *, size_t, u8 **, size_t);
-u8 havoc_mutation_probability_py(void *);
-u8 queue_get_py(void *, const u8 *);
-void queue_new_entry_py(void *, const u8 *, const u8 *);
-void deinit_py(void *);
+u32 fuzz_count_py(void *, const u8 *, size_t);
+size_t post_process_py(void *, u8 *, size_t, u8 **);
+s32 init_trim_py(void *, u8 *, size_t);
+s32 post_trim_py(void *, u8);
+size_t trim_py(void *, u8 **);
+size_t havoc_mutation_py(void *, u8 *, size_t, u8 **, size_t);
+u8 havoc_mutation_probability_py(void *);
+u8 queue_get_py(void *, const u8 *);
+const char *introspection_py(void *);
+void queue_new_entry_py(void *, const u8 *, const u8 *);
+void deinit_py(void *);
#endif
diff --git a/include/alloc-inl.h b/include/alloc-inl.h
index d7aa51a7..68255fb6 100644
--- a/include/alloc-inl.h
+++ b/include/alloc-inl.h
@@ -636,7 +636,7 @@ struct afl_alloc_buf {
#define AFL_ALLOC_SIZE_OFFSET (offsetof(struct afl_alloc_buf, buf))
-/* Returs the container element to this ptr */
+/* Returns the container element to this ptr */
static inline struct afl_alloc_buf *afl_alloc_bufptr(void *buf) {
return (struct afl_alloc_buf *)((u8 *)buf - AFL_ALLOC_SIZE_OFFSET);
@@ -694,12 +694,18 @@ static inline void *afl_realloc(void **buf, size_t size_needed) {
}
/* alloc */
- new_buf = (struct afl_alloc_buf *)realloc(new_buf, next_size);
- if (unlikely(!new_buf)) {
+ struct afl_alloc_buf *newer_buf =
+ (struct afl_alloc_buf *)realloc(new_buf, next_size);
+ if (unlikely(!newer_buf)) {
+ free(new_buf); // avoid a leak
*buf = NULL;
return NULL;
+ } else {
+
+ new_buf = newer_buf;
+
}
new_buf->complete_size = next_size;
@@ -730,12 +736,18 @@ static inline void *afl_realloc_exact(void **buf, size_t size_needed) {
if (unlikely(current_size == size_needed)) { return *buf; }
/* alloc */
- new_buf = (struct afl_alloc_buf *)realloc(new_buf, size_needed);
- if (unlikely(!new_buf)) {
+ struct afl_alloc_buf *newer_buf =
+ (struct afl_alloc_buf *)realloc(new_buf, size_needed);
+ if (unlikely(!newer_buf)) {
+ free(new_buf); // avoid a leak
*buf = NULL;
return NULL;
+ } else {
+
+ new_buf = newer_buf;
+
}
new_buf->complete_size = size_needed;
diff --git a/include/envs.h b/include/envs.h
index b753d5f8..8255cf4f 100644
--- a/include/envs.h
+++ b/include/envs.h
@@ -6,6 +6,7 @@ static char *afl_environment_deprecated[] = {
"AFL_LLVM_WHITELIST",
"AFL_GCC_WHITELIST",
+ "AFL_DEBUG_CHILD_OUTPUT",
"AFL_DEFER_FORKSRV",
"AFL_POST_LIBRARY",
"AFL_PERSISTENT",
@@ -36,7 +37,7 @@ static char *afl_environment_variables[] = {
"AFL_CXX",
"AFL_CYCLE_SCHEDULES",
"AFL_DEBUG",
- "AFL_DEBUG_CHILD_OUTPUT",
+ "AFL_DEBUG_CHILD",
"AFL_DEBUG_GDB",
"AFL_DISABLE_TRIM",
"AFL_DONT_OPTIMIZE",
diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc
index b3c55108..e85f9cd3 100644
--- a/instrumentation/SanitizerCoveragePCGUARD.so.cc
+++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc
@@ -544,7 +544,9 @@ bool ModuleSanitizerCoverage::instrumentModule(
be_quiet = 1;
skip_nozero = getenv("AFL_LLVM_SKIP_NEVERZERO");
- // scanForDangerousFunctions(&M);
+
+ initInstrumentList();
+ scanForDangerousFunctions(&M);
if (debug) {
@@ -819,6 +821,8 @@ void ModuleSanitizerCoverage::instrumentFunction(
Function &F, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) {
if (F.empty()) return;
+ if (!isInInstrumentList(&F)) return;
+
if (F.getName().find(".module_ctor") != std::string::npos)
return; // Should not instrument sanitizer init functions.
if (F.getName().startswith("__sanitizer_"))
@@ -1315,6 +1319,7 @@ std::string ModuleSanitizerCoverage::getSectionEnd(
}
char ModuleSanitizerCoverageLegacyPass::ID = 0;
+
INITIALIZE_PASS_BEGIN(ModuleSanitizerCoverageLegacyPass, "sancov",
"Pass for instrumenting coverage on functions", false,
false)
@@ -1323,6 +1328,7 @@ INITIALIZE_PASS_DEPENDENCY(PostDominatorTreeWrapperPass)
INITIALIZE_PASS_END(ModuleSanitizerCoverageLegacyPass, "sancov",
"Pass for instrumenting coverage on functions", false,
false)
+
ModulePass *llvm::createModuleSanitizerCoverageLegacyPassPass(
const SanitizerCoverageOptions &Options,
const std::vector<std::string> &AllowlistFiles,
diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c
index f38af668..485f500c 100644
--- a/instrumentation/afl-compiler-rt.o.c
+++ b/instrumentation/afl-compiler-rt.o.c
@@ -123,7 +123,7 @@ void __afl_trace(const u32 x) {
u8 c = __builtin_add_overflow(*p, 1, p);
*p += c;
#else
- *p += 1 + ((u8)(1 + *p == 0);
+ *p += 1 + ((u8)(1 + *p) == 0);
#endif
#else
++*p;
@@ -182,7 +182,7 @@ static void __afl_map_shm_fuzz() {
if (!map || map == (void *)-1) {
- perror("Could not access fuzzign shared memory");
+ perror("Could not access fuzzing shared memory");
exit(1);
}
@@ -992,7 +992,7 @@ void __sanitizer_cov_trace_pc_guard(uint32_t *guard) {
// For stability analysis, if you want to know to which function unstable
// edge IDs belong - uncomment, recompile+install llvm_mode, recompile
// the target. libunwind and libbacktrace are better solutions.
- // Set AFL_DEBUG_CHILD_OUTPUT=1 and run afl-fuzz with 2>file to capture
+ // Set AFL_DEBUG_CHILD=1 and run afl-fuzz with 2>file to capture
// the backtrace output
/*
uint32_t unstable[] = { ... unstable edge IDs };
diff --git a/qemu_mode/QEMUAFL_VERSION b/qemu_mode/QEMUAFL_VERSION
index 75883247..43403430 100644
--- a/qemu_mode/QEMUAFL_VERSION
+++ b/qemu_mode/QEMUAFL_VERSION
@@ -1 +1 @@
-21ff343837
+d66c9e2654
diff --git a/qemu_mode/libcompcov/pmparser.h b/qemu_mode/libcompcov/pmparser.h
index 9421d47e..0eb4fb1d 100644
--- a/qemu_mode/libcompcov/pmparser.h
+++ b/qemu_mode/libcompcov/pmparser.h
@@ -108,8 +108,7 @@ void pmparser_print(procmaps_struct *map, int order);
procmaps_iterator *pmparser_parse(int pid) {
- procmaps_iterator *maps_it = malloc(sizeof(procmaps_iterator));
- char maps_path[500];
+ char maps_path[500];
if (pid >= 0) {
sprintf(maps_path, "/proc/%d/maps", pid);
@@ -129,8 +128,9 @@ procmaps_iterator *pmparser_parse(int pid) {
}
- int ind = 0;
- char buf[PROCMAPS_LINE_MAX_LENGTH];
+ procmaps_iterator *maps_it = malloc(sizeof(procmaps_iterator));
+ int ind = 0;
+ char buf[PROCMAPS_LINE_MAX_LENGTH];
// int c;
procmaps_struct *list_maps = NULL;
procmaps_struct *tmp;
diff --git a/src/afl-cc.c b/src/afl-cc.c
index 771a58f5..19dc9a6a 100644
--- a/src/afl-cc.c
+++ b/src/afl-cc.c
@@ -49,14 +49,14 @@ static u8 * obj_path; /* Path to runtime libraries */
static u8 **cc_params; /* Parameters passed to the real CC */
static u32 cc_par_cnt = 1; /* Param count, including argv0 */
static u8 llvm_fullpath[PATH_MAX];
-static u8 instrument_mode, instrument_opt_mode, ngram_size, lto_mode,
- compiler_mode, plusplus_mode;
-static u8 have_gcc, have_llvm, have_gcc_plugin, have_lto;
-static u8 *lto_flag = AFL_CLANG_FLTO, *argvnull;
-static u8 debug;
-static u8 cwd[4096];
-static u8 cmplog_mode;
-u8 use_stdin; /* dummy */
+static u8 instrument_mode, instrument_opt_mode, ngram_size, lto_mode;
+static u8 compiler_mode, plusplus_mode, have_instr_env = 0;
+static u8 have_gcc, have_llvm, have_gcc_plugin, have_lto, have_instr_list = 0;
+static u8 * lto_flag = AFL_CLANG_FLTO, *argvnull;
+static u8 debug;
+static u8 cwd[4096];
+static u8 cmplog_mode;
+u8 use_stdin; /* dummy */
// static u8 *march_opt = CFLAGS_OPT;
enum {
@@ -354,19 +354,13 @@ static void edit_params(u32 argc, char **argv, char **envp) {
if (lto_mode && plusplus_mode)
cc_params[cc_par_cnt++] = "-lc++"; // needed by fuzzbench, early
- if (lto_mode) {
-
- if (getenv("AFL_LLVM_INSTRUMENT_FILE") != NULL ||
- getenv("AFL_LLVM_WHITELIST") || getenv("AFL_LLVM_ALLOWLIST") ||
- getenv("AFL_LLVM_DENYLIST") || getenv("AFL_LLVM_BLOCKLIST")) {
-
- cc_params[cc_par_cnt++] = "-Xclang";
- cc_params[cc_par_cnt++] = "-load";
- cc_params[cc_par_cnt++] = "-Xclang";
- cc_params[cc_par_cnt++] =
- alloc_printf("%s/afl-llvm-lto-instrumentlist.so", obj_path);
+ if (lto_mode && have_instr_env) {
- }
+ cc_params[cc_par_cnt++] = "-Xclang";
+ cc_params[cc_par_cnt++] = "-load";
+ cc_params[cc_par_cnt++] = "-Xclang";
+ cc_params[cc_par_cnt++] =
+ alloc_printf("%s/afl-llvm-lto-instrumentlist.so", obj_path);
}
@@ -508,11 +502,25 @@ static void edit_params(u32 argc, char **argv, char **envp) {
if (instrument_mode == INSTRUMENT_PCGUARD) {
#if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0)
- cc_params[cc_par_cnt++] = "-Xclang";
- cc_params[cc_par_cnt++] = "-load";
- cc_params[cc_par_cnt++] = "-Xclang";
- cc_params[cc_par_cnt++] =
- alloc_printf("%s/SanitizerCoveragePCGUARD.so", obj_path);
+ if (have_instr_list) {
+
+ if (!be_quiet)
+ SAYF(
+ "Using unoptimized trace-pc-guard, due usage of "
+ "-fsanitize-coverage-allow/denylist, you can use "
+ "AFL_LLVM_ALLOWLIST/AFL_LLMV_DENYLIST instead.\n");
+ cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard";
+
+ } else {
+
+ cc_params[cc_par_cnt++] = "-Xclang";
+ cc_params[cc_par_cnt++] = "-load";
+ cc_params[cc_par_cnt++] = "-Xclang";
+ cc_params[cc_par_cnt++] =
+ alloc_printf("%s/SanitizerCoveragePCGUARD.so", obj_path);
+
+ }
+
#else
#if LLVM_MAJOR >= 4
if (!be_quiet)
@@ -590,6 +598,9 @@ static void edit_params(u32 argc, char **argv, char **envp) {
if (!strcmp(cur, "armv7a-linux-androideabi")) bit_mode = 32;
if (!strcmp(cur, "-m64")) bit_mode = 64;
+ if (!strncmp(cur, "-fsanitize-coverage-", 20) && strstr(cur, "list="))
+ have_instr_list = 1;
+
if (!strcmp(cur, "-fsanitize=address") || !strcmp(cur, "-fsanitize=memory"))
asan_set = 1;
@@ -826,7 +837,7 @@ static void edit_params(u32 argc, char **argv, char **envp) {
}
- #ifndef __APPLE__
+ #if !defined(__APPLE__) && !defined(__sun)
if (!shared_linking)
cc_params[cc_par_cnt++] =
alloc_printf("-Wl,--dynamic-list=%s/dynamic_list.txt", obj_path);
@@ -856,6 +867,14 @@ int main(int argc, char **argv, char **envp) {
be_quiet = 1;
+ if (getenv("AFL_LLVM_INSTRUMENT_FILE") || getenv("AFL_LLVM_WHITELIST") ||
+ getenv("AFL_LLVM_ALLOWLIST") || getenv("AFL_LLVM_DENYLIST") ||
+ getenv("AFL_LLVM_BLOCKLIST")) {
+
+ have_instr_env = 1;
+
+ }
+
if ((ptr = strrchr(callname, '/')) != NULL) callname = ptr + 1;
argvnull = (u8 *)argv[0];
check_environment_vars(envp);
@@ -1015,14 +1034,14 @@ int main(int argc, char **argv, char **envp) {
}
- if ((getenv("AFL_LLVM_INSTRUMENT_FILE") != NULL ||
- getenv("AFL_LLVM_WHITELIST") || getenv("AFL_LLVM_ALLOWLIST") ||
- getenv("AFL_LLVM_DENYLIST") || getenv("AFL_LLVM_BLOCKLIST")) &&
- getenv("AFL_DONT_OPTIMIZE"))
+ if (have_instr_env && getenv("AFL_DONT_OPTIMIZE")) {
+
WARNF(
"AFL_LLVM_ALLOWLIST/DENYLIST and AFL_DONT_OPTIMIZE cannot be combined "
"for file matching, only function matching!");
+ }
+
if (getenv("AFL_LLVM_INSTRIM") || getenv("INSTRIM") ||
getenv("INSTRIM_LIB")) {
@@ -1307,15 +1326,20 @@ int main(int argc, char **argv, char **envp) {
" AFL_GCC_INSTRUMENT_FILE: enable selective instrumentation by "
"filename\n");
+#if LLVM_MAJOR < 9
+ #define COUNTER_BEHAVIOUR \
+ " AFL_LLVM_NOT_ZERO: use cycling trace counters that skip zero\n"
+#else
+ #define COUNTER_BEHAVIOUR \
+ " AFL_LLVM_SKIP_NEVERZERO: do not skip zero on trace counters\n"
+#endif
if (have_llvm)
SAYF(
"\nLLVM/LTO/afl-clang-fast/afl-clang-lto specific environment "
"variables:\n"
-#if LLVM_MAJOR < 9
- " AFL_LLVM_NOT_ZERO: use cycling trace counters that skip zero\n"
-#else
- " AFL_LLVM_SKIP_NEVERZERO: do not skip zero on trace counters\n"
-#endif
+
+ COUNTER_BEHAVIOUR
+
" AFL_LLVM_DICT2FILE: generate an afl dictionary based on found "
"comparisons\n"
" AFL_LLVM_LAF_ALL: enables all LAF splits/transforms\n"
@@ -1426,22 +1450,20 @@ int main(int argc, char **argv, char **envp) {
#if LLVM_MAJOR <= 6
instrument_mode = INSTRUMENT_AFL;
#else
- if (getenv("AFL_LLVM_INSTRUMENT_FILE") != NULL ||
- getenv("AFL_LLVM_WHITELIST") || getenv("AFL_LLVM_ALLOWLIST") ||
- getenv("AFL_LLVM_DENYLIST") || getenv("AFL_LLVM_BLOCKLIST")) {
+ #if LLVM_MAJOR < 11 && (LLVM_MAJOR < 10 || LLVM_MINOR < 1)
+ if (have_instr_env) {
instrument_mode = INSTRUMENT_AFL;
- WARNF(
- "switching to classic instrumentation because "
- "AFL_LLVM_ALLOWLIST/DENYLIST does not work with PCGUARD. Use "
- "-fsanitize-coverage-allowlist=allowlist.txt or "
- "-fsanitize-coverage-blocklist=denylist.txt if you want to use "
- "PCGUARD. Requires llvm 12+. See https://clang.llvm.org/docs/ "
- "SanitizerCoverage.html#partially-disabling-instrumentation");
+ if (!be_quiet)
+ WARNF(
+ "Switching to classic instrumentation because "
+ "AFL_LLVM_ALLOWLIST/DENYLIST does not work with PCGUARD < 10.0.1.");
} else
+ #endif
instrument_mode = INSTRUMENT_PCGUARD;
+
#endif
}
@@ -1487,18 +1509,16 @@ int main(int argc, char **argv, char **envp) {
"AFL_LLVM_NOT_ZERO and AFL_LLVM_SKIP_NEVERZERO can not be set "
"together");
- if (instrument_mode == INSTRUMENT_PCGUARD &&
- (getenv("AFL_LLVM_INSTRUMENT_FILE") != NULL ||
- getenv("AFL_LLVM_WHITELIST") || getenv("AFL_LLVM_ALLOWLIST") ||
- getenv("AFL_LLVM_DENYLIST") || getenv("AFL_LLVM_BLOCKLIST")))
+#if LLVM_MAJOR < 11 && (LLVM_MAJOR < 10 || LLVM_MINOR < 1)
+ if (instrument_mode == INSTRUMENT_PCGUARD && have_instr_env) {
+
FATAL(
"Instrumentation type PCGUARD does not support "
- "AFL_LLVM_ALLOWLIST/DENYLIST! Use "
- "-fsanitize-coverage-allowlist=allowlist.txt or "
- "-fsanitize-coverage-blocklist=denylist.txt instead (requires llvm "
- "12+), see "
- "https://clang.llvm.org/docs/"
- "SanitizerCoverage.html#partially-disabling-instrumentation");
+ "AFL_LLVM_ALLOWLIST/DENYLIST! Use LLVM 10.0.1+ instead.");
+
+ }
+
+#endif
u8 *ptr2;
diff --git a/src/afl-common.c b/src/afl-common.c
index 19c9419b..8cf1a444 100644
--- a/src/afl-common.c
+++ b/src/afl-common.c
@@ -342,7 +342,7 @@ u8 *find_binary(u8 *fname) {
if (stat(target_path, &st) || !S_ISREG(st.st_mode) ||
!(st.st_mode & 0111) || st.st_size < 4) {
- free(target_path);
+ ck_free(target_path);
FATAL("Program '%s' not found or not executable", fname);
}
diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c
index 45be2abd..3814a77e 100644
--- a/src/afl-forkserver.c
+++ b/src/afl-forkserver.c
@@ -116,7 +116,7 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) {
fsrv_to->use_fauxsrv = 0;
fsrv_to->last_run_timed_out = 0;
- fsrv_to->init_child_func = fsrv_exec_child;
+ fsrv_to->init_child_func = from->init_child_func;
// Note: do not copy ->add_extra_func
list_append(&fsrv_list, fsrv_to);
@@ -272,7 +272,8 @@ static void afl_fauxsrv_execv(afl_forkserver_t *fsrv, char **argv) {
*(u32 *)fsrv->trace_bits = EXEC_FAIL_SIG;
- PFATAL("Execv failed in fauxserver.");
+ WARNF("Execv failed in fauxserver.");
+ break;
}
@@ -286,13 +287,13 @@ static void afl_fauxsrv_execv(afl_forkserver_t *fsrv, char **argv) {
if (waitpid(child_pid, &status, 0) < 0) {
// Zombie Child could not be collected. Scary!
- PFATAL("Fauxserver could not determin child's exit code. ");
+ WARNF("Fauxserver could not determine child's exit code. ");
}
/* Relay wait status to AFL pipe, then loop back. */
- if (write(FORKSRV_FD + 1, &status, 4) != 4) { exit(0); }
+ if (write(FORKSRV_FD + 1, &status, 4) != 4) { exit(1); }
}
@@ -330,7 +331,7 @@ static void report_error_and_exit(int error) {
"memory failed.");
break;
default:
- FATAL("unknown error code %u from fuzzing target!", error);
+ FATAL("unknown error code %d from fuzzing target!", error);
}
@@ -355,7 +356,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
if (fsrv->use_fauxsrv) {
- /* TODO: Come up with sone nice way to initialize this all */
+ /* TODO: Come up with some nice way to initialize this all */
if (fsrv->init_child_func != fsrv_exec_child) {
@@ -520,7 +521,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
*(u32 *)fsrv->trace_bits = EXEC_FAIL_SIG;
fprintf(stderr, "Error: execv to target failed\n");
- exit(0);
+ exit(1);
}
@@ -1137,7 +1138,7 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
}
// Fauxserver should handle this now.
- // if (tb4 == EXEC_FAIL_SIG) return FSRV_RUN_ERROR;
+ if (*(u32 *)fsrv->trace_bits == EXEC_FAIL_SIG) return FSRV_RUN_ERROR;
return FSRV_RUN_OK;
diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c
index 735420c3..2d14b04e 100644
--- a/src/afl-fuzz-bitmap.c
+++ b/src/afl-fuzz-bitmap.c
@@ -584,12 +584,39 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
alloc_printf("%s/queue/id_%06u", afl->out_dir, afl->queued_paths);
#endif /* ^!SIMPLE_FILES */
-
+ fd = open(queue_fn, O_WRONLY | O_CREAT | O_EXCL, 0600);
+ if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", queue_fn); }
+ ck_write(fd, mem, len, queue_fn);
+ close(fd);
add_to_queue(afl, queue_fn, len, 0);
#ifdef INTROSPECTION
- fprintf(afl->introspection_file, "QUEUE %s = %s\n", afl->mutation,
- afl->queue_top->fname);
+ if (afl->custom_mutators_count && afl->current_custom_fuzz) {
+
+ LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
+
+ if (afl->current_custom_fuzz == el && el->afl_custom_introspection) {
+
+ const char *ptr = el->afl_custom_introspection(el->data);
+
+ if (ptr != NULL && *ptr != 0) {
+
+ fprintf(afl->introspection_file, "QUEUE CUSTOM %s = %s\n", ptr,
+ afl->queue_top->fname);
+
+ }
+
+ }
+
+ });
+
+ } else if (afl->mutation[0] != 0) {
+
+ fprintf(afl->introspection_file, "QUEUE %s = %s\n", afl->mutation,
+ afl->queue_top->fname);
+
+ }
+
#endif
if (hnb == 2) {
@@ -623,11 +650,6 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
}
- fd = open(queue_fn, O_WRONLY | O_CREAT | O_EXCL, 0600);
- if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", queue_fn); }
- ck_write(fd, mem, len, queue_fn);
- close(fd);
-
if (likely(afl->q_testcase_max_cache_size)) {
queue_testcase_store_mem(afl, afl->queue_top, mem);
@@ -665,7 +687,32 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
++afl->unique_tmouts;
#ifdef INTROSPECTION
- fprintf(afl->introspection_file, "UNIQUE_TIMEOUT %s\n", afl->mutation);
+ if (afl->custom_mutators_count && afl->current_custom_fuzz) {
+
+ LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
+
+ if (afl->current_custom_fuzz == el && el->afl_custom_introspection) {
+
+ const char *ptr = el->afl_custom_introspection(el->data);
+
+ if (ptr != NULL && *ptr != 0) {
+
+ fprintf(afl->introspection_file,
+ "UNIQUE_TIMEOUT CUSTOM %s = %s\n", ptr,
+ afl->queue_top->fname);
+
+ }
+
+ }
+
+ });
+
+ } else if (afl->mutation[0] != 0) {
+
+ fprintf(afl->introspection_file, "UNIQUE_TIMEOUT %s\n", afl->mutation);
+
+ }
+
#endif
/* Before saving, we make sure that it's a genuine hang by re-running
@@ -751,7 +798,31 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
++afl->unique_crashes;
#ifdef INTROSPECTION
- fprintf(afl->introspection_file, "UNIQUE_CRASH %s\n", afl->mutation);
+ if (afl->custom_mutators_count && afl->current_custom_fuzz) {
+
+ LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
+
+ if (afl->current_custom_fuzz == el && el->afl_custom_introspection) {
+
+ const char *ptr = el->afl_custom_introspection(el->data);
+
+ if (ptr != NULL && *ptr != 0) {
+
+ fprintf(afl->introspection_file, "UNIQUE_CRASH CUSTOM %s = %s\n",
+ ptr, afl->queue_top->fname);
+
+ }
+
+ }
+
+ });
+
+ } else if (afl->mutation[0] != 0) {
+
+ fprintf(afl->introspection_file, "UNIQUE_CRASH %s\n", afl->mutation);
+
+ }
+
#endif
if (unlikely(afl->infoexec)) {
diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c
index 19a8d77b..0360cdb0 100644
--- a/src/afl-fuzz-init.c
+++ b/src/afl-fuzz-init.c
@@ -355,7 +355,7 @@ void bind_to_free_cpu(afl_state_t *afl) {
if (ncpus > sizeof(cpu_used)) ncpus = sizeof(cpu_used);
- for (i = 0; i < ncpus; i++) {
+ for (i = 0; i < (s32)ncpus; i++) {
k = kstat_lookup(m, "cpu_stat", i, NULL);
if (kstat_read(m, k, &cs)) {
@@ -2300,12 +2300,6 @@ void fix_up_sync(afl_state_t *afl) {
u8 *x = afl->sync_id;
- if (afl->non_instrumented_mode) {
-
- FATAL("-S / -M and -n are mutually exclusive");
-
- }
-
while (*x) {
if (!isalnum(*x) && *x != '_' && *x != '-') {
@@ -2503,7 +2497,8 @@ void check_binary(afl_state_t *afl, u8 *fname) {
}
- if (afl->afl_env.afl_skip_bin_check || afl->use_wine || afl->unicorn_mode) {
+ if (afl->afl_env.afl_skip_bin_check || afl->use_wine || afl->unicorn_mode ||
+ afl->non_instrumented_mode) {
return;
diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c
index c4d7233c..1d14f657 100644
--- a/src/afl-fuzz-mutators.c
+++ b/src/afl-fuzz-mutators.c
@@ -166,6 +166,13 @@ struct custom_mutator *load_custom_mutator(afl_state_t *afl, const char *fn) {
}
+ /* "afl_custom_introspection", optional */
+#ifdef INTROSPECTION
+ mutator->afl_custom_introspection = dlsym(dh, "afl_custom_introspection");
+ if (!mutator->afl_custom_introspection)
+ ACTF("optional symbol 'afl_custom_introspection' not found.");
+#endif
+
/* "afl_custom_fuzz_count", optional */
mutator->afl_custom_fuzz_count = dlsym(dh, "afl_custom_fuzz_count");
if (!mutator->afl_custom_fuzz_count)
diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c
index 91bbced6..0adc3719 100644
--- a/src/afl-fuzz-one.c
+++ b/src/afl-fuzz-one.c
@@ -1780,10 +1780,16 @@ custom_mutator_stage:
orig_hit_cnt = afl->queued_paths + afl->unique_crashes;
+#ifdef INTROSPECTION
+ afl->mutation[0] = 0;
+#endif
+
LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
if (el->afl_custom_fuzz) {
+ afl->current_custom_fuzz = el;
+
if (el->afl_custom_fuzz_count)
afl->stage_max = el->afl_custom_fuzz_count(el->data, out_buf, len);
else
@@ -1840,12 +1846,6 @@ custom_mutator_stage:
if (mutated_size > 0) {
-#ifdef INTROSPECTION
- snprintf(afl->mutation, sizeof(afl->mutation), "%s CUSTOM-%s",
- afl->queue_cur->fname,
- target != NULL ? (char *)target->fname : "none");
-#endif
-
if (common_fuzz_stuff(afl, mutated_buf, (u32)mutated_size)) {
goto abandon_entry;
@@ -1889,6 +1889,8 @@ custom_mutator_stage:
});
+ afl->current_custom_fuzz = NULL;
+
if (!has_custom_fuzz) goto havoc_stage;
new_hit_cnt = afl->queued_paths + afl->unique_crashes;
diff --git a/src/afl-fuzz-python.c b/src/afl-fuzz-python.c
index adb92649..9ac4403b 100644
--- a/src/afl-fuzz-python.c
+++ b/src/afl-fuzz-python.c
@@ -96,7 +96,7 @@ static size_t fuzz_py(void *py_mutator, u8 *buf, size_t buf_size, u8 **out_buf,
mutated_size = PyByteArray_Size(py_value);
*out_buf = afl_realloc(BUF_PARAMS(fuzz), mutated_size);
- if (unlikely(!out_buf)) { PFATAL("alloc"); }
+ if (unlikely(!*out_buf)) { PFATAL("alloc"); }
memcpy(*out_buf, PyByteArray_AsString(py_value), mutated_size);
Py_DECREF(py_value);
@@ -134,6 +134,18 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
PyObject * py_module = py->py_module;
PyObject **py_functions = py->py_functions;
+ // initialize the post process buffer; ensures it's always valid
+ PyObject *unused_bytes = PyByteArray_FromStringAndSize("OHAI", 4);
+ if (!unused_bytes) { FATAL("allocation failed!"); }
+ if (PyObject_GetBuffer(unused_bytes, &py->post_process_buf, PyBUF_SIMPLE) ==
+ -1) {
+
+ FATAL("buffer initialization failed");
+
+ }
+
+ Py_DECREF(unused_bytes);
+
if (py_module != NULL) {
u8 py_notrim = 0, py_idx;
@@ -163,6 +175,8 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
PyObject_GetAttrString(py_module, "queue_get");
py_functions[PY_FUNC_QUEUE_NEW_ENTRY] =
PyObject_GetAttrString(py_module, "queue_new_entry");
+ py_functions[PY_FUNC_INTROSPECTION] =
+ PyObject_GetAttrString(py_module, "introspection");
py_functions[PY_FUNC_DEINIT] = PyObject_GetAttrString(py_module, "deinit");
if (!py_functions[PY_FUNC_DEINIT])
FATAL("deinit function not found in python module");
@@ -212,6 +226,7 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
PyErr_Print();
fprintf(stderr, "Failed to load \"%s\"\n", module_name);
+ free(py);
return NULL;
}
@@ -310,7 +325,6 @@ struct custom_mutator *load_custom_mutator_py(afl_state_t *afl,
struct custom_mutator *mutator;
mutator = ck_alloc(sizeof(struct custom_mutator));
- mutator->post_process_buf = NULL;
mutator->name = module_name;
ACTF("Loading Python mutator library from '%s'...", module_name);
@@ -326,9 +340,7 @@ struct custom_mutator *load_custom_mutator_py(afl_state_t *afl,
if (py_functions[PY_FUNC_DEINIT]) { mutator->afl_custom_deinit = deinit_py; }
- /* "afl_custom_fuzz" should not be NULL, but the interface of Python mutator
- is quite different from the custom mutator. */
- mutator->afl_custom_fuzz = fuzz_py;
+ if (py_functions[PY_FUNC_FUZZ]) { mutator->afl_custom_fuzz = fuzz_py; }
if (py_functions[PY_FUNC_POST_PROCESS]) {
@@ -381,6 +393,15 @@ struct custom_mutator *load_custom_mutator_py(afl_state_t *afl,
}
+ #ifdef INTROSPECTION
+ if (py_functions[PY_FUNC_INTROSPECTION]) {
+
+ mutator->afl_custom_introspection = introspection_py;
+
+ }
+
+ #endif
+
OKF("Python mutator '%s' installed successfully.", module_name);
/* Initialize the custom mutator */
@@ -393,10 +414,13 @@ struct custom_mutator *load_custom_mutator_py(afl_state_t *afl,
size_t post_process_py(void *py_mutator, u8 *buf, size_t buf_size,
u8 **out_buf) {
- size_t py_out_buf_size;
PyObject * py_args, *py_value;
py_mutator_t *py = (py_mutator_t *)py_mutator;
+ // buffer returned previously must be released; initialized during init
+ // so we don't need to do comparisons
+ PyBuffer_Release(&py->post_process_buf);
+
py_args = PyTuple_New(1);
py_value = PyByteArray_FromStringAndSize(buf, buf_size);
if (!py_value) {
@@ -416,20 +440,20 @@ size_t post_process_py(void *py_mutator, u8 *buf, size_t buf_size,
if (py_value != NULL) {
- py_out_buf_size = PyByteArray_Size(py_value);
-
- if (unlikely(!afl_realloc(BUF_PARAMS(post_process), py_out_buf_size))) {
+ if (PyObject_GetBuffer(py_value, &py->post_process_buf, PyBUF_SIMPLE) ==
+ -1) {
- PFATAL("alloc");
+ PyErr_Print();
+ FATAL(
+ "Python custom mutator: post_process call return value not a "
+ "bytes-like object");
}
- memcpy(py->post_process_buf, PyByteArray_AsString(py_value),
- py_out_buf_size);
Py_DECREF(py_value);
- *out_buf = py->post_process_buf;
- return py_out_buf_size;
+ *out_buf = (u8 *)py->post_process_buf.buf;
+ return py->post_process_buf.len;
} else {
@@ -569,7 +593,7 @@ size_t trim_py(void *py_mutator, u8 **out_buf) {
ret = PyByteArray_Size(py_value);
*out_buf = afl_realloc(BUF_PARAMS(trim), ret);
- if (unlikely(!out_buf)) { PFATAL("alloc"); }
+ if (unlikely(!*out_buf)) { PFATAL("alloc"); }
memcpy(*out_buf, PyByteArray_AsString(py_value), ret);
Py_DECREF(py_value);
@@ -635,7 +659,7 @@ size_t havoc_mutation_py(void *py_mutator, u8 *buf, size_t buf_size,
/* A new buf is needed... */
*out_buf = afl_realloc(BUF_PARAMS(havoc), mutated_size);
- if (unlikely(!out_buf)) { PFATAL("alloc"); }
+ if (unlikely(!*out_buf)) { PFATAL("alloc"); }
}
@@ -679,6 +703,28 @@ u8 havoc_mutation_probability_py(void *py_mutator) {
}
+const char *introspection_py(void *py_mutator) {
+
+ PyObject *py_args, *py_value;
+
+ py_args = PyTuple_New(0);
+ py_value = PyObject_CallObject(
+ ((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_INTROSPECTION],
+ py_args);
+ Py_DECREF(py_args);
+
+ if (py_value == NULL) {
+
+ return NULL;
+
+ } else {
+
+ return PyByteArray_AsString(py_value);
+
+ }
+
+}
+
u8 queue_get_py(void *py_mutator, const u8 *filename) {
PyObject *py_args, *py_value;
diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c
index c78df8be..f35b4f57 100644
--- a/src/afl-fuzz-queue.c
+++ b/src/afl-fuzz-queue.c
@@ -56,7 +56,12 @@ void create_alias_table(afl_state_t *afl) {
int * S = (u32 *)afl_realloc(AFL_BUF_PARAM(out_scratch), n * sizeof(u32));
int * L = (u32 *)afl_realloc(AFL_BUF_PARAM(in_scratch), n * sizeof(u32));
- if (!P || !S || !L) { FATAL("could not aquire memory for alias table"); }
+ if (!P || !S || !L || !afl->alias_table || !afl->alias_probability) {
+
+ FATAL("could not acquire memory for alias table");
+
+ }
+
memset((void *)afl->alias_table, 0, n * sizeof(u32));
memset((void *)afl->alias_probability, 0, n * sizeof(double));
diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c
index e969994d..95b3ee8a 100644
--- a/src/afl-fuzz-run.c
+++ b/src/afl-fuzz-run.c
@@ -332,7 +332,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
}
afl_fsrv_start(&afl->fsrv, afl->argv, &afl->stop_soon,
- afl->afl_env.afl_debug_child_output);
+ afl->afl_env.afl_debug_child);
if (afl->fsrv.support_shmem_fuzz && !afl->fsrv.use_shmem_fuzz) {
@@ -590,7 +590,7 @@ void sync_fuzzers(afl_state_t *afl) {
while (m < n) {
- if (strcmp(namelist[m]->d_name, entry)) {
+ if (strncmp(namelist[m]->d_name, entry, 9)) {
m++;
diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c
index 61bd06b7..489d4e53 100644
--- a/src/afl-fuzz-state.c
+++ b/src/afl-fuzz-state.c
@@ -268,11 +268,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
afl->afl_env.afl_bench_until_crash =
get_afl_env(afl_environment_variables[i]) ? 1 : 0;
- } else if (!strncmp(env, "AFL_DEBUG_CHILD_OUTPUT",
+ } else if (!strncmp(env, "AFL_DEBUG_CHILD",
+ afl_environment_variable_len) ||
+ !strncmp(env, "AFL_DEBUG_CHILD_OUTPUT",
afl_environment_variable_len)) {
- afl->afl_env.afl_debug_child_output =
+ afl->afl_env.afl_debug_child =
get_afl_env(afl_environment_variables[i]) ? 1 : 0;
} else if (!strncmp(env, "AFL_AUTORESUME",
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index 269ce1bf..1008f28c 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -166,7 +166,7 @@ static void usage(u8 *argv0, int more_help) {
"AFL_CUSTOM_MUTATOR_ONLY: avoid AFL++'s internal mutators\n"
"AFL_CYCLE_SCHEDULES: after completing a cycle, switch to a different -p schedule\n"
"AFL_DEBUG: extra debugging output for Python mode trimming\n"
- "AFL_DEBUG_CHILD_OUTPUT: do not suppress stdout/stderr from target\n"
+ "AFL_DEBUG_CHILD: do not suppress stdout/stderr from target\n"
"AFL_DISABLE_TRIM: disable the trimming of test cases\n"
"AFL_DUMB_FORKSRV: use fork server without feedback from target\n"
"AFL_EXIT_WHEN_DONE: exit when all inputs are run and no new finds are found\n"
@@ -350,6 +350,7 @@ int main(int argc, char **argv_orig, char **envp) {
case 's': {
+ if (optarg == NULL) { FATAL("No valid seed provided. Got NULL."); }
rand_set_seed(afl, strtoul(optarg, 0L, 10));
afl->fixed_seed = 1;
break;
@@ -419,6 +420,7 @@ int main(int argc, char **argv_orig, char **envp) {
case 'i': /* input dir */
if (afl->in_dir) { FATAL("Multiple -i options not supported"); }
+ if (optarg == NULL) { FATAL("Invalid -i option (got NULL)."); }
afl->in_dir = optarg;
if (!strcmp(afl->in_dir, "-")) { afl->in_place_resume = 1; }
@@ -435,9 +437,26 @@ int main(int argc, char **argv_orig, char **envp) {
u8 *c;
+ if (afl->non_instrumented_mode) {
+
+ FATAL("-M is not supported in non-instrumented mode");
+
+ }
+
if (afl->sync_id) { FATAL("Multiple -S or -M options not supported"); }
+
+ /* sanity check for argument: should not begin with '-' (possible
+ * option) */
+ if (optarg && *optarg == '-') {
+
+ FATAL(
+ "argument for -M started with a dash '-', which is used for "
+ "options");
+
+ }
+
afl->sync_id = ck_strdup(optarg);
- afl->skip_deterministic = 0; // force determinsitic fuzzing
+ afl->skip_deterministic = 0; // force deterministic fuzzing
afl->old_seed_selection = 1; // force old queue walking seed selection
if ((c = strchr(afl->sync_id, ':'))) {
@@ -464,7 +483,24 @@ int main(int argc, char **argv_orig, char **envp) {
case 'S': /* secondary sync id */
+ if (afl->non_instrumented_mode) {
+
+ FATAL("-S is not supported in non-instrumented mode");
+
+ }
+
if (afl->sync_id) { FATAL("Multiple -S or -M options not supported"); }
+
+ /* sanity check for argument: should not begin with '-' (possible
+ * option) */
+ if (optarg && *optarg == '-') {
+
+ FATAL(
+ "argument for -M started with a dash '-', which is used for "
+ "options");
+
+ }
+
afl->sync_id = ck_strdup(optarg);
afl->is_secondary_node = 1;
break;
@@ -620,6 +656,12 @@ int main(int argc, char **argv_orig, char **envp) {
case 'n': /* dumb mode */
+ if (afl->is_main_node || afl->is_secondary_node) {
+
+ FATAL("Non instrumented mode is not supported with -M / -S");
+
+ }
+
if (afl->non_instrumented_mode) {
FATAL("Multiple -n options not supported");
@@ -906,7 +948,7 @@ int main(int argc, char **argv_orig, char **envp) {
afl->power_name = power_names[afl->schedule];
- if (!afl->sync_id) {
+ if (!afl->non_instrumented_mode && !afl->sync_id) {
auto_sync = 1;
afl->sync_id = ck_strdup("default");
@@ -1338,7 +1380,11 @@ int main(int argc, char **argv_orig, char **envp) {
}
- if (!afl->fsrv.qemu_mode) { check_binary(afl, afl->cmplog_binary); }
+ if (!afl->fsrv.qemu_mode && !afl->non_instrumented_mode) {
+
+ check_binary(afl, afl->cmplog_binary);
+
+ }
}
@@ -1380,7 +1426,7 @@ int main(int argc, char **argv_orig, char **envp) {
afl->cmplog_fsrv.cmplog_binary = afl->cmplog_binary;
afl->cmplog_fsrv.init_child_func = cmplog_exec_child;
afl_fsrv_start(&afl->cmplog_fsrv, afl->argv, &afl->stop_soon,
- afl->afl_env.afl_debug_child_output);
+ afl->afl_env.afl_debug_child);
OKF("Cmplog forkserver successfully started");
}
diff --git a/src/afl-gotcpu.c b/src/afl-gotcpu.c
index bd0f7de6..1aea3e40 100644
--- a/src/afl-gotcpu.c
+++ b/src/afl-gotcpu.c
@@ -65,7 +65,6 @@
#define cpu_set_t cpuset_t
#elif defined(__NetBSD__)
#include <pthread.h>
- #include <sched.h>
#elif defined(__APPLE__)
#include <pthread.h>
#include <mach/thread_act.h>
diff --git a/src/afl-showmap.c b/src/afl-showmap.c
index 4b357254..69527007 100644
--- a/src/afl-showmap.c
+++ b/src/afl-showmap.c
@@ -1091,7 +1091,11 @@ int main(int argc, char **argv_orig, char **envp) {
}
afl_fsrv_start(fsrv, use_argv, &stop_soon,
- get_afl_env("AFL_DEBUG_CHILD_OUTPUT") ? 1 : 0);
+ (get_afl_env("AFL_DEBUG_CHILD") ||
+ get_afl_env("AFL_DEBUG_CHILD_OUTPUT"))
+ ? 1
+ : 0);
+
map_size = fsrv->map_size;
if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz)
diff --git a/src/afl-tmin.c b/src/afl-tmin.c
index 06037d61..e4fb068d 100644
--- a/src/afl-tmin.c
+++ b/src/afl-tmin.c
@@ -1141,8 +1141,11 @@ int main(int argc, char **argv_orig, char **envp) {
read_initial_file();
- afl_fsrv_start(fsrv, use_argv, &stop_soon,
- get_afl_env("AFL_DEBUG_CHILD_OUTPUT") ? 1 : 0);
+ afl_fsrv_start(
+ fsrv, use_argv, &stop_soon,
+ (get_afl_env("AFL_DEBUG_CHILD") || get_afl_env("AFL_DEBUG_CHILD_OUTPUT"))
+ ? 1
+ : 0);
if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz)
shm_fuzz = deinit_shmem(fsrv, shm_fuzz);
diff --git a/test/test-unicorn-mode.sh b/test/test-unicorn-mode.sh
index 7ac4cdd2..b4c6eb3e 100755
--- a/test/test-unicorn-mode.sh
+++ b/test/test-unicorn-mode.sh
@@ -7,7 +7,7 @@ test -d ../unicorn_mode/unicornafl -a -e ../unicorn_mode/unicornafl/samples/shel
test -e ../unicorn_mode/samples/simple/simple_target.bin -a -e ../unicorn_mode/samples/compcov_x64/compcov_target.bin && {
{
# We want to see python errors etc. in logs, in case something doesn't work
- export AFL_DEBUG_CHILD_OUTPUT=1
+ export AFL_DEBUG_CHILD=1
# some python version should be available now
PYTHONS="`command -v python3` `command -v python` `command -v python2`"
@@ -34,7 +34,7 @@ test -d ../unicorn_mode/unicornafl -a -e ../unicorn_mode/unicornafl/samples/shel
cd ../unicorn_mode/samples/persistent
make >>errors 2>&1
$ECHO "$GREY[*] running afl-fuzz for unicorn_mode (persistent), this will take approx 25 seconds"
- AFL_DEBUG_CHILD_OUTPUT=1 ../../../afl-fuzz -m none -V25 -U -i sample_inputs -o out -d -- ./harness @@ >>errors 2>&1
+ AFL_DEBUG_CHILD=1 ../../../afl-fuzz -m none -V25 -U -i sample_inputs -o out -d -- ./harness @@ >>errors 2>&1
test -n "$( ls out/default/queue/id:000002* 2>/dev/null )" && {
$ECHO "$GREEN[+] afl-fuzz is working correctly with unicorn_mode (persistent)"
} || {
@@ -96,7 +96,7 @@ test -d ../unicorn_mode/unicornafl -a -e ../unicorn_mode/unicornafl/samples/shel
}
fi
- unset AFL_DEBUG_CHILD_OUTPUT
+ unset AFL_DEBUG_CHILD
}
} || {
diff --git a/unicorn_mode/samples/persistent/simple_target_noncrashing.c b/unicorn_mode/samples/persistent/simple_target_noncrashing.c
index 00764473..9257643b 100644
--- a/unicorn_mode/samples/persistent/simple_target_noncrashing.c
+++ b/unicorn_mode/samples/persistent/simple_target_noncrashing.c
@@ -10,7 +10,7 @@
* Written by Nathan Voss <njvoss99@gmail.com>
* Adapted by Lukas Seidel <seidel.1@campus.tu-berlin.de>
*/
-
+#include <string.h>
int main(int argc, char** argv) {
if(argc < 2){
@@ -19,15 +19,19 @@ int main(int argc, char** argv) {
char *data_buf = argv[1];
- if len(data_buf < 20) {
- if (data_buf[20] != 0) {
+ if (strlen(data_buf) >= 21 && data_buf[20] != 0) {
printf("Not crashing");
- } else if (data_buf[0] > 0x10 && data_buf[0] < 0x20 && data_buf[1] > data_buf[2]) {
+ } else if (strlen(data_buf) > 1
+ && data_buf[0] > 0x10 && data_buf[0] < 0x20 && data_buf[1] > data_buf[2]) {
printf("Also not crashing with databuf[0] == %c", data_buf[0])
- } else if (data_buf[9] == 0x00 && data_buf[10] != 0x00 && data_buf[11] == 0x00) {
+ }
+#if 0
+ // not possible with argv (zero terminated strings) (hexcoder-)
+ // do not try to access data_buf[10] and beyond
+ else if (data_buf[9] == 0x00 && data_buf[10] != 0x00 && data_buf[11] == 0x00) {
// Cause a crash if data[10] is not zero, but [9] and [11] are zero
unsigned char invalid_read = *(unsigned char *) 0x00000000;
}
-
+#endif
return 0;
}
diff --git a/unicorn_mode/unicornafl b/unicorn_mode/unicornafl
-Subproject 0bf26f6c2601e1c1c84998551ed7d50b4108fbd
+Subproject f44ec48f8d5929f243522c1152b5b3c0985a554