aboutsummaryrefslogtreecommitdiff
path: root/tests/python_dependencies/impacket/ntlm.py
diff options
context:
space:
mode:
authorMarc Hoersken <info@marc-hoersken.de>2020-03-15 10:01:38 +0100
committerMarc Hoersken <info@marc-hoersken.de>2020-03-15 10:01:38 +0100
commit4be2560e01ed40e256b5143c8b4f5de2450ffefd (patch)
tree296d1332ef1a53ab03d31c31ee2aa52bcef92353 /tests/python_dependencies/impacket/ntlm.py
parent67f3f6cff19ed323849280316c592969ab97ee21 (diff)
tests: remove python_dependencies for smbserver from our tree
Users of the SMB tests will have to install impacket manually. Reasoning: our in-tree version of impacket was quite outdated and only compatible with Python 2 which is already end-of-life. Upgrading to Python 3 and a compatible impacket version would require to import additional Python-only and CPython-extension dependencies. This would have hindered portability enormously. Closes #5094
Diffstat (limited to 'tests/python_dependencies/impacket/ntlm.py')
-rw-r--r--tests/python_dependencies/impacket/ntlm.py973
1 files changed, 0 insertions, 973 deletions
diff --git a/tests/python_dependencies/impacket/ntlm.py b/tests/python_dependencies/impacket/ntlm.py
deleted file mode 100644
index 8845e9d50..000000000
--- a/tests/python_dependencies/impacket/ntlm.py
+++ /dev/null
@@ -1,973 +0,0 @@
-from __future__ import print_function
-# Copyright (c) 2003-2016 CORE Security Technologies:
-#
-# This software is provided under under a slightly modified version
-# of the Apache Software License. See the accompanying LICENSE file
-# for more information.
-#
-import base64
-import struct
-import calendar
-import time
-import hashlib
-import random
-import string
-import binascii
-
-from impacket.structure import Structure
-from impacket import LOG
-
-
-# This is important. NTLMv2 is not negotiated by the client or server.
-# It is used if set locally on both sides. Change this item if you don't want to use
-# NTLMv2 by default and fall back to NTLMv1 (with EXTENDED_SESSION_SECURITY or not)
-# Check the following links:
-# http://davenport.sourceforge.net/ntlm.html
-# http://blogs.msdn.com/b/openspecification/archive/2010/04/20/ntlm-keys-and-sundry-stuff.aspx
-# http://social.msdn.microsoft.com/Forums/en-US/os_interopscenarios/thread/c8f488ed-1b96-4e06-bd65-390aa41138d1/
-# So I'm setting a global variable to control this, this can also be set programmatically
-
-USE_NTLMv2 = True # if false will fall back to NTLMv1 (or NTLMv1 with ESS a.k.a NTLM2)
-
-
-def computeResponse(flags, serverChallenge, clientChallenge, serverName, domain, user, password, lmhash='', nthash='',
- use_ntlmv2=USE_NTLMv2):
- if use_ntlmv2:
- return computeResponseNTLMv2(flags, serverChallenge, clientChallenge, serverName, domain, user, password,
- lmhash, nthash, use_ntlmv2=use_ntlmv2)
- else:
- return computeResponseNTLMv1(flags, serverChallenge, clientChallenge, serverName, domain, user, password,
- lmhash, nthash, use_ntlmv2=use_ntlmv2)
-try:
- POW = None
- from Crypto.Cipher import ARC4
- from Crypto.Cipher import DES
- from Crypto.Hash import MD4
-except Exception:
- try:
- import POW
- except Exception:
- LOG.critical("Warning: You don't have any crypto installed. You need PyCrypto")
- LOG.critical("See http://www.pycrypto.org/")
-
-NTLM_AUTH_NONE = 1
-NTLM_AUTH_CONNECT = 2
-NTLM_AUTH_CALL = 3
-NTLM_AUTH_PKT = 4
-NTLM_AUTH_PKT_INTEGRITY = 5
-NTLM_AUTH_PKT_PRIVACY = 6
-
-# If set, requests 56-bit encryption. If the client sends NTLMSSP_NEGOTIATE_SEAL or NTLMSSP_NEGOTIATE_SIGN
-# with NTLMSSP_NEGOTIATE_56 to the server in the NEGOTIATE_MESSAGE, the server MUST return NTLMSSP_NEGOTIATE_56 to
-# the client in the CHALLENGE_MESSAGE. Otherwise it is ignored. If both NTLMSSP_NEGOTIATE_56 and NTLMSSP_NEGOTIATE_128
-# are requested and supported by the client and server, NTLMSSP_NEGOTIATE_56 and NTLMSSP_NEGOTIATE_128 will both be
-# returned to the client. Clients and servers that set NTLMSSP_NEGOTIATE_SEAL SHOULD set NTLMSSP_NEGOTIATE_56 if it is
-# supported. An alternate name for this field is NTLMSSP_NEGOTIATE_56.
-NTLMSSP_NEGOTIATE_56 = 0x80000000
-
-# If set, requests an explicit key exchange. This capability SHOULD be used because it improves security for message
-# integrity or confidentiality. See sections 3.2.5.1.2, 3.2.5.2.1, and 3.2.5.2.2 for details. An alternate name for
-# this field is NTLMSSP_NEGOTIATE_KEY_EXCH.
-NTLMSSP_NEGOTIATE_KEY_EXCH = 0x40000000
-
-# If set, requests 128-bit session key negotiation. An alternate name for this field is NTLMSSP_NEGOTIATE_128.
-# If the client sends NTLMSSP_NEGOTIATE_128 to the server in the NEGOTIATE_MESSAGE, the server MUST return
-# NTLMSSP_NEGOTIATE_128 to the client in the CHALLENGE_MESSAGE only if the client sets NTLMSSP_NEGOTIATE_SEAL or
-# NTLMSSP_NEGOTIATE_SIGN. Otherwise it is ignored. If both NTLMSSP_NEGOTIATE_56 and NTLMSSP_NEGOTIATE_128 are
-# requested and supported by the client and server, NTLMSSP_NEGOTIATE_56 and NTLMSSP_NEGOTIATE_128 will both be
-# returned to the client. Clients and servers that set NTLMSSP_NEGOTIATE_SEAL SHOULD set NTLMSSP_NEGOTIATE_128 if it
-# is supported. An alternate name for this field is NTLMSSP_NEGOTIATE_128
-NTLMSSP_NEGOTIATE_128 = 0x20000000
-
-NTLMSSP_RESERVED_1 = 0x10000000
-NTLMSSP_RESERVED_2 = 0x08000000
-NTLMSSP_RESERVED_3 = 0x04000000
-
-# If set, requests the protocol version number. The data corresponding to this flag is provided in the Version field
-# of the NEGOTIATE_MESSAGE, the CHALLENGE_MESSAGE, and the AUTHENTICATE_MESSAGE.<22> An alternate name for this field
-# is NTLMSSP_NEGOTIATE_VERSION
-NTLMSSP_NEGOTIATE_VERSION = 0x02000000
-NTLMSSP_RESERVED_4 = 0x01000000
-
-# If set, indicates that the TargetInfo fields in the CHALLENGE_MESSAGE (section 2.2.1.2) are populated.
-# An alternate name for this field is NTLMSSP_NEGOTIATE_TARGET_INFO.
-NTLMSSP_NEGOTIATE_TARGET_INFO = 0x00800000
-
-# If set, requests the usage of the LMOWF (section 3.3). An alternate name for this field is
-# NTLMSSP_REQUEST_NON_NT_SESSION_KEY.
-NTLMSSP_REQUEST_NON_NT_SESSION_KEY = 0x00400000
-NTLMSSP_RESERVED_5 = 0x00200000
-
-# If set, requests an identify level token. An alternate name for this field is NTLMSSP_NEGOTIATE_IDENTIFY
-NTLMSSP_NEGOTIATE_IDENTIFY = 0x00100000
-
-# If set, requests usage of the NTLM v2 session security. NTLM v2 session security is a misnomer because it is not
-# NTLM v2. It is NTLM v1 using the extended session security that is also in NTLM v2. NTLMSSP_NEGOTIATE_LM_KEY and
-# NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY are mutually exclusive. If both NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY
-# and NTLMSSP_NEGOTIATE_LM_KEY are requested, NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY alone MUST be returned to the
-# client. NTLM v2 authentication session key generation MUST be supported by both the client and the DC in order to be
-# used, and extended session security signing and sealing requires support from the client and the server in order to
-# be used.<23> An alternate name for this field is NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY
-NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY = 0x00080000
-NTLMSSP_NEGOTIATE_NTLM2 = 0x00080000
-NTLMSSP_TARGET_TYPE_SHARE = 0x00040000
-
-# If set, TargetName MUST be a server name. The data corresponding to this flag is provided by the server in the
-# TargetName field of the CHALLENGE_MESSAGE. If this bit is set, then NTLMSSP_TARGET_TYPE_DOMAIN MUST NOT be set.
-# This flag MUST be ignored in the NEGOTIATE_MESSAGE and the AUTHENTICATE_MESSAGE. An alternate name for this field
-# is NTLMSSP_TARGET_TYPE_SERVER
-NTLMSSP_TARGET_TYPE_SERVER = 0x00020000
-
-# If set, TargetName MUST be a domain name. The data corresponding to this flag is provided by the server in the
-# TargetName field of the CHALLENGE_MESSAGE. If set, then NTLMSSP_TARGET_TYPE_SERVER MUST NOT be set. This flag MUST
-# be ignored in the NEGOTIATE_MESSAGE and the AUTHENTICATE_MESSAGE. An alternate name for this field is
-# NTLMSSP_TARGET_TYPE_DOMAIN.
-NTLMSSP_TARGET_TYPE_DOMAIN = 0x00010000
-
-# If set, requests the presence of a signature block on all messages. NTLMSSP_NEGOTIATE_ALWAYS_SIGN MUST be set in the
-# NEGOTIATE_MESSAGE to the server and the CHALLENGE_MESSAGE to the client. NTLMSSP_NEGOTIATE_ALWAYS_SIGN is overridden
-# by NTLMSSP_NEGOTIATE_SIGN and NTLMSSP_NEGOTIATE_SEAL, if they are supported. An alternate name for this field is
-# NTLMSSP_NEGOTIATE_ALWAYS_SIGN.
-NTLMSSP_NEGOTIATE_ALWAYS_SIGN = 0x00008000 # forces the other end to sign packets
-NTLMSSP_RESERVED_6 = 0x00004000
-
-# This flag indicates whether the Workstation field is present. If this flag is not set, the Workstation field MUST be
-# ignored. If this flag is set, the length field of the Workstation field specifies whether the workstation name is
-# nonempty or not.<24> An alternate name for this field is NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED.
-NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED = 0x00002000
-
-# If set, the domain name is provided (section 2.2.1.1).<25> An alternate name for this field is
-# NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED
-NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED = 0x00001000
-NTLMSSP_RESERVED_7 = 0x00000800
-
-
-# If set, LM authentication is not allowed and only NT authentication is used.
-NTLMSSP_NEGOTIATE_NT_ONLY = 0x00000400
-
-# If set, requests usage of the NTLM v1 session security protocol. NTLMSSP_NEGOTIATE_NTLM MUST be set in the
-# NEGOTIATE_MESSAGE to the server and the CHALLENGE_MESSAGE to the client. An alternate name for this field is
-# NTLMSSP_NEGOTIATE_NTLM
-NTLMSSP_NEGOTIATE_NTLM = 0x00000200
-NTLMSSP_RESERVED_8 = 0x00000100
-
-# If set, requests LAN Manager (LM) session key computation. NTLMSSP_NEGOTIATE_LM_KEY and
-# NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY are mutually exclusive. If both NTLMSSP_NEGOTIATE_LM_KEY and
-# NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY are requested, NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY alone MUST be
-# returned to the client. NTLM v2 authentication session key generation MUST be supported by both the client and the
-# DC in order to be used, and extended session security signing and sealing requires support from the client and the
-# server to be used. An alternate name for this field is NTLMSSP_NEGOTIATE_LM_KEY.
-NTLMSSP_NEGOTIATE_LM_KEY = 0x00000080
-
-# If set, requests connectionless authentication. If NTLMSSP_NEGOTIATE_DATAGRAM is set, then NTLMSSP_NEGOTIATE_KEY_EXCH
-# MUST always be set in the AUTHENTICATE_MESSAGE to the server and the CHALLENGE_MESSAGE to the client. An alternate
-# name for this field is NTLMSSP_NEGOTIATE_DATAGRAM.
-NTLMSSP_NEGOTIATE_DATAGRAM = 0x00000040
-
-# If set, requests session key negotiation for message confidentiality. If the client sends NTLMSSP_NEGOTIATE_SEAL to
-# the server in the NEGOTIATE_MESSAGE, the server MUST return NTLMSSP_NEGOTIATE_SEAL to the client in the
-# CHALLENGE_MESSAGE. Clients and servers that set NTLMSSP_NEGOTIATE_SEAL SHOULD always set NTLMSSP_NEGOTIATE_56 and
-# NTLMSSP_NEGOTIATE_128, if they are supported. An alternate name for this field is NTLMSSP_NEGOTIATE_SEAL.
-NTLMSSP_NEGOTIATE_SEAL = 0x00000020
-
-# If set, requests session key negotiation for message signatures. If the client sends NTLMSSP_NEGOTIATE_SIGN to the
-# server in the NEGOTIATE_MESSAGE, the server MUST return NTLMSSP_NEGOTIATE_SIGN to the client in the CHALLENGE_MESSAGE.
-# An alternate name for this field is NTLMSSP_NEGOTIATE_SIGN.
-NTLMSSP_NEGOTIATE_SIGN = 0x00000010 # means packet is signed, if verifier is wrong it fails
-NTLMSSP_RESERVED_9 = 0x00000008
-
-# If set, a TargetName field of the CHALLENGE_MESSAGE (section 2.2.1.2) MUST be supplied. An alternate name for this
-# field is NTLMSSP_REQUEST_TARGET.
-NTLMSSP_REQUEST_TARGET = 0x00000004
-
-# If set, requests OEM character set encoding. An alternate name for this field is NTLM_NEGOTIATE_OEM. See bit A for
-# details.
-NTLM_NEGOTIATE_OEM = 0x00000002
-
-# If set, requests Unicode character set encoding. An alternate name for this field is NTLMSSP_NEGOTIATE_UNICODE.
-NTLMSSP_NEGOTIATE_UNICODE = 0x00000001
-
-# AV_PAIR constants
-NTLMSSP_AV_EOL = 0x00
-NTLMSSP_AV_HOSTNAME = 0x01
-NTLMSSP_AV_DOMAINNAME = 0x02
-NTLMSSP_AV_DNS_HOSTNAME = 0x03
-NTLMSSP_AV_DNS_DOMAINNAME = 0x04
-NTLMSSP_AV_DNS_TREENAME = 0x05
-NTLMSSP_AV_FLAGS = 0x06
-NTLMSSP_AV_TIME = 0x07
-NTLMSSP_AV_RESTRICTIONS = 0x08
-NTLMSSP_AV_TARGET_NAME = 0x09
-NTLMSSP_AV_CHANNEL_BINDINGS = 0x0a
-
-class AV_PAIRS():
- def __init__(self, data = None):
- self.fields = {}
- if data is not None:
- self.fromString(data)
-
- def __setitem__(self,key,value):
- self.fields[key] = (len(value),value)
-
- def __getitem__(self, key):
- if key in self.fields:
- return self.fields[key]
- return None
-
- def __delitem__(self, key):
- del self.fields[key]
-
- def __len__(self):
- return len(self.getData())
-
- def __str__(self):
- return len(self.getData())
-
- def fromString(self, data):
- tInfo = data
- fType = 0xff
- while fType is not NTLMSSP_AV_EOL:
- fType = struct.unpack('<H',tInfo[:struct.calcsize('<H')])[0]
- tInfo = tInfo[struct.calcsize('<H'):]
- length = struct.unpack('<H',tInfo[:struct.calcsize('<H')])[0]
- tInfo = tInfo[struct.calcsize('<H'):]
- content = tInfo[:length]
- self.fields[fType]=(length,content)
- tInfo = tInfo[length:]
-
- def dump(self):
- for i in self.fields.keys():
- print("%s: {%r}" % (i,self[i]))
-
- def getData(self):
- if NTLMSSP_AV_EOL in self.fields:
- del self.fields[NTLMSSP_AV_EOL]
- ans = ''
- for i in self.fields.keys():
- ans+= struct.pack('<HH', i, self[i][0])
- ans+= self[i][1]
-
- # end with a NTLMSSP_AV_EOL
- ans += struct.pack('<HH', NTLMSSP_AV_EOL, 0)
-
- return ans
-
-class NTLMAuthMixin:
- def get_os_version(self):
- if self['os_version'] == '':
- return None
- else:
- mayor_v = struct.unpack('B',self['os_version'][0])[0]
- minor_v = struct.unpack('B',self['os_version'][1])[0]
- build_v = struct.unpack('H',self['os_version'][2:4])
- return (mayor_v,minor_v,build_v)
-
-class NTLMAuthNegotiate(Structure, NTLMAuthMixin):
-
- structure = (
- ('','"NTLMSSP\x00'),
- ('message_type','<L=1'),
- ('flags','<L'),
- ('domain_len','<H-domain_name'),
- ('domain_max_len','<H-domain_name'),
- ('domain_offset','<L=0'),
- ('host_len','<H-host_name'),
- ('host_maxlen','<H-host_name'),
- ('host_offset','<L=0'),
- ('os_version',':'),
- ('host_name',':'),
- ('domain_name',':'))
-
- def __init__(self):
- Structure.__init__(self)
- self['flags']= (
- NTLMSSP_NEGOTIATE_128 |
- NTLMSSP_NEGOTIATE_KEY_EXCH|
- # NTLMSSP_LM_KEY |
- NTLMSSP_NEGOTIATE_NTLM |
- NTLMSSP_NEGOTIATE_UNICODE |
- # NTLMSSP_ALWAYS_SIGN |
- NTLMSSP_NEGOTIATE_SIGN |
- NTLMSSP_NEGOTIATE_SEAL |
- # NTLMSSP_TARGET |
- 0)
- self['host_name']=''
- self['domain_name']=''
- self['os_version']=''
-
- def getData(self):
- if len(self.fields['host_name']) > 0:
- self['flags'] |= NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED
- if len(self.fields['domain_name']) > 0:
- self['flags'] |= NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED
- if len(self.fields['os_version']) > 0:
- self['flags'] |= NTLMSSP_NEGOTIATE_VERSION
- if (self['flags'] & NTLMSSP_NEGOTIATE_VERSION) == NTLMSSP_NEGOTIATE_VERSION:
- version_len = 8
- else:
- version_len = 0
- if (self['flags'] & NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED) == NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED:
- self['host_offset']=32 + version_len
- if (self['flags'] & NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED) == NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED:
- self['domain_offset']=32+len(self['host_name']) + version_len
- return Structure.getData(self)
-
- def fromString(self,data):
- Structure.fromString(self,data)
-
- domain_offset = self['domain_offset']
- domain_end = self['domain_len'] + domain_offset
- self['domain_name'] = data[ domain_offset : domain_end ]
-
- host_offset = self['host_offset']
- host_end = self['host_len'] + host_offset
- self['host_name'] = data[ host_offset : host_end ]
-
- hasOsInfo = self['flags'] & NTLMSSP_NEGOTIATE_VERSION
- if len(data) >= 36 and hasOsInfo:
- self['os_version'] = data[32:40]
- else:
- self['os_version'] = ''
-
-class NTLMAuthChallenge(Structure):
-
- structure = (
- ('','"NTLMSSP\x00'),
- ('message_type','<L=2'),
- ('domain_len','<H-domain_name'),
- ('domain_max_len','<H-domain_name'),
- ('domain_offset','<L=40'),
- ('flags','<L=0'),
- ('challenge','8s'),
- ('reserved','8s=""'),
- ('TargetInfoFields_len','<H-TargetInfoFields'),
- ('TargetInfoFields_max_len','<H-TargetInfoFields'),
- ('TargetInfoFields_offset','<L'),
- ('VersionLen','_-Version','self.checkVersion(self["flags"])'),
- ('Version',':'),
- ('domain_name',':'),
- ('TargetInfoFields',':'))
-
- def checkVersion(self, flags):
- if flags is not None:
- if flags & NTLMSSP_NEGOTIATE_VERSION == 0:
- return 0
- return 8
-
- def getData(self):
- if self['TargetInfoFields'] is not None and type(self['TargetInfoFields']) is not str:
- raw_av_fields = self['TargetInfoFields'].getData()
- self['TargetInfoFields'] = raw_av_fields
- return Structure.getData(self)
-
- def fromString(self,data):
- Structure.fromString(self,data)
- # Just in case there's more data after the TargetInfoFields
- self['TargetInfoFields'] = self['TargetInfoFields'][:self['TargetInfoFields_len']]
- # We gotta process the TargetInfoFields
- #if self['TargetInfoFields_len'] > 0:
- # av_pairs = AV_PAIRS(self['TargetInfoFields'][:self['TargetInfoFields_len']])
- # self['TargetInfoFields'] = av_pairs
-
- return self
-
-class NTLMAuthChallengeResponse(Structure, NTLMAuthMixin):
-
- structure = (
- ('','"NTLMSSP\x00'),
- ('message_type','<L=3'),
- ('lanman_len','<H-lanman'),
- ('lanman_max_len','<H-lanman'),
- ('lanman_offset','<L'),
- ('ntlm_len','<H-ntlm'),
- ('ntlm_max_len','<H-ntlm'),
- ('ntlm_offset','<L'),
- ('domain_len','<H-domain_name'),
- ('domain_max_len','<H-domain_name'),
- ('domain_offset','<L'),
- ('user_len','<H-user_name'),
- ('user_max_len','<H-user_name'),
- ('user_offset','<L'),
- ('host_len','<H-host_name'),
- ('host_max_len','<H-host_name'),
- ('host_offset','<L'),
- ('session_key_len','<H-session_key'),
- ('session_key_max_len','<H-session_key'),
- ('session_key_offset','<L'),
- ('flags','<L'),
- ('VersionLen','_-Version','self.checkVersion(self["flags"])'),
- ('Version',':=""'),
- ('MICLen','_-MIC','self.checkMIC(self["flags"])'),
- ('MIC',':=""'),
- ('domain_name',':'),
- ('user_name',':'),
- ('host_name',':'),
- ('lanman',':'),
- ('ntlm',':'),
- ('session_key',':'))
-
- def __init__(self, username = '', password = '', challenge = '', lmhash = '', nthash = '', flags = 0):
- Structure.__init__(self)
- self['session_key']=''
- self['user_name']=username.encode('utf-16le')
- self['domain_name']='' #"CLON".encode('utf-16le')
- self['host_name']='' #"BETS".encode('utf-16le')
- self['flags'] = ( #authResp['flags']
- # we think (beto & gera) that his flags force a memory conten leakage when a windows 2000 answers using uninitializaed verifiers
- NTLMSSP_NEGOTIATE_128 |
- NTLMSSP_NEGOTIATE_KEY_EXCH|
- # NTLMSSP_LM_KEY |
- NTLMSSP_NEGOTIATE_NTLM |
- NTLMSSP_NEGOTIATE_UNICODE |
- # NTLMSSP_ALWAYS_SIGN |
- NTLMSSP_NEGOTIATE_SIGN |
- NTLMSSP_NEGOTIATE_SEAL |
- # NTLMSSP_TARGET |
- 0)
- # Here we do the stuff
- if username and ( lmhash != '' or nthash != ''):
- self['lanman'] = get_ntlmv1_response(lmhash, challenge)
- self['ntlm'] = get_ntlmv1_response(nthash, challenge)
- elif (username and password):
- lmhash = compute_lmhash(password)
- nthash = compute_nthash(password)
- self['lanman']=get_ntlmv1_response(lmhash, challenge)
- self['ntlm']=get_ntlmv1_response(nthash, challenge) # This is not used for LM_KEY nor NTLM_KEY
- else:
- self['lanman'] = ''
- self['ntlm'] = ''
- if not self['host_name']:
- self['host_name'] = 'NULL'.encode('utf-16le') # for NULL session there must be a hostname
-
- def checkVersion(self, flags):
- if flags is not None:
- if flags & NTLMSSP_NEGOTIATE_VERSION == 0:
- return 0
- return 8
-
- def checkMIC(self, flags):
- # TODO: Find a proper way to check the MIC is in there
- if flags is not None:
- if flags & NTLMSSP_NEGOTIATE_VERSION == 0:
- return 0
- return 16
-
- def getData(self):
- self['domain_offset']=64+self.checkMIC(self["flags"])+self.checkVersion(self["flags"])
- self['user_offset']=64+self.checkMIC(self["flags"])+self.checkVersion(self["flags"])+len(self['domain_name'])
- self['host_offset']=self['user_offset']+len(self['user_name'])
- self['lanman_offset']=self['host_offset']+len(self['host_name'])
- self['ntlm_offset']=self['lanman_offset']+len(self['lanman'])
- self['session_key_offset']=self['ntlm_offset']+len(self['ntlm'])
- return Structure.getData(self)
-
- def fromString(self,data):
- Structure.fromString(self,data)
- # [MS-NLMP] page 27
- # Payload data can be present in any order within the Payload field,
- # with variable-length padding before or after the data
-
- domain_offset = self['domain_offset']
- domain_end = self['domain_len'] + domain_offset
- self['domain_name'] = data[ domain_offset : domain_end ]
-
- host_offset = self['host_offset']
- host_end = self['host_len'] + host_offset
- self['host_name'] = data[ host_offset: host_end ]
-
- user_offset = self['user_offset']
- user_end = self['user_len'] + user_offset
- self['user_name'] = data[ user_offset: user_end ]
-
- ntlm_offset = self['ntlm_offset']
- ntlm_end = self['ntlm_len'] + ntlm_offset
- self['ntlm'] = data[ ntlm_offset : ntlm_end ]
-
- lanman_offset = self['lanman_offset']
- lanman_end = self['lanman_len'] + lanman_offset
- self['lanman'] = data[ lanman_offset : lanman_end]
-
- #if len(data) >= 36:
- # self['os_version'] = data[32:36]
- #else:
- # self['os_version'] = ''
-
-class ImpacketStructure(Structure):
- def set_parent(self, other):
- self.parent = other
-
- def get_packet(self):
- return str(self)
-
- def get_size(self):
- return len(self)
-
-class ExtendedOrNotMessageSignature(Structure):
- def __init__(self, flags = 0, **kargs):
- if flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY:
- self.structure = self.extendedMessageSignature
- else:
- self.structure = self.MessageSignature
- return Structure.__init__(self, **kargs)
-
-class NTLMMessageSignature(ExtendedOrNotMessageSignature):
- extendedMessageSignature = (
- ('Version','<L=1'),
- ('Checksum','<q'),
- ('SeqNum','<i'),
- )
-
- MessageSignature = (
- ('Version','<L=1'),
- ('RandomPad','<i=0'),
- ('Checksum','<i'),
- ('SeqNum','<i'),
- )
-
-KNOWN_DES_INPUT = "KGS!@#$%"
-
-def __expand_DES_key( key):
- # Expand the key from a 7-byte password key into a 8-byte DES key
- key = key[:7]
- key += '\x00'*(7-len(key))
- s = chr(((ord(key[0]) >> 1) & 0x7f) << 1)
- s = s + chr(((ord(key[0]) & 0x01) << 6 | ((ord(key[1]) >> 2) & 0x3f)) << 1)
- s = s + chr(((ord(key[1]) & 0x03) << 5 | ((ord(key[2]) >> 3) & 0x1f)) << 1)
- s = s + chr(((ord(key[2]) & 0x07) << 4 | ((ord(key[3]) >> 4) & 0x0f)) << 1)
- s = s + chr(((ord(key[3]) & 0x0f) << 3 | ((ord(key[4]) >> 5) & 0x07)) << 1)
- s = s + chr(((ord(key[4]) & 0x1f) << 2 | ((ord(key[5]) >> 6) & 0x03)) << 1)
- s = s + chr(((ord(key[5]) & 0x3f) << 1 | ((ord(key[6]) >> 7) & 0x01)) << 1)
- s = s + chr((ord(key[6]) & 0x7f) << 1)
- return s
-
-def __DES_block(key, msg):
- if POW:
- cipher = POW.Symmetric(POW.DES_ECB)
- cipher.encryptInit(__expand_DES_key(key))
- return cipher.update(msg)
- else:
- cipher = DES.new(__expand_DES_key(key),DES.MODE_ECB)
- return cipher.encrypt(msg)
-
-def ntlmssp_DES_encrypt(key, challenge):
- answer = __DES_block(key[:7], challenge)
- answer += __DES_block(key[7:14], challenge)
- answer += __DES_block(key[14:], challenge)
- return answer
-
-# High level functions to use NTLMSSP
-
-def getNTLMSSPType1(workstation='', domain='', signingRequired = False, use_ntlmv2 = USE_NTLMv2):
- # Let's do some encoding checks before moving on. Kind of dirty, but found effective when dealing with
- # international characters.
- import sys
- encoding = sys.getfilesystemencoding()
- if encoding is not None:
- try:
- workstation.encode('utf-16le')
- except:
- workstation = workstation.decode(encoding)
- try:
- domain.encode('utf-16le')
- except:
- domain = domain.decode(encoding)
-
- # Let's prepare a Type 1 NTLMSSP Message
- auth = NTLMAuthNegotiate()
- auth['flags']=0
- if signingRequired:
- auth['flags'] = NTLMSSP_NEGOTIATE_KEY_EXCH | NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_ALWAYS_SIGN | NTLMSSP_NEGOTIATE_SEAL
- if use_ntlmv2:
- auth['flags'] |= NTLMSSP_NEGOTIATE_TARGET_INFO
- auth['flags'] |= NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY | NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_56
- auth['domain_name'] = domain.encode('utf-16le')
- return auth
-
-def getNTLMSSPType3(type1, type2, user, password, domain, lmhash = '', nthash = '', use_ntlmv2 = USE_NTLMv2):
-
- # Let's do some encoding checks before moving on. Kind of dirty, but found effective when dealing with
- # international characters.
- import sys
- encoding = sys.getfilesystemencoding()
- if encoding is not None:
- try:
- user.encode('utf-16le')
- except:
- user = user.decode(encoding)
- try:
- password.encode('utf-16le')
- except:
- password = password.decode(encoding)
- try:
- domain.encode('utf-16le')
- except:
- domain = user.decode(encoding)
-
- ntlmChallenge = NTLMAuthChallenge(type2)
-
- # Let's start with the original flags sent in the type1 message
- responseFlags = type1['flags']
-
- # Token received and parsed. Depending on the authentication
- # method we will create a valid ChallengeResponse
- ntlmChallengeResponse = NTLMAuthChallengeResponse(user, password, ntlmChallenge['challenge'])
-
- clientChallenge = "".join([random.choice(string.digits+string.letters) for i in range(8)])
-
- serverName = ntlmChallenge['TargetInfoFields']
-
- ntResponse, lmResponse, sessionBaseKey = computeResponse(ntlmChallenge['flags'], ntlmChallenge['challenge'], clientChallenge, serverName, domain, user, password, lmhash, nthash, use_ntlmv2 )
-
- # Let's check the return flags
- if (ntlmChallenge['flags'] & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY) == 0:
- # No extended session security, taking it out
- responseFlags &= 0xffffffff ^ NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY
- if (ntlmChallenge['flags'] & NTLMSSP_NEGOTIATE_128 ) == 0:
- # No support for 128 key len, taking it out
- responseFlags &= 0xffffffff ^ NTLMSSP_NEGOTIATE_128
- if (ntlmChallenge['flags'] & NTLMSSP_NEGOTIATE_KEY_EXCH) == 0:
- # No key exchange supported, taking it out
- responseFlags &= 0xffffffff ^ NTLMSSP_NEGOTIATE_KEY_EXCH
- if (ntlmChallenge['flags'] & NTLMSSP_NEGOTIATE_SEAL) == 0:
- # No sign available, taking it out
- responseFlags &= 0xffffffff ^ NTLMSSP_NEGOTIATE_SEAL
- if (ntlmChallenge['flags'] & NTLMSSP_NEGOTIATE_SIGN) == 0:
- # No sign available, taking it out
- responseFlags &= 0xffffffff ^ NTLMSSP_NEGOTIATE_SIGN
- if (ntlmChallenge['flags'] & NTLMSSP_NEGOTIATE_ALWAYS_SIGN) == 0:
- # No sign available, taking it out
- responseFlags &= 0xffffffff ^ NTLMSSP_NEGOTIATE_ALWAYS_SIGN
-
- keyExchangeKey = KXKEY(ntlmChallenge['flags'],sessionBaseKey, lmResponse, ntlmChallenge['challenge'], password, lmhash, nthash,use_ntlmv2)
-
- # Special case for anonymous login
- if user == '' and password == '' and lmhash == '' and nthash == '':
- keyExchangeKey = '\x00'*16
-
- # If we set up key exchange, let's fill the right variables
- if ntlmChallenge['flags'] & NTLMSSP_NEGOTIATE_KEY_EXCH:
- # not exactly what I call random tho :\
- # exportedSessionKey = this is the key we should use to sign
- exportedSessionKey = "".join([random.choice(string.digits+string.letters) for i in range(16)])
- #exportedSessionKey = "A"*16
- #print "keyExchangeKey %r" % keyExchangeKey
- # Let's generate the right session key based on the challenge flags
- #if responseFlags & NTLMSSP_NTLM2_KEY:
- # Extended session security enabled
- # if responseFlags & NTLMSSP_KEY_128:
- # Full key
- # exportedSessionKey = exportedSessionKey
- # elif responseFlags & NTLMSSP_KEY_56:
- # Only 56-bit key
- # exportedSessionKey = exportedSessionKey[:7]
- # else:
- # exportedSessionKey = exportedSessionKey[:5]
- #elif responseFlags & NTLMSSP_KEY_56:
- # No extended session security, just 56 bits key
- # exportedSessionKey = exportedSessionKey[:7] + '\xa0'
- #else:
- # exportedSessionKey = exportedSessionKey[:5] + '\xe5\x38\xb0'
-
- encryptedRandomSessionKey = generateEncryptedSessionKey(keyExchangeKey, exportedSessionKey)
- else:
- encryptedRandomSessionKey = None
- # [MS-NLMP] page 46
- exportedSessionKey = keyExchangeKey
-
- ntlmChallengeResponse['flags'] = responseFlags
- ntlmChallengeResponse['domain_name'] = domain.encode('utf-16le')
- ntlmChallengeResponse['lanman'] = lmResponse
- ntlmChallengeResponse['ntlm'] = ntResponse
- if encryptedRandomSessionKey is not None:
- ntlmChallengeResponse['session_key'] = encryptedRandomSessionKey
-
- return ntlmChallengeResponse, exportedSessionKey
-
-
-# NTLMv1 Algorithm
-
-def generateSessionKeyV1(password, lmhash, nthash):
- if POW:
- hash = POW.Digest(POW.MD4_DIGEST)
- else:
- hash = MD4.new()
- hash.update(NTOWFv1(password, lmhash, nthash))
- return hash.digest()
-
-def computeResponseNTLMv1(flags, serverChallenge, clientChallenge, serverName, domain, user, password, lmhash='', nthash='', use_ntlmv2 = USE_NTLMv2):
- if (user == '' and password == ''):
- # Special case for anonymous authentication
- lmResponse = ''
- ntResponse = ''
- else:
- lmhash = LMOWFv1(password, lmhash, nthash)
- nthash = NTOWFv1(password, lmhash, nthash)
- if flags & NTLMSSP_NEGOTIATE_LM_KEY:
- ntResponse = ''
- lmResponse = get_ntlmv1_response(lmhash, serverChallenge)
- elif flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY:
- md5 = hashlib.new('md5')
- chall = (serverChallenge + clientChallenge)
- md5.update(chall)
- ntResponse = ntlmssp_DES_encrypt(nthash, md5.digest()[:8])
- lmResponse = clientChallenge + '\x00'*16
- else:
- ntResponse = get_ntlmv1_response(nthash,serverChallenge)
- lmResponse = get_ntlmv1_response(lmhash, serverChallenge)
-
- sessionBaseKey = generateSessionKeyV1(password, lmhash, nthash)
- return ntResponse, lmResponse, sessionBaseKey
-
-def compute_lmhash(password):
- # This is done according to Samba's encryption specification (docs/html/ENCRYPTION.html)
- password = password.upper()
- lmhash = __DES_block(password[:7], KNOWN_DES_INPUT)
- lmhash += __DES_block(password[7:14], KNOWN_DES_INPUT)
- return lmhash
-
-def NTOWFv1(password, lmhash = '', nthash=''):
- if nthash != '':
- return nthash
- return compute_nthash(password)
-
-def LMOWFv1(password, lmhash = '', nthash=''):
- if lmhash != '':
- return lmhash
- return compute_lmhash(password)
-
-def compute_nthash(password):
- # This is done according to Samba's encryption specification (docs/html/ENCRYPTION.html)
- try:
- password = unicode(password).encode('utf_16le')
- except NameError: # unicode() was removed in Python 3
- password = str(password).encode('utf_16le')
- except UnicodeDecodeError:
- import sys
- password = password.decode(sys.getfilesystemencoding()).encode('utf_16le')
-
- if POW:
- hash = POW.Digest(POW.MD4_DIGEST)
- else:
- hash = MD4.new()
- hash.update(password)
- return hash.digest()
-
-def get_ntlmv1_response(key, challenge):
- return ntlmssp_DES_encrypt(key, challenge)
-
-# NTLMv2 Algorithm - as described in MS-NLMP Section 3.3.2
-
-# Crypto Stuff
-
-def MAC(flags, handle, signingKey, seqNum, message):
- # [MS-NLMP] Section 3.4.4
- # Returns the right messageSignature depending on the flags
- messageSignature = NTLMMessageSignature(flags)
- if flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY:
- if flags & NTLMSSP_NEGOTIATE_KEY_EXCH:
- messageSignature['Version'] = 1
- messageSignature['Checksum'] = struct.unpack('<q',handle(hmac_md5(signingKey, struct.pack('<i',seqNum)+message)[:8]))[0]
- messageSignature['SeqNum'] = seqNum
- seqNum += 1
- else:
- messageSignature['Version'] = 1
- messageSignature['Checksum'] = struct.unpack('<q',hmac_md5(signingKey, struct.pack('<i',seqNum)+message)[:8])[0]
- messageSignature['SeqNum'] = seqNum
- seqNum += 1
- else:
- messageSignature['Version'] = 1
- messageSignature['Checksum'] = struct.pack('<i',binascii.crc32(message))
- messageSignature['RandomPad'] = 0
- messageSignature['RandomPad'] = handle(struct.pack('<i',messageSignature['RandomPad']))
- messageSignature['Checksum'] = struct.unpack('<i',handle(messageSignature['Checksum']))[0]
- messageSignature['SeqNum'] = handle('\x00\x00\x00\x00')
- messageSignature['SeqNum'] = struct.unpack('<i',messageSignature['SeqNum'])[0] ^ seqNum
- messageSignature['RandomPad'] = 0
-
- return messageSignature
-
-def SEAL(flags, signingKey, sealingKey, messageToSign, messageToEncrypt, seqNum, handle):
- sealedMessage = handle(messageToEncrypt)
- signature = MAC(flags, handle, signingKey, seqNum, messageToSign)
- return sealedMessage, signature
-
-def SIGN(flags, signingKey, message, seqNum, handle):
- return MAC(flags, handle, signingKey, seqNum, message)
-
-def SIGNKEY(flags, randomSessionKey, mode = 'Client'):
- if flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY:
- if mode == 'Client':
- md5 = hashlib.new('md5')
- md5.update(randomSessionKey + "session key to client-to-server signing key magic constant\x00")
- signKey = md5.digest()
- else:
- md5 = hashlib.new('md5')
- md5.update(randomSessionKey + "session key to server-to-client signing key magic constant\x00")
- signKey = md5.digest()
- else:
- signKey = None
- return signKey
-
-def SEALKEY(flags, randomSessionKey, mode = 'Client'):
- if flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY:
- if flags & NTLMSSP_NEGOTIATE_128:
- sealKey = randomSessionKey
- elif flags & NTLMSSP_NEGOTIATE_56:
- sealKey = randomSessionKey[:7]
- else:
- sealKey = randomSessionKey[:5]
-
- if mode == 'Client':
- md5 = hashlib.new('md5')
- md5.update(sealKey + 'session key to client-to-server sealing key magic constant\x00')
- sealKey = md5.digest()
- else:
- md5 = hashlib.new('md5')
- md5.update(sealKey + 'session key to server-to-client sealing key magic constant\x00')
- sealKey = md5.digest()
-
- elif flags & NTLMSSP_NEGOTIATE_56:
- sealKey = randomSessionKey[:7] + '\xa0'
- else:
- sealKey = randomSessionKey[:5] + '\xe5\x38\xb0'
-
- return sealKey
-
-
-def generateEncryptedSessionKey(keyExchangeKey, exportedSessionKey):
- if POW:
- cipher = POW.Symmetric(POW.RC4)
- cipher.encryptInit(keyExchangeKey)
- cipher_encrypt = cipher.update
- else:
- cipher = ARC4.new(keyExchangeKey)
- cipher_encrypt = cipher.encrypt
-
- sessionKey = cipher_encrypt(exportedSessionKey)
- return sessionKey
-
-def KXKEY(flags, sessionBaseKey, lmChallengeResponse, serverChallenge, password, lmhash, nthash, use_ntlmv2 = USE_NTLMv2):
- if use_ntlmv2:
- return sessionBaseKey
-
- if flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY:
- if flags & NTLMSSP_NEGOTIATE_NTLM:
- keyExchangeKey = hmac_md5(sessionBaseKey, serverChallenge + lmChallengeResponse[:8])
- else:
- keyExchangeKey = sessionBaseKey
- elif flags & NTLMSSP_NEGOTIATE_NTLM:
- if flags & NTLMSSP_NEGOTIATE_LM_KEY:
- keyExchangeKey = __DES_block(LMOWFv1(password,lmhash)[:7], lmChallengeResponse[:8]) + __DES_block(LMOWFv1(password,lmhash)[7] + '\xBD\xBD\xBD\xBD\xBD\xBD', lmChallengeResponse[:8])
- elif flags & NTLMSSP_REQUEST_NON_NT_SESSION_KEY:
- keyExchangeKey = LMOWFv1(password,lmhash)[:8] + '\x00'*8
- else:
- keyExchangeKey = sessionBaseKey
- else:
- raise "Can't create a valid KXKEY!"
-
- return keyExchangeKey
-
-def hmac_md5(key, data):
- if POW:
- h = POW.Hmac(POW.MD5_DIGEST, key)
- h.update(data)
- result = h.mac()
- else:
- import hmac
- h = hmac.new(key)
- h.update(data)
- result = h.digest()
- return result
-
-def NTOWFv2( user, password, domain, hash = ''):
- if hash != '':
- theHash = hash
- else:
- theHash = compute_nthash(password)
- return hmac_md5(theHash, user.upper().encode('utf-16le') + domain.encode('utf-16le'))
-
-def LMOWFv2( user, password, domain, lmhash = ''):
- return NTOWFv2( user, password, domain, lmhash)
-
-
-def computeResponseNTLMv2(flags, serverChallenge, clientChallenge, serverName, domain, user, password, lmhash = '', nthash = '', use_ntlmv2 = USE_NTLMv2):
-
- responseServerVersion = '\x01'
- hiResponseServerVersion = '\x01'
- responseKeyNT = NTOWFv2(user, password, domain, nthash)
- responseKeyLM = LMOWFv2(user, password, domain, lmhash)
-
- # If you're running test-ntlm, comment the following lines and uncoment the ones that are commented. Don't forget to turn it back after the tests!
- ######################
- av_pairs = AV_PAIRS(serverName)
- # In order to support SPN target name validation, we have to add this to the serverName av_pairs. Otherwise we will get access denied
- # This is set at Local Security Policy -> Local Policies -> Security Options -> Server SPN target name validation level
- av_pairs[NTLMSSP_AV_TARGET_NAME] = 'cifs/'.encode('utf-16le') + av_pairs[NTLMSSP_AV_HOSTNAME][1]
- if av_pairs[NTLMSSP_AV_TIME] is not None:
- aTime = av_pairs[NTLMSSP_AV_TIME][1]
- else:
- aTime = struct.pack('<q', (116444736000000000 + calendar.timegm(time.gmtime()) * 10000000) )
- #aTime = '\x00'*8
- av_pairs[NTLMSSP_AV_TIME] = aTime
- serverName = av_pairs.getData()
-
- ######################
- #aTime = '\x00'*8
- ######################
- temp = responseServerVersion + hiResponseServerVersion + '\x00' * 6 + aTime + clientChallenge + '\x00' * 4 + serverName + '\x00' * 4
-
- ntProofStr = hmac_md5(responseKeyNT, serverChallenge + temp)
-
- ntChallengeResponse = ntProofStr + temp
- lmChallengeResponse = hmac_md5(responseKeyNT, serverChallenge + clientChallenge) + clientChallenge
- sessionBaseKey = hmac_md5(responseKeyNT, ntProofStr)
-
- if (user == '' and password == ''):
- # Special case for anonymous authentication
- ntChallengeResponse = ''
- lmChallengeResponse = ''
-
- return ntChallengeResponse, lmChallengeResponse, sessionBaseKey
-
-class NTLM_HTTP(object):
- '''Parent class for NTLM HTTP classes.'''
- MSG_TYPE = None
-
- @classmethod
- def get_instace(cls,msg_64):
- msg = None
- msg_type = 0
- if msg_64 != '':
- msg = base64.b64decode(msg_64[5:]) # Remove the 'NTLM '
- msg_type = ord(msg[8])
-
- for _cls in NTLM_HTTP.__subclasses__():
- if msg_type == _cls.MSG_TYPE:
- instance = _cls()
- instance.fromString(msg)
- return instance
-
-
-class NTLM_HTTP_AuthRequired(NTLM_HTTP):
- commonHdr = ()
- # Message 0 means the first HTTP request e.g. 'GET /bla.png'
- MSG_TYPE = 0
-
- def fromString(self,data):
- pass
-
-
-class NTLM_HTTP_AuthNegotiate(NTLM_HTTP, NTLMAuthNegotiate):
- commonHdr = ()
- MSG_TYPE = 1
-
- def __init__(self):
- NTLMAuthNegotiate.__init__(self)
-
-
-class NTLM_HTTP_AuthChallengeResponse(NTLM_HTTP, NTLMAuthChallengeResponse):
- commonHdr = ()
- MSG_TYPE = 3
-
- def __init__(self):
- NTLMAuthChallengeResponse.__init__(self)