Files
fortra-impacket/examples/DumpNTLMInfo.py
T
Gabriel Gonzalez ae0ec300f8 Techdebt examples bootstrapping v2 (#1928)
* Standardized examples logger init method

* Fixing missing import

* Standardized examples init_ldap_session function #1

* Calling new shared function _ldap3_kerberos_login from example addcomputer

* Removed considering -debug in each example. Now it's handled in utils.

* Standardized EMPTY_LM_HASH in impacket.examples.utils

* Unify parse_identity function (phase 1)

* Standardized parse_identity

* Renamed "_ldap3_kerberos_login" to "ldap3_kerberos_login" (as it is called from outside)

* Standardize "logger" init in regsecrets.py

* Standardized LDAP login into a single function in utils.py:ldap_login
2025-03-26 22:58:39 -03:00

676 lines
29 KiB
Python

#!/usr/bin/env python
# Impacket - Collection of Python classes for working with network protocols.
#
# Copyright Fortra, LLC and its affiliated companies
#
# All rights reserved.
#
# This software is provided under a slightly modified version
# of the Apache Software License. See the accompanying LICENSE file
# for more information.
#
# Description:
# Dump remote host information in ntlm authentication model, without credentials.
# For SMB protocols (1/2/3), it's easy to use SMBConnection class (thanks to @agsolino),
# but since negotiate response is not available in original classes,
# we made out custom classes based on them.
# The usefull information in negotiate response are "Dialect Version", "Signing Options",
# "Maximum bytes allowed per smb request" and "Servers time information".
# The point is sometimes server dosn't include "boot time" in response. But we show it,
# when available, in this script.
#
# It's very easy to use:
# python DumpNTLMInfo.py 192.168.1.63
#
# Author:
# Alex Romero (@NtAlexio2)
#
# Reference for:
# [MS-SMB2]
# [MS-RPCE]
#
# ToDo:
# [ ] MSSQL
# [ ] Find new protocols using NTLM for authentication in network.
#
import os
import sys
import argparse
import logging
import struct
import socket
import math, string, random
from six import indexbytes
from datetime import datetime, timedelta, timezone
from impacket import version
from impacket import nmb, ntlm
from impacket.examples import logger
from impacket.smb import SMB, NewSMBPacket, SMBCommand, SMBNTLMDialect_Parameters,\
SMBNTLMDialect_Data, SMBExtended_Security_Parameters, SMBExtended_Security_Data, UnsupportedFeature,\
SMBSessionSetupAndX_Extended_Data, SMBSessionSetupAndX_Extended_Parameters, SMBSessionSetupAndX_Extended_Response_Parameters,\
SMBSessionSetupAndX_Extended_Response_Data, SMBSessionSetupAndXResponse_Parameters, SMB_DIALECT
from impacket.smb3structs import *
from impacket.spnego import SPNEGO_NegTokenInit, SPNEGO_NegTokenResp, TypesMech
from impacket.nt_errors import STATUS_SUCCESS, STATUS_MORE_PROCESSING_REQUIRED
from impacket.uuid import uuidtup_to_bin
from impacket.dcerpc.v5 import transport, epm
from impacket.dcerpc.v5.rpcrt import *
EPOCH_AS_FILETIME = 116444736000000000 # January 1, 1970 as MS file time
class RPC:
def __init__(self, target) -> None:
self.MaxTrasmitionSize = 0
self._initializeTransport(target)
def GetChallange(self):
ntlmChallenge = None
packet = self._create_bind_request()
self._rpctransport.send(packet.get_packet())
buffer = self._rpctransport.recv()
if buffer != 0:
response = MSRPCHeader(buffer)
bindResp = MSRPCBindAck(response.getData())
self.MaxTrasmitionSize = bindResp['max_rfrag']
ntlmChallenge = ntlm.NTLMAuthChallenge(bindResp['auth_data'])
return ntlmChallenge
def _initializeTransport(self, target):
self._rpctransport = transport.DCERPCTransportFactory(r'ncacn_ip_tcp:%s[135]' % target)
self._rpctransport.set_credentials('', '', '', '', '')
self._rpctransport.set_dport(135)
self._rpctransport.connect()
def _create_bind_request(self):
bind = MSRPCBind()
item = CtxItem()
item['AbstractSyntax'] = epm.MSRPC_UUID_PORTMAP
item['TransferSyntax'] = uuidtup_to_bin(('8a885d04-1ceb-11c9-9fe8-08002b104860', '2.0'))
item['ContextID'] = 0
item['TransItems'] = 1
bind.addCtxItem(item)
packet = MSRPCHeader()
packet['type'] = MSRPC_BIND
packet['pduData'] = bind.getData()
packet['call_id'] = 1
auth = ntlm.getNTLMSSPType1('', '', signingRequired=True, use_ntlmv2=True)
sec_trailer = SEC_TRAILER()
sec_trailer['auth_type'] = RPC_C_AUTHN_WINNT
sec_trailer['auth_level'] = RPC_C_AUTHN_LEVEL_PKT_INTEGRITY
sec_trailer['auth_ctx_id'] = 0 + 79231
pad = (4 - (len(packet.get_packet()) % 4)) % 4
if pad != 0:
packet['pduData'] += b'\xFF'*pad
sec_trailer['auth_pad_len']=pad
packet['sec_trailer'] = sec_trailer
packet['auth_data'] = auth
return packet
class SMB1:
def __init__(self, remote_name, remote_host, my_name=None,
sess_port=445, timeout=60, session=None, negSessionResponse=None):
self._uid = 0
self._dialects_data = None
self._SignatureRequired = False
self._dialects_parameters = None
self.__flags1 = SMB.FLAGS1_PATHCASELESS | SMB.FLAGS1_CANONICALIZED_PATHS
self.__flags2 = SMB.FLAGS2_EXTENDED_SECURITY | SMB.FLAGS2_NT_STATUS | SMB.FLAGS2_LONG_NAMES
self.__timeout = timeout
self._session = session
self._my_name = my_name
self._auth = None
if session is None:
self._session = nmb.NetBIOSTCPSession(my_name, remote_name, remote_host, nmb.TYPE_SERVER, sess_port, self.__timeout)
self._negotiateResponse = self._negotiateSession(negSessionResponse)
def GetNegotiateResponse(self):
return self._negotiateResponse
def GetChallange(self):
packet = NewSMBPacket()
if self._SignatureRequired:
packet['Flags2'] |= SMB.FLAGS2_SMB_SECURITY_SIGNATURE
sessionSetup = self._createSessionSetupRequest()
packet.addCommand(sessionSetup)
self.send(packet)
packet = self.receive()
if packet.isValidAnswer(SMB.SMB_COM_SESSION_SETUP_ANDX):
self._uid = packet['Uid']
sessionResponse = SMBCommand(packet['Data'][0])
sessionParameters = SMBSessionSetupAndX_Extended_Response_Parameters(sessionResponse['Parameters'])
sessionData = SMBSessionSetupAndX_Extended_Response_Data(flags = packet['Flags2'])
sessionData['SecurityBlobLength'] = sessionParameters['SecurityBlobLength']
sessionData.fromString(sessionResponse['Data'])
self._respToken = SPNEGO_NegTokenResp(sessionData['SecurityBlob'])
ntlmChallenge = ntlm.NTLMAuthChallenge(self._respToken['ResponseToken'])
return ntlmChallenge
def Authenticate(self):
type3, _ = ntlm.getNTLMSSPType3(self._auth, self._respToken['ResponseToken'], '', '', '', '', '', use_ntlmv2=True)
packet = NewSMBPacket()
if self._SignatureRequired:
packet['Flags2'] |= SMB.FLAGS2_SMB_SECURITY_SIGNATURE
respToken2 = SPNEGO_NegTokenResp()
respToken2['ResponseToken'] = type3.getData()
sessionSetup = self._createSessionSetupRequest()
sessionSetup['Parameters']['SecurityBlobLength'] = len(respToken2)
sessionSetup['Data']['SecurityBlob'] = respToken2.getData()
packet.addCommand(sessionSetup)
self.send(packet)
packet = self.receive()
try:
if packet.isValidAnswer(SMB.SMB_COM_SESSION_SETUP_ANDX):
sessionResponse = SMBCommand(packet['Data'][0])
sessionParameters = SMBSessionSetupAndXResponse_Parameters(sessionResponse['Parameters'])
self._action = sessionParameters['Action']
return True
except:
pass
return False
def send(self, negoPacket):
negoPacket['Uid'] = self._uid
negoPacket['Pid'] = (os.getpid() & 0xFFFF)
negoPacket['Flags1'] |= self.__flags1
negoPacket['Flags2'] |= self.__flags2
self._session.send_packet(negoPacket.getData())
def receive(self):
r = self._session.recv_packet(self.__timeout)
return NewSMBPacket(data = r.get_trailer())
def _negotiateSession(self, negPacket = None):
def parsePacket(negoPacket):
if negoPacket['Flags2'] & SMB.FLAGS2_UNICODE:
self.__flags2 |= SMB.FLAGS2_UNICODE
if negoPacket.isValidAnswer(SMB.SMB_COM_NEGOTIATE):
sessionResponse = SMBCommand(negoPacket['Data'][0])
self._dialects_parameters = SMBNTLMDialect_Parameters(sessionResponse['Parameters'])
self._dialects_data = SMBNTLMDialect_Data()
self._dialects_data['ChallengeLength'] = self._dialects_parameters['ChallengeLength']
self._dialects_data.fromString(sessionResponse['Data'])
if self._dialects_parameters['Capabilities'] & SMB.CAP_EXTENDED_SECURITY:
self._dialects_parameters = SMBExtended_Security_Parameters(sessionResponse['Parameters'])
self._dialects_data = SMBExtended_Security_Data(sessionResponse['Data'])
if self._dialects_parameters['SecurityMode'] & SMB.SECURITY_SIGNATURES_REQUIRED:
self._SignatureRequired = True
else:
if self._dialects_parameters['DialectIndex'] == 0xffff:
raise UnsupportedFeature("Remote server does not know NT LM 0.12")
return self._wrapper(sessionResponse)
if negPacket is None:
negoPacket = NewSMBPacket()
negSession = SMBCommand(SMB.SMB_COM_NEGOTIATE)
self.__flags2 = self.__flags2 | SMB.FLAGS2_EXTENDED_SECURITY
negSession['Data'] = b'\x02NT LM 0.12\x00'
negoPacket.addCommand(negSession)
self.send(negoPacket)
negoPacket = self.receive()
return parsePacket(negoPacket)
return parsePacket(NewSMBPacket(data = negPacket))
def _createSessionSetupRequest(self):
sessionSetup = SMBCommand(SMB.SMB_COM_SESSION_SETUP_ANDX)
sessionSetup['Data'] = SMBSessionSetupAndX_Extended_Data()
sessionSetup['Parameters'] = SMBSessionSetupAndX_Extended_Parameters()
sessionSetup['Parameters']['MaxBufferSize'] = 61440
sessionSetup['Parameters']['MaxMpxCount'] = 2
sessionSetup['Parameters']['VcNumber'] = 1
sessionSetup['Parameters']['SessionKey'] = 0
sessionSetup['Parameters']['Capabilities'] = SMB.CAP_EXTENDED_SECURITY | SMB.CAP_USE_NT_ERRORS | SMB.CAP_UNICODE | SMB.CAP_LARGE_READX | SMB.CAP_LARGE_WRITEX
blob = SPNEGO_NegTokenInit()
blob['MechTypes'] = [TypesMech['NTLMSSP - Microsoft NTLM Security Support Provider']]
self._auth = ntlm.getNTLMSSPType1(self._my_name, '', self._SignatureRequired, use_ntlmv2=True)
blob['MechToken'] = self._auth.getData()
sessionSetup['Parameters']['SecurityBlobLength'] = len(blob)
sessionSetup['Parameters'].getData()
sessionSetup['Data']['SecurityBlob'] = blob.getData()
sessionSetup['Data']['NativeOS'] = 'U\x00n\x00i\x00x\x00\x00\x00'
sessionSetup['Data']['NativeLanMan'] = 'S\x00a\x00m\x00b\x00a\x00\x00'
return sessionSetup
def _wrapper(self, sessionResponse):
sessionResponse['SecurityMode'] = 0x0
sessionResponse['DialectRevision'] = SMB_DIALECT
if self._dialects_parameters['SecurityMode'] & SMB.SECURITY_SIGNATURES_ENABLED:
sessionResponse['SecurityMode'] = SMB2_NEGOTIATE_SIGNING_ENABLED
if self._SignatureRequired:
sessionResponse['SecurityMode'] |= SMB2_NEGOTIATE_SIGNING_REQUIRED
sessionResponse['MaxReadSize'] = self._dialects_parameters['MaxBufferSize']
sessionResponse['MaxWriteSize'] = self._dialects_parameters['MaxBufferSize']
sessionResponse['SystemTime'] = self._to_long_filetime(self._dialects_parameters['LowDateTime'], self._dialects_parameters['HighDateTime'])
sessionResponse['ServerStartTime'] = 0 # SMB1 has not boot time totally
return sessionResponse
def _to_long_filetime(self, dwLowDateTime, dwHighDateTime):
temp_time = dwHighDateTime
temp_time <<= 32
temp_time |= dwLowDateTime
return temp_time
class SMB3:
def __init__(self, remote_name, remote_host, my_name=None,
sess_port=445, timeout=60, session=None, negSessionResponse=None):
self._NetBIOSSession = session
self._sequenceWindow = 0
self._sessionId = 0
self._timeout = timeout
self._auth = None
if session is None:
self._NetBIOSSession = nmb.NetBIOSTCPSession(my_name, remote_name, remote_host, nmb.TYPE_SERVER, sess_port, timeout)
else:
self._sequenceWindow += 1
self._negotiateResponse = self._negotiateSession(negSessionResponse)
def GetNegotiateResponse(self):
return self._negotiateResponse
def GetChallange(self):
packet = self._createSessionSetupRequest(self._negotiateResponse['DialectRevision'])
self.send(packet)
self._answer = self.receive()
sessionSetupResponse = SMB2SessionSetup_Response(self._answer['Data'])
self._respToken = SPNEGO_NegTokenResp(sessionSetupResponse['Buffer'])
ntlmChallenge = ntlm.NTLMAuthChallenge(self._respToken['ResponseToken'])
return ntlmChallenge
def Authenticate(self):
packet = SMB2Packet()
if self.GetNegotiateResponse()['DialectRevision'] >= SMB2_DIALECT_30:
packet = SMB3Packet()
packet['Command'] = SMB2_SESSION_SETUP
if self._answer.isValidAnswer(STATUS_MORE_PROCESSING_REQUIRED):
self._sessionId = self._answer['SessionID']
type3, _ = ntlm.getNTLMSSPType3(self._auth, self._respToken['ResponseToken'], '', '', '', '', '')
respToken2 = SPNEGO_NegTokenResp()
respToken2['ResponseToken'] = type3.getData()
sessionSetup = SMB2SessionSetup()
sessionSetup['SecurityMode'] = SMB2_NEGOTIATE_SIGNING_ENABLED
sessionSetup['SecurityBufferLength'] = len(respToken2)
sessionSetup['Buffer'] = respToken2.getData()
packet['Data'] = sessionSetup
self.send(packet)
packet = self.receive()
try:
return packet.isValidAnswer(STATUS_SUCCESS)
except:
return False
def send(self, packet):
packet['MessageID'] = self._sequenceWindow
self._sequenceWindow += 1
packet['SessionID'] = self._sessionId
packet['CreditCharge'] = 1
messageId = packet['MessageID']
data = packet.getData()
self._NetBIOSSession.send_packet(data)
return messageId
def receive(self):
data = self._NetBIOSSession.recv_packet(self._timeout)
packet = SMB2Packet(data.get_trailer())
return packet
def _negotiateSession(self, negSessionResponse = None):
currentDialect = SMB2_DIALECT_WILDCARD
if negSessionResponse is not None:
negotiateResponse = SMB2Negotiate_Response(negSessionResponse['Data'])
currentDialect = negotiateResponse['DialectRevision']
if currentDialect == SMB2_DIALECT_WILDCARD:
packet = SMB2Packet()
packet['Command'] = SMB2_NEGOTIATE
negSession = SMB2Negotiate()
negSession['SecurityMode'] = SMB2_NEGOTIATE_SIGNING_ENABLED
negSession['Capabilities'] = SMB2_GLOBAL_CAP_ENCRYPTION
negSession['ClientGuid'] = ''.join([random.choice(string.ascii_letters) for _ in range(16)])
negSession['Dialects'] = [SMB2_DIALECT_002, SMB2_DIALECT_21, SMB2_DIALECT_30]
negSession['DialectCount'] = len(negSession['Dialects'])
packet['Data'] = negSession
self.send(packet)
answer = self.receive()
if answer.isValidAnswer(STATUS_SUCCESS):
negotiateResponse = SMB2Negotiate_Response(answer['Data'])
return negotiateResponse
def _createSessionSetupRequest(self, dialect):
sessionSetup = SMB2SessionSetup()
sessionSetup['Flags'] = 0
blob = SPNEGO_NegTokenInit()
blob['MechTypes'] = [TypesMech['NTLMSSP - Microsoft NTLM Security Support Provider']]
self._auth = ntlm.getNTLMSSPType1('', '', False)
blob['MechToken'] = self._auth.getData()
sessionSetup['SecurityBufferLength'] = len(blob)
sessionSetup['Buffer'] = blob.getData()
packet = SMB2Packet()
if dialect >= SMB2_DIALECT_30:
packet = SMB3Packet()
packet['Command'] = SMB2_SESSION_SETUP
packet['Data'] = sessionSetup
return packet
class SmbConnection:
def __init__(self, ip, hostname, port) -> None:
self.target = ip
self.hostname = hostname
self._sess_port = int(port)
self._timeout = 60
self._myName = self._get_my_name()
self._nmbSession = None
self._SMBConnection = None
def IsSmb1Enabled(self):
flags1 = SMB.FLAGS1_PATHCASELESS | SMB.FLAGS1_CANONICALIZED_PATHS
flags2 = SMB.FLAGS2_EXTENDED_SECURITY | SMB.FLAGS2_NT_STATUS | SMB.FLAGS2_LONG_NAMES
smbv1NegoData = '\x02NT LM 0.12\x00'
smb1_enabled = False
try:
self._negotiateSessionWildcard(True, flags1=flags1, flags2=flags2, data=smbv1NegoData)
except Exception as e:
if 'No answer!' in str(e):
smb1_enabled = False
else:
smb1_enabled = True
return smb1_enabled
def NegotiateSession(self):
flags1 = SMB.FLAGS1_PATHCASELESS | SMB.FLAGS1_CANONICALIZED_PATHS
flags2 = SMB.FLAGS2_EXTENDED_SECURITY | SMB.FLAGS2_NT_STATUS | SMB.FLAGS2_LONG_NAMES
negoData = '\x02NT LM 0.12\x00\x02SMB 2.002\x00\x02SMB 2.???\x00'
if self._sess_port == nmb.NETBIOS_SESSION_PORT:
negoData = '\x02NT LM 0.12\x00\x02SMB 2.002\x00'
packet = self._negotiateSessionWildcard(True, flags1=flags1, flags2=flags2, data=negoData)
if packet[0:1] == b'\xfe':
self._SMBConnection = SMB3(self.hostname, self.target, self._myName, self._sess_port,
self._timeout, session=self._nmbSession, negSessionResponse=SMB2Packet(packet))
else:
self._SMBConnection = SMB1(self.hostname, self.target, self._myName, self._sess_port,
self._timeout, session=self._nmbSession, negSessionResponse=packet)
return self._SMBConnection.GetNegotiateResponse()
def GetChallange(self):
return self._SMBConnection.GetChallange()
def Authenticate(self):
return self._SMBConnection.Authenticate()
def _negotiateSessionWildcard(self, extended_security=True, flags1=0, flags2=0, data=None):
tries = 0
smbp = NewSMBPacket()
smbp['Flags1'] = flags1
smbp['Flags2'] = flags2 | SMB.FLAGS2_UNICODE
response = None
while tries < 2:
self._nmbSession = nmb.NetBIOSTCPSession(self._myName, self.hostname, self.target, nmb.TYPE_SERVER, self._sess_port, self._timeout)
negSession = SMBCommand(SMB.SMB_COM_NEGOTIATE)
if extended_security is True:
smbp['Flags2'] |= SMB.FLAGS2_EXTENDED_SECURITY
negSession['Data'] = data
smbp.addCommand(negSession)
self._nmbSession.send_packet(smbp.getData())
try:
response = self._nmbSession.recv_packet(self._timeout)
break
except nmb.NetBIOSError:
smbp['Flags2'] |= SMB.FLAGS2_NT_STATUS | SMB.FLAGS2_LONG_NAMES | SMB.FLAGS2_UNICODE
smbp['Data'] = []
tries += 1
if response is None:
raise Exception('No answer!')
return response.get_trailer()
def _get_my_name(self):
myName = socket.gethostname()
i = myName.find('.')
if i > -1:
myName = myName[:i]
return myName
class DumpNtlm:
def __init__(self, ip, hostname, port, protocol) -> None:
self.target = ip
self.hostname = hostname
self._sess_port = int(port)
self._protocol = protocol
self._timeout = 60
def DisplayInfo(self):
if self._protocol == 'SMB':
self.DisplaySmbInfo()
elif self._protocol == 'RPC':
self.DisplayRpcInfo()
def DisplayRpcInfo(self):
rpc = RPC(self.target)
ntlmChallenge = rpc.GetChallange()
self.DisplayChallangeInfo(ntlmChallenge)
self.DisplayIo({'MaxReadSize': rpc.MaxTrasmitionSize, 'MaxWriteSize': rpc.MaxTrasmitionSize})
def DisplaySmbInfo(self):
connection = SmbConnection(self.target, self.hostname, self._sess_port)
negotiation = connection.NegotiateSession()
dialect = negotiation['DialectRevision']
secMode = negotiation['SecurityMode']
smb1_enabled = connection.IsSmb1Enabled()
self.DisplayDialect(dialect, smb1_enabled)
self.DisplaySigning(secMode)
self.DisplayIo(negotiation)
self.DisplayTime(negotiation)
ntlmChallenge = connection.GetChallange()
self.DisplayChallangeInfo(ntlmChallenge)
nullSession = connection.Authenticate()
self.DisplayNullSession(nullSession)
def DisplaySigning(self, secMode):
mode = ''
if (secMode & SMB2_NEGOTIATE_SIGNING_ENABLED) == SMB2_NEGOTIATE_SIGNING_ENABLED:
mode = 'SIGNING_ENABLED'
if (secMode & SMB2_NEGOTIATE_SIGNING_REQUIRED) == SMB2_NEGOTIATE_SIGNING_REQUIRED:
mode += ' | SIGNING_REQUIRED'
else:
mode += ' (not required)'
print("[+] Server Security : {}".format(mode))
def DisplayDialect(self, dialect, smb1_enabled):
print("[+] SMBv1 Enabled : {0}".format(smb1_enabled))
if dialect == SMB2_DIALECT_002:
print("[+] Prefered Dialect: SMB 002")
elif dialect == SMB2_DIALECT_21:
print("[+] Prefered Dialect: SMB 2.1")
elif dialect == SMB2_DIALECT_30:
print("[+] Prefered Dialect: SMB 3.0")
elif dialect == SMB2_DIALECT_302:
print("[+] Prefered Dialect: SMB 3.0.2")
elif dialect == SMB2_DIALECT_302:
print("[+] Prefered Dialect: SMB 3.0.2")
elif dialect == SMB2_DIALECT_311:
print("[+] Prefered Dialect: SMB 3.1.1")
elif type(dialect) is str:
print("[+] Prefered Dialect: {}".format(dialect)) # SMB1
else:
print("[+] Prefered Dialect: 0x{:x}".format(dialect))
def DisplayIo(self, negotiateResponse):
print("[+] Max Read Size : {} ({} bytes)".format(self.__convert_size(negotiateResponse['MaxReadSize']), negotiateResponse['MaxReadSize']))
print("[+] Max Write Size : {} ({} bytes)".format(self.__convert_size(negotiateResponse['MaxWriteSize']), negotiateResponse['MaxWriteSize']))
def DisplayTime(self, negotiateResponse):
currentTime = 0 if negotiateResponse['SystemTime'] == 0 else self.__filetime_to_dt(negotiateResponse['SystemTime']).astimezone(timezone.utc)
bootTime = 0 if negotiateResponse['ServerStartTime'] == 0 else self.__filetime_to_dt(negotiateResponse['ServerStartTime']).astimezone(timezone.utc)
print("[+] Current Time : {}".format(currentTime))
if bootTime != 0:
print("[+] Boot Time : {}".format(bootTime))
print("[+] Server Up Time : {}".format(currentTime - bootTime))
def DisplayChallangeInfo(self, challange):
if challange['TargetInfoFields_len'] > 0:
av_pairs = ntlm.AV_PAIRS(challange['TargetInfoFields'][:challange['TargetInfoFields_len']])
if av_pairs[ntlm.NTLMSSP_AV_HOSTNAME] is not None:
try:
print("[+] Name : {}".format(av_pairs[ntlm.NTLMSSP_AV_HOSTNAME][1].decode('utf-16le')))
except:
pass
if av_pairs[ntlm.NTLMSSP_AV_DOMAINNAME] is not None:
try:
print("[+] Domain : {}".format(av_pairs[ntlm.NTLMSSP_AV_DOMAINNAME][1].decode('utf-16le')))
except:
pass
if av_pairs[ntlm.NTLMSSP_AV_DNS_TREENAME] is not None:
try:
print("[+] DNS Tree Name : {}".format(av_pairs[ntlm.NTLMSSP_AV_DNS_TREENAME][1].decode('utf-16le')))
except:
pass
if av_pairs[ntlm.NTLMSSP_AV_DNS_DOMAINNAME] is not None:
try:
print("[+] DNS Domain Name : {}".format(av_pairs[ntlm.NTLMSSP_AV_DNS_DOMAINNAME][1].decode('utf-16le')))
except:
pass
if av_pairs[ntlm.NTLMSSP_AV_DNS_HOSTNAME] is not None:
try:
print("[+] DNS Host Name : {}".format(av_pairs[ntlm.NTLMSSP_AV_DNS_HOSTNAME][1].decode('utf-16le')))
except:
pass
# if av_pairs[ntlm.NTLMSSP_AV_TIME] is not None:
# try:
# timelong = struct.unpack('<q', av_pairs[ntlm.NTLMSSP_AV_TIME][1])[0]
# print("[+] Time : {}".format(self.__filetime_to_dt(timelong).astimezone(timezone.utc)))
# except:
# pass
if 'Version' in challange.fields:
version = challange['Version']
if len(version) >= 4:
print("[+] OS : {}".format("Windows NT %d.%d Build %d" % (indexbytes(version,0), indexbytes(version,1), struct.unpack('<H',version[2:4])[0])))
def DisplayNullSession(self, nullSession):
print("[+] Null Session : {}".format(nullSession))
# https://stackoverflow.com/questions/38878647/python-convert-filetime-to-datetime-for-dates-before-1970
def __filetime_to_dt(self, filetime):
us = (filetime - EPOCH_AS_FILETIME) // 10
return datetime(1970, 1, 1) + timedelta(microseconds = us)
# https://stackoverflow.com/questions/5194057/better-way-to-convert-file-sizes-in-python
def __convert_size(self, size_bytes):
if size_bytes == 0:
return "0B"
size_name = ("B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB")
i = int(math.floor(math.log(size_bytes, 1024)))
p = math.pow(1024, i)
s = round(size_bytes / p, 2)
return "%s %s" % (s, size_name[i])
if __name__ == '__main__':
print(version.BANNER)
parser = argparse.ArgumentParser(add_help = True, description = "Do ntlm authentication and parse information.")
parser.add_argument('target', action='store', help='<targetName or address>')
parser.add_argument('-debug', action='store_true', help='Turn DEBUG output ON')
parser.add_argument('-ts', action='store_true', help='Adds timestamp to every logging output')
parser.add_argument('-target-ip', action='store', metavar="ip address",
help='IP Address of the target machine. If omitted it will use whatever was specified as target. '
'This is useful when target is the NetBIOS name and you cannot resolve it')
parser.add_argument('-port', type=int, default=445, metavar="destination port",
help='Destination port to connect to SMB/RPC Server')
parser.add_argument('-protocol', choices=['SMB', 'RPC'], nargs='?', metavar="protocol",
help='Protocol to use (SMB or RPC). Default is SMB, port 135 uses RPC normally.')
if len(sys.argv) == 1:
parser.print_help()
sys.exit(1)
options = parser.parse_args()
logger.init(options.ts, options.debug)
if options.port == 135:
if not options.protocol:
options.protocol = 'RPC'
logging.info("Port 135 specified; using RPC protocol by default. Use `-protocol SMB` to force SMB protocol.")
elif options.protocol == 'SMB':
logging.info("Port 135 specified with SMB protocol. Are you sure you don't want `-protocol RPC`?")
elif not options.protocol:
options.protocol = 'SMB'
logging.info("Defaulting to SMB protocol.")
try:
if options.target_ip is not None:
dumper = DumpNtlm(options.target_ip, options.target, int(options.port), options.protocol)
else:
dumper = DumpNtlm(options.target, options.target, int(options.port), options.protocol)
logging.info("Using target: %s, IP: %s, Port: %d, Protocol: %s" % (options.target, options.target_ip or options.target, options.port, options.protocol) )
dumper.DisplayInfo()
except Exception as e:
if logging.getLogger().level == logging.DEBUG:
import traceback
traceback.print_exc()
logging.error(str(e))