Code: Select all
#!/usr/bin/python
'''
FuzzDiff
Written by: Dan Rosenberg
This is a simple tool designed to help out with crash analysis during fuzz
testing. It selectively "un-fuzzes" portions of a fuzzed file that is known to
cause a crash, re-launches the targeted application, and sees if it still
crashes. Eventually, this will yield a file that still causes the crash, but
contains a minimum set of changes from the original un-fuzzed file.
Copyright (C) 2010 Virtual Security Research, LLC. - All rights reserved
This program is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program. If not, see <http://www.gnu.org/licenses/>.
'''
import sys
import os
import random
import shutil
import subprocess
import time
# Probability a fuzzed byte will be reverted
THRESHOLD = .5
# Number of iterations before stopping
ITER = 6000
# Temporary output
TMPFILE = "/tmp/fuzz123"
# Time to wait before killing target program
WAIT = 2
def unfuzz(orig, fuzz, out):
origstat = os.stat(orig)
fuzzstat = os.stat(fuzz)
if(origstat.st_size != fuzzstat.st_size):
print "[*] Files are not the same size."
term(-1)
try:
origfd = open(orig, "r")
fuzzfd = open(fuzz, "r")
outfd = open(out, "w")
except:
print "[*] Error opening file - bad arguments"
term(-1)
diff = 0
unchanged = 0
while(1):
c = origfd.read(1)
if not c: break
d = fuzzfd.read(1)
# If there's a diff...
if(c != d):
diff += 1
# With some probability, revert it
if(random.random() > THRESHOLD):
outfd.write(c)
else:
unchanged += 1
outfd.write(d)
else:
outfd.write(c)
return (diff, unchanged)
def term(ret):
print "[*] Terminating..."
try:
os.remove(TMPFILE)
finally:
sys.exit(ret)
#######################
# Program entry point #
#######################
if(len(sys.argv) < 4):
print "[*] Usage: fuzzdiff [orig] [fuzzed] [program] [args]"
sys.exit(-1)
progargs = sys.argv[3:]
orig = sys.argv[1]
best = "fuzz.out"
try:
shutil.copy(sys.argv[2], best)
except:
print "[*] Error opening file - bad fuzzfile argument"
term(-1)
null = open("/dev/null", "rw")
# Main loop
for i in range(ITER):
(diff, unchanged) = unfuzz(orig, best, TMPFILE)
# Only bother if we actually reduced the number of diffs
if(unchanged < diff):
# Test if the result still crashes the target
try:
p = subprocess.Popen(progargs + [TMPFILE], stdout=null, stderr=null)
except:
print "[*] Error running program"
term(-1)
# Give the program some time to start...
time.sleep(WAIT)
# If it segfaulted, keep the changes
if (p.poll() == -11):
shutil.copy(TMPFILE, best)
print "[*] Reduced diffs from", diff, "to", unchanged
if(unchanged == 1):
break
# If the program hasn't terminated, kill it
elif(p.returncode == None):
p.terminate()
print "[*] Output written to fuzz.out"
term(1)
How does fuzzdiff works :
When provided with a fuzzed file, a corresponding original un-fuzzed
file, and the path to the targeted program, FuzzDiff will selectively “un-fuzz” portions of the fuzzed file while re-launching theapplication to monitor for crashes. This will yield a file that still crashes the target application, but contains a minimum set of changes from the original, un-fuzzed file. This can be useful in pinning down the exact cause of a crash.
The tool is written in Python and currently only works on Unix-based systems, since it monitors for crashes by checking for SIGSEGV. It also assumes thatthe target program adheres to the syntax “[program] [args] [input file]“. Both of these limitations can be easily worked around. The code is hardly what I’d call production-ready, but it gets the job done.
FuzzDiff will help to analysis and find the root cause analysis of problem and fine tune our fuzz method.
Source :
Code: Select all
http://vsecurity.com/download/tools/fuzzdiff.py