prepare for strategies

This commit is contained in:
vanhauser-thc
2023-04-04 15:47:53 +02:00
parent 635da39bd1
commit fcd2125678
5 changed files with 1143 additions and 100 deletions

View File

@ -0,0 +1,10 @@
CFLAGS = -O3 -funroll-loops -fPIC -Wl,-Bsymbolic
all: aflpp-mutator.so
aflpp-mutator.so: aflpp.c
$(CC) $(CFLAGS) -I../../include -I. -shared -o aflpp-mutator.so aflpp.c ../../src/afl-performance.c
clean:
rm -f *.o *~ *.so core

View File

@ -0,0 +1,8 @@
# custum mutator: AFL++
this is the AFL++ havoc mutator as a custom mutator module for AFL++.
just type `make` to build
```AFL_CUSTOM_MUTATOR_LIBRARY=custom_mutators/aflpp/aflpp-mutator.so afl-fuzz ...```

View File

@ -0,0 +1,68 @@
#include "afl-mutations.h"
typedef struct my_mutator {
afl_state_t *afl;
u8 *buf;
} my_mutator_t;
my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
(void)seed;
my_mutator_t *data = calloc(1, sizeof(my_mutator_t));
if (!data) {
perror("afl_custom_init alloc");
return NULL;
}
data->buf = malloc(MAX_FILE);
if (!data->buf) {
perror("afl_custom_init alloc");
return NULL;
}
data->afl = afl;
return data;
}
/* here we run the AFL++ mutator, which is the best! */
size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
u8 **out_buf, uint8_t *add_buf, size_t add_buf_size,
size_t max_size) {
u32 havoc_steps = 1 + rand_below(data->afl, 16);
/* set everything up, costly ... :( */
memcpy(data->buf, buf, buf_size);
/* the mutation */
u32 out_buf_len = afl_mutate(data->afl, data->buf, buf_size, havoc_steps,
false, true, add_buf, add_buf_size);
/* return size of mutated data */
*out_buf = data->buf;
return out_buf_len;
}
/**
* Deinitialize everything
*
* @param data The data ptr from afl_custom_init
*/
void afl_custom_deinit(my_mutator_t *data) {
free(data->buf);
free(data);
}

992
include/afl-mutations.h Normal file
View File

@ -0,0 +1,992 @@
/* Implementation of afl havoc mutation to be used in AFL++ custom mutators and
partially in afl-fuzz itself.
How to use:
#include "afl-mutations.h" // needs afl-fuzz.h
u32 afl_mutate(afl_state_t *afl, u8 *buf, u32 len, u32t steps, bool is_text,
bool is_exploration, u8 *splice_buf, u32 splice_len);
Returns:
u32 - the length of the mutated data return in *buf. 0 = error
Parameters:
afl_state_t *afl - the *afl state pointer
u8 *buf - the input buffer to mutate which will be mutated into.
NOTE: must be of MAX_FILE size!
u32 len - the length of the input
u32 steps - how many mutations to perform on the input
bool is_text - is the target expecting text inputs
bool is_exploration - mutate for exploration mode (instead of exploitation)
splice_buf - a buffer from another corpus item to splice with.
If NULL then no splicing
splice_len - the length of the splice buffer. If 0 then no splicing
*/
#ifndef _ANDROID_ASHMEM_H
#define AFL_MUTATIONS_H
#include <stdbool.h>
#include "afl-fuzz.h"
#define MUT_STRATEGY_ARRAY_SIZE 256
enum {
/* 00 */ MUT_FLIPBIT,
/* 01 */ MUT_INTERESTING8,
/* 02 */ MUT_INTERESTING16,
/* 03 */ MUT_INTERESTING16BE,
/* 04 */ MUT_INTERESTING32,
/* 05 */ MUT_INTERESTING32BE,
/* 06 */ MUT_ARITH8_,
/* 07 */ MUT_ARITH8,
/* 08 */ MUT_ARITH16_,
/* 09 */ MUT_ARITH16BE_,
/* 10 */ MUT_ARITH16,
/* 11 */ MUT_ARITH16BE,
/* 12 */ MUT_ARITH32_,
/* 13 */ MUT_ARITH32BE_,
/* 14 */ MUT_ARITH32,
/* 15 */ MUT_ARITH32BE,
/* 16 */ MUT_RAND8,
/* 17 */ MUT_CLONE_OVERWRITE,
/* 18 */ MUT_CLONE_INSERT,
/* 19 */ MUT_OVERWRITE_COPY,
/* 20 */ MUT_OVERWRITE_FIXED,
/* 21 */ MUT_BYTEADD,
/* 22 */ MUT_BYTESUB,
/* 23 */ MUT_FLIP8,
/* 24 */ MUT_SWITCH,
/* 25 */ MUT_DEL,
/* 26 */ MUT_SHUFFLE,
/* 27 */ MUT_DELONE,
/* 28 */ MUT_INSERTONE,
/* 29 */ MUT_ASCIINUM,
/* 30 */ MUT_NEG,
/* 31 */ MUT_INSERTASCIINUM,
/* 32 */ MUT_EXTRA_OVERWRITE,
/* 33 */ MUT_EXTRA_INSERT,
/* 34 */ MUT_AUTO_EXTRA_OVERWRITE,
/* 35 */ MUT_AUTO_EXTRA_INSERT,
/* 36 */ MUT_SPLICE_OVERWRITE,
/* 37 */ MUT_SPLICE_INSERT,
MUT_MAX
};
unsigned int mutation_strategy_exploration_text[MUT_STRATEGY_ARRAY_SIZE] = {};
unsigned int mutation_strategy_exploration_binary[MUT_STRATEGY_ARRAY_SIZE] = {};
unsigned int mutation_strategy_exploitation_text[MUT_STRATEGY_ARRAY_SIZE] = {};
unsigned int mutation_strategy_exploitation_binary[MUT_STRATEGY_ARRAY_SIZE] =
{};
unsigned int afl_mutate(afl_state_t *, unsigned char *, unsigned int,
unsigned int, bool, bool, unsigned char *,
unsigned int);
u32 choose_block_len(afl_state_t *, u32);
/* Helper to choose random block len for block operations in fuzz_one().
Doesn't return zero, provided that max_len is > 0. */
inline u32 choose_block_len(afl_state_t *afl, u32 limit) {
u32 min_value, max_value;
u32 rlim = MIN(afl->queue_cycle, (u32)3);
if (unlikely(!afl->run_over10m)) { rlim = 1; }
switch (rand_below(afl, rlim)) {
case 0:
min_value = 1;
max_value = HAVOC_BLK_SMALL;
break;
case 1:
min_value = HAVOC_BLK_SMALL;
max_value = HAVOC_BLK_MEDIUM;
break;
default:
if (likely(rand_below(afl, 10))) {
min_value = HAVOC_BLK_MEDIUM;
max_value = HAVOC_BLK_LARGE;
} else {
min_value = HAVOC_BLK_LARGE;
max_value = HAVOC_BLK_XL;
}
}
if (min_value >= limit) { min_value = 1; }
return min_value + rand_below(afl, MIN(max_value, limit) - min_value + 1);
}
unsigned int afl_mutate(afl_state_t *afl, unsigned char *buf, unsigned int len,
unsigned int steps, bool is_text, bool is_exploration,
unsigned char *splice_buf, unsigned int splice_len) {
if (!buf || !len) { return 0; }
u32 *mutation_array;
static unsigned char *tmp_buf = NULL;
if (!tmp_buf) {
if ((tmp_buf = malloc(MAX_FILE)) == NULL) { return 0; }
}
if (is_text) {
if (is_exploration) {
mutation_array = (unsigned int *)&mutation_strategy_exploration_text;
} else {
mutation_array = (unsigned int *)&mutation_strategy_exploitation_text;
}
} else {
if (is_exploration) {
mutation_array = (unsigned int *)&mutation_strategy_exploration_binary;
} else {
mutation_array = (unsigned int *)&mutation_strategy_exploitation_binary;
}
}
for (unsigned int step = 0; step < steps; ++step) {
retry_havoc_step:
u32 r = rand_below(afl, MUT_STRATEGY_ARRAY_SIZE), item;
switch (mutation_array[r]) {
case MUT_FLIPBIT: {
/* Flip a single bit somewhere. Spooky! */
u8 bit = rand_below(afl, 8);
u32 off = rand_below(afl, len);
buf[off] ^= 1 << bit;
break;
}
case MUT_INTERESTING8: {
/* Set byte to interesting value. */
item = rand_below(afl, sizeof(interesting_8));
buf[rand_below(afl, len)] = interesting_8[item];
break;
}
case MUT_INTERESTING16: {
/* Set word to interesting value, little endian. */
if (unlikely(len < 2)) { break; } // no retry
item = rand_below(afl, sizeof(interesting_16) >> 1);
*(u16 *)(buf + rand_below(afl, len - 1)) = interesting_16[item];
break;
}
case MUT_INTERESTING16BE: {
/* Set word to interesting value, big endian. */
if (unlikely(len < 2)) { break; } // no retry
item = rand_below(afl, sizeof(interesting_16) >> 1);
*(u16 *)(buf + rand_below(afl, len - 1)) = SWAP16(interesting_16[item]);
break;
}
case MUT_INTERESTING32: {
/* Set dword to interesting value, little endian. */
if (unlikely(len < 4)) { break; } // no retry
item = rand_below(afl, sizeof(interesting_32) >> 2);
*(u32 *)(buf + rand_below(afl, len - 3)) = interesting_32[item];
break;
}
case MUT_INTERESTING32BE: {
/* Set dword to interesting value, big endian. */
if (unlikely(len < 4)) { break; } // no retry
item = rand_below(afl, sizeof(interesting_32) >> 2);
*(u32 *)(buf + rand_below(afl, len - 3)) = SWAP32(interesting_32[item]);
break;
}
case MUT_ARITH8_: {
/* Randomly subtract from byte. */
item = 1 + rand_below(afl, ARITH_MAX);
buf[rand_below(afl, len)] -= item;
break;
}
case MUT_ARITH8: {
/* Randomly add to byte. */
item = 1 + rand_below(afl, ARITH_MAX);
buf[rand_below(afl, len)] += item;
break;
}
case MUT_ARITH16_: {
/* Randomly subtract from word, little endian. */
if (unlikely(len < 2)) { break; } // no retry
u32 pos = rand_below(afl, len - 1);
item = 1 + rand_below(afl, ARITH_MAX);
*(u16 *)(buf + pos) -= item;
break;
}
case MUT_ARITH16BE_: {
/* Randomly subtract from word, big endian. */
if (unlikely(len < 2)) { break; } // no retry
u32 pos = rand_below(afl, len - 1);
u16 num = 1 + rand_below(afl, ARITH_MAX);
*(u16 *)(buf + pos) = SWAP16(SWAP16(*(u16 *)(buf + pos)) - num);
break;
}
case MUT_ARITH16: {
/* Randomly add to word, little endian. */
if (unlikely(len < 2)) { break; } // no retry
u32 pos = rand_below(afl, len - 1);
item = 1 + rand_below(afl, ARITH_MAX);
*(u16 *)(buf + pos) += item;
break;
}
case MUT_ARITH16BE: {
/* Randomly add to word, big endian. */
if (unlikely(len < 2)) { break; } // no retry
u32 pos = rand_below(afl, len - 1);
u16 num = 1 + rand_below(afl, ARITH_MAX);
*(u16 *)(buf + pos) = SWAP16(SWAP16(*(u16 *)(buf + pos)) + num);
break;
}
case MUT_ARITH32_: {
/* Randomly subtract from dword, little endian. */
if (unlikely(len < 4)) { break; } // no retry
u32 pos = rand_below(afl, len - 3);
item = 1 + rand_below(afl, ARITH_MAX);
*(u32 *)(buf + pos) -= item;
break;
}
case MUT_ARITH32BE_: {
/* Randomly subtract from dword, big endian. */
if (unlikely(len < 4)) { break; } // no retry
u32 pos = rand_below(afl, len - 3);
u32 num = 1 + rand_below(afl, ARITH_MAX);
*(u32 *)(buf + pos) = SWAP32(SWAP32(*(u32 *)(buf + pos)) - num);
break;
}
case MUT_ARITH32: {
/* Randomly add to dword, little endian. */
if (unlikely(len < 4)) { break; } // no retry
u32 pos = rand_below(afl, len - 3);
item = 1 + rand_below(afl, ARITH_MAX);
*(u32 *)(buf + pos) += item;
break;
}
case MUT_ARITH32BE: {
/* Randomly add to dword, big endian. */
if (unlikely(len < 4)) { break; } // no retry
u32 pos = rand_below(afl, len - 3);
u32 num = 1 + rand_below(afl, ARITH_MAX);
*(u32 *)(buf + pos) = SWAP32(SWAP32(*(u32 *)(buf + pos)) + num);
break;
}
case MUT_RAND8: {
/* Just set a random byte to a random value. Because,
why not. We use XOR with 1-255 to eliminate the
possibility of a no-op. */
u32 pos = rand_below(afl, len);
item = 1 + rand_below(afl, 255);
buf[pos] ^= item;
break;
}
case MUT_CLONE_OVERWRITE: {
if (likely(len + HAVOC_BLK_XL < MAX_FILE)) {
/* Clone bytes. */
u32 clone_len = choose_block_len(afl, len);
u32 clone_from = rand_below(afl, len - clone_len + 1);
u32 clone_to = rand_below(afl, len);
/* Head */
memcpy(tmp_buf, buf, clone_to);
/* Inserted part */
memcpy(tmp_buf + clone_to, buf + clone_from, clone_len);
/* Tail */
memcpy(tmp_buf + clone_to + clone_len, buf + clone_to,
len - clone_to);
len += clone_len;
memcpy(buf, tmp_buf, len);
} else if (unlikely(len < 8)) {
break;
} else {
goto retry_havoc_step;
}
break;
}
case MUT_CLONE_INSERT: {
if (likely(len + HAVOC_BLK_XL < MAX_FILE)) {
/* Insert a block of constant bytes (25%). */
u32 clone_len = choose_block_len(afl, HAVOC_BLK_XL);
u32 clone_to = rand_below(afl, len);
u32 strat = rand_below(afl, 2);
u32 clone_from = clone_to ? clone_to - 1 : 0;
item = strat ? rand_below(afl, 256) : buf[clone_from];
/* Head */
memcpy(tmp_buf, buf, clone_to);
/* Inserted part */
memset(tmp_buf + clone_to, item, clone_len);
/* Tail */
memcpy(tmp_buf + clone_to + clone_len, buf + clone_to,
len - clone_to);
len += clone_len;
memcpy(buf, tmp_buf, len);
} else if (unlikely(len < 8)) {
break;
} else {
goto retry_havoc_step;
}
break;
}
case MUT_OVERWRITE_COPY: {
/* Overwrite bytes with a randomly selected chunk bytes. */
if (unlikely(len < 2)) { break; } // no retry
u32 copy_len = choose_block_len(afl, len - 1);
u32 copy_from = rand_below(afl, len - copy_len + 1);
u32 copy_to = rand_below(afl, len - copy_len + 1);
if (likely(copy_from != copy_to)) {
memmove(buf + copy_to, buf + copy_from, copy_len);
}
break;
}
case MUT_OVERWRITE_FIXED: {
/* Overwrite bytes with fixed bytes. */
if (unlikely(len < 2)) { break; } // no retry
u32 copy_len = choose_block_len(afl, len - 1);
u32 copy_to = rand_below(afl, len - copy_len + 1);
u32 strat = rand_below(afl, 2);
u32 copy_from = copy_to ? copy_to - 1 : 0;
item = strat ? rand_below(afl, 256) : buf[copy_from];
memset(buf + copy_to, item, copy_len);
break;
}
case MUT_BYTEADD: {
/* Increase byte by 1. */
buf[rand_below(afl, len)]++;
break;
}
case MUT_BYTESUB: {
/* Decrease byte by 1. */
buf[rand_below(afl, len)]--;
break;
}
case MUT_FLIP8: {
/* Flip byte. */
buf[rand_below(afl, len)] ^= 0xff;
break;
}
case MUT_SWITCH: {
if (unlikely(len < 4)) { break; } // no retry
/* Switch bytes. */
u32 to_end, switch_to, switch_len, switch_from;
switch_from = rand_below(afl, len);
do {
switch_to = rand_below(afl, len);
} while (unlikely(switch_from == switch_to));
if (switch_from < switch_to) {
switch_len = switch_to - switch_from;
to_end = len - switch_to;
} else {
switch_len = switch_from - switch_to;
to_end = len - switch_from;
}
switch_len = choose_block_len(afl, MIN(switch_len, to_end));
/* Backup */
memcpy(tmp_buf, buf + switch_from, switch_len);
/* Switch 1 */
memcpy(buf + switch_from, buf + switch_to, switch_len);
/* Switch 2 */
memcpy(buf + switch_to, tmp_buf, switch_len);
break;
}
case MUT_DEL: {
/* Delete bytes. */
if (unlikely(len < 2)) { break; } // no retry
/* Don't delete too much. */
u32 del_len = choose_block_len(afl, len - 1);
u32 del_from = rand_below(afl, len - del_len + 1);
memmove(buf + del_from, buf + del_from + del_len,
len - del_from - del_len);
len -= del_len;
break;
}
case MUT_SHUFFLE: {
/* Shuffle bytes. */
if (unlikely(len < 4)) { break; } // no retry
u32 len = choose_block_len(afl, len - 1);
u32 off = rand_below(afl, len - len + 1);
for (u32 i = len - 1; i > 0; i--) {
u32 j;
do {
j = rand_below(afl, i + 1);
} while (unlikely(i == j));
unsigned char temp = buf[off + i];
buf[off + i] = buf[off + j];
buf[off + j] = temp;
}
break;
}
case MUT_DELONE: {
/* Delete bytes. */
if (unlikely(len < 2)) { break; } // no retry
/* Don't delete too much. */
u32 del_len = 1;
u32 del_from = rand_below(afl, len - del_len + 1);
memmove(buf + del_from, buf + del_from + del_len,
len - del_from - del_len);
len -= del_len;
break;
}
case MUT_INSERTONE: {
if (unlikely(len < 2)) { break; } // no retry
u32 clone_len = 1;
u32 clone_to = rand_below(afl, len);
u32 strat = rand_below(afl, 2);
u32 clone_from = clone_to ? clone_to - 1 : 0;
item = strat ? rand_below(afl, 256) : buf[clone_from];
/* Head */
memcpy(tmp_buf, buf, clone_to);
/* Inserted part */
memset(tmp_buf + clone_to, item, clone_len);
/* Tail */
memcpy(tmp_buf + clone_to + clone_len, buf + clone_to, len - clone_to);
len += clone_len;
memcpy(buf, tmp_buf, len);
break;
}
case MUT_ASCIINUM: {
if (unlikely(len < 4)) { break; } // no retry
u32 off = rand_below(afl, len), off2 = off, cnt = 0;
while (off2 + cnt < len && !isdigit(buf[off2 + cnt])) {
++cnt;
}
// none found, wrap
if (off2 + cnt == len) {
off2 = 0;
cnt = 0;
while (cnt < off && !isdigit(buf[off2 + cnt])) {
++cnt;
}
if (cnt == off) {
if (len < 8) {
break;
} else {
goto retry_havoc_step;
}
}
}
off = off2 + cnt;
off2 = off + 1;
while (off2 < len && isdigit(buf[off2])) {
++off2;
}
s64 val = buf[off] - '0';
for (u32 i = off + 1; i < off2; ++i) {
val = (val * 10) + buf[i] - '0';
}
if (off && buf[off - 1] == '-') { val = -val; }
u32 strat = rand_below(afl, 8);
switch (strat) {
case 0:
val++;
break;
case 1:
val--;
break;
case 2:
val *= 2;
break;
case 3:
val /= 2;
break;
case 4:
if (likely(val && (u64)val < 0x19999999)) {
val = (u64)rand_next(afl) % (u64)((u64)val * 10);
} else {
val = rand_below(afl, 256);
}
break;
case 5:
val += rand_below(afl, 256);
break;
case 6:
val -= rand_below(afl, 256);
break;
case 7:
val = ~(val);
break;
}
char buf[20];
snprintf(buf, sizeof(buf), "%ld", val);
u32 old_len = off2 - off;
u32 new_len = strlen(buf);
if (old_len == new_len) {
memcpy(buf + off, buf, new_len);
} else {
/* Head */
memcpy(tmp_buf, buf, off);
/* Inserted part */
memcpy(tmp_buf + off, buf, new_len);
/* Tail */
memcpy(tmp_buf + off + new_len, buf + off2, len - off2);
len += (new_len - old_len);
memcpy(buf, tmp_buf, len);
}
// fprintf(stderr, "AFTER : %s\n", buf);
break;
}
case MUT_NEG: {
/* Neg byte. */
item = rand_below(afl, len);
buf[item] = ~buf[item];
break;
}
case MUT_INSERTASCIINUM: {
u32 len = 1 + rand_below(afl, 8);
u32 pos = rand_below(afl, len);
/* Insert ascii number. */
if (unlikely(len < pos + len)) {
if (unlikely(len < 8)) {
break;
} else {
goto retry_havoc_step;
}
}
u64 val = rand_next(afl);
char buf[20];
snprintf(buf, sizeof(buf), "%llu", val);
memcpy(buf + pos, buf, len);
break;
}
case MUT_EXTRA_OVERWRITE: {
if (unlikely(!afl->extras_cnt)) { goto retry_havoc_step; }
/* Use the dictionary. */
u32 use_extra = rand_below(afl, afl->extras_cnt);
u32 extra_len = afl->extras[use_extra].len;
if (unlikely(extra_len > len)) { goto retry_havoc_step; }
u32 insert_at = rand_below(afl, len - extra_len + 1);
memcpy(buf + insert_at, afl->extras[use_extra].data, extra_len);
break;
}
case MUT_EXTRA_INSERT: {
if (unlikely(!afl->extras_cnt)) { goto retry_havoc_step; }
u32 use_extra = rand_below(afl, afl->extras_cnt);
u32 extra_len = afl->extras[use_extra].len;
if (unlikely(len + extra_len >= MAX_FILE)) { goto retry_havoc_step; }
u8 *ptr = afl->extras[use_extra].data;
u32 insert_at = rand_below(afl, len + 1);
/* Tail */
memmove(buf + insert_at + extra_len, buf + insert_at, len - insert_at);
/* Inserted part */
memcpy(buf + insert_at, ptr, extra_len);
len += extra_len;
break;
}
case MUT_AUTO_EXTRA_OVERWRITE: {
if (unlikely(!afl->a_extras_cnt)) { goto retry_havoc_step; }
/* Use the dictionary. */
u32 use_extra = rand_below(afl, afl->a_extras_cnt);
u32 extra_len = afl->a_extras[use_extra].len;
if (unlikely(extra_len > len)) { goto retry_havoc_step; }
u32 insert_at = rand_below(afl, len - extra_len + 1);
memcpy(buf + insert_at, afl->a_extras[use_extra].data, extra_len);
break;
}
case MUT_AUTO_EXTRA_INSERT: {
if (unlikely(!afl->a_extras_cnt)) { goto retry_havoc_step; }
u32 use_extra = rand_below(afl, afl->a_extras_cnt);
u32 extra_len = afl->a_extras[use_extra].len;
if (unlikely(len + extra_len >= MAX_FILE)) { goto retry_havoc_step; }
u8 *ptr = afl->a_extras[use_extra].data;
u32 insert_at = rand_below(afl, len + 1);
/* Tail */
memmove(buf + insert_at + extra_len, buf + insert_at, len - insert_at);
/* Inserted part */
memcpy(buf + insert_at, ptr, extra_len);
len += extra_len;
break;
}
case MUT_SPLICE_OVERWRITE: {
if (unlikely(!splice_buf || !splice_len)) { goto retry_havoc_step; }
/* overwrite mode */
u32 copy_from, copy_to, copy_len;
copy_len = choose_block_len(afl, splice_len - 1);
if (copy_len > len) copy_len = len;
copy_from = rand_below(afl, splice_len - copy_len + 1);
copy_to = rand_below(afl, len - copy_len + 1);
memmove(buf + copy_to, splice_buf + copy_from, copy_len);
break;
}
case MUT_SPLICE_INSERT: {
if (unlikely(!splice_buf || !splice_len)) { goto retry_havoc_step; }
if (unlikely(len + HAVOC_BLK_XL >= MAX_FILE)) { goto retry_havoc_step; }
/* insert mode */
u32 clone_from, clone_to, clone_len;
clone_len = choose_block_len(afl, splice_len);
clone_from = rand_below(afl, splice_len - clone_len + 1);
clone_to = rand_below(afl, len + 1);
/* Head */
memcpy(tmp_buf, buf, clone_to);
/* Inserted part */
memcpy(tmp_buf + clone_to, splice_buf + clone_from, clone_len);
/* Tail */
memcpy(tmp_buf + clone_to + clone_len, buf + clone_to, len - clone_to);
len += clone_len;
memcpy(buf, tmp_buf, len);
break;
}
}
}
return len;
}
#endif /* !AFL_MUTATIONS_H */

View File

@ -27,21 +27,7 @@
#include <string.h> #include <string.h>
#include <limits.h> #include <limits.h>
#include "cmplog.h" #include "cmplog.h"
#include "afl-mutations.h"
static u32 mutation_array_explore[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37};
// static u32 mutation_array_exploit[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
// 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
// 31 }; static u32 mutation_array_txt_explore[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8,
// 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
// 28, 29, 30, 31 }; static u32 mutation_array_txt_exploit[] = { 0, 1, 2, 3, 4,
// 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
// 25, 26, 27, 28, 29, 30, 31 };
// what about more splicing?
// what about -x and cmplog learn?
/* MOpt */ /* MOpt */
@ -85,50 +71,6 @@ static int select_algorithm(afl_state_t *afl, u32 max_algorithm) {
} }
/* Helper to choose random block len for block operations in fuzz_one().
Doesn't return zero, provided that max_len is > 0. */
static inline u32 choose_block_len(afl_state_t *afl, u32 limit) {
u32 min_value, max_value;
u32 rlim = MIN(afl->queue_cycle, (u32)3);
if (unlikely(!afl->run_over10m)) { rlim = 1; }
switch (rand_below(afl, rlim)) {
case 0:
min_value = 1;
max_value = HAVOC_BLK_SMALL;
break;
case 1:
min_value = HAVOC_BLK_SMALL;
max_value = HAVOC_BLK_MEDIUM;
break;
default:
if (likely(rand_below(afl, 10))) {
min_value = HAVOC_BLK_MEDIUM;
max_value = HAVOC_BLK_LARGE;
} else {
min_value = HAVOC_BLK_LARGE;
max_value = HAVOC_BLK_XL;
}
}
if (min_value >= limit) { min_value = 1; }
return min_value + rand_below(afl, MIN(max_value, limit) - min_value + 1);
}
/* Helper function to see if a particular change (xor_val = old ^ new) could /* Helper function to see if a particular change (xor_val = old ^ new) could
be a product of deterministic bit flips with the lengths and stepovers be a product of deterministic bit flips with the lengths and stepovers
attempted by afl-fuzz. This is used to avoid dupes in some of the attempted by afl-fuzz. This is used to avoid dupes in some of the
@ -2136,8 +2078,31 @@ havoc_stage:
u32 *mutation_array; u32 *mutation_array;
u32 stack_max; u32 stack_max;
// if ( ... ) if (afl->queue_cur->is_ascii) { // is text?
mutation_array = (u32 *)&mutation_array_explore;
if (1) { // is exploration?
mutation_array = (unsigned int *)&mutation_strategy_exploration_text;
} else { // is exploitation!
mutation_array = (unsigned int *)&mutation_strategy_exploitation_text;
}
} else { // is binary!
if (1) { // is exploration?
mutation_array = (unsigned int *)&mutation_strategy_exploration_binary;
} else { // is exploitation!
mutation_array = (unsigned int *)&mutation_strategy_exploitation_binary;
}
}
if (temp_len < 64) { if (temp_len < 64) {
@ -2208,11 +2173,11 @@ havoc_stage:
} }
retry_havoc_step: retry_havoc_step:
u32 r = rand_below(afl, 256), item; u32 r = rand_below(afl, MUT_STRATEGY_ARRAY_SIZE), item;
switch (mutation_array[r]) { switch (mutation_array[r]) {
case 0: { case MUT_FLIPBIT: {
/* Flip a single bit somewhere. Spooky! */ /* Flip a single bit somewhere. Spooky! */
u8 bit = rand_below(afl, 8); u8 bit = rand_below(afl, 8);
@ -2227,7 +2192,7 @@ havoc_stage:
} }
case 1: { case MUT_INTERESTING8: {
/* Set byte to interesting value. */ /* Set byte to interesting value. */
@ -2241,7 +2206,7 @@ havoc_stage:
} }
case 2: { case MUT_INTERESTING16: {
/* Set word to interesting value, little endian. */ /* Set word to interesting value, little endian. */
@ -2260,7 +2225,7 @@ havoc_stage:
} }
case 3: { case MUT_INTERESTING16BE: {
/* Set word to interesting value, big endian. */ /* Set word to interesting value, big endian. */
@ -2278,7 +2243,7 @@ havoc_stage:
} }
case 4: { case MUT_INTERESTING32: {
/* Set dword to interesting value, little endian. */ /* Set dword to interesting value, little endian. */
@ -2297,7 +2262,7 @@ havoc_stage:
} }
case 5: { case MUT_INTERESTING32BE: {
/* Set dword to interesting value, big endian. */ /* Set dword to interesting value, big endian. */
@ -2315,7 +2280,7 @@ havoc_stage:
} }
case 6: { case MUT_ARITH8_: {
/* Randomly subtract from byte. */ /* Randomly subtract from byte. */
@ -2329,7 +2294,7 @@ havoc_stage:
} }
case 7: { case MUT_ARITH8: {
/* Randomly add to byte. */ /* Randomly add to byte. */
@ -2343,7 +2308,7 @@ havoc_stage:
} }
case 8: { case MUT_ARITH16_: {
/* Randomly subtract from word, little endian. */ /* Randomly subtract from word, little endian. */
@ -2362,7 +2327,7 @@ havoc_stage:
} }
case 9: { case MUT_ARITH16BE_: {
/* Randomly subtract from word, big endian. */ /* Randomly subtract from word, big endian. */
@ -2382,7 +2347,7 @@ havoc_stage:
} }
case 10: { case MUT_ARITH16: {
/* Randomly add to word, little endian. */ /* Randomly add to word, little endian. */
@ -2401,7 +2366,7 @@ havoc_stage:
} }
case 11: { case MUT_ARITH16BE: {
/* Randomly add to word, big endian. */ /* Randomly add to word, big endian. */
@ -2421,7 +2386,7 @@ havoc_stage:
} }
case 12: { case MUT_ARITH32_: {
/* Randomly subtract from dword, little endian. */ /* Randomly subtract from dword, little endian. */
@ -2440,7 +2405,7 @@ havoc_stage:
} }
case 13: { case MUT_ARITH32BE_: {
/* Randomly subtract from dword, big endian. */ /* Randomly subtract from dword, big endian. */
@ -2460,7 +2425,7 @@ havoc_stage:
} }
case 14: { case MUT_ARITH32: {
/* Randomly add to dword, little endian. */ /* Randomly add to dword, little endian. */
@ -2479,7 +2444,7 @@ havoc_stage:
} }
case 15: { case MUT_ARITH32BE: {
/* Randomly add to dword, big endian. */ /* Randomly add to dword, big endian. */
@ -2499,7 +2464,7 @@ havoc_stage:
} }
case 16: { case MUT_RAND8: {
/* Just set a random byte to a random value. Because, /* Just set a random byte to a random value. Because,
why not. We use XOR with 1-255 to eliminate the why not. We use XOR with 1-255 to eliminate the
@ -2517,7 +2482,7 @@ havoc_stage:
} }
case 17: { case MUT_CLONE_OVERWRITE: {
if (likely(temp_len + HAVOC_BLK_XL < MAX_FILE)) { if (likely(temp_len + HAVOC_BLK_XL < MAX_FILE)) {
@ -2566,7 +2531,7 @@ havoc_stage:
} }
case 18: { case MUT_CLONE_INSERT: {
if (likely(temp_len + HAVOC_BLK_XL < MAX_FILE)) { if (likely(temp_len + HAVOC_BLK_XL < MAX_FILE)) {
@ -2617,7 +2582,7 @@ havoc_stage:
} }
case 19: { case MUT_OVERWRITE_COPY: {
/* Overwrite bytes with a randomly selected chunk bytes. */ /* Overwrite bytes with a randomly selected chunk bytes. */
@ -2642,7 +2607,7 @@ havoc_stage:
} }
case 20: { case MUT_OVERWRITE_FIXED: {
/* Overwrite bytes with fixed bytes. */ /* Overwrite bytes with fixed bytes. */
@ -2666,7 +2631,7 @@ havoc_stage:
} }
case 21: { case MUT_BYTEADD: {
/* Increase byte by 1. */ /* Increase byte by 1. */
@ -2679,7 +2644,7 @@ havoc_stage:
} }
case 22: { case MUT_BYTESUB: {
/* Decrease byte by 1. */ /* Decrease byte by 1. */
@ -2692,7 +2657,7 @@ havoc_stage:
} }
case 23: { case MUT_FLIP8: {
/* Flip byte. */ /* Flip byte. */
@ -2705,7 +2670,7 @@ havoc_stage:
} }
case 24: { case MUT_SWITCH: {
if (unlikely(temp_len < 4)) { break; } // no retry if (unlikely(temp_len < 4)) { break; } // no retry
@ -2757,7 +2722,7 @@ havoc_stage:
} }
case 25: { case MUT_DEL: {
/* Delete bytes. */ /* Delete bytes. */
@ -2782,7 +2747,7 @@ havoc_stage:
} }
case 26: { case MUT_SHUFFLE: {
/* Shuffle bytes. */ /* Shuffle bytes. */
@ -2815,7 +2780,7 @@ havoc_stage:
} }
case 27: { case MUT_DELONE: {
/* Delete bytes. */ /* Delete bytes. */
@ -2839,7 +2804,7 @@ havoc_stage:
} }
case 28: { case MUT_INSERTONE: {
if (unlikely(temp_len < 2)) { break; } // no retry if (unlikely(temp_len < 2)) { break; } // no retry
@ -2878,7 +2843,7 @@ havoc_stage:
} }
case 29: { case MUT_ASCIINUM: {
if (unlikely(temp_len < 4)) { break; } // no retry if (unlikely(temp_len < 4)) { break; } // no retry
@ -3022,7 +2987,7 @@ havoc_stage:
} }
case 30: { case MUT_NEG: {
/* Neg byte. */ /* Neg byte. */
@ -3037,7 +3002,7 @@ havoc_stage:
} }
case 31: { case MUT_INSERTASCIINUM: {
u32 len = 1 + rand_below(afl, 8); u32 len = 1 + rand_below(afl, 8);
u32 pos = rand_below(afl, temp_len); u32 pos = rand_below(afl, temp_len);
@ -3069,7 +3034,7 @@ havoc_stage:
} }
case 32: { case MUT_EXTRA_OVERWRITE: {
if (unlikely(!afl->extras_cnt)) { goto retry_havoc_step; } if (unlikely(!afl->extras_cnt)) { goto retry_havoc_step; }
@ -3092,7 +3057,7 @@ havoc_stage:
} }
case 33: { case MUT_EXTRA_INSERT: {
if (unlikely(!afl->extras_cnt)) { goto retry_havoc_step; } if (unlikely(!afl->extras_cnt)) { goto retry_havoc_step; }
@ -3127,7 +3092,7 @@ havoc_stage:
} }
case 34: { case MUT_AUTO_EXTRA_OVERWRITE: {
if (unlikely(!afl->a_extras_cnt)) { goto retry_havoc_step; } if (unlikely(!afl->a_extras_cnt)) { goto retry_havoc_step; }
@ -3150,7 +3115,7 @@ havoc_stage:
} }
case 35: { case MUT_AUTO_EXTRA_INSERT: {
if (unlikely(!afl->a_extras_cnt)) { goto retry_havoc_step; } if (unlikely(!afl->a_extras_cnt)) { goto retry_havoc_step; }
@ -3185,7 +3150,7 @@ havoc_stage:
} }
case 36: { case MUT_SPLICE_OVERWRITE: {
if (unlikely(afl->ready_for_splicing_count <= 1)) { if (unlikely(afl->ready_for_splicing_count <= 1)) {
@ -3231,7 +3196,7 @@ havoc_stage:
} }
case 37: { case MUT_SPLICE_INSERT: {
if (unlikely(afl->ready_for_splicing_count <= 1)) { if (unlikely(afl->ready_for_splicing_count <= 1)) {