-
Notifications
You must be signed in to change notification settings - Fork 3
/
fuzzer.py
executable file
·163 lines (128 loc) · 3.76 KB
/
fuzzer.py
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
159
160
161
162
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import argparse
import pprint
import os
import sys
import random
import subprocess
import struct
import time
print "Fuzzing stuff"
usage = "usage: %prog [options] ORIGFILES"
desc = """Example:
./fuzzer.py --random 10 raw_dat*.bin
"""
parser = argparse.ArgumentParser(description=desc)
parser.add_argument("files", metavar="FILES", type=str, nargs='+', help="Original input files")
parser.add_argument("--random", dest="random", type=int, default=1, help="How random is random")
args = parser.parse_args()
pprint.pprint(args)
def unique_fuzz_file(file_name_begin):
counter = 1
while 1:
file_name = file_name_begin + '_' + str(counter) + ".cnf"
try:
fd = os.open(file_name, os.O_CREAT | os.O_EXCL)
os.fdopen(fd).close()
return file_name
except OSError:
pass
counter += 1
def setlimits():
#sys.stdout.write("Setting resource limit in child (pid %d): %d s\n" % (os.getpid(), maxTime))
resource.setrlimit(resource.RLIMIT_CPU, (maxTime, maxTime))
random.seed(time.time())
messages = []
def go_through_file(fname) :
with open(fname, "rb") as in_file:
more_in_file = True
while more_in_file:
message = []
for i in xrange(4096) :
val = in_file.read(1)
if not val:
more_in_file = False
break
val = ord(val)
if val == 0x7e :
message.append(val)
break
if val == 0x7d :
message.append(val)
val = in_file.read(1)
if not val:
more_in_file = False
break
val = ord(val)
message.append(val)
#print "message is: ", message
print '%dB' % len(message)
a = struct.pack('%dB' % len(message), *message)
messages.append(a)
def remove_random_bytes(data, max_remove) :
if random.randint(0,100) < 90:
return data
to_remove = random.randint(0, max_remove)
for i in range(to_remove) :
skip_how_many = random.randint(1,100)
end = len(data)-skip_how_many
if end < 0 :
continue
from_pos = random.randint(0, end)
data = data[:from_pos] + data[from_pos+skip_how_many:]
return data
def perturb_values(data, max_num_perturbed) :
if len(data) == 0:
return data
tmp = struct.unpack("%dB" % len(data), data)
tmp = list(tmp)
for x in range(random.randint(0,max_num_perturbed)) :
assert len(tmp) > 0
mess_up_at = random.randint(0,len(tmp)-1)
tmp[mess_up_at] = random.randint(0,255)
tmp = remove_random_bytes(tmp, 2)
return struct.pack("%dB" % len(tmp), *tmp)
for fname in args.files:
go_through_file(fname)
def check_for_uper(data) :
for line in data:
if "SEQUENCE_decode_uper".lower() in line.lower():
return True
return False
for x in xrange(1000*1000) :
fuzz_fname = unique_fuzz_file("fuzz_")
print "Fuzzing attempt", x, " fname:", fuzz_fname
f = open(fuzz_fname, "wb")
#for at in range(len(messages)) :
for a in range(random.randint(1, 100)) :
at = random.randint(0, len(messages)-1)
towrite = messages[at]
towrite = perturb_values(towrite, 1)
f.write(towrite)
f.close()
if random.randint(0,100) > 80:
os.system("radamsa %s > %s_new" % (fuzz_fname, fuzz_fname))
os.unlink(fuzz_fname)
fuzz_fname = fuzz_fname + "_new"
print "New fuzz name:" , fuzz_fname
toexec = "valgrind ./diag_import 0 0 ".split()
f = open(fuzz_fname, "rb")
p = subprocess.Popen(toexec, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin = f)
out, err = p.communicate()
f.close()
out = out.split("\n")
err = err.split("\n")
for line in err:
print line
line = line.lower()
if "signal" in line or "fail" in line or "invalid" in line or "abort" in line:
if "assert" in line:
continue
if check_for_uper(err):
continue
print "out:", "\n".join(out)
print "err:", "\n".join(err)
print "filename:", fuzz_fname
exit(-1)
os.unlink(fuzz_fname)