* Implement -P / --protect.

This commit is contained in:
Sam Hocevar
2007-01-04 01:09:04 +00:00
committed by sam
parent 39a8524c0e
commit ab9a1d771c
5 changed files with 134 additions and 12 deletions

View File

@@ -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>.

View File

@@ -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];
}
}
}

View File

@@ -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
{

View File

@@ -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));

View File

@@ -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");