Randy – Random-based Fuzzer in Python

Fuzzers are often perceived as complex pieces of software, but not all of them are really that complex. The following script is an example of a random-based fuzzer that was created during one of our training courses to demonstrate how simple but yet effective fuzzers can really be.

Randy, the random-based fuzzer shown below, uses a random approach to modify the initial sample and create interesting test cases to find bugs in software applications.

#!/usr/bin/env python
#
# Randy - Random-based fuzzer in Python.
#
# Gianni Gnesa (@GianniGnesa)
# http://35.159.40.32
#
# randy.py is a simple random-based fuzzer that can be used to find bugs in
# software applications. To run this fuzzer, use the following command:
#
# ./randy.py <file_to_mutate> <num_of_files_to_generate>
#
# Example:
#
# ./randy.py input.pdf 15
#

from sys import *
from math import ceil
from random import randrange

XFACTOR = 0.5# Fuzz factor (value between 0.0 and 1.0)

def main():
print """
____ _ _ _ ______ __
| _ \ / \ | \ | | _ \ \ / /
| |_) | / _ \ | \| | | | \ V /
| _ < / ___ \| |\ | |_| || |
|_| \_\/_/ \_\_| \_|____/ |_| v0.3

"""

if len(argv) != 3:
print "Usage: %s <file_to_mutate> <num_of_files_to_generate>"
exit(-1)

buf = ''
fname= argv[1]
nfiles = int(argv[2])
inbytes = list(open(fname, 'rb').read())

print "[+] Creating %d test cases [sizeof(sample) == %d bytes]\n" % (nfiles, len(inbytes))
for i in range(1, nfiles+1):
buf = list(inbytes)
nchanges= randrange(ceil(len(inbytes) * XFACTOR)) + 1# Number of changes

for j in range(nchanges):
buf[randrange(len(buf))] = "%c" % (randrange(256))

f = open('testcase' + str(i) + '_' + fname, 'wb')
f.write("".join(buf))
f.close()

print "[+] Generating test case %2d\t[nchanges=%6d]" % (i, nchanges)

print "[+] Done."


if __name__ == "__main__":
main()

This script takes 2 arguments, a file and a number. The file is the initial sample that will be used to generate the test cases. It can be any file you want: mp3, pdf, exe, etc. The second argument is the number of files that we want to generate. For example, the following command takes a PDF file and creates 15 malformed PDFs.

./randy.py input.pdf 15

Just as an exercise, try to download randy.py and use it to generate some input files to test a music player. Do you get any crashes?