MITMf/core/protocols/ldap/LDAPPackets.py
byt3bl33d3r 9712eed4a3 This is 1/2 of the work done... lot's of cool stuff!
I've re-written a decent amount of the framework to support dynamic config file updates, revamped the ARP Spoofing 'engine' and changed the way MITMf integrates Responder and Netcreds.

- Net-creds is now started by default and no longer a plugin.. It's all about getting those creds after all.
- Integrated the Subterfuge Framework's ARPWatch script, it will enable itself when spoofing the whole subnet (also squashed bugs in the original ARP spoofing code)
- The spoof plugin now supports specifying a range of targets (e.g. --target 10.10.10.1-15) and multiple targets (e.g. --target 10.10.10.1,10.10.10.2)
- An SMB Server is now started by default, MITMf now uses Impacket's SMBserver as supposed to the one built into Responder, mainly for 2 reasons:
  1) Impacket is moving towards SMB2 support and is actively developed
  2) Impacket's SMB server is fully functional as supposed to Responder's (will be adding a section for it in the config file)
  3) Responder's SMB server was unrealiable when used through MITMf (After spending a day trying to figure out why, I just gave up and yanked it out)

- Responder's code has been broken down into single importable classes (way easier to manage and read, ugh!)
- Started adding dynamic config support to Responder's code and changed the logging messages to be a bit more readable.
- POST data captured through the proxy will now only be logged and printed to STDOUT when it's decodable to UTF-8 (this prevents logging encrypted data which is no use)
- Responder and the Beefapi script are no longer submodules (they seem to be a pain to package, so i removed them to help a brother out)
- Some plugins are missing because I'm currently re-writing them, will be added later
- Main plugin class now inharates from the ConfigWatcher class, this way plugins will support dynamic configs natively! \o/
2015-04-27 18:33:55 +02:00

238 lines
14 KiB
Python

#! /usr/bin/env python
# NBT-NS/LLMNR Responder
# Created by Laurent Gaffie
# Copyright (C) 2014 Trustwave Holdings, Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import struct
from odict import OrderedDict
class Packet():
fields = OrderedDict([
("data", ""),
])
def __init__(self, **kw):
self.fields = OrderedDict(self.__class__.fields)
for k,v in 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()))
class LDAPSearchDefaultPacket(Packet):
fields = OrderedDict([
("ParserHeadASNID", "\x30"),
("ParserHeadASNLen", "\x0c"),
("MessageIDASNID", "\x02"),
("MessageIDASNLen", "\x01"),
("MessageIDASNStr", "\x0f"),
("OpHeadASNID", "\x65"),
("OpHeadASNIDLen", "\x07"),
("SearchDoneSuccess", "\x0A\x01\x00\x04\x00\x04\x00"),#No Results.
])
class LDAPSearchSupportedCapabilitiesPacket(Packet):
fields = OrderedDict([
("ParserHeadASNID", "\x30"),
("ParserHeadASNLenOfLen", "\x84"),
("ParserHeadASNLen", "\x00\x00\x00\x7e"),#126
("MessageIDASNID", "\x02"),
("MessageIDASNLen", "\x01"),
("MessageIDASNStr", "\x02"),
("OpHeadASNID", "\x64"),
("OpHeadASNIDLenOfLen", "\x84"),
("OpHeadASNIDLen", "\x00\x00\x00\x75"),#117
("ObjectName", "\x04\x00"),
("SearchAttribASNID", "\x30"),
("SearchAttribASNLenOfLen", "\x84"),
("SearchAttribASNLen", "\x00\x00\x00\x6d"),#109
("SearchAttribASNID1", "\x30"),
("SearchAttribASN1LenOfLen", "\x84"),
("SearchAttribASN1Len", "\x00\x00\x00\x67"),#103
("SearchAttribASN2ID", "\x04"),
("SearchAttribASN2Len", "\x15"),#21
("SearchAttribASN2Str", "supportedCapabilities"),
("SearchAttribASN3ID", "\x31"),
("SearchAttribASN3LenOfLen", "\x84"),
("SearchAttribASN3Len", "\x00\x00\x00\x4a"),
("SearchAttrib1ASNID", "\x04"),
("SearchAttrib1ASNLen", "\x16"),#22
("SearchAttrib1ASNStr", "1.2.840.113556.1.4.800"),
("SearchAttrib2ASNID", "\x04"),
("SearchAttrib2ASNLen", "\x17"),#23
("SearchAttrib2ASNStr", "1.2.840.113556.1.4.1670"),
("SearchAttrib3ASNID", "\x04"),
("SearchAttrib3ASNLen", "\x17"),#23
("SearchAttrib3ASNStr", "1.2.840.113556.1.4.1791"),
("SearchDoneASNID", "\x30"),
("SearchDoneASNLenOfLen", "\x84"),
("SearchDoneASNLen", "\x00\x00\x00\x10"),#16
("MessageIDASN2ID", "\x02"),
("MessageIDASN2Len", "\x01"),
("MessageIDASN2Str", "\x02"),
("SearchDoneStr", "\x65\x84\x00\x00\x00\x07\x0a\x01\x00\x04\x00\x04\x00"),
## No need to calculate anything this time, this packet is generic.
])
class LDAPSearchSupportedMechanismsPacket(Packet):
fields = OrderedDict([
("ParserHeadASNID", "\x30"),
("ParserHeadASNLenOfLen", "\x84"),
("ParserHeadASNLen", "\x00\x00\x00\x60"),#96
("MessageIDASNID", "\x02"),
("MessageIDASNLen", "\x01"),
("MessageIDASNStr", "\x02"),
("OpHeadASNID", "\x64"),
("OpHeadASNIDLenOfLen", "\x84"),
("OpHeadASNIDLen", "\x00\x00\x00\x57"),#87
("ObjectName", "\x04\x00"),
("SearchAttribASNID", "\x30"),
("SearchAttribASNLenOfLen", "\x84"),
("SearchAttribASNLen", "\x00\x00\x00\x4f"),#79
("SearchAttribASNID1", "\x30"),
("SearchAttribASN1LenOfLen", "\x84"),
("SearchAttribASN1Len", "\x00\x00\x00\x49"),#73
("SearchAttribASN2ID", "\x04"),
("SearchAttribASN2Len", "\x17"),#23
("SearchAttribASN2Str", "supportedSASLMechanisms"),
("SearchAttribASN3ID", "\x31"),
("SearchAttribASN3LenOfLen", "\x84"),
("SearchAttribASN3Len", "\x00\x00\x00\x2a"),#42
("SearchAttrib1ASNID", "\x04"),
("SearchAttrib1ASNLen", "\x06"),#6
("SearchAttrib1ASNStr", "GSSAPI"),
("SearchAttrib2ASNID", "\x04"),
("SearchAttrib2ASNLen", "\x0a"),#10
("SearchAttrib2ASNStr", "GSS-SPNEGO"),
("SearchAttrib3ASNID", "\x04"),
("SearchAttrib3ASNLen", "\x08"),#8
("SearchAttrib3ASNStr", "EXTERNAL"),
("SearchAttrib4ASNID", "\x04"),
("SearchAttrib4ASNLen", "\x0a"),#10
("SearchAttrib4ASNStr", "DIGEST-MD5"),
("SearchDoneASNID", "\x30"),
("SearchDoneASNLenOfLen", "\x84"),
("SearchDoneASNLen", "\x00\x00\x00\x10"),#16
("MessageIDASN2ID", "\x02"),
("MessageIDASN2Len", "\x01"),
("MessageIDASN2Str", "\x02"),
("SearchDoneStr", "\x65\x84\x00\x00\x00\x07\x0a\x01\x00\x04\x00\x04\x00"),
## No need to calculate anything this time, this packet is generic.
])
class LDAPNTLMChallenge(Packet):
fields = OrderedDict([
("ParserHeadASNID", "\x30"),
("ParserHeadASNLenOfLen", "\x84"),
("ParserHeadASNLen", "\x00\x00\x00\xD0"),#208
("MessageIDASNID", "\x02"),
("MessageIDASNLen", "\x01"),
("MessageIDASNStr", "\x02"),
("OpHeadASNID", "\x61"),
("OpHeadASNIDLenOfLen", "\x84"),
("OpHeadASNIDLen", "\x00\x00\x00\xc7"),#199
("Status", "\x0A"),
("StatusASNLen", "\x01"),
("StatusASNStr", "\x0e"), #In Progress.
("MatchedDN", "\x04\x00"), #Null
("ErrorMessage", "\x04\x00"), #Null
("SequenceHeader", "\x87"),
("SequenceHeaderLenOfLen", "\x81"),
("SequenceHeaderLen", "\x82"), #188
("NTLMSSPSignature", "NTLMSSP"),
("NTLMSSPSignatureNull", "\x00"),
("NTLMSSPMessageType", "\x02\x00\x00\x00"),
("NTLMSSPNtWorkstationLen","\x1e\x00"),
("NTLMSSPNtWorkstationMaxLen","\x1e\x00"),
("NTLMSSPNtWorkstationBuffOffset","\x38\x00\x00\x00"),
("NTLMSSPNtNegotiateFlags","\x15\x82\x89\xe2"),
("NTLMSSPNtServerChallenge","\x81\x22\x33\x34\x55\x46\xe7\x88"),
("NTLMSSPNtReserved","\x00\x00\x00\x00\x00\x00\x00\x00"),
("NTLMSSPNtTargetInfoLen","\x94\x00"),
("NTLMSSPNtTargetInfoMaxLen","\x94\x00"),
("NTLMSSPNtTargetInfoBuffOffset","\x56\x00\x00\x00"),
("NegTokenInitSeqMechMessageVersionHigh","\x05"),
("NegTokenInitSeqMechMessageVersionLow","\x02"),
("NegTokenInitSeqMechMessageVersionBuilt","\xce\x0e"),
("NegTokenInitSeqMechMessageVersionReserved","\x00\x00\x00"),
("NegTokenInitSeqMechMessageVersionNTLMType","\x0f"),
("NTLMSSPNtWorkstationName","SMB12"),
("NTLMSSPNTLMChallengeAVPairsId","\x02\x00"),
("NTLMSSPNTLMChallengeAVPairsLen","\x0a\x00"),
("NTLMSSPNTLMChallengeAVPairsUnicodeStr","smb12"),
("NTLMSSPNTLMChallengeAVPairs1Id","\x01\x00"),
("NTLMSSPNTLMChallengeAVPairs1Len","\x1e\x00"),
("NTLMSSPNTLMChallengeAVPairs1UnicodeStr","SERVER2008"),
("NTLMSSPNTLMChallengeAVPairs2Id","\x04\x00"),
("NTLMSSPNTLMChallengeAVPairs2Len","\x1e\x00"),
("NTLMSSPNTLMChallengeAVPairs2UnicodeStr","smb12.local"),
("NTLMSSPNTLMChallengeAVPairs3Id","\x03\x00"),
("NTLMSSPNTLMChallengeAVPairs3Len","\x1e\x00"),
("NTLMSSPNTLMChallengeAVPairs3UnicodeStr","SERVER2008.smb12.local"),
("NTLMSSPNTLMChallengeAVPairs5Id","\x05\x00"),
("NTLMSSPNTLMChallengeAVPairs5Len","\x04\x00"),
("NTLMSSPNTLMChallengeAVPairs5UnicodeStr","smb12.local"),
("NTLMSSPNTLMChallengeAVPairs6Id","\x00\x00"),
("NTLMSSPNTLMChallengeAVPairs6Len","\x00\x00"),
])
def calculate(self):
##Convert strings to Unicode first...
self.fields["NTLMSSPNtWorkstationName"] = self.fields["NTLMSSPNtWorkstationName"].encode('utf-16le')
self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"].encode('utf-16le')
self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"].encode('utf-16le')
self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"].encode('utf-16le')
self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"].encode('utf-16le')
self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"] = self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"].encode('utf-16le')
###### Workstation Offset
CalculateOffsetWorkstation = str(self.fields["NTLMSSPSignature"])+str(self.fields["NTLMSSPSignatureNull"])+str(self.fields["NTLMSSPMessageType"])+str(self.fields["NTLMSSPNtWorkstationLen"])+str(self.fields["NTLMSSPNtWorkstationMaxLen"])+str(self.fields["NTLMSSPNtWorkstationBuffOffset"])+str(self.fields["NTLMSSPNtNegotiateFlags"])+str(self.fields["NTLMSSPNtServerChallenge"])+str(self.fields["NTLMSSPNtReserved"])+str(self.fields["NTLMSSPNtTargetInfoLen"])+str(self.fields["NTLMSSPNtTargetInfoMaxLen"])+str(self.fields["NTLMSSPNtTargetInfoBuffOffset"])+str(self.fields["NegTokenInitSeqMechMessageVersionHigh"])+str(self.fields["NegTokenInitSeqMechMessageVersionLow"])+str(self.fields["NegTokenInitSeqMechMessageVersionBuilt"])+str(self.fields["NegTokenInitSeqMechMessageVersionReserved"])+str(self.fields["NegTokenInitSeqMechMessageVersionNTLMType"])
###### AvPairs Offset
CalculateLenAvpairs = str(self.fields["NTLMSSPNTLMChallengeAVPairsId"])+str(self.fields["NTLMSSPNTLMChallengeAVPairsLen"])+str(self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs1Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs1Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs2Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs2Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs3Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs3Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs5Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs5Len"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"])+(self.fields["NTLMSSPNTLMChallengeAVPairs6Id"])+str(self.fields["NTLMSSPNTLMChallengeAVPairs6Len"])
###### LDAP Packet Len
CalculatePacketLen = str(self.fields["MessageIDASNID"])+str(self.fields["MessageIDASNLen"])+str(self.fields["MessageIDASNStr"])+str(self.fields["OpHeadASNID"])+str(self.fields["OpHeadASNIDLenOfLen"])+str(self.fields["OpHeadASNIDLen"])+str(self.fields["Status"])+str(self.fields["StatusASNLen"])+str(self.fields["StatusASNStr"])+str(self.fields["MatchedDN"])+str(self.fields["ErrorMessage"])+str(self.fields["SequenceHeader"])+str(self.fields["SequenceHeaderLen"])+str(self.fields["SequenceHeaderLenOfLen"])+CalculateOffsetWorkstation+str(self.fields["NTLMSSPNtWorkstationName"])+CalculateLenAvpairs
OperationPacketLen = str(self.fields["Status"])+str(self.fields["StatusASNLen"])+str(self.fields["StatusASNStr"])+str(self.fields["MatchedDN"])+str(self.fields["ErrorMessage"])+str(self.fields["SequenceHeader"])+str(self.fields["SequenceHeaderLen"])+str(self.fields["SequenceHeaderLenOfLen"])+CalculateOffsetWorkstation+str(self.fields["NTLMSSPNtWorkstationName"])+CalculateLenAvpairs
NTLMMessageLen = CalculateOffsetWorkstation+str(self.fields["NTLMSSPNtWorkstationName"])+CalculateLenAvpairs
##### LDAP Len Calculation:
self.fields["ParserHeadASNLen"] = struct.pack(">i", len(CalculatePacketLen))
self.fields["OpHeadASNIDLen"] = struct.pack(">i", len(OperationPacketLen))
self.fields["SequenceHeaderLen"] = struct.pack(">B", len(NTLMMessageLen))
##### Workstation Offset Calculation:
self.fields["NTLMSSPNtWorkstationBuffOffset"] = struct.pack("<i", len(CalculateOffsetWorkstation))
self.fields["NTLMSSPNtWorkstationLen"] = struct.pack("<h", len(str(self.fields["NTLMSSPNtWorkstationName"])))
self.fields["NTLMSSPNtWorkstationMaxLen"] = struct.pack("<h", len(str(self.fields["NTLMSSPNtWorkstationName"])))
##### IvPairs Offset Calculation:
self.fields["NTLMSSPNtTargetInfoBuffOffset"] = struct.pack("<i", len(CalculateOffsetWorkstation+str(self.fields["NTLMSSPNtWorkstationName"])))
self.fields["NTLMSSPNtTargetInfoLen"] = struct.pack("<h", len(CalculateLenAvpairs))
self.fields["NTLMSSPNtTargetInfoMaxLen"] = struct.pack("<h", len(CalculateLenAvpairs))
##### IvPair Calculation:
self.fields["NTLMSSPNTLMChallengeAVPairs5Len"] = struct.pack("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs5UnicodeStr"])))
self.fields["NTLMSSPNTLMChallengeAVPairs3Len"] = struct.pack("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs3UnicodeStr"])))
self.fields["NTLMSSPNTLMChallengeAVPairs2Len"] = struct.pack("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs2UnicodeStr"])))
self.fields["NTLMSSPNTLMChallengeAVPairs1Len"] = struct.pack("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairs1UnicodeStr"])))
self.fields["NTLMSSPNTLMChallengeAVPairsLen"] = struct.pack("<h", len(str(self.fields["NTLMSSPNTLMChallengeAVPairsUnicodeStr"])))