Compare commits

...

73 Commits

Author SHA1 Message Date
9f6b012fbf Merge pull request #2117 from AFLplusplus/dev
push to stable
2024-06-09 19:09:17 +02:00
ec0b83f127 4.21c 2024-06-09 18:39:56 +02:00
0c81982e67 nit 2024-06-09 18:32:36 +02:00
5014b86c3c fix AFL_FRIDA_DEBUG_MAPS 2024-06-09 15:44:10 +02:00
44b5e1f488 fix no_forkserver mode 2024-06-09 12:26:48 +02:00
31652eeb2a nit 2024-06-09 12:19:58 +02:00
4bb4d4ad00 fix -n 2024-06-09 12:16:32 +02:00
5331eca5d9 allow multiple -m 2024-06-09 12:02:59 +02:00
74e264a20a move function 2024-06-07 13:46:15 +02:00
f0937f96d4 target hash 2024-06-07 11:48:58 +02:00
92cbdb9f45 update unicorn 2024-06-07 11:41:35 +02:00
fe36ceaa55 minor testcache optimizations 2024-06-07 11:16:42 +02:00
0618bfd4ae fix 2024-06-07 09:58:27 +02:00
bdfd38771a add cmplog_time measurement 2024-06-07 09:47:29 +02:00
477063e9ee memory adjustments 2024-06-06 17:52:21 +02:00
e46c106b89 new seed selection algorithm 2024-06-06 10:25:23 +02:00
69630338ff Merge pull request #2114 from WorksButNotTested/frida-rlimit
Fix issue for setrlimit
2024-06-05 20:21:51 +02:00
112759cd39 Merge pull request #2113 from AFLplusplus/fix_mmap_cmplog
Fix cmplog shared memory size when USEMMAP=1
2024-06-05 20:19:38 +02:00
f8767c397b Fix issue for setrlimit 2024-06-05 18:43:20 +01:00
e8d098335b Fix cmplog shared memory size when USEMMAP=1 2024-06-05 19:33:02 +02:00
12a87cfacb nits 2024-06-05 10:40:12 +02:00
2806d6be2f optimize syncing 2024-06-05 09:20:30 +02:00
2d9b793dbb AFL_NO_SYNC 2024-06-04 14:48:02 +02:00
7f02f0da61 Merge pull request #2106 from a-shvedov/stable
feature: Added (generate_libtoken_dict.sh) script for simplified work with `libtokencap`
2024-06-04 11:29:27 +02:00
bc2ccf464f Update README.md 2024-06-03 19:14:04 +03:00
b8536ced09 Update generate_libtoken_dict.sh 2024-06-03 19:01:50 +03:00
1db82f3303 update grammar mutator 2024-06-03 09:23:43 +02:00
fd713413e8 Merge pull request #2109 from AFLplusplus/dev
fix afl-showmap
2024-06-01 16:56:35 +02:00
2d4a4ba73f fix afl-showmap 2024-06-01 16:55:56 +02:00
348f980f21 Merge pull request #2108 from AFLplusplus/dev
push to stable
2024-06-01 16:37:28 +02:00
ca55858aa7 Merge pull request #2107 from AFLplusplus/reg
fix regression
2024-06-01 16:34:50 +02:00
e639521b01 changelog 2024-06-01 16:34:23 +02:00
894339c5d7 try regression fix 2024-06-01 12:26:26 +02:00
e13dc9b7e6 todo 2024-06-01 12:17:53 +02:00
5fb657f569 Rename make_dict_v2.sh to generate_libtoken_dict.sh 2024-06-01 13:03:55 +03:00
d2700c7525 Update README.md 2024-06-01 13:03:22 +03:00
4cf358b589 Update README.md 2024-06-01 02:06:20 +03:00
5e708b23c6 Update make_dict_v2.sh
(-) removed default vars ;
(+) added LD_PRELOAD_PATH check
2024-06-01 01:18:03 +03:00
9419e39fdf nits 2024-05-31 18:32:31 +02:00
c202d80dea Update make_dict_v2.sh 2024-05-30 22:38:37 +03:00
eecbdd99e1 Update and rename make_dict.sh to make_dict_v2.sh 2024-05-30 22:26:24 +03:00
64293cdc82 Create make_dict.sh 2024-05-30 11:13:56 +03:00
f8a5f1cd9e Merge branch 'AFLplusplus:stable' into stable 2024-05-30 10:43:01 +03:00
a3125c38f4 fix afl-showmap shmmemleak 2024-05-29 12:55:28 +02:00
224add0222 update unicorn 2024-05-28 11:12:33 +02:00
19636f748c Unicornafl: Fix incorrect comment (#2103) 2024-05-28 02:24:43 +02:00
7aa5e1c443 Merge pull request #2104 from Evian-Zhang/fix-unicorn-lldb-dumper
Make lldb dumper of unicorn_mode work in modern LLDB
2024-05-27 21:18:28 +02:00
93279db71b Make lldb dumper of unicorn_mode work in modern LLDB 2024-05-27 19:15:35 +08:00
5bf760510e Merge pull request #2102 from ndrewh/testcache-fix
fix: testcache hangs for large test cases
2024-05-26 08:12:29 +02:00
03dc80afc4 fix: testcache hangs for large test cases 2024-05-25 23:44:57 +00:00
fda3106fd9 Merge pull request #2099 from Atlante45/dev
Fix dynamic_lookup linker flag for Apple clang
2024-05-24 01:33:55 +02:00
9721a77204 Fix dynamic_lookup linker flag for Apple clang 2024-05-23 11:14:53 -07:00
92a8c2804f fix the fix for symcc 2024-05-21 16:31:42 +02:00
e1521fa8eb fix symcc custom mutator 2024-05-21 11:04:25 +02:00
4e3cd8ac3f nit 2024-05-20 14:02:22 +02:00
31a8beb449 support new llvm 19 changes 2024-05-19 13:47:53 +02:00
e7d871c8bf Merge pull request #2093 from AFLplusplus/dev
push to stable
2024-05-17 23:55:55 +02:00
56d5aa3101 log 2024-05-17 23:55:43 +02:00
c6a2a4046e Merge pull request #2092 from fbeqv/dev
Fix runtime underflow & -V exiting before syncing
2024-05-17 23:41:39 +02:00
6dd5e931fc Fix runtime underflow & -V exiting before syncing
print_stats sets exit_soon even while syncing, this leaves -V 0 still broken, as we don't finish syncing.

Additionally, the change that introduced the previous -V fix also broke the runtime tracking, as runtime needs to include all time including sync, splice etc. This caused an underflow in the reported runtime.
2024-05-17 14:33:32 -07:00
635140ba43 help qemu build for some linux platforms 2024-05-17 09:45:56 +02:00
497f341eac Revert "no weights"
This reverts commit 068aa13c6b.
2024-05-16 14:27:33 +02:00
068aa13c6b no weights 2024-05-16 14:27:04 +02:00
ba7ae6c59d nits 2024-05-16 14:21:00 +02:00
6ae95271be nits 2024-05-16 09:17:59 +02:00
a2e0163cc1 Merge pull request #2091 from bet4it/collect_coverage
Fix bug of `afl-showmap` in `collect_coverage` mode
2024-05-16 09:14:15 +02:00
a26bb0b0f2 Merge pull request #2090 from AFLplusplus/dev
push to stable
2024-05-14 13:18:22 +02:00
0cf78b7748 Fix bug of afl-showmap in collect_coverage mode 2024-05-14 17:17:58 +08:00
90fbf59bf1 Merge pull request #2084 from AFLplusplus/dev
push to stable
2024-05-11 09:16:21 +02:00
ad0d0c77fb Merge pull request #2071 from AFLplusplus/dev
Push to stable
2024-04-26 16:17:41 +02:00
1d17210d9f Merge pull request #2052 from AFLplusplus/dev
4.20 release pre-PR
2024-04-13 11:50:49 +02:00
629edb1e78 Merge pull request #2 from AFLplusplus/stable
push to stable (#1734)
2023-05-22 16:57:45 +03:00
8012b555a8 Merge pull request #1 from AFLplusplus/stable
sync
2023-05-05 23:27:13 +03:00
36 changed files with 558 additions and 356 deletions

View File

@ -2,9 +2,9 @@
<img align="right" src="https://raw.githubusercontent.com/AFLplusplus/Website/main/static/aflpp_bg.svg" alt="AFL++ logo" width="250" heigh="250">
Release version: [4.20c](https://github.com/AFLplusplus/AFLplusplus/releases)
Release version: [4.21c](https://github.com/AFLplusplus/AFLplusplus/releases)
GitHub version: 4.21a
GitHub version: 4.21c
Repository:
[https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus)

View File

@ -2,6 +2,8 @@
## Must
- fast restart of afl-fuzz if cmdline + target hash is the same
- check for null ptr for xml/curl/g_ string transform functions
- hardened_usercopy=0 page_alloc.shuffle=0
- add value_profile but only enable after 15 minutes without finds
- cmplog max items env?
@ -11,12 +13,12 @@
- afl-showmap -f support
- afl-fuzz multicore wrapper script
- when trimming then perform crash detection
- cyclomatic complexity: 2 + calls + edges - blocks
## Should
- afl-crash-analysis
- cmplog: add loop count resolving (byte -> loop cnt change, calc special values)
- support persistent and deferred fork server in afl-showmap?
- better autodetection of shifting runtime timeout values
- afl-plot to support multiple plot_data

View File

@ -1 +1 @@
5ed4f8d
95a6857

View File

@ -22,10 +22,10 @@ afl_state_t *afl_struct;
typedef struct my_mutator {
afl_state_t *afl;
u8 * mutator_buf;
u8 * out_dir;
u8 * tmp_dir;
u8 * target;
u8 *mutator_buf;
u8 *out_dir;
u8 *tmp_dir;
u8 *target;
uint32_t seed;
} my_mutator_t;
@ -101,7 +101,7 @@ my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
/* When a new queue entry is added we run this input with the symcc
instrumented binary */
uint8_t afl_custom_queue_new_entry(my_mutator_t * data,
uint8_t afl_custom_queue_new_entry(my_mutator_t *data,
const uint8_t *filename_new_queue,
const uint8_t *filename_orig_queue) {
@ -176,7 +176,7 @@ uint8_t afl_custom_queue_new_entry(my_mutator_t * data,
struct dirent **nl;
int32_t items = scandir(data->tmp_dir, &nl, NULL, NULL);
u8 * origin_name = basename(filename_new_queue);
u8 *origin_name = basename(filename_new_queue);
int32_t i;
if (items > 0) {
@ -187,8 +187,8 @@ uint8_t afl_custom_queue_new_entry(my_mutator_t * data,
DBG("test=%s\n", fn);
if (stat(source_name, &st) == 0 && S_ISREG(st.st_mode) && st.st_size) {
u8 *destination_name =
alloc_printf("%s/%s.%s", data->out_dir, origin_name, nl[i]->d_name);
u8 *destination_name = alloc_printf("%s/%s.%s", data->out_dir,
origin_name, nl[i]->d_name);
rename(source_name, destination_name);
ck_free(destination_name);
DBG("found=%s\n", source_name);
@ -248,7 +248,7 @@ uint32_t afl_custom_fuzz_count(my_mutator_t *data, const u8 *buf,
for (i = 0; i < (u32)items; ++i) {
struct stat st;
u8 * fn = alloc_printf("%s/%s", data->out_dir, nl[i]->d_name);
u8 *fn = alloc_printf("%s/%s", data->out_dir, nl[i]->d_name);
DBG("test=%s\n", fn);
if (stat(fn, &st) == 0 && S_ISREG(st.st_mode) && st.st_size) {
@ -282,12 +282,12 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
if (items <= 0) return 0;
for (i = 0; i < (u32)items; ++i) {
for (i = 0; i < (s32)items; ++i) {
struct stat st;
u8 * fn = alloc_printf("%s/%s", data->out_dir, nl[i]->d_name);
if (!done) {
if (done == 0) {
struct stat st;
u8 *fn = alloc_printf("%s/%s", data->out_dir, nl[i]->d_name);
if (stat(fn, &st) == 0 && S_ISREG(st.st_mode) && st.st_size) {
@ -306,10 +306,10 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
}
unlink(fn);
ck_free(fn);
}
ck_free(fn);
free(nl[i]);
}

View File

@ -3,24 +3,44 @@
This is the list of all noteworthy changes made in every public
release of the tool. See README.md for the general instruction manual.
### Version ++4.21a (dev)
### Version ++4.21c (release)
* afl-fuzz
- fixed a regression in afl-fuzz that resulted in a 5-10% performace loss
do a switch from gettimeofday() to clock_gettime() which should be rather
three times faster. The reason for this is unknown.
- new queue selection algorithm based on 2 core years of queue data
analysis. gives a noticable improvement on coverage although the results
seem counterintuitive :-)
- added AFL_DISABLE_REDUNDANT for huge queues
- added `AFL_NO_SYNC` environment variable that does what you think it does
- fix AFL_PERSISTENT_RECORD
- run custom_post_process after standard trimming
- prevent filenames in the queue that have spaces
- minor fix for FAST schedules
- more frequent stats update when syncing (todo: check performance impact)
- now timing of calibration, trimming and syncing is measured seperately,
thanks to @eqv!
- -V timing is now accurately the fuzz time (without syncing), before
long calibration times and syncing could result in now fuzzing being
made when the time was already run out until then, thanks to @eqv!
- fix -n uninstrumented mode when ending fuzzing
- enhanced the ASAN configuration
- make afl-fuzz use less memory with cmplog and fix a memleak
* afl-cc:
- re-enable i386 support that was accidently disabled
- fixes for LTO and outdated afl-gcc mode
- fixes for LTO and outdated afl-gcc mode for i386
- fix COMPCOV split compare for old LLVMs
- disable xml/curl/g_ string transform functions because we do not check
for null pointers ... TODO
- ensure shared memory variables are visible in weird build setups
- compatability to new LLVM 19 changes
* afl-cmin
- work with input files that have a space
* enhanced the ASAN configuration
* afl-showmap
- fix memory leak on shmem testcase usage (thanks to @ndrewh)
- minor fix to collect coverage -C (thanks to @bet4it)
* Fixed a shmem mmap bug (that rarely came up on MacOS)
* libtokencap: script generate_libtoken_dict.sh added by @a-shvedov
### Version ++4.20c (release)
@ -56,12 +76,13 @@
- afl-whatsup:
- now also displays current average speed
- small bugfixes
- Fixes for aflpp custom mutator and standalone tool
- custom mutators:
- fixes for aflpp custom mutator and standalone tool
- important fix to the symcc custom mutator
- Minor edits to afl-persistent-config
- Prevent temporary files being left behind on aborted afl-whatsup
- More CPU benchmarks added to benchmark/
### Version ++4.10c (release)
- afl-fuzz:
- default power schedule is now EXPLORE, due a fix in fast schedules

View File

@ -588,6 +588,9 @@ checks or alter some of the more exotic semantics of the tool:
between fuzzing instances synchronization. Default sync time is 30 minutes,
note that time is halved for -M main nodes.
- `AFL_NO_SYNC` disables any syncing whatsoever and takes priority on all
other syncing parameters.
- Setting `AFL_TARGET_ENV` causes AFL++ to set extra environment variables for
the target binary. Example: `AFL_TARGET_ENV="VAR1=1 VAR2='a b c'" afl-fuzz
... `. This exists mostly for things like `LD_LIBRARY_PATH` but it would

View File

@ -49,14 +49,23 @@ void instrument_cache_init(void) {
if (setrlimit(RLIMIT_AS, &data_limit) != 0) {
FFATAL("Failed to setrlimit: %d", errno);
FWARNF("Failed to setrlimit: %d, you may need root or CAP_SYS_RESOURCE",
errno);
}
map_base =
gum_memory_allocate(NULL, instrument_cache_size, instrument_cache_size,
GUM_PAGE_READ | GUM_PAGE_WRITE);
if (map_base == MAP_FAILED) { FFATAL("Failed to map segment: %d", errno); }
if (map_base == MAP_FAILED) {
FFATAL(
"Failed to map segment: %d. This can be caused by failure to setrlimit."
"Disabling or reducing the size of the allocation using "
"AFL_FRIDA_INST_NO_CACHE or AFL_FRIDA_INST_CACHE_SIZE may help",
errno);
}
FOKF(cBLU "Instrumentation" cRST " - " cGRN "cache addr:" cYEL " [0x%016lX]",
GUM_ADDRESS(map_base));

View File

@ -194,24 +194,23 @@ static gboolean print_ranges_callback(const GumRangeDetails *details,
if (details->file == NULL) {
FVERBOSE("\t0x%016" G_GINT64_MODIFIER "x-0x%016" G_GINT64_MODIFIER
"X %c%c%c",
details->range->base_address,
details->range->base_address + details->range->size,
details->protection & GUM_PAGE_READ ? 'R' : '-',
details->protection & GUM_PAGE_WRITE ? 'W' : '-',
details->protection & GUM_PAGE_EXECUTE ? 'X' : '-');
OKF("\t0x%016" G_GINT64_MODIFIER "x-0x%016" G_GINT64_MODIFIER "X %c%c%c",
details->range->base_address,
details->range->base_address + details->range->size,
details->protection & GUM_PAGE_READ ? 'R' : '-',
details->protection & GUM_PAGE_WRITE ? 'W' : '-',
details->protection & GUM_PAGE_EXECUTE ? 'X' : '-');
} else {
FVERBOSE("\t0x%016" G_GINT64_MODIFIER "x-0x%016" G_GINT64_MODIFIER
"X %c%c%c %s(0x%016" G_GINT64_MODIFIER "x)",
details->range->base_address,
details->range->base_address + details->range->size,
details->protection & GUM_PAGE_READ ? 'R' : '-',
details->protection & GUM_PAGE_WRITE ? 'W' : '-',
details->protection & GUM_PAGE_EXECUTE ? 'X' : '-',
details->file->path, details->file->offset);
OKF("\t0x%016" G_GINT64_MODIFIER "x-0x%016" G_GINT64_MODIFIER
"X %c%c%c %s(0x%016" G_GINT64_MODIFIER "x)",
details->range->base_address,
details->range->base_address + details->range->size,
details->protection & GUM_PAGE_READ ? 'R' : '-',
details->protection & GUM_PAGE_WRITE ? 'W' : '-',
details->protection & GUM_PAGE_EXECUTE ? 'X' : '-', details->file->path,
details->file->offset);
}
@ -581,7 +580,7 @@ static GArray *merge_ranges(GArray *a) {
void ranges_print_debug_maps(void) {
FVERBOSE("Maps");
OKF("Maps");
gum_process_enumerate_ranges(GUM_PAGE_NO_ACCESS, print_ranges_callback, NULL);
}

View File

@ -139,6 +139,10 @@
#define AFL_RAND_RETURN u32
#endif
#ifndef INTERESTING_32_LEN
#error INTERESTING_32_LEN not defined - BUG!
#endif
extern s8 interesting_8[INTERESTING_8_LEN];
extern s16 interesting_16[INTERESTING_8_LEN + INTERESTING_16_LEN];
extern s32
@ -453,7 +457,7 @@ typedef struct afl_env_vars {
afl_no_startup_calibration, afl_no_warn_instability,
afl_post_process_keep_original, afl_crashing_seeds_as_new_crash,
afl_final_sync, afl_ignore_seed_problems, afl_disable_redundant,
afl_sha1_filenames;
afl_sha1_filenames, afl_no_sync;
u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path,
*afl_hang_tmout, *afl_forksrv_init_tmout, *afl_preload,
@ -652,6 +656,7 @@ typedef struct afl_state {
switch_fuzz_mode, /* auto or fixed fuzz mode */
calibration_time_us, /* Time spend on calibration */
sync_time_us, /* Time spend on sync */
cmplog_time_us, /* Time spend on cmplog */
trim_time_us; /* Time spend on trimming */
u32 slowest_exec_ms, /* Slowest testcase non hang in ms */
@ -1222,6 +1227,7 @@ void show_init_stats(afl_state_t *);
void update_calibration_time(afl_state_t *afl, u64 *time);
void update_trim_time(afl_state_t *afl, u64 *time);
void update_sync_time(afl_state_t *afl, u64 *time);
void update_cmplog_time(afl_state_t *afl, u64 *time);
/* StatsD */
@ -1272,6 +1278,7 @@ void get_core_count(afl_state_t *);
void fix_up_sync(afl_state_t *);
void check_asan_opts(afl_state_t *);
void check_binary(afl_state_t *, u8 *);
u64 get_binary_hash(u8 *fn);
void check_if_tty(afl_state_t *);
void save_cmdline(afl_state_t *, u32, char **);
void read_foreign_testcases(afl_state_t *, int);

View File

@ -33,6 +33,10 @@
#define MUT_STRATEGY_ARRAY_SIZE 256
#ifndef INTERESTING_32
#error INTERESTING_32 is not defined - BUG!
#endif
s8 interesting_8[] = {INTERESTING_8};
s16 interesting_16[] = {INTERESTING_8, INTERESTING_16};
s32 interesting_32[] = {INTERESTING_8, INTERESTING_16, INTERESTING_32};

View File

@ -26,7 +26,7 @@
/* Version string: */
// c = release, a = volatile github dev, e = experimental branch
#define VERSION "++4.21a"
#define VERSION "++4.21c"
/******************************************************
* *
@ -324,9 +324,9 @@
#define SYNC_INTERVAL 8
/* Sync time (minimum time between syncing in ms, time is halfed for -M main
nodes) - default is 30 minutes: */
nodes) - default is 20 minutes: */
#define SYNC_TIME (30 * 60 * 1000)
#define SYNC_TIME (20 * 60 * 1000)
/* Output directory reuse grace period (minutes): */

View File

@ -81,14 +81,13 @@ static char *afl_environment_variables[] = {
"AFL_LLVM_MAP_DYNAMIC", "AFL_LLVM_NGRAM_SIZE", "AFL_NGRAM_SIZE",
"AFL_LLVM_NO_RPATH", "AFL_LLVM_NOT_ZERO", "AFL_LLVM_INSTRUMENT_FILE",
"AFL_LLVM_THREADSAFE_INST", "AFL_LLVM_SKIP_NEVERZERO", "AFL_NO_AFFINITY",
"AFL_TRY_AFFINITY", "AFL_LLVM_LTO_DONTWRITEID",
"AFL_LLVM_LTO_SKIPINIT"
"AFL_LLVM_LTO_STARTID",
"AFL_FUZZER_LOOPCOUNT", "AFL_NO_ARITH", "AFL_NO_AUTODICT", "AFL_NO_BUILTIN",
"AFL_TRY_AFFINITY", "AFL_LLVM_LTO_DONTWRITEID", "AFL_LLVM_LTO_SKIPINIT",
"AFL_LLVM_LTO_STARTID", "AFL_FUZZER_LOOPCOUNT", "AFL_NO_ARITH",
"AFL_NO_AUTODICT", "AFL_NO_BUILTIN",
#if defined USE_COLOR && !defined ALWAYS_COLORED
"AFL_NO_COLOR", "AFL_NO_COLOUR",
#endif
"AFL_NO_CPU_RED",
"AFL_NO_CPU_RED", "AFL_NO_SYNC",
"AFL_NO_CFG_FUZZING", // afl.rs rust crate option
"AFL_NO_CRASH_README", "AFL_NO_FORKSRV", "AFL_NO_UI", "AFL_NO_PYTHON",
"AFL_NO_STARTUP_CALIBRATION", "AFL_NO_WARN_INSTABILITY",

View File

@ -1849,7 +1849,7 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) {
to avoid duplicate calls (which can happen as an artifact of the underlying
implementation in LLVM). */
if (__afl_final_loc < 5) __afl_final_loc = 5; // we skip the first 5 entries
if (__afl_final_loc < 4) __afl_final_loc = 4; // we skip the first 5 entries
*(start++) = ++__afl_final_loc;

View File

@ -136,7 +136,11 @@ bool isIgnoreFunction(const llvm::Function *F) {
for (auto const &ignoreListFunc : ignoreList) {
#if LLVM_VERSION_MAJOR >= 19
if (F->getName().starts_with(ignoreListFunc)) { return true; }
#else
if (F->getName().startswith(ignoreListFunc)) { return true; }
#endif
}

View File

@ -54,6 +54,12 @@
#define nullptr 0
#endif
#if LLVM_MAJOR >= 19
#define STARTSWITH starts_with
#else
#define STARTSWITH startswith
#endif
#include <set>
#include "afl-llvm-common.h"
@ -532,10 +538,10 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
}
if (!isSizedcmp) needs_null = true;
if (Callee->getName().startswith("g_") ||
Callee->getName().startswith("curl_") ||
Callee->getName().startswith("Curl_") ||
Callee->getName().startswith("xml"))
if (Callee->getName().STARTSWITH("g_") ||
Callee->getName().STARTSWITH("curl_") ||
Callee->getName().STARTSWITH("Curl_") ||
Callee->getName().STARTSWITH("xml"))
nullCheck = true;
Value *sizedValue = isSizedcmp ? callInst->getArgOperand(2) : NULL;

View File

@ -202,6 +202,8 @@ QEMU_CONF_FLAGS=" \
--disable-xfsctl \
--target-list="${CPU_TARGET}-linux-user" \
--without-default-devices \
--extra-cflags=-Wno-int-conversion \
--disable-werror \
"
if [ -n "${CROSS_PREFIX}" ]; then
@ -243,7 +245,6 @@ if [ "$DEBUG" = "1" ]; then
--enable-debug-stack-usage \
--enable-debug-tcg \
--enable-qom-cast-debug \
--enable-werror \
"
else
@ -254,7 +255,6 @@ else
--disable-debug-tcg \
--disable-qom-cast-debug \
--disable-stack-protector \
--disable-werror \
--disable-docs \
"

View File

@ -2366,8 +2366,7 @@ static void add_aflpplib(aflcc_state_t *aflcc) {
insert_param(aflcc, afllib);
#ifdef __APPLE__
insert_param(aflcc, "-Wl,-undefined");
insert_param(aflcc, "dynamic_lookup");
insert_param(aflcc, "-Wl,-undefined,dynamic_lookup");
#endif
}
@ -2794,11 +2793,11 @@ static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) {
"MODES: NCC PERSIST DICT LAF "
"CMPLOG SELECT\n"
" [LLVM] LLVM: %s%s\n"
" PCGUARD %s yes yes module yes yes "
" PCGUARD %s yes yes module yes yes "
"yes\n"
" NATIVE AVAILABLE no yes no no "
"part. yes\n"
" CLASSIC %s no yes module yes yes "
" CLASSIC %s no yes module yes yes "
"yes\n"
" - NORMAL\n"
" - CALLER\n"
@ -2815,10 +2814,10 @@ static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) {
" [GCC/CLANG] simple gcc/clang: %s%s\n"
" CLASSIC DEFAULT no no no no no "
"no\n\n",
aflcc->have_llvm ? "AVAILABLE" : "unavailable!",
aflcc->have_llvm ? "AVAILABLE " : "unavailable!",
aflcc->compiler_mode == LLVM ? " [SELECTED]" : "",
aflcc->have_llvm ? "AVAILABLE" : "unavailable!",
aflcc->have_llvm ? "AVAILABLE" : "unavailable!",
aflcc->have_llvm ? "AVAILABLE " : "unavailable!",
aflcc->have_llvm ? "AVAILABLE " : "unavailable!",
aflcc->have_lto ? "AVAILABLE" : "unavailable!",
aflcc->compiler_mode == LTO ? " [SELECTED]" : "",
aflcc->have_gcc_plugin ? "AVAILABLE" : "unavailable!",
@ -2844,7 +2843,7 @@ static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) {
" The best is LTO but it often needs RANLIB and AR settings outside "
"of afl-cc.\n\n");
#if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0)
#if LLVM_MAJOR >= 11 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0)
#define NATIVE_MSG \
" LLVM-NATIVE: use llvm's native PCGUARD instrumentation (less " \
"performant)\n"

View File

@ -59,27 +59,6 @@ u8 last_intr = 0;
#define AFL_PATH "/usr/local/lib/afl/"
#endif
/* - Some BSD (i.e.: FreeBSD) offer the FAST clock source as
* equivalent to Linux COARSE clock source. Aliasing COARSE to
* FAST on such systems when COARSE is not already defined.
* - macOS has no support of CLOCK_MONOTONIC_COARSE clock type.
*/
#if defined(OS_DARWIN) || defined(OS_SUNOS) || defined(__APPLE__) || \
defined(__sun) || defined(__NetBSD__)
#define CLOCK_MONOTONIC_COARSE CLOCK_MONOTONIC
#elif defined(OS_FREEBSD)
#define CLOCK_MONOTONIC_COARSE CLOCK_MONOTONIC_FAST
#endif
/* Convert seconds to milliseconds. */
#define SEC_TO_MS(sec) ((sec) * 1000)
/* Convert seconds to microseconds. */
#define SEC_TO_US(sec) ((sec) * 1000000)
/* Convert nanoseconds to milliseconds. */
#define NS_TO_MS(ns) ((ns) / 1000000)
/* Convert nanoseconds to microseconds. */
#define NS_TO_US(ns) ((ns) / 1000)
void *afl_memmem(const void *haystack, size_t haystacklen, const void *needle,
size_t needlelen) {
@ -997,33 +976,25 @@ void read_bitmap(u8 *fname, u8 *map, size_t len) {
inline u64 get_cur_time(void) {
struct timespec ts;
int rc = clock_gettime(CLOCK_MONOTONIC_COARSE, &ts);
if (rc == -1) {
struct timeval tv;
struct timezone tz;
PFATAL("Failed to obtain timestamp (errno = %i: %s)\n", errno,
strerror(errno));
gettimeofday(&tv, &tz);
}
return SEC_TO_MS((uint64_t)ts.tv_sec) + NS_TO_MS((uint64_t)ts.tv_nsec);
return (tv.tv_sec * 1000ULL) + (tv.tv_usec / 1000);
}
/* Get unix time in microseconds */
u64 get_cur_time_us(void) {
inline u64 get_cur_time_us(void) {
struct timespec ts;
int rc = clock_gettime(CLOCK_MONOTONIC_COARSE, &ts);
if (rc == -1) {
struct timeval tv;
struct timezone tz;
PFATAL("Failed to obtain timestamp (errno = %i: %s)\n", errno,
strerror(errno));
gettimeofday(&tv, &tz);
}
return SEC_TO_US((uint64_t)ts.tv_sec) + NS_TO_US((uint64_t)ts.tv_nsec);
return (tv.tv_sec * 1000000ULL) + tv.tv_usec;
}

View File

@ -578,7 +578,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
void *nyx_config = fsrv->nyx_handlers->nyx_config_load(fsrv->target_path);
fsrv->nyx_handlers->nyx_config_set_workdir_path(nyx_config, workdir_path);
fsrv->nyx_handlers->nyx_config_set_input_buffer_size(nyx_config, fsrv->max_length);
fsrv->nyx_handlers->nyx_config_set_input_buffer_size(nyx_config,
fsrv->max_length);
fsrv->nyx_handlers->nyx_config_set_input_buffer_write_protection(nyx_config,
true);
@ -1654,7 +1655,8 @@ void afl_fsrv_kill(afl_forkserver_t *fsrv) {
if (fsrv->fsrv_pid > 0) {
kill(fsrv->fsrv_pid, fsrv->fsrv_kill_signal);
waitpid(fsrv->fsrv_pid, NULL, 0);
usleep(25);
waitpid(fsrv->fsrv_pid, NULL, WNOHANG);
}

View File

@ -60,32 +60,6 @@ inline u32 select_next_queue_entry(afl_state_t *afl) {
}
double compute_weight(afl_state_t *afl, struct queue_entry *q,
double avg_exec_us, double avg_bitmap_size,
double avg_top_size) {
double weight = 1.0;
if (likely(afl->schedule >= FAST && afl->schedule <= RARE)) {
u32 hits = afl->n_fuzz[q->n_fuzz_entry];
if (likely(hits)) { weight /= (log10(hits) + 1); }
}
if (likely(afl->schedule < RARE)) { weight *= (avg_exec_us / q->exec_us); }
weight *= (log(q->bitmap_size) / avg_bitmap_size);
weight *= (1 + (q->tc_ref / avg_top_size));
if (unlikely(weight < 0.1)) { weight = 0.1; }
if (unlikely(q->favored)) { weight *= 5; }
if (unlikely(!q->was_fuzzed)) { weight *= 2; }
if (unlikely(q->fs_redundant)) { weight *= 0.8; }
return weight;
}
/* create the alias table that allows weighted random selection - expensive */
void create_alias_table(afl_state_t *afl) {
@ -117,7 +91,7 @@ void create_alias_table(afl_state_t *afl) {
double avg_exec_us = 0.0;
double avg_bitmap_size = 0.0;
double avg_top_size = 0.0;
double avg_len = 0.0;
u32 active = 0;
for (i = 0; i < n; i++) {
@ -129,7 +103,7 @@ void create_alias_table(afl_state_t *afl) {
avg_exec_us += q->exec_us;
avg_bitmap_size += log(q->bitmap_size);
avg_top_size += q->tc_ref;
avg_len += q->len;
++active;
}
@ -138,7 +112,7 @@ void create_alias_table(afl_state_t *afl) {
avg_exec_us /= active;
avg_bitmap_size /= active;
avg_top_size /= active;
avg_len /= active;
for (i = 0; i < n; i++) {
@ -146,8 +120,59 @@ void create_alias_table(afl_state_t *afl) {
if (likely(!q->disabled)) {
q->weight =
compute_weight(afl, q, avg_exec_us, avg_bitmap_size, avg_top_size);
double weight = 1.0;
{ // inline does result in a compile error with LTO, weird
if (likely(afl->schedule >= FAST && afl->schedule <= RARE)) {
u32 hits = afl->n_fuzz[q->n_fuzz_entry];
if (likely(hits)) { weight /= (log10(hits) + 1); }
}
if (likely(afl->schedule < RARE)) {
double t = q->exec_us / avg_exec_us;
if (likely(t < 0.1)) {
// nothing
} else if (likely(t <= 0.25))
weight *= 0.9;
else if (likely(t <= 0.5)) {
// nothing
} else if (likely(t < 1.0))
weight *= 1.15;
else if (unlikely(t > 2.5 && t < 5.0))
weight *= 1.1;
// else nothing
}
double l = q->len / avg_len;
if (likely(l < 0.1))
weight *= 0.75;
else if (likely(l < 0.25))
weight *= 1.1;
else if (unlikely(l >= 10))
weight *= 1.1;
double bms = q->bitmap_size / avg_bitmap_size;
if (likely(bms < 0.5))
weight *= (1.0 + ((bms - 0.5) / 2));
else if (unlikely(bms > 1.33))
weight *= 1.1;
if (unlikely(!q->was_fuzzed)) { weight *= 2.5; }
if (unlikely(q->fs_redundant)) { weight *= 0.75; }
}
q->weight = weight;
q->perf_score = calculate_score(afl, q);
sum += q->weight;
@ -596,6 +621,8 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) {
q->trace_mini = NULL;
q->testcase_buf = NULL;
q->mother = afl->queue_cur;
q->weight = 1.0;
q->perf_score = 100;
#ifdef INTROSPECTION
q->bitsmap_size = afl->bitsmap_size;
@ -1201,9 +1228,11 @@ inline void queue_testcase_retake(afl_state_t *afl, struct queue_entry *q,
u32 len = q->len;
if (len != old_len) {
// only realloc if necessary or useful
// (a custom trim can make the testcase larger)
if (unlikely(len > old_len || len < old_len + 1024)) {
afl->q_testcase_cache_size = afl->q_testcase_cache_size + len - old_len;
afl->q_testcase_cache_size += len - old_len;
q->testcase_buf = (u8 *)realloc(q->testcase_buf, len);
if (unlikely(!q->testcase_buf)) {
@ -1232,41 +1261,48 @@ inline void queue_testcase_retake_mem(afl_state_t *afl, struct queue_entry *q,
if (likely(q->testcase_buf)) {
u32 is_same = in == q->testcase_buf;
if (likely(in != q->testcase_buf)) {
if (likely(len != old_len)) {
// only realloc if we save memory
if (unlikely(len < old_len + 1024)) {
u8 *ptr = (u8 *)realloc(q->testcase_buf, len);
u8 *ptr = (u8 *)realloc(q->testcase_buf, len);
if (likely(ptr)) {
if (likely(ptr)) {
q->testcase_buf = ptr;
afl->q_testcase_cache_size = afl->q_testcase_cache_size + len - old_len;
q->testcase_buf = ptr;
afl->q_testcase_cache_size += len - old_len;
}
}
}
memcpy(q->testcase_buf, in, len);
if (unlikely(!is_same)) { memcpy(q->testcase_buf, in, len); }
}
}
}
/* Returns the testcase buf from the file behind this queue entry.
Increases the refcount. */
Increases the refcount. */
inline u8 *queue_testcase_get(afl_state_t *afl, struct queue_entry *q) {
u32 len = q->len;
if (likely(q->testcase_buf)) { return q->testcase_buf; }
/* first handle if no testcase cache is configured */
u32 len = q->len;
double weight = q->weight;
if (unlikely(!afl->q_testcase_max_cache_size)) {
// first handle if no testcase cache is configured, or if the
// weighting of the testcase is below average.
if (unlikely(weight < 1.0 || !afl->q_testcase_max_cache_size)) {
u8 *buf;
if (unlikely(q == afl->queue_cur)) {
if (likely(q == afl->queue_cur)) {
buf = (u8 *)afl_realloc((void **)&afl->testcase_buf, len);
@ -1292,117 +1328,113 @@ inline u8 *queue_testcase_get(afl_state_t *afl, struct queue_entry *q) {
}
/* now handle the testcase cache */
/* now handle the testcase cache and we know it is an interesting one */
if (unlikely(!q->testcase_buf)) {
/* Buf not cached, let's load it */
u32 tid = afl->q_testcase_max_cache_count;
static u32 do_once = 0; // because even threaded we would want this. WIP
/* Buf not cached, let's load it */
u32 tid = afl->q_testcase_max_cache_count;
static u32 do_once = 0; // because even threaded we would want this. WIP
while (unlikely(
(afl->q_testcase_cache_size + len >= afl->q_testcase_max_cache_size &&
afl->q_testcase_cache_count > 1) ||
afl->q_testcase_cache_count >= afl->q_testcase_max_cache_entries - 1)) {
while (unlikely(
afl->q_testcase_cache_size + len >= afl->q_testcase_max_cache_size ||
afl->q_testcase_cache_count >= afl->q_testcase_max_cache_entries - 1)) {
/* We want a max number of entries to the cache that we learn.
Very simple: once the cache is filled by size - that is the max. */
/* We want a max number of entries to the cache that we learn.
Very simple: once the cache is filled by size - that is the max. */
if (unlikely(
afl->q_testcase_cache_size + len >=
afl->q_testcase_max_cache_size &&
(afl->q_testcase_cache_count < afl->q_testcase_max_cache_entries &&
afl->q_testcase_max_cache_count <
afl->q_testcase_max_cache_entries) &&
!do_once)) {
if (unlikely(afl->q_testcase_cache_size + len >=
afl->q_testcase_max_cache_size &&
(afl->q_testcase_cache_count <
afl->q_testcase_max_cache_entries &&
afl->q_testcase_max_cache_count <
afl->q_testcase_max_cache_entries) &&
!do_once)) {
if (afl->q_testcase_max_cache_count > afl->q_testcase_cache_count) {
if (afl->q_testcase_max_cache_count > afl->q_testcase_cache_count) {
afl->q_testcase_max_cache_entries = afl->q_testcase_max_cache_count + 1;
afl->q_testcase_max_cache_entries =
afl->q_testcase_max_cache_count + 1;
} else {
} else {
afl->q_testcase_max_cache_entries = afl->q_testcase_cache_count + 1;
}
do_once = 1;
// release unneeded memory
afl->q_testcase_cache = (struct queue_entry **)ck_realloc(
afl->q_testcase_cache,
(afl->q_testcase_max_cache_entries + 1) * sizeof(size_t));
afl->q_testcase_max_cache_entries = afl->q_testcase_cache_count + 1;
}
/* Cache full. We neet to evict one or more to map one.
Get a random one which is not in use */
do {
// if the cache (MB) is not enough for the queue then this gets
// undesirable because q_testcase_max_cache_count grows sometimes
// although the number of items in the cache will not change hence
// more and more loops
tid = rand_below(afl, afl->q_testcase_max_cache_count);
} while (afl->q_testcase_cache[tid] == NULL ||
afl->q_testcase_cache[tid] == afl->queue_cur);
struct queue_entry *old_cached = afl->q_testcase_cache[tid];
free(old_cached->testcase_buf);
old_cached->testcase_buf = NULL;
afl->q_testcase_cache_size -= old_cached->len;
afl->q_testcase_cache[tid] = NULL;
--afl->q_testcase_cache_count;
++afl->q_testcase_evictions;
if (tid < afl->q_testcase_smallest_free)
afl->q_testcase_smallest_free = tid;
do_once = 1;
// release unneeded memory
afl->q_testcase_cache = (struct queue_entry **)ck_realloc(
afl->q_testcase_cache,
(afl->q_testcase_max_cache_entries + 1) * sizeof(size_t));
}
if (unlikely(tid >= afl->q_testcase_max_cache_entries)) {
/* Cache full. We neet to evict one or more to map one.
Get a random one which is not in use */
// uh we were full, so now we have to search from start
tid = afl->q_testcase_smallest_free;
do {
}
// if the cache (MB) is not enough for the queue then this gets
// undesirable because q_testcase_max_cache_count grows sometimes
// although the number of items in the cache will not change hence
// more and more loops
tid = rand_below(afl, afl->q_testcase_max_cache_count);
// we need this while loop in case there were ever previous evictions but
// not in this call.
while (unlikely(afl->q_testcase_cache[tid] != NULL))
++tid;
} while (afl->q_testcase_cache[tid] == NULL ||
/* Map the test case into memory. */
afl->q_testcase_cache[tid] == afl->queue_cur);
int fd = open((char *)q->fname, O_RDONLY);
struct queue_entry *old_cached = afl->q_testcase_cache[tid];
free(old_cached->testcase_buf);
old_cached->testcase_buf = NULL;
afl->q_testcase_cache_size -= old_cached->len;
afl->q_testcase_cache[tid] = NULL;
--afl->q_testcase_cache_count;
++afl->q_testcase_evictions;
if (tid < afl->q_testcase_smallest_free)
afl->q_testcase_smallest_free = tid;
if (unlikely(fd < 0)) { PFATAL("Unable to open '%s'", (char *)q->fname); }
}
q->testcase_buf = (u8 *)malloc(len);
if (unlikely(tid >= afl->q_testcase_max_cache_entries)) {
if (unlikely(!q->testcase_buf)) {
// uh we were full, so now we have to search from start
tid = afl->q_testcase_smallest_free;
PFATAL("Unable to malloc '%s' with len %u", (char *)q->fname, len);
}
}
// we need this while loop in case there were ever previous evictions but
// not in this call.
while (unlikely(afl->q_testcase_cache[tid] != NULL))
++tid;
ck_read(fd, q->testcase_buf, len, q->fname);
close(fd);
/* Map the test case into memory. */
/* Register testcase as cached */
afl->q_testcase_cache[tid] = q;
afl->q_testcase_cache_size += len;
++afl->q_testcase_cache_count;
if (likely(tid >= afl->q_testcase_max_cache_count)) {
int fd = open((char *)q->fname, O_RDONLY);
afl->q_testcase_max_cache_count = tid + 1;
if (unlikely(fd < 0)) { PFATAL("Unable to open '%s'", (char *)q->fname); }
} else if (unlikely(tid == afl->q_testcase_smallest_free)) {
q->testcase_buf = (u8 *)malloc(len);
afl->q_testcase_smallest_free = tid + 1;
if (unlikely(!q->testcase_buf)) {
}
PFATAL("Unable to malloc '%s' with len %u", (char *)q->fname, len);
}
ck_read(fd, q->testcase_buf, len, q->fname);
close(fd);
/* Register testcase as cached */
afl->q_testcase_cache[tid] = q;
afl->q_testcase_cache_size += len;
++afl->q_testcase_cache_count;
if (likely(tid >= afl->q_testcase_max_cache_count)) {
afl->q_testcase_max_cache_count = tid + 1;
} else if (unlikely(tid == afl->q_testcase_smallest_free)) {
afl->q_testcase_smallest_free = tid + 1;
}
@ -1417,12 +1449,13 @@ inline void queue_testcase_store_mem(afl_state_t *afl, struct queue_entry *q,
u32 len = q->len;
if (unlikely(afl->q_testcase_cache_size + len >=
if (unlikely(q->weight < 1.0 ||
afl->q_testcase_cache_size + len >=
afl->q_testcase_max_cache_size ||
afl->q_testcase_cache_count >=
afl->q_testcase_max_cache_entries - 1)) {
// no space? will be loaded regularly later.
// no space or uninteresting? will be loaded regularly later.
return;
}

View File

@ -322,7 +322,7 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len,
memcpy(backup, buf, len);
memcpy(changed, buf, len);
if (afl->cmplog_random_colorization) {
if (likely(afl->cmplog_random_colorization)) {
random_replace(afl, changed, len);
@ -402,6 +402,7 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len,
u32 i = 1;
u32 positions = 0;
while (i) {
restart:
@ -2937,7 +2938,8 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
// afl->queue_cur->exec_cksum
u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
u8 r = 1;
u64 cmplog_start_us = get_cur_time_us();
u8 r = 1;
if (unlikely(!afl->pass_stats)) {
afl->pass_stats = ck_alloc(sizeof(struct afl_pass_stat) * CMP_MAP_W);
@ -2965,7 +2967,12 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
if (!afl->queue_cur->taint || !afl->queue_cur->cmplog_colorinput) {
if (unlikely(colorization(afl, buf, len, &taint))) { return 1; }
if (unlikely(colorization(afl, buf, len, &taint))) {
update_cmplog_time(afl, &cmplog_start_us);
return 1;
}
// no taint? still try, create a dummy to prevent again colorization
if (!taint) {
@ -2974,6 +2981,7 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
fprintf(stderr, "TAINT FAILED\n");
#endif
afl->queue_cur->colorized = CMPLOG_LVL_MAX;
update_cmplog_time(afl, &cmplog_start_us);
return 0;
}
@ -2994,17 +3002,20 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
}
update_cmplog_time(afl, &cmplog_start_us);
struct tainted *t = taint;
#ifdef _DEBUG
while (t) {
#ifdef _DEBUG
fprintf(stderr, "T: idx=%u len=%u\n", t->pos, t->len);
#endif
t = t->next;
}
#endif
#if defined(_DEBUG) || defined(CMPLOG_INTROSPECTION)
u64 start_time = get_cur_time();
u32 cmp_locations = 0;
@ -3025,6 +3036,7 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
}
update_cmplog_time(afl, &cmplog_start_us);
return 1;
}
@ -3048,6 +3060,7 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
}
update_cmplog_time(afl, &cmplog_start_us);
return 1;
}
@ -3066,6 +3079,7 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
u64 orig_hit_cnt, new_hit_cnt;
u64 orig_execs = afl->fsrv.total_execs;
orig_hit_cnt = afl->queued_items + afl->saved_crashes;
update_cmplog_time(afl, &cmplog_start_us);
afl->stage_name = "input-to-state";
afl->stage_short = "its";
@ -3142,33 +3156,35 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
}
update_cmplog_time(afl, &cmplog_start_us);
}
r = 0;
exit_its:
if (afl->cmplog_lvl == CMPLOG_LVL_MAX) {
// if (afl->cmplog_lvl == CMPLOG_LVL_MAX) {
afl->queue_cur->colorized = CMPLOG_LVL_MAX;
afl->queue_cur->colorized = CMPLOG_LVL_MAX;
if (afl->queue_cur->cmplog_colorinput) {
if (afl->queue_cur->cmplog_colorinput) {
ck_free(afl->queue_cur->cmplog_colorinput);
ck_free(afl->queue_cur->cmplog_colorinput);
}
}
while (taint) {
while (taint) {
t = taint->next;
ck_free(taint);
taint = t;
t = taint->next;
ck_free(taint);
taint = t;
}
}
afl->queue_cur->taint = NULL;
afl->queue_cur->taint = NULL;
} else {
/*} else {
afl->queue_cur->colorized = LVL2;
@ -3182,7 +3198,7 @@ exit_its:
}
}
}*/
#ifdef CMPLOG_COMBINE
if (afl->queued_items + afl->saved_crashes > orig_hit_cnt + 1) {
@ -3270,6 +3286,7 @@ exit_its:
#endif
update_cmplog_time(afl, &cmplog_start_us);
return r;
}

View File

@ -606,6 +606,8 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
}
q->exec_us = diff_us / afl->stage_max;
if (unlikely(!q->exec_us)) { q->exec_us = 1; }
q->bitmap_size = count_bytes(afl, afl->fsrv.trace_bits);
q->handicap = handicap;
q->cal_failed = 0;
@ -664,6 +666,8 @@ abort_calibration:
void sync_fuzzers(afl_state_t *afl) {
if (unlikely(afl->afl_env.afl_no_sync)) { return; }
DIR *sd;
struct dirent *sd_ent;
u32 sync_cnt = 0, synced = 0, entries = 0;

View File

@ -33,15 +33,15 @@ u8 is_det_timeout(u64 cur_ms, u8 is_flip) {
u8 should_det_fuzz(afl_state_t *afl, struct queue_entry *q) {
if (!afl->skipdet_g->virgin_det_bits) {
if (unlikely(!afl->skipdet_g->virgin_det_bits)) {
afl->skipdet_g->virgin_det_bits =
(u8 *)ck_alloc(sizeof(u8) * afl->fsrv.map_size);
}
if (!q->favored || q->passed_det) return 0;
if (!q->trace_mini) return 0;
if (likely(!q->favored || q->passed_det)) return 0;
if (unlikely(!q->trace_mini)) return 0;
if (!afl->skipdet_g->last_cov_undet)
afl->skipdet_g->last_cov_undet = get_cur_time();
@ -122,7 +122,8 @@ u8 skip_deterministic_stage(afl_state_t *afl, u8 *orig_buf, u8 *out_buf,
afl->stage_cur = 0;
orig_hit_cnt = afl->queued_items + afl->saved_crashes;
u8 *inf_eff_map = (u8 *)ck_alloc(sizeof(u8) * len);
static u8 *inf_eff_map;
inf_eff_map = (u8 *)ck_realloc(inf_eff_map, sizeof(u8) * len);
memset(inf_eff_map, 1, sizeof(u8) * len);
if (common_fuzz_stuff(afl, orig_buf, len)) { return 0; }

View File

@ -279,6 +279,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
afl->afl_env.afl_final_sync =
get_afl_env(afl_environment_variables[i]) ? 1 : 0;
} else if (!strncmp(env, "AFL_NO_SYNC",
afl_environment_variable_len)) {
afl->afl_env.afl_no_sync =
get_afl_env(afl_environment_variables[i]) ? 1 : 0;
} else if (!strncmp(env, "AFL_CUSTOM_MUTATOR_ONLY",
afl_environment_variable_len)) {
@ -762,8 +769,9 @@ void afl_states_stop(void) {
if (el->fsrv.fsrv_pid > 0) {
kill(el->fsrv.fsrv_pid, el->fsrv.fsrv_kill_signal);
usleep(100);
/* Make sure the forkserver does not end up as zombie. */
waitpid(el->fsrv.fsrv_pid, NULL, 0);
waitpid(el->fsrv.fsrv_pid, NULL, WNOHANG);
}

View File

@ -207,6 +207,12 @@ void load_stats_file(afl_state_t *afl) {
}
if (starts_with("cmplog_time", keystring)) {
afl->cmplog_time_us = strtoull(lptr, &nptr, 10) * 1000000;
}
if (starts_with("trim_time", keystring)) {
afl->trim_time_us = strtoull(lptr, &nptr, 10) * 1000000;
@ -321,8 +327,11 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
#ifndef __HAIKU__
if (getrusage(RUSAGE_CHILDREN, &rus)) { rus.ru_maxrss = 0; }
#endif
u64 runtime = afl->prev_run_time + cur_time - afl->start_time;
if (!runtime) { runtime = 1; }
u64 runtime_ms = afl->prev_run_time + cur_time - afl->start_time;
u64 overhead_ms = (afl->calibration_time_us + afl->sync_time_us +
afl->trim_time_us + afl->cmplog_time_us) /
1000;
if (!runtime_ms) { runtime_ms = 1; }
fprintf(
f,
@ -335,6 +344,7 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
"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"
@ -375,20 +385,18 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
"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 / 1000, (u32)getpid(),
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 -
((afl->calibration_time_us + afl->sync_time_us + afl->trim_time_us) /
1000)) /
1000,
afl->calibration_time_us / 1000000, afl->sync_time_us / 1000000,
afl->trim_time_us / 1000000, afl->fsrv.total_execs,
afl->fsrv.total_execs / ((double)(runtime) / 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,
@ -632,9 +640,10 @@ void show_stats_normal(afl_state_t *afl) {
cur_ms = get_cur_time();
if (afl->most_time_key) {
if (afl->most_time_key && afl->queue_cycle) {
if (afl->most_time * 1000 < cur_ms - afl->start_time) {
if (afl->most_time * 1000 + afl->sync_time_us / 1000 <
cur_ms - afl->start_time) {
afl->most_time_key = 2;
afl->stop_soon = 2;
@ -643,7 +652,7 @@ void show_stats_normal(afl_state_t *afl) {
}
if (afl->most_execs_key == 1) {
if (afl->most_execs_key == 1 && afl->queue_cycle) {
if (afl->most_execs <= afl->fsrv.total_execs) {
@ -1331,7 +1340,9 @@ void show_stats_normal(afl_state_t *afl) {
sprintf(tmp, "disabled, ");
} else if (unlikely(!afl->bytes_trim_out)) {
} else if (unlikely(!afl->bytes_trim_out ||
afl->bytes_trim_in <= afl->bytes_trim_out)) {
sprintf(tmp, "n/a, ");
@ -1348,7 +1359,9 @@ void show_stats_normal(afl_state_t *afl) {
strcat(tmp, "disabled");
} else if (unlikely(!afl->blocks_eff_total)) {
} else if (unlikely(!afl->blocks_eff_total ||
afl->blocks_eff_select >= afl->blocks_eff_total)) {
strcat(tmp, "n/a");
@ -1462,9 +1475,10 @@ void show_stats_pizza(afl_state_t *afl) {
cur_ms = get_cur_time();
if (afl->most_time_key) {
if (afl->most_time_key && afl->queue_cycle) {
if (afl->most_time * 1000 < cur_ms - afl->start_time) {
if (afl->most_time * 1000 + afl->sync_time_us / 1000 <
cur_ms - afl->start_time) {
afl->most_time_key = 2;
afl->stop_soon = 2;
@ -1473,7 +1487,7 @@ void show_stats_pizza(afl_state_t *afl) {
}
if (afl->most_execs_key == 1) {
if (afl->most_execs_key == 1 && afl->queue_cycle) {
if (afl->most_execs <= afl->fsrv.total_execs) {
@ -2482,7 +2496,7 @@ void show_init_stats(afl_state_t *afl) {
}
void update_calibration_time(afl_state_t *afl, u64 *time) {
inline void update_calibration_time(afl_state_t *afl, u64 *time) {
u64 cur = get_cur_time_us();
afl->calibration_time_us += cur - *time;
@ -2490,7 +2504,7 @@ void update_calibration_time(afl_state_t *afl, u64 *time) {
}
void update_trim_time(afl_state_t *afl, u64 *time) {
inline void update_trim_time(afl_state_t *afl, u64 *time) {
u64 cur = get_cur_time_us();
afl->trim_time_us += cur - *time;
@ -2498,7 +2512,7 @@ void update_trim_time(afl_state_t *afl, u64 *time) {
}
void update_sync_time(afl_state_t *afl, u64 *time) {
inline void update_sync_time(afl_state_t *afl, u64 *time) {
u64 cur = get_cur_time_us();
afl->sync_time_us += cur - *time;
@ -2506,3 +2520,11 @@ void update_sync_time(afl_state_t *afl, u64 *time) {
}
inline void update_cmplog_time(afl_state_t *afl, u64 *time) {
u64 cur = get_cur_time_us();
afl->cmplog_time_us += cur - *time;
*time = cur;
}

View File

@ -335,6 +335,7 @@ static void usage(u8 *argv0, int more_help) {
"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"
"AFL_NO_SYNC: disables all syncing\n"
"AFL_SYNC_TIME: sync time between fuzzing instances (in minutes)\n"
"AFL_FINAL_SYNC: sync a final time when exiting (will delay the exit!)\n"
"AFL_NO_CRASH_README: do not create a README in the crashes directory\n"
@ -914,8 +915,15 @@ int main(int argc, char **argv_orig, char **envp) {
u8 suffix = 'M';
if (mem_limit_given) { FATAL("Multiple -m options not supported"); }
mem_limit_given = 1;
if (mem_limit_given) {
WARNF("Overriding previous -m option.");
} else {
mem_limit_given = 1;
}
if (!optarg) { FATAL("Wrong usage of -m"); }
@ -1461,15 +1469,16 @@ int main(int argc, char **argv_orig, char **envp) {
#endif
configure_afl_kill_signals(&afl->fsrv, afl->afl_env.afl_child_kill_signal,
afl->afl_env.afl_fsrv_kill_signal,
(afl->fsrv.qemu_mode || afl->unicorn_mode
configure_afl_kill_signals(
&afl->fsrv, afl->afl_env.afl_child_kill_signal,
afl->afl_env.afl_fsrv_kill_signal,
(afl->fsrv.qemu_mode || afl->unicorn_mode || afl->fsrv.use_fauxsrv
#ifdef __linux__
|| afl->fsrv.nyx_mode
|| afl->fsrv.nyx_mode
#endif
)
? SIGKILL
: SIGTERM);
)
? SIGKILL
: SIGTERM);
setup_signal_handlers();
check_asan_opts(afl);
@ -1806,7 +1815,7 @@ int main(int argc, char **argv_orig, char **envp) {
afl->fsrv.use_fauxsrv = afl->non_instrumented_mode == 1 || afl->no_forkserver;
afl->fsrv.max_length = afl->max_length;
#ifdef __linux__
if (!afl->fsrv.nyx_mode) {
@ -2586,7 +2595,7 @@ int main(int argc, char **argv_orig, char **envp) {
(!afl->queue_cycle && afl->afl_env.afl_import_first)) &&
afl->sync_id)) {
if (!afl->queue_cycle && afl->afl_env.afl_import_first) {
if (unlikely(!afl->queue_cycle && afl->afl_env.afl_import_first)) {
OKF("Syncing queues from other fuzzer instances first ...");
@ -2594,16 +2603,15 @@ int main(int argc, char **argv_orig, char **envp) {
sync_fuzzers(afl);
if (!afl->queue_cycle && afl->afl_env.afl_import_first) {
// real start time, we reset, so this works correctly with -V
afl->start_time = get_cur_time();
}
}
++afl->queue_cycle;
if (afl->afl_env.afl_no_ui) {
ACTF("Entering queue cycle %llu\n", afl->queue_cycle);
}
runs_in_current_cycle = (u32)-1;
afl->cur_skipped_items = 0;
@ -2612,7 +2620,7 @@ int main(int argc, char **argv_orig, char **envp) {
// queue is fully cycled.
time_t cursec = time(NULL);
struct tm *curdate = localtime(&cursec);
if (likely(!afl->afl_env.afl_pizza_mode)) {
if (unlikely(!afl->afl_env.afl_pizza_mode)) {
if (unlikely(curdate->tm_mon == 3 && curdate->tm_mday == 1)) {
@ -2657,13 +2665,6 @@ int main(int argc, char **argv_orig, char **envp) {
}
if (unlikely(afl->not_on_tty)) {
ACTF("Entering queue cycle %llu.", afl->queue_cycle);
fflush(stdout);
}
/* If we had a full queue cycle with no new finds, try
recombination strategies next. */
@ -2949,26 +2950,13 @@ int main(int argc, char **argv_orig, char **envp) {
if (likely(!afl->stop_soon && afl->sync_id)) {
if (likely(afl->skip_deterministic)) {
if (unlikely(afl->is_main_node)) {
if (unlikely(afl->is_main_node)) {
if (unlikely(cur_time > (afl->sync_time >> 1) + afl->last_sync_time)) {
if (unlikely(cur_time >
(afl->sync_time >> 1) + afl->last_sync_time)) {
if (!(sync_interval_cnt++ % (SYNC_INTERVAL / 3))) {
if (!(sync_interval_cnt++ % (SYNC_INTERVAL / 3))) {
sync_fuzzers(afl);
}
}
} else {
if (unlikely(cur_time > afl->sync_time + afl->last_sync_time)) {
if (!(sync_interval_cnt++ % SYNC_INTERVAL)) { sync_fuzzers(afl); }
sync_fuzzers(afl);
}
@ -2976,7 +2964,11 @@ int main(int argc, char **argv_orig, char **envp) {
} else {
sync_fuzzers(afl);
if (unlikely(cur_time > afl->sync_time + afl->last_sync_time)) {
if (!(sync_interval_cnt++ % SYNC_INTERVAL)) { sync_fuzzers(afl); }
}
}

View File

@ -95,6 +95,24 @@ inline u64 hash64(u8 *key, u32 len, u64 seed) {
}
/* Hash a file */
u64 get_binary_hash(u8 *fn) {
int fd = open(fn, O_RDONLY);
if (fd < 0) { PFATAL("Unable to open '%s'", fn); }
struct stat st;
if (fstat(fd, &st) < 0) { PFATAL("Unable to fstat '%s'", fn); }
u32 f_len = st.st_size;
u8 *f_data = mmap(0, f_len, PROT_READ, MAP_PRIVATE, fd, 0);
if (f_data == MAP_FAILED) { PFATAL("Unable to mmap file '%s'", fn); }
close(fd);
u64 hash = hash64(f_data, f_len, 0);
if (munmap(f_data, f_len)) { PFATAL("unmap() failed"); }
return hash;
}
// Public domain SHA1 implementation copied from:
// https://github.com/x42/liboauth/blob/7001b8256cd654952ec2515b055d2c5b243be600/src/sha1.c

View File

@ -239,15 +239,15 @@ u8 *afl_shm_init(sharedmem_t *shm, size_t map_size,
if (shm->cmplog_g_shm_fd == -1) { PFATAL("shm_open() failed"); }
/* configure the size of the shared memory segment */
if (ftruncate(shm->cmplog_g_shm_fd, map_size)) {
if (ftruncate(shm->cmplog_g_shm_fd, sizeof(struct cmp_map))) {
PFATAL("setup_shm(): cmplog ftruncate() failed");
}
/* map the shared memory segment to the address space of the process */
shm->cmp_map = mmap(0, map_size, PROT_READ | PROT_WRITE, MAP_SHARED,
shm->cmplog_g_shm_fd, 0);
shm->cmp_map = mmap(0, sizeof(struct cmp_map), PROT_READ | PROT_WRITE,
MAP_SHARED, shm->cmplog_g_shm_fd, 0);
if (shm->cmp_map == MAP_FAILED) {
close(shm->cmplog_g_shm_fd);

View File

@ -178,7 +178,8 @@ fsrv_run_result_t fuzz_run_target(afl_state_t *afl, afl_forkserver_t *fsrv,
void classify_counts(afl_forkserver_t *fsrv) {
u8 *mem = fsrv->trace_bits;
const u8 *map = binary_mode ? count_class_binary : count_class_human;
const u8 *map = (binary_mode || collect_coverage) ? count_class_binary
: count_class_human;
u32 i = map_size;
@ -224,8 +225,13 @@ static void at_exit_handler(void) {
if (remove_shm) {
remove_shm = false;
if (shm.map) afl_shm_deinit(&shm);
if (fsrv->use_shmem_fuzz) deinit_shmem(fsrv, shm_fuzz);
if ((shm_fuzz && shm_fuzz->shmemfuzz_mode) || fsrv->use_shmem_fuzz) {
shm_fuzz = deinit_shmem(fsrv, shm_fuzz);
}
}
@ -240,14 +246,7 @@ static void analyze_results(afl_forkserver_t *fsrv) {
u32 i;
for (i = 0; i < map_size; i++) {
if (fsrv->trace_bits[i]) {
total += fsrv->trace_bits[i];
if (fsrv->trace_bits[i] > highest) highest = fsrv->trace_bits[i];
// if (!coverage_map[i]) { coverage_map[i] = 1; }
coverage_map[i] |= fsrv->trace_bits[i];
}
if (fsrv->trace_bits[i]) { coverage_map[i] |= fsrv->trace_bits[i]; }
}
@ -1339,6 +1338,8 @@ int main(int argc, char **argv_orig, char **envp) {
}
if (collect_coverage) { binary_mode = false; } // ensure this
if (optind == argc || !out_file) { usage(argv[0]); }
if (in_dir && in_filelist) { FATAL("you can only specify either -i or -I"); }
@ -1531,6 +1532,8 @@ int main(int argc, char **argv_orig, char **envp) {
/* initialize cmplog_mode */
shm_fuzz->cmplog_mode = 0;
atexit(at_exit_handler);
u8 *map = afl_shm_init(shm_fuzz, MAX_FILE + sizeof(u32), 1);
shm_fuzz->shmemfuzz_mode = true;
if (!map) { FATAL("BUG: Zero return from afl_shm_init."); }
@ -1677,12 +1680,9 @@ int main(int argc, char **argv_orig, char **envp) {
if ((coverage_map = (u8 *)malloc(map_size + 64)) == NULL)
FATAL("coult not grab memory");
edges_only = false;
raw_instr_output = true;
}
atexit(at_exit_handler);
if (get_afl_env("AFL_DEBUG")) {
int j = optind;
@ -1699,9 +1699,12 @@ int main(int argc, char **argv_orig, char **envp) {
map_size = fsrv->map_size;
if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz)
if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz) {
shm_fuzz = deinit_shmem(fsrv, shm_fuzz);
}
if (in_dir) {
if (execute_testcases(in_dir) == 0) {
@ -1733,9 +1736,12 @@ int main(int argc, char **argv_orig, char **envp) {
} else {
if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz)
if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz) {
shm_fuzz = deinit_shmem(fsrv, shm_fuzz);
}
#ifdef __linux__
if (!fsrv->nyx_mode) {
@ -1782,9 +1788,9 @@ int main(int argc, char **argv_orig, char **envp) {
}
remove_shm = 0;
remove_shm = false;
afl_shm_deinit(&shm);
if (fsrv->use_shmem_fuzz) shm_fuzz = deinit_shmem(fsrv, shm_fuzz);
if (fsrv->use_shmem_fuzz) { shm_fuzz = deinit_shmem(fsrv, shm_fuzz); }
u32 ret;

View File

@ -1 +1 @@
764b66b2
4b4fdab1

View File

@ -136,7 +136,7 @@ def overlap_alignments(segments, memory):
# https://github.com/llvm-mirror/llvm/blob/master/include/llvm/ADT/Triple.h
def get_arch():
arch, arch_vendor, arch_os = lldb.target.GetTriple().split("-")
arch, arch_vendor, arch_os, *arch_remains = lldb.debugger.GetSelectedTarget().GetTriple().split("-")
if arch == "x86_64":
return "x64"
elif arch == "x86" or arch == "i386":
@ -165,7 +165,7 @@ def dump_arch_info():
def dump_regs():
reg_state = {}
for reg_list in lldb.frame.GetRegisters():
for reg_list in lldb.debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame().GetRegisters():
if "general purpose registers" in reg_list.GetName().lower():
for reg in reg_list:
reg_state[reg.GetName()] = int(reg.GetValue(), 16)
@ -180,8 +180,9 @@ def get_section_info(sec):
module_name = sec.addr.module.file.GetFilename()
module_name = module_name if module_name is not None else ""
long_name = module_name + "." + name
load_addr = sec.addr.GetLoadAddress(lldb.debugger.GetSelectedTarget())
return sec.addr.load_addr, (sec.addr.load_addr + sec.size), sec.size, long_name
return load_addr, (load_addr + sec.size), sec.size, long_name
def dump_process_memory(output_dir):
@ -191,7 +192,7 @@ def dump_process_memory(output_dir):
# 1st pass:
# Loop over the segments, fill in the segment info dictionary
for module in lldb.target.module_iter():
for module in lldb.debugger.GetSelectedTarget().module_iter():
for seg_ea in module.section_iter():
seg_info = {"module": module.file.GetFilename()}
(
@ -201,8 +202,8 @@ def dump_process_memory(output_dir):
seg_info["name"],
) = get_section_info(seg_ea)
# TODO: Ugly hack for -1 LONG address on 32-bit
if seg_info["start"] >= sys.maxint or seg_size <= 0:
print "Throwing away page: {}".format(seg_info["name"])
if seg_info["start"] >= sys.maxsize or seg_size <= 0:
print ("Throwing away page: {}".format(seg_info["name"]))
continue
# Page-align segment
@ -212,7 +213,7 @@ def dump_process_memory(output_dir):
raw_segment_list.append(seg_info)
# Add the stack memory region (just hardcode 0x1000 around the current SP)
sp = lldb.frame.GetSP()
sp = lldb.debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame().GetSP()
start_sp = ALIGN_PAGE_DOWN(sp)
raw_segment_list.append(
{"start": start_sp, "end": start_sp + 0x1000, "name": "STACK"}
@ -228,7 +229,7 @@ def dump_process_memory(output_dir):
start_addr = -1
next_region_addr = 0
while next_region_addr > start_addr:
err = lldb.process.GetMemoryRegionInfo(next_region_addr, mem_info)
err = lldb.debugger.GetSelectedTarget().GetProcess().GetMemoryRegionInfo(next_region_addr, mem_info)
# TODO: Should check err.success. If False, what do we do?
if not err.success:
break
@ -267,7 +268,7 @@ def dump_process_memory(output_dir):
region_name = seg_info["name"]
# Compress and dump the content to a file
err = lldb.SBError()
seg_content = lldb.process.ReadMemory(
seg_content = lldb.debugger.GetSelectedTarget().GetProcess().ReadMemory(
start_addr, end_addr - start_addr, err
)
if seg_content == None:
@ -340,11 +341,12 @@ def main():
index_file.close()
print ("Done.")
except Exception, e:
except Exception as e:
print ("!!! ERROR:\n\t{}".format(repr(e)))
if __name__ == "__main__":
lldb.debugger = lldb.SBDebugger.Create()
main()
elif lldb.debugger:
main()

View File

@ -119,7 +119,7 @@ def main():
binary_code = binary_file.read()
binary_file.close()
# Apply constraints to the mutated input
# Assert that the binary size is within limits
if len(binary_code) > CODE_SIZE_MAX:
print("Binary code is too large (> {} bytes)".format(CODE_SIZE_MAX))
return

View File

@ -69,3 +69,21 @@ need to be changed for other OSes.
Current supported OSes are: Linux, Darwin, FreeBSD (thanks to @devnexen)
Also, the following example (generate_libtoken_dict.sh) shows how to use a script to capture tokens from the
files in the target output directory,
and then generate a dictionary file from those tokens.
#### usage:
```bash
./generate_libtoken_dict.sh -p /path/to/libtokencap.so -b /path/to/target/program -o /path/to/target/output -t 5 -- [-program_args]
```
#### description opts:
- ```-o``` : Path to target output directory ;
- ```-b``` : Path to target program binary ;
- ```-p``` : Path to LD_PRELOAD library ;
- ```-t``` : Timeout in seconds ;
- ```-- [-program_args]```: Any additional arguments required by the target binary can be specified after ```--```.
#### output:
A sorted and unique token dictionary file with the extension ``*.dict``
is created in the same directory as the target output containing tokens captured during the execution of the target binary.

View File

@ -0,0 +1,55 @@
#help
usage() {
echo "Usage: $0 -o <target_output> -b <target_bin> -p <LD_PRELOAD_PATH> [-t <timeout_sec>] -- [target_args]"
echo "Options:"
echo " -o Path to target output directory"
echo " -b Path to target program binary"
echo " -p Path to LD_PRELOAD library"
echo " -t Timeout in seconds"
exit 1
}
#parse cli options
while getopts ":o:b:p:t:" opt; do
case $opt in
o) target_output="$OPTARG" ;;
b) target_bin="$OPTARG" ;;
p) LD_PRELOAD_PATH="$OPTARG" ;;
t) timeout_sec="$OPTARG" ;;
\?) echo "Invalid option: -$OPTARG" >&2; usage ;;
:) echo "Option -$OPTARG requires an argument." >&2; usage ;;
esac
done
#shift away the parsed opts
shift $((OPTIND - 1))
#check options
if [ -z "$target_output" ] || [ -z "$target_bin" ] || [ -z "$LD_PRELOAD_PATH" ]; then
echo "Error: Missing mandatory opts" >&2
usage
fi
# initialize vars
AFL_TOKEN_FILE="${PWD}/temp_output.txt"
AFL_DICT_FILE="${PWD}/$(basename "$target_bin")_tokens.dict"
#generate token-file
{
touch "$AFL_TOKEN_FILE"
for i in $(find "$target_output" -type f -name "id*"); do
LD_PRELOAD="$LD_PRELOAD_PATH" \
timeout -s SIGKILL "$timeout_sec" \
"$target_bin" "$@" "$i"
done
} >"$AFL_TOKEN_FILE"
# sort & remove duplicates
sort -u "$AFL_TOKEN_FILE" >"$AFL_DICT_FILE"
# delete temp-file
rm "$AFL_TOKEN_FILE"
# print done-message
echo "Token dictionary created: $AFL_DICT_FILE"
echo "Script completed successfully"