-
Notifications
You must be signed in to change notification settings - Fork 24
/
iofuzz-prototype.py
176 lines (171 loc) · 6.4 KB
/
iofuzz-prototype.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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
'''
Author : Debasish Mandal
Blog :http://www.debasish.in/
Twitter : https://twitter.com/debasishm89
A mutation based user mode (ring3) dumb in-memory IOCTL Fuzzer/Logger.
This script attach it self to any given process and hooks DeviceIoControl!Kernel32 API and
try to log or fuzz all I/O Control code I/O Buffer pointer, I/O buffer length that
process sends to any Kernel driver.
'''
try:
import utils
except ImportError:
print 'Could not import utils,Get it from https://github.com/OpenRCE/paimei'
import pydbg
from pydbg import *
from pydbg.defines import *
import random
import math
import ConfigParser
import sys
#Write these values in stack when size to be fuzzed
fuzzed_size = ['\x00\x00\x00\x00','\xff\xff\xff\xff','\x00\x00\xff\xff','\xff\xff\x00\x00']
logfile_path = 'c:\\ioctllog.xml'
def formatit(s):
buff = ''
for i in range(0,len(s)):
if i%2 == 0:
buff += '\\x'
buff += s[i]
return buff
def fuzzit(buf):
fuzzpercent = float(0.05)
b = list(buf)
numwrites=random.randrange(math.ceil((float(len(buf))) * fuzzpercent))+1
for j in range(numwrites):
rbyte = random.randrange(256)
rn = random.randrange(len(buf))
b[rn] = '%c'%(rbyte)
c=''.join(b)
return c
def startlog():
f = open(logfile_path,'w')
f.write('<?xml version="1.0" encoding="windows-1251" ?><ioctllog>')
f.close()
def writelog(data):
f = open(logfile_path,'a')
f.write(data)
f.close()
def sniff( dbg, args ):
'''
BOOL WINAPI DeviceIoControl(
_In_ HANDLE hDevice,
_In_ DWORD dwIoControlCode,
_In_opt_ LPVOID lpInBuffer,
_In_ DWORD nInBufferSize,
_Out_opt_ LPVOID lpOutBuffer,
_In_ DWORD nOutBufferSize,
_Out_opt_ LPDWORD lpBytesReturned,
_Inout_opt_ LPOVERLAPPED lpOverlapped
);
esp+4 -> 0 -> HANDLE hDevice
esp+8 -> 1 -> DWORD dwIoControlCode
esp+12-> 2 -> LPVOID lpInBuffer
esp+16-> 3 -> DWORD nInBufferSize
esp+20-> 4 -> LPVOID lpOutBuffer pointer
esp+24-> 5 -> DWORD nOutBufferSize
..
..
'''
log = "\n<ioentry>"
log += '\n<iocode>' + hex(args[1]) + '</iocode>'
print '[+] IOCTL Code : ',hex(args[1])
esp = dbg.context.Esp
if fuzz_in_size:
log+= '\n<inbufsize>' + hex(args[3]) + '</inbufsize>'
print '[+] Actual In-Buffer Size :',hex(args[3])
fsz = random.choice(fuzzed_size)
log+= '\n<fuzzinbufsize>' + fsz + '</fuzzinbufsize>'
print '[+] Fuzzed In-Buffer Size :' , fsz
dbg.write_process_memory( esp+0x10, fsz, 4)
else:
log+= '\n<inbufsize>' + hex(args[3]) + '</inbufsize>'
print '[+] Logging Mode : In-Buffer Size : ',hex(args[3])
if fuzz_op_size:
log+= '\n<outbufsize>' + hex(args[5]) + '</outbufsize>'
print '[+] Actual Out-Buffer Size :',hex(args[5])
fsz = random.choice(fuzzed_size)
log+= '\n<fuzzoutbufsize>' + fsz + '</fuzzoutbufsize>'
print '[+] Fuzzed Out-Buffer Size :' , fsz
dbg.write_process_memory( esp+0x18, fsz, 4)
else:
log+= '\n<outbufsize>' + hex(args[5]) + '</outbufsize>'
print '[+] Logging Mode : Out-Buffer Size : ',hex(args[5])
input_buffer = dbg.read_process_memory(args[2], int(args[3]))
if fuzz_input:
fuzzed_data = fuzzit(input_buffer)
log += '\n<inbuffdata>' + fuzzed_data.encode('hex') + '</inbuffdata>'
log += '\n<fuzzinbuffdata>' + formatit(fuzzed_data.encode('hex')) + '</fuzzinbuffdata>'
print '[+] Fuzzed Input-Buffer Data :',fuzzed_data.encode('hex')
else:
fuzzed_data = input_buffer
log += '\n<inbuffdata>' + formatit(fuzzed_data.encode('hex')) + '</inbuffdata>'
print '[+] Logging Mode : Input-Buffer Data :',fuzzed_data.encode('hex')
try:
dbg.write_process_memory( args[2], fuzzed_data, int(args[3])) #Writing fuzzed data into memory
except Exception, e:
log += '\n[+] Error : Cannot Write Fuzzed Data into memory!!'
print '[+] Error : Cannot Write Fuzzed Data into memory!!'
log += '</ioentry>'
print '\n\n'+'*'*50
if target_ioctl == "*":
writelog(log)
else:
if args[1] == target_ioctl:
writelog(log)
else:
print '[+] Skipping'
return DBG_CONTINUE
def parseconfig():
global proc_name,fuzz_input,fuzz_in_size,fuzz_op_size,target_ioctl
config = ConfigParser.ConfigParser()
try:
config.read(sys.argv[1])
proc_name = config.get('IOCTLFuzzerConfig', 'ProcessName', 0)
if_fuzz_input = config.get('IOCTLFuzzerConfig', 'FuzzInput', 0)
if if_fuzz_input == "True":
fuzz_input = True
else:
fuzz_input = False
if_fuzz_in_size = config.get('IOCTLFuzzerConfig', 'FuzzInSize', 0)
if if_fuzz_in_size == "True":
fuzz_in_size = True
else:
fuzz_in_size = False
if_fuzz_op_size = config.get('IOCTLFuzzerConfig', 'FuzzOutSize', 0)
if if_fuzz_op_size == "True":
fuzz_op_size = True
else:
fuzz_op_size = False
try:
target_ioctl = int(config.get('IOCTLFuzzerConfig', 'IoctlCodeToLog', 0),16)
except Exception,e:
target_ioctl = "*"
print '\t[*]Process to Hook :',proc_name
print '\t[*]Fuzz input buffer:',if_fuzz_input
print '\t[*]Fuzz input size :',if_fuzz_input
print '\t[*]Fuzz output buffer size :',if_fuzz_op_size
print '\t[*] IOCTL to Log ',target_ioctl
raw_input('[+] If above informations are corrects press enter to continue')
except Exception,e:
print '[+] Error Reading/Parsing Config file'
print '[+] Usage :python iofuzz.py ioconfig.conf'
exit()
def main():
parseconfig()
startlog()
dbg = pydbg()
hooks = utils.hook_container()
for (pid,name) in dbg.enumerate_processes():
if name == proc_name:
print '[+] Attaching to ',proc_name
try:
dbg.attach(pid)
except Exception,e:
print '[Error] Cannot Attach to process ',proc_name,pid
exit()
hook_address = dbg.func_resolve_debuggee("kernel32.dll","DeviceIoControl")
hooks.add( dbg, hook_address, 8, sniff, None )
dbg.run()
if __name__ == '__main__':
main()