}}}
= 2. `zzuf` as a batch testing tool =
The most useful aspect of `zzuf` is its use as an automated tool, testing thousands of different fuzzing combinations and analysing the fuzzed application’s behaviour in each situation.
== 2.1. Debug mode ==
Consider this invocation of `zzuf` with the `file` utility:
{{{
% zzuf file /bin/ls
/etc/magic, 4: Warning: using regular magic file `/usr/share/file/magic'
/usr/share/file/magic, 33: Warning: Printf format `d' is not valid for type `string' in description `RISC OS outline font data,>5 byte x varsion %d'
/usr/share/file/magic, 47: Warning: type `stri?g \x02\x01\x13\x13\x13\x01\x0d\x10 Digital Symphony sound sample (RISC OS),' invalid
[...]
}}}
This is not the expected behaviour at all. What happens exactly? The problem is that `file` also opens its own configuration files to gather information about file formats, and of course `zzuf` fuzzes these files, since no one told it that they were special.
We may run `zzuf` in '''debug mode''' to learn more about what happens, using the '''`-d` flag''':
{{{
% zzuf -d file /bin/ls
** zzuf debug ** libzzuf initialised for PID 29526
** zzuf debug ** fopen("/etc/magic", "r") = [3]
** zzuf debug ** fgets(0x7fffc46e04b0, 8192, [3]) = 0x7fffc46e04b0
** zzuf debug ** fgets(0x7fffc46e04b0, 8192, [3]) = 0x7fffc46e04b0
** zzuf debug ** fgets(0x7fffc46e04b0, 8192, [3]) = 0x7fffc46e04b0
** zzuf debug ** fgets(0x7fffc46e04b0, 8192, [3]) = NULL
** zzuf debug ** fclose([3]) = 0
** zzuf debug ** open("/usr/share/file/magic.mgc", 0) = 3
** zzuf debug ** mmap(NULL, 1636608, 3, 2, 3, 0) = 0x2acce776e000 "\x1c\x04\x1c\xf1...
** zzuf debug ** close(3) = 0
** zzuf debug ** fopen("/usr/share/file/magic", "r") = [3]
** zzuf debug ** fgets(0x7fffc46e04b0, 8192, [3]) = 0x7fffc46e04b0
** zzuf debug ** fgets(0x7fffc46e04b0, 8192, [3]) = 0x7fffc46e04b0
** zzuf debug ** fgets(0x7fffc46e04b0, 8192, [3]) = 0x7fffc46e04b0
[...]
}}}
We see that `file` opens at least `/etc/magic`, `/usr/share/file/magic.mgc` and `/usr/share/file/magic`. Since they are installed in trusted directories, it is useless to fuzz these files, unless of course we wish to test `file`’s robustness against corruption of these files.
== 2.2. Include and exclude patterns ==
One way to make `zzuf` ignore files is to '''exclude''' them, using the '''`-E` flag''' as many times as necessary. This flag specifies that files matching a given regular expression should not be fuzzed:
{{{
% zzuf -d -E /etc/ -E /usr/share/ file /bin/ls
** zzuf debug ** libzzuf initialised for PID 30541
** zzuf debug ** open("/bin/ls", 0) = 3
** zzuf debug ** read(3, 0x60a590, 98304) = 98304 "\x7fENF...
** zzuf debug ** close(3) = 0
/bin/ls: data
%
}}}
Another way to avoid the issue is to only '''include''' the files or directories we want to fuzz, using the '''`-I` flag''' as many times as necessary:
{{{
% zzuf -d -I /bin/ file /bin/ls
** zzuf debug ** libzzuf initialised for PID 30550
** zzuf debug ** open("/bin/ls", 0) = 3
** zzuf debug ** read(3, 0x606c20, 98304) = 98304 "\x7fENF...
** zzuf debug ** close(3) = 0
/bin/ls: data
%
}}}
Yet another way is to tell `zzuf` to only fuzz files that appear on the fuzzed application’s commandline, using the '''`-c` flag''':
{{{
% zzuf -d -c file /bin/ls
** zzuf debug ** libzzuf initialised for PID 30555
** zzuf debug ** open("/bin/ls", 0) = 3
** zzuf debug ** read(3, 0x608de0, 98304) = 98304 "\x7fENF...
** zzuf debug ** close(3) = 0
/bin/ls: data
%
}}}
We can now properly fuzz the `file` application.
== 2.3. Seed ranges ==
Instead of specifying a random seed with the `-s` flag, one can specify a whole range by separating values with a colon. `zzuf` will simply run the program several times, each time with another seed in the range:
{{{
% zzuf -c -s 0:5 file /bin/ls
/bin/ls: data
/bin/ls: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, stripped
/bin/ls: ELF 64-bit LSB executable, x86-64, (SYSV), statically linked (uses shared libs), stripped
/bin/ls: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), for GNU/Linux 2.6.8388616, statically linked (uses shared libs), corrupted section header size
/bin/ls: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked (uses shared libs), stripped
%
}}}
As can be seen, the file analysed by `file` is slightly corrupted in a different way each time.
Using the '''`-v` flag''' for more verbosity helps understanding what is going on, especially with large seed ranges:
{{{
% zzuf -vc -s 0:5 file /bin/ls
zzuf[s=0,r=0.004]: launched `file'
/bin/ls: data
zzuf[s=1,r=0.004]: launched `file'
/bin/ls: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, stripped
zzuf[s=2,r=0.004]: launched `file'
/bin/ls: ELF 64-bit LSB executable, x86-64, (SYSV), statically linked (uses shared libs), stripped
zzuf[s=3,r=0.004]: launched `file'
/bin/ls: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), for GNU/Linux 2.6.8388616, statically linked (uses shared libs), corrupted section header size
zzuf[s=4,r=0.004]: launched `file'
/bin/ls: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked (uses shared libs), stripped
%
}}}
== 2.4. Ratio ranges ==
When a seed range is being used with `-s`, a ratio range can be used with `-r`. Instead of using the same bit fuzzing ratio for each seed, `zzuf` will pick one at random within the specified interval:
{{{
% zzuf -vc -s 0:5 -r 0.0001:0.01 file /bin/ls
zzuf[s=0,r=0.0001:0.01]: launched `file'
/bin/ls: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), for GNU/Linux 2.6.8, dynamically linked (uses shared libs), stripped
zzuf[s=1,r=0.0001:0.01]: launched `file'
/bin/ls: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked (uses shared libs), stripped
zzuf[s=2,r=0.0001:0.01]: launched `file'
/bin/ls: ERROR: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), for GNU/Linux 2.6.8, dynamically linked (uses shared libs)error reading
zzuf[s=3,r=0.0001:0.01]: launched `file'
/bin/ls: ERROR: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linkedCannot allocate memory for note (Cannot allocate memory)
zzuf[s=4,r=0.0001:0.01]: launched `file'
/bin/ls: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, stripped
%
}}}
To generate a file that reproduces a given behaviour, the corresponding `-s` flag and the exact same `-r` flag need to be used:
{{{
% zzuf -s 4 -r 0.0001:0.01 < /bin/ls > output.file
% file output.file
output.file: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, stripped
%
}}}
{{{
#!html