/usr/share/fusil/fuzzers/fusil-zzuf is in fusil 1.4-1.
This file is owned by root:root, with mode 0o755.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | #!/usr/bin/env python
"""
Fuzz a process using the zzuf library.
zzuf homepage: http://libcaca.zoy.org/wiki/zzuf
"""
MIN_SEED = 0
MAX_SEED = 2**32 - 1
from fusil.application import Application
from optparse import OptionGroup
from fusil.zzuf import ZzufProcess, DEFAULT_RATIO
from fusil.process.create import DEFAULT_TIMEOUT
from fusil.process.watch import WatchProcess, DEFAULT_TIMEOUT_SCORE
from fusil.process.env import EnvVarIntegerRange
import re
import itertools
class Fuzzer(Application):
NAME = "zzuf"
USAGE = "%prog [options] program [arg1 arg2 ...]"
NB_ARGUMENTS = (1, None)
def createFuzzerOptions(self, parser):
options = OptionGroup(parser, "zzuf fuzzer options")
options.add_option("-r", "--ratio",
help="bit fuzzing ratio (default %g) or ratio range (<start:stop>)" % DEFAULT_RATIO,
type="str")
options.add_option("-b", "--bytes",
help="only fuzz bytes at offsets within <ranges>",
type="str")
options.add_option("-l", "--list",
help="only fuzz Nth descriptor with N in <list>",
type="str")
options.add_option("-f", "--fuzzing",
help="use fuzzing mode <mode>: xor, set, unset (default: xor)",
type="str")
options.add_option("-E", "--exclude",
help="do not fuzz files matching <regex>",
type="str")
options.add_option("-I", "--include",
help="only fuzz files matching <regex>",
type="str")
options.add_option("-p", "--ports",
help="only fuzz network destination ports in <list>",
type="str")
options.add_option("-P", "--protect",
help="protect bytes and characters in <list>",
type="str")
options.add_option("-R", "--refuse",
help="refuse bytes and characters in <list>",
type="str")
options.add_option("-n", "--network",
help="fuzz network input",
action="store_true")
options.add_option("--cmdline",
help="Only fuzz files specified in the command line",
action="store_true")
options.add_option("--timeout",
help="Process maximum execution time in seconds (default: %.1f sec)" % DEFAULT_TIMEOUT,
type="float", default=DEFAULT_TIMEOUT)
options.add_option("--check-exit",
help="report processes that exit with a non-zero status",
action="store_true")
options.add_option("--timeout-score",
help="Process timeout score in percent (default: %.1f%%)" % (DEFAULT_TIMEOUT_SCORE*100),
type="float", default=DEFAULT_TIMEOUT_SCORE*100)
options.add_option("--zzuf-library",
help="zzuf library full path (default: guess common paths)",
type="str", default=None)
return options
def getFilenames(self):
dashdash = False
filenames = []
for arg in self.arguments[1:]:
if dashdash:
filenames.append(arg)
elif arg == '--':
dashdash = True
elif not arg.startswith("-"):
filenames.append(arg)
return filenames
def setupProject(self):
# Check options
if self.options.ports \
and not self.options.network:
raise ValueError("port option (-p) requires network fuzzing (-n)")
# Create include/exclude filters
include = None
if self.options.include:
include = self.options.include
elif self.options.cmdline:
filenames = self.getFilenames()
filenames = itertools.imap(re.escape, filenames)
include = '(%s)' % '|'.join(filenames)
exclude = self.options.exclude
# Get the ratio
if self.options.ratio:
ratio = self.options.ratio
if ":" in ratio:
ratio = ratio.split(":", 1)
minratio = float(ratio[0])
maxratio = float(ratio[1])
else:
minratio = float(ratio)
maxratio = minratio
else:
minratio = DEFAULT_RATIO
maxratio = DEFAULT_RATIO
# Create the process agent
process = ZzufProcess(self.project,
self.arguments,
library_path=self.options.zzuf_library,
timeout=self.options.timeout)
# Generate a random zzuf seed
process.env.add(EnvVarIntegerRange('ZZUF_SEED', MIN_SEED, MAX_SEED))
# Set zzuf options
process.setRatio(minratio, maxratio)
if include:
process.env.set('ZZUF_INCLUDE', include)
if exclude:
process.env.set('ZZUF_EXCLUDE', exclude)
if self.options.network:
process.env.set('ZZUF_NETWORK', '1')
if self.options.fuzzing:
process.env.set('ZZUF_FUZZING', self.options.fuzzing)
if self.options.bytes:
process.env.set('ZZUF_BYTES', self.options.bytes)
if self.options.list:
process.env.set('ZZUF_LIST', self.options.list)
if self.options.ports:
process.env.set('ZZUF_PORTS', self.options.ports)
if self.options.protect:
process.env.set('ZZUF_PROTECT', self.options.protect)
if self.options.refuse:
process.env.set('ZZUF_REFUSE', self.options.refuse)
# Watch process exit status and stdout
if self.options.check_exit:
exitcode_score = 1.00
else:
exitcode_score = 0.10
WatchProcess(process,
exitcode_score=exitcode_score,
timeout_score=self.options.timeout_score / 100)
if __name__ == "__main__":
Fuzzer().main()
|