improve aflpp-standalone

This commit is contained in:
vanhauser-thc 2024-08-28 13:17:43 +02:00
parent 088dd6476c
commit 72a24e6439
4 changed files with 131 additions and 41 deletions

View File

@ -4,7 +4,7 @@ CFLAGS = -O3 -funroll-loops -fPIC
all: aflpp-standalone all: aflpp-standalone
aflpp-standalone: aflpp-standalone.c aflpp-standalone: aflpp-standalone.c
$(CC) $(CFLAGS) -I../../../include -I. -o aflpp-standalone aflpp-standalone.c ../../../src/afl-performance.c $(CC) $(CFLAGS) -DBIN_PATH=\"foo\" -I../../../include -I. -o aflpp-standalone aflpp-standalone.c ../../../src/afl-performance.c ../../../src/afl-fuzz-extras.c ../../../src/afl-common.c
clean: clean:
rm -f *.o *~ aflpp-standalone core rm -f *.o *~ aflpp-standalone core

View File

@ -5,6 +5,6 @@ this is the AFL++ havoc mutator as a standalone mutator
just type `make` to build. just type `make` to build.
``` ```
aflpp-standalone inputfile outputfile [splicefile] aflpp-standalone -h # to see all parameteres
cat file | aflpp-standalone -m 4 -x foo.dict - outputfile splicefile # example
``` ```

View File

@ -1,6 +1,12 @@
#include "afl-fuzz.h" #include "afl-fuzz.h"
#include "afl-mutations.h" #include "afl-mutations.h"
#include <unistd.h>
#include <getopt.h>
static int max_havoc = 16, verbose;
static unsigned char *dict;
typedef struct my_mutator { typedef struct my_mutator {
afl_state_t *afl; afl_state_t *afl;
@ -21,14 +27,14 @@ my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
} }
if ((data->buf = malloc(1024*1024)) == NULL) { if ((data->buf = malloc(1024 * 1024)) == NULL) {
perror("afl_custom_init alloc"); perror("afl_custom_init alloc");
return NULL; return NULL;
} else { } else {
data->buf_size = 1024*1024; data->buf_size = 1024 * 1024;
} }
@ -36,9 +42,23 @@ my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
data->afl = calloc(1, sizeof(afl_state_t)); data->afl = calloc(1, sizeof(afl_state_t));
data->afl->queue_cycle = 1; data->afl->queue_cycle = 1;
data->afl->fsrv.dev_urandom_fd = open("/dev/urandom", O_RDONLY); data->afl->fsrv.dev_urandom_fd = open("/dev/urandom", O_RDONLY);
if (data->afl->fsrv.dev_urandom_fd < 0) { PFATAL("Unable to open /dev/urandom"); } if (data->afl->fsrv.dev_urandom_fd < 0) {
PFATAL("Unable to open /dev/urandom");
}
rand_set_seed(data->afl, getpid()); rand_set_seed(data->afl, getpid());
if (dict) {
load_extras(data->afl, dict);
if (verbose)
fprintf(stderr, "Loaded dictionary: %s (%u entries)\n", dict,
data->afl->extras_cnt);
}
return data; return data;
} }
@ -66,14 +86,20 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
} }
u32 havoc_steps = 1 + rand_below(data->afl, 16); u32 havoc_steps = 1 + rand_below(data->afl, max_havoc);
if (verbose) fprintf(stderr, "Havoc steps: %u\n", havoc_steps);
/* set everything up, costly ... :( */ /* set everything up, costly ... :( */
memcpy(data->buf, buf, buf_size); memcpy(data->buf, buf, buf_size);
/* the mutation */ /* the mutation */
u32 out_buf_len = afl_mutate(data->afl, data->buf, buf_size, havoc_steps, u32 out_buf_len;
false, true, add_buf, add_buf_size, max_size); do {
out_buf_len = afl_mutate(data->afl, data->buf, buf_size, havoc_steps, false,
true, add_buf, add_buf_size, max_size);
} while (out_buf_len == buf_size && memcmp(buf, data->buf, buf_size) == 0);
/* return size of mutated data */ /* return size of mutated data */
*out_buf = data->buf; *out_buf = data->buf;
@ -84,80 +110,143 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
if (argc > 1 && strncmp(argv[1], "-h", 2) == 0) { if (argc > 1 && strncmp(argv[1], "-h", 2) == 0) {
printf("Syntax: %s [-v] [inputfile [outputfile [splicefile]]]\n\n", argv[0]);
printf("Reads a testcase from stdin when no input file (or '-') is specified,\n"); printf(
printf("mutates according to AFL++'s mutation engine, and write to stdout when '-' or\n"); "Syntax: %s [-v] [-m maxmutations] [-x dict] [inputfile [outputfile "
printf("no output filename is given. As an optional third parameter you can give a file\n"); "[splicefile]]]\n\n",
argv[0]);
printf(
"Reads a testcase from stdin when no input file (or '-') is "
"specified,\n");
printf(
"mutates according to AFL++'s mutation engine, and write to stdout "
"when '-' or\n");
printf(
"no output filename is given. As an optional third parameter you can "
"give a file\n");
printf("for splicing. Maximum input and output length is 1MB.\n"); printf("for splicing. Maximum input and output length is 1MB.\n");
printf("The -v verbose option prints debug output to stderr.\n"); printf("Options:\n");
printf(" -v verbose debug output to stderr.\n");
printf(" -m val max mutations (1-val, val default is 16)\n");
printf(" -x file dictionary file (AFL++ format)\n");
return 0; return 0;
} }
FILE *in = stdin, *out = stdout, *splice = NULL; FILE *in = stdin, *out = stdout, *splice = NULL;
unsigned char *inbuf = malloc(1024 * 1024), *outbuf, *splicebuf = NULL; unsigned char *inbuf = malloc(1024 * 1024), *outbuf = NULL, *splicebuf = NULL;
int verbose = 0, splicelen = 0; int splicelen = 0, opt;
while ((opt = getopt(argc, argv, "vm:x:")) > 0) {
switch (opt) {
case 'm':
max_havoc = atoi(optarg);
break;
case 'v':
verbose = 1;
break;
case 'x':
dict = optarg;
break;
default:
fprintf(stderr, "Error: unknown parameter -%c\n", opt);
exit(-1);
}
}
if (max_havoc < 1) {
fprintf(stderr, "Error: illegal -m value\n");
exit(-1);
if (argc > 1 && strcmp(argv[1], "-v") == 0) {
verbose = 1;
argc--;
argv++;
fprintf(stderr, "Verbose active\n");
} }
my_mutator_t *data = afl_custom_init(NULL, 0); my_mutator_t *data = afl_custom_init(NULL, 0);
if (argc > 1 && strcmp(argv[1], "-") != 0) { if (argc > optind && strcmp(argv[optind], "-") != 0) {
if ((in = fopen(argv[1], "r")) == NULL) {
if ((in = fopen(argv[optind], "r")) == NULL) {
perror(argv[1]); perror(argv[1]);
return -1; return -1;
} }
if (verbose) fprintf(stderr, "Input: %s\n", argv[1]);
if (verbose) fprintf(stderr, "Input: %s\n", argv[optind]);
} }
size_t inlen = fread(inbuf, 1, 1024*1024, in); size_t inlen = fread(inbuf, 1, 1024 * 1024, in);
if (!inlen) { if (!inlen) {
fprintf(stderr, "Error: empty file %s\n", argv[1] ? argv[1] : "stdin");
fprintf(stderr, "Error: empty file %s\n",
argv[optind] ? argv[optind] : "stdin");
return -1; return -1;
} }
if (argc > 2 && strcmp(argv[2], "-") != 0) { if (argc > optind + 1 && strcmp(argv[optind + 1], "-") != 0) {
if ((out = fopen(argv[2], "w")) == NULL) {
perror(argv[2]); if ((out = fopen(argv[optind + 1], "w")) == NULL) {
perror(argv[optind + 1]);
return -1; return -1;
} }
if (verbose) fprintf(stderr, "Output: %s\n", argv[2]);
if (verbose) fprintf(stderr, "Output: %s\n", argv[optind + 1]);
} }
if (argc > 3) { if (argc > optind + 2) {
if ((splice = fopen(argv[3], "r")) == NULL) {
perror(argv[3]); if ((splice = fopen(argv[optind + 2], "r")) == NULL) {
perror(argv[optind + 2]);
return -1; return -1;
} }
if (verbose) fprintf(stderr, "Splice: %s\n", argv[3]);
splicebuf = malloc(1024*1024); if (verbose) fprintf(stderr, "Splice: %s\n", argv[optind + 2]);
size_t splicelen = fread(splicebuf, 1, 1024*1024, splice); splicebuf = malloc(1024 * 1024);
size_t splicelen = fread(splicebuf, 1, 1024 * 1024, splice);
if (!splicelen) { if (!splicelen) {
fprintf(stderr, "Error: empty file %s\n", argv[3]);
fprintf(stderr, "Error: empty file %s\n", argv[optind + 2]);
return -1; return -1;
} }
if (verbose) fprintf(stderr, "Mutation splice length: %zu\n", splicelen); if (verbose) fprintf(stderr, "Mutation splice length: %zu\n", splicelen);
} }
if (verbose) fprintf(stderr, "Mutation input length: %zu\n", inlen); if (verbose) fprintf(stderr, "Mutation input length: %zu\n", inlen);
unsigned int outlen = afl_custom_fuzz(data, inbuf, inlen, &outbuf, splicebuf, splicelen, 1024*1024); unsigned int outlen = afl_custom_fuzz(data, inbuf, inlen, &outbuf, splicebuf,
splicelen, 1024 * 1024);
if (outlen == 0 || !outbuf) { if (outlen == 0 || !outbuf) {
fprintf(stderr, "Error: no mutation data returned.\n"); fprintf(stderr, "Error: no mutation data returned.\n");
return -1; return -1;
} }
if (verbose) fprintf(stderr, "Mutation output length: %u\n", outlen); if (verbose) fprintf(stderr, "Mutation output length: %u\n", outlen);
if (fwrite(outbuf, 1, outlen, out) != outlen) { if (fwrite(outbuf, 1, outlen, out) != outlen) {
fprintf(stderr, "Warning: incomplete write.\n"); fprintf(stderr, "Warning: incomplete write.\n");
return -1; return -1;
} }
return 0; return 0;
} }

View File

@ -32,6 +32,7 @@
AFL type forkserver. Useful for symcc/symqemu/nautilus/etc. with AFL type forkserver. Useful for symcc/symqemu/nautilus/etc. with
AFL_LLVM_INSTRUMENT=CLASSIC AFL_LLVM_INSTRUMENT=CLASSIC
- code formatting updated to llvm 18 - code formatting updated to llvm 18
- improve /custom_mutators/aflpp/standalone/aflpp-standalone
### Version ++4.21c (release) ### Version ++4.21c (release)