mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-11 17:51:32 +00:00
commit
9cac7ced05
@ -2,9 +2,9 @@
|
||||
|
||||
<img align="right" src="https://raw.githubusercontent.com/AFLplusplus/Website/main/static/aflpp_bg.svg" alt="AFL++ logo" width="250" height="250">
|
||||
|
||||
Release version: [4.30c](https://github.com/AFLplusplus/AFLplusplus/releases)
|
||||
Release version: [4.31c](https://github.com/AFLplusplus/AFLplusplus/releases)
|
||||
|
||||
GitHub version: 4.31a
|
||||
GitHub version: 4.31c
|
||||
|
||||
Repository:
|
||||
[https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus)
|
||||
@ -230,6 +230,7 @@ Thank you! (For people sending pull requests - please add yourself to this list
|
||||
Ruben ten Hove Joey Jiao
|
||||
fuzzah @intrigus-lgtm
|
||||
Yaakov Saxon Sergej Schumilo
|
||||
Ziqiao Kong
|
||||
```
|
||||
|
||||
</details>
|
||||
|
1
TODO.md
1
TODO.md
@ -2,6 +2,7 @@
|
||||
|
||||
## Must
|
||||
|
||||
- afl_fsrv_deinit cmplog
|
||||
- ijon support?
|
||||
- check for null ptr for xml/curl/g_ string transform functions
|
||||
- hardened_usercopy=0 page_alloc.shuffle=0
|
||||
|
@ -115,7 +115,7 @@ PLATFORM=`uname -s`
|
||||
#if [ "$PLATFORM" = "Linux" ] ; then
|
||||
# CUR_TIME=`cat /proc/uptime | awk '{printf "%.0f\n", $1}'`
|
||||
#else
|
||||
# This will lead to inacurate results but will prevent the script from breaking on platforms other than Linux
|
||||
# This will lead to inaccurate results but will prevent the script from breaking on platforms other than Linux
|
||||
CUR_TIME=`date +%s`
|
||||
#fi
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# custum mutator: AFL++
|
||||
# custom mutator: AFL++
|
||||
|
||||
this is the AFL++ havoc mutator as a custom mutator module for AFL++.
|
||||
|
||||
|
@ -409,7 +409,7 @@ size_t afl_custom_fuzz(atnwalk_mutator_t *data, uint8_t *buf, size_t buf_size,
|
||||
|
||||
} else {
|
||||
|
||||
// new_size fits into buf, so re-use it
|
||||
// new_size fits into buf, so reuse it
|
||||
*out_buf = buf;
|
||||
|
||||
}
|
||||
|
@ -7,6 +7,6 @@ just type `make` to build.
|
||||
You *MUST* use a dictionary file to have an effective grammarless grammar fuzzer!
|
||||
|
||||
```
|
||||
autotokens-standalone -h # to see all parameteres
|
||||
autotokens-standalone -h # to see all parameters
|
||||
autotokens-standalone -x foo.dict inputfile outputfile # example
|
||||
```
|
||||
|
@ -304,7 +304,7 @@ class XmlMutatorMin:
|
||||
|
||||
# Log something
|
||||
if self.verbose:
|
||||
print("Reseting tag #%i '%s'" % (rand_elem_id, rand_elem.tag))
|
||||
print("Resetting tag #%i '%s'" % (rand_elem_id, rand_elem.tag))
|
||||
|
||||
# Reset the node
|
||||
rand_elem.clear()
|
||||
|
@ -80,12 +80,12 @@ def fuzz(buf, add_buf, max_size):
|
||||
via_buffer = False
|
||||
log("fuzz(): Can't initialize mutator with AFL buffer")
|
||||
|
||||
# If init from AFL buffer wasn't succesful
|
||||
# If init from AFL buffer wasn't successful
|
||||
if not via_buffer:
|
||||
log("fuzz(): Returning unmodified AFL buffer")
|
||||
return buf
|
||||
|
||||
# Sucessful initialization -> mutate
|
||||
# Successful initialization -> mutate
|
||||
try:
|
||||
__mutator__.mutate(max=5)
|
||||
log("fuzz(): Input mutated")
|
||||
|
@ -143,7 +143,7 @@ test -e json-c/.libs/libjson-c.a || {
|
||||
echo
|
||||
echo
|
||||
echo "[+] Json-c successfully prepared!"
|
||||
echo "[+] Builing gramatron now."
|
||||
echo "[+] Building gramatron now."
|
||||
$CC -O3 -g -fPIC -Wno-unused-result -Wl,--allow-multiple-definition -I../../include -o gramatron.so -shared -I. -I/prg/dev/include gramfuzz.c gramfuzz-helpers.c gramfuzz-mutators.c gramfuzz-util.c hashmap.c ../../src/afl-performance.o json-c/.libs/libjson-c.a || exit 1
|
||||
echo
|
||||
echo "[+] gramatron successfully built!"
|
||||
|
@ -1,4 +1,4 @@
|
||||
# custum mutator: honggfuzz mangle
|
||||
# custom mutator: honggfuzz mangle
|
||||
|
||||
this is the honggfuzz mutator in mangle.c as a custom mutator
|
||||
module for AFL++. It is the original mangle.c, mangle.h and honggfuzz.h
|
||||
|
@ -850,7 +850,7 @@ static void mangle_ASCIINumChange(run_t *run, bool printable) {
|
||||
|
||||
size_t len = 0;
|
||||
uint64_t val = 0;
|
||||
/* 20 is maximum lenght of a string representing a 64-bit unsigned value */
|
||||
/* 20 is maximum length of a string representing a 64-bit unsigned value */
|
||||
for (len = 0; (len < 20) && (len < left); len++) {
|
||||
|
||||
char c = run->dynfile->data[off + len];
|
||||
|
@ -40,7 +40,7 @@ bool BlockCoverage::AppendCoverage(const std::string &S) {
|
||||
// Coverage lines have this form:
|
||||
// CN X Y Z T
|
||||
// where N is the number of the function, T is the total number of instrumented
|
||||
// BBs, and X,Y,Z, if present, are the indecies of covered BB.
|
||||
// BBs, and X,Y,Z, if present, are the indices of covered BB.
|
||||
// BB #0, which is the entry block, is not explicitly listed.
|
||||
bool BlockCoverage::AppendCoverage(std::istream &IN) {
|
||||
|
||||
|
@ -106,7 +106,7 @@ private:
|
||||
};
|
||||
|
||||
// Parses one dictionary entry.
|
||||
// If successful, write the enty to Unit and returns true,
|
||||
// If successful, write the entry to Unit and returns true,
|
||||
// otherwise returns false.
|
||||
bool ParseOneDictionaryEntry(const std::string &Str, Unit *U);
|
||||
// Parses the dictionary file, fills Units, returns true iff all lines
|
||||
|
@ -427,7 +427,7 @@ void FuzzWithFork(Random &Rand, const FuzzingOptions &Options,
|
||||
|
||||
Env.RunOneMergeJob(Job.get());
|
||||
|
||||
// Continue if our crash is one of the ignorred ones.
|
||||
// Continue if our crash is one of the ignored ones.
|
||||
if (Options.IgnoreTimeouts && ExitCode == Options.TimeoutExitCode)
|
||||
Env.NumTimeouts++;
|
||||
else if (Options.IgnoreOOMs && ExitCode == Options.OOMExitCode)
|
||||
|
@ -452,7 +452,7 @@ void CrashResistantMerge(const Vector<std::string> &Args,
|
||||
auto ExitCode = ExecuteCommand(Cmd);
|
||||
if (!ExitCode) {
|
||||
|
||||
VPrintf(V, "MERGE-OUTER: succesfull in %zd attempt(s)\n", Attempt);
|
||||
VPrintf(V, "MERGE-OUTER: succesful in %zd attempt(s)\n", Attempt);
|
||||
break;
|
||||
|
||||
}
|
||||
|
@ -498,9 +498,9 @@ size_t ChangeBinaryInteger(uint8_t *Data, size_t Size, Random &Rand) {
|
||||
T Add = Rand(21);
|
||||
Add -= 10;
|
||||
if (Rand.RandBool())
|
||||
Val = Bswap(T(Bswap(Val) + Add)); // Add assuming different endiannes.
|
||||
Val = Bswap(T(Bswap(Val) + Add)); // Add assuming different endianness.
|
||||
else
|
||||
Val = Val + Add; // Add assuming current endiannes.
|
||||
Val = Val + Add; // Add assuming current endianness.
|
||||
if (Add == 0 || Rand.RandBool()) // Maybe negate.
|
||||
Val = -Val;
|
||||
|
||||
|
@ -460,7 +460,7 @@ static size_t InternalStrnlen(const char *S, size_t MaxLen) {
|
||||
}
|
||||
|
||||
// Finds min of (strlen(S1), strlen(S2)).
|
||||
// Needed bacause one of these strings may actually be non-zero terminated.
|
||||
// Needed because one of these strings may actually be non-zero terminated.
|
||||
static size_t InternalStrnlen2(const char *S1, const char *S2) {
|
||||
|
||||
size_t Len = 0;
|
||||
|
@ -1,4 +1,4 @@
|
||||
# custum mutator: libfuzzer LLVMFuzzerMutate()
|
||||
# custom mutator: libfuzzer LLVMFuzzerMutate()
|
||||
|
||||
This uses the libfuzzer LLVMFuzzerMutate() function in llvm 12.
|
||||
|
||||
|
@ -2,7 +2,7 @@ CUR_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
|
||||
|
||||
all: radamsa-mutator.so
|
||||
|
||||
# These can be overriden:
|
||||
# These can be overridden:
|
||||
CFLAGS ?= $(CFLAGS_FLTO)
|
||||
|
||||
# These are required: (otherwise radamsa gets very very slooooow)
|
||||
|
@ -1,4 +1,4 @@
|
||||
# custum mutator: libradamsa
|
||||
# custom mutator: libradamsa
|
||||
|
||||
Pretranslated radamsa library. This code belongs to the radamsa author.
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# custum mutator: symcc
|
||||
# custom mutator: symcc
|
||||
|
||||
This uses the symcc to find new paths into the target.
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
# custum mutator: symqemu
|
||||
# custom mutator: symqemu
|
||||
|
||||
This uses the symcc to find new paths into the target.
|
||||
|
||||
|
@ -4,9 +4,11 @@
|
||||
release of the tool. See README.md for the general instruction manual.
|
||||
|
||||
|
||||
### Version ++4.31a (dev)
|
||||
### Version ++4.31c (release)
|
||||
- SAND mode added (docs/SAND.md) for more effecient fuzzing with sanitizers
|
||||
(thanks to @wtdcode !)
|
||||
- afl-fuzz:
|
||||
- splicing is now DISABLED by default because research showed
|
||||
- splicing phase is now DISABLED by default because research showed
|
||||
it is counterproductive. New command line parameter `-u` to enable
|
||||
it. Splicing is auto-enabled if two cycles without finds happen.
|
||||
- Python 3.13+ support
|
||||
|
@ -106,7 +106,7 @@ If you find an interesting or important question missing, submit it via
|
||||
<details>
|
||||
<summary id="should-you-ever-stop-afl-fuzz-minimize-the-corpus-and-restart">Should you ever stop afl-fuzz, minimize the corpus and restart?</summary><p>
|
||||
|
||||
To stop afl-fuzz, minimize it's corpus and restart you would usually do:
|
||||
To stop afl-fuzz, minimize its corpus and restart you would usually do:
|
||||
|
||||
```
|
||||
Control-C # to terminate afl-fuzz
|
||||
@ -274,7 +274,7 @@ If you find an interesting or important question missing, submit it via
|
||||
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. Note that there is additionally `AFL_IGNORE_PROBLEMS_COVERAGE` to
|
||||
additionally tell AFL++ to ignore any coverage from the late loaded libaries.
|
||||
additionally tell AFL++ to ignore any coverage from the late loaded libraries.
|
||||
</p></details>
|
||||
|
||||
<details>
|
||||
|
81
docs/SAND.md
Normal file
81
docs/SAND.md
Normal file
@ -0,0 +1,81 @@
|
||||
# SAND: Decoupling Sanitization from Fuzzing for Low Overhead
|
||||
|
||||
- Authors: Ziqiao Kong, Shaohua Li, Heqing Huang, Zhendong Su
|
||||
- Maintainer: [Ziqiao Kong](https://github.com/wtdcode)
|
||||
- Preprint: [arXiv](https://arxiv.org/abs/2402.16497), accepted by ICSE 2025
|
||||
- Main repo (for paper, reproduction, reference or cite): https://github.com/wtdcode/sand-aflpp
|
||||
|
||||
## Motivation
|
||||
|
||||
SAND introduces a new fuzzing workflow that can greatly reduce (or even eliminate) sanitizer overhead and combine different sanitizers in one fuzzing campaign.
|
||||
|
||||
The key point of SAND is that: sanitizing all inputs is wasting fuzzing power, because bug-triggering inputs are extremely rare (~1%). Obviously, not all inputs worth going through sanitizers. Therefore, if we can somehow "predict" if an input could trigger bugs (defined as "execution pattern"), we could greatly save fuzzing power by only sanitizing a small proportion of all inputs. That's exactly how SAND works.
|
||||
|
||||
## Usage
|
||||
|
||||
For a normal fuzzing workflow, we have:
|
||||
|
||||
1. Build target project with AFL_USE_ASAN=1 to get `target_asan`
|
||||
2. Fuzz the target with `afl-fuzz -i seeds -o out -- ./target_asan`
|
||||
|
||||
For SAND fuzzing workflow, this is slightly different:
|
||||
|
||||
1. Build target project _without_ any sanitizers to get `target_native`, which we will define as a "native binary". It is usually done by using `afl-clang-fast/lto(++)` to compile your project _without_ `AFL_USE_ASAN/UBSAN/MSAN`.
|
||||
2. Build target project with AFL_USE_ASAN=1 AFL_SAN_NO_INST=1 to get `target_asan`. Do note this step can be repeated for multiple sanitizers, like MSAN, UBSAN etc. It is also possible to have ASAN and UBSAN to build together.
|
||||
3. Fuzz the target with `afl-fuzz -i seeds -o out -w ./target_asan -- ./target_native`. Note `-w` can be specified multiple times.
|
||||
|
||||
Then you get:
|
||||
|
||||
- almost the same performance as `afl-fuzz -i seeds -o out -- ./target_native`
|
||||
- and the same bug-finding capability as `afl-fuzz -i seeds -o out -- ./target_asan`
|
||||
|
||||
## Example Workflow
|
||||
|
||||
Take [test-instr.c](../test-instr.c) as an example.
|
||||
|
||||
1. Build the native binary
|
||||
|
||||
```bash
|
||||
afl-clang-fast test-instr.c -o ./native
|
||||
```
|
||||
|
||||
Just like the normal building process, except using `afl-clang-fast`
|
||||
|
||||
2. Build the sanitizers-enabled binaries.
|
||||
|
||||
```bash
|
||||
AFL_SAN_NO_INST=1 AFL_USE_UBSAN=1 AFL_USE_ASAN=1 afl-clang-fast test-instr.c -o ./asanubsan
|
||||
AFL_SAN_NO_INST=1 AFL_USE_MSAN=1 afl-clang-fast test-instr.c -o ./msan
|
||||
```
|
||||
|
||||
Do note `AFL_SAN_NO_INST=1` is crucial, this enables forkservers but disables pc instrumentation. Do not reuse sanitizers-enabled binaries built _without_ `AFL_SAN_NO_INST=1`. This will mess up SAND execution pattern.
|
||||
|
||||
3. Start fuzzing
|
||||
|
||||
```bash
|
||||
mkdir /tmp/test
|
||||
echo "a" > /tmp/test/a
|
||||
AFL_NO_UI=1 AFL_SKIP_CPUFREQ=1 afl-fuzz -i /tmp/test -o /tmp/out -w ./asanubsan -w ./msan -- ./native @@
|
||||
```
|
||||
|
||||
That's it!
|
||||
|
||||
## Tips
|
||||
|
||||
### Alternative execution patterns
|
||||
|
||||
By default, SAND uses the hash value of the simplified coverage map as execution pattern, i.e. if an input has a unique simplefied coverage map, it will be sent to sanitizers for inspection. This shall work for most cases. However, if you are strongly worried about missing bugs, try `AFL_SAN_ABSTRACTION=unique_trace afl-fuzz ...`, which filters inputs having a _unique coverage map_. Do note this significantly increases the number of inputs by 4-10 times, leading to much lower throughput. Alternatively, SAND also supports `AFL_SAN_ABSTRACTION=coverage_increase`, which essentially equals to running sanitizers on the corpus and thus having almost zero overhead, but at a cost of missing ~15% bugs in our evaluation.
|
||||
|
||||
### Run as many sanitizers as possible
|
||||
|
||||
Though we just used ASAN as an example, SAND works best if you provide more sanitizers, for example, UBSAN and MSAN.
|
||||
|
||||
You might do it via `afl-fuzz -i seeds -o out -w ./target_asan -w ./target_msan -w ./target_ubsan -- ./target_native`. Don't worry about the slow sanitizers like MSAN, SAND could still run very fast because only rather a few inputs are sanitized.
|
||||
|
||||
### Bugs types
|
||||
|
||||
The execution pattern evaluated in our papers is targeting the common bugs, as ASAN/MSAN/UBSAN catches. For other bug types, you probably need to define new execution patterns and re-evaluate.
|
||||
|
||||
### My throughput is greatly impacted
|
||||
|
||||
Generally, this is due to too many inputs going through sanitizers, for example, because of unstable targets. You could check stats from `plot_file` to confirm this. Try to switch execution patterns as stated above.
|
@ -6,7 +6,7 @@ coverage to effortlessly pick up subtle, local-scale changes to program control
|
||||
flow.
|
||||
|
||||
Note: If you are interested in a more current up-to-date deep dive how AFL++
|
||||
works then we commend this blog post:
|
||||
works then we recommend this blog post:
|
||||
[https://blog.ritsec.club/posts/afl-under-hood/](https://blog.ritsec.club/posts/afl-under-hood/)
|
||||
|
||||
Simplifying a bit, the overall algorithm can be summed up as:
|
||||
|
@ -151,7 +151,7 @@ def deinit(): # optional for Python
|
||||
splicing - or anything else - and can also be ignored. If you are not
|
||||
using this additional data then define `splice_optout` (see above).
|
||||
This function is optional.
|
||||
Returing a length of 0 is valid and is interpreted as skipping this
|
||||
Returning a length of 0 is valid and is interpreted as skipping this
|
||||
one mutation result.
|
||||
For non-Python: the returned output buffer is under **your** memory
|
||||
management!
|
||||
|
@ -247,7 +247,7 @@ used if several separated instrumentations are performed which are then later
|
||||
combined.
|
||||
|
||||
- `AFL_LLVM_LTO_CALLER` activates collision free CALLER instrumentation
|
||||
- `AFL_LLVM_LTO_CALLER` sets the maximum mumber of single block functions
|
||||
- `AFL_LLVM_LTO_CALLER` sets the maximum number of single block functions
|
||||
to dig deeper into a real function. Default 0.
|
||||
- `AFL_LLVM_DOCUMENT_IDS=file` will document to a file which edge ID was given
|
||||
to which function. This helps to identify functions with variable bytes or
|
||||
|
@ -196,7 +196,7 @@ afl-clang-fast's.
|
||||
|
||||
RetroWrite is a static binary rewriter that can be combined with AFL++. If you
|
||||
have an x86_64 or arm64 binary that does not contain C++ exceptions and - if
|
||||
x86_64 - still has it's symbols and compiled with position independent code
|
||||
x86_64 - still has its symbols and compiled with position independent code
|
||||
(PIC/PIE), then the RetroWrite solution might be for you.
|
||||
It decompiles to ASM files which can then be instrumented with afl-gcc.
|
||||
Note that afl-gcc is only present until AFL++ v4.21c and was subsequently removed as it is obsolete.
|
||||
|
@ -203,6 +203,9 @@ instances, so running more than one address sanitized target would be a waste.
|
||||
*IF* you are running a saturated corpus, then you can run up to half of the
|
||||
instances with sanitizers.
|
||||
|
||||
An alternative but more effective approach is to use [SAND](./SAND.md) which could
|
||||
combine different sanitizers at a much higher throughput.
|
||||
|
||||
The following sanitizers have built-in support in AFL++:
|
||||
|
||||
* ASAN = Address SANitizer, finds memory corruption vulnerabilities like
|
||||
|
@ -39,7 +39,7 @@ is *VERY* important to carry out these basic steps first before taking on the
|
||||
additional complexity of debugging with FRIDA mode or `afl-fuzz`.
|
||||
|
||||
- Run your harness outside of the fuzzer, passing it a representative seed as
|
||||
it's input `./harness <input>`.
|
||||
its input `./harness <input>`.
|
||||
- Pass your harness multiple seeds to check that it is stable when running
|
||||
multiple tests as it will when running in fork server mode `./harness <input1>
|
||||
<intput2>`.
|
||||
|
@ -107,7 +107,7 @@ every block of code we execute, performance is critical.
|
||||
However, the design of the binary instrumentation modes of AFL++ has moved on.
|
||||
Both QEMU and FRIDA modes use a two stage process when executing a target
|
||||
application. Each block is first compiled or instrumented, and then it is
|
||||
executed. The compiled blocks can be re-used each time the target executes them.
|
||||
executed. The compiled blocks can be reused each time the target executes them.
|
||||
|
||||
Since a blocks ID is based on its address, and this is known at compile time, we
|
||||
only need to generate this ID once per block and so this ID generation no longer
|
||||
|
@ -200,10 +200,10 @@ instrumented address block translations.
|
||||
* `AFL_FRIDA_INST_NO_SUPPRESS` - Disable deterministic branch suppression.
|
||||
Deterministic branch suppression skips the preamble which generates coverage
|
||||
information at the start of each block, if the block is reached by a
|
||||
deterministic branch. This reduces map polution, and may improve performance
|
||||
deterministic branch. This reduces map pollution, and may improve performance
|
||||
when all the executing blocks have been prefetched and backpatching applied.
|
||||
However, in the event that backpatching is incomplete, this may incur a
|
||||
performance penatly as branch instructions are disassembled on each branch.
|
||||
performance penalty as branch instructions are disassembled on each branch.
|
||||
* `AFL_FRIDA_INST_SEED` - Sets the initial seed for the hash function used to
|
||||
generate block (and hence edge) IDs. Setting this to a constant value may be
|
||||
useful for debugging purposes, e.g., investigating unstable edges.
|
||||
@ -215,7 +215,7 @@ instrumented address block translations.
|
||||
coverage information for unstable edges (e.g., to be loaded within IDA
|
||||
lighthouse).
|
||||
* `AFL_FRIDA_JS_SCRIPT` - Set the script to be loaded by the FRIDA scripting
|
||||
engine. See [Scipting.md](Scripting.md) for details.
|
||||
engine. See [Scripting.md](Scripting.md) for details.
|
||||
* `AFL_FRIDA_OUTPUT_STDOUT` - Redirect the standard output of the target
|
||||
application to the named file (supersedes the setting of `AFL_DEBUG_CHILD`).
|
||||
* `AFL_FRIDA_OUTPUT_STDERR` - Redirect the standard error of the target
|
||||
|
@ -724,16 +724,16 @@ class Afl {
|
||||
* it takes as arguments a `NativePointer` and a `number`. It can be
|
||||
* called multiple times to exclude several ranges.
|
||||
*/
|
||||
static addExcludedRange(addressess, size) {
|
||||
Afl.jsApiAddExcludeRange(addressess, size);
|
||||
static addExcludedRange(addresses, size) {
|
||||
Afl.jsApiAddExcludeRange(addresses, size);
|
||||
}
|
||||
/**
|
||||
* This is equivalent to setting a value in `AFL_FRIDA_INST_RANGES`,
|
||||
* it takes as arguments a `NativePointer` and a `number`. It can be
|
||||
* called multiple times to include several ranges.
|
||||
*/
|
||||
static addIncludedRange(addressess, size) {
|
||||
Afl.jsApiAddIncludeRange(addressess, size);
|
||||
static addIncludedRange(addresses, size) {
|
||||
Afl.jsApiAddIncludeRange(addresses, size);
|
||||
}
|
||||
/**
|
||||
* This must always be called at the end of your script. This lets
|
||||
@ -771,7 +771,7 @@ class Afl {
|
||||
}
|
||||
/**
|
||||
* Print a message to the STDOUT. This should be preferred to
|
||||
* FRIDA's `console.log` since FRIDA will queue it's log messages.
|
||||
* FRIDA's `console.log` since FRIDA will queue its log messages.
|
||||
* If `console.log` is used in a callback in particular, then there
|
||||
* may no longer be a thread running to service this queue.
|
||||
*/
|
||||
@ -893,14 +893,14 @@ class Afl {
|
||||
}
|
||||
/**
|
||||
* This is equivalent to setting `AFL_FRIDA_PERSISTENT_ADDR`, again a
|
||||
* `NativePointer` should be provided as it's argument.
|
||||
* `NativePointer` should be provided as its argument.
|
||||
*/
|
||||
static setPersistentAddress(address) {
|
||||
Afl.jsApiSetPersistentAddress(address);
|
||||
}
|
||||
/**
|
||||
* This is equivalent to setting `AFL_FRIDA_PERSISTENT_CNT`, a
|
||||
* `number` should be provided as it's argument.
|
||||
* `number` should be provided as its argument.
|
||||
*/
|
||||
static setPersistentCount(count) {
|
||||
Afl.jsApiSetPersistentCount(count);
|
||||
@ -920,7 +920,7 @@ class Afl {
|
||||
}
|
||||
/**
|
||||
* This is equivalent to setting `AFL_FRIDA_PERSISTENT_RET`, again a
|
||||
* `NativePointer` should be provided as it's argument.
|
||||
* `NativePointer` should be provided as its argument.
|
||||
*/
|
||||
static setPersistentReturn(address) {
|
||||
Afl.jsApiSetPersistentReturn(address);
|
||||
|
@ -4,6 +4,6 @@ This folder contains a Docker image to allow the building of
|
||||
`afl-frida-trace.so` using the `many-linux` docker image. This docker image is
|
||||
based on CentOS Linux 5. By building `afl-frida-trace.so` for such an old
|
||||
version of Linux, given the strong backward compatibility of Linux, this should
|
||||
work on the majority of Linux environments. This may be useful for targetting
|
||||
work on the majority of Linux environments. This may be useful for targeting
|
||||
Linux distributions other than your development environment. `many-local` builds
|
||||
`AFLplusplus` from the local working copy in the `many-linux` environment.
|
||||
|
@ -166,7 +166,7 @@ gboolean cmplog_is_readable(guint64 addr, size_t size) {
|
||||
*/
|
||||
if (addr < DEFAULT_MMAP_MIN_ADDR) { return false; }
|
||||
|
||||
/* Check our addres/length don't wrap around */
|
||||
/* Check our address/length don't wrap around */
|
||||
if (SIZE_MAX - addr < size) { return false; }
|
||||
|
||||
GumAddress inner_base = addr;
|
||||
|
@ -186,7 +186,7 @@ static void instrument_basic_block(GumStalkerIterator *iterator,
|
||||
* execution), we instead ensure that we honour the additional
|
||||
* instrumentation requested (e.g. coverage, asan and complog) when a block
|
||||
* is compiled no matter where we are during initialization. We will end up
|
||||
* re-using these blocks if the code under test calls a block which is also
|
||||
* reusing these blocks if the code under test calls a block which is also
|
||||
* used during initialization.
|
||||
*
|
||||
* Coverage data generated during initialization isn't a problem since the
|
||||
|
@ -285,7 +285,7 @@ static void instrument_coverage_switch(GumStalkerObserver *self,
|
||||
|
||||
/*
|
||||
* If the branch is deterministic, then we should start execution at the
|
||||
* begining of the block. From here, we will branch and skip the coverage
|
||||
* beginning of the block. From here, we will branch and skip the coverage
|
||||
* code and jump right to the target code of the instrumented block.
|
||||
* Otherwise, if the branch is non-deterministic, then we need to branch
|
||||
* part way into the block to where the coverage instrumentation starts.
|
||||
@ -516,7 +516,7 @@ void instrument_coverage_optimize(const cs_insn *instr,
|
||||
* an instruction to load x16,x17 from beyond the red-zone on the stack. A
|
||||
* pair of registers are saved/restored because on AARCH64, the stack pointer
|
||||
* must be 16 byte aligned. This instruction is emitted into the block before
|
||||
* the tranformer (from which we are called) is executed. If is is possible
|
||||
* the transformer (from which we are called) is executed. If is is possible
|
||||
* for Stalker to make a direct branch (the target block is close enough), it
|
||||
* can forego pushing the registers and instead branch at an offset into the
|
||||
* block to skip this restoration prolog.
|
||||
|
@ -5,16 +5,16 @@ class Afl {
|
||||
* it takes as arguments a `NativePointer` and a `number`. It can be
|
||||
* called multiple times to exclude several ranges.
|
||||
*/
|
||||
static addExcludedRange(addressess, size) {
|
||||
Afl.jsApiAddExcludeRange(addressess, size);
|
||||
static addExcludedRange(addresses, size) {
|
||||
Afl.jsApiAddExcludeRange(addresses, size);
|
||||
}
|
||||
/**
|
||||
* This is equivalent to setting a value in `AFL_FRIDA_INST_RANGES`,
|
||||
* it takes as arguments a `NativePointer` and a `number`. It can be
|
||||
* called multiple times to include several ranges.
|
||||
*/
|
||||
static addIncludedRange(addressess, size) {
|
||||
Afl.jsApiAddIncludeRange(addressess, size);
|
||||
static addIncludedRange(addresses, size) {
|
||||
Afl.jsApiAddIncludeRange(addresses, size);
|
||||
}
|
||||
/**
|
||||
* This must always be called at the end of your script. This lets
|
||||
@ -52,7 +52,7 @@ class Afl {
|
||||
}
|
||||
/**
|
||||
* Print a message to the STDOUT. This should be preferred to
|
||||
* FRIDA's `console.log` since FRIDA will queue it's log messages.
|
||||
* FRIDA's `console.log` since FRIDA will queue its log messages.
|
||||
* If `console.log` is used in a callback in particular, then there
|
||||
* may no longer be a thread running to service this queue.
|
||||
*/
|
||||
@ -205,14 +205,14 @@ class Afl {
|
||||
}
|
||||
/**
|
||||
* This is equivalent to setting `AFL_FRIDA_PERSISTENT_ADDR`, again a
|
||||
* `NativePointer` should be provided as it's argument.
|
||||
* `NativePointer` should be provided as its argument.
|
||||
*/
|
||||
static setPersistentAddress(address) {
|
||||
Afl.jsApiSetPersistentAddress(address);
|
||||
}
|
||||
/**
|
||||
* This is equivalent to setting `AFL_FRIDA_PERSISTENT_CNT`, a
|
||||
* `number` should be provided as it's argument.
|
||||
* `number` should be provided as its argument.
|
||||
*/
|
||||
static setPersistentCount(count) {
|
||||
Afl.jsApiSetPersistentCount(count);
|
||||
@ -232,7 +232,7 @@ class Afl {
|
||||
}
|
||||
/**
|
||||
* This is equivalent to setting `AFL_FRIDA_PERSISTENT_RET`, again a
|
||||
* `NativePointer` should be provided as it's argument.
|
||||
* `NativePointer` should be provided as its argument.
|
||||
*/
|
||||
static setPersistentReturn(address) {
|
||||
Afl.jsApiSetPersistentReturn(address);
|
||||
|
@ -37,7 +37,7 @@ static void convert_address_token(gchar *token, GumMemoryRange *range) {
|
||||
|
||||
if (token_count != 2) {
|
||||
|
||||
FFATAL("Invalid range (should have two addresses seperated by a '-'): %s\n",
|
||||
FFATAL("Invalid range (should have two addresses separated by a '-'): %s\n",
|
||||
token);
|
||||
|
||||
}
|
||||
|
@ -11,8 +11,8 @@ class Afl {
|
||||
* it takes as arguments a `NativePointer` and a `number`. It can be
|
||||
* called multiple times to exclude several ranges.
|
||||
*/
|
||||
public static addExcludedRange(addressess: NativePointer, size: number): void {
|
||||
Afl.jsApiAddExcludeRange(addressess, size);
|
||||
public static addExcludedRange(addresses: NativePointer, size: number): void {
|
||||
Afl.jsApiAddExcludeRange(addresses, size);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -20,8 +20,8 @@ class Afl {
|
||||
* it takes as arguments a `NativePointer` and a `number`. It can be
|
||||
* called multiple times to include several ranges.
|
||||
*/
|
||||
public static addIncludedRange(addressess: NativePointer, size: number): void {
|
||||
Afl.jsApiAddIncludeRange(addressess, size);
|
||||
public static addIncludedRange(addresses: NativePointer, size: number): void {
|
||||
Afl.jsApiAddIncludeRange(addresses, size);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -66,7 +66,7 @@ class Afl {
|
||||
|
||||
/**
|
||||
* Print a message to the STDOUT. This should be preferred to
|
||||
* FRIDA's `console.log` since FRIDA will queue it's log messages.
|
||||
* FRIDA's `console.log` since FRIDA will queue its log messages.
|
||||
* If `console.log` is used in a callback in particular, then there
|
||||
* may no longer be a thread running to service this queue.
|
||||
*/
|
||||
@ -241,7 +241,7 @@ class Afl {
|
||||
|
||||
/**
|
||||
* This is equivalent to setting `AFL_FRIDA_PERSISTENT_ADDR`, again a
|
||||
* `NativePointer` should be provided as it's argument.
|
||||
* `NativePointer` should be provided as its argument.
|
||||
*/
|
||||
public static setPersistentAddress(address: NativePointer): void {
|
||||
Afl.jsApiSetPersistentAddress(address);
|
||||
@ -249,7 +249,7 @@ class Afl {
|
||||
|
||||
/**
|
||||
* This is equivalent to setting `AFL_FRIDA_PERSISTENT_CNT`, a
|
||||
* `number` should be provided as it's argument.
|
||||
* `number` should be provided as its argument.
|
||||
*/
|
||||
public static setPersistentCount(count: number): void {
|
||||
Afl.jsApiSetPersistentCount(count);
|
||||
@ -272,7 +272,7 @@ class Afl {
|
||||
|
||||
/**
|
||||
* This is equivalent to setting `AFL_FRIDA_PERSISTENT_RET`, again a
|
||||
* `NativePointer` should be provided as it's argument.
|
||||
* `NativePointer` should be provided as its argument.
|
||||
*/
|
||||
public static setPersistentReturn(address: NativePointer): void {
|
||||
Afl.jsApiSetPersistentReturn(address);
|
||||
|
@ -75,6 +75,7 @@
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/types.h>
|
||||
#include "asanfuzz.h"
|
||||
|
||||
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || \
|
||||
defined(__NetBSD__) || defined(__DragonFly__)
|
||||
@ -610,7 +611,11 @@ typedef struct afl_state {
|
||||
u8 *var_bytes; /* Bytes that appear to be variable */
|
||||
|
||||
#define N_FUZZ_SIZE (1 << 21)
|
||||
#define N_FUZZ_SIZE_BITMAP (1 << 29)
|
||||
u32 *n_fuzz;
|
||||
u8 *n_fuzz_dup;
|
||||
u8 *classified_n_fuzz;
|
||||
u8 *simplified_n_fuzz;
|
||||
|
||||
volatile u8 stop_soon, /* Ctrl-C pressed? */
|
||||
clear_screen; /* Window resized? */
|
||||
@ -728,6 +733,13 @@ typedef struct afl_state {
|
||||
char *cmplog_binary;
|
||||
afl_forkserver_t cmplog_fsrv; /* cmplog has its own little forkserver */
|
||||
|
||||
/* ASAN Fuzing */
|
||||
char *san_binary[MAX_EXTRA_SAN_BINARY];
|
||||
afl_forkserver_t san_fsrvs[MAX_EXTRA_SAN_BINARY];
|
||||
u8 san_binary_length; /* 0 means extra san binaries not given */
|
||||
u32 san_case_status;
|
||||
enum SanitizerAbstraction san_abstraction;
|
||||
|
||||
/* Custom mutators */
|
||||
struct custom_mutator *mutator;
|
||||
|
||||
@ -908,7 +920,7 @@ struct custom_mutator {
|
||||
/**
|
||||
* Opt-out of a splicing input for the fuzz mutator
|
||||
*
|
||||
* Empty dummy function. It's presence tells afl-fuzz not to pass a
|
||||
* Empty dummy function. Its presence tells afl-fuzz not to pass a
|
||||
* splice data pointer and len.
|
||||
*
|
||||
* @param data pointer returned in afl_custom_init by this custom mutator
|
||||
@ -940,12 +952,12 @@ struct custom_mutator {
|
||||
/**
|
||||
* Describe the current testcase, generated by the last mutation.
|
||||
* This will be called, for example, to give the written testcase a name
|
||||
* after a crash ocurred. It can help to reproduce crashing mutations.
|
||||
* after a crash occurred. It can help to reproduce crashing mutations.
|
||||
*
|
||||
* (Optional)
|
||||
*
|
||||
* @param data pointer returned by afl_customm_init for this custom mutator
|
||||
* @paramp[in] max_description_len maximum size avaliable for the description.
|
||||
* @paramp[in] max_description_len maximum size available for the description.
|
||||
* A longer return string is legal, but will be truncated.
|
||||
* @return A valid ptr to a 0-terminated string.
|
||||
* An empty or NULL return will result in a default description
|
||||
@ -1122,7 +1134,7 @@ struct custom_mutator {
|
||||
void afl_state_init(afl_state_t *, uint32_t map_size);
|
||||
void afl_state_deinit(afl_state_t *);
|
||||
|
||||
/* Set stop_soon flag on all childs, kill all childs */
|
||||
/* Set stop_soon flag on all children, kill all children */
|
||||
void afl_states_stop(void);
|
||||
/* Set clear_screen flag on all states */
|
||||
void afl_states_clear_screen(void);
|
||||
|
54
include/asanfuzz.h
Normal file
54
include/asanfuzz.h
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
american fuzzy lop++ - cmplog header
|
||||
------------------------------------
|
||||
|
||||
Originally written by Michal Zalewski
|
||||
|
||||
Forkserver design by Jann Horn <jannhorn@googlemail.com>
|
||||
|
||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||
Dominik Maier <mail@dmnk.co>,
|
||||
Andrea Fioraldi <andreafioraldi@gmail.com>,
|
||||
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>
|
||||
|
||||
Copyright 2016, 2017 Google Inc. All rights reserved.
|
||||
Copyright 2019-2023 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:
|
||||
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Shared code to handle the shared memory. This is used by the fuzzer
|
||||
as well the other components like afl-tmin, afl-showmap, etc...
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _AFL_ASAMFUZZ_H
|
||||
#define _AFL_ASAMFUZZ_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
// new_bits for describe_op
|
||||
// new_bits value 1, 2 and 0x80 are already used!
|
||||
#define SAN_CRASH_ONLY (1 << 4)
|
||||
#define NON_COV_INCREASE_BUG (1 << 5)
|
||||
|
||||
enum SanitizerAbstraction {
|
||||
|
||||
SIMPLIFY_TRACE = 0, // Feed all unique trace to sanitizers, the
|
||||
// most sensitive
|
||||
UNIQUE_TRACE,
|
||||
COVERAGE_INCREASE // Feed all coverage increasing cases to sanitizers, the
|
||||
// least sensitive
|
||||
|
||||
};
|
||||
|
||||
/* Execs the child */
|
||||
|
||||
struct afl_forkserver;
|
||||
void sanfuzz_exec_child(struct afl_forkserver *fsrv, char **argv);
|
||||
|
||||
#endif
|
||||
|
@ -76,8 +76,9 @@ u8 *find_afl_binary(u8 *own_loc, u8 *fname);
|
||||
int parse_afl_kill_signal(u8 *numeric_signal_as_str, int default_signal);
|
||||
|
||||
/* Configure the signals that are used to kill the forkserver
|
||||
and the forked childs. If `afl_kill_signal_env` or `afl_fsrv_kill_signal_env`
|
||||
is NULL, the appropiate values are read from the environment. */
|
||||
and the forked children. If `afl_kill_signal_env` or
|
||||
`afl_fsrv_kill_signal_env` is NULL, the appropriate values are read from the
|
||||
environment. */
|
||||
void configure_afl_kill_signals(afl_forkserver_t *fsrv,
|
||||
char *afl_kill_signal_env,
|
||||
char *afl_fsrv_kill_signal_env,
|
||||
|
@ -26,7 +26,7 @@
|
||||
/* Version string: */
|
||||
|
||||
// c = release, a = volatile github dev, e = experimental branch
|
||||
#define VERSION "++4.31a"
|
||||
#define VERSION "++4.31c"
|
||||
|
||||
/******************************************************
|
||||
* *
|
||||
@ -39,7 +39,7 @@
|
||||
However if a target has problematic constructors and init arrays then
|
||||
this can fail. Hence afl-fuzz deploys a larger default map. The largest
|
||||
map seen so far is the xlsx fuzzer for libreoffice which is 5MB.
|
||||
At runtime this value can be overriden via AFL_MAP_SIZE.
|
||||
At runtime this value can be overridden via AFL_MAP_SIZE.
|
||||
Default: 8MB (defined in bytes) */
|
||||
#define DEFAULT_SHMEM_SIZE (8 * 1024 * 1024)
|
||||
|
||||
@ -97,11 +97,17 @@
|
||||
/* Maximum allowed fails per CMP value. Default: 96 */
|
||||
#define CMPLOG_FAIL_MAX 96
|
||||
|
||||
/*
|
||||
* Effective fuzzing with selective feeding inputs
|
||||
*/
|
||||
|
||||
#define MAX_EXTRA_SAN_BINARY 4
|
||||
|
||||
/* -------------------------------------*/
|
||||
/* Now non-cmplog configuration options */
|
||||
/* -------------------------------------*/
|
||||
|
||||
/* If a persistent target keeps state and found crashes are not reproducable
|
||||
/* If a persistent target keeps state and found crashes are not reproducible
|
||||
then enable this option and set the AFL_PERSISTENT_RECORD env variable
|
||||
to a number. These number of testcases prior and including the crash case
|
||||
will be kept and written to the crash/ directory as RECORD:... files.
|
||||
@ -504,6 +510,9 @@
|
||||
|
||||
#define CMPLOG_SHM_ENV_VAR "__AFL_CMPLOG_SHM_ID"
|
||||
|
||||
/* ASAN SHM ID */
|
||||
#define AFL_ASAN_FUZZ_SHM_ENV_VAR "__AFL_ASAN_SHM_ID"
|
||||
|
||||
/* CPU Affinity lockfile env var */
|
||||
|
||||
#define CPU_AFFINITY_ENV_VAR "__AFL_LOCKFILE"
|
||||
@ -535,7 +544,7 @@
|
||||
|
||||
#define AFL_TXT_MAX_LEN 65535
|
||||
|
||||
/* What is the minimum percentage of ascii characters present to be classifed
|
||||
/* What is the minimum percentage of ascii characters present to be classified
|
||||
as "is_ascii"? */
|
||||
|
||||
#define AFL_TXT_MIN_PERCENT 99
|
||||
|
@ -72,6 +72,22 @@ inline void classify_counts(afl_forkserver_t *fsrv) {
|
||||
|
||||
}
|
||||
|
||||
inline static void classify_counts_mem(u64 *mem, u32 size) {
|
||||
|
||||
u32 i = (size >> 3);
|
||||
|
||||
while (i--) {
|
||||
|
||||
/* Optimize for sparse bitmaps. */
|
||||
|
||||
if (unlikely(*mem)) { *mem = classify_word(*mem); }
|
||||
|
||||
mem++;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Updates the virgin bits, then reflects whether a new count or a new tuple is
|
||||
* seen in ret. */
|
||||
inline void discover_word(u8 *ret, u64 *current, u64 *virgin) {
|
||||
|
@ -117,9 +117,8 @@ static char *afl_environment_variables[] = {
|
||||
"AFL_USE_UBSAN", "AFL_UBSAN_VERBOSE", "AFL_USE_TSAN", "AFL_USE_CFISAN",
|
||||
"AFL_CFISAN_VERBOSE", "AFL_USE_LSAN", "AFL_WINE_PATH", "AFL_NO_SNAPSHOT",
|
||||
"AFL_EXPAND_HAVOC_NOW", "AFL_USE_FASAN", "AFL_USE_QASAN",
|
||||
"AFL_PRINT_FILENAMES", "AFL_PIZZA_MODE", "AFL_NO_FASTRESUME", NULL
|
||||
|
||||
};
|
||||
"AFL_PRINT_FILENAMES", "AFL_PIZZA_MODE", "AFL_NO_FASTRESUME",
|
||||
"AFL_SAN_ABSTRACTION", "AFL_SAN_NO_INST", "AFL_SAN_RECOVER", NULL};
|
||||
|
||||
extern char *afl_environment_variables[];
|
||||
|
||||
|
@ -159,6 +159,9 @@ typedef struct afl_forkserver {
|
||||
|
||||
bool debug; /* debug mode? */
|
||||
|
||||
u8 san_but_not_instrumented; /* Is it sanitizer enabled but not instrumented?
|
||||
*/
|
||||
|
||||
bool uses_crash_exitcode; /* Custom crash exitcode specified? */
|
||||
u8 crash_exitcode; /* The crash exitcode specified */
|
||||
|
||||
@ -167,6 +170,7 @@ typedef struct afl_forkserver {
|
||||
u8 *shmem_fuzz; /* allocated memory for fuzzing */
|
||||
|
||||
char *cmplog_binary; /* the name of the cmplog binary */
|
||||
char *asanfuzz_binary; /* the name of the ASAN binary */
|
||||
|
||||
/* persistent mode replay functionality */
|
||||
u32 persistent_record; /* persistent replay setting */
|
||||
|
@ -51,6 +51,7 @@ typedef struct sharedmem {
|
||||
size_t map_size; /* actual allocated size */
|
||||
|
||||
int cmplog_mode;
|
||||
int sanfuzz_mode;
|
||||
int shmemfuzz_mode;
|
||||
struct cmp_map *cmp_map;
|
||||
|
||||
|
@ -63,7 +63,7 @@
|
||||
* // To enable unaligned access, but indicate that it significantly slow.
|
||||
* #define T1HA_SYS_UNALIGNED_ACCESS 1
|
||||
*
|
||||
* // To enable unaligned access, and indicate that it effecient.
|
||||
* // To enable unaligned access, and indicate that it's efficient.
|
||||
* #define T1HA_SYS_UNALIGNED_ACCESS 2
|
||||
*
|
||||
*
|
||||
@ -512,7 +512,7 @@ T1HA_API uint64_t t1ha2_atonce128(uint64_t *__restrict extra_result,
|
||||
uint64_t seed);
|
||||
|
||||
/* The init/update/final trinity for streaming.
|
||||
* Return 64 or 128-bit result depentently from `extra_result` argument. */
|
||||
* Return 64 or 128-bit result dependently from `extra_result` argument. */
|
||||
T1HA_API void t1ha2_init(t1ha_context_t *ctx, uint64_t seed_x, uint64_t seed_y);
|
||||
T1HA_API void t1ha2_update(t1ha_context_t *__restrict ctx,
|
||||
const void *__restrict data, size_t length);
|
||||
|
@ -29,7 +29,7 @@ Alternatively you can set `AFL_LLVM_INJECTIONS_ALL` to enable all.
|
||||
|
||||
## How to modify
|
||||
|
||||
If you want to add more fuctions to check for e.g. SQL injections:
|
||||
If you want to add more functions to check for e.g. SQL injections:
|
||||
Add these to `instrumentation/injection-pass.cc` and recompile.
|
||||
|
||||
If you want to test for more injection inputs:
|
||||
|
@ -8,7 +8,7 @@ most effective way to fuzz, as the speed can easily be x10 or x20 times faster
|
||||
without any disadvantages. *All professional fuzzing uses this mode.*
|
||||
|
||||
Persistent mode requires that the target can be called in one or more functions,
|
||||
and that it's state can be completely reset so that multiple calls can be
|
||||
and that its state can be completely reset so that multiple calls can be
|
||||
performed without resource leaks, and that earlier runs will have no impact on
|
||||
future runs. An indicator for this is the `stability` value in the `afl-fuzz`
|
||||
UI. If this decreases to lower values in persistent mode compared to
|
||||
|
@ -327,7 +327,16 @@ class ModuleSanitizerCoverageLTOLegacyPass : public ModulePass {
|
||||
|
||||
};
|
||||
|
||||
return ModuleSancov.instrumentModule(M, DTCallback, PDTCallback);
|
||||
if (!getenv("AFL_SAN_NO_INST")) {
|
||||
|
||||
return ModuleSancov.instrumentModule(M, DTCallback, PDTCallback);
|
||||
|
||||
} else {
|
||||
|
||||
if (getenv("AFL_DEBUG")) { DEBUGF("Instrument disabled\n"); }
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -380,8 +389,16 @@ PreservedAnalyses ModuleSanitizerCoverageLTO::run(Module &M,
|
||||
|
||||
};
|
||||
|
||||
if (ModuleSancov.instrumentModule(M, DTCallback, PDTCallback))
|
||||
return PreservedAnalyses::none();
|
||||
if (!getenv("AFL_SAN_NO_INST")) {
|
||||
|
||||
if (ModuleSancov.instrumentModule(M, DTCallback, PDTCallback))
|
||||
return PreservedAnalyses::none();
|
||||
|
||||
} else {
|
||||
|
||||
if (debug) { DEBUGF("Instrument disabled\n"); }
|
||||
|
||||
}
|
||||
|
||||
return PreservedAnalyses::all();
|
||||
|
||||
@ -500,7 +517,7 @@ bool ModuleSanitizerCoverageLTO::instrumentModule(
|
||||
}
|
||||
|
||||
// we make this the default as the fixed map has problems with
|
||||
// defered forkserver, early constructors, ifuncs and maybe more
|
||||
// deferred forkserver, early constructors, ifuncs and maybe more
|
||||
/*if (getenv("AFL_LLVM_MAP_DYNAMIC"))*/
|
||||
map_addr = 0;
|
||||
|
||||
|
@ -261,8 +261,20 @@ PreservedAnalyses ModuleSanitizerCoverageAFL::run(Module &M,
|
||||
|
||||
};
|
||||
|
||||
if (ModuleSancov.instrumentModule(M, DTCallback, PDTCallback))
|
||||
return PreservedAnalyses::none();
|
||||
// TODO: Support LTO or llvm classic?
|
||||
// Note we still need afl-compiler-rt so we just disable the instrumentation
|
||||
// here.
|
||||
if (!getenv("AFL_SAN_NO_INST")) {
|
||||
|
||||
if (ModuleSancov.instrumentModule(M, DTCallback, PDTCallback))
|
||||
return PreservedAnalyses::none();
|
||||
|
||||
} else {
|
||||
|
||||
if (getenv("AFL_DEBUG")) { DEBUGF("Instrument disabled\n"); }
|
||||
|
||||
}
|
||||
|
||||
return PreservedAnalyses::all();
|
||||
|
||||
}
|
||||
@ -330,7 +342,7 @@ Function *ModuleSanitizerCoverageAFL::CreateInitCallsForSections(
|
||||
|
||||
if (TargetTriple.isOSBinFormatCOFF()) {
|
||||
|
||||
// In COFF files, if the contructors are set as COMDAT (they are because
|
||||
// In COFF files, if the constructors are set as COMDAT (they are because
|
||||
// COFF supports COMDAT) and the linker flag /OPT:REF (strip unreferenced
|
||||
// functions and data) is used, the constructors get stripped. To prevent
|
||||
// this, give the constructors weak ODR linkage and ensure the linker knows
|
||||
|
@ -157,7 +157,7 @@ bool isIgnoreFunction(const llvm::Function *F) {
|
||||
// mangled name of the user-written function
|
||||
for (auto const &ignoreListFunc : ignoreSubstringList) {
|
||||
|
||||
// hexcoder: F->getName().contains() not avaiilable in llvm 3.8.0
|
||||
// hexcoder: F->getName().contains() not available in llvm 3.8.0
|
||||
if (StringRef::npos != F->getName().find(ignoreListFunc)) { return true; }
|
||||
|
||||
}
|
||||
|
@ -223,6 +223,24 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
|
||||
if (getenv("AFL_DEBUG")) debug = 1;
|
||||
|
||||
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
|
||||
if (getenv("AFL_SAN_NO_INST")) {
|
||||
|
||||
if (debug) { fprintf(stderr, "Instrument disabled\n"); }
|
||||
return PreservedAnalyses::all();
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
if (getenv("AFL_SAN_NO_INST")) {
|
||||
|
||||
if (debug) { fprintf(stderr, "Instrument disabled\n"); }
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if ((isatty(2) && !getenv("AFL_QUIET")) || getenv("AFL_DEBUG") != NULL) {
|
||||
|
||||
SAYF(cCYA "afl-llvm-pass" VERSION cRST
|
||||
|
@ -112,7 +112,7 @@ class SplitComparesTransform : public ModulePass {
|
||||
/// simplify a signed comparison (signed less or greater than)
|
||||
bool simplifySignedCompare(CmpInst *IcmpInst, Module &M,
|
||||
CmpWorklist &worklist);
|
||||
/// splits an icmp into nested icmps recursivly until target_bitwidth is
|
||||
/// splits an icmp into nested icmps recursively until target_bitwidth is
|
||||
/// reached
|
||||
bool splitCompare(CmpInst *I, Module &M, CmpWorklist &worklist);
|
||||
|
||||
@ -679,7 +679,7 @@ bool SplitComparesTransform::splitCompare(CmpInst *cmp_inst, Module &M,
|
||||
|
||||
PHINode *PN = nullptr;
|
||||
|
||||
/* now we have to destinguish between == != and > < */
|
||||
/* now we have to distinguish between == != and > < */
|
||||
switch (pred) {
|
||||
|
||||
case CmpInst::ICMP_EQ:
|
||||
@ -767,7 +767,7 @@ bool SplitComparesTransform::splitCompare(CmpInst *cmp_inst, Module &M,
|
||||
|
||||
} else {
|
||||
|
||||
// Never gonna appen
|
||||
// Never gonna happen
|
||||
if (!be_quiet)
|
||||
fprintf(stderr,
|
||||
"Error: split-compare: Equals or signed not removed: %d\n",
|
||||
@ -1435,14 +1435,14 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
|
||||
|
||||
case CmpInst::FCMP_UEQ:
|
||||
case CmpInst::FCMP_OEQ:
|
||||
/* if the exponents are satifying the compare do a fraction cmp in
|
||||
/* if the exponents are satisfying the compare do a fraction cmp in
|
||||
* middle_bb */
|
||||
BranchInst::Create(middle_bb, end_bb, icmp_exponent_result,
|
||||
signequal2_bb);
|
||||
break;
|
||||
case CmpInst::FCMP_ONE:
|
||||
case CmpInst::FCMP_UNE:
|
||||
/* if the exponents are satifying the compare do a fraction cmp in
|
||||
/* if the exponents are satisfying the compare do a fraction cmp in
|
||||
* middle_bb */
|
||||
BranchInst::Create(end_bb, middle_bb, icmp_exponent_result,
|
||||
signequal2_bb);
|
||||
|
@ -17,14 +17,14 @@ int main(int argc, char **argv) {
|
||||
*/
|
||||
hprintf("Agent test\n");
|
||||
|
||||
/* Request information on available (host) capabilites (optional) */
|
||||
/* Request information on available (host) capabilities (optional) */
|
||||
host_config_t host_config;
|
||||
kAFL_hypercall(HYPERCALL_KAFL_GET_HOST_CONFIG, (uintptr_t)&host_config);
|
||||
hprintf("[capablities] host_config.bitmap_size: 0x%" PRIx64 "\n",
|
||||
hprintf("[capabilities] host_config.bitmap_size: 0x%" PRIx64 "\n",
|
||||
host_config.bitmap_size);
|
||||
hprintf("[capablities] host_config.ijon_bitmap_size: 0x%" PRIx64 "\n",
|
||||
hprintf("[capabilities] host_config.ijon_bitmap_size: 0x%" PRIx64 "\n",
|
||||
host_config.ijon_bitmap_size);
|
||||
hprintf("[capablities] host_config.payload_buffer_size: 0x%" PRIx64 "x\n",
|
||||
hprintf("[capabilities] host_config.payload_buffer_size: 0x%" PRIx64 "x\n",
|
||||
host_config.payload_buffer_size);
|
||||
|
||||
/* this is our "bitmap" that is later shared with the fuzzer (you can also
|
||||
@ -47,9 +47,9 @@ int main(int argc, char **argv) {
|
||||
*/
|
||||
agent_config.agent_tracing =
|
||||
1; /* set this flag to propagade that instrumentation-based fuzzing is
|
||||
availabe */
|
||||
available */
|
||||
agent_config.agent_ijon_tracing = 0; /* set this flag to propagade that IJON
|
||||
extension is implmented agent-wise */
|
||||
extension is implemented agent-wise */
|
||||
agent_config.trace_buffer_vaddr =
|
||||
(uintptr_t)trace_buffer; /* trace "bitmap" pointer - required for
|
||||
instrumentation-only fuzzing */
|
||||
@ -106,8 +106,8 @@ int main(int argc, char **argv) {
|
||||
if (payload_buffer->data[3] == 'X') {
|
||||
|
||||
((uint8_t *)trace_buffer)[4] = 0x1;
|
||||
/* Notifiy the hypervisor and the fuzzer that a "crash" has
|
||||
* occured. Also a string is passed by this hypercall (this is
|
||||
/* Notify the hypervisor and the fuzzer that a "crash" has
|
||||
* occurred. Also a string is passed by this hypercall (this is
|
||||
* currently not supported by AFL++-Nyx) */
|
||||
kAFL_hypercall(HYPERCALL_KAFL_PANIC_EXTENDED,
|
||||
(uintptr_t) "Something went wrong\n");
|
||||
|
@ -11,7 +11,7 @@ Run build_qemu_support.sh as you do to compile qemuafl, additionally with three
|
||||
* `ENABLE_HOOKING=1` to compile the bridge
|
||||
* `GLIB_H` and `GLIB_CONFIG_H` point to headers `glib.h` and `glibconfig.h` to wherever they are installed on your system
|
||||
|
||||
## Writting hooks
|
||||
## Writing hooks
|
||||
1. Create one or more hooking functions in a shared library, say `hook.so`.
|
||||
2. Include `exports.h` in your hook build. You can find this header at `<your AFL++ path>/qemu_mode/hooking_bridge/inc`.
|
||||
3. Shown below is an example which will use to walkthrough hook creation
|
||||
|
@ -101,7 +101,7 @@ void _pmparser_split_line(char *buf, char *addr1, char *addr2, char *perm,
|
||||
void pmparser_print(procmaps_struct *map, int order);
|
||||
|
||||
/**
|
||||
* gobal variables
|
||||
* global variables
|
||||
*/
|
||||
// procmaps_struct *g_last_head=NULL;
|
||||
// procmaps_struct *g_current=NULL;
|
||||
|
@ -175,7 +175,7 @@ static void find_libc(void) {
|
||||
}
|
||||
|
||||
/* Why this shit? https://twitter.com/andreafioraldi/status/1227635146452541441
|
||||
Unfortunatly, symbol override with LD_PRELOAD is not enough to prevent libc
|
||||
Unfortunately, symbol override with LD_PRELOAD is not enough to prevent libc
|
||||
code to call this optimized XMM-based routines.
|
||||
We patch them at runtime to call our unoptimized version of the same routine.
|
||||
*/
|
||||
|
@ -974,7 +974,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
break;
|
||||
|
||||
case 'Y': // fallthough
|
||||
case 'Y': // fallthrough
|
||||
#ifdef __linux__
|
||||
case 'X': /* NYX mode */
|
||||
|
||||
@ -987,7 +987,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
break;
|
||||
#else
|
||||
case 'X':
|
||||
FATAL("Nyx mode is only availabe on linux...");
|
||||
FATAL("Nyx mode is only available on linux...");
|
||||
break;
|
||||
#endif
|
||||
|
||||
|
22
src/afl-cc.c
22
src/afl-cc.c
@ -247,6 +247,13 @@ static inline void insert_object(aflcc_state_t *aflcc, u8 *obj, u8 *fmt,
|
||||
/* Insert params into the new argv, make clang load the pass. */
|
||||
static inline void load_llvm_pass(aflcc_state_t *aflcc, u8 *pass) {
|
||||
|
||||
if (getenv("AFL_SAN_NO_INST")) {
|
||||
|
||||
if (!be_quiet) { DEBUGF("SAND: Coverage instrumentation disabled\n"); }
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
#if LLVM_MAJOR >= 11 /* use new pass manager */
|
||||
#if LLVM_MAJOR < 16
|
||||
insert_param(aflcc, "-fexperimental-new-pass-manager");
|
||||
@ -2079,6 +2086,12 @@ void add_native_pcguard(aflcc_state_t *aflcc) {
|
||||
* anyway.
|
||||
*/
|
||||
if (aflcc->have_rust_asanrt) { return; }
|
||||
if (getenv("AFL_SAN_NO_INST")) {
|
||||
|
||||
if (!be_quiet) { DEBUGF("SAND: Coverage instrumentation disabled\n"); }
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
/* If llvm-config doesn't figure out LLVM_MAJOR, just
|
||||
go on anyway and let compiler complain if doesn't work. */
|
||||
@ -2091,6 +2104,7 @@ void add_native_pcguard(aflcc_state_t *aflcc) {
|
||||
"pcguard instrumentation with pc-table requires LLVM 6.0.1+"
|
||||
" otherwise the compiler will fail");
|
||||
#endif
|
||||
|
||||
if (aflcc->instrument_opt_mode & INSTRUMENT_OPT_CODECOV) {
|
||||
|
||||
insert_param(aflcc,
|
||||
@ -2113,9 +2127,15 @@ void add_native_pcguard(aflcc_state_t *aflcc) {
|
||||
*/
|
||||
void add_optimized_pcguard(aflcc_state_t *aflcc) {
|
||||
|
||||
if (getenv("AFL_SAN_NO_INST")) {
|
||||
|
||||
if (!be_quiet) { DEBUGF("SAND: Coverage instrumentation disabled\n"); }
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
#if LLVM_MAJOR >= 13
|
||||
#if defined __ANDROID__ || ANDROID
|
||||
|
||||
insert_param(aflcc, "-fsanitize-coverage=trace-pc-guard");
|
||||
aflcc->instrument_mode = INSTRUMENT_LLVMNATIVE;
|
||||
|
||||
|
@ -438,7 +438,7 @@ static void afl_fauxsrv_execv(afl_forkserver_t *fsrv, char **argv) {
|
||||
|
||||
}
|
||||
|
||||
// enable terminating on sigpipe in the childs
|
||||
// enable terminating on sigpipe in the children
|
||||
struct sigaction sa;
|
||||
memset((char *)&sa, 0, sizeof(sa));
|
||||
sa.sa_handler = SIG_DFL;
|
||||
@ -878,7 +878,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
|
||||
|
||||
/* CHILD PROCESS */
|
||||
|
||||
// enable terminating on sigpipe in the childs
|
||||
// enable terminating on sigpipe in the children
|
||||
struct sigaction sa;
|
||||
memset((char *)&sa, 0, sizeof(sa));
|
||||
sa.sa_handler = SIG_DFL;
|
||||
@ -1918,19 +1918,25 @@ fsrv_run_result_t __attribute__((hot)) afl_fsrv_run_target(
|
||||
must prevent any earlier operations from venturing into that
|
||||
territory. */
|
||||
|
||||
/* If the binary is not instrumented, we don't care about the coverage. Make
|
||||
* it a bit faster */
|
||||
if (!fsrv->san_but_not_instrumented) {
|
||||
|
||||
#ifdef __linux__
|
||||
if (likely(!fsrv->nyx_mode)) {
|
||||
if (likely(!fsrv->nyx_mode)) {
|
||||
|
||||
memset(fsrv->trace_bits, 0, fsrv->map_size);
|
||||
MEM_BARRIER();
|
||||
memset(fsrv->trace_bits, 0, fsrv->map_size);
|
||||
MEM_BARRIER();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
memset(fsrv->trace_bits, 0, fsrv->map_size);
|
||||
MEM_BARRIER();
|
||||
memset(fsrv->trace_bits, 0, fsrv->map_size);
|
||||
MEM_BARRIER();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/* we have the fork server (or faux server) up and running
|
||||
First, tell it if the previous run timed out. */
|
||||
|
||||
|
@ -25,6 +25,9 @@
|
||||
|
||||
#include "afl-fuzz.h"
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "asanfuzz.h"
|
||||
#if !defined NAME_MAX
|
||||
#define NAME_MAX _XOPEN_NAME_MAX
|
||||
#endif
|
||||
@ -297,6 +300,8 @@ void minimize_bits(afl_state_t *afl, u8 *dst, u8 *src) {
|
||||
u8 *describe_op(afl_state_t *afl, u8 new_bits, size_t max_description_len) {
|
||||
|
||||
u8 is_timeout = 0;
|
||||
u8 san_crash_only = (afl->san_case_status & SAN_CRASH_ONLY);
|
||||
u8 non_cov_incr = (afl->san_case_status & NON_COV_INCREASE_BUG);
|
||||
|
||||
if (new_bits & 0xf0) {
|
||||
|
||||
@ -388,6 +393,10 @@ u8 *describe_op(afl_state_t *afl, u8 new_bits, size_t max_description_len) {
|
||||
|
||||
if (new_bits == 2) { strcat(ret, ",+cov"); }
|
||||
|
||||
if (san_crash_only) { strcat(ret, ",+san"); }
|
||||
|
||||
if (non_cov_incr) { strcat(ret, ",+noncov"); }
|
||||
|
||||
if (unlikely(strlen(ret) >= max_description_len))
|
||||
FATAL("describe string is too long");
|
||||
|
||||
@ -452,6 +461,18 @@ void write_crash_readme(afl_state_t *afl) {
|
||||
|
||||
}
|
||||
|
||||
static inline void bitmap_set(u8 *map, u32 index) {
|
||||
|
||||
map[index / 8] |= (1u << (index % 8));
|
||||
|
||||
}
|
||||
|
||||
static inline u8 bitmap_read(u8 *map, u32 index) {
|
||||
|
||||
return (map[index / 8] >> (index % 8)) & 1;
|
||||
|
||||
}
|
||||
|
||||
/* Check if the result of an execve() during routine fuzzing is interesting,
|
||||
save or queue the input test case for further analysis if so. Returns 1 if
|
||||
entry is saved, 0 otherwise. */
|
||||
@ -484,6 +505,12 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem,
|
||||
need_hash = 1;
|
||||
s32 fd;
|
||||
u64 cksum = 0;
|
||||
u32 cksum_simplified = 0, cksum_unique = 0;
|
||||
u8 san_fault = 0;
|
||||
u8 san_idx = 0;
|
||||
u8 feed_san = 0;
|
||||
|
||||
afl->san_case_status = 0;
|
||||
|
||||
/* Update path frequency. */
|
||||
|
||||
@ -503,30 +530,131 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem,
|
||||
|
||||
}
|
||||
|
||||
/* Only "normal" inputs seem interested to us */
|
||||
if (likely(fault == afl->crash_mode)) {
|
||||
|
||||
if (unlikely(afl->san_binary_length) &&
|
||||
likely(afl->san_abstraction == SIMPLIFY_TRACE)) {
|
||||
|
||||
memcpy(afl->san_fsrvs[0].trace_bits, afl->fsrv.trace_bits,
|
||||
afl->fsrv.map_size);
|
||||
classify_counts_mem((u64 *)afl->san_fsrvs[0].trace_bits,
|
||||
afl->fsrv.map_size);
|
||||
simplify_trace(afl, afl->san_fsrvs[0].trace_bits);
|
||||
|
||||
// Note: Original SAND implementation used XXHASH32
|
||||
cksum_simplified =
|
||||
hash32(afl->san_fsrvs[0].trace_bits, afl->fsrv.map_size, HASH_CONST);
|
||||
|
||||
if (unlikely(!bitmap_read(afl->simplified_n_fuzz, cksum_simplified))) {
|
||||
|
||||
feed_san = 1;
|
||||
bitmap_set(afl->simplified_n_fuzz, cksum_simplified);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (unlikely(afl->san_binary_length) &&
|
||||
unlikely(afl->san_abstraction == COVERAGE_INCREASE)) {
|
||||
|
||||
/* Check if the input increase the coverage */
|
||||
new_bits = has_new_bits_unclassified(afl, afl->virgin_bits);
|
||||
|
||||
if (unlikely(new_bits)) { feed_san = 1; }
|
||||
|
||||
}
|
||||
|
||||
if (unlikely(afl->san_binary_length) &&
|
||||
likely(afl->san_abstraction == UNIQUE_TRACE)) {
|
||||
|
||||
cksum_unique =
|
||||
hash32(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
|
||||
if (unlikely(!bitmap_read(afl->n_fuzz_dup, cksum) &&
|
||||
fault == afl->crash_mode)) {
|
||||
|
||||
feed_san = 1;
|
||||
bitmap_set(afl->n_fuzz_dup, cksum_unique);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (feed_san) {
|
||||
|
||||
/* The input seems interested to other sanitizers, feed it into extra
|
||||
* binaries. */
|
||||
|
||||
for (san_idx = 0; san_idx < afl->san_binary_length; san_idx++) {
|
||||
|
||||
len = write_to_testcase(afl, &mem, len, 0);
|
||||
san_fault = fuzz_run_target(afl, &afl->san_fsrvs[san_idx],
|
||||
afl->san_fsrvs[san_idx].exec_tmout);
|
||||
|
||||
// DEBUGF("ASAN Result: %hhd\n", asan_fault);
|
||||
|
||||
if (unlikely(san_fault && fault == afl->crash_mode)) {
|
||||
|
||||
/* sanitizers discovers distinct bugs! */
|
||||
afl->san_case_status |= SAN_CRASH_ONLY;
|
||||
|
||||
}
|
||||
|
||||
if (san_fault == FSRV_RUN_CRASH) {
|
||||
|
||||
/* Treat this execution as fault detected by ASAN */
|
||||
// fault = san_fault;
|
||||
|
||||
/* That's pretty enough, break to avoid more overhead. */
|
||||
break;
|
||||
|
||||
} else {
|
||||
|
||||
// or keep san_fault as ok
|
||||
san_fault = FSRV_RUN_OK;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* If there is no crash, everything is fine. */
|
||||
if (likely(fault == afl->crash_mode)) {
|
||||
|
||||
/* Keep only if there are new bits in the map, add to queue for
|
||||
future fuzzing, etc. */
|
||||
if (!unlikely(afl->san_abstraction == COVERAGE_INCREASE && feed_san)) {
|
||||
|
||||
if (likely(classified)) {
|
||||
|
||||
new_bits = has_new_bits(afl, afl->virgin_bits);
|
||||
|
||||
} else {
|
||||
|
||||
/* If we are in coverage increasing abstraction and have fed input to
|
||||
sanitizers, we are sure it has new bits.*/
|
||||
new_bits = has_new_bits_unclassified(afl, afl->virgin_bits);
|
||||
|
||||
if (unlikely(new_bits)) { classified = 1; }
|
||||
|
||||
}
|
||||
|
||||
if (likely(!new_bits)) {
|
||||
|
||||
if (unlikely(afl->crash_mode)) { ++afl->total_crashes; }
|
||||
return 0;
|
||||
if (san_fault == FSRV_RUN_OK) {
|
||||
|
||||
if (unlikely(afl->crash_mode)) { ++afl->total_crashes; }
|
||||
return 0;
|
||||
|
||||
} else {
|
||||
|
||||
afl->san_case_status |= NON_COV_INCREASE_BUG;
|
||||
fault = san_fault;
|
||||
classified = new_bits;
|
||||
goto may_save_fault;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fault = san_fault;
|
||||
classified = new_bits;
|
||||
|
||||
save_to_queue:
|
||||
|
||||
#ifndef SIMPLE_FILES
|
||||
@ -654,6 +782,7 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem,
|
||||
|
||||
}
|
||||
|
||||
may_save_fault:
|
||||
switch (fault) {
|
||||
|
||||
case FSRV_RUN_TMOUT:
|
||||
|
@ -2328,11 +2328,23 @@ void setup_dirs_fds(afl_state_t *afl) {
|
||||
afl->fsrv.plot_file = fdopen(fd, "w");
|
||||
if (!afl->fsrv.plot_file) { PFATAL("fdopen() failed"); }
|
||||
|
||||
fprintf(
|
||||
afl->fsrv.plot_file,
|
||||
"# relative_time, cycles_done, cur_item, corpus_count, "
|
||||
"pending_total, pending_favs, map_size, saved_crashes, "
|
||||
"saved_hangs, max_depth, execs_per_sec, total_execs, edges_found\n");
|
||||
fprintf(afl->fsrv.plot_file,
|
||||
"# relative_time, cycles_done, cur_item, corpus_count, "
|
||||
"pending_total, pending_favs, map_size, saved_crashes, "
|
||||
"saved_hangs, max_depth, execs_per_sec, total_execs, edges_found, "
|
||||
"total_crashes, servers_count");
|
||||
|
||||
if (afl->san_binary_length) {
|
||||
|
||||
for (u8 i = 0; i < afl->san_binary_length; i++) {
|
||||
|
||||
fprintf(afl->fsrv.plot_file, ", sand_fsrv%u_exec", i);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fprintf(afl->fsrv.plot_file, "\n");
|
||||
|
||||
} else {
|
||||
|
||||
|
@ -155,7 +155,7 @@ void destroy_custom_mutators(afl_state_t *afl) {
|
||||
|
||||
LIST_FOREACH_CLEAR(&afl->custom_mutator_list, struct custom_mutator, {
|
||||
|
||||
if (!el->data) { FATAL("Deintializing NULL mutator"); }
|
||||
if (!el->data) { FATAL("Deinitializing NULL mutator"); }
|
||||
if (el->afl_custom_deinit) el->afl_custom_deinit(el->data);
|
||||
if (el->dh) dlclose(el->dh);
|
||||
|
||||
|
@ -6185,7 +6185,7 @@ u8 fuzz_one(afl_state_t *afl) {
|
||||
#endif
|
||||
|
||||
/*
|
||||
-L command line paramter => limit_time_sig value
|
||||
-L command line parameter => limit_time_sig value
|
||||
limit_time_sig == 0 then run the default mutator
|
||||
limit_time_sig > 0 then run MOpt
|
||||
limit_time_sig < 0 both are run
|
||||
|
@ -68,7 +68,7 @@ static void *unsupported(afl_state_t *afl, unsigned int seed) {
|
||||
|
||||
}
|
||||
|
||||
/* sorry for this makro...
|
||||
/* sorry for this macro...
|
||||
it just fills in `&py_mutator->something_buf, &py_mutator->something_size`. */
|
||||
#define BUF_PARAMS(name) (void **)&((py_mutator_t *)py_mutator)->name##_buf
|
||||
|
||||
|
@ -1468,7 +1468,7 @@ inline u8 *queue_testcase_get(afl_state_t *afl, struct queue_entry *q) {
|
||||
|
||||
}
|
||||
|
||||
/* Cache full. We neet to evict one or more to map one.
|
||||
/* Cache full. We need to evict one or more to map one.
|
||||
Get a random one which is not in use */
|
||||
|
||||
do {
|
||||
|
@ -35,12 +35,12 @@
|
||||
// CMP attribute enum
|
||||
enum {
|
||||
|
||||
IS_EQUAL = 1, // arithemtic equal comparison
|
||||
IS_EQUAL = 1, // arithmetic equal comparison
|
||||
IS_GREATER = 2, // arithmetic greater comparison
|
||||
IS_LESSER = 4, // arithmetic lesser comparison
|
||||
IS_FP = 8, // is a floating point, not an integer
|
||||
/* --- below are internal settings, not from target cmplog */
|
||||
IS_FP_MOD = 16, // arithemtic changed floating point
|
||||
IS_FP_MOD = 16, // arithmetic changed floating point
|
||||
IS_INT_MOD = 32, // arithmetic changed integer
|
||||
IS_TRANSFORM = 64 // transformed integer
|
||||
|
||||
@ -68,7 +68,7 @@ enum {
|
||||
|
||||
LVL1 = 1, // Integer solving
|
||||
LVL2 = 2, // unused except for setting the queue entry
|
||||
LVL3 = 4 // expensive tranformations
|
||||
LVL3 = 4 // expensive transformations
|
||||
|
||||
};
|
||||
|
||||
@ -203,7 +203,7 @@ static void type_replace(afl_state_t *afl, u8 *buf, u32 len) {
|
||||
u8 c;
|
||||
for (i = 0; i < len; ++i) {
|
||||
|
||||
// wont help for UTF or non-latin charsets
|
||||
// won't help for UTF or non-latin charsets
|
||||
do {
|
||||
|
||||
switch (buf[i]) {
|
||||
@ -1437,7 +1437,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
|
||||
// here we add and subtract 1 from the value, but only if it is not an
|
||||
// == or != comparison
|
||||
// Bits: 1 = Equal, 2 = Greater, 4 = Lesser, 8 = Float
|
||||
// 16 = modified float, 32 = modified integer (modified = wont match
|
||||
// 16 = modified float, 32 = modified integer (modified = won't match
|
||||
// in original buffer)
|
||||
|
||||
if (!afl->cmplog_enable_arith || lvl < LVL3 || attr == IS_TRANSFORM) {
|
||||
|
@ -33,6 +33,7 @@
|
||||
#endif
|
||||
|
||||
#include "cmplog.h"
|
||||
#include "asanfuzz.h"
|
||||
|
||||
#ifdef PROFILING
|
||||
u64 time_spent_working = 0;
|
||||
|
45
src/afl-fuzz-sanfuzz.c
Normal file
45
src/afl-fuzz-sanfuzz.c
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
american fuzzy lop++ - cmplog execution routines
|
||||
------------------------------------------------
|
||||
|
||||
Originally written by Michal Zalewski
|
||||
|
||||
Forkserver design by Jann Horn <jannhorn@googlemail.com>
|
||||
|
||||
Now maintained by by Marc Heuse <mh@mh-sec.de>,
|
||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
|
||||
Andrea Fioraldi <andreafioraldi@gmail.com>
|
||||
|
||||
Copyright 2016, 2017 Google Inc. All rights reserved.
|
||||
Copyright 2019-2023 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:
|
||||
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Shared code to handle the shared memory. This is used by the fuzzer
|
||||
as well the other components like afl-tmin, afl-showmap, etc...
|
||||
|
||||
*/
|
||||
|
||||
/* This file roughly follows afl-fuzz-asanfuzz */
|
||||
|
||||
#include <sys/select.h>
|
||||
|
||||
#include "afl-fuzz.h"
|
||||
|
||||
void sanfuzz_exec_child(afl_forkserver_t *fsrv, char **argv) {
|
||||
|
||||
if (!fsrv->qemu_mode && !fsrv->frida_mode &&
|
||||
argv[0] != fsrv->asanfuzz_binary) {
|
||||
|
||||
argv[0] = fsrv->asanfuzz_binary;
|
||||
|
||||
}
|
||||
|
||||
execv(fsrv->target_path, argv);
|
||||
|
||||
}
|
||||
|
@ -764,7 +764,7 @@ void afl_state_deinit(afl_state_t *afl) {
|
||||
void afl_states_stop(void) {
|
||||
|
||||
/* We may be inside a signal handler.
|
||||
Set flags first, send kill signals to child proceses later. */
|
||||
Set flags first, send kill signals to child processes later. */
|
||||
LIST_FOREACH(&afl_states, afl_state_t, {
|
||||
|
||||
el->stop_soon = 1;
|
||||
|
@ -356,107 +356,122 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
|
||||
1000;
|
||||
if (!runtime_ms) { runtime_ms = 1; }
|
||||
|
||||
fprintf(
|
||||
f,
|
||||
"start_time : %llu\n"
|
||||
"last_update : %llu\n"
|
||||
"run_time : %llu\n"
|
||||
"fuzzer_pid : %u\n"
|
||||
"cycles_done : %llu\n"
|
||||
"cycles_wo_finds : %llu\n"
|
||||
"time_wo_finds : %llu\n"
|
||||
"fuzz_time : %llu\n"
|
||||
"calibration_time : %llu\n"
|
||||
"cmplog_time : %llu\n"
|
||||
"sync_time : %llu\n"
|
||||
"trim_time : %llu\n"
|
||||
"execs_done : %llu\n"
|
||||
"execs_per_sec : %0.02f\n"
|
||||
"execs_ps_last_min : %0.02f\n"
|
||||
"corpus_count : %u\n"
|
||||
"corpus_favored : %u\n"
|
||||
"corpus_found : %u\n"
|
||||
"corpus_imported : %u\n"
|
||||
"corpus_variable : %u\n"
|
||||
"max_depth : %u\n"
|
||||
"cur_item : %u\n"
|
||||
"pending_favs : %u\n"
|
||||
"pending_total : %u\n"
|
||||
"stability : %0.02f%%\n"
|
||||
"bitmap_cvg : %0.02f%%\n"
|
||||
"saved_crashes : %llu\n"
|
||||
"saved_hangs : %llu\n"
|
||||
"last_find : %llu\n"
|
||||
"last_crash : %llu\n"
|
||||
"last_hang : %llu\n"
|
||||
"execs_since_crash : %llu\n"
|
||||
"exec_timeout : %u\n"
|
||||
"slowest_exec_ms : %u\n"
|
||||
"peak_rss_mb : %lu\n"
|
||||
"cpu_affinity : %d\n"
|
||||
"edges_found : %u\n"
|
||||
"total_edges : %u\n"
|
||||
"var_byte_count : %u\n"
|
||||
"havoc_expansion : %u\n"
|
||||
"auto_dict_entries : %u\n"
|
||||
"testcache_size : %llu\n"
|
||||
"testcache_count : %u\n"
|
||||
"testcache_evict : %u\n"
|
||||
"afl_banner : %s\n"
|
||||
"afl_version : " VERSION
|
||||
"\n"
|
||||
"target_mode : %s%s%s%s%s%s%s%s%s%s\n"
|
||||
"command_line : %s\n",
|
||||
(afl->start_time /*- afl->prev_run_time*/) / 1000, cur_time / 1000,
|
||||
runtime_ms / 1000, (u32)getpid(),
|
||||
afl->queue_cycle ? (afl->queue_cycle - 1) : 0, afl->cycles_wo_finds,
|
||||
afl->longest_find_time > cur_time - afl->last_find_time
|
||||
? afl->longest_find_time / 1000
|
||||
: ((afl->start_time == 0 || afl->last_find_time == 0)
|
||||
? 0
|
||||
: (cur_time - afl->last_find_time) / 1000),
|
||||
(runtime_ms - MIN(runtime_ms, overhead_ms)) / 1000,
|
||||
afl->calibration_time_us / 1000000, afl->cmplog_time_us / 1000000,
|
||||
afl->sync_time_us / 1000000, afl->trim_time_us / 1000000,
|
||||
afl->fsrv.total_execs,
|
||||
afl->fsrv.total_execs / ((double)(runtime_ms) / 1000),
|
||||
afl->last_avg_execs_saved, afl->queued_items, afl->queued_favored,
|
||||
afl->queued_discovered, afl->queued_imported, afl->queued_variable,
|
||||
afl->max_depth, afl->current_entry, afl->pending_favored,
|
||||
afl->pending_not_fuzzed, stability, bitmap_cvg, afl->saved_crashes,
|
||||
afl->saved_hangs, afl->last_find_time / 1000, afl->last_crash_time / 1000,
|
||||
afl->last_hang_time / 1000, afl->fsrv.total_execs - afl->last_crash_execs,
|
||||
afl->fsrv.exec_tmout, afl->slowest_exec_ms,
|
||||
fprintf(f,
|
||||
"start_time : %llu\n"
|
||||
"last_update : %llu\n"
|
||||
"run_time : %llu\n"
|
||||
"fuzzer_pid : %u\n"
|
||||
"cycles_done : %llu\n"
|
||||
"cycles_wo_finds : %llu\n"
|
||||
"time_wo_finds : %llu\n"
|
||||
"fuzz_time : %llu\n"
|
||||
"calibration_time : %llu\n"
|
||||
"cmplog_time : %llu\n"
|
||||
"sync_time : %llu\n"
|
||||
"trim_time : %llu\n"
|
||||
"execs_done : %llu\n"
|
||||
"execs_per_sec : %0.02f\n"
|
||||
"execs_ps_last_min : %0.02f\n"
|
||||
"corpus_count : %u\n"
|
||||
"corpus_favored : %u\n"
|
||||
"corpus_found : %u\n"
|
||||
"corpus_imported : %u\n"
|
||||
"corpus_variable : %u\n"
|
||||
"max_depth : %u\n"
|
||||
"cur_item : %u\n"
|
||||
"pending_favs : %u\n"
|
||||
"pending_total : %u\n"
|
||||
"stability : %0.02f%%\n"
|
||||
"bitmap_cvg : %0.02f%%\n"
|
||||
"saved_crashes : %llu\n"
|
||||
"saved_hangs : %llu\n"
|
||||
"total_tmout : %llu\n"
|
||||
"last_find : %llu\n"
|
||||
"last_crash : %llu\n"
|
||||
"last_hang : %llu\n"
|
||||
"execs_since_crash : %llu\n"
|
||||
"exec_timeout : %u\n"
|
||||
"slowest_exec_ms : %u\n"
|
||||
"peak_rss_mb : %lu\n"
|
||||
"cpu_affinity : %d\n"
|
||||
"edges_found : %u\n"
|
||||
"total_edges : %u\n"
|
||||
"var_byte_count : %u\n"
|
||||
"havoc_expansion : %u\n"
|
||||
"auto_dict_entries : %u\n"
|
||||
"testcache_size : %llu\n"
|
||||
"testcache_count : %u\n"
|
||||
"testcache_evict : %u\n"
|
||||
"afl_banner : %s\n"
|
||||
"afl_version : " VERSION
|
||||
"\n"
|
||||
"target_mode : %s%s%s%s%s%s%s%s%s%s\n"
|
||||
"command_line : %s\n",
|
||||
(afl->start_time /*- afl->prev_run_time*/) / 1000, cur_time / 1000,
|
||||
runtime_ms / 1000, (u32)getpid(),
|
||||
afl->queue_cycle ? (afl->queue_cycle - 1) : 0, afl->cycles_wo_finds,
|
||||
afl->longest_find_time > cur_time - afl->last_find_time
|
||||
? afl->longest_find_time / 1000
|
||||
: ((afl->start_time == 0 || afl->last_find_time == 0)
|
||||
? 0
|
||||
: (cur_time - afl->last_find_time) / 1000),
|
||||
(runtime_ms - MIN(runtime_ms, overhead_ms)) / 1000,
|
||||
afl->calibration_time_us / 1000000, afl->cmplog_time_us / 1000000,
|
||||
afl->sync_time_us / 1000000, afl->trim_time_us / 1000000,
|
||||
afl->fsrv.total_execs,
|
||||
afl->fsrv.total_execs / ((double)(runtime_ms) / 1000),
|
||||
afl->last_avg_execs_saved, afl->queued_items, afl->queued_favored,
|
||||
afl->queued_discovered, afl->queued_imported, afl->queued_variable,
|
||||
afl->max_depth, afl->current_entry, afl->pending_favored,
|
||||
afl->pending_not_fuzzed, stability, bitmap_cvg, afl->saved_crashes,
|
||||
afl->saved_hangs, afl->total_tmouts, afl->last_find_time / 1000,
|
||||
afl->last_crash_time / 1000, afl->last_hang_time / 1000,
|
||||
afl->fsrv.total_execs - afl->last_crash_execs, afl->fsrv.exec_tmout,
|
||||
afl->slowest_exec_ms,
|
||||
#ifndef __HAIKU__
|
||||
#ifdef __APPLE__
|
||||
(unsigned long int)(rus.ru_maxrss >> 20),
|
||||
(unsigned long int)(rus.ru_maxrss >> 20),
|
||||
#else
|
||||
(unsigned long int)(rus.ru_maxrss >> 10),
|
||||
(unsigned long int)(rus.ru_maxrss >> 10),
|
||||
#endif
|
||||
#else
|
||||
-1UL,
|
||||
-1UL,
|
||||
#endif
|
||||
#ifdef HAVE_AFFINITY
|
||||
afl->cpu_aff,
|
||||
afl->cpu_aff,
|
||||
#else
|
||||
-1,
|
||||
-1,
|
||||
#endif
|
||||
t_bytes, afl->fsrv.real_map_size, afl->var_byte_count, afl->expand_havoc,
|
||||
afl->a_extras_cnt, afl->q_testcase_cache_size,
|
||||
afl->q_testcase_cache_count, afl->q_testcase_evictions, afl->use_banner,
|
||||
afl->unicorn_mode ? "unicorn" : "", afl->fsrv.qemu_mode ? "qemu " : "",
|
||||
afl->fsrv.cs_mode ? "coresight" : "",
|
||||
afl->non_instrumented_mode ? " non_instrumented " : "",
|
||||
afl->no_forkserver ? "no_fsrv " : "", afl->crash_mode ? "crash " : "",
|
||||
afl->persistent_mode ? "persistent " : "",
|
||||
afl->shmem_testcase_mode ? "shmem_testcase " : "",
|
||||
afl->deferred_mode ? "deferred " : "",
|
||||
(afl->unicorn_mode || afl->fsrv.qemu_mode || afl->fsrv.cs_mode ||
|
||||
afl->non_instrumented_mode || afl->no_forkserver || afl->crash_mode ||
|
||||
afl->persistent_mode || afl->deferred_mode)
|
||||
? ""
|
||||
: "default",
|
||||
afl->orig_cmdline);
|
||||
t_bytes, afl->fsrv.real_map_size, afl->var_byte_count,
|
||||
afl->expand_havoc, afl->a_extras_cnt, afl->q_testcase_cache_size,
|
||||
afl->q_testcase_cache_count, afl->q_testcase_evictions,
|
||||
afl->use_banner, afl->unicorn_mode ? "unicorn" : "",
|
||||
afl->fsrv.qemu_mode ? "qemu " : "",
|
||||
afl->fsrv.cs_mode ? "coresight" : "",
|
||||
afl->non_instrumented_mode ? " non_instrumented " : "",
|
||||
afl->no_forkserver ? "no_fsrv " : "", afl->crash_mode ? "crash " : "",
|
||||
afl->persistent_mode ? "persistent " : "",
|
||||
afl->shmem_testcase_mode ? "shmem_testcase " : "",
|
||||
afl->deferred_mode ? "deferred " : "",
|
||||
(afl->unicorn_mode || afl->fsrv.qemu_mode || afl->fsrv.cs_mode ||
|
||||
afl->non_instrumented_mode || afl->no_forkserver ||
|
||||
afl->crash_mode || afl->persistent_mode || afl->deferred_mode)
|
||||
? ""
|
||||
: "default",
|
||||
afl->orig_cmdline);
|
||||
|
||||
if (afl->san_binary_length) {
|
||||
|
||||
for (u8 i = 0; i < afl->san_binary_length; i++) {
|
||||
|
||||
fprintf(f,
|
||||
"extra_binary : %s\n"
|
||||
"total_execs : %llu\n",
|
||||
afl->san_binary[i], afl->san_fsrvs[i].total_execs);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* ignore errors */
|
||||
|
||||
@ -565,12 +580,21 @@ void maybe_update_plot_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
|
||||
|
||||
fprintf(afl->fsrv.plot_file,
|
||||
"%llu, %llu, %u, %u, %u, %u, %0.02f%%, %llu, %llu, %u, %0.02f, %llu, "
|
||||
"%u\n",
|
||||
"%u, %llu, %u",
|
||||
((afl->prev_run_time + get_cur_time() - afl->start_time) / 1000),
|
||||
afl->queue_cycle - 1, afl->current_entry, afl->queued_items,
|
||||
afl->pending_not_fuzzed, afl->pending_favored, bitmap_cvg,
|
||||
afl->saved_crashes, afl->saved_hangs, afl->max_depth, eps,
|
||||
afl->plot_prev_ed, t_bytes); /* ignore errors */
|
||||
afl->plot_prev_ed, t_bytes, afl->total_crashes,
|
||||
(u32)afl->san_binary_length); /* ignore errors */
|
||||
|
||||
for (u32 i = 0; i < afl->san_binary_length; i++) {
|
||||
|
||||
fprintf(afl->fsrv.plot_file, ", %llu", afl->san_fsrvs[i].total_execs);
|
||||
|
||||
}
|
||||
|
||||
fprintf(afl->fsrv.plot_file, "\n");
|
||||
|
||||
fflush(afl->fsrv.plot_file);
|
||||
|
||||
@ -2105,13 +2129,13 @@ void show_stats_pizza(afl_state_t *afl) {
|
||||
|
||||
} else {
|
||||
|
||||
strcpy(tmp, "18 year aniversary mode");
|
||||
strcpy(tmp, "18 year anniversary mode");
|
||||
|
||||
}
|
||||
|
||||
SAYF(bV bSTOP
|
||||
" dictionary : " cRST "%-36s " bSTG bV bSTOP
|
||||
" patrons from old resturant : " cRST "%-10s " bSTG bV
|
||||
" patrons from old restaurant : " cRST "%-10s " bSTG bV
|
||||
"\n",
|
||||
tmp,
|
||||
afl->sync_id ? u_stringify_int(IB(0), afl->queued_imported)
|
||||
|
192
src/afl-fuzz.c
192
src/afl-fuzz.c
@ -25,7 +25,9 @@
|
||||
*/
|
||||
|
||||
#include "afl-fuzz.h"
|
||||
#include "alloc-inl.h"
|
||||
#include "cmplog.h"
|
||||
#include "asanfuzz.h"
|
||||
#include "common.h"
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
@ -252,13 +254,17 @@ static void usage(u8 *argv0, int more_help) {
|
||||
" X=extreme transform solving, R=random colorization "
|
||||
"bytes.\n\n"
|
||||
"Fuzzing behavior settings:\n"
|
||||
" -Z - sequential queue selection instead of weighted "
|
||||
" -Z - sequential queue selection instead of weighted "
|
||||
"random\n"
|
||||
" -N - do not unlink the fuzzing input file (for devices "
|
||||
" -N - do not unlink the fuzzing input file (for devices "
|
||||
"etc.)\n"
|
||||
" -n - fuzz without instrumentation (non-instrumented mode)\n"
|
||||
" -x dict_file - fuzzer dictionary (see README.md, specify up to 4 "
|
||||
"times)\n\n"
|
||||
" -n - fuzz without instrumentation (non-instrumented "
|
||||
"mode)\n"
|
||||
" -x dict_file - fuzzer dictionary (see README.md, specify up to 4 "
|
||||
"times)\n"
|
||||
" -w san_binary - Specify the extra sanitizer instrumented binaries,\n"
|
||||
" can be specified multiple times.\n"
|
||||
" Read docs/SAND.md for details.\n\n"
|
||||
|
||||
"Test settings:\n"
|
||||
" -s seed - use a fixed seed for the RNG\n"
|
||||
@ -396,7 +402,7 @@ static void usage(u8 *argv0, int more_help) {
|
||||
"AFL_STATSD_HOST: change default statsd host (default 127.0.0.1)\n"
|
||||
"AFL_STATSD_PORT: change default statsd port (default: 8125)\n"
|
||||
"AFL_STATSD_TAGS_FLAVOR: set statsd tags format (default: disable tags)\n"
|
||||
" suported formats: dogstatsd, librato, signalfx, influxdb\n"
|
||||
" supported formats: dogstatsd, librato, signalfx, influxdb\n"
|
||||
"AFL_NO_FASTRESUME: do not read or write a fast resume file\n"
|
||||
"AFL_NO_SYNC: disables all syncing\n"
|
||||
"AFL_SYNC_TIME: sync time between fuzzing instances (in minutes)\n"
|
||||
@ -549,6 +555,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
u8 mem_limit_given = 0, exit_1 = 0, debug = 0,
|
||||
extras_dir_cnt = 0 /*, have_p = 0*/;
|
||||
char *afl_preload;
|
||||
char *san_abstraction;
|
||||
char *frida_afl_preload = NULL;
|
||||
char **use_argv;
|
||||
|
||||
@ -606,9 +613,10 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
afl->shmem_testcase_mode = 1; // we always try to perform shmem fuzzing
|
||||
|
||||
// still available: HjJkKqruvwz
|
||||
while ((opt = getopt(argc, argv,
|
||||
"+a:Ab:B:c:CdDe:E:f:F:g:G:hi:I:l:L:m:M:nNo:Op:P:QRs:S:t:"
|
||||
"T:uUV:WXx:YzZ")) > 0) {
|
||||
while (
|
||||
(opt = getopt(argc, argv,
|
||||
"+aw:Ab:B:c:CdDe:E:f:F:g:G:hi:I:l:L:m:M:nNo:Op:P:QRs:S:t:"
|
||||
"T:uUV:WXx:YzZ")) > 0) {
|
||||
|
||||
switch (opt) {
|
||||
|
||||
@ -741,6 +749,21 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
}
|
||||
|
||||
case 'w': {
|
||||
|
||||
if (afl->san_binary_length == MAX_EXTRA_SAN_BINARY) {
|
||||
|
||||
FATAL("Only %d extra sanitizer instrumented binaries are supported.",
|
||||
MAX_EXTRA_SAN_BINARY);
|
||||
|
||||
}
|
||||
|
||||
afl->shm.sanfuzz_mode = 1;
|
||||
afl->san_binary[afl->san_binary_length++] = optarg;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
case 's': {
|
||||
|
||||
if (optarg == NULL) { FATAL("No valid seed provided. Got NULL."); }
|
||||
@ -1147,7 +1170,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
#else
|
||||
case 'X':
|
||||
case 'Y':
|
||||
FATAL("Nyx mode is only availabe on linux...");
|
||||
FATAL("Nyx mode is only available on linux...");
|
||||
break;
|
||||
#endif
|
||||
case 'A': /* CoreSight mode */
|
||||
@ -1727,6 +1750,9 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
}
|
||||
|
||||
afl->n_fuzz_dup = ck_alloc(N_FUZZ_SIZE_BITMAP * sizeof(u8));
|
||||
afl->simplified_n_fuzz = ck_alloc(N_FUZZ_SIZE_BITMAP * sizeof(u8));
|
||||
|
||||
if (get_afl_env("AFL_NO_FORKSRV")) { afl->no_forkserver = 1; }
|
||||
if (get_afl_env("AFL_NO_CPU_RED")) { afl->no_cpu_meter_red = 1; }
|
||||
if (get_afl_env("AFL_NO_ARITH")) { afl->no_arith = 1; }
|
||||
@ -2218,6 +2244,16 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
}
|
||||
|
||||
setup_cmdline_file(afl, argv + optind);
|
||||
|
||||
// Let's check SAND sanitizers binaries a bit earlier
|
||||
// so that we won't overwrite target_path.
|
||||
// Lazymio: why does cmplog fsrv even work?!
|
||||
for (u8 i = 0; i < afl->san_binary_length; i++) {
|
||||
|
||||
check_binary(afl, afl->san_binary[i]);
|
||||
|
||||
}
|
||||
|
||||
check_binary(afl, argv[optind]);
|
||||
|
||||
u64 prev_target_hash = 0;
|
||||
@ -2295,7 +2331,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
if (NZLIBREAD(fr_fd, ver_string, sizeof(ver_string)) !=
|
||||
sizeof(ver_string))
|
||||
WARNF("Emtpy fastresume.bin, ignoring, cannot perform FAST RESUME");
|
||||
WARNF("Empty fastresume.bin, ignoring, cannot perform FAST RESUME");
|
||||
else if (expect_ver != *ver)
|
||||
WARNF(
|
||||
"Different AFL++ version or feature usage, cannot perform FAST "
|
||||
@ -2554,6 +2590,129 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
}
|
||||
|
||||
san_abstraction = getenv("AFL_SAN_ABSTRACTION");
|
||||
if (!san_abstraction || !strcmp(san_abstraction, "simplify_trace")) {
|
||||
|
||||
afl->san_abstraction = SIMPLIFY_TRACE;
|
||||
|
||||
} else if (!strcmp(san_abstraction, "coverage_increase")) {
|
||||
|
||||
afl->san_abstraction = COVERAGE_INCREASE;
|
||||
|
||||
} else if (!strcmp(san_abstraction, "unique_trace")) {
|
||||
|
||||
afl->san_abstraction = UNIQUE_TRACE;
|
||||
|
||||
} else {
|
||||
|
||||
WARNF("Unknown abstraction: %s, fallback to unique trace.\n",
|
||||
san_abstraction);
|
||||
afl->san_abstraction = SIMPLIFY_TRACE;
|
||||
|
||||
}
|
||||
|
||||
if (!afl->san_binary_length && san_abstraction) {
|
||||
|
||||
WARNF(
|
||||
"No extra sanitizer instrumented binaries are given, do you forget "
|
||||
"-a?\n");
|
||||
|
||||
}
|
||||
|
||||
/* Maybe merge with cmplog but much cmplog code was already copy-paste
|
||||
* style... */
|
||||
if (afl->san_binary_length) {
|
||||
|
||||
for (u8 i = 0; i < afl->san_binary_length; i++) {
|
||||
|
||||
ACTF("Spawning SAND forkserver for %s", afl->san_binary[i]);
|
||||
afl_fsrv_init_dup(&afl->san_fsrvs[i], &afl->fsrv);
|
||||
|
||||
/*
|
||||
* We don't really collect trace bits for sanitizer instrumented binary so
|
||||
* we just allocate some dummy memory here.
|
||||
*/
|
||||
afl->san_fsrvs[i].trace_bits = ck_alloc(
|
||||
afl->fsrv.map_size + 8); /* One more u64 according to afl_shm_init*/
|
||||
afl->san_fsrvs[i].map_size = afl->fsrv.map_size;
|
||||
afl->san_fsrvs[i].san_but_not_instrumented = 1;
|
||||
|
||||
afl->san_fsrvs[i].cs_mode = afl->fsrv.cs_mode;
|
||||
afl->san_fsrvs[i].qemu_mode = afl->fsrv.qemu_mode;
|
||||
afl->san_fsrvs[i].frida_mode = afl->fsrv.frida_mode;
|
||||
afl->san_fsrvs[i].asanfuzz_binary = afl->san_binary[i];
|
||||
afl->san_fsrvs[i].target_path = afl->san_binary[i];
|
||||
afl->san_fsrvs[i].init_child_func = sanfuzz_exec_child;
|
||||
|
||||
afl->san_fsrvs[i].child_kill_signal =
|
||||
afl->fsrv.child_kill_signal; // I believe cmplog also needs this.
|
||||
afl->san_fsrvs[i].fsrv_kill_signal = afl->fsrv.fsrv_kill_signal;
|
||||
|
||||
if ((map_size <= DEFAULT_SHMEM_SIZE ||
|
||||
afl->san_fsrvs[i].map_size < map_size) &&
|
||||
!afl->non_instrumented_mode && !afl->fsrv.qemu_mode &&
|
||||
!afl->fsrv.frida_mode && !afl->unicorn_mode && !afl->fsrv.cs_mode &&
|
||||
!afl->afl_env.afl_skip_bin_check) {
|
||||
|
||||
afl->san_fsrvs[i].map_size = MAX(map_size, (u32)DEFAULT_SHMEM_SIZE);
|
||||
char vbuf[16];
|
||||
snprintf(vbuf, sizeof(vbuf), "%u", afl->san_fsrvs[i].map_size);
|
||||
setenv("AFL_MAP_SIZE", vbuf, 1);
|
||||
|
||||
}
|
||||
|
||||
u32 new_map_size =
|
||||
afl_fsrv_get_mapsize(&afl->san_fsrvs[i], afl->argv, &afl->stop_soon,
|
||||
afl->afl_env.afl_debug_child);
|
||||
|
||||
// only reinitialize when it needs to be larger
|
||||
if (map_size < new_map_size) {
|
||||
|
||||
OKF("Re-initializing maps to %u bytes due to SAN instrumented binary",
|
||||
new_map_size);
|
||||
|
||||
afl->virgin_bits = ck_realloc(afl->virgin_bits, new_map_size);
|
||||
afl->virgin_tmout = ck_realloc(afl->virgin_tmout, new_map_size);
|
||||
afl->virgin_crash = ck_realloc(afl->virgin_crash, new_map_size);
|
||||
afl->var_bytes = ck_realloc(afl->var_bytes, new_map_size);
|
||||
afl->top_rated =
|
||||
ck_realloc(afl->top_rated, new_map_size * sizeof(void *));
|
||||
afl->clean_trace = ck_realloc(afl->clean_trace, new_map_size);
|
||||
afl->clean_trace_custom =
|
||||
ck_realloc(afl->clean_trace_custom, new_map_size);
|
||||
afl->first_trace = ck_realloc(afl->first_trace, new_map_size);
|
||||
afl->map_tmp_buf = ck_realloc(afl->map_tmp_buf, new_map_size);
|
||||
|
||||
afl_fsrv_kill(&afl->fsrv);
|
||||
afl_fsrv_kill(&afl->san_fsrvs[i]);
|
||||
afl_shm_deinit(&afl->shm);
|
||||
|
||||
afl->san_fsrvs[i].map_size = new_map_size; // non-cmplog stays the same
|
||||
map_size = new_map_size;
|
||||
|
||||
setenv("AFL_NO_AUTODICT", "1", 1); // loaded already
|
||||
afl->fsrv.trace_bits =
|
||||
afl_shm_init(&afl->shm, new_map_size, afl->non_instrumented_mode);
|
||||
ck_free(afl->san_fsrvs[i].trace_bits);
|
||||
afl->san_fsrvs[i].trace_bits = ck_alloc(afl->fsrv.map_size + 8);
|
||||
afl->san_fsrvs[i].map_size = afl->fsrv.map_size;
|
||||
afl_fsrv_start(&afl->fsrv, afl->argv, &afl->stop_soon,
|
||||
afl->afl_env.afl_debug_child);
|
||||
afl_fsrv_start(&afl->san_fsrvs[i], afl->argv, &afl->stop_soon,
|
||||
afl->afl_env.afl_debug_child);
|
||||
|
||||
}
|
||||
|
||||
OKF("SAND forkserver for %s successfully started", afl->san_binary[i]);
|
||||
|
||||
}
|
||||
|
||||
OKF("All forkservers for extra sanitizers instrumented binares are up and "
|
||||
"we have abstraction = %d",
|
||||
afl->san_abstraction);
|
||||
|
||||
}
|
||||
|
||||
if (afl->cmplog_binary) {
|
||||
|
||||
ACTF("Spawning cmplog forkserver");
|
||||
@ -3426,7 +3585,7 @@ stop_fuzzing:
|
||||
|
||||
ZLIBCLOSE(fr_fd);
|
||||
afl->var_byte_count = count_bytes(afl, afl->var_bytes);
|
||||
OKF("fastresume.bin succesfully written with %u bytes.", w);
|
||||
OKF("fastresume.bin successfully written with %u bytes.", w);
|
||||
|
||||
} else {
|
||||
|
||||
@ -3450,6 +3609,15 @@ stop_fuzzing:
|
||||
|
||||
afl_fsrv_deinit(&afl->fsrv);
|
||||
|
||||
for (u8 i = 0; i < afl->san_binary_length; i++) {
|
||||
|
||||
ck_free(afl->san_fsrvs[i].trace_bits);
|
||||
afl_fsrv_deinit(&afl->san_fsrvs[i]);
|
||||
|
||||
}
|
||||
|
||||
if (afl->cmplog_binary) { afl_fsrv_deinit(&afl->cmplog_fsrv); }
|
||||
|
||||
/* remove tmpfile */
|
||||
if (!afl->in_place_resume && afl->fsrv.out_file) {
|
||||
|
||||
|
@ -214,7 +214,7 @@ int main(int argc, char **argv) {
|
||||
#if defined(__linux__)
|
||||
if (sched_setaffinity(0, sizeof(c), &c)) {
|
||||
|
||||
const char *error_code = "Unkown error code";
|
||||
const char *error_code = "Unknown error code";
|
||||
if (errno == EFAULT) error_code = "EFAULT";
|
||||
if (errno == EINVAL) error_code = "EINVAL";
|
||||
if (errno == EPERM) error_code = "EPERM";
|
||||
|
@ -1259,7 +1259,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
break;
|
||||
|
||||
/* FIXME: We want to use -P for consistency, but it is already unsed for
|
||||
/* FIXME: We want to use -P for consistency, but it is already unused for
|
||||
* undocumenetd feature "Another afl-cmin specific feature." */
|
||||
case 'A': /* CoreSight mode */
|
||||
|
||||
@ -1307,7 +1307,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
break;
|
||||
#else
|
||||
case 'X':
|
||||
FATAL("Nyx mode is only availabe on linux...");
|
||||
FATAL("Nyx mode is only available on linux...");
|
||||
break;
|
||||
#endif
|
||||
|
||||
@ -1684,7 +1684,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
} else {
|
||||
|
||||
if ((coverage_map = (u8 *)malloc(map_size + 64)) == NULL)
|
||||
FATAL("coult not grab memory");
|
||||
FATAL("could not grab memory");
|
||||
edges_only = false;
|
||||
|
||||
}
|
||||
|
@ -1014,7 +1014,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
break;
|
||||
|
||||
case 'Y': // fallthough
|
||||
case 'Y': // fallthrough
|
||||
#ifdef __linux__
|
||||
case 'X': /* NYX mode */
|
||||
|
||||
@ -1027,7 +1027,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
break;
|
||||
#else
|
||||
case 'X':
|
||||
FATAL("Nyx mode is only availabe on linux...");
|
||||
FATAL("Nyx mode is only available on linux...");
|
||||
break;
|
||||
#endif
|
||||
|
||||
@ -1035,7 +1035,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
/* Minimizes a testcase to the minimum that still times out */
|
||||
|
||||
if (hang_mode) { FATAL("Multipe -H options not supported"); }
|
||||
if (hang_mode) { FATAL("Multiple -H options not supported"); }
|
||||
if (edges_only) {
|
||||
|
||||
FATAL("Edges only and hang mode are mutually exclusive.");
|
||||
|
@ -6,7 +6,7 @@ test -z "$1" -o -n "$4" && {
|
||||
echo "Syntax: $0 commit-id <indir> \"<cmdline>\""
|
||||
echo
|
||||
echo "Switches to the defined commit ID, compiles with profiling and runs"
|
||||
echo "afl-fuzz on a defind target and input directory, saving timing,"
|
||||
echo "afl-fuzz on a defined target and input directory, saving timing,"
|
||||
echo "fuzzer_stats and profiling output to \"<commit-id>.out\""
|
||||
echo "Honors CFLAGS and LDFLAGS"
|
||||
echo
|
||||
|
@ -3,7 +3,7 @@
|
||||
. ./test-pre.sh
|
||||
|
||||
$ECHO "$BLUE[*] Testing: unicorn_mode"
|
||||
test -d ../unicorn_mode/unicornafl -a -e ../unicorn_mode/unicornafl/Makefile && {
|
||||
test -s ../unicorn_mode/unicornafl/build/libunicornafl.a && {
|
||||
test -e ../unicorn_mode/samples/python_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
|
||||
|
@ -63,7 +63,7 @@ def parse_mapping_index(filepath: str):
|
||||
def get_input_name():
|
||||
"""Get the name of the input file
|
||||
|
||||
:retrun: Name of the input file
|
||||
:return: Name of the input file
|
||||
"""
|
||||
|
||||
input_filepath = ida_nalt.get_input_file_path()
|
||||
|
@ -171,7 +171,7 @@ def dump_process_memory(output_dir):
|
||||
|
||||
|
||||
# ---------------------------------------------
|
||||
# ---- ARM Extention (dump floating point regs)
|
||||
# ---- ARM Extension (dump floating point regs)
|
||||
|
||||
|
||||
def dump_float(rge=32):
|
||||
|
@ -75,7 +75,7 @@ def map_arch():
|
||||
return "arm64be"
|
||||
elif "arm" in arch:
|
||||
cpsr = pwndbg.gdblib.regs["cpsr"]
|
||||
# check endianess
|
||||
# check endianness
|
||||
if pwndbg.gdblib.arch.endian == "big":
|
||||
# check for THUMB mode
|
||||
if cpsr & (1 << 5):
|
||||
|
@ -26,7 +26,7 @@ from unicorn.arm64_const import *
|
||||
from unicorn.x86_const import *
|
||||
from unicorn.mips_const import *
|
||||
|
||||
# If Capstone libraries are availible (only check once)
|
||||
# If Capstone libraries are available (only check once)
|
||||
try:
|
||||
from capstone import *
|
||||
|
||||
|
@ -42,7 +42,7 @@ static const int64_t STACK_ADDRESS = (((int64_t) 0x01) << 58);
|
||||
static const int64_t STACK_SIZE = 0x10000;
|
||||
// Location where the input will be placed (make sure the emulated program knows this somehow, too ;) )
|
||||
static const int64_t INPUT_LOCATION = 0x10000;
|
||||
// Inside the location, we have an ofset in our special case
|
||||
// Inside the location, we have an offset in our special case
|
||||
static const int64_t INPUT_OFFSET = 0x16;
|
||||
// Maximum allowable size of mutated data from AFL
|
||||
static const int64_t INPUT_SIZE_MAX = 0x10000;
|
||||
@ -65,7 +65,7 @@ static void hook_code(uc_engine *uc, uint64_t address, uint32_t size, void *user
|
||||
|
||||
/*
|
||||
The sample uses strlen, since we don't have a loader or libc, we'll fake it.
|
||||
We know the strlen will return the lenght of argv[1] that we just planted.
|
||||
We know the strlen will return the length of argv[1] that we just planted.
|
||||
It will be a lot faster than an actual strlen for this specific purpose.
|
||||
*/
|
||||
static void hook_strlen(uc_engine *uc, uint64_t address, uint32_t size, void *user_data) {
|
||||
@ -247,7 +247,7 @@ int main(int argc, char **argv, char **envp) {
|
||||
place_input_callback, // Callback that places the input (automatically loaded from the file at filename) in the unicorninstance
|
||||
&end_address, // Where to exit (this is an array)
|
||||
1, // Count of end addresses
|
||||
NULL, // Optional calback to run after each exec
|
||||
NULL, // Optional callback to run after each exec
|
||||
false, // true, if the optional callback should be run also for non-crashes
|
||||
1, // For persistent mode: How many rounds to run
|
||||
NULL // additional data pointer
|
||||
|
@ -12,7 +12,7 @@
|
||||
$ make
|
||||
$ ../../../afl-fuzz -m none -i sample_inputs -o out -- ./harness @@
|
||||
|
||||
(Re)run a simgle input with block tracing using:
|
||||
(Re)run a single input with block tracing using:
|
||||
|
||||
$ ./harness -t [inputfile]
|
||||
*/
|
||||
@ -46,7 +46,7 @@ static const int64_t STACK_ADDRESS = (((int64_t) 0x01) << 58);
|
||||
static const int64_t STACK_SIZE = 0x10000;
|
||||
// Location where the input will be placed (make sure the emulated program knows this somehow, too ;) )
|
||||
static const int64_t INPUT_LOCATION = 0x10000;
|
||||
// Inside the location, we have an ofset in our special case
|
||||
// Inside the location, we have an offset in our special case
|
||||
static const int64_t INPUT_OFFSET = 0x16;
|
||||
// Maximum allowable size of mutated data from AFL
|
||||
static const int64_t INPUT_SIZE_MAX = 0x10000;
|
||||
@ -233,7 +233,7 @@ int main(int argc, char **argv, char **envp) {
|
||||
// build a "dummy" argv with length 2 at 0x10000:
|
||||
// 0x10000 argv[0] NULL
|
||||
// 0x10008 argv[1] (char *)0x10016 --. points to the next offset.
|
||||
// 0x10016 argv[1][0], ... <-^ contains the acutal input data. (INPUT_LOCATION + INPUT_OFFSET)
|
||||
// 0x10016 argv[1][0], ... <-^ contains the actual input data. (INPUT_LOCATION + INPUT_OFFSET)
|
||||
|
||||
uc_mem_write(uc, 0x10008, "\x16\x00\x01", 3); // little endian of 0x10016, see above
|
||||
|
||||
@ -260,7 +260,7 @@ int main(int argc, char **argv, char **envp) {
|
||||
place_input_callback, // Callback that places the input (automatically loaded from the file at filename) in the unicorninstance
|
||||
&end_address, // Where to exit (this is an array)
|
||||
1, // Count of end addresses
|
||||
NULL, // Optional calback to run after each exec
|
||||
NULL, // Optional callback to run after each exec
|
||||
false, // true, if the optional callback should be run also for non-crashes
|
||||
1000, // For persistent mode: How many rounds to run
|
||||
NULL // additional data pointer
|
||||
|
@ -308,7 +308,7 @@ int main(int argc, char **argv, char **envp) {
|
||||
}
|
||||
uint64_t start_address;
|
||||
if(fscanf(f, "%llx", (unsigned long long) &start_address) == EOF) {
|
||||
puts("Start address not found in target.offests.main");
|
||||
puts("Start address not found in target.offsets.main");
|
||||
exit(-1);
|
||||
}
|
||||
fclose(f);
|
||||
@ -371,7 +371,7 @@ int main(int argc, char **argv, char **envp) {
|
||||
place_input_callback, // Callback that places the input (automatically loaded from the file at filename) in the unicorninstance
|
||||
exits, // Where to exit (this is an array)
|
||||
exit_count, // Count of end addresses
|
||||
NULL, // Optional calback to run after each exec
|
||||
NULL, // Optional callback to run after each exec
|
||||
false, // true, if the optional callback should be run also for non-crashes
|
||||
1000, // For persistent mode: How many rounds to run
|
||||
NULL // additional data pointer
|
||||
|
@ -43,7 +43,7 @@ for line in objdump_output.split("\n"):
|
||||
if "<main>:" in line:
|
||||
if main_loc is not None:
|
||||
raise Exception("Found multiple main functions, odd target!")
|
||||
# main_loc is the label, so it's parsed differntly (i.e. `0000000000001220 <main>:`)
|
||||
# main_loc is the label, so it's parsed differently (i.e. `0000000000001220 <main>:`)
|
||||
main_loc = "0x" + line.strip().split(" ", 1)[0].strip()
|
||||
else:
|
||||
[
|
||||
|
@ -62,7 +62,7 @@ def do_string_analysis(corpdir, infile1):
|
||||
or ("<" in str11)
|
||||
or (">" in str11)
|
||||
):
|
||||
print("Space / Paranthesis String : %s" % str11)
|
||||
print("Space / Parenthesis String : %s" % str11)
|
||||
else:
|
||||
with open(corpdir + "/memcmp-str{0}".format(n), "w") as file:
|
||||
file.write(str11)
|
||||
|
@ -62,7 +62,7 @@ def do_string_analysis(corpdir, infile1):
|
||||
or ("<" in str11)
|
||||
or (">" in str11)
|
||||
):
|
||||
print("Space / Paranthesis String : %s" % str11)
|
||||
print("Space / Parenthesis String : %s" % str11)
|
||||
else:
|
||||
with open(corpdir + "/seed-str{0}".format(n), "w") as file:
|
||||
file.write(str11)
|
||||
|
@ -62,7 +62,7 @@ def do_string_analysis(corpdir, infile1):
|
||||
or ("<" in str11)
|
||||
or (">" in str11)
|
||||
):
|
||||
print("Space / Paranthesis String : %s" % str11)
|
||||
print("Space / Parenthesis String : %s" % str11)
|
||||
else:
|
||||
with open(corpdir + "/strcmp-str{0}".format(n), "w") as file:
|
||||
file.write(str11)
|
||||
|
@ -62,7 +62,7 @@ def do_string_analysis(corpdir, infile1):
|
||||
or ("<" in str11)
|
||||
or (">" in str11)
|
||||
):
|
||||
print("Space / Paranthesis String : %s" % str11)
|
||||
print("Space / Parenthesis String : %s" % str11)
|
||||
else:
|
||||
with open(corpdir + "/strncmp-str{0}".format(n), "w") as file:
|
||||
file.write(str11)
|
||||
|
@ -3,7 +3,7 @@
|
||||
when the target forks, this breaks all normal fuzzing runs.
|
||||
Sometimes, though, it is enough to just run the child process.
|
||||
If this is the case, then this LD_PRELOAD library will always return 0 on fork,
|
||||
the target will belive it is running as the child, post-fork.
|
||||
the target will believe it is running as the child, post-fork.
|
||||
|
||||
This is defork.c from the amazing preeny project
|
||||
https://github.com/zardus/preeny
|
||||
|
@ -26,7 +26,7 @@ def fillDictWithFilenameKeys(dir):
|
||||
dict[filename] = None
|
||||
return dict
|
||||
|
||||
# recusively compute the chain of queue items that led to the AFL crash file
|
||||
# recursively compute the chain of queue items that led to the AFL crash file
|
||||
def compute_mutation_chain(filename, current_fuzzer, n):
|
||||
|
||||
if re.match(".*src:(\\d+),", filename):
|
||||
@ -104,7 +104,7 @@ def main():
|
||||
parser.add_argument(
|
||||
"-n", "--node",
|
||||
action = 'store',
|
||||
help = '[Only used in single mode; optinal] name of the fuzzer node that contains the crash file supplied in the --file argument (e.g. \'fuzzer03\'). Defaults to \'fuzzer01\' if not supplied',
|
||||
help = '[Only used in single mode; optional] name of the fuzzer node that contains the crash file supplied in the --file argument (e.g. \'fuzzer03\'). Defaults to \'fuzzer01\' if not supplied',
|
||||
required = False
|
||||
)
|
||||
|
||||
@ -130,7 +130,7 @@ def main():
|
||||
print("Error: \'" + crash_file_path + "\' does not exist.\nPlease verify whether the node and filename are correct.")
|
||||
return
|
||||
|
||||
# Create the interal representation of the various queues of parallel fuzzing nodes
|
||||
# Create the internal representation of the various queues of parallel fuzzing nodes
|
||||
for dir in os.listdir(args.input):
|
||||
if re.match("^fuzzer\\d+", dir):
|
||||
queues[dir] = fillDictWithFilenameKeys(args.input + '/' + dir + '/queue')
|
||||
|
Loading…
x
Reference in New Issue
Block a user