home *** CD-ROM | disk | FTP | other *** search
/ Hackers Magazine 57 / CdHackersMagazineNr57.iso / Software / Networking / nmap-5.00-setup.exe / nselib / smbauth.lua < prev    next >
Text File  |  2009-07-06  |  29KB  |  684 lines

  1. ---This module takes care of the authentication used in SMB (LM, NTLM, LMv2, NTLMv2). 
  2. -- There is a lot to this functionality, so if you're interested in how it works, read
  3. -- on. 
  4. --
  5. -- In SMB authentication, there are two distinct concepts. Each will be dealt with
  6. -- separately. There are:
  7. -- * Stored hashes
  8. -- * Authentication
  9. --
  10. -- What's confusing is that the same names are used for each of those. 
  11. --
  12. -- Stored Hashes
  13. -- Windows stores two types of hashes: Lanman and NT Lanman (or NTLM). Vista and later
  14. -- store NTLM only. Lanman passwords are divided into two 7-character passwords and 
  15. -- used as a key in DES, while NTLM is converted to unicode and MD4ed. 
  16. --
  17. -- The stored hashes can be dumped in a variety of ways (pwdump6, fgdump, metasploit's
  18. -- priv module, smb-pwdump.nse, etc). Generally, two hashes are dumped together 
  19. -- (generally, Lanman:NTLM). Sometimes, Lanman is empty and only NTLM is given. Lanman
  20. -- is never required. 
  21. --
  22. -- The password hashes can be given instead of passwords when supplying credentials; 
  23. -- this is done by using the <code>smbhash</code> argument. Either a pair of hashes
  24. -- can be passed, in the form of Lanman:NTLM, or a single hash, which is assumed to
  25. -- be NTLM. 
  26. --
  27. -- Authentication
  28. -- There are four types of authentication. Confusingly, these have the same names as
  29. -- stored hashes, but only slight relationships. The four types are Lanmanv1, NTLMv1, 
  30. -- Lanmanv2, and NTLMv2. By default, Lanmanv1 and NTLMv1 are used together in most 
  31. -- applications. These Nmap scripts default to NTLMv1 alone, except in special cases, 
  32. -- but it can be overridden by the user. 
  33. --
  34. -- Lanmanv1 and NTLMv1 both use DES for their response. The DES mixes a server challenge
  35. -- with the hash (Lanman hash for Lanmanv1 response and NTLMv1 hash for NTLM response). 
  36. -- The way the challenge is DESed with the hashes is identical for Lanmanv1 and NTLMv1, 
  37. -- the only difference is the starting hash (Lanman vs NTLM). 
  38. --
  39. -- Lanmanv2 and NTLMv2 both use HMAC-MD5 for their response. The HMAC-MD5 mixes a 
  40. -- server challenge and a client challenge with the NTLM hash, in both cases. The 
  41. -- difference between Lanmanv2 and NTLMv2 is the length of the client challenge;
  42. -- Lanmanv2 has a maximum client challenge of 8 bytes, whereas NTLMv2 doesn't limit
  43. -- the length of the client challenge. 
  44. --
  45. -- The primary advantage to the 'v2' protocols is the client challenge -- by 
  46. -- incorporating a client challenge, a malicious server can't use a precomputation
  47. -- attack. 
  48. --
  49. -- In addition to hashing the passwords, messages are also signed, by default, if a 
  50. -- v1 protocol is being used (I (Ron Bowes) couldn't get signatures to work on v2 
  51. -- protocols; if anybody knows how I'd love to implement it).
  52. --
  53. --@args  smbusername The SMB username to log in with. The forms "DOMAIN\username" and "username@DOMAIN"
  54. --                   are not understood. To set a domain, use the <code>smbdomain</code> argument.
  55. --@args  smbdomain   The domain to log in with. If you aren't in a domained environment, then anything
  56. --                   will (should?) be accepted by the server.
  57. --@args  smbpassword The password to connect with. Be cautious with this, since some servers will lock
  58. --                   accounts if the incorrect password is given. Although it's rare that the
  59. --                   Administrator account can be locked out, in the off chance that it can, you could
  60. --                   get yourself in trouble. To use a blank password, leave this parameter off
  61. --                   altogether. 
  62. --@args  smbhash     A password hash to use when logging in. This is given as a single hex string (32
  63. --                   characters) or a pair of hex strings (both 32 characters, optionally separated by a
  64. --                   single character). These hashes are the LanMan or NTLM hash of the user's password,
  65. --                   and are stored on disk or in memory. They can be retrieved from memory
  66. --                   using the fgdump or pwdump tools.
  67. --@args  smbtype     The type of SMB authentication to use. These are the possible options:
  68. -- * <code>v1</code>:     Sends LMv1 and NTLMv1.
  69. -- * <code>LMv1</code>:   Sends LMv1 only.
  70. -- * <code>NTLMv1</code>: Sends NTLMv1 only (default).
  71. -- * <code>v2</code>:     Sends LMv2 and NTLMv2.
  72. -- * <code>LMv2</code>:   Sends LMv2 only.
  73. -- * <code>NTLMv2</code>: Doesn't exist; the protocol doesn't support NTLMv2 alone. 
  74. --                   The default, <code>NTLMv1</code>, is a pretty decent compromise between security and 
  75. --                   compatibility. If you are paranoid, you might want to use <code>v2</code> or 
  76. --                   <code>lmv2</code> for this. (Actually, if you're paranoid, you should be avoiding this 
  77. --                   protocol altogether!). If you're using an extremely old system, you might need to set 
  78. --                   this to <code>v1</code> or <code>lm</code>, which are less secure but more compatible.  
  79. --                   For information, see <code>smbauth.lua</code>. 
  80.  
  81. module(... or "smbauth", package.seeall)
  82.  
  83. require 'bit'
  84. require 'bin'
  85. require 'netbios'
  86. require 'stdnse'
  87.  
  88. have_ssl = (nmap.have_ssl() and pcall(require, "openssl"))
  89.  
  90. -- Constants
  91. local NTLMSSP_NEGOTIATE = 0x00000001
  92. local NTLMSSP_CHALLENGE = 0x00000002
  93. local NTLMSSP_AUTH      = 0x00000003
  94.  
  95. local function to_unicode(str)
  96.     local unicode = ""
  97.  
  98.     for i = 1, #str, 1 do
  99.         unicode = unicode .. bin.pack("<S", string.byte(str, i))
  100.     end
  101.  
  102.     return unicode
  103. end
  104.  
  105. ---Generate the Lanman v1 hash (LMv1). The generated hash is incredibly easy to reverse, because the input
  106. -- is padded or truncated to 14 characters, then split into two 7-character strings. Each of these strings
  107. -- are used as a key to encrypt the string, "KGS!@#$%" in DES. Because the keys are no longer than 
  108. -- 7-characters long, it's pretty trivial to bruteforce them. 
  109. --
  110. --@param password the password to hash
  111. --@return (status, hash) If status is true, the hash is returned; otherwise, an error message is returned.
  112. local function lm_create_hash(password)
  113.     if(have_ssl ~= true) then
  114.         return false, "SMB: OpenSSL not present"
  115.     end
  116.  
  117.     local str1, str2
  118.     local key1, key2
  119.     local result
  120.  
  121.     -- Convert the password to uppercase
  122.     password = string.upper(password)
  123.  
  124.     -- If password is under 14 characters, pad it to 14
  125.     if(#password < 14) then
  126.         password = password .. string.rep(string.char(0), 14 - #password)
  127.     end
  128.  
  129.     -- Take the first and second half of the password (note that if it's longer than 14 characters, it's truncated)
  130.     str1 = string.sub(password, 1, 7)
  131.     str2 = string.sub(password, 8, 14)
  132.  
  133.     -- Generate the keys
  134.     key1 = openssl.DES_string_to_key(str1)
  135.     key2 = openssl.DES_string_to_key(str2)
  136.  
  137.     -- Encrypt the string "KGS!@#$%" with each half, and concatenate it
  138.     result = openssl.encrypt("DES", key1, nil, "KGS!@#$%") .. openssl.encrypt("DES", key2, nil, "KGS!@#$%")
  139.  
  140.     return true, result
  141. end
  142.  
  143. ---Generate the NTLMv1 hash. This hash is quite a bit better than LMv1, and is far easier to generate. Basically,
  144. -- it's the MD4 of the Unicode password. 
  145. --
  146. --@param password the password to hash
  147. --@return (status, hash) If status is true, the hash is returned; otherwise, an error message is returned.
  148. function ntlm_create_hash(password)
  149.     if(have_ssl ~= true) then
  150.         return false, "SMB: OpenSSL not present"
  151.     end
  152.  
  153.     return true, openssl.md4(to_unicode(password))
  154. end
  155.  
  156. ---Create the Lanman response to send back to the server. To do this, the Lanman password is padded to 21 
  157. -- characters and split into three 7-character strings. Each of those strings is used as a key to encrypt
  158. -- the server challenge. The three encrypted strings are concatenated and returned. 
  159. --
  160. --@param lanman    The LMv1 hash
  161. --@param challenge The server's challenge. 
  162. --@return (status, response) If status is true, the response is returned; otherwise, an error message is returned.
  163. function lm_create_response(lanman, challenge)
  164.     if(have_ssl ~= true) then
  165.         return false, "SMB: OpenSSL not present"
  166.     end
  167.  
  168.     local str1, str2, str3
  169.     local key1, key2, key3
  170.     local result
  171.  
  172.     -- Pad the hash to 21 characters
  173.     lanman = lanman .. string.rep(string.char(0), 21 - #lanman)
  174.  
  175.     -- Take the first and second half of the password (note that if it's longer than 14 characters, it's truncated)
  176.     str1 = string.sub(lanman, 1,  7)
  177.     str2 = string.sub(lanman, 8,  14)
  178.     str3 = string.sub(lanman, 15, 21)
  179.  
  180.     -- Generate the keys
  181.     key1 = openssl.DES_string_to_key(str1)
  182.     key2 = openssl.DES_string_to_key(str2)
  183.     key3 = openssl.DES_string_to_key(str3)
  184.  
  185.     -- Print a warning message if a blank challenge is received, and create a phony challenge. A blank challenge is
  186.     -- invalid in the protocol, and causes some versions of OpenSSL to abort with no possible error handling. 
  187.     if(challenge == "") then
  188.         stdnse.print_debug(1, "SMB: ERROR: Server returned invalid (blank) challenge value (should be 8 bytes); failing login to avoid OpenSSL crash.")
  189.         challenge = "AAAAAAAA"
  190.     end
  191.  
  192.     -- Encrypt the challenge with each key
  193.     result = openssl.encrypt("DES", key1, nil, challenge) .. openssl.encrypt("DES", key2, nil, challenge) .. openssl.encrypt("DES", key3, nil, challenge)
  194.  
  195.     return true, result
  196. end
  197.  
  198. ---Create the NTLM response to send back to the server. This is actually done the exact same way as the Lanman hash,
  199. -- so I call the <code>Lanman</code> function. 
  200. --
  201. --@param ntlm      The NTLMv1 hash
  202. --@param challenge The server's challenge. 
  203. --@return (status, response) If status is true, the response is returned; otherwise, an error message is returned.
  204. function ntlm_create_response(ntlm, challenge)
  205.     if(have_ssl ~= true) then
  206.         return false, "SMB: OpenSSL not present"
  207.     end
  208.  
  209.     return lm_create_response(ntlm, challenge)
  210. end
  211.  
  212. ---Create the NTLM mac key, which is used for message signing. For basic authentication, this is the md4 of the 
  213. -- NTLM hash, concatenated with the response hash; for extended authentication, this is just the md4 of the NTLM
  214. -- hash. 
  215. --@param ntlm_hash The NTLM hash. 
  216. --@param ntlm_response The NTLM response. 
  217. --@param is_extended Should be set if extended security negotiations are being used. 
  218. function ntlm_create_mac_key(ntlm_hash, ntlm_response, is_extended)
  219.     if(have_ssl ~= true) then
  220.         return false, "SMB: OpenSSL not present"
  221.     end
  222.     if(is_extended) then
  223.         return openssl.md4(ntlm_hash)
  224.     else
  225.         return openssl.md4(ntlm_hash) .. ntlm_response
  226.     end
  227. end
  228.  
  229. ---Create the LM mac key, which is used for message signing. For basic authentication, it's the first 8 bytes 
  230. -- of the lanman hash, followed by 8 null bytes, followed by the lanman response; for extended authentication, 
  231. -- this is just the first 8 bytes of the lanman hash followed by 8 null bytes. 
  232. --@param ntlm_hash The NTLM hash. 
  233. --@param ntlm_response The NTLM response. 
  234. --@param is_extended Should be set if extended security negotiations are being used. 
  235. function lm_create_mac_key(lm_hash, lm_response, is_extended)
  236.     if(have_ssl ~= true) then
  237.         return false, "SMB: OpenSSL not present"
  238.     end
  239.  
  240.     if(is_extended) then
  241.         return string.sub(lm_hash, 1, 8) .. string.rep(string.char(0), 8)
  242.     else
  243.         return string.sub(lm_hash, 1, 8) .. string.rep(string.char(0), 8) .. lm_response
  244.     end
  245. end
  246.  
  247. ---Create the NTLMv2 hash, which is based on the NTLMv1 hash (for easy upgrading), the username, and the domain. 
  248. -- Essentially, the NTLM hash is used as a HMAC-MD5 key, which is used to hash the unicode domain concatenated 
  249. -- with the unicode username. 
  250. --
  251. --@param ntlm     The NTLMv1 hash. 
  252. --@param username The username we're using. 
  253. --@param domain   The domain. 
  254. --@return (status, response) If status is true, the response is returned; otherwise, an error message is returned.
  255. function ntlmv2_create_hash(ntlm, username, domain)
  256.     if(have_ssl ~= true) then
  257.         return false, "SMB: OpenSSL not present"
  258.     end
  259.  
  260.     local unicode = ""
  261.  
  262.     username = to_unicode(string.upper(username))
  263.     domain   = to_unicode(string.upper(domain))
  264.  
  265.     return true, openssl.hmac("MD5", ntlm, username .. domain)
  266. end
  267.  
  268. ---Create the LMv2 response, which can be sent back to the server. This is identical to the <code>NTLMv2</code> function, 
  269. -- except that it uses an 8-byte client challenge. 
  270. --
  271. -- The reason for LMv2 is a long and twisted story. Well, not really. The reason is basically that the v1 hashes
  272. -- are always 24-bytes, and some servers expect 24 bytes, but the NTLMv2 hash is more than 24 bytes. So, the only
  273. -- way to keep pass-through compatibility was to have a v2-hash that was guaranteed to be 24 bytes. So LMv1 was
  274. -- born -- it has a 16-byte hash followed by the 8-byte client challenge, for a total of 24 bytes. And now you've
  275. -- learned something
  276. --
  277. --@param ntlm      The NVLMv1 hash.
  278. --@param username  The username we're using. 
  279. --@param domain    The domain. 
  280. --@param challenge The server challenge. 
  281. --@return (status, response) If status is true, the response is returned; otherwise, an error message is returned.
  282. function lmv2_create_response(ntlm, username, domain, challenge)
  283.     if(have_ssl ~= true) then
  284.         return false, "SMB: OpenSSL not present"
  285.     end
  286.  
  287.     return ntlmv2_create_response(ntlm, username, domain, challenge, 8)
  288. end
  289.  
  290. ---Create the NTLMv2 response, which can be sent back to the server. This is done by using the HMAC-MD5 algorithm
  291. -- with the NTLMv2 hash as a key, and the server challenge concatenated with the client challenge for the data. 
  292. -- The resulting hash is concatenated with the client challenge and returned.
  293. --
  294. -- The "proper" implementation for this uses a certain structure for the client challenge, involving the time
  295. -- and computer name and stuff (if you don't do this, Wireshark tells you it's a malformed packet). In my tests, 
  296. -- however, I couldn't get Vista to recognize a client challenge longer than 24 bytes, and this structure was
  297. -- guaranteed to be much longer than 24 bytes. So, I just use a random string generated by OpenSSL. I've tested
  298. -- it on every Windows system from Windows 2000 to Windows Vista, and it has always worked. 
  299. function ntlmv2_create_response(ntlm, username, domain, challenge, client_challenge_length)
  300.     if(have_ssl ~= true) then
  301.         return false, "SMB: OpenSSL not present"
  302.     end
  303.  
  304.     local client_challenge = openssl.rand_bytes(client_challenge_length)
  305.     local ntlmv2_hash
  306.  
  307.     status, ntlmv2_hash = ntlmv2_create_hash(ntlm, username, domain)
  308.  
  309.     return true, openssl.hmac("MD5", ntlmv2_hash, challenge .. client_challenge) .. client_challenge
  310. end
  311.  
  312. ---Determines which hash type is going to be used, based on the function parameters and 
  313. -- the nmap arguments (in that order).
  314. --
  315. --@param hash_type [optional] The function parameter version, which will override all others if set. 
  316. --@return The highest priority hash type that's set.
  317. local function get_hash_type(hash_type)
  318.     
  319.     if(hash_type ~= nil) then
  320.         stdnse.print_debug(2, "SMB: Using logon type passed as a parameter: %s", hash_type)
  321.     else
  322.         if(nmap.registry.args.smbtype ~= nil) then
  323.             hash_type = nmap.registry.args.smbtype
  324.             stdnse.print_debug(2, "SMB: Using logon type passed as an nmap parameter: %s", hash_type)
  325.         else
  326.             hash_type = "ntlm"
  327.             stdnse.print_debug(2, "SMB: Using default logon type: %s", hash_type)
  328.         end
  329.     end
  330.  
  331.     return string.lower(hash_type)
  332. end
  333.  
  334.  
  335. ---Determines which username is going to be used, based on the function parameters, the nmap arguments, 
  336. -- and the registry (in that order).
  337. --
  338. --@param ip       The ip address, used when reading from the registry
  339. --@param username [optional] The function parameter version, which will override all others if set. 
  340. --@return The highest priority username that's set.
  341. local function get_username(ip, username)
  342.  
  343.     if(username ~= nil) then
  344.         stdnse.print_debug(2, "SMB: Using username passed as a parameter: %s", username)
  345.     else
  346.         if(nmap.registry.args.smbusername ~= nil) then
  347.             username = nmap.registry.args.smbusername
  348.             stdnse.print_debug(2, "SMB: Using username passed as an nmap parameter (smbusername): %s", username)
  349.         elseif(nmap.registry.args.smbuser ~= nil) then
  350.             username = nmap.registry.args.smbuser
  351.             stdnse.print_debug(2, "SMB: Using username passed as an nmap parameter (smbuser): %s", username)
  352.         elseif(nmap.registry[ip] ~= nil and nmap.registry[ip]['smbaccount'] ~= nil and nmap.registry[ip]['smbaccount']['username'] ~= nil) then
  353.             username = nmap.registry[ip]['smbaccount']['username']
  354.             stdnse.print_debug(2, "SMB: Using username found in the registry: %s", username)
  355.         else
  356.             username = nil
  357.             stdnse.print_debug(2, "SMB: Couldn't find a username to use, not logging in")
  358.         end
  359.     end
  360.  
  361.     return username
  362. end
  363.  
  364. ---Determines which domain is going to be used, based on the function parameters and 
  365. -- the nmap arguments (in that order).
  366. --
  367. -- [TODO] registry
  368. --
  369. --@param domain [optional] The function parameter version, which will override all others if set. 
  370. --@return The highest priority domain that's set.
  371. local function get_domain(ip, domain)
  372.  
  373.     if(domain ~= nil) then
  374.         stdnse.print_debug(2, "SMB: Using domain passed as a parameter: %s", domain)
  375.     else
  376.         if(nmap.registry.args.smbdomain ~= nil) then
  377.             domain = nmap.registry.args.smbdomain
  378.             stdnse.print_debug(2, "SMB: Using domain passed as an nmap parameter: %s", domain)
  379.         else
  380.             domain = ""
  381.             stdnse.print_debug(2, "SMB: Couldn't find domain to use, using blank")
  382.         end
  383.     end
  384.  
  385.     return domain
  386. end
  387.  
  388. ---Generate the Lanman and NTLM password hashes. The password itself is taken from the function parameters,
  389. -- the nmap arguments, and the registry (in that order). If no password is set, then the password hash
  390. -- is used (which is read from all the usual places). If neither is set, then a blank password is used. 
  391. --
  392. -- The output passwords are hashed based on the hash type. 
  393. --
  394. --@param ip       The ip address of the host, used for registry lookups. 
  395. --@param username The username, which is used for v2 passwords. 
  396. --@param domain The username, which is used for v2 passwords. 
  397. --@param password [optional] The overriding password. 
  398. --@param password_hash [optional] The overriding password hash. Shouldn't be set if password is set. 
  399. --@param challenge The server challenge.
  400. --@param hash_type The way in which to hash the password. 
  401. --@param is_extended Set to 'true' if extended security negotiations are being used (this has to be known for the
  402. --                   message-signing key to be generated properly). 
  403. --@return (lm_response, ntlm_response, mac_key) The two strings that can be sent directly back to the server, 
  404. --                 and the mac_key, which is used for message signing. 
  405. local function get_password_response(ip, username, domain, password, password_hash, challenge, hash_type, is_extended)
  406.  
  407.     local lm_hash   = nil
  408.     local ntlm_hash = nil
  409.     local mac_key   = nil
  410.  
  411.     -- Check if there's a password or hash set. This is a little tricky, because in all places (except the one passed
  412.     -- as a parameter), it's based on whether or not the username was stored. This lets us use blank passwords by not
  413.     -- specifying one. 
  414.     if(password ~= nil) then
  415.         stdnse.print_debug(2, "SMB: Using password/hash passed as a parameter (username = '%s')", username)
  416.  
  417.     elseif(nmap.registry.args.smbusername ~= nil or nmap.registry.args.smbuser ~= nil) then
  418.         stdnse.print_debug(2, "SMB: Using password/hash passed as an nmap parameter")
  419.  
  420.         if(nmap.registry.args.smbpassword ~= nil) then
  421.             password = nmap.registry.args.smbpassword
  422.         elseif(nmap.registry.args.smbpass ~= nil) then
  423.             password = nmap.registry.args.smbpass
  424.         elseif(nmap.registry.args.smbhash ~= nil) then
  425.             password_hash = nmap.registry.args.smbhash
  426.         end
  427.  
  428.     elseif(nmap.registry[ip] ~= nil and nmap.registry[ip]['smbaccount'] ~= nil and nmap.registry[ip]['smbaccount']['username'] ~= nil) then
  429.         stdnse.print_debug(2, "SMB: Using password/hash found in the registry")
  430.  
  431.         if(nmap.registry[ip]['smbaccount']['password'] ~= nil) then
  432.             password = nmap.registry[ip]['smbaccount']['password']
  433.         elseif(nmap.registry[ip]['smbaccount']['hash'] ~= nil) then
  434.             password_hash = nmap.registry[ip]['smbaccount']['password']
  435.         end
  436.  
  437.     else
  438.         password = nil
  439.         password_hash = nil
  440.     end
  441.  
  442.     -- Check for a blank password
  443.     if(password == nil and password_hash == nil) then
  444.         stdnse.print_debug(2, "SMB: Couldn't find password or hash to use (assuming blank)")
  445.         password = ""
  446.     end
  447.  
  448.     -- If we got a password, hash it
  449.     if(password ~= nil) then
  450.         status, lm_hash   = lm_create_hash(password)
  451.         status, ntlm_hash = ntlm_create_hash(password)
  452.     else
  453.         if(password_hash ~= nil) then
  454.             if(string.find(password_hash, "^" .. string.rep("%x%x", 16) .. "$")) then
  455.                 stdnse.print_debug(2, "SMB: Found a 16-byte hex string")
  456.                 lm_hash   = bin.pack("H", password_hash:sub(1, 32))
  457.                 ntlm_hash = bin.pack("H", password_hash:sub(1, 32))
  458.             elseif(string.find(password_hash, "^" .. string.rep("%x%x", 32) .. "$")) then
  459.                 stdnse.print_debug(2, "SMB: Found a 32-byte hex string")
  460.                 lm_hash   = bin.pack("H", password_hash:sub(1, 32))
  461.                 ntlm_hash = bin.pack("H", password_hash:sub(33, 64))
  462.             elseif(string.find(password_hash, "^" .. string.rep("%x%x", 16) .. "." .. string.rep("%x%x", 16) .. "$")) then
  463.                 stdnse.print_debug(2, "SMB: Found two 16-byte hex strings")
  464.                 lm_hash   = bin.pack("H", password_hash:sub(1, 32))
  465.                 ntlm_hash = bin.pack("H", password_hash:sub(34, 65))
  466.             else
  467.                 stdnse.print_debug(1, "SMB: ERROR: Hash(es) provided in an invalid format (should be 32, 64, or 65 hex characters)")
  468.                 lm_hash = nil
  469.                 ntlm_hash = nil
  470.             end
  471.         end
  472.     end
  473.  
  474.     -- At this point, we should have a good lm_hash and ntlm_hash if we're getting one
  475.     if(lm_hash == nil or ntlm_hash == nil) then
  476.         stdnse.print_debug(2, "SMB: Couldn't determine which password to use, using a blank one")
  477.         return "", ""
  478.     end
  479.  
  480.     -- Output what we've got so far
  481.     stdnse.print_debug(2, "SMB: Lanman hash: %s", stdnse.tohex(lm_hash))
  482.     stdnse.print_debug(2, "SMB: NTLM   hash: %s", stdnse.tohex(ntlm_hash))
  483.             
  484.     -- Hash the password the way the user wants
  485.     if(hash_type == "v1") then
  486.         -- LM and NTLM are hashed with their respective algorithms
  487.         stdnse.print_debug(2, "SMB: Creating v1 response")
  488.         status, lm_response   = lm_create_response(lm_hash, challenge)
  489.         status, ntlm_response = ntlm_create_response(ntlm_hash, challenge)
  490.  
  491.         mac_key               = ntlm_create_mac_key(ntlm_hash, ntlm_response, is_extended)
  492.  
  493.     elseif(hash_type == "lm") then
  494.         -- LM is hashed with its algorithm, NTLM is blank
  495.         stdnse.print_debug(2, "SMB: Creating LMv1 response")
  496.         status, lm_response   = lm_create_response(lm_hash, challenge)
  497.                 ntlm_response = ""
  498.  
  499.         mac_key               = lm_create_mac_key(lm_hash, lm_response, is_extended)
  500.  
  501.     elseif(hash_type == "ntlm") then
  502.         -- LM and NTLM both use the NTLM algorithm
  503.         stdnse.print_debug(2, "SMB: Creating NTLMv1 response")
  504.         status, lm_response   = ntlm_create_response(ntlm_hash, challenge)
  505.         status, ntlm_response = ntlm_create_response(ntlm_hash, challenge)
  506.  
  507.         mac_key               = ntlm_create_mac_key(ntlm_hash, ntlm_response, is_extended)
  508.  
  509.     elseif(hash_type == "v2") then
  510.         -- LM and NTLM are hashed with their respective v2 algorithms
  511.         stdnse.print_debug(2, "SMB: Creating v2 response")
  512.         status, lm_response   = lmv2_create_response(ntlm_hash, username, domain, challenge)
  513.         status, ntlm_response = ntlmv2_create_response(ntlm_hash, username, domain, challenge, 24)
  514.  
  515.     elseif(hash_type == "lmv2") then
  516.         -- LM is hashed with its v2 algorithm, NTLM is blank
  517.         stdnse.print_debug(2, "SMB: Creating LMv2 response")
  518.         status, lm_response   = lmv2_create_response(ntlm_hash, username, domain, challenge)
  519.                 ntlm_response = ""
  520.  
  521.     else
  522.         -- Default to NTLMv1
  523.         stdnse.print_debug(1, "SMB: Invalid login type specified, using default (NTLM)")
  524.         status, lm_response   = ntlm_create_response(ntlm_hash, challenge)
  525.         status, ntlm_response = ntlm_create_response(ntlm_hash, challenge)
  526.  
  527.     end
  528.  
  529.     stdnse.print_debug(2, "SMB: Lanman response: %s", stdnse.tohex(lm_response))
  530.     stdnse.print_debug(2, "SMB: NTLM   response: %s", stdnse.tohex(ntlm_response))
  531.  
  532.     return lm_response, ntlm_response, mac_key
  533. end
  534.  
  535. ---Get the list of accounts to use to log in. TODO: More description
  536. function get_accounts(ip, overrides, use_defaults)
  537.     local results = {}
  538.     -- Just so we can index into it
  539.     if(overrides == nil) then
  540.         overrides = {}
  541.     end
  542.     -- By default, use defaults
  543.     if(use_defaults == nil) then
  544.         use_defaults = true
  545.     end
  546.  
  547.     -- If we don't have OpenSSL, don't bother with any of this because we aren't going to 
  548.     -- be able to hash the password
  549.     if(have_ssl == true) then
  550.         local result = {}
  551.  
  552.         -- Get the "real" information
  553.         result['username']  = get_username(ip, overrides['username'])
  554.         result['domain']    = get_domain(ip,   overrides['domain'])
  555.         result['hash_type'] = get_hash_type(overrides['hash_type'])
  556.  
  557.         if(result['username'] ~= nil) then
  558.             results[#results + 1] = result
  559.         end
  560.  
  561.         -- Do the "guest" account, if use_defaults is set
  562.         if(use_defaults) then
  563.             result = {}
  564.             result['username'] = "guest"
  565.             result['domain']   = ""
  566.             result['hash_type'] = get_hash_type(overrides['hash_type'])
  567.             results[#results + 1] = result
  568.         end
  569.     end
  570.  
  571.     -- Do the "anonymous" account
  572.     if(use_defaults) then
  573.         result = {}
  574.         result['username'] = ""
  575.         result['domain']   = ""
  576.         results[#results + 1] = result
  577.     end
  578.  
  579.     return results
  580. end
  581.  
  582. function get_password_hashes(ip, username, domain, hash_type, overrides, challenge, is_extended)
  583.     if(overrides == nil) then
  584.         overrides = {}
  585.     end
  586.  
  587.     if(username == "") then
  588.         return string.char(0), '', nil
  589.     elseif(username == "guest") then
  590.         return get_password_response(ip, username, domain, "", nil, challenge, hash_type, is_extended)
  591.     else
  592.         return get_password_response(ip, username, domain, overrides['password'], overrides['password_hash'], challenge, hash_type, is_extended)
  593.     end
  594. end
  595.  
  596. function get_security_blob(security_blob, ip, username, domain, hash_type, overrides, use_default)
  597.     local pos = 1
  598.     local new_blob
  599.     local flags = 0x00008211 -- (NEGOTIATE_SIGN_ALWAYS | NEGOTIATE_NTLM | NEGOTIATE_SIGN | NEGOTIATE_UNICODE)
  600.  
  601.     if(session_key == nil) then
  602.         session_key = string.rep(string.char(0x00), 16)
  603.     end
  604.  
  605.     if(security_blob == nil) then
  606.         -- If security_blob is nil, this is the initial packet
  607.         new_blob = bin.pack("<zIILL", 
  608.                     "NTLMSSP",            -- Identifier
  609.                     NTLMSSP_NEGOTIATE,    -- Type
  610.                     flags,                -- Flags 
  611.                     0,                    -- Calling workstation domain
  612.                     0                     -- Calling workstation name
  613.                 )
  614.  
  615.         return true, new_blob, "", ""
  616.     else
  617.         local identifier, message_type, domain_length, domain_max, domain_offset, server_flags, challenge, reserved
  618.  
  619.         -- Parse the old security blob
  620.         pos, identifier, message_type, domain_length, domain_max, domain_offset, server_flags, challenge, reserved = bin.unpack("<LISSIIA8A8", security_blob, 1)
  621.  
  622.         -- Get the information for the current login
  623.         local lanman, ntlm, mac_key = get_password_hashes(ip, username, domain, hash_type, overrides, challenge, true)
  624.  
  625.         -- Convert the username and domain to unicode (TODO: Disable the unicode flag, evaluate if that'll work)
  626.         username = to_unicode(username)
  627.         domain   = to_unicode(domain)
  628.  
  629.         new_blob = bin.pack("<zISSISSISSISSISSISSII", 
  630.                     "NTLMSSP",            -- Identifier
  631.                     NTLMSSP_AUTH,         -- Type
  632.                     #lanman,              -- Lanman (length, max, offset)
  633.                     #lanman,              -- 
  634.                     0x40,                 -- 
  635.                     #ntlm,                -- NTLM (length, max, offset)
  636.                     #ntlm,                -- 
  637.                     0x40 + #lanman,       -- 
  638.                     #domain,              -- Domain (length, max, offset)
  639.                     #domain,              --
  640.                     0x40 + #lanman + #ntlm,--
  641.                     #username,            -- Username (length, max, offset)
  642.                     #username,            -- 
  643.                     0x40 + #lanman + #ntlm + #domain,
  644.                     #domain,              -- Hostname (length, max, offset)
  645.                     #domain,              --
  646.                     0x40 + #lanman + #ntlm + #domain + #username,
  647.                     #session_key,         -- Session key (length, max, offset)
  648.                     #session_key,         --
  649.                     0x40 + #lanman + #ntlm + #domain + #username + #domain,
  650.                     flags                 -- Flags
  651.                 )
  652.  
  653.         new_blob = new_blob .. bin.pack("AAAAAA", lanman, ntlm, domain, username, domain, session_key)
  654.         return true, new_blob, mac_key
  655.     end
  656.  
  657. end
  658.  
  659. ---Create an 8-byte message signature that's sent with all SMB packets. 
  660. --
  661. --@param mac_key The key used for authentication. It's the concatination of the session key and the
  662. --               response hash. 
  663. --@param data The packet to generate the signature for. This should be the packet that's about to be
  664. --            sent, except with the signature slot replaced with the sequence number. 
  665. --@return The 8-byte signature. The signature is equal to the first eight bytes of md5(mac_key .. smb_data)
  666. function calculate_signature(mac_key, data)
  667.     if(have_ssl) then
  668.         return string.sub(openssl.md5(mac_key .. data), 1, 8)
  669.     else
  670.         return string.rep(string.char(0), 8)
  671.     end
  672. end
  673.  
  674.  
  675.  
  676.  
  677.  
  678.  
  679.  
  680.  
  681.  
  682.  
  683.  
  684.