PageRenderTime 58ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/nselib/smb.lua

https://github.com/prakashgamit/nmap
Lua | 4284 lines | 3222 code | 390 blank | 672 comment | 460 complexity | fb307d45757867fabf35c5ec47caa3b4 MD5 | raw file
Possible License(s): BSD-3-Clause, GPL-2.0, LGPL-2.0, LGPL-2.1

Large files files are truncated, but you can click here to view the full file

  1. ---
  2. -- Implements functionality related to Server Message Block (SMB, an extension
  3. -- of CIFS) traffic, which is a Windows protocol.
  4. --
  5. -- SMB traffic is normally sent to/from ports 139 or 445 of Windows systems. Other systems
  6. -- implement SMB as well, including Samba and a lot of embedded devices. Some of them implement
  7. -- it properly and many of them not. Although the protocol has been documented decently
  8. -- well by Samba and others, many 3rd party implementations are broken or make assumptions.
  9. -- Even Samba's and Windows' implementations aren't completely compatible. As a result,
  10. -- creating an implementation that accepts everything is a bit of a minefield. Microsoft's
  11. -- extensive documentation is available at the following URLs:
  12. -- * SMB: http://msdn.microsoft.com/en-us/library/cc246231(v=prot.13).aspx
  13. -- * CIFS: http://msdn.microsoft.com/en-us/library/ee442092(v=prot.13).aspx
  14. --
  15. -- Where possible, this implementation, since it's intended for scanning, will attempt to
  16. -- accept any invalid implementations it can, and fail gracefully if it can't. This has
  17. -- been tested against a great number of weird implementations, and it now works against
  18. -- all of them.
  19. --
  20. -- The intention of this library is to eventually handle all aspects of the SMB protocol.
  21. -- That being said, I'm only implementing the pieces that I (Ron Bowes) need. If you
  22. -- require something more, let me know and I'll put it on my todo list.
  23. --
  24. -- A programmer using this library should already have some knowledge of the SMB protocol,
  25. -- although a lot isn't necessary. You can pick up a lot by looking at the code. The basic
  26. -- login/logoff is this:
  27. --
  28. -- <code>
  29. -- [connect]
  30. -- C->S SMB_COM_NEGOTIATE
  31. -- S->C SMB_COM_NEGOTIATE
  32. -- C->S SMB_COM_SESSION_SETUP_ANDX
  33. -- S->C SMB_COM_SESSION_SETUP_ANDX
  34. -- C->S SMB_COM_TREE_CONNECT_ANDX
  35. -- S->C SMB_COM_TREE_CONNECT_ANDX
  36. -- ...
  37. -- C->S SMB_COM_TREE_DISCONNECT
  38. -- S->C SMB_COM_TREE_DISCONNECT
  39. -- C->S SMB_COM_LOGOFF_ANDX
  40. -- S->C SMB_COM_LOGOFF_ANDX
  41. -- [disconnect]
  42. -- </code>
  43. --
  44. -- In terms of functions here, the protocol is:
  45. --
  46. -- <code>
  47. -- status, smbstate = smb.start(host)
  48. -- status, err = smb.negotiate_protocol(smbstate, {})
  49. -- status, err = smb.start_session(smbstate, {})
  50. -- status, err = smb.tree_connect(smbstate, path, {})
  51. -- ...
  52. -- status, err = smb.tree_disconnect(smbstate)
  53. -- status, err = smb.logoff(smbstate)
  54. -- status, err = smb.stop(smbstate)
  55. -- </code>
  56. --
  57. -- The <code>stop</code> function will automatically call tree_disconnect and logoff,
  58. -- cleaning up the session, if it hasn't been done already.
  59. --
  60. -- To initially begin the connection, there are two options:
  61. --
  62. -- 1) Attempt to start a raw session over 445, if it's open.
  63. --
  64. -- 2) Attempt to start a NetBIOS session over 139. Although the
  65. -- protocol's the same, it requires a <code>session request</code> packet.
  66. -- That packet requires the computer's name, which is requested
  67. -- using a NBSTAT probe over UDP port 137.
  68. --
  69. -- Once it's connected, a <code>SMB_COM_NEGOTIATE</code> packet is sent, requesting the protocol
  70. -- "NT LM 0.12", which is the most commonly supported one. Among other things, the server's
  71. -- response contains the host's security level, the system time, and the computer/domain name.
  72. -- Some systems will refuse to use that protocol and return "-1" or "1" instead of 0. If that's
  73. -- detected, we kill the connection (because the protocol following won't work).
  74. --
  75. -- If that's successful, <code>SMB_COM_SESSION_SETUP_ANDX</code> is sent. It is essentially the logon
  76. -- packet, where the username, domain, and password are sent to the server for verification.
  77. -- The username and password are generally picked up from the program parameters, which are
  78. -- set when running a script, or from the registry where it can be set by other scripts (for
  79. -- example, <code>smb-brute.nse</code>). However, they can also be passed as parameters to the
  80. -- function, which will override any other username/password set.
  81. --
  82. -- If a username and password are set, they are used for the first login attempt. If a login fails,
  83. -- or they weren't set, a connection as the 'GUEST' account with a blank password is attempted. If
  84. -- that fails, then a NULL session is established, which should always work. The username/password
  85. -- will give the highest access level, GUEST will give lower access, and NULL will give the lowest
  86. -- (often, NULL will give no access).
  87. --
  88. -- The actual login protocol used by <code>SMB_COM_SESSION_SETUP_ANDX</code> is explained in detail
  89. -- in <code>smbauth.lua</code>.
  90. --
  91. -- Thanks go to Christopher R. Hertel and his book Implementing CIFS, which
  92. -- taught me everything I know about Microsoft's protocols. Additionally, I used Samba's
  93. -- list of error codes for my constants. Although I don't believe they would be covered
  94. -- by GPL, since they're public now anyways, but I'm not a lawyer and, if somebody feels
  95. -- differently, let me know and we can sort this out.
  96. --
  97. -- Scripts that use this module can use the script arguments listed below
  98. -- example of using these script arguments:
  99. -- <code>
  100. -- nmap --script=smb-<script>.nse --script-args=smbuser=ron,smbpass=iagotest2k3,smbbasic=1,smbsign=force <host>
  101. -- </code>
  102. --
  103. -- @args smbbasic Forces the authentication to use basic security, as opposed to "extended security".
  104. -- Against most modern systems, extended security should work, but there may be cases
  105. -- where you want to force basic. There's a chance that you'll get better results for
  106. -- enumerating users if you turn on basic authentication.
  107. -- @args smbsign Controls whether or not server signatures are checked in SMB packets. By default, on Windows,
  108. -- server signatures aren't enabled or required. By default, this library will always sign
  109. -- packets if it knows how, and will check signatures if the server says to. Possible values are:
  110. -- * <code>force</code>: Always check server signatures, even if server says it doesn't support them (will
  111. -- probably fail, but is technically more secure).
  112. -- * <code>negotiate</code>: [default] Use signatures if server supports them.
  113. -- * <code>ignore</code>: Never check server signatures. Not recommended.
  114. -- * <code>disable</code>: Don't send signatures, at all, and don't check the server's. not recommended.
  115. -- More information on signatures can be found in <code>smbauth.lua</code>.
  116. -- @args smbport Override the default port choice. If <code>smbport</code> is open, it's used. It's assumed
  117. -- to be the same protocol as port 445, not port 139. Since it probably isn't possible to change
  118. -- Windows' ports normally, this is mostly useful if you're bouncing through a relay or something.
  119. -- @args randomseed Set to a value to change the filenames/service names that are randomly generated.
  120. --
  121. -- @author Ron Bowes <ron@skullsecurity.net>
  122. -- @copyright Same as Nmap--See http://nmap.org/book/man-legal.html
  123. -----------------------------------------------------------------------
  124. local asn1 = require "asn1"
  125. local bin = require "bin"
  126. local bit = require "bit"
  127. local coroutine = require "coroutine"
  128. local io = require "io"
  129. local math = require "math"
  130. local match = require "match"
  131. local netbios = require "netbios"
  132. local nmap = require "nmap"
  133. local os = require "os"
  134. local smbauth = require "smbauth"
  135. local stdnse = require "stdnse"
  136. local string = require "string"
  137. local table = require "table"
  138. _ENV = stdnse.module("smb", stdnse.seeall)
  139. -- These arrays are filled in with constants at the bottom of this file
  140. command_codes = {}
  141. command_names = {}
  142. status_codes = {}
  143. status_names = {}
  144. filetype_codes = {}
  145. filetype_names = {}
  146. local TIMEOUT = 10000
  147. ---Wrapper around <code>smbauth.add_account</code>.
  148. function add_account(host, username, domain, password, password_hash, hash_type, is_admin)
  149. smbauth.add_account(host, username, domain, password, password_hash, hash_type, is_admin)
  150. end
  151. ---Wrapper around <code>smbauth.get_account</code>.
  152. function get_account(host)
  153. return smbauth.get_account(host)
  154. end
  155. ---Create an 'overrides' table
  156. function get_overrides(username, domain, password, password_hash, hash_type, overrides)
  157. if(not(overrides)) then
  158. return {username=username, domain=domain, password=password, password_hash=password_hash, hash_type=hash_type}
  159. else
  160. overrides['username'] = username
  161. overrides['domain'] = domain
  162. overrides['password'] = password
  163. overrides['password_hash'] = password_hash
  164. overrides['hash_type'] = hash_type
  165. end
  166. end
  167. ---Get an 'overrides' table for the anonymous user
  168. --
  169. --@param overrides [optional] A base table of overrides. The appropriate fields will be added.
  170. function get_overrides_anonymous(overrides)
  171. if(not(overrides)) then
  172. return {username='', domain='', password='', password_hash=nil, hash_type='none'}
  173. else
  174. overrides['username'] = ''
  175. overrides['domain'] = ''
  176. overrides['password'] = ''
  177. overrides['password_hash'] = ''
  178. overrides['hash_type'] = 'none'
  179. end
  180. end
  181. ---Convert a status number from the SMB header into a status name, returning an error message (not nil) if
  182. -- it wasn't found.
  183. --
  184. --@param status The numerical status.
  185. --@return A string representing the error. Never nil.
  186. function get_status_name(status)
  187. if(status_names[status] == nil) then
  188. -- If the name wasn't found in the array, do a linear search on it
  189. for i, v in pairs(status_names) do
  190. if(v == status) then
  191. return i
  192. end
  193. end
  194. return string.format("NT_STATUS_UNKNOWN (0x%08x)", status)
  195. else
  196. return status_names[status]
  197. end
  198. end
  199. --- Determines whether or not SMB checks are possible on this host, and, if they are,
  200. -- which port is best to use. This is how it decides:
  201. --
  202. -- * If port tcp/445 is open, use it for a raw connection
  203. -- * Otherwise, if ports tcp/139 and udp/137 are open, do a NetBIOS connection. Since UDP scanning isn't default, we're also ok with udp/137 in an unknown state.
  204. --
  205. --@param host The host object.
  206. --@return The port number to use, or nil if we don't have an SMB port
  207. function get_port(host)
  208. local port_u137 = nmap.get_port_state(host, {number=137, protocol="udp"})
  209. local port_t139 = nmap.get_port_state(host, {number=139, protocol="tcp"})
  210. local port_t445 = nmap.get_port_state(host, {number=445, protocol="tcp"})
  211. local custom_port = nil
  212. if(nmap.registry.args.smbport ~= nil) then
  213. custom_port = nmap.get_port_state(host, {number=tonumber(nmap.registry.args.smbport), protocol="tcp"})
  214. end
  215. -- Try a user-defined port first
  216. if(custom_port ~= nil and custom_port.state == "open") then
  217. return custom_port.number
  218. end
  219. if(port_t445 ~= nil and port_t445.state == "open") then
  220. -- tcp/445 is open, we're good
  221. return 445
  222. end
  223. if(port_t139 ~= nil and port_t139.state == "open") then
  224. -- tcp/139 is open, check uf udp/137 is open or unknown
  225. if(port_u137 == nil or port_u137.state == "open" or port_u137.state == "open|filtered") then
  226. return 139
  227. end
  228. end
  229. return nil
  230. end
  231. ---Turn off extended security negotiations for this connection. There are a few reasons you might want to
  232. -- do that, the main ones being that extended security is going to be marginally slower and it's not going
  233. -- to give the same level of information in some cases (namely, it doesn't present the server's name).
  234. --@param smb The SMB state table.
  235. function disable_extended(smb)
  236. smb['extended_security'] = false
  237. end
  238. --- Begins a SMB session, automatically determining the best way to connect.
  239. --
  240. -- @param host The host object
  241. -- @return (status, smb) if the status is true, result is the newly crated smb object;
  242. -- otherwise, socket is the error message.
  243. function start(host)
  244. local port = get_port(host)
  245. local status, result
  246. local state = {}
  247. state['uid'] = 0
  248. state['tid'] = 0
  249. state['mid'] = 1
  250. state['pid'] = math.random(32766) + 1
  251. state['host'] = host
  252. state['ip'] = host.ip
  253. state['sequence'] = -1
  254. -- Check whether or not the user requested basic authentication
  255. if(stdnse.get_script_args( "smbbasic" )) then
  256. state['extended_security'] = false
  257. else
  258. state['extended_security'] = true
  259. end
  260. -- Store the name of the server
  261. local nbcache_mutex = nmap.mutex("Netbios lookup mutex")
  262. nbcache_mutex "lock"
  263. if ( not(host.registry['netbios_name']) ) then
  264. status, result = netbios.get_server_name(host.ip)
  265. if(status == true) then
  266. host.registry['netbios_name'] = result
  267. state['name'] = result
  268. end
  269. else
  270. stdnse.print_debug(2, "SMB: Resolved netbios name from cache")
  271. state['name'] = host.registry['netbios_name']
  272. end
  273. nbcache_mutex "done"
  274. stdnse.print_debug(2, "SMB: Starting SMB session for %s (%s)", host.name, host.ip)
  275. if(port == nil) then
  276. return false, "SMB: Couldn't find a valid port to check"
  277. end
  278. -- Initialize the accounts for logging on
  279. smbauth.init_account(host)
  280. if(port ~= 139) then
  281. status, state['socket'] = start_raw(host, port)
  282. state['port'] = port
  283. if(status == false) then
  284. return false, state['socket']
  285. end
  286. return true, state
  287. else
  288. status, state['socket'] = start_netbios(host, port)
  289. state['port'] = port
  290. if(status == false) then
  291. return false, state['socket']
  292. end
  293. return true, state
  294. end
  295. return false, "SMB: Couldn't find a valid port to check"
  296. end
  297. ---Initiates a SMB connection over whichever port it can, then optionally sends the common
  298. -- initialization packets. Note that each packet depends on the previous one, so if you want
  299. -- to go all the way up to create_file, you have to set all parameters.
  300. --
  301. -- If anything fails, we back out of the connection and return an error, so the calling function
  302. -- doesn't have to call smb.stop().
  303. --
  304. --@param host The host object.
  305. --@param bool_negotiate_protocol [optional] If 'true', send the protocol negotiation. Default: false.
  306. --@param bool_start_session [optional] If 'true', start the session. Default: false.
  307. --@param str_tree_connect [optional] The tree to connect to, if given (eg. "IPC$" or "C$"). If not given,
  308. -- packet isn't sent.
  309. --@param str_create_file [optional] The path and name of the file (or pipe) that's created, if given. If
  310. -- not given, packet isn't sent.
  311. --@param overrides [optional] A table of overrides (for, for example, username, password, etc.) to pass
  312. -- to all functions.
  313. --@param bool_disable_extended [optional] If set to true, disables extended security negotiations.
  314. function start_ex(host, bool_negotiate_protocol, bool_start_session, str_tree_connect, str_create_file, bool_disable_extended, overrides)
  315. local smbstate
  316. local status, err
  317. -- Make sure we have overrides
  318. overrides = overrides or {}
  319. -- Begin the SMB session
  320. status, smbstate = start(host)
  321. if(status == false) then
  322. return false, smbstate
  323. end
  324. -- Disable extended security if it was requested
  325. if(bool_disable_extended == true) then
  326. disable_extended(smbstate)
  327. end
  328. if(bool_negotiate_protocol == true) then
  329. -- Negotiate the protocol
  330. status, err = negotiate_protocol(smbstate, overrides)
  331. if(status == false) then
  332. stop(smbstate)
  333. return false, err
  334. end
  335. if(bool_start_session == true) then
  336. -- Start up a session
  337. status, err = start_session(smbstate, overrides)
  338. if(status == false) then
  339. stop(smbstate)
  340. return false, err
  341. end
  342. if(str_tree_connect ~= nil) then
  343. -- Connect to share
  344. status, err = tree_connect(smbstate, str_tree_connect, overrides)
  345. if(status == false) then
  346. stop(smbstate)
  347. return false, err
  348. end
  349. if(str_create_file ~= nil) then
  350. -- Try to connect to requested pipe
  351. status, err = create_file(smbstate, str_create_file, overrides)
  352. if(status == false) then
  353. stop(smbstate)
  354. return false, err
  355. end
  356. end
  357. end
  358. end
  359. end
  360. -- Return everything
  361. return true, smbstate
  362. end
  363. --- Kills the SMB connection and closes the socket.
  364. --
  365. -- In addition to killing the connection, this function will log off the user and disconnect
  366. -- the connected tree, if possible.
  367. --
  368. --@param smb The SMB object associated with the connection
  369. --@return (status, result) If status is false, result is an error message. Otherwise, result
  370. -- is undefined.
  371. function stop(smb)
  372. if(smb['tid'] ~= 0) then
  373. tree_disconnect(smb)
  374. end
  375. if(smb['uid'] ~= 0) then
  376. logoff(smb)
  377. end
  378. stdnse.print_debug(2, "SMB: Closing socket")
  379. if(smb['socket'] ~= nil) then
  380. local status, err = smb['socket']:close()
  381. if(status == false) then
  382. return false, "SMB: Failed to close socket: " .. err
  383. end
  384. end
  385. return true
  386. end
  387. --- Begins a raw SMB session, likely over port 445. Since nothing extra is required, this
  388. -- function simply makes a connection and returns the socket.
  389. --
  390. --@param host The host object to check.
  391. --@param port The port to use (most likely 445).
  392. --@return (status, socket) if status is true, result is the newly created socket.
  393. -- Otherwise, socket is the error message.
  394. function start_raw(host, port)
  395. local status, err
  396. local socket = nmap.new_socket()
  397. socket:set_timeout(TIMEOUT)
  398. status, err = socket:connect(host, port, "tcp")
  399. if(status == false) then
  400. return false, "SMB: Failed to connect to host: " .. err
  401. end
  402. return true, socket
  403. end
  404. --- This function will take a string like "a.b.c.d" and return "a", "a.b", "a.b.c", and "a.b.c.d".
  405. -- This is used for discovering NetBIOS names. If a NetBIOS name is unknown, the substrings of the
  406. -- DNS name can be used in this way.
  407. --
  408. --@param name The name to take apart
  409. --@return An array of the sub names
  410. local function get_subnames(name)
  411. local i = -1
  412. local list = {}
  413. repeat
  414. local subname = name
  415. i = string.find(name, "[.]", i + 1)
  416. if(i ~= nil) then
  417. subname = string.sub(name, 1, i - 1)
  418. end
  419. list[#list + 1] = string.upper(subname)
  420. until i == nil
  421. return list
  422. end
  423. --- Begins a SMB session over NetBIOS. This requires a NetBIOS Session Start message to
  424. -- be sent first, which in turn requires the NetBIOS name. The name can be provided as
  425. -- a parameter, or it can be automatically determined.
  426. --
  427. -- Automatically determining the name is interesting, to say the least. Here are the names
  428. -- it tries, and the order it tries them in:
  429. -- * The name the user provided, if present
  430. -- * The name pulled from NetBIOS (udp/137), if possible
  431. -- * The generic name "*SMBSERVER"
  432. -- * Each subset of the domain name (for example, scanme.insecure.org would attempt "scanme",
  433. -- "scanme.insecure", and "scanme.insecure.org")
  434. --
  435. -- This whole sequence is a little hackish, but it's the standard way of doing it.
  436. --
  437. --@param host The host object to check.
  438. --@param port The port to use (most likely 139).
  439. --@param name [optional] The NetBIOS name of the host. Will attempt to automatically determine
  440. -- if it isn't given.
  441. --@return (status, socket) if status is true, result is the port
  442. -- Otherwise, socket is the error message.
  443. function start_netbios(host, port, name)
  444. local i
  445. local status, err
  446. local pos, result, flags, length
  447. local socket = nmap.new_socket()
  448. -- First, populate the name array with all possible names, in order of significance
  449. local names = {}
  450. -- Use the name parameter
  451. if(name ~= nil) then
  452. names[#names + 1] = name
  453. end
  454. -- Get the name of the server from NetBIOS
  455. status, name = netbios.get_server_name(host.ip)
  456. if(status == true) then
  457. names[#names + 1] = name
  458. end
  459. -- "*SMBSERVER" is a special name that any server should respond to
  460. names[#names + 1] = "*SMBSERVER"
  461. -- If all else fails, use each substring of the DNS name (this is a HUGE hack, but is actually
  462. -- a recommended way of doing this!)
  463. if(host.name ~= nil and host.name ~= "") then
  464. local new_names = get_subnames(host.name)
  465. for i = 1, #new_names, 1 do
  466. names[#names + 1] = new_names[i]
  467. end
  468. end
  469. -- This loop will try all the NetBIOS names we've collected, hoping one of them will work. Yes,
  470. -- this is a hackish way, but it's actually the recommended way.
  471. i = 1
  472. repeat
  473. -- Use the current name
  474. name = names[i]
  475. -- Some debug information
  476. stdnse.print_debug(1, "SMB: Trying to start NetBIOS session with name = '%s'", name)
  477. -- Request a NetBIOS session
  478. local session_request = bin.pack(">CCSzz",
  479. 0x81, -- session request
  480. 0x00, -- flags
  481. 0x44, -- length
  482. netbios.name_encode(name), -- server name
  483. netbios.name_encode("NMAP") -- client name
  484. );
  485. stdnse.print_debug(3, "SMB: Connecting to %s", host.ip)
  486. socket:set_timeout(TIMEOUT)
  487. status, err = socket:connect(host, port, "tcp")
  488. if(status == false) then
  489. socket:close()
  490. return false, "SMB: Failed to connect: " .. err
  491. end
  492. -- Send the session request
  493. stdnse.print_debug(3, "SMB: Sending NetBIOS session request with name %s", name)
  494. status, err = socket:send(session_request)
  495. if(status == false) then
  496. socket:close()
  497. return false, "SMB: Failed to send: " .. err
  498. end
  499. socket:set_timeout(TIMEOUT)
  500. -- Receive the session response
  501. stdnse.print_debug(3, "SMB: Receiving NetBIOS session response")
  502. status, result = socket:receive_buf(match.numbytes(4), true);
  503. if(status == false) then
  504. socket:close()
  505. return false, "SMB: Failed to close socket: " .. result
  506. end
  507. pos, result, flags, length = bin.unpack(">CCS", result)
  508. if(result == nil or length == nil) then
  509. return false, "SMB: ERROR: Server returned less data than it was supposed to (one or more fields are missing); aborting [1]"
  510. end
  511. -- Check for a positive session response (0x82)
  512. if result == 0x82 then
  513. stdnse.print_debug(3, "SMB: Successfully established NetBIOS session with server name %s", name)
  514. return true, socket
  515. end
  516. -- If the session failed, close the socket and try the next name
  517. stdnse.print_debug(1, "SMB: Session request failed, trying next name")
  518. socket:close()
  519. -- Try the next name
  520. i = i + 1
  521. until i > #names
  522. -- We reached the end of our names list
  523. stdnse.print_debug(1, "SMB: None of the NetBIOS names worked!")
  524. return false, "SMB: Couldn't find a NetBIOS name that works for the server. Sorry!"
  525. end
  526. --- Creates a string containing a SMB packet header. The header looks like this:
  527. --
  528. --<code>
  529. -- --------------------------------------------------------------------------------------------------
  530. -- | 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 |
  531. -- --------------------------------------------------------------------------------------------------
  532. -- | 0xFF | 'S' | 'M' | 'B' |
  533. -- --------------------------------------------------------------------------------------------------
  534. -- | Command | Status... |
  535. -- --------------------------------------------------------------------------------------------------
  536. -- | ...Status | Flags | Flags2 |
  537. -- --------------------------------------------------------------------------------------------------
  538. -- | PID_high | Signature..... |
  539. -- --------------------------------------------------------------------------------------------------
  540. -- | ....Signature.... |
  541. -- --------------------------------------------------------------------------------------------------
  542. -- | ....Signature | Unused |
  543. -- --------------------------------------------------------------------------------------------------
  544. -- | TID | PID |
  545. -- --------------------------------------------------------------------------------------------------
  546. -- | UID | MID |
  547. -- -------------------------------------------------------------------------------------------------
  548. --</code>
  549. --
  550. -- All fields are, incidentally, encoded in little endian byte order.
  551. --
  552. -- For the purposes here, the program doesn't care about most of the fields so they're given default
  553. -- values. The "command" field is the only one we ever have to set manually, in my experience. The TID
  554. -- and UID need to be set, but those are stored in the smb state and don't require user intervention.
  555. --
  556. --@param smb The smb state table.
  557. --@param command The command to use.
  558. --@param overrides The overrides table. Keep in mind that overriding things like flags is generally a very bad idea, unless you know what you're doing.
  559. --@return A binary string containing the packed packet header.
  560. function smb_encode_header(smb, command, overrides)
  561. -- Make sure we have an overrides array
  562. overrides = overrides or {}
  563. -- Used for the header
  564. local sig = string.char(0xFF) .. "SMB"
  565. -- Pretty much every flags is deprecated. We set these two because they're required to be on.
  566. local flags = bit.bor(0x10, 0x08) -- SMB_FLAGS_CANONICAL_PATHNAMES | SMB_FLAGS_CASELESS_PATHNAMES
  567. -- These flags are less deprecated. We negotiate 32-bit status codes and long names. We also don't include Unicode, which tells
  568. -- the server that we deal in ASCII.
  569. local flags2 = bit.bor(0x4000, 0x2000, 0x0040, 0x0001) -- SMB_FLAGS2_32BIT_STATUS | SMB_FLAGS2_EXECUTE_ONLY_READS | SMB_FLAGS2_IS_LONG_NAME | SMB_FLAGS2_KNOWS_LONG_NAMES
  570. -- Unless the user's disabled the security signature, add it
  571. if(nmap.registry.args.smbsign ~= "disable") then
  572. flags2 = bit.bor(flags2, 0x0004) -- SMB_FLAGS2_SECURITY_SIGNATURE
  573. end
  574. if(smb['extended_security'] == true) then
  575. flags2 = bit.bor(flags2, 0x0800) -- SMB_EXTENDED_SECURITY
  576. end
  577. -- TreeID should never ever be 'nil', but it seems to happen once in awhile so print an error
  578. if(smb['tid'] == nil) then
  579. return false, string.format("SMB: ERROR: TreeID value was set to nil on host %s", smb['ip'])
  580. end
  581. local header = bin.pack("<CCCCCICSSLSSSSS",
  582. sig:byte(1), -- Header
  583. sig:byte(2), -- Header
  584. sig:byte(3), -- Header
  585. sig:byte(4), -- Header
  586. command, -- Command
  587. (overrides['status'] or 0), -- status
  588. (overrides['flags'] or flags), -- flags
  589. (overrides['flags2'] or flags2), -- flags2
  590. (overrides['pid_high'] or 0), -- extra (pid_high)
  591. (overrides['signature'] or 0), -- extra (signature)
  592. (overrides['extra'] or 0), -- extra (unused)
  593. (overrides['tid'] or smb['tid']), -- tid
  594. (overrides['pid'] or smb['pid']), -- pid
  595. (overrides['uid'] or smb['uid']), -- uid
  596. (overrides['mid'] or smb['mid']) -- mid
  597. )
  598. return header
  599. end
  600. --- Converts a string containing the parameters section into the encoded parameters string.
  601. -- The encoding is simple:
  602. -- * (1 byte) The number of 2-byte values in the parameters section
  603. -- * (variable) The parameter section
  604. -- This is automatically done by <code>smb_send</code>.
  605. --
  606. -- @param parameters The parameters section.
  607. -- @param overrides The overrides table. The only thing possible to override here is the length.
  608. -- @return The encoded parameters.
  609. local function smb_encode_parameters(parameters, overrides)
  610. -- Make sure we have an overrides array
  611. overrides = overrides or {}
  612. return bin.pack("<CA", (overrides['parameters_length'] or (#parameters / 2)), parameters)
  613. end
  614. --- Converts a string containing the data section into the encoded data string.
  615. -- The encoding is simple:
  616. -- * (2 bytes) The number of bytes in the data section
  617. -- * (variable) The data section
  618. -- This is automatically done by <code>smb_send</code>.
  619. --
  620. -- @param data The data section.
  621. -- @param overrides The overrides table. The only thing possible to override here is the length.
  622. -- @return The encoded data.
  623. local function smb_encode_data(data, overrides)
  624. -- Make sure we have an overrides array
  625. overrides = overrides or {}
  626. return bin.pack("<SA", (overrides['data_length'] or #data), data)
  627. end
  628. ---Sign the message, if possible. This is done by replacing the signature with the sequence
  629. -- number, creating a hash, then putting that hash in the signature location.
  630. --@param smb The smb state object.
  631. --@param body The body of the packet that's being signed.
  632. --@return The body of the packet, with the signature in place.
  633. local function message_sign(smb, body)
  634. smb['sequence'] = smb['sequence'] + 1
  635. if(smb['mac_key'] == nil) then
  636. stdnse.print_debug(3, "SMB: Not signing message (missing mac_key)")
  637. return body
  638. elseif(nmap.registry.args.smbsign == "disable") then
  639. stdnse.print_debug(3, "SMB: Not signing message (disabled by user)")
  640. return body
  641. end
  642. -- Convert the sequence number to a string
  643. local sequence = bin.pack("<L", smb['sequence'])
  644. -- Create a new string, with the sequence number in place
  645. local new_packet = string.sub(body, 1, 14) .. sequence .. string.sub(body, 23)
  646. -- Calculate the signature
  647. local signature = smbauth.calculate_signature(smb['mac_key'], new_packet)
  648. return string.sub(body, 1, 14) .. signature .. string.sub(body, 23)
  649. end
  650. ---Check the signature of the message. This is the opposite of <code>message_sign</code>,
  651. -- and works the same way (replaces the signature with the sequence number, calculates
  652. -- hash, checks)
  653. --@param smb The smb state object.
  654. --@param body The body of the packet that's being checked.
  655. --@return A true/false value -- true if the packet was signed properly, false if it wasn't.
  656. local function message_check_signature(smb, body)
  657. smb['sequence'] = smb['sequence'] + 1
  658. if(smb['mac_key'] == nil) then
  659. stdnse.print_debug(3, "SMB: Not signing message (missing mac_key)")
  660. return true
  661. elseif(nmap.registry.args.smbsign ~= "force" and bit.band(smb['security_mode'], 0x0A) ~= 0) then
  662. stdnse.print_debug(3, "SMB: Not signing message (server doesn't support it -- default)")
  663. return true
  664. elseif(nmap.registry.args.smbsign == "disable" or nmap.registry.args.smbsign == "ignore") then
  665. stdnse.print_debug(3, "SMB: Not signing message (disabled by user)")
  666. return true
  667. end
  668. -- Pull out the signature that they used
  669. local signature = string.sub(body, 15, 22)
  670. -- Turn the sequence into a string
  671. local sequence = bin.pack("<L", smb['sequence'])
  672. -- Create a new string, with the sequence number in place
  673. local new_packet = string.sub(body, 1, 14) .. sequence .. string.sub(body, 23)
  674. -- Calculate the proper signature
  675. local real_signature = smbauth.calculate_signature(smb['mac_key'], new_packet)
  676. -- Validate the signature
  677. return signature == real_signature
  678. end
  679. --- Prepends the NetBIOS header to the packet, which is essentially the length, encoded
  680. -- in 4 bytes of big endian, and sends it out. The length field is actually 17 or 24 bits
  681. -- wide, depending on whether or not we're using raw, but that shouldn't matter.
  682. --
  683. --@param smb The SMB object associated with the connection
  684. --@param header The header, encoded with <code>smb_get_header</code>.
  685. --@param parameters The parameters.
  686. --@param data The data.
  687. --@param overrides Overrides table.
  688. --@return (result, err) If result is false, err is the error message. Otherwise, err is
  689. -- undefined
  690. function smb_send(smb, header, parameters, data, overrides)
  691. overrides = overrides or {}
  692. local encoded_parameters = smb_encode_parameters(parameters, overrides)
  693. local encoded_data = smb_encode_data(data, overrides)
  694. local body = header .. encoded_parameters .. encoded_data
  695. local attempts = 5
  696. local status, err
  697. -- Calculate the message signature
  698. body = message_sign(smb, body)
  699. local out = bin.pack(">I<A", #body, body)
  700. repeat
  701. attempts = attempts - 1
  702. stdnse.print_debug(3, "SMB: Sending SMB packet (len: %d, attempts remaining: %d)", #out, attempts)
  703. status, err = smb['socket']:send(out)
  704. until(status or (attempts == 0))
  705. if(attempts == 0) then
  706. stdnse.print_debug(1, "SMB: Sending packet failed after 5 tries! Giving up.")
  707. end
  708. return status, err
  709. end
  710. --- Reads the next packet from the socket, and parses it into the header, parameters,
  711. -- and data.
  712. --
  713. --@param smb The SMB object associated with the connection
  714. --@param read_data [optional] This function will read the data section if and only if
  715. -- this value is true. This is a workaround for a bug in the tree connect packet,
  716. -- where the length is set incorrectly. Default: true.
  717. --@return (status, header, parameters, data) If status is true, the header,
  718. -- parameters, and data are all the raw arrays (with the lengths already
  719. -- removed). If status is false, header contains an error message and parameters/
  720. -- data are undefined.
  721. function smb_read(smb, read_data)
  722. local status
  723. local pos, netbios_data, netbios_length, length, header, parameter_length, parameters, data_length, data
  724. local attempts = 5
  725. stdnse.print_debug(3, "SMB: Receiving SMB packet")
  726. -- Receive the response -- we make sure to receive at least 4 bytes, the length of the NetBIOS length
  727. smb['socket']:set_timeout(TIMEOUT)
  728. -- perform 5 attempt to read the Netbios header
  729. local netbios
  730. repeat
  731. attempts = attempts - 1
  732. status, netbios_data = smb['socket']:receive_buf(match.numbytes(4), true);
  733. if ( not(status) and netbios_data == "EOF" ) then
  734. stdnse.print_debug(1, "SMB: ERROR: Server disconnected the connection")
  735. return false, "SMB: ERROR: Server disconnected the connection"
  736. end
  737. until(status or (attempts == 0))
  738. -- Make sure the connection is still alive
  739. if(status ~= true) then
  740. return false, "SMB: Failed to receive bytes after 5 attempts: " .. netbios_data
  741. end
  742. -- The length of the packet is 4 bytes of big endian (for our purposes).
  743. -- The NetBIOS header is 24 bits, big endian
  744. pos, netbios_length = bin.unpack(">I", netbios_data)
  745. if(netbios_length == nil) then
  746. return false, "SMB: ERROR: Server returned less data than it was supposed to (one or more fields are missing); aborting [2]"
  747. end
  748. -- Make the length 24 bits
  749. netbios_length = bit.band(netbios_length, 0x00FFFFFF)
  750. -- The total length is the netbios_length, plus 4 (for the length itself)
  751. length = netbios_length + 4
  752. local attempts = 5
  753. local smb_data
  754. repeat
  755. attempts = attempts - 1
  756. status, smb_data = smb['socket']:receive_buf(match.numbytes(netbios_length), true)
  757. until(status or (attempts == 0))
  758. -- Make sure the connection is still alive
  759. if(status ~= true) then
  760. return false, "SMB: Failed to receive bytes after 5 attempts: " .. smb_data
  761. end
  762. local result = netbios_data .. smb_data
  763. if(#result ~= length) then
  764. stdnse.print_debug(1, "SMB: ERROR: Received wrong number of bytes, there will likely be issues (recieved %d, expected %d)", #result, length)
  765. return false, string.format("SMB: ERROR: Didn't receive the expected number of bytes; recieved %d, expected %d. This will almost certainly cause some errors.", #result, length)
  766. end
  767. -- Check the message signature (ignoring the first four bytes, which are the netbios header)
  768. local good_signature = message_check_signature(smb, string.sub(result, 5))
  769. if(good_signature == false) then
  770. return false, "SMB: ERROR: Server returned invalid signature"
  771. end
  772. -- The header is 32 bytes.
  773. pos, header = bin.unpack("<A32", result, pos)
  774. if(header == nil) then
  775. return false, "SMB: ERROR: Server returned less data than it was supposed to (one or more fields are missing); aborting [3]"
  776. end
  777. -- The parameters length is a 1-byte value.
  778. pos, parameter_length = bin.unpack("<C", result, pos)
  779. if(parameter_length == nil) then
  780. return false, "SMB: ERROR: Server returned less data than it was supposed to (one or more fields are missing); aborting [4]"
  781. end
  782. -- Double the length parameter, since parameters are two-byte values.
  783. pos, parameters = bin.unpack(string.format("<A%d", parameter_length*2), result, pos)
  784. if(parameters == nil) then
  785. return false, "SMB: ERROR: Server returned less data than it was supposed to (one or more fields are missing); aborting [5]"
  786. end
  787. -- The data length is a 2-byte value.
  788. pos, data_length = bin.unpack("<S", result, pos)
  789. if(data_length == nil) then
  790. return false, "SMB: ERROR: Server returned less data than it was supposed to (one or more fields are missing); aborting [6]"
  791. end
  792. -- Read that many bytes of data.
  793. if(read_data == nil or read_data == true) then
  794. pos, data = bin.unpack(string.format("<A%d", data_length), result, pos)
  795. if(data == nil) then
  796. return false, "SMB: ERROR: Server returned less data than it was supposed to (one or more fields are missing); aborting [7]"
  797. end
  798. else
  799. data = nil
  800. end
  801. stdnse.print_debug(3, "SMB: Received %d bytes", #result)
  802. return true, header, parameters, data
  803. end
  804. --- Sends out <code>SMB_COM_NEGOTIATE</code>, which is typically the first SMB packet sent out.
  805. -- Sends the following:
  806. -- * List of known protocols
  807. --
  808. -- Receives:
  809. -- * The preferred dialect
  810. -- * The security mode
  811. -- * Max number of multiplexed connections, virtual circuits, and buffer sizes
  812. -- * The server's system time and timezone
  813. -- * The "encryption key" (aka, the server challenge)
  814. -- * The capabilities
  815. -- * The server and domain names
  816. --
  817. --@param smb The SMB object associated with the connection
  818. --@param overrides [optional] Overrides for various fields
  819. --@return (status, result) If status is false, result is an error message. Otherwise, result is
  820. -- nil and the following elements are added to <code>smb</code>:
  821. -- * 'security_mode' Whether or not to use cleartext passwords, message signatures, etc.
  822. -- * 'max_mpx' Maximum number of multiplexed connections
  823. -- * 'max_vc' Maximum number of virtual circuits
  824. -- * 'max_buffer' Maximum buffer size
  825. -- * 'max_raw_buffer' Maximum buffer size for raw connections (considered obsolete)
  826. -- * 'session_key' A value that's basically just echoed back
  827. -- * 'capabilities' The server's capabilities
  828. -- * 'time' The server's time (in UNIX-style seconds since 1970)
  829. -- * 'date' The server's date in a user-readable format
  830. -- * 'timezone' The server's timezone, in hours from UTC
  831. -- * 'timezone_str' The server's timezone, as a string
  832. -- * 'server_challenge' A random string used for challenge/response
  833. -- * 'domain' The server's primary domain or workgroup
  834. -- * 'server' The server's name
  835. function negotiate_protocol(smb, overrides)
  836. local header, parameters, data
  837. local pos
  838. local header1, header2, header3, ehader4, command, status, flags, flags2, pid_high, signature, unused, pid, mid
  839. header = smb_encode_header(smb, command_codes['SMB_COM_NEGOTIATE'], overrides)
  840. -- Make sure we have overrides
  841. overrides = overrides or {}
  842. -- Parameters are blank
  843. parameters = ""
  844. -- Data is a list of strings, terminated by a blank one.
  845. if(overrides['dialects'] == nil) then
  846. data = bin.pack("<CzCz", 2, (overrides['dialect'] or "NT LM 0.12"), 2, "")
  847. else
  848. data = ""
  849. for _, v in ipairs(overrides['dialects']) do
  850. data = data .. bin.pack("<Cz", 2, v)
  851. end
  852. data = data .. bin.pack("Cz", 2, "")
  853. end
  854. -- Send the negotiate request
  855. stdnse.print_debug(2, "SMB: Sending SMB_COM_NEGOTIATE")
  856. local result, err = smb_send(smb, header, parameters, data, overrides)
  857. if(status == false) then
  858. return false, err
  859. end
  860. -- Read the result
  861. status, header, parameters, data = smb_read(smb)
  862. if(status ~= true) then
  863. return false, header
  864. end
  865. -- Parse out the header
  866. local uid, tid, header4
  867. pos, header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, tid, pid, uid, mid = bin.unpack("<CCCCCICSSlSSSSS", header)
  868. -- Get the protocol version
  869. local protocol_version = string.char(header1, header2, header3, header4)
  870. if(protocol_version == (string.char(0xFE) .. "SMB")) then
  871. return false, "SMB: Server returned a SMBv2 packet, don't know how to handle"
  872. end
  873. -- Check if we fell off the packet (if that happened, the last parameter will be nil)
  874. if(header1 == nil or mid == nil) then
  875. return false, "SMB: ERROR: Server returned less data than it was supposed to (one or more fields are missing); aborting [8]"
  876. end
  877. -- Since this is the first response seen, check any necessary flags here
  878. if(bit.band(flags2, 0x0800) ~= 0x0800) then
  879. smb['extended_security'] = false
  880. end
  881. -- Parse the parameter section
  882. pos, smb['dialect'] = bin.unpack("<S", parameters)
  883. if(smb['dialect'] == nil) then
  884. return false, "SMB: ERROR: Server returned less data than it was supposed to (one or more fields are missing); aborting [9]"
  885. end
  886. -- Check if we ran off the packet
  887. if(smb['dialect'] == nil) then
  888. return false, "SMB: ERROR: Server returned less data than it was supposed to (one or more fields are missing); aborting [10]"
  889. end
  890. -- Check if the server didn't like our requested protocol
  891. if(smb['dialect'] ~= 0) then
  892. return false, string.format("Server negotiated an unknown protocol (#%d) -- aborting", smb['dialect'])
  893. end
  894. pos, smb['security_mode'], smb['max_mpx'], smb['max_vc'], smb['max_buffer'], smb['max_raw_buffer'], smb['session_key'], smb['capabilities'], smb['time'], smb['timezone'], smb['key_length'] = bin.unpack("<CSSIIIILsC", parameters, pos)
  895. if(smb['security_mode'] == nil or smb['capabilities'] == nil) then
  896. return false, "SMB: ERROR: Server returned less data than it was supposed to (one or more fields are missing); aborting [11]"
  897. end
  898. -- Some broken implementations of SMB don't send these variables
  899. if(smb['time'] == nil) then
  900. smb['time'] = 0
  901. end
  902. if(smb['timezone'] == nil) then
  903. smb['timezone'] = 0
  904. end
  905. if(smb['key_length'] == nil) then
  906. smb['key_length'] = 0
  907. end
  908. if(smb['byte_count'] == nil) then
  909. smb['byte_count'] = 0
  910. end
  911. -- Convert the time and timezone to more useful values
  912. smb['time'] = (smb['time'] / 10000000) - 11644473600
  913. smb['date'] = os.date("%Y-%m-%d %H:%M:%S", smb['time'])
  914. smb['timezone'] = -(smb['timezone'] / 60)
  915. if(smb['timezone'] == 0) then
  916. smb['timezone_str'] = "UTC+0"
  917. elseif(smb['timezone'] < 0) then
  918. smb['timezone_str'] = "UTC-" .. math.abs(smb['timezone'])
  919. else
  920. smb['timezone_str'] = "UTC+" .. smb['timezone']
  921. end
  922. -- Data section
  923. if(smb['extended_security'] == true) then
  924. pos, smb['server_challenge'] = bin.unpack(string.format("<A%d", smb['key_length']), data)
  925. if(smb['server_challenge'] == nil) then
  926. return false, "SMB: ERROR: Server returned less data than it was supposed to (one or more fields are missing); aborting [12]"
  927. end
  928. pos, smb['server_guid'] = bin.unpack("<A16", data, pos)
  929. if(smb['server_guid'] == nil) then
  930. return false, "SMB: ERROR: Server returned less data than it was supposed to (one or more fields are missing); aborting [12]"
  931. end
  932. -- do we have a security blob?
  933. if ( #data - pos > 0 ) then
  934. pos, smb['security_blob'] = bin.unpack("<A" .. #data - pos, data, pos )
  935. end
  936. else
  937. pos, smb['server_challenge'] = bin.unpack(string.format("<A%d", smb['key_length']), data)
  938. if(smb['server_challenge'] == nil) then
  939. return false, "SMB: ERROR: Server returned less data than it was supposed to (one or more fields are missing); aborting [12]"
  940. end
  941. -- Get the domain as a Unicode string
  942. local ch, dummy
  943. smb['domain'] = ""
  944. smb['server'] = ""
  945. pos, ch, dummy = bin.unpack("<CC", data, pos)
  946. -- if(dummy == nil) then
  947. -- return false, "SMB: ERROR: Server returned less data than it was supposed to (one or more fields are missing); aborting [13]"
  948. -- end
  949. while ch ~= nil and ch ~= 0 do
  950. smb['domain'] = smb['domain'] .. string.char(ch)
  951. pos, ch, dummy = bin.unpack("<CC", data, pos)
  952. if(ch == nil or dummy == nil) then
  953. return false, "SMB: ERROR: Server returned less data than it was supposed to (one or more fields are missing); aborting [14]"
  954. end
  955. end
  956. -- Get the server name as a Unicode string
  957. -- Note: This can be nil, Samba leaves this off
  958. pos, ch, dummy = bin.unpack("<CC", data, pos)
  959. while ch ~= nil and ch ~= 0 do
  960. smb['server'] = smb['server'] .. string.char(ch)
  961. pos, ch, dummy = bin.unpack("<CC", data, pos)
  962. end
  963. end
  964. return true
  965. end
  966. --- This is an internal function and should not be called externally. Use
  967. -- the start_session() function instead.
  968. local function start_session_basic(smb, log_errors, overrides)
  969. local i, err
  970. local status, result
  971. local header, parameters, data, domain
  972. local pos
  973. local header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, tid, pid, uid, mid
  974. local andx_command, andx_reserved, andx_offset, action
  975. local os, lanmanager
  976. local username, domain, password, password_hash, hash_type
  977. local busy_count = 0
  978. header = smb_encode_header(smb, command_codes['SMB_COM_SESSION_SETUP_ANDX'], overrides)
  979. -- Get the first account, unless they overrode it
  980. if(overrides ~= nil and overrides['username'] ~= nil) then
  981. result = true
  982. username = overrides['username']
  983. domain = overrides['domain']
  984. password = overrides['password']
  985. password_hash = overrides['password_hash']
  986. hash_type = overrides['hash_type']
  987. else
  988. result, username, domain, password, password_hash, hash_type = smbauth.get_account(smb['host'])
  989. end
  990. while result ~= false do
  991. local lanman, ntlm
  992. lanman, ntlm, smb['mac_key'] = smbauth.get_password_response(smb['ip'], username, domain, password, password_hash, hash_type, smb['server_challenge'], false)
  993. -- Parameters
  994. parameters = bin.pack("<CCSSSSISSII",
  995. 0xFF, -- ANDX -- no further commands
  996. 0x00, -- ANDX -- Reserved (0)
  997. 0x0000, -- ANDX -- next offset
  998. 0xFFFF, -- Max buffer size
  999. 0x0001, -- Max multiplexes
  1000. 0x0001, -- Virtual circuit num
  1001. smb['session_key'], -- The session key
  1002. #lanman, -- ANSI/Lanman password length
  1003. #ntlm, -- Unicode/NTLM password length
  1004. 0x00000000, -- Reserved
  1005. 0x00000050 -- Capabilities
  1006. )
  1007. -- Data is a list of strings, terminated by a blank one.
  1008. data = bin.pack("<AAzzzz",
  1009. lanman, -- ANSI/Lanman password
  1010. ntlm, -- Unicode/NTLM password
  1011. username, -- Account
  1012. domain, -- Domain
  1013. "Nmap", -- OS
  1014. "Native Lanman" -- Native LAN Manager
  1015. )
  1016. -- Send the session setup request
  1017. stdnse.print_debug(2, "SMB: Sending SMB_COM_SESSION_SETUP_ANDX")
  1018. result, err = smb_send(smb, header, parameters, data, overrides)
  1019. if(result == false) then
  1020. return false, err
  1021. end
  1022. -- Read the result
  1023. status, header, parameters, data = smb_read(smb)
  1024. if(status ~= true) then
  1025. return false, header
  1026. end
  1027. -- Check if we were allowed in
  1028. pos, header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, tid, pid, uid, mid = bin.unpack("<CCCCCICSSlSSSSS", header)
  1029. if(header1 == nil or mid == nil) then
  1030. return false, "SMB: ERROR: Server returned less data than it was supposed to (one or more fields are missing); aborting [17]"
  1031. end
  1032. -- Check if we're successful
  1033. if(status == 0) then
  1034. -- Parse the parameters
  1035. pos, andx_command, andx_reserved, andx_offset, action = bin.unpack("<CCSS", parameters)
  1036. if(andx_command == nil or action == nil) then
  1037. return false, "SMB: ERROR: Server returned less data than it was supposed to (one or more fields are missing); aborting [18]"
  1038. end
  1039. -- Parse the data
  1040. pos, os, lanmanager, domain = bin.unpack("<zzz", data)
  1041. if(os == nil or domain == nil) then
  1042. return false, "SMB: ERROR: Server returned less data than it was supposed to (one or more fields are missing); aborting [19]"
  1043. end
  1044. -- Fill in the smb object and smb string
  1045. smb['uid'] = uid
  1046. smb['is_guest'] = bit.band(action, 1)
  1047. smb['os'] = os
  1048. smb['lanmanager'] = lanmanager
  1049. -- Check if they're using an un-supported system
  1050. if(os == nil or lanmanager == nil or domain == nil) then
  1051. stdnse.print_debug(1, "SMB: WARNING: the server is using a non-standard SMB implementation; your mileage may vary (%s)", smb['ip'])
  1052. elseif(os == "Unix" or string.sub(lanmanager, 1, 5) == "Samba") then
  1053. stdnse.print_debug(1, "SMB: WARNING: the server appears to be Unix; your mileage may vary.")
  1054. end
  1055. -- Check if they were logged in as a guest
  1056. if(log_errors == nil or log_errors == true) then
  1057. if(smb['is_guest'] == 1) then
  1058. stdnse.print_debug(1, "SMB: Login as %s\\%s failed, but was given guest access (username may be wrong, or system may only allow guest)", domain, stdnse.string_or_blank(username))
  1059. else
  1060. stdnse.print_debug(2, "SMB: Login as %s\\%s succeeded", domain, stdnse.string_or_blank(username))
  1061. end
  1062. end
  1063. -- Set the initial sequence number
  1064. smb['sequence'] = 1
  1065. return true
  1066. else
  1067. -- Check if we got the error NT_STATUS_REQUEST_NOT_ACCEPTED
  1068. if(status == 0xc00000d0) then
  1069. busy_count = busy_count + 1
  1070. if(busy_count > 9) then
  1071. return false, "SMB: ERROR: Server has too many active connections; giving up."
  1072. end
  1073. local backoff = math.random() * 10
  1074. stdnse.print_debug(1, "SMB: Server has too many active connections; pausing for %s seconds.", math.floor(backoff * 100) / 100)
  1075. stdnse.sleep(backoff)
  1076. else
  1077. -- This username failed, print a warning and keep going
  1078. if(log_errors == nil or log_errors == true) then
  1079. stdnse.print_debug(1, "SMB: Login as %s\\%s failed (%s)", domain, stdnse.string_or_blank(username), get_status_name(status))
  1080. end
  1081. -- Go to the next account
  1082. if(overrides == nil or overrides['username'] == nil) then
  1083. smbauth.next_account(smb['host'])
  1084. result, username, domain, password, passwo

Large files files are truncated, but you can click here to view the full file