Skip to content

Instantly share code, notes, and snippets.

@FrankSpierings
Created February 12, 2024 06:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save FrankSpierings/6cd848fc2f368f54cb762eda8696a3fc to your computer and use it in GitHub Desktop.
Save FrankSpierings/6cd848fc2f368f54cb762eda8696a3fc to your computer and use it in GitHub Desktop.
Impacket - Print NTLM packets in JSON format for further analysis
import datetime
import json
from impacket.structure import Structure
from enum import Flag, Enum
class NegotiateFlags(Flag):
NTLMSSP_NEGOTIATE_56 = 0x80000000
NTLMSSP_NEGOTIATE_KEY_EXCH = 0x40000000
NTLMSSP_NEGOTIATE_128 = 0x20000000
NTLMSSP_RESERVED_1 = 0x10000000
NTLMSSP_RESERVED_2 = 0x08000000
NTLMSSP_RESERVED_3 = 0x04000000
NTLMSSP_NEGOTIATE_VERSION = 0x02000000
NTLMSSP_RESERVED_4 = 0x01000000
NTLMSSP_NEGOTIATE_TARGET_INFO = 0x00800000
NTLMSSP_REQUEST_NON_NT_SESSION_KEY = 0x00400000
NTLMSSP_RESERVED_5 = 0x00200000
NTLMSSP_NEGOTIATE_IDENTIFY = 0x00100000
NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY = 0x00080000
NTLMSSP_NEGOTIATE_NTLM2 = 0x00080000
NTLMSSP_TARGET_TYPE_SHARE = 0x00040000
NTLMSSP_TARGET_TYPE_SERVER = 0x00020000
NTLMSSP_TARGET_TYPE_DOMAIN = 0x00010000
NTLMSSP_NEGOTIATE_ALWAYS_SIGN = 0x00008000
NTLMSSP_RESERVED_6 = 0x00004000
NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED = 0x00002000
NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED = 0x00001000
NTLMSSP_NEGOTIATE_ANONYMOUS = 0x00000800
NTLMSSP_NEGOTIATE_NT_ONLY = 0x00000400
NTLMSSP_NEGOTIATE_NTLM = 0x00000200
NTLMSSP_RESERVED_8 = 0x00000100
NTLMSSP_NEGOTIATE_LM_KEY = 0x00000080
NTLMSSP_NEGOTIATE_DATAGRAM = 0x00000040
NTLMSSP_NEGOTIATE_SEAL = 0x00000020
NTLMSSP_NEGOTIATE_SIGN = 0x00000010
NTLMSSP_RESERVED_9 = 0x00000008
NTLMSSP_REQUEST_TARGET = 0x00000004
NTLM_NEGOTIATE_OEM = 0x00000002
NTLMSSP_NEGOTIATE_UNICODE = 0x00000001
class NTLMSSP_AV(Enum):
EOL = 0x00
HOSTNAME = 0x01
DOMAINNAME = 0x02
DNS_HOSTNAME = 0x03
DNS_DOMAINNAME = 0x04
DNS_TREENAME = 0x05
FLAGS = 0x06
TIME = 0x07
RESTRICTIONS = 0x08
TARGET_NAME = 0x09
CHANNEL_BINDINGS = 0x0a
class NTLMv2_CLIENT_CHALLENGE(Structure):
structure = (
('RespType', '<B=1'),
('HiRespType', '<B=1'),
('Reserved1', '<H=0'),
('Reserved2', '<I=0'),
('TimeStamp', '<q=0'),
('ChallengeFromClient', '8s'),
('Reserved3', '<I=0'),
('AvPairs', ":")
)
def filetime_to_datetime(filetime):
filetime_int = int.from_bytes(filetime, byteorder='little')
seconds_since_epoch = (filetime_int - 116444736000000000) / 10000000
return datetime.datetime.utcfromtimestamp(seconds_since_epoch)
def serialize_avpairs(av_pairs):
data = {}
for nr in av_pairs.fields:
av_type = NTLMSSP_AV(nr)
av_value = av_pairs.fields[nr][1]
if av_type not in [NTLMSSP_AV.EOL, NTLMSSP_AV.FLAGS, NTLMSSP_AV.TIME, NTLMSSP_AV.RESTRICTIONS, NTLMSSP_AV.CHANNEL_BINDINGS]:
data[av_type.name] = av_value.decode("utf-16-le")
elif av_type in [NTLMSSP_AV.TIME]:
data[av_type.name] = str(filetime_to_datetime(av_value))
else:
try:
data[av_type.name] = av_value.decode()
except:
data[av_type.name] = repr(av_value)
return data
def json_ntlmssp(structure):
data = {}
for field in structure.fields:
value = structure.fields[field]
if field in ['user_name', 'domain_name', 'host_name']:
try:
data[field] = value.decode("utf-16-le")
except:
data[field] = value
elif field in ['flags']:
data[field] = []
flag = NegotiateFlags(value)
for attribute in flag:
data[field].append(attribute.name)
elif field in ['session_key', 'lanman', 'challenge', 'MIC', 'reserved', 'Reserved']:
try:
data[field] = value.hex()
except:
data[field] = value
elif field in ['Version']:
data[field] = {}
version = VERSION(value)
for vfield in version.fields:
data[field][vfield] = version.fields[vfield]
elif field in ['TargetInfoFields']:
output = f'{field}: '
av_pairs = AV_PAIRS(value)
data[field] = serialize_avpairs(av_pairs)
elif field in ['ntlm']:
response = value[:16]
data[field] = {}
data[field]['Response'] = response.hex()
data[field]['Challenge'] = {}
challenge = NTLMv2_CLIENT_CHALLENGE(value[16:])
for cfield in challenge.fields:
cvalue = challenge.fields[cfield]
if cfield in ['ChallengeFromClient']:
data[field]['Challenge'][cfield] = cvalue.hex()
elif cfield not in ['AvPairs']:
data[field]['Challenge'][cfield] = cvalue
else:
av_pairs = AV_PAIRS(cvalue)
data[field]['Challenge'][cfield] = serialize_avpairs(av_pairs)
else:
data[field] = value
return json.dumps(data, indent=True, default=str)
print(json_ntlmssp(self))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment