|
|
0a5818e |
# Proxyfuzz - On the fly TCP and UDP network fuzzer
|
|
|
0a5818e |
# Copyright (C) 2011 Rodrigo Marcos
|
|
|
0a5818e |
#
|
|
|
0a5818e |
# This program is free software: you can redistribute it and/or modify
|
|
|
0a5818e |
# it under the terms of the GNU General Public License as published by
|
|
|
0a5818e |
# the Free Software Foundation, either version 3 of the License, or
|
|
|
0a5818e |
# (at your option) any later version.
|
|
|
0a5818e |
#
|
|
|
0a5818e |
# This program is distributed in the hope that it will be useful,
|
|
|
0a5818e |
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
0a5818e |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
0a5818e |
# GNU General Public License for more details.
|
|
|
0a5818e |
#
|
|
|
0a5818e |
# You should have received a copy of the GNU General Public License
|
|
|
0a5818e |
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
0a5818e |
#
|
|
|
0a5818e |
# Proxyfuzz: a TCP and UDP proxy man-in-the-middle fuzzer
|
|
|
0a5818e |
# v 0.1
|
|
|
0a5818e |
# By Rodrigo Marcos
|
|
|
0a5818e |
# http://www.secforce.co.uk
|
|
|
0a5818e |
|
|
|
0a5818e |
from twisted.protocols import portforward
|
|
|
0a5818e |
from twisted.internet.protocol import DatagramProtocol
|
|
|
0a5818e |
from twisted.internet import reactor
|
|
|
0a5818e |
import getopt, sys
|
|
|
0a5818e |
from random import randint
|
|
|
0a5818e |
|
|
|
0a5818e |
|
|
|
0a5818e |
# UDP Proxy stuff
|
|
|
0a5818e |
|
|
|
0a5818e |
class Client(DatagramProtocol):
|
|
|
0a5818e |
def __init__(self, server, host, port):
|
|
|
0a5818e |
self.server = server
|
|
|
0a5818e |
self.host = host
|
|
|
0a5818e |
self.port = port
|
|
|
0a5818e |
|
|
|
0a5818e |
def startProtocol(self):
|
|
|
0a5818e |
self.transport.connect(desthost, destport)
|
|
|
0a5818e |
|
|
|
0a5818e |
def datagramReceived(self, data, (host, port)):
|
|
|
0a5818e |
global verbose
|
|
|
0a5818e |
global notuntil
|
|
|
0a5818e |
global request
|
|
|
0a5818e |
global testclient
|
|
|
0a5818e |
|
|
|
0a5818e |
if testclient:
|
|
|
0a5818e |
if request < notuntil:
|
|
|
0a5818e |
request = request + 1
|
|
|
0a5818e |
else:
|
|
|
0a5818e |
data = fuzz(data)
|
|
|
0a5818e |
if verbose:
|
|
|
0a5818e |
print "Server ------> Client"
|
|
|
0a5818e |
print "%r" % data
|
|
|
0a5818e |
|
|
|
0a5818e |
self.server.transport.write(data, (self.host, self.port))
|
|
|
0a5818e |
|
|
|
0a5818e |
class Server(DatagramProtocol):
|
|
|
0a5818e |
client = None
|
|
|
0a5818e |
|
|
|
0a5818e |
def datagramReceived(self, data, (host, port)):
|
|
|
0a5818e |
if not self.client or self.client.host != host or self.client.port != port:
|
|
|
0a5818e |
self.client = Client(self, host, port)
|
|
|
0a5818e |
reactor.listenUDP(0, self.client)
|
|
|
0a5818e |
|
|
|
0a5818e |
global verbose
|
|
|
0a5818e |
global notuntil
|
|
|
0a5818e |
global request
|
|
|
0a5818e |
global testserver
|
|
|
0a5818e |
|
|
|
0a5818e |
if testserver:
|
|
|
0a5818e |
if request < notuntil:
|
|
|
0a5818e |
request = request + 1
|
|
|
0a5818e |
else:
|
|
|
0a5818e |
data = fuzz(data)
|
|
|
0a5818e |
if verbose:
|
|
|
0a5818e |
print "Client ------> Server"
|
|
|
0a5818e |
print "%r" % data
|
|
|
0a5818e |
self.client.transport.write(data, (desthost, destport))
|
|
|
0a5818e |
|
|
|
0a5818e |
# TCP proxy stuff
|
|
|
0a5818e |
|
|
|
0a5818e |
def server_dataReceived(self, data):
|
|
|
0a5818e |
global verbose
|
|
|
0a5818e |
global notuntil
|
|
|
0a5818e |
global request
|
|
|
0a5818e |
global testserver
|
|
|
0a5818e |
|
|
|
0a5818e |
if testserver:
|
|
|
0a5818e |
if request < notuntil:
|
|
|
0a5818e |
request = request + 1
|
|
|
0a5818e |
else:
|
|
|
0a5818e |
data = fuzz(data)
|
|
|
0a5818e |
|
|
|
0a5818e |
if verbose:
|
|
|
0a5818e |
print "Client ------> server"
|
|
|
0a5818e |
print "%r" % data
|
|
|
0a5818e |
|
|
|
0a5818e |
portforward.Proxy.dataReceived(self, data)
|
|
|
0a5818e |
|
|
|
0a5818e |
portforward.ProxyServer.dataReceived = server_dataReceived
|
|
|
0a5818e |
|
|
|
0a5818e |
def client_dataReceived(self, data):
|
|
|
0a5818e |
global verbose
|
|
|
0a5818e |
global notuntil
|
|
|
0a5818e |
global request
|
|
|
0a5818e |
global testclient
|
|
|
0a5818e |
|
|
|
0a5818e |
if testclient:
|
|
|
0a5818e |
if request < notuntil:
|
|
|
0a5818e |
request = request + 1
|
|
|
0a5818e |
else:
|
|
|
0a5818e |
data = fuzz(data)
|
|
|
0a5818e |
if verbose:
|
|
|
0a5818e |
print "Server ------> Client"
|
|
|
0a5818e |
print "%r" % data
|
|
|
0a5818e |
|
|
|
0a5818e |
portforward.Proxy.dataReceived(self, data)
|
|
|
0a5818e |
|
|
|
0a5818e |
portforward.ProxyClient.dataReceived = client_dataReceived
|
|
|
0a5818e |
|
|
|
0a5818e |
|
|
|
0a5818e |
overflowstrings = ["A" * 255, "A" * 256, "A" * 257, "A" * 420, "A" * 511, "A" * 512, "A" * 1023, "A" * 1024, "A" * 2047, "A" * 2048, "A" * 4096, "A" * 4097, "A" * 5000, "A" * 10000, "A" * 20000, "A" * 32762, "A" * 32763, "A" * 32764, "A" * 32765, "A" * 32766, "A" * 32767, "A" * 32768, "A" * 65534, "A" * 65535, "A" * 65536, "%x" * 1024, "%n" * 1025 , "%s" * 2048, "%s%n%x%d" * 5000, "%s" * 30000, "%s" * 40000, "%.1024d", "%.2048d", "%.4096d", "%.8200d", "%99999999999s", "%99999999999d", "%99999999999x", "%99999999999n", "%99999999999s" * 1000, "%99999999999d" * 1000, "%99999999999x" * 1000, "%99999999999n" * 1000, "%08x" * 100, "%%20s" * 1000,"%%20x" * 1000,"%%20n" * 1000,"%%20d" * 1000, "%#0123456x%08x%x%s%p%n%d%o%u%c%h%l%q%j%z%Z%t%i%e%g%f%a%C%S%08x%%#0123456x%%x%%s%%p%%n%%d%%o%%u%%c%%h%%l%%q%%j%%z%%Z%%t%%i%%e%%g%%f%%a%%C%%S%%08x"]
|
|
|
0a5818e |
|
|
|
0a5818e |
def bitflipping(data):
|
|
|
0a5818e |
l = len(data)
|
|
|
0a5818e |
n = int(l*7/100) # 7% of the bytes to be modified
|
|
|
0a5818e |
|
|
|
0a5818e |
for i in range(0,n): # We change the bytes
|
|
|
0a5818e |
r = randint(0,l-1)
|
|
|
0a5818e |
data = data[0:r] + chr(randint(0,255)) + data[r+1:]
|
|
|
0a5818e |
return data
|
|
|
0a5818e |
|
|
|
0a5818e |
def bofinjection(data):
|
|
|
0a5818e |
l = len(data)
|
|
|
0a5818e |
r = randint(0,len(overflowstrings)-1)
|
|
|
0a5818e |
data = data[0:r] + overflowstrings[r] + data[r-l:]
|
|
|
0a5818e |
return data
|
|
|
0a5818e |
|
|
|
0a5818e |
def fuzz(data):
|
|
|
0a5818e |
|
|
|
0a5818e |
r = randint(0,5)
|
|
|
0a5818e |
if r==0:
|
|
|
0a5818e |
data = bitflipping(data)
|
|
|
0a5818e |
|
|
|
0a5818e |
r = randint(0,5)
|
|
|
0a5818e |
if r==0:
|
|
|
0a5818e |
data = bofinjection(data)
|
|
|
0a5818e |
return data
|
|
|
0a5818e |
|
|
|
0a5818e |
def startudpproxy():
|
|
|
0a5818e |
reactor.listenUDP(localport, Server())
|
|
|
0a5818e |
reactor.run()
|
|
|
0a5818e |
|
|
|
0a5818e |
def starttcpproxy():
|
|
|
0a5818e |
reactor.listenTCP(localport, portforward.ProxyFactory(desthost, destport))
|
|
|
0a5818e |
reactor.run()
|
|
|
0a5818e |
|
|
|
0a5818e |
def usage():
|
|
|
0a5818e |
#print "###############################################################"
|
|
|
0a5818e |
print
|
|
|
0a5818e |
print "ProxyFuzz 0.1, Simple fuzzing proxy by Rodrigo Marcos"
|
|
|
0a5818e |
print "http://www.secforce.co.uk"
|
|
|
0a5818e |
print
|
|
|
0a5818e |
print "usage():"
|
|
|
0a5818e |
#print
|
|
|
0a5818e |
print "python proxyfuzz -l <localport> -r <remotehost> -p <remoteport> [options]"
|
|
|
0a5818e |
print
|
|
|
0a5818e |
print " [options]"
|
|
|
0a5818e |
print " -c: Fuzz only client side (both otherwise)"
|
|
|
0a5818e |
print " -s: Fuzz only server side (both otherwise)"
|
|
|
0a5818e |
print " -w: Number of requests to send before start fuzzing"
|
|
|
0a5818e |
print " -u: UDP protocol (otherwise TCP is used)"
|
|
|
0a5818e |
print " -v: Verbose (outputs network traffic)"
|
|
|
0a5818e |
print " -h: Help page"
|
|
|
0a5818e |
|
|
|
0a5818e |
|
|
|
0a5818e |
verbose = False
|
|
|
0a5818e |
notuntil = 0
|
|
|
0a5818e |
request = 0
|
|
|
0a5818e |
proto = "tcp"
|
|
|
0a5818e |
localport = 0
|
|
|
0a5818e |
desthost = ""
|
|
|
0a5818e |
destport = 0
|
|
|
0a5818e |
testclient = 1
|
|
|
0a5818e |
testserver = 1
|
|
|
0a5818e |
def main():
|
|
|
0a5818e |
global verbose
|
|
|
0a5818e |
global notuntil
|
|
|
0a5818e |
global proto
|
|
|
0a5818e |
global localport
|
|
|
0a5818e |
global desthost
|
|
|
0a5818e |
global destport
|
|
|
0a5818e |
global testclient
|
|
|
0a5818e |
global testserver
|
|
|
0a5818e |
|
|
|
0a5818e |
try:
|
|
|
0a5818e |
opts, args = getopt.getopt(sys.argv[1:], "uvhcsl:r:p:w:", ["help"])
|
|
|
0a5818e |
except getopt.GetoptError:
|
|
|
0a5818e |
usage()
|
|
|
0a5818e |
sys.exit(2)
|
|
|
0a5818e |
try:
|
|
|
0a5818e |
for o, a in opts:
|
|
|
0a5818e |
if o in ("-h", "--help"):
|
|
|
0a5818e |
usage()
|
|
|
0a5818e |
sys.exit()
|
|
|
0a5818e |
if o == "-l":
|
|
|
0a5818e |
localport=int(a)
|
|
|
0a5818e |
if o == "-r":
|
|
|
0a5818e |
desthost=a
|
|
|
0a5818e |
if o == "-p":
|
|
|
0a5818e |
destport=int(a)
|
|
|
0a5818e |
if o == "-v":
|
|
|
0a5818e |
verbose = True
|
|
|
0a5818e |
if o == "-w":
|
|
|
0a5818e |
notuntil=int(a)
|
|
|
0a5818e |
if o == "-u":
|
|
|
0a5818e |
proto="udp"
|
|
|
0a5818e |
if o == "-c": # Only client
|
|
|
0a5818e |
testserver=0
|
|
|
0a5818e |
if o == "-s": # Only server
|
|
|
0a5818e |
testclient=0
|
|
|
0a5818e |
|
|
|
0a5818e |
|
|
|
0a5818e |
except:
|
|
|
0a5818e |
usage()
|
|
|
0a5818e |
sys.exit(2)
|
|
|
0a5818e |
|
|
|
0a5818e |
if testserver==0 and testclient==0:
|
|
|
0a5818e |
usage()
|
|
|
0a5818e |
sys.exit(2)
|
|
|
0a5818e |
elif localport==0 or desthost=="" or destport==0:
|
|
|
0a5818e |
usage()
|
|
|
0a5818e |
sys.exit(2)
|
|
|
0a5818e |
else:
|
|
|
0a5818e |
if proto=="tcp":
|
|
|
0a5818e |
starttcpproxy()
|
|
|
0a5818e |
else: # UDP
|
|
|
0a5818e |
startudpproxy()
|
|
|
0a5818e |
|
|
|
0a5818e |
if __name__ == "__main__":
|
|
|
0a5818e |
main()
|
|
|
0a5818e |
|
|
|
0a5818e |
|