zzuf: add a -X flag for hexadecimal dumps.

This commit is contained in:
Sam Hocevar 2015-01-19 00:26:05 +01:00
parent 2738d9bd9d
commit eb8c73c57d
9 changed files with 183 additions and 5 deletions

View File

@ -174,7 +174,7 @@ considered by the \fB\-l\fR flag.
\fB\-m\fR, \fB\-\-md5\fR
Instead of displaying the program's \fIstandard output\fR, just print its MD5
digest to \fBzzuf\fR's standard output. The standard error channel is left
untouched.
untouched. See also the \fB\-X\fR flag.
.TP
\fB\-M\fR, \fB\-\-max\-memory\fR=\fImebibytes\fR
Specify the maximum amount of memory, in mebibytes (1 MiB = 1,048,576 bytes),
@ -354,6 +354,10 @@ get run, their exit status, etc.
Report processes that exit with a non-zero status. By default only processes
that crash due to a signal are reported.
.TP
\fB\-X\fR, \fB\-\-hex\fR
Convert the fuzzed program's \fIstandard output\fR to hexadecimal. The standard
error channel is left untouched. See also the \fB\-m\fR flag.
.TP
\fB\-h\fR, \fB\-\-help\fR
Display a short help message and exit.
.TP

View File

@ -181,6 +181,7 @@
<ClInclude Include="..\src\opts.h" />
<ClInclude Include="..\src\timer.h" />
<ClInclude Include="..\src\util\getopt.h" />
<ClInclude Include="..\src\util\hex.h" />
<ClInclude Include="..\src\util\md5.h" />
<ClInclude Include="..\src\util\mutex.h" />
<ClInclude Include="..\src\util\regex.h" />
@ -195,6 +196,7 @@
<ClCompile Include="..\src\opts.c" />
<ClCompile Include="..\src\timer.c" />
<ClCompile Include="..\src\util\getopt.c" />
<ClCompile Include="..\src\util\hex.c" />
<ClCompile Include="..\src\util\md5.c" />
<ClCompile Include="..\src\util\regex.cpp">
<CompileAs>CompileAsCpp</CompileAs>

View File

@ -4,7 +4,8 @@ pkglib_LTLIBRARIES = libzzuf.la
ZZUF = \
zzuf.c opts.c opts.h timer.c timer.h myfork.c myfork.h \
util/getopt.c util/getopt.h util/md5.c util/md5.h
util/getopt.c util/getopt.h util/md5.c util/md5.h \
util/hex.c util/hex.h
ZZAT = \
zzat.c \

View File

@ -43,6 +43,7 @@ void _zz_opts_init(struct opts *opts)
opts->b_quiet = 0;
opts->b_md5 = 0;
opts->b_hex = 0;
opts->b_checkexit = 0;
opts->b_verbose = 0;

View File

@ -36,6 +36,7 @@ struct opts
double maxratio;
int b_md5;
int b_hex;
int b_checkexit;
int b_verbose;
int b_quiet;
@ -71,6 +72,7 @@ struct opts
double ratio;
int64_t date;
struct zz_md5 *md5;
struct zz_hex *hex;
char **newargv;
} *child;
};

116
src/util/hex.c Normal file
View File

@ -0,0 +1,116 @@
/*
* zzuf - general purpose fuzzer
*
* Copyright © 20022015 Sam Hocevar <sam@hocevar.net>
*
* 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 the WTFPL Task Force.
* See http://www.wtfpl.net/ for more details.
*/
/*
* hex.c: hexadecimal data dump
*/
#include "config.h"
#if defined HAVE_STDINT_H
# include <stdint.h>
#elif defined HAVE_INTTYPES_H
# include <inttypes.h>
#endif
#if defined HAVE_ENDIAN_H
# include <endian.h>
#endif
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "util/hex.h"
struct zz_hex
{
/* Buffered line */
uint8_t current_line[16];
/* The previous line FIXME: not used yet */
uint8_t prev_line[16];
/* Number of bytes read so far */
int64_t count;
};
struct zz_hex *zz_hex_init(void)
{
struct zz_hex *ctx = malloc(sizeof(struct zz_hex));
ctx->count = 0;
return ctx;
}
static void print_hex(struct zz_hex *ctx, unsigned len)
{
uint8_t *buf = ctx->current_line;
uint32_t address = (uint32_t)(ctx->count - len);
/* Create the hex dump */
uint8_t hex[49] = " ";
for (unsigned i = 0; i < len; ++i)
{
static char const *hex2char = "0123456789abcdef";
hex[i * 3 + (i >= 8)] = hex2char[buf[i] >> 4];
hex[i * 3 + (i >= 8) + 1] = hex2char[buf[i] & 0xf];
}
/* Create the ASCII representation */
uint8_t ascii[17] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
for (unsigned i = 0; i < len; ++i)
{
ascii[i] = (buf[i] >= 0x20 && buf[i] <= 0x7f) ? buf[i] : '.';
}
printf("%08x %s |%s|\n", address, hex, ascii);
}
void zz_hex_add(struct zz_hex *ctx, uint8_t *buf, unsigned len)
{
unsigned buffered_len = (unsigned)(ctx->count & 15);
while (len > 0)
{
/* Copy as many bytes as possible into our data buffer */
unsigned to_copy = 16 - buffered_len;
if (to_copy > len)
to_copy = len;
memcpy(ctx->current_line + buffered_len, buf, to_copy);
buffered_len += to_copy;
buf += to_copy;
len -= to_copy;
ctx->count += to_copy;
/* If the buffer is full, print it */
if (buffered_len == 16)
{
print_hex(ctx, 16);
buffered_len = 0;
}
}
fflush(stdout);
}
void zz_hex_fini(struct zz_hex *ctx)
{
/* Print the last line, if non-empty */
if (ctx->count & 15)
print_hex(ctx, (unsigned)(ctx->count & 15));
/* Print the last offset */
printf("%08x\n", (uint32_t)ctx->count);
free(ctx);
fflush(stdout);
}

20
src/util/hex.h Normal file
View File

@ -0,0 +1,20 @@
/*
* zzuf - general purpose fuzzer
*
* Copyright © 20022015 Sam Hocevar <sam@hocevar.net>
*
* 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 the WTFPL Task Force.
* See http://www.wtfpl.net/ for more details.
*/
/*
* hex.h: hexadecimal data dump
*/
extern struct zz_hex *zz_hex_init(void);
extern void zz_hex_add(struct zz_hex *ctx, uint8_t *buf, unsigned len);
extern void zz_hex_fini(struct zz_hex *ctx);

View File

@ -14,8 +14,6 @@
* md5.h: MD5 computation
*/
struct md5;
extern struct zz_md5 *zz_md5_init(void);
extern void zz_md5_add(struct zz_md5 *ctx, uint8_t *buf, unsigned len);
extern void zz_md5_fini(uint8_t *digest, struct zz_md5 *ctx);

View File

@ -66,6 +66,7 @@
#include "timer.h"
#include "util/getopt.h"
#include "util/md5.h"
#include "util/hex.h"
#if !defined SIGKILL
# define SIGKILL 9
@ -159,7 +160,7 @@ int main(int argc, char *argv[])
# define OPTSTR_RLIMIT_CPU ""
#endif
#define OPTSTR "+" OPTSTR_REGEX OPTSTR_RLIMIT_MEM OPTSTR_RLIMIT_CPU \
"a:Ab:B:C:dD:e:f:F:ij:l:mnO:p:P:qr:R:s:St:U:vxhV"
"a:Ab:B:C:dD:e:f:F:ij:l:mnO:p:P:qr:R:s:St:U:vxXhV"
#define MOREINFO "Try `%s --help' for more information.\n"
int option_index = 0;
static struct zz_option long_options[] =
@ -201,6 +202,7 @@ int main(int argc, char *argv[])
{ "max-usertime", 1, NULL, 'U' },
{ "verbose", 0, NULL, 'v' },
{ "check-exit", 0, NULL, 'x' },
{ "hex", 0, NULL, 'X' },
{ "help", 0, NULL, 'h' },
{ "version", 0, NULL, 'V' },
{ NULL, 0, NULL, 0 }
@ -368,6 +370,9 @@ int main(int argc, char *argv[])
case 'x': /* --check-exit */
opts->b_checkexit = 1;
break;
case 'X': /* --hex */
opts->b_hex = 1;
break;
case 'v': /* --verbose */
opts->b_verbose = 1;
break;
@ -387,6 +392,15 @@ int main(int argc, char *argv[])
}
}
if (opts->b_md5 && opts->b_hex)
{
fprintf(stderr, "%s: MD5 hash (-m) and hexadecimal dump (-X) are "
"incompatible\n", argv[0]);
printf(MOREINFO, argv[0]);
_zz_opts_fini(opts);
return EXIT_FAILURE;
}
if (opts->ports && !b_network)
{
fprintf(stderr, "%s: port option (-p) requires network fuzzing (-n)\n",
@ -565,9 +579,12 @@ int main(int argc, char *argv[])
static void loop_stdin(struct opts *opts)
{
struct zz_md5 *md5 = NULL;
struct zz_hex *hex = NULL;
if (opts->b_md5)
md5 = zz_md5_init();
else if (opts->b_hex)
hex = zz_hex_init();
_zz_register(0);
@ -595,6 +612,8 @@ static void loop_stdin(struct opts *opts)
if (opts->b_md5)
zz_md5_add(md5, buf, ret);
else if (opts->b_hex)
zz_hex_add(hex, buf, ret);
else while (ret)
{
int nw = 0;
@ -617,6 +636,10 @@ static void loop_stdin(struct opts *opts)
md5sum[12], md5sum[13], md5sum[14], md5sum[15]);
fflush(stdout);
}
else if (opts->b_hex)
{
zz_hex_fini(hex);
}
_zz_unregister(0);
}
@ -773,6 +796,8 @@ static void spawn_children(struct opts *opts)
opts->child[slot].status = STATUS_RUNNING;
if (opts->b_md5)
opts->child[slot].md5 = zz_md5_init();
else if (opts->b_hex)
opts->child[slot].hex = zz_hex_init();
if (opts->b_verbose)
{
@ -969,6 +994,10 @@ static void clean_children(struct opts *opts)
md5sum[11], md5sum[12], md5sum[13], md5sum[14], md5sum[15]);
fflush(stdout);
}
else if (opts->b_hex)
{
zz_hex_fini(opts->child[i].hex);
}
opts->child[i].status = STATUS_FREE;
opts->nchild--;
}
@ -1014,6 +1043,8 @@ static void __stdcall read_child(DWORD err_code, DWORD nbr_of_bytes_transfered,
if (co->opts->b_md5 && co->fd_no == 2)
zz_md5_add(co->opts->child[co->child_no].md5, co->buf, nbr_of_bytes_transfered);
else if (co->opts->b_hex && co->fd_no == 2)
zz_hex_add(co->opts->child[co->child_no].hex, co->buf, nbr_of_bytes_transfered);
free(co); /* clean up allocated data */
}
@ -1118,6 +1149,8 @@ static void read_children(struct opts *opts)
if (opts->b_md5 && j == 2)
zz_md5_add(opts->child[i].md5, buf, ret);
else if (opts->b_hex && j == 2)
zz_hex_add(opts->child[i].hex, buf, ret);
else if (!opts->b_quiet || j == 0)
write((j < 2) ? STDERR_FILENO : STDOUT_FILENO, buf, ret);
}
@ -1266,6 +1299,7 @@ static void usage(void)
printf(" -U, --max-usertime <n> kill children that run for more than <n> seconds\n");
printf(" -v, --verbose print information during the run\n");
printf(" -x, --check-exit report processes that exit with a non-zero status\n");
printf(" -X, --hex convert program output to hexadecimal\n");
printf(" -h, --help display this help and exit\n");
printf(" -V, --version output version information and exit\n");
printf("\n");