* Implement -P / --protect.
This commit is contained in:
40
doc/zzuf.1
40
doc/zzuf.1
@@ -55,9 +55,6 @@ of the regular expressions will be ignored.
|
||||
Specify the number of simultaneous children that can be run. This option is
|
||||
only useful if the \fB\-s\fR flag is used with an interval argument.
|
||||
.TP
|
||||
\fB\-h\fR, \fB\-\-help\fR
|
||||
Display a short help message and exit.
|
||||
.TP
|
||||
\fB\-i\fR, \fB\-\-stdin\fR
|
||||
Fuzz the application's standard input. By default \fBzzuf\fR only fuzzes files.
|
||||
.TP
|
||||
@@ -69,6 +66,36 @@ and you only want specific files to be fuzzed.
|
||||
Multiple \fB\-I\fR flags can be specified, in which case files matching any one
|
||||
of the regular expressions will be fuzzed. See also the \fB\-c\fR flag.
|
||||
.TP
|
||||
\fB\-P\fR, \fB\-\-protect\fR=\fIlist\fR
|
||||
Protect a list of characters so that if they appear in input data that would
|
||||
normally be fuzzed, they are left unmodified instead.
|
||||
|
||||
Characters in \fIlist\fR can be expressed verbatim or through escape sequences.
|
||||
The sequences interpreted by \fBzzuf\fR are:
|
||||
.RS
|
||||
.TP
|
||||
\fB\\n\fR
|
||||
new line
|
||||
.TP
|
||||
\fB\\r\fR
|
||||
return
|
||||
.TP
|
||||
\fB\\t\fR
|
||||
tabulation
|
||||
.TP
|
||||
\fB\\0\fR
|
||||
the null character
|
||||
.TP
|
||||
\fB\\x\fR\fINN\fR
|
||||
the byte whose hexadecimal value is \fINN\fR
|
||||
.TP
|
||||
\fB\\\\\fR
|
||||
backslash ('\\')
|
||||
.RE
|
||||
.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.
|
||||
.TP
|
||||
\fB\-q\fR, \fB\-\-quiet\fR
|
||||
Hide the output of the fuzzed application. This is useful if the application
|
||||
is very verbose but only its exit code or signaled status is really useful to
|
||||
@@ -110,6 +137,9 @@ Automatically terminate child processes that run for more than \fIn\fR
|
||||
seconds. This is useful to detect infinite loops or processes stuck in other
|
||||
situations. See also the \fB\-B\fR flag.
|
||||
.TP
|
||||
\fB\-h\fR, \fB\-\-help\fR
|
||||
Display a short help message and exit.
|
||||
.TP
|
||||
\fB\-v\fR, \fB\-\-version\fR
|
||||
Output version information and exit.
|
||||
.SH EXAMPLES
|
||||
@@ -179,6 +209,10 @@ all these complicated operations. They are planned, though.
|
||||
Due to \fBzzuf\fR using \fBLD_PRELOAD\fR to run its child processes, it will
|
||||
fail in the presence of any mechanism that disables preloading. For instance
|
||||
setuid root binaries will not be fuzzed when run as an unprivileged user.
|
||||
.PP
|
||||
As of now, \fBzzuf\fR does not really support multithreaded applications. The
|
||||
behaviour with multithreaded applications where more than one thread do file
|
||||
descriptor operations is undefined.
|
||||
.SH AUTHOR
|
||||
.PP
|
||||
Copyright \(co 2006, 2007 Sam Hocevar <sam@zoy.org>.
|
||||
|
||||
11
src/fuzz.c
11
src/fuzz.c
@@ -42,8 +42,10 @@ void _zz_fuzz(int fd, uint8_t *buf, uint64_t len)
|
||||
unsigned long int pos = _zz_getpos(fd);
|
||||
unsigned int i, j, todo;
|
||||
|
||||
/*
|
||||
debug("fuzz(%i, %lli@%li)", fd, (unsigned long long int)len,
|
||||
(unsigned long int)pos);
|
||||
*/
|
||||
|
||||
fuzz = _zz_getfuzz(fd);
|
||||
aligned_buf = buf - pos;
|
||||
@@ -68,9 +70,9 @@ void _zz_fuzz(int fd, uint8_t *buf, uint64_t len)
|
||||
while(todo--)
|
||||
{
|
||||
unsigned int idx = _zz_rand(CHUNKBYTES);
|
||||
uint8_t byte = (1 << _zz_rand(8));
|
||||
uint8_t bit = (1 << _zz_rand(8));
|
||||
|
||||
fuzz->data[idx] ^= byte;
|
||||
fuzz->data[idx] ^= bit;
|
||||
}
|
||||
|
||||
fuzz->cur = i;
|
||||
@@ -83,7 +85,12 @@ void _zz_fuzz(int fd, uint8_t *buf, uint64_t len)
|
||||
? (i + 1) * CHUNKBYTES : pos + len;
|
||||
|
||||
for(j = start; j < stop; j++)
|
||||
{
|
||||
if(_zz_protect[aligned_buf[j]])
|
||||
continue;
|
||||
|
||||
aligned_buf[j] ^= fuzz->data[j % CHUNKBYTES];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <regex.h>
|
||||
|
||||
@@ -45,11 +46,15 @@ float _zz_ratio = 0.004f;
|
||||
int _zz_seed = 0;
|
||||
int _zz_signal = 0;
|
||||
|
||||
/* Global tables */
|
||||
int _zz_protect[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_fd_init(void);
|
||||
static void _zz_fd_fini(void);
|
||||
|
||||
@@ -74,6 +79,10 @@ void _zz_init(void)
|
||||
else if(_zz_ratio > 5.0f)
|
||||
_zz_ratio = 5.0f;
|
||||
|
||||
tmp = getenv("ZZUF_PROTECT");
|
||||
if(tmp && *tmp)
|
||||
_zz_protect_init(tmp);
|
||||
|
||||
tmp = getenv("ZZUF_INCLUDE");
|
||||
if(tmp && *tmp)
|
||||
{
|
||||
@@ -113,6 +122,67 @@ void _zz_fini(void)
|
||||
_zz_fd_fini();
|
||||
}
|
||||
|
||||
/* Byte list stuff */
|
||||
static void _zz_protect_init(char const *list)
|
||||
{
|
||||
static char const hex[] = "0123456789abcdef0123456789ABCDEF";
|
||||
char const *tmp;
|
||||
int a, b;
|
||||
|
||||
memset(_zz_protect, 0, 256 * sizeof(int));
|
||||
|
||||
for(tmp = list, a = b = -1; *tmp; tmp++)
|
||||
{
|
||||
int new;
|
||||
|
||||
if(*tmp == '\\' && tmp[1] == '\0')
|
||||
new = '\\';
|
||||
else if(*tmp == '\\')
|
||||
{
|
||||
tmp++;
|
||||
if(*tmp == 'n')
|
||||
new = '\n';
|
||||
else if(*tmp == 'r')
|
||||
new = '\r';
|
||||
else if(*tmp == 't')
|
||||
new = '\t';
|
||||
else if(*tmp == '0')
|
||||
new = '\0';
|
||||
else if((*tmp == 'x' || *tmp == 'X')
|
||||
&& tmp[1] && strchr(hex, tmp[1])
|
||||
&& tmp[2] && strchr(hex, tmp[2]))
|
||||
{
|
||||
new = ((strchr(hex, tmp[1]) - hex) & 0xf) << 4;
|
||||
new |= (strchr(hex, tmp[2]) - hex) & 0xf;
|
||||
tmp += 2;
|
||||
}
|
||||
else
|
||||
new = (unsigned char)*tmp; /* XXX: OK for \\, but what else? */
|
||||
}
|
||||
else
|
||||
new = (unsigned char)*tmp;
|
||||
|
||||
if(a != -1 && b == '-' && a <= new)
|
||||
{
|
||||
while(a <= new)
|
||||
_zz_protect[a++] = 1;
|
||||
a = b = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(a != -1)
|
||||
_zz_protect[a] = 1;
|
||||
a = b;
|
||||
b = new;
|
||||
}
|
||||
}
|
||||
|
||||
if(a != -1)
|
||||
_zz_protect[a] = 1;
|
||||
if(b != -1)
|
||||
_zz_protect[b] = 1;
|
||||
}
|
||||
|
||||
/* File descriptor stuff */
|
||||
static struct files
|
||||
{
|
||||
|
||||
@@ -39,6 +39,9 @@ extern float _zz_ratio;
|
||||
extern int _zz_seed;
|
||||
extern int _zz_signal;
|
||||
|
||||
/* Internal tables */
|
||||
extern int _zz_protect[256];
|
||||
|
||||
/* Library initialisation shit */
|
||||
extern void _zz_init(void) __attribute__((constructor));
|
||||
extern void _zz_fini(void) __attribute__((destructor));
|
||||
|
||||
22
src/zzuf.c
22
src/zzuf.c
@@ -110,6 +110,7 @@ int main(int argc, char *argv[])
|
||||
{ "help", 0, NULL, 'h' },
|
||||
{ "stdin", 0, NULL, 'i' },
|
||||
{ "include", 1, NULL, 'I' },
|
||||
{ "protect", 1, NULL, 'P' },
|
||||
{ "quiet", 0, NULL, 'q' },
|
||||
{ "ratio", 1, NULL, 'r' },
|
||||
{ "seed", 1, NULL, 's' },
|
||||
@@ -117,11 +118,11 @@ int main(int argc, char *argv[])
|
||||
{ "max-time", 1, NULL, 'T' },
|
||||
{ "version", 0, NULL, 'v' },
|
||||
};
|
||||
int c = getopt_long(argc, argv, "B:cdE:F:hiI:qr:s:ST:v",
|
||||
int c = getopt_long(argc, argv, "B:cdE:F:hiI:P:qr: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:qr:s:ST:v");
|
||||
int c = getopt(argc, argv, "B:cdE:F:hiI:P:qr:s:ST:v");
|
||||
# endif
|
||||
if(c == -1)
|
||||
break;
|
||||
@@ -167,6 +168,9 @@ int main(int argc, char *argv[])
|
||||
case 'T': /* --max-time */
|
||||
maxtime = atof(optarg);
|
||||
break;
|
||||
case 'P': /* --protect */
|
||||
setenv("ZZUF_PROTECT", optarg, 1);
|
||||
break;
|
||||
case 'q': /* --quiet */
|
||||
quiet = 1;
|
||||
break;
|
||||
@@ -541,9 +545,11 @@ static void version(void)
|
||||
#if defined(HAVE_GETOPT_H)
|
||||
static void usage(void)
|
||||
{
|
||||
printf("Usage: zzuf [ -vqdhic ] [ -r ratio ] [ -s seed | -s start:stop ]\n");
|
||||
printf(" [ -F children ] [ -B bytes ] [ -T seconds ]\n");
|
||||
printf(" [ -I include ] [ -E exclude ] COMMAND [ARGS]...\n");
|
||||
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(" zzuf -h\n");
|
||||
printf(" zzuf -v\n");
|
||||
printf("Run COMMAND and randomly fuzz its input.\n");
|
||||
printf("\n");
|
||||
printf("Mandatory arguments to long options are mandatory for short options too.\n");
|
||||
@@ -553,15 +559,16 @@ static void usage(void)
|
||||
printf(" -d, --debug print debug messages\n");
|
||||
printf(" -E, --exclude <regex> do not fuzz files matching <regex>\n");
|
||||
printf(" -F, --fork <count> number of concurrent children (default 1)\n");
|
||||
printf(" -h, --help display this help and exit\n");
|
||||
printf(" -i, --stdin fuzz standard input\n");
|
||||
printf(" -I, --include <regex> only fuzz files matching <regex>\n");
|
||||
printf(" -P, --protect <list> protect bytes and characters in <list>\n");
|
||||
printf(" -q, --quiet do not print children's messages\n");
|
||||
printf(" -r, --ratio <ratio> bit fuzzing ratio (default 0.004)\n");
|
||||
printf(" -s, --seed <seed> random seed (default 0)\n");
|
||||
printf(" --seed <start:stop> specify a seed range\n");
|
||||
printf(" -S, --signal prevent children from diverting crashing signals\n");
|
||||
printf(" -T, --max-time <n> kill children that run for more than <n> seconds\n");
|
||||
printf(" -h, --help display this help and exit\n");
|
||||
printf(" -v, --version output version information and exit\n");
|
||||
# else
|
||||
printf(" -B <n> kill children that output more than <n> bytes\n");
|
||||
@@ -569,15 +576,16 @@ static void usage(void)
|
||||
printf(" -d print debug messages\n");
|
||||
printf(" -E <regex> do not fuzz files matching <regex>\n");
|
||||
printf(" -F <count> number of concurrent forks (default 1)\n");
|
||||
printf(" -h display this help and exit\n");
|
||||
printf(" -i fuzz standard input\n");
|
||||
printf(" -I <regex> only fuzz files matching <regex>\n");
|
||||
printf(" -P <list> protect bytes and characters in <list>\n");
|
||||
printf(" -q do not print the fuzzed application's messages\n");
|
||||
printf(" -r <ratio> bit fuzzing ratio (default 0.004)\n");
|
||||
printf(" -s <seed> random seed (default 0)\n");
|
||||
printf(" <start:stop> specify a seed range\n");
|
||||
printf(" -S prevent children from diverting crashing signals\n");
|
||||
printf(" -T <n> kill children that run for more than <n> seconds\n");
|
||||
printf(" -h display this help and exit\n");
|
||||
printf(" -v output version information and exit\n");
|
||||
# endif
|
||||
printf("\n");
|
||||
|
||||
Reference in New Issue
Block a user