ntlm.py 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973
  1. from __future__ import print_function
  2. # Copyright (c) 2003-2016 CORE Security Technologies:
  3. #
  4. # This software is provided under under a slightly modified version
  5. # of the Apache Software License. See the accompanying LICENSE file
  6. # for more information.
  7. #
  8. import base64
  9. import struct
  10. import calendar
  11. import time
  12. import hashlib
  13. import random
  14. import string
  15. import binascii
  16. from impacket.structure import Structure
  17. from impacket import LOG
  18. # This is important. NTLMv2 is not negotiated by the client or server.
  19. # It is used if set locally on both sides. Change this item if you don't want to use
  20. # NTLMv2 by default and fall back to NTLMv1 (with EXTENDED_SESSION_SECURITY or not)
  21. # Check the following links:
  22. # http://davenport.sourceforge.net/ntlm.html
  23. # http://blogs.msdn.com/b/openspecification/archive/2010/04/20/ntlm-keys-and-sundry-stuff.aspx
  24. # http://social.msdn.microsoft.com/Forums/en-US/os_interopscenarios/thread/c8f488ed-1b96-4e06-bd65-390aa41138d1/
  25. # So I'm setting a global variable to control this, this can also be set programmatically
  26. USE_NTLMv2 = True # if false will fall back to NTLMv1 (or NTLMv1 with ESS a.k.a NTLM2)
  27. def computeResponse(flags, serverChallenge, clientChallenge, serverName, domain, user, password, lmhash='', nthash='',
  28. use_ntlmv2=USE_NTLMv2):
  29. if use_ntlmv2:
  30. return computeResponseNTLMv2(flags, serverChallenge, clientChallenge, serverName, domain, user, password,
  31. lmhash, nthash, use_ntlmv2=use_ntlmv2)
  32. else:
  33. return computeResponseNTLMv1(flags, serverChallenge, clientChallenge, serverName, domain, user, password,
  34. lmhash, nthash, use_ntlmv2=use_ntlmv2)
  35. try:
  36. POW = None
  37. from Crypto.Cipher import ARC4
  38. from Crypto.Cipher import DES
  39. from Crypto.Hash import MD4
  40. except Exception:
  41. try:
  42. import POW
  43. except Exception:
  44. LOG.critical("Warning: You don't have any crypto installed. You need PyCrypto")
  45. LOG.critical("See http://www.pycrypto.org/")
  46. NTLM_AUTH_NONE = 1
  47. NTLM_AUTH_CONNECT = 2
  48. NTLM_AUTH_CALL = 3
  49. NTLM_AUTH_PKT = 4
  50. NTLM_AUTH_PKT_INTEGRITY = 5
  51. NTLM_AUTH_PKT_PRIVACY = 6
  52. # If set, requests 56-bit encryption. If the client sends NTLMSSP_NEGOTIATE_SEAL or NTLMSSP_NEGOTIATE_SIGN
  53. # with NTLMSSP_NEGOTIATE_56 to the server in the NEGOTIATE_MESSAGE, the server MUST return NTLMSSP_NEGOTIATE_56 to
  54. # the client in the CHALLENGE_MESSAGE. Otherwise it is ignored. If both NTLMSSP_NEGOTIATE_56 and NTLMSSP_NEGOTIATE_128
  55. # are requested and supported by the client and server, NTLMSSP_NEGOTIATE_56 and NTLMSSP_NEGOTIATE_128 will both be
  56. # returned to the client. Clients and servers that set NTLMSSP_NEGOTIATE_SEAL SHOULD set NTLMSSP_NEGOTIATE_56 if it is
  57. # supported. An alternate name for this field is NTLMSSP_NEGOTIATE_56.
  58. NTLMSSP_NEGOTIATE_56 = 0x80000000
  59. # If set, requests an explicit key exchange. This capability SHOULD be used because it improves security for message
  60. # 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
  61. # this field is NTLMSSP_NEGOTIATE_KEY_EXCH.
  62. NTLMSSP_NEGOTIATE_KEY_EXCH = 0x40000000
  63. # If set, requests 128-bit session key negotiation. An alternate name for this field is NTLMSSP_NEGOTIATE_128.
  64. # If the client sends NTLMSSP_NEGOTIATE_128 to the server in the NEGOTIATE_MESSAGE, the server MUST return
  65. # NTLMSSP_NEGOTIATE_128 to the client in the CHALLENGE_MESSAGE only if the client sets NTLMSSP_NEGOTIATE_SEAL or
  66. # NTLMSSP_NEGOTIATE_SIGN. Otherwise it is ignored. If both NTLMSSP_NEGOTIATE_56 and NTLMSSP_NEGOTIATE_128 are
  67. # requested and supported by the client and server, NTLMSSP_NEGOTIATE_56 and NTLMSSP_NEGOTIATE_128 will both be
  68. # returned to the client. Clients and servers that set NTLMSSP_NEGOTIATE_SEAL SHOULD set NTLMSSP_NEGOTIATE_128 if it
  69. # is supported. An alternate name for this field is NTLMSSP_NEGOTIATE_128
  70. NTLMSSP_NEGOTIATE_128 = 0x20000000
  71. NTLMSSP_RESERVED_1 = 0x10000000
  72. NTLMSSP_RESERVED_2 = 0x08000000
  73. NTLMSSP_RESERVED_3 = 0x04000000
  74. # If set, requests the protocol version number. The data corresponding to this flag is provided in the Version field
  75. # of the NEGOTIATE_MESSAGE, the CHALLENGE_MESSAGE, and the AUTHENTICATE_MESSAGE.<22> An alternate name for this field
  76. # is NTLMSSP_NEGOTIATE_VERSION
  77. NTLMSSP_NEGOTIATE_VERSION = 0x02000000
  78. NTLMSSP_RESERVED_4 = 0x01000000
  79. # If set, indicates that the TargetInfo fields in the CHALLENGE_MESSAGE (section 2.2.1.2) are populated.
  80. # An alternate name for this field is NTLMSSP_NEGOTIATE_TARGET_INFO.
  81. NTLMSSP_NEGOTIATE_TARGET_INFO = 0x00800000
  82. # If set, requests the usage of the LMOWF (section 3.3). An alternate name for this field is
  83. # NTLMSSP_REQUEST_NON_NT_SESSION_KEY.
  84. NTLMSSP_REQUEST_NON_NT_SESSION_KEY = 0x00400000
  85. NTLMSSP_RESERVED_5 = 0x00200000
  86. # If set, requests an identify level token. An alternate name for this field is NTLMSSP_NEGOTIATE_IDENTIFY
  87. NTLMSSP_NEGOTIATE_IDENTIFY = 0x00100000
  88. # If set, requests usage of the NTLM v2 session security. NTLM v2 session security is a misnomer because it is not
  89. # NTLM v2. It is NTLM v1 using the extended session security that is also in NTLM v2. NTLMSSP_NEGOTIATE_LM_KEY and
  90. # NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY are mutually exclusive. If both NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY
  91. # and NTLMSSP_NEGOTIATE_LM_KEY are requested, NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY alone MUST be returned to the
  92. # client. NTLM v2 authentication session key generation MUST be supported by both the client and the DC in order to be
  93. # used, and extended session security signing and sealing requires support from the client and the server in order to
  94. # be used.<23> An alternate name for this field is NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY
  95. NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY = 0x00080000
  96. NTLMSSP_NEGOTIATE_NTLM2 = 0x00080000
  97. NTLMSSP_TARGET_TYPE_SHARE = 0x00040000
  98. # If set, TargetName MUST be a server name. The data corresponding to this flag is provided by the server in the
  99. # TargetName field of the CHALLENGE_MESSAGE. If this bit is set, then NTLMSSP_TARGET_TYPE_DOMAIN MUST NOT be set.
  100. # This flag MUST be ignored in the NEGOTIATE_MESSAGE and the AUTHENTICATE_MESSAGE. An alternate name for this field
  101. # is NTLMSSP_TARGET_TYPE_SERVER
  102. NTLMSSP_TARGET_TYPE_SERVER = 0x00020000
  103. # If set, TargetName MUST be a domain name. The data corresponding to this flag is provided by the server in the
  104. # TargetName field of the CHALLENGE_MESSAGE. If set, then NTLMSSP_TARGET_TYPE_SERVER MUST NOT be set. This flag MUST
  105. # be ignored in the NEGOTIATE_MESSAGE and the AUTHENTICATE_MESSAGE. An alternate name for this field is
  106. # NTLMSSP_TARGET_TYPE_DOMAIN.
  107. NTLMSSP_TARGET_TYPE_DOMAIN = 0x00010000
  108. # If set, requests the presence of a signature block on all messages. NTLMSSP_NEGOTIATE_ALWAYS_SIGN MUST be set in the
  109. # NEGOTIATE_MESSAGE to the server and the CHALLENGE_MESSAGE to the client. NTLMSSP_NEGOTIATE_ALWAYS_SIGN is overridden
  110. # by NTLMSSP_NEGOTIATE_SIGN and NTLMSSP_NEGOTIATE_SEAL, if they are supported. An alternate name for this field is
  111. # NTLMSSP_NEGOTIATE_ALWAYS_SIGN.
  112. NTLMSSP_NEGOTIATE_ALWAYS_SIGN = 0x00008000 # forces the other end to sign packets
  113. NTLMSSP_RESERVED_6 = 0x00004000
  114. # This flag indicates whether the Workstation field is present. If this flag is not set, the Workstation field MUST be
  115. # ignored. If this flag is set, the length field of the Workstation field specifies whether the workstation name is
  116. # nonempty or not.<24> An alternate name for this field is NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED.
  117. NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED = 0x00002000
  118. # If set, the domain name is provided (section 2.2.1.1).<25> An alternate name for this field is
  119. # NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED
  120. NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED = 0x00001000
  121. NTLMSSP_RESERVED_7 = 0x00000800
  122. # If set, LM authentication is not allowed and only NT authentication is used.
  123. NTLMSSP_NEGOTIATE_NT_ONLY = 0x00000400
  124. # If set, requests usage of the NTLM v1 session security protocol. NTLMSSP_NEGOTIATE_NTLM MUST be set in the
  125. # NEGOTIATE_MESSAGE to the server and the CHALLENGE_MESSAGE to the client. An alternate name for this field is
  126. # NTLMSSP_NEGOTIATE_NTLM
  127. NTLMSSP_NEGOTIATE_NTLM = 0x00000200
  128. NTLMSSP_RESERVED_8 = 0x00000100
  129. # If set, requests LAN Manager (LM) session key computation. NTLMSSP_NEGOTIATE_LM_KEY and
  130. # NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY are mutually exclusive. If both NTLMSSP_NEGOTIATE_LM_KEY and
  131. # NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY are requested, NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY alone MUST be
  132. # returned to the client. NTLM v2 authentication session key generation MUST be supported by both the client and the
  133. # DC in order to be used, and extended session security signing and sealing requires support from the client and the
  134. # server to be used. An alternate name for this field is NTLMSSP_NEGOTIATE_LM_KEY.
  135. NTLMSSP_NEGOTIATE_LM_KEY = 0x00000080
  136. # If set, requests connectionless authentication. If NTLMSSP_NEGOTIATE_DATAGRAM is set, then NTLMSSP_NEGOTIATE_KEY_EXCH
  137. # MUST always be set in the AUTHENTICATE_MESSAGE to the server and the CHALLENGE_MESSAGE to the client. An alternate
  138. # name for this field is NTLMSSP_NEGOTIATE_DATAGRAM.
  139. NTLMSSP_NEGOTIATE_DATAGRAM = 0x00000040
  140. # If set, requests session key negotiation for message confidentiality. If the client sends NTLMSSP_NEGOTIATE_SEAL to
  141. # the server in the NEGOTIATE_MESSAGE, the server MUST return NTLMSSP_NEGOTIATE_SEAL to the client in the
  142. # CHALLENGE_MESSAGE. Clients and servers that set NTLMSSP_NEGOTIATE_SEAL SHOULD always set NTLMSSP_NEGOTIATE_56 and
  143. # NTLMSSP_NEGOTIATE_128, if they are supported. An alternate name for this field is NTLMSSP_NEGOTIATE_SEAL.
  144. NTLMSSP_NEGOTIATE_SEAL = 0x00000020
  145. # If set, requests session key negotiation for message signatures. If the client sends NTLMSSP_NEGOTIATE_SIGN to the
  146. # server in the NEGOTIATE_MESSAGE, the server MUST return NTLMSSP_NEGOTIATE_SIGN to the client in the CHALLENGE_MESSAGE.
  147. # An alternate name for this field is NTLMSSP_NEGOTIATE_SIGN.
  148. NTLMSSP_NEGOTIATE_SIGN = 0x00000010 # means packet is signed, if verifier is wrong it fails
  149. NTLMSSP_RESERVED_9 = 0x00000008
  150. # If set, a TargetName field of the CHALLENGE_MESSAGE (section 2.2.1.2) MUST be supplied. An alternate name for this
  151. # field is NTLMSSP_REQUEST_TARGET.
  152. NTLMSSP_REQUEST_TARGET = 0x00000004
  153. # If set, requests OEM character set encoding. An alternate name for this field is NTLM_NEGOTIATE_OEM. See bit A for
  154. # details.
  155. NTLM_NEGOTIATE_OEM = 0x00000002
  156. # If set, requests Unicode character set encoding. An alternate name for this field is NTLMSSP_NEGOTIATE_UNICODE.
  157. NTLMSSP_NEGOTIATE_UNICODE = 0x00000001
  158. # AV_PAIR constants
  159. NTLMSSP_AV_EOL = 0x00
  160. NTLMSSP_AV_HOSTNAME = 0x01
  161. NTLMSSP_AV_DOMAINNAME = 0x02
  162. NTLMSSP_AV_DNS_HOSTNAME = 0x03
  163. NTLMSSP_AV_DNS_DOMAINNAME = 0x04
  164. NTLMSSP_AV_DNS_TREENAME = 0x05
  165. NTLMSSP_AV_FLAGS = 0x06
  166. NTLMSSP_AV_TIME = 0x07
  167. NTLMSSP_AV_RESTRICTIONS = 0x08
  168. NTLMSSP_AV_TARGET_NAME = 0x09
  169. NTLMSSP_AV_CHANNEL_BINDINGS = 0x0a
  170. class AV_PAIRS():
  171. def __init__(self, data = None):
  172. self.fields = {}
  173. if data is not None:
  174. self.fromString(data)
  175. def __setitem__(self,key,value):
  176. self.fields[key] = (len(value),value)
  177. def __getitem__(self, key):
  178. if key in self.fields:
  179. return self.fields[key]
  180. return None
  181. def __delitem__(self, key):
  182. del self.fields[key]
  183. def __len__(self):
  184. return len(self.getData())
  185. def __str__(self):
  186. return len(self.getData())
  187. def fromString(self, data):
  188. tInfo = data
  189. fType = 0xff
  190. while fType is not NTLMSSP_AV_EOL:
  191. fType = struct.unpack('<H',tInfo[:struct.calcsize('<H')])[0]
  192. tInfo = tInfo[struct.calcsize('<H'):]
  193. length = struct.unpack('<H',tInfo[:struct.calcsize('<H')])[0]
  194. tInfo = tInfo[struct.calcsize('<H'):]
  195. content = tInfo[:length]
  196. self.fields[fType]=(length,content)
  197. tInfo = tInfo[length:]
  198. def dump(self):
  199. for i in self.fields.keys():
  200. print("%s: {%r}" % (i,self[i]))
  201. def getData(self):
  202. if NTLMSSP_AV_EOL in self.fields:
  203. del self.fields[NTLMSSP_AV_EOL]
  204. ans = ''
  205. for i in self.fields.keys():
  206. ans+= struct.pack('<HH', i, self[i][0])
  207. ans+= self[i][1]
  208. # end with a NTLMSSP_AV_EOL
  209. ans += struct.pack('<HH', NTLMSSP_AV_EOL, 0)
  210. return ans
  211. class NTLMAuthMixin:
  212. def get_os_version(self):
  213. if self['os_version'] == '':
  214. return None
  215. else:
  216. mayor_v = struct.unpack('B',self['os_version'][0])[0]
  217. minor_v = struct.unpack('B',self['os_version'][1])[0]
  218. build_v = struct.unpack('H',self['os_version'][2:4])
  219. return (mayor_v,minor_v,build_v)
  220. class NTLMAuthNegotiate(Structure, NTLMAuthMixin):
  221. structure = (
  222. ('','"NTLMSSP\x00'),
  223. ('message_type','<L=1'),
  224. ('flags','<L'),
  225. ('domain_len','<H-domain_name'),
  226. ('domain_max_len','<H-domain_name'),
  227. ('domain_offset','<L=0'),
  228. ('host_len','<H-host_name'),
  229. ('host_maxlen','<H-host_name'),
  230. ('host_offset','<L=0'),
  231. ('os_version',':'),
  232. ('host_name',':'),
  233. ('domain_name',':'))
  234. def __init__(self):
  235. Structure.__init__(self)
  236. self['flags']= (
  237. NTLMSSP_NEGOTIATE_128 |
  238. NTLMSSP_NEGOTIATE_KEY_EXCH|
  239. # NTLMSSP_LM_KEY |
  240. NTLMSSP_NEGOTIATE_NTLM |
  241. NTLMSSP_NEGOTIATE_UNICODE |
  242. # NTLMSSP_ALWAYS_SIGN |
  243. NTLMSSP_NEGOTIATE_SIGN |
  244. NTLMSSP_NEGOTIATE_SEAL |
  245. # NTLMSSP_TARGET |
  246. 0)
  247. self['host_name']=''
  248. self['domain_name']=''
  249. self['os_version']=''
  250. def getData(self):
  251. if len(self.fields['host_name']) > 0:
  252. self['flags'] |= NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED
  253. if len(self.fields['domain_name']) > 0:
  254. self['flags'] |= NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED
  255. if len(self.fields['os_version']) > 0:
  256. self['flags'] |= NTLMSSP_NEGOTIATE_VERSION
  257. if (self['flags'] & NTLMSSP_NEGOTIATE_VERSION) == NTLMSSP_NEGOTIATE_VERSION:
  258. version_len = 8
  259. else:
  260. version_len = 0
  261. if (self['flags'] & NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED) == NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED:
  262. self['host_offset']=32 + version_len
  263. if (self['flags'] & NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED) == NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED:
  264. self['domain_offset']=32+len(self['host_name']) + version_len
  265. return Structure.getData(self)
  266. def fromString(self,data):
  267. Structure.fromString(self,data)
  268. domain_offset = self['domain_offset']
  269. domain_end = self['domain_len'] + domain_offset
  270. self['domain_name'] = data[ domain_offset : domain_end ]
  271. host_offset = self['host_offset']
  272. host_end = self['host_len'] + host_offset
  273. self['host_name'] = data[ host_offset : host_end ]
  274. hasOsInfo = self['flags'] & NTLMSSP_NEGOTIATE_VERSION
  275. if len(data) >= 36 and hasOsInfo:
  276. self['os_version'] = data[32:40]
  277. else:
  278. self['os_version'] = ''
  279. class NTLMAuthChallenge(Structure):
  280. structure = (
  281. ('','"NTLMSSP\x00'),
  282. ('message_type','<L=2'),
  283. ('domain_len','<H-domain_name'),
  284. ('domain_max_len','<H-domain_name'),
  285. ('domain_offset','<L=40'),
  286. ('flags','<L=0'),
  287. ('challenge','8s'),
  288. ('reserved','8s=""'),
  289. ('TargetInfoFields_len','<H-TargetInfoFields'),
  290. ('TargetInfoFields_max_len','<H-TargetInfoFields'),
  291. ('TargetInfoFields_offset','<L'),
  292. ('VersionLen','_-Version','self.checkVersion(self["flags"])'),
  293. ('Version',':'),
  294. ('domain_name',':'),
  295. ('TargetInfoFields',':'))
  296. def checkVersion(self, flags):
  297. if flags is not None:
  298. if flags & NTLMSSP_NEGOTIATE_VERSION == 0:
  299. return 0
  300. return 8
  301. def getData(self):
  302. if self['TargetInfoFields'] is not None and type(self['TargetInfoFields']) is not str:
  303. raw_av_fields = self['TargetInfoFields'].getData()
  304. self['TargetInfoFields'] = raw_av_fields
  305. return Structure.getData(self)
  306. def fromString(self,data):
  307. Structure.fromString(self,data)
  308. # Just in case there's more data after the TargetInfoFields
  309. self['TargetInfoFields'] = self['TargetInfoFields'][:self['TargetInfoFields_len']]
  310. # We gotta process the TargetInfoFields
  311. #if self['TargetInfoFields_len'] > 0:
  312. # av_pairs = AV_PAIRS(self['TargetInfoFields'][:self['TargetInfoFields_len']])
  313. # self['TargetInfoFields'] = av_pairs
  314. return self
  315. class NTLMAuthChallengeResponse(Structure, NTLMAuthMixin):
  316. structure = (
  317. ('','"NTLMSSP\x00'),
  318. ('message_type','<L=3'),
  319. ('lanman_len','<H-lanman'),
  320. ('lanman_max_len','<H-lanman'),
  321. ('lanman_offset','<L'),
  322. ('ntlm_len','<H-ntlm'),
  323. ('ntlm_max_len','<H-ntlm'),
  324. ('ntlm_offset','<L'),
  325. ('domain_len','<H-domain_name'),
  326. ('domain_max_len','<H-domain_name'),
  327. ('domain_offset','<L'),
  328. ('user_len','<H-user_name'),
  329. ('user_max_len','<H-user_name'),
  330. ('user_offset','<L'),
  331. ('host_len','<H-host_name'),
  332. ('host_max_len','<H-host_name'),
  333. ('host_offset','<L'),
  334. ('session_key_len','<H-session_key'),
  335. ('session_key_max_len','<H-session_key'),
  336. ('session_key_offset','<L'),
  337. ('flags','<L'),
  338. ('VersionLen','_-Version','self.checkVersion(self["flags"])'),
  339. ('Version',':=""'),
  340. ('MICLen','_-MIC','self.checkMIC(self["flags"])'),
  341. ('MIC',':=""'),
  342. ('domain_name',':'),
  343. ('user_name',':'),
  344. ('host_name',':'),
  345. ('lanman',':'),
  346. ('ntlm',':'),
  347. ('session_key',':'))
  348. def __init__(self, username = '', password = '', challenge = '', lmhash = '', nthash = '', flags = 0):
  349. Structure.__init__(self)
  350. self['session_key']=''
  351. self['user_name']=username.encode('utf-16le')
  352. self['domain_name']='' #"CLON".encode('utf-16le')
  353. self['host_name']='' #"BETS".encode('utf-16le')
  354. self['flags'] = ( #authResp['flags']
  355. # we think (beto & gera) that his flags force a memory conten leakage when a windows 2000 answers using uninitializaed verifiers
  356. NTLMSSP_NEGOTIATE_128 |
  357. NTLMSSP_NEGOTIATE_KEY_EXCH|
  358. # NTLMSSP_LM_KEY |
  359. NTLMSSP_NEGOTIATE_NTLM |
  360. NTLMSSP_NEGOTIATE_UNICODE |
  361. # NTLMSSP_ALWAYS_SIGN |
  362. NTLMSSP_NEGOTIATE_SIGN |
  363. NTLMSSP_NEGOTIATE_SEAL |
  364. # NTLMSSP_TARGET |
  365. 0)
  366. # Here we do the stuff
  367. if username and ( lmhash != '' or nthash != ''):
  368. self['lanman'] = get_ntlmv1_response(lmhash, challenge)
  369. self['ntlm'] = get_ntlmv1_response(nthash, challenge)
  370. elif (username and password):
  371. lmhash = compute_lmhash(password)
  372. nthash = compute_nthash(password)
  373. self['lanman']=get_ntlmv1_response(lmhash, challenge)
  374. self['ntlm']=get_ntlmv1_response(nthash, challenge) # This is not used for LM_KEY nor NTLM_KEY
  375. else:
  376. self['lanman'] = ''
  377. self['ntlm'] = ''
  378. if not self['host_name']:
  379. self['host_name'] = 'NULL'.encode('utf-16le') # for NULL session there must be a hostname
  380. def checkVersion(self, flags):
  381. if flags is not None:
  382. if flags & NTLMSSP_NEGOTIATE_VERSION == 0:
  383. return 0
  384. return 8
  385. def checkMIC(self, flags):
  386. # TODO: Find a proper way to check the MIC is in there
  387. if flags is not None:
  388. if flags & NTLMSSP_NEGOTIATE_VERSION == 0:
  389. return 0
  390. return 16
  391. def getData(self):
  392. self['domain_offset']=64+self.checkMIC(self["flags"])+self.checkVersion(self["flags"])
  393. self['user_offset']=64+self.checkMIC(self["flags"])+self.checkVersion(self["flags"])+len(self['domain_name'])
  394. self['host_offset']=self['user_offset']+len(self['user_name'])
  395. self['lanman_offset']=self['host_offset']+len(self['host_name'])
  396. self['ntlm_offset']=self['lanman_offset']+len(self['lanman'])
  397. self['session_key_offset']=self['ntlm_offset']+len(self['ntlm'])
  398. return Structure.getData(self)
  399. def fromString(self,data):
  400. Structure.fromString(self,data)
  401. # [MS-NLMP] page 27
  402. # Payload data can be present in any order within the Payload field,
  403. # with variable-length padding before or after the data
  404. domain_offset = self['domain_offset']
  405. domain_end = self['domain_len'] + domain_offset
  406. self['domain_name'] = data[ domain_offset : domain_end ]
  407. host_offset = self['host_offset']
  408. host_end = self['host_len'] + host_offset
  409. self['host_name'] = data[ host_offset: host_end ]
  410. user_offset = self['user_offset']
  411. user_end = self['user_len'] + user_offset
  412. self['user_name'] = data[ user_offset: user_end ]
  413. ntlm_offset = self['ntlm_offset']
  414. ntlm_end = self['ntlm_len'] + ntlm_offset
  415. self['ntlm'] = data[ ntlm_offset : ntlm_end ]
  416. lanman_offset = self['lanman_offset']
  417. lanman_end = self['lanman_len'] + lanman_offset
  418. self['lanman'] = data[ lanman_offset : lanman_end]
  419. #if len(data) >= 36:
  420. # self['os_version'] = data[32:36]
  421. #else:
  422. # self['os_version'] = ''
  423. class ImpacketStructure(Structure):
  424. def set_parent(self, other):
  425. self.parent = other
  426. def get_packet(self):
  427. return str(self)
  428. def get_size(self):
  429. return len(self)
  430. class ExtendedOrNotMessageSignature(Structure):
  431. def __init__(self, flags = 0, **kargs):
  432. if flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY:
  433. self.structure = self.extendedMessageSignature
  434. else:
  435. self.structure = self.MessageSignature
  436. return Structure.__init__(self, **kargs)
  437. class NTLMMessageSignature(ExtendedOrNotMessageSignature):
  438. extendedMessageSignature = (
  439. ('Version','<L=1'),
  440. ('Checksum','<q'),
  441. ('SeqNum','<i'),
  442. )
  443. MessageSignature = (
  444. ('Version','<L=1'),
  445. ('RandomPad','<i=0'),
  446. ('Checksum','<i'),
  447. ('SeqNum','<i'),
  448. )
  449. KNOWN_DES_INPUT = "KGS!@#$%"
  450. def __expand_DES_key( key):
  451. # Expand the key from a 7-byte password key into a 8-byte DES key
  452. key = key[:7]
  453. key += '\x00'*(7-len(key))
  454. s = chr(((ord(key[0]) >> 1) & 0x7f) << 1)
  455. s = s + chr(((ord(key[0]) & 0x01) << 6 | ((ord(key[1]) >> 2) & 0x3f)) << 1)
  456. s = s + chr(((ord(key[1]) & 0x03) << 5 | ((ord(key[2]) >> 3) & 0x1f)) << 1)
  457. s = s + chr(((ord(key[2]) & 0x07) << 4 | ((ord(key[3]) >> 4) & 0x0f)) << 1)
  458. s = s + chr(((ord(key[3]) & 0x0f) << 3 | ((ord(key[4]) >> 5) & 0x07)) << 1)
  459. s = s + chr(((ord(key[4]) & 0x1f) << 2 | ((ord(key[5]) >> 6) & 0x03)) << 1)
  460. s = s + chr(((ord(key[5]) & 0x3f) << 1 | ((ord(key[6]) >> 7) & 0x01)) << 1)
  461. s = s + chr((ord(key[6]) & 0x7f) << 1)
  462. return s
  463. def __DES_block(key, msg):
  464. if POW:
  465. cipher = POW.Symmetric(POW.DES_ECB)
  466. cipher.encryptInit(__expand_DES_key(key))
  467. return cipher.update(msg)
  468. else:
  469. cipher = DES.new(__expand_DES_key(key),DES.MODE_ECB)
  470. return cipher.encrypt(msg)
  471. def ntlmssp_DES_encrypt(key, challenge):
  472. answer = __DES_block(key[:7], challenge)
  473. answer += __DES_block(key[7:14], challenge)
  474. answer += __DES_block(key[14:], challenge)
  475. return answer
  476. # High level functions to use NTLMSSP
  477. def getNTLMSSPType1(workstation='', domain='', signingRequired = False, use_ntlmv2 = USE_NTLMv2):
  478. # Let's do some encoding checks before moving on. Kind of dirty, but found effective when dealing with
  479. # international characters.
  480. import sys
  481. encoding = sys.getfilesystemencoding()
  482. if encoding is not None:
  483. try:
  484. workstation.encode('utf-16le')
  485. except:
  486. workstation = workstation.decode(encoding)
  487. try:
  488. domain.encode('utf-16le')
  489. except:
  490. domain = domain.decode(encoding)
  491. # Let's prepare a Type 1 NTLMSSP Message
  492. auth = NTLMAuthNegotiate()
  493. auth['flags']=0
  494. if signingRequired:
  495. auth['flags'] = NTLMSSP_NEGOTIATE_KEY_EXCH | NTLMSSP_NEGOTIATE_SIGN | NTLMSSP_NEGOTIATE_ALWAYS_SIGN | NTLMSSP_NEGOTIATE_SEAL
  496. if use_ntlmv2:
  497. auth['flags'] |= NTLMSSP_NEGOTIATE_TARGET_INFO
  498. auth['flags'] |= NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY | NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_56
  499. auth['domain_name'] = domain.encode('utf-16le')
  500. return auth
  501. def getNTLMSSPType3(type1, type2, user, password, domain, lmhash = '', nthash = '', use_ntlmv2 = USE_NTLMv2):
  502. # Let's do some encoding checks before moving on. Kind of dirty, but found effective when dealing with
  503. # international characters.
  504. import sys
  505. encoding = sys.getfilesystemencoding()
  506. if encoding is not None:
  507. try:
  508. user.encode('utf-16le')
  509. except:
  510. user = user.decode(encoding)
  511. try:
  512. password.encode('utf-16le')
  513. except:
  514. password = password.decode(encoding)
  515. try:
  516. domain.encode('utf-16le')
  517. except:
  518. domain = user.decode(encoding)
  519. ntlmChallenge = NTLMAuthChallenge(type2)
  520. # Let's start with the original flags sent in the type1 message
  521. responseFlags = type1['flags']
  522. # Token received and parsed. Depending on the authentication
  523. # method we will create a valid ChallengeResponse
  524. ntlmChallengeResponse = NTLMAuthChallengeResponse(user, password, ntlmChallenge['challenge'])
  525. clientChallenge = "".join([random.choice(string.digits+string.letters) for i in range(8)])
  526. serverName = ntlmChallenge['TargetInfoFields']
  527. ntResponse, lmResponse, sessionBaseKey = computeResponse(ntlmChallenge['flags'], ntlmChallenge['challenge'], clientChallenge, serverName, domain, user, password, lmhash, nthash, use_ntlmv2 )
  528. # Let's check the return flags
  529. if (ntlmChallenge['flags'] & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY) == 0:
  530. # No extended session security, taking it out
  531. responseFlags &= 0xffffffff ^ NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY
  532. if (ntlmChallenge['flags'] & NTLMSSP_NEGOTIATE_128 ) == 0:
  533. # No support for 128 key len, taking it out
  534. responseFlags &= 0xffffffff ^ NTLMSSP_NEGOTIATE_128
  535. if (ntlmChallenge['flags'] & NTLMSSP_NEGOTIATE_KEY_EXCH) == 0:
  536. # No key exchange supported, taking it out
  537. responseFlags &= 0xffffffff ^ NTLMSSP_NEGOTIATE_KEY_EXCH
  538. if (ntlmChallenge['flags'] & NTLMSSP_NEGOTIATE_SEAL) == 0:
  539. # No sign available, taking it out
  540. responseFlags &= 0xffffffff ^ NTLMSSP_NEGOTIATE_SEAL
  541. if (ntlmChallenge['flags'] & NTLMSSP_NEGOTIATE_SIGN) == 0:
  542. # No sign available, taking it out
  543. responseFlags &= 0xffffffff ^ NTLMSSP_NEGOTIATE_SIGN
  544. if (ntlmChallenge['flags'] & NTLMSSP_NEGOTIATE_ALWAYS_SIGN) == 0:
  545. # No sign available, taking it out
  546. responseFlags &= 0xffffffff ^ NTLMSSP_NEGOTIATE_ALWAYS_SIGN
  547. keyExchangeKey = KXKEY(ntlmChallenge['flags'],sessionBaseKey, lmResponse, ntlmChallenge['challenge'], password, lmhash, nthash,use_ntlmv2)
  548. # Special case for anonymous login
  549. if user == '' and password == '' and lmhash == '' and nthash == '':
  550. keyExchangeKey = '\x00'*16
  551. # If we set up key exchange, let's fill the right variables
  552. if ntlmChallenge['flags'] & NTLMSSP_NEGOTIATE_KEY_EXCH:
  553. # not exactly what I call random tho :\
  554. # exportedSessionKey = this is the key we should use to sign
  555. exportedSessionKey = "".join([random.choice(string.digits+string.letters) for i in range(16)])
  556. #exportedSessionKey = "A"*16
  557. #print "keyExchangeKey %r" % keyExchangeKey
  558. # Let's generate the right session key based on the challenge flags
  559. #if responseFlags & NTLMSSP_NTLM2_KEY:
  560. # Extended session security enabled
  561. # if responseFlags & NTLMSSP_KEY_128:
  562. # Full key
  563. # exportedSessionKey = exportedSessionKey
  564. # elif responseFlags & NTLMSSP_KEY_56:
  565. # Only 56-bit key
  566. # exportedSessionKey = exportedSessionKey[:7]
  567. # else:
  568. # exportedSessionKey = exportedSessionKey[:5]
  569. #elif responseFlags & NTLMSSP_KEY_56:
  570. # No extended session security, just 56 bits key
  571. # exportedSessionKey = exportedSessionKey[:7] + '\xa0'
  572. #else:
  573. # exportedSessionKey = exportedSessionKey[:5] + '\xe5\x38\xb0'
  574. encryptedRandomSessionKey = generateEncryptedSessionKey(keyExchangeKey, exportedSessionKey)
  575. else:
  576. encryptedRandomSessionKey = None
  577. # [MS-NLMP] page 46
  578. exportedSessionKey = keyExchangeKey
  579. ntlmChallengeResponse['flags'] = responseFlags
  580. ntlmChallengeResponse['domain_name'] = domain.encode('utf-16le')
  581. ntlmChallengeResponse['lanman'] = lmResponse
  582. ntlmChallengeResponse['ntlm'] = ntResponse
  583. if encryptedRandomSessionKey is not None:
  584. ntlmChallengeResponse['session_key'] = encryptedRandomSessionKey
  585. return ntlmChallengeResponse, exportedSessionKey
  586. # NTLMv1 Algorithm
  587. def generateSessionKeyV1(password, lmhash, nthash):
  588. if POW:
  589. hash = POW.Digest(POW.MD4_DIGEST)
  590. else:
  591. hash = MD4.new()
  592. hash.update(NTOWFv1(password, lmhash, nthash))
  593. return hash.digest()
  594. def computeResponseNTLMv1(flags, serverChallenge, clientChallenge, serverName, domain, user, password, lmhash='', nthash='', use_ntlmv2 = USE_NTLMv2):
  595. if (user == '' and password == ''):
  596. # Special case for anonymous authentication
  597. lmResponse = ''
  598. ntResponse = ''
  599. else:
  600. lmhash = LMOWFv1(password, lmhash, nthash)
  601. nthash = NTOWFv1(password, lmhash, nthash)
  602. if flags & NTLMSSP_NEGOTIATE_LM_KEY:
  603. ntResponse = ''
  604. lmResponse = get_ntlmv1_response(lmhash, serverChallenge)
  605. elif flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY:
  606. md5 = hashlib.new('md5')
  607. chall = (serverChallenge + clientChallenge)
  608. md5.update(chall)
  609. ntResponse = ntlmssp_DES_encrypt(nthash, md5.digest()[:8])
  610. lmResponse = clientChallenge + '\x00'*16
  611. else:
  612. ntResponse = get_ntlmv1_response(nthash,serverChallenge)
  613. lmResponse = get_ntlmv1_response(lmhash, serverChallenge)
  614. sessionBaseKey = generateSessionKeyV1(password, lmhash, nthash)
  615. return ntResponse, lmResponse, sessionBaseKey
  616. def compute_lmhash(password):
  617. # This is done according to Samba's encryption specification (docs/html/ENCRYPTION.html)
  618. password = password.upper()
  619. lmhash = __DES_block(password[:7], KNOWN_DES_INPUT)
  620. lmhash += __DES_block(password[7:14], KNOWN_DES_INPUT)
  621. return lmhash
  622. def NTOWFv1(password, lmhash = '', nthash=''):
  623. if nthash != '':
  624. return nthash
  625. return compute_nthash(password)
  626. def LMOWFv1(password, lmhash = '', nthash=''):
  627. if lmhash != '':
  628. return lmhash
  629. return compute_lmhash(password)
  630. def compute_nthash(password):
  631. # This is done according to Samba's encryption specification (docs/html/ENCRYPTION.html)
  632. try:
  633. password = unicode(password).encode('utf_16le')
  634. except NameError: # unicode() was removed in Python 3
  635. password = str(password).encode('utf_16le')
  636. except UnicodeDecodeError:
  637. import sys
  638. password = password.decode(sys.getfilesystemencoding()).encode('utf_16le')
  639. if POW:
  640. hash = POW.Digest(POW.MD4_DIGEST)
  641. else:
  642. hash = MD4.new()
  643. hash.update(password)
  644. return hash.digest()
  645. def get_ntlmv1_response(key, challenge):
  646. return ntlmssp_DES_encrypt(key, challenge)
  647. # NTLMv2 Algorithm - as described in MS-NLMP Section 3.3.2
  648. # Crypto Stuff
  649. def MAC(flags, handle, signingKey, seqNum, message):
  650. # [MS-NLMP] Section 3.4.4
  651. # Returns the right messageSignature depending on the flags
  652. messageSignature = NTLMMessageSignature(flags)
  653. if flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY:
  654. if flags & NTLMSSP_NEGOTIATE_KEY_EXCH:
  655. messageSignature['Version'] = 1
  656. messageSignature['Checksum'] = struct.unpack('<q',handle(hmac_md5(signingKey, struct.pack('<i',seqNum)+message)[:8]))[0]
  657. messageSignature['SeqNum'] = seqNum
  658. seqNum += 1
  659. else:
  660. messageSignature['Version'] = 1
  661. messageSignature['Checksum'] = struct.unpack('<q',hmac_md5(signingKey, struct.pack('<i',seqNum)+message)[:8])[0]
  662. messageSignature['SeqNum'] = seqNum
  663. seqNum += 1
  664. else:
  665. messageSignature['Version'] = 1
  666. messageSignature['Checksum'] = struct.pack('<i',binascii.crc32(message))
  667. messageSignature['RandomPad'] = 0
  668. messageSignature['RandomPad'] = handle(struct.pack('<i',messageSignature['RandomPad']))
  669. messageSignature['Checksum'] = struct.unpack('<i',handle(messageSignature['Checksum']))[0]
  670. messageSignature['SeqNum'] = handle('\x00\x00\x00\x00')
  671. messageSignature['SeqNum'] = struct.unpack('<i',messageSignature['SeqNum'])[0] ^ seqNum
  672. messageSignature['RandomPad'] = 0
  673. return messageSignature
  674. def SEAL(flags, signingKey, sealingKey, messageToSign, messageToEncrypt, seqNum, handle):
  675. sealedMessage = handle(messageToEncrypt)
  676. signature = MAC(flags, handle, signingKey, seqNum, messageToSign)
  677. return sealedMessage, signature
  678. def SIGN(flags, signingKey, message, seqNum, handle):
  679. return MAC(flags, handle, signingKey, seqNum, message)
  680. def SIGNKEY(flags, randomSessionKey, mode = 'Client'):
  681. if flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY:
  682. if mode == 'Client':
  683. md5 = hashlib.new('md5')
  684. md5.update(randomSessionKey + "session key to client-to-server signing key magic constant\x00")
  685. signKey = md5.digest()
  686. else:
  687. md5 = hashlib.new('md5')
  688. md5.update(randomSessionKey + "session key to server-to-client signing key magic constant\x00")
  689. signKey = md5.digest()
  690. else:
  691. signKey = None
  692. return signKey
  693. def SEALKEY(flags, randomSessionKey, mode = 'Client'):
  694. if flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY:
  695. if flags & NTLMSSP_NEGOTIATE_128:
  696. sealKey = randomSessionKey
  697. elif flags & NTLMSSP_NEGOTIATE_56:
  698. sealKey = randomSessionKey[:7]
  699. else:
  700. sealKey = randomSessionKey[:5]
  701. if mode == 'Client':
  702. md5 = hashlib.new('md5')
  703. md5.update(sealKey + 'session key to client-to-server sealing key magic constant\x00')
  704. sealKey = md5.digest()
  705. else:
  706. md5 = hashlib.new('md5')
  707. md5.update(sealKey + 'session key to server-to-client sealing key magic constant\x00')
  708. sealKey = md5.digest()
  709. elif flags & NTLMSSP_NEGOTIATE_56:
  710. sealKey = randomSessionKey[:7] + '\xa0'
  711. else:
  712. sealKey = randomSessionKey[:5] + '\xe5\x38\xb0'
  713. return sealKey
  714. def generateEncryptedSessionKey(keyExchangeKey, exportedSessionKey):
  715. if POW:
  716. cipher = POW.Symmetric(POW.RC4)
  717. cipher.encryptInit(keyExchangeKey)
  718. cipher_encrypt = cipher.update
  719. else:
  720. cipher = ARC4.new(keyExchangeKey)
  721. cipher_encrypt = cipher.encrypt
  722. sessionKey = cipher_encrypt(exportedSessionKey)
  723. return sessionKey
  724. def KXKEY(flags, sessionBaseKey, lmChallengeResponse, serverChallenge, password, lmhash, nthash, use_ntlmv2 = USE_NTLMv2):
  725. if use_ntlmv2:
  726. return sessionBaseKey
  727. if flags & NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY:
  728. if flags & NTLMSSP_NEGOTIATE_NTLM:
  729. keyExchangeKey = hmac_md5(sessionBaseKey, serverChallenge + lmChallengeResponse[:8])
  730. else:
  731. keyExchangeKey = sessionBaseKey
  732. elif flags & NTLMSSP_NEGOTIATE_NTLM:
  733. if flags & NTLMSSP_NEGOTIATE_LM_KEY:
  734. keyExchangeKey = __DES_block(LMOWFv1(password,lmhash)[:7], lmChallengeResponse[:8]) + __DES_block(LMOWFv1(password,lmhash)[7] + '\xBD\xBD\xBD\xBD\xBD\xBD', lmChallengeResponse[:8])
  735. elif flags & NTLMSSP_REQUEST_NON_NT_SESSION_KEY:
  736. keyExchangeKey = LMOWFv1(password,lmhash)[:8] + '\x00'*8
  737. else:
  738. keyExchangeKey = sessionBaseKey
  739. else:
  740. raise "Can't create a valid KXKEY!"
  741. return keyExchangeKey
  742. def hmac_md5(key, data):
  743. if POW:
  744. h = POW.Hmac(POW.MD5_DIGEST, key)
  745. h.update(data)
  746. result = h.mac()
  747. else:
  748. import hmac
  749. h = hmac.new(key)
  750. h.update(data)
  751. result = h.digest()
  752. return result
  753. def NTOWFv2( user, password, domain, hash = ''):
  754. if hash != '':
  755. theHash = hash
  756. else:
  757. theHash = compute_nthash(password)
  758. return hmac_md5(theHash, user.upper().encode('utf-16le') + domain.encode('utf-16le'))
  759. def LMOWFv2( user, password, domain, lmhash = ''):
  760. return NTOWFv2( user, password, domain, lmhash)
  761. def computeResponseNTLMv2(flags, serverChallenge, clientChallenge, serverName, domain, user, password, lmhash = '', nthash = '', use_ntlmv2 = USE_NTLMv2):
  762. responseServerVersion = '\x01'
  763. hiResponseServerVersion = '\x01'
  764. responseKeyNT = NTOWFv2(user, password, domain, nthash)
  765. responseKeyLM = LMOWFv2(user, password, domain, lmhash)
  766. # 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!
  767. ######################
  768. av_pairs = AV_PAIRS(serverName)
  769. # In order to support SPN target name validation, we have to add this to the serverName av_pairs. Otherwise we will get access denied
  770. # This is set at Local Security Policy -> Local Policies -> Security Options -> Server SPN target name validation level
  771. av_pairs[NTLMSSP_AV_TARGET_NAME] = 'cifs/'.encode('utf-16le') + av_pairs[NTLMSSP_AV_HOSTNAME][1]
  772. if av_pairs[NTLMSSP_AV_TIME] is not None:
  773. aTime = av_pairs[NTLMSSP_AV_TIME][1]
  774. else:
  775. aTime = struct.pack('<q', (116444736000000000 + calendar.timegm(time.gmtime()) * 10000000) )
  776. #aTime = '\x00'*8
  777. av_pairs[NTLMSSP_AV_TIME] = aTime
  778. serverName = av_pairs.getData()
  779. ######################
  780. #aTime = '\x00'*8
  781. ######################
  782. temp = responseServerVersion + hiResponseServerVersion + '\x00' * 6 + aTime + clientChallenge + '\x00' * 4 + serverName + '\x00' * 4
  783. ntProofStr = hmac_md5(responseKeyNT, serverChallenge + temp)
  784. ntChallengeResponse = ntProofStr + temp
  785. lmChallengeResponse = hmac_md5(responseKeyNT, serverChallenge + clientChallenge) + clientChallenge
  786. sessionBaseKey = hmac_md5(responseKeyNT, ntProofStr)
  787. if (user == '' and password == ''):
  788. # Special case for anonymous authentication
  789. ntChallengeResponse = ''
  790. lmChallengeResponse = ''
  791. return ntChallengeResponse, lmChallengeResponse, sessionBaseKey
  792. class NTLM_HTTP(object):
  793. '''Parent class for NTLM HTTP classes.'''
  794. MSG_TYPE = None
  795. @classmethod
  796. def get_instace(cls,msg_64):
  797. msg = None
  798. msg_type = 0
  799. if msg_64 != '':
  800. msg = base64.b64decode(msg_64[5:]) # Remove the 'NTLM '
  801. msg_type = ord(msg[8])
  802. for _cls in NTLM_HTTP.__subclasses__():
  803. if msg_type == _cls.MSG_TYPE:
  804. instance = _cls()
  805. instance.fromString(msg)
  806. return instance
  807. class NTLM_HTTP_AuthRequired(NTLM_HTTP):
  808. commonHdr = ()
  809. # Message 0 means the first HTTP request e.g. 'GET /bla.png'
  810. MSG_TYPE = 0
  811. def fromString(self,data):
  812. pass
  813. class NTLM_HTTP_AuthNegotiate(NTLM_HTTP, NTLMAuthNegotiate):
  814. commonHdr = ()
  815. MSG_TYPE = 1
  816. def __init__(self):
  817. NTLMAuthNegotiate.__init__(self)
  818. class NTLM_HTTP_AuthChallengeResponse(NTLM_HTTP, NTLMAuthChallengeResponse):
  819. commonHdr = ()
  820. MSG_TYPE = 3
  821. def __init__(self):
  822. NTLMAuthChallengeResponse.__init__(self)