* Implemented -M/--md5 flag.

This commit is contained in:
Sam Hocevar
2007-01-08 17:50:34 +00:00
committed by sam
parent 9966eafc15
commit 5ba521a706
5 changed files with 341 additions and 31 deletions
+8 -4
View File
@@ -2,13 +2,13 @@
.SH NAME
zzuf \- multiple purpose fuzzer
.SH SYNOPSIS
\fBzzuf\fR [\fB\-cdinqS\fR] [\fB\-r\fR \fIratio\fR] [\fB\-s\fR \fIseed\fR | \fB\-s\fR \fIstart:stop\fR]
\fBzzuf\fR [\fB\-cdiMnqS\fR] [\fB\-r\fR \fIratio\fR] [\fB\-s\fR \fIseed\fR | \fB\-s\fR \fIstart:stop\fR]
.br
[\fB\-F\fR \fIforks\fR] [\fB\-C\fR \fIcrashes\fR] [\fB\-B\fR \fIbytes\fR] [\fB\-T\fR \fIseconds\fR]
[\fB\-F\fR \fIforks\fR] [\fB\-C\fR \fIcrashes\fR] [\fB\-B\fR \fIbytes\fR] [\fB\-T\fR \fIseconds\fR]
.br
[\fB\-P\fR \fIprotect\fR] [\fB\-R\fR \fIrefuse\fR]
[\fB\-P\fR \fIprotect\fR] [\fB\-R\fR \fIrefuse\fR]
.br
[\fB\-I\fR \fIinclude\fR] [\fB\-E\fR \fIexclude\fR] [\fIPROGRAM\fR [\fIARGS\fR]...]
[\fB\-I\fR \fIinclude\fR] [\fB\-E\fR \fIexclude\fR] [\fIPROGRAM\fR [\fIARGS\fR]...]
.br
\fBzzuf \-h\fR | \fB\-\-help\fR
.br
@@ -94,6 +94,10 @@ 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\-M\fR, \fB\-\-md5\fR
Instead of displaying the program's output, just print the MD5 digest of that
output.
.TP
\fB\-n\fR, \fB\-\-network\fR
Fuzz the application's network input. By default \fBzzuf\fR only fuzzes files.
.TP
+1 -1
View File
@@ -1,7 +1,7 @@
COMMON = random.c random.h fd.c fd.h fuzz.c fuzz.h
bin_PROGRAMS = zzuf
zzuf_SOURCES = zzuf.c $(COMMON)
zzuf_SOURCES = zzuf.c $(COMMON) md5.c md5.h
zzuf_CFLAGS = -DLIBDIR=\"$(libdir)/zzuf\"
pkglib_LTLIBRARIES = libzzuf.la
+237
View File
@@ -0,0 +1,237 @@
/*
* zzuf - general purpose fuzzer
* Copyright (c) 2002, 2007 Sam Hocevar <sam@zoy.org>
* All Rights Reserved
*
* $Id$
*
* This program is free software. It comes without any warranty, to
* the extent permitted by applicable law. You can redistribute it
* and/or modify it under the terms of the Do What The Fuck You Want
* To Public License, Version 2, as published by Sam Hocevar. See
* http://sam.zoy.org/wtfpl/COPYING for more details.
*/
/*
* md5.c: MD5 computation. Written and put into the public domain
* by Colin Plumb in 1993.
*/
#include "config.h"
#if defined HAVE_STDINT_H
# include <stdint.h>
#elif defined HAVE_INTTYPES_H
# include <inttypes.h>
#endif
#include <string.h>
#include <stdlib.h>
#include "md5.h"
struct md5 {
uint32_t buf[4];
uint32_t bits[2];
uint8_t in[64];
};
static void transform(uint32_t buf[4], uint32_t in[16]);
#define HIGHFIRST
#ifdef __i386__
#undef HIGHFIRST
#endif
#ifndef HIGHFIRST
#define swapbytes(buf, len) /* Nothing */
#else
/*
* Note: this code is harmless on little-endian machines.
*/
void swapbytes(uint8_t *buf, unsigned bytes)
{
uint32_t t;
do
{
t = (uint32_t) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
((unsigned) buf[1] << 8 | buf[0]);
*(uint32_t *) buf = t;
buf += 4;
bytes -= 4;
} while(bytes > 0);
}
#endif
struct md5 *_zz_md5_init(void)
{
struct md5 *ctx = malloc(sizeof(struct md5));
ctx->buf[0] = 0x67452301;
ctx->buf[1] = 0xefcdab89;
ctx->buf[2] = 0x98badcfe;
ctx->buf[3] = 0x10325476;
ctx->bits[0] = 0;
ctx->bits[1] = 0;
return ctx;
}
void _zz_md5_add(struct md5 *ctx, uint8_t *buf, unsigned len)
{
uint32_t t;
t = ctx->bits[0];
if((ctx->bits[0] = t + ((uint32_t)len << 3)) < t)
ctx->bits[1]++;
ctx->bits[1] += len >> 29;
t = (t >> 3) & 0x3f;
if(t)
{
uint8_t *p = (uint8_t *)ctx->in + t;
t = 64 - t;
if(len < t)
{
memcpy(p, buf, len);
return;
}
memcpy(p, buf, t);
swapbytes(ctx->in, 64);
transform(ctx->buf, (uint32_t *)ctx->in);
buf += t;
len -= t;
}
while (len >= 64)
{
memcpy(ctx->in, buf, 64);
swapbytes(ctx->in, 64);
transform(ctx->buf, (uint32_t *)ctx->in);
buf += 64;
len -= 64;
}
memcpy(ctx->in, buf, len);
}
void _zz_md5_fini(uint8_t *digest, struct md5 *ctx)
{
unsigned count;
uint8_t *p;
count = (ctx->bits[0] >> 3) & 0x3F;
p = ctx->in + count;
*p++ = 0x80;
count = 64 - 1 - count;
if(count < 8)
{
memset(p, 0, count);
swapbytes(ctx->in, 64);
transform(ctx->buf, (uint32_t *) ctx->in);
memset(ctx->in, 0, 56);
}
else
memset(p, 0, count - 8);
swapbytes(ctx->in, 56);
memcpy(ctx->in + 56, ctx->bits, 8);
transform(ctx->buf, (uint32_t *)ctx->in);
swapbytes((uint8_t *)ctx->buf, 16);
memcpy(digest, ctx->buf, 16);
free(ctx);
}
/* #define F1(x, y, z) (x & y | ~x & z) */
#define F1(x, y, z) (z ^ (x & (y ^ z)))
#define F2(x, y, z) F1(z, x, y)
#define F3(x, y, z) (x ^ y ^ z)
#define F4(x, y, z) (y ^ (x | ~z))
#define MD5STEP(f, w, x, y, z, data, s) \
( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
static void transform(uint32_t buf[4], uint32_t in[16])
{
uint32_t a = buf[0];
uint32_t b = buf[1];
uint32_t c = buf[2];
uint32_t d = buf[3];
MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
buf[0] += a;
buf[1] += b;
buf[2] += c;
buf[3] += d;
}
+24
View File
@@ -0,0 +1,24 @@
/*
* zzuf - general purpose fuzzer
* Copyright (c) 2002, 2007 Sam Hocevar <sam@zoy.org>
* All Rights Reserved
*
* $Id$
*
* This program is free software. It comes without any warranty, to
* the extent permitted by applicable law. You can redistribute it
* and/or modify it under the terms of the Do What The Fuck You Want
* To Public License, Version 2, as published by Sam Hocevar. See
* http://sam.zoy.org/wtfpl/COPYING for more details.
*/
/*
* md5.h: MD5 computation
*/
struct md5;
extern struct md5 *_zz_md5_init(void);
extern void _zz_md5_add(struct md5 *ctx, uint8_t *buf, unsigned len);
extern void _zz_md5_fini(uint8_t *digest, struct md5 *ctx);
+71 -26
View File
@@ -41,6 +41,7 @@
#include "random.h"
#include "fd.h"
#include "fuzz.h"
#include "md5.h"
static void spawn_child(char **);
static void clean_children(void);
@@ -69,6 +70,7 @@ static struct child_list
int fd[3]; /* 0 is debug, 1 is stderr, 2 is stdout */
int bytes, seed;
time_t date;
struct md5 *ctx;
} *child_list;
static int maxforks = 1, child_count = 0, maxcrashes = 1, crashes = 0;
@@ -76,6 +78,7 @@ static int seed = 0;
static int endseed = 1;
static int quiet = 0;
static int maxbytes = -1;
static int md5 = 0;
static double maxtime = -1.0;
#define ZZUF_FD_SET(fd, p_fdset, maxfd) \
@@ -114,6 +117,7 @@ int main(int argc, char *argv[])
{ "max-forks", 1, NULL, 'F' },
{ "stdin", 0, NULL, 'i' },
{ "include", 1, NULL, 'I' },
{ "md5", 0, NULL, 'M' },
{ "network", 0, NULL, 'n' },
{ "protect", 1, NULL, 'P' },
{ "quiet", 0, NULL, 'q' },
@@ -125,11 +129,11 @@ int main(int argc, char *argv[])
{ "help", 0, NULL, 'h' },
{ "version", 0, NULL, 'v' },
};
int c = getopt_long(argc, argv, "B:cC:dE:F:iI:nP:qr:R:s:ST:hv",
int c = getopt_long(argc, argv, "B:cC:dE:F:iI:MnP:qr:R:s:ST:hv",
long_options, &option_index);
# else
# define MOREINFO "Try `%s -h' for more information.\n"
int c = getopt(argc, argv, "B:cC:dE:F:iI:nP:qr:R:s:ST:hv");
int c = getopt(argc, argv, "B:cC:dE:F:iI:MnP:qr:R:s:ST:hv");
# endif
if(c == -1)
break;
@@ -172,6 +176,9 @@ int main(int argc, char *argv[])
return EXIT_FAILURE;
}
break;
case 'M': /* --md5 */
md5 = 1;
break;
case 'n': /* --network */
setenv("ZZUF_NETWORK", "1", 1);
break;
@@ -219,6 +226,12 @@ int main(int argc, char *argv[])
/* If asked to read from the standard input */
if(optind >= argc)
{
uint8_t md5sum[16];
struct md5 *ctx = NULL;
if(md5)
ctx = _zz_md5_init();
if(endseed != seed + 1)
{
printf("%s: seed ranges are incompatible with stdin fuzzing\n",
@@ -245,7 +258,22 @@ int main(int argc, char *argv[])
_zz_fuzz(0, buf, ret);
_zz_addpos(0, ret);
fwrite(buf, 1, ret, stdout);
if(md5)
_zz_md5_add(ctx, buf, ret);
else
fwrite(buf, 1, ret, stdout);
}
if(md5)
{
_zz_md5_fini(md5sum, ctx);
fprintf(stdout, "zzuf[seed=%i]: %.02x%.02x%.02x%.02x%.02x%.02x"
"%.02x%.02x%.02x%.02x%.02x%.02x%.02x%.02x%.02x%.02x\n",
seed, md5sum[0], md5sum[1], md5sum[2], md5sum[3],
md5sum[4], md5sum[5], md5sum[6], md5sum[7],
md5sum[8], md5sum[9], md5sum[10], md5sum[11],
md5sum[12], md5sum[13], md5sum[14], md5sum[15]);
fflush(stdout);
}
_zz_unregister(0);
@@ -369,7 +397,7 @@ static void spawn_child(char **argv)
pid_t pid;
int i, j;
/* Find an empty slot */
/* Find the empty slot */
for(i = 0; i < maxforks; i++)
if(child_list[i].status == STATUS_FREE)
break;
@@ -408,23 +436,24 @@ static void spawn_child(char **argv)
perror(argv[0]);
exit(EXIT_FAILURE);
}
break;
default:
/* Were the parent, acknowledge spawn */
child_list[i].date = time(NULL);
child_list[i].pid = pid;
for(j = 0; j < 3; j++)
{
close(fd[j][1]);
child_list[i].fd[j] = fd[j][0];
}
child_list[i].bytes = 0;
child_list[i].seed = seed;
child_list[i].status = STATUS_RUNNING;
child_count++;
seed++;
break;
return;
}
/* Were the parent, acknowledge spawn */
child_list[i].date = time(NULL);
child_list[i].pid = pid;
for(j = 0; j < 3; j++)
{
close(fd[j][1]);
child_list[i].fd[j] = fd[j][0];
}
child_list[i].bytes = 0;
child_list[i].seed = seed;
child_list[i].status = STATUS_RUNNING;
if(md5)
child_list[i].ctx = _zz_md5_init();
child_count++;
seed++;
}
static void clean_children(void)
@@ -473,6 +502,7 @@ static void clean_children(void)
/* Collect dead children */
for(i = 0; i < maxforks; i++)
{
uint8_t md5sum[16];
int status;
pid_t pid;
@@ -502,6 +532,16 @@ static void clean_children(void)
if(child_list[i].fd[j] >= 0)
close(child_list[i].fd[j]);
if(md5)
{
_zz_md5_fini(md5sum, child_list[i].ctx);
fprintf(stdout, "zzuf[seed=%i]: %.02x%.02x%.02x%.02x%.02x%.02x"
"%.02x%.02x%.02x%.02x%.02x%.02x%.02x%.02x%.02x%.02x\n",
child_list[i].seed, md5sum[0], md5sum[1], md5sum[2],
md5sum[3], md5sum[4], md5sum[5], md5sum[6], md5sum[7],
md5sum[8], md5sum[9], md5sum[10], md5sum[11], md5sum[12],
md5sum[13], md5sum[14], md5sum[15]);
}
child_list[i].status = STATUS_FREE;
child_count--;
}
@@ -537,7 +577,7 @@ static void read_children(void)
/* XXX: cute (i, j) iterating hack */
for(i = 0, j = 0; i < maxforks; i += (j == 2), j = (j + 1) % 3)
{
char buf[BUFSIZ];
uint8_t buf[BUFSIZ];
if(child_list[i].status != STATUS_RUNNING)
continue;
@@ -551,7 +591,10 @@ static void read_children(void)
/* We got data */
if(j != 0)
child_list[i].bytes += ret;
if(!quiet || j == 0)
if(md5 && j > 0)
_zz_md5_add(child_list[i].ctx, buf, ret);
else if(!quiet || j == 0)
write((j < 2) ? STDERR_FILENO : STDOUT_FILENO, buf, ret);
}
else if(ret == 0)
@@ -606,10 +649,10 @@ static void version(void)
#if defined(HAVE_GETOPT_H)
static void usage(void)
{
printf("Usage: zzuf [-cdinqS] [-r ratio] [-s seed | -s start:stop]\n");
printf(" [-F forks] [-C crashes] [-B bytes] [-T seconds]\n");
printf(" [-P protect] [-R refuse]\n");
printf(" [-I include] [-E exclude] [PROGRAM [ARGS]...]\n");
printf("Usage: zzuf [-cdiMnqS] [-r ratio] [-s seed | -s start:stop]\n");
printf(" [-F forks] [-C crashes] [-B bytes] [-T seconds]\n");
printf(" [-P protect] [-R refuse]\n");
printf(" [-I include] [-E exclude] [PROGRAM [ARGS]...]\n");
# ifdef HAVE_GETOPT_LONG
printf(" zzuf -h | --help\n");
printf(" zzuf -v | --version\n");
@@ -629,6 +672,7 @@ static void usage(void)
printf(" -F, --max-forks <n> number of concurrent children (default 1)\n");
printf(" -i, --stdin fuzz standard input\n");
printf(" -I, --include <regex> only fuzz files matching <regex>\n");
printf(" -M, --md5 compute the output's MD5 hash\n");
printf(" -n, --network fuzz network input\n");
printf(" -P, --protect <list> protect bytes and characters in <list>\n");
printf(" -q, --quiet do not print children's messages\n");
@@ -649,6 +693,7 @@ static void usage(void)
printf(" -F <n> number of concurrent forks (default 1)\n");
printf(" -i fuzz standard input\n");
printf(" -I <regex> only fuzz files matching <regex>\n");
printf(" -M compute the output's MD5 hash\n");
printf(" -n fuzz network input\n");
printf(" -P <list> protect bytes and characters in <list>\n");
printf(" -q do not print the fuzzed application's messages\n");