#!/usr/bin/env python3 """ DNS Fuzzer using JRSFuzz by Javantea Oct 11, 2015 Based on SMTP Fuzzer using JRSFuzz by Javantea Oct 11, 2015 Based on SMTP Grammar Fuzzer by Javantea Sept 14, 2015 A very reasonable dumb fuzzer for DNS. It's a mutation fuzzer. Provide the following values to fuzz a binary file you have captured: python3 dns_jrsfuzz1.py host port filename If you get connection refused, try forcing the family using -4 or -6 for IPv4 or IPv6. TODO: Random transaction id Handle errors returned by the server. Monitors with GDB and ASAN integration. """ import jrsfuzz import sys import socket import select def main(): # This works on any DNS server but it won't work on certain types data = b'\xabL\x01 \x00\x01\x00\x00\x00\x00\x00\x01\x03www\x05Peach\x03edu\x00\x00\x01\x00\x01\x00\x00)\x10\x00\x00\x00\x00\x00\x00\x00' host, port = 'localhost', 53 family = socket.AF_UNSPEC socktype = socket.SOCK_DGRAM # TCP support if '-t' in sys.argv: socktype = socket.SOCK_STREAM sys.argv.remove('-t') #end if if '-4' in sys.argv: family = socket.AF_INET sys.argv.remove('-4') #end if if '-6' in sys.argv: family = socket.AF_INET6 sys.argv.remove('-6') #end if if len(sys.argv) > 1: host = sys.argv[1] #end if if len(sys.argv) > 2: port = int(sys.argv[2]) #end if dest = (host, port) gai = socket.getaddrinfo(host, port, family, socktype) if len(sys.argv) > 3: filename = sys.argv[3] data = open(filename, 'rb').read() #end if lines_output = len(data) * 256 print("%i outputs, %3.3f MB" % (lines_output, lines_output*len(data)/(1<<20)), file=sys.stderr) our_data = None for family, socktype, proto, canonname, addr in gai: try: s = socket.socket(family, socktype, proto) s.connect(addr) except Exception as e: print(e,) continue #end try our_data = (family, socktype, proto, canonname, addr) break #next family, socktype, proto, canonname, addr if our_data == None: print("Can't connect to dest", dest) #end if family, socktype, proto, canonname, addr = our_data prevResp = None for i in range(lines_output): x = jrsfuzz.JRSFuzz(data, i) # We might be sending 2 commands, but let it be. s = socket.socket(family, socktype, proto) s.connect(addr) try: s.send(x) except BrokenPipeError: print("Broken Pipe.", i, x) except ConnectionResetError: print("Conn Reset.", i, x) #end try f = select.select([s], [], [], 0.01) resp = b'' if len(f) > 0 and len(f[0]) > 0: try: resp = s.recv(1024) except ConnectionResetError: print("Conn Reset on recv.", i, x) resp = b'' #end try #end try print(resp) if resp != prevResp: print(i, x) prevResp = resp s.close() #next i #end def main() if __name__ == '__main__': main() #end if