diff --git a/doc/zzuf.1 b/doc/zzuf.1 index 7700c8d..f3bf231 100644 --- a/doc/zzuf.1 +++ b/doc/zzuf.1 @@ -5,6 +5,8 @@ zzuf \- multiple purpose fuzzer \fBzzuf\fR [\fB\-cdiqS\fR] [\fB\-r\fR \fIratio\fR] [\fB\-s\fR \fIseed\fR | \fB\-s\fR \fIstart:stop\fR] .br [\fB\-F\fR \fIchildren\fR] [\fB\-B\fR \fIbytes\fR] [\fB\-T\fR \fIseconds\fR] +.br + [\fB\-P\fR \fIlist\fR] [\fB\-R\fR \fIlist\fR] .br [\fB\-I\fR \fIinclude\fR] [\fB\-E\fR \fIexclude\fR] \fICOMMAND\fR [\fIARGS\fR]... .br @@ -95,6 +97,8 @@ backslash ('\\') .IP You can use '\fB-\fR' to specify ranges. For instance, to protect all bytes from '\fB\\x01\fR' to ' ', use \fB\-P \(dq\\x01- \(dq\fR. + +See also the \fB\-R\fR flag. .TP \fB\-q\fR, \fB\-\-quiet\fR Hide the output of the fuzzed application. This is useful if the application @@ -108,6 +112,13 @@ bits. A value of 1.0 or more will fuzz all the bytes, theoretically making the input files undiscernible from random data. The default fuzzing ratio is 0.004 (fuzz 0.4% of the files' bits). .TP +\fB\-R\fR, \fB\-\-refuse\fR=\fIlist\fR +Refuse a list of characters by not fuzzing bytes that would otherwise be +changed to a character that is in \fIlist\fR. If the original byte is already +in \fIlist\fR, it is left unchanged. + +See the \fB\-P\fR option for a description of \fIlist\fR. +.TP \fB\-s\fR, \fB\-\-seed\fR=\fIseed\fR .PD 0 .TP @@ -160,6 +171,15 @@ Fuzz 1% of the input bits of the \fBcat\fR program using seed 94324: .fi .RE .PP +Fuzz the input of the \fBcat\fR program but do not fuzz the newline character +and prevent non-ASCII characters from appearing in the output: +.PP +.RS +.nf +\fB# zzuf -P \(dq\\n\(dq -R \(dq\\0-\\x1f\\x7f-\\xff\(dq cat /etc/motd\fR +.fi +.RE +.PP Fuzz the input of the \fBconvert\fR program, using file \fBfoo.jpeg\fR as the original input and excluding \fB.xml\fR files from fuzzing (because \fBconvert\fR will also open its own XML configuration files and we do not diff --git a/src/fuzz.c b/src/fuzz.c index 1b2aa3b..53c4140 100644 --- a/src/fuzz.c +++ b/src/fuzz.c @@ -86,10 +86,17 @@ void _zz_fuzz(int fd, uint8_t *buf, uint64_t len) for(j = start; j < stop; j++) { - if(_zz_protect[aligned_buf[j]]) + uint8_t byte = aligned_buf[j]; + + if(_zz_protect[byte]) continue; - aligned_buf[j] ^= fuzz->data[j % CHUNKBYTES]; + byte ^= fuzz->data[j % CHUNKBYTES]; + + if(_zz_refuse[byte]) + continue; + + aligned_buf[j] = byte; } } } diff --git a/src/libzzuf.c b/src/libzzuf.c index 52e2617..2ab094e 100644 --- a/src/libzzuf.c +++ b/src/libzzuf.c @@ -48,13 +48,14 @@ int _zz_signal = 0; /* Global tables */ int _zz_protect[256]; +int _zz_refuse[256]; /* Local variables */ static regex_t * re_include = NULL; static regex_t * re_exclude = NULL; /* Local prototypes */ -static void _zz_protect_init(char const *); +static void _zz_list_init(int *, char const *); static void _zz_fd_init(void); static void _zz_fd_fini(void); @@ -81,7 +82,11 @@ void _zz_init(void) tmp = getenv("ZZUF_PROTECT"); if(tmp && *tmp) - _zz_protect_init(tmp); + _zz_list_init(_zz_protect, tmp); + + tmp = getenv("ZZUF_REFUSE"); + if(tmp && *tmp) + _zz_list_init(_zz_refuse, tmp); tmp = getenv("ZZUF_INCLUDE"); if(tmp && *tmp) @@ -123,13 +128,13 @@ void _zz_fini(void) } /* Byte list stuff */ -static void _zz_protect_init(char const *list) +static void _zz_list_init(int *table, char const *list) { static char const hex[] = "0123456789abcdef0123456789ABCDEF"; char const *tmp; int a, b; - memset(_zz_protect, 0, 256 * sizeof(int)); + memset(table, 0, 256 * sizeof(int)); for(tmp = list, a = b = -1; *tmp; tmp++) { @@ -165,22 +170,22 @@ static void _zz_protect_init(char const *list) if(a != -1 && b == '-' && a <= new) { while(a <= new) - _zz_protect[a++] = 1; + table[a++] = 1; a = b = -1; } else { if(a != -1) - _zz_protect[a] = 1; + table[a] = 1; a = b; b = new; } } if(a != -1) - _zz_protect[a] = 1; + table[a] = 1; if(b != -1) - _zz_protect[b] = 1; + table[b] = 1; } /* File descriptor stuff */ diff --git a/src/libzzuf.h b/src/libzzuf.h index 41737ed..b23d61a 100644 --- a/src/libzzuf.h +++ b/src/libzzuf.h @@ -39,8 +39,9 @@ extern float _zz_ratio; extern int _zz_seed; extern int _zz_signal; -/* Internal tables */ +/* Internal tables TODO: merge them and use bitmasks */ extern int _zz_protect[256]; +extern int _zz_refuse[256]; /* Library initialisation shit */ extern void _zz_init(void) __attribute__((constructor)); diff --git a/src/zzuf.c b/src/zzuf.c index 1e458e3..1a16156 100644 --- a/src/zzuf.c +++ b/src/zzuf.c @@ -113,16 +113,17 @@ int main(int argc, char *argv[]) { "protect", 1, NULL, 'P' }, { "quiet", 0, NULL, 'q' }, { "ratio", 1, NULL, 'r' }, + { "refuse", 1, NULL, 'R' }, { "seed", 1, NULL, 's' }, { "signal", 0, NULL, 'S' }, { "max-time", 1, NULL, 'T' }, { "version", 0, NULL, 'v' }, }; - int c = getopt_long(argc, argv, "B:cdE:F:hiI:P:qr:s:ST:v", + int c = getopt_long(argc, argv, "B:cdE:F:hiI:P:qr:R:s:ST:v", long_options, &option_index); # else # define MOREINFO "Try `%s -h' for more information.\n" - int c = getopt(argc, argv, "B:cdE:F:hiI:P:qr:s:ST:v"); + int c = getopt(argc, argv, "B:cdE:F:hiI:P:qr:R:s:ST:v"); # endif if(c == -1) break; @@ -171,6 +172,9 @@ int main(int argc, char *argv[]) case 'P': /* --protect */ setenv("ZZUF_PROTECT", optarg, 1); break; + case 'R': /* --refuse */ + setenv("ZZUF_REFUSE", optarg, 1); + break; case 'q': /* --quiet */ quiet = 1; break; @@ -545,9 +549,10 @@ static void version(void) #if defined(HAVE_GETOPT_H) static void usage(void) { - printf("Usage: zzuf [ -qdic ] [ -r ratio ] [ -s seed | -s start:stop ]\n"); - printf(" [ -F children ] [ -B bytes ] [ -T seconds ] [ -P protect ]\n"); - printf(" [ -I include ] [ -E exclude ] COMMAND [ARGS]...\n"); + printf("Usage: zzuf [ -cdiqS ] [ -r ratio ] [ -s seed | -s start:stop ]\n"); + printf(" [ -F children ] [ -B bytes ] [ -T seconds ]\n"); + printf(" [ -P protect ] [ -R refuse ]\n"); + printf(" [ -I include ] [ -E exclude ] COMMAND [ARGS]...\n"); printf(" zzuf -h\n"); printf(" zzuf -v\n"); printf("Run COMMAND and randomly fuzz its input.\n"); @@ -564,6 +569,7 @@ static void usage(void) printf(" -P, --protect protect bytes and characters in \n"); printf(" -q, --quiet do not print children's messages\n"); printf(" -r, --ratio bit fuzzing ratio (default 0.004)\n"); + printf(" -R, --refuse refuse bytes and characters in \n"); printf(" -s, --seed random seed (default 0)\n"); printf(" --seed specify a seed range\n"); printf(" -S, --signal prevent children from diverting crashing signals\n"); @@ -581,6 +587,7 @@ static void usage(void) printf(" -P protect bytes and characters in \n"); printf(" -q do not print the fuzzed application's messages\n"); printf(" -r bit fuzzing ratio (default 0.004)\n"); + printf(" -R refuse bytes and characters in \n"); printf(" -s random seed (default 0)\n"); printf(" specify a seed range\n"); printf(" -S prevent children from diverting crashing signals\n");