PageRenderTime 51ms CodeModel.GetById 19ms 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
  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, password_hash, hash_type = smbauth.get_account(smb['host'])
  1085. else
  1086. result = false
  1087. end
  1088. end
  1089. end
  1090. end
  1091. if(log_errors ~= false) then
  1092. stdnse.print_debug(1, "SMB: ERROR: %s", username)
  1093. end
  1094. if (status ~= nil) then
  1095. return false, get_status_name(status)
  1096. else
  1097. return false, username
  1098. end
  1099. end
  1100. --- This is an internal function and should not be called externally. Use
  1101. -- the start_session() function instead.
  1102. local function start_session_extended(smb, log_errors, overrides)
  1103. local i
  1104. local status, status_name, result, err
  1105. local header, parameters, data
  1106. local pos
  1107. local header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, tid, pid, uid, mid
  1108. local andx_command, andx_reserved, andx_offset, action, security_blob_length
  1109. local os, lanmanager
  1110. local username, domain, password, password_hash, hash_type
  1111. local busy_count = 0
  1112. -- Set a default status_name, in case everything fails
  1113. status_name = "An unknown error has occurred"
  1114. -- Get the first account, unless they overrode it
  1115. if(overrides ~= nil and overrides['username'] ~= nil) then
  1116. result = true
  1117. username = overrides['username']
  1118. domain = overrides['domain']
  1119. password = overrides['password']
  1120. password_hash = overrides['password_hash']
  1121. hash_type = overrides['hash_type']
  1122. else
  1123. result, username, domain, password, password_hash, hash_type = smbauth.get_account(smb['host'])
  1124. if(not(result)) then
  1125. return result, username
  1126. end
  1127. end
  1128. -- check what kind of security blob we were given in the negotiate protocol request
  1129. local sp_nego = false
  1130. if ( smb['security_blob'] and #smb['security_blob'] > 11 ) then
  1131. local pos, oid = bin.unpack(">A6", smb['security_blob'], 5)
  1132. sp_nego = ( oid == "\x2b\x06\x01\x05\x05\x02" ) -- check for SPNEGO OID 1.3.6.1.5.5.2
  1133. end
  1134. while result ~= false do
  1135. -- These are loop variables
  1136. local security_blob = nil
  1137. local security_blob_length = 0
  1138. -- This loop takes care of the multiple packets that "extended security" requires
  1139. repeat
  1140. -- Get the new security blob, passing the old security blob as a parameter. If there was no previous security blob, then nil is passed, which creates a new one
  1141. if ( not(security_blob) ) then
  1142. status, security_blob, smb['mac_key'] = smbauth.get_security_blob(security_blob, smb['ip'], username, domain, password, password_hash, hash_type, (sp_nego and 0x00088215))
  1143. if ( sp_nego ) then
  1144. local enc = asn1.ASN1Encoder:new()
  1145. local mechtype = enc:encode( { type = 'A0', value = enc:encode( { type = '30', value = enc:encode( { type = '06', value = bin.pack("H", "2b06010401823702020a") } ) } ) } )
  1146. local oid = enc:encode( { type = '06', value = bin.pack("H", "2b0601050502") } )
  1147. security_blob = enc:encode(security_blob)
  1148. security_blob = enc:encode( { type = 'A2', value = security_blob } )
  1149. security_blob = mechtype .. security_blob
  1150. security_blob = enc:encode( { type = '30', value = security_blob } )
  1151. security_blob = enc:encode( { type = 'A0', value = security_blob } )
  1152. security_blob = oid .. security_blob
  1153. security_blob = enc:encode( { type = '60', value = security_blob } )
  1154. end
  1155. else
  1156. if ( sp_nego ) then
  1157. if ( smb['domain'] or smb['server'] and ( not(domain) or #domain == 0 ) ) then
  1158. domain = smb['domain'] or smb['server']
  1159. end
  1160. hash_type = "ntlm"
  1161. end
  1162. status, security_blob, smb['mac_key'] = smbauth.get_security_blob(security_blob, smb['ip'], username, domain, password, password_hash, hash_type, (sp_nego and 0x00088215))
  1163. if ( sp_nego ) then
  1164. local enc = asn1.ASN1Encoder:new()
  1165. security_blob = enc:encode(security_blob)
  1166. security_blob = enc:encode( { type = 'A2', value = security_blob } )
  1167. security_blob = enc:encode( { type = '30', value = security_blob } )
  1168. security_blob = enc:encode( { type = 'A1', value = security_blob } )
  1169. end
  1170. end
  1171. -- There was an error processing the security blob
  1172. if(status == false) then
  1173. return false, string.format("SMB: ERROR: Security blob: %s", security_blob)
  1174. end
  1175. header = smb_encode_header(smb, command_codes['SMB_COM_SESSION_SETUP_ANDX'], overrides)
  1176. -- Data is a list of strings, terminated by a blank one.
  1177. data = bin.pack("<Azzz",
  1178. security_blob, -- Security blob
  1179. "Nmap", -- OS
  1180. "Native Lanman", -- Native LAN Manager
  1181. "" -- Primary domain
  1182. )
  1183. -- Parameters
  1184. parameters = bin.pack("<CCSSSSISII",
  1185. 0xFF, -- ANDX -- no further commands
  1186. 0x00, -- ANDX -- Reserved (0)
  1187. #data + 24 + #header + 3, -- ANDX -- next offset
  1188. 0xFFFF, -- Max buffer size
  1189. 0x0001, -- Max multiplexes
  1190. 0x0001, -- Virtual circuit num
  1191. smb['session_key'], -- The session key
  1192. #security_blob, -- Security blob length
  1193. 0x00000000, -- Reserved
  1194. 0x80000050 -- Capabilities
  1195. )
  1196. -- Send the session setup request
  1197. stdnse.print_debug(2, "SMB: Sending SMB_COM_SESSION_SETUP_ANDX")
  1198. result, err = smb_send(smb, header, parameters, data, overrides)
  1199. if(result == false) then
  1200. return false, err
  1201. end
  1202. -- Read the result
  1203. status, header, parameters, data = smb_read(smb)
  1204. if(status ~= true) then
  1205. return false, header
  1206. end
  1207. -- Check if we were allowed in
  1208. pos, header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, tid, pid, uid, mid = bin.unpack("<CCCCCICSSlSSSSS", header)
  1209. if(header1 == nil or mid == nil) then
  1210. return false, "SMB: ERROR: Server returned less data than it was supposed to (one or more fields are missing); aborting [17]"
  1211. end
  1212. smb['uid'] = uid
  1213. -- Get a human readable name
  1214. status_name = get_status_name(status)
  1215. -- Only parse the parameters if it's ok or if we're going to keep going
  1216. if(status_name == "NT_STATUS_SUCCESS" or status_name == "NT_STATUS_MORE_PROCESSING_REQUIRED") then
  1217. -- Parse the parameters
  1218. pos, andx_command, andx_reserved, andx_offset, action, security_blob_length = bin.unpack("<CCSSS", parameters)
  1219. if(andx_command == nil or security_blob_length == nil) then
  1220. return false, "SMB: ERROR: Server returned less data than it was supposed to (one or more fields are missing); aborting [18]"
  1221. end
  1222. smb['is_guest'] = bit.band(action, 1)
  1223. -- Parse the data
  1224. pos, security_blob, os, lanmanager = bin.unpack(string.format("<A%dzz", security_blob_length), data)
  1225. if ( status_name == "NT_STATUS_MORE_PROCESSING_REQUIRED" and sp_nego ) then
  1226. local start = security_blob:find("NTLMSSP")
  1227. security_blob = security_blob:sub(start)
  1228. end
  1229. if(security_blob == nil or lanmanager == nil) then
  1230. return false, "SMB: ERROR: Server returned less data than it was supposed to (one or more fields are missing); aborting [19]"
  1231. end
  1232. smb['os'] = os
  1233. smb['lanmanager'] = lanmanager
  1234. local host_info = smbauth.get_host_info_from_security_blob(security_blob)
  1235. if ( host_info ) then
  1236. smb['fqdn'] = host_info['fqdn']
  1237. smb['domain_dns'] = host_info['dns_domain_name']
  1238. smb['forest_dns'] = host_info['dns_forest_name']
  1239. smb['server'] = host_info['netbios_computer_name']
  1240. smb['domain'] = host_info['netbios_domain_name']
  1241. end
  1242. -- If it's ok, do a cleanup and return true
  1243. if(status_name == "NT_STATUS_SUCCESS") then
  1244. -- Check if they're using an un-supported system
  1245. if(os == nil or lanmanager == nil) then
  1246. stdnse.print_debug(1, "SMB: WARNING: the server is using a non-standard SMB implementation; your mileage may vary (%s)", smb['ip'])
  1247. elseif(os == "Unix" or string.sub(lanmanager, 1, 5) == "Samba") then
  1248. stdnse.print_debug(1, "SMB: WARNING: the server appears to be Unix; your mileage may vary.")
  1249. end
  1250. -- Check if they were logged in as a guest
  1251. if(log_errors == nil or log_errors == true) then
  1252. if(smb['is_guest'] == 1) then
  1253. stdnse.print_debug(1, string.format("SMB: Extended login to %s as %s\\%s failed, but was given guest access (username may be wrong, or system may only allow guest)", smb['ip'], domain, stdnse.string_or_blank(username)))
  1254. else
  1255. stdnse.print_debug(2, string.format("SMB: Extended login to %s as %s\\%s succeeded", smb['ip'], domain, stdnse.string_or_blank(username)))
  1256. end
  1257. end
  1258. -- Set the initial sequence number
  1259. smb['sequence'] = 1
  1260. return true
  1261. end -- Status is ok
  1262. end -- Should we parse the parameters/data?
  1263. until status_name ~= "NT_STATUS_MORE_PROCESSING_REQUIRED"
  1264. -- Check if we got the error NT_STATUS_REQUEST_NOT_ACCEPTED
  1265. if(status == 0xc00000d0) then
  1266. busy_count = busy_count + 1
  1267. if(busy_count > 9) then
  1268. return false, "SMB: ERROR: Server has too many active connections; giving up."
  1269. end
  1270. local backoff = math.random() * 10
  1271. stdnse.print_debug(1, "SMB: Server has too many active connections; pausing for %s seconds.", math.floor(backoff * 100) / 100)
  1272. stdnse.sleep(backoff)
  1273. else
  1274. -- Display a message to the user, and try the next account
  1275. if(log_errors == nil or log_errors == true) then
  1276. stdnse.print_debug(1, "SMB: Extended login to %s as %s\\%s failed (%s)", smb['ip'], domain, stdnse.string_or_blank(username), status_name)
  1277. end
  1278. -- Go to the next account
  1279. if(overrides == nil or overrides['username'] == nil) then
  1280. smbauth.next_account(smb['host'])
  1281. result, username, domain, password, password_hash, hash_type = smbauth.get_account(smb['host'])
  1282. if(not(result)) then
  1283. return false, username
  1284. end
  1285. else
  1286. result = false
  1287. end
  1288. end
  1289. -- Reset the user id
  1290. smb['uid'] = 0
  1291. end -- Loop over the accounts
  1292. if(log_errors == nil or log_errors == true) then
  1293. stdnse.print_debug(1, "SMB: ERROR: All logins failed, sorry it didn't work out!")
  1294. end
  1295. return false, status_name
  1296. end
  1297. --- Sends out SMB_COM_SESSION_SETUP_ANDX, which attempts to log a user in.
  1298. -- Sends the following:
  1299. -- * Negotiated parameters (multiplexed connections, virtual circuit, capabilities)
  1300. -- * Passwords (plaintext, unicode, lanman, ntlm, lmv2, ntlmv2, etc)
  1301. -- * Account name
  1302. -- * OS (I just send "Nmap")
  1303. -- * Native LAN Manager (no clue what that is, but it seems to be ignored)
  1304. --
  1305. -- Receives the following:
  1306. -- * User ID
  1307. -- * Server OS
  1308. --
  1309. --@param smb The SMB object associated with the connection
  1310. --@param overrides [optional] A table of overrides for username, domain, password, password_hash, and hash_type.
  1311. -- If any of these are given, it's used first. If they aren't, then Nmap parameters, Nmap registry entries,
  1312. -- guest, and NULL sessions are used.
  1313. --@param log_errors [optional] If set, will display login. Default: true.
  1314. --@return (status, result) If status is false, result is an error message. Otherwise, result is nil and the following
  1315. -- elements are added to the smb table:
  1316. -- * 'uid' The UserID for the session
  1317. -- * 'is_guest' If set, the username wasn't found so the user was automatically logged in as the guest account
  1318. -- * 'os' The operating system
  1319. -- * 'lanmanager' The servers's LAN Manager
  1320. function start_session(smb, overrides, log_errors)
  1321. -- Use a mutex to avoid some issues (see http://seclists.org/nmap-dev/2011/q1/464)
  1322. local smb_auth_mutex = nmap.mutex( "SMB Authentication Mutex" )
  1323. smb_auth_mutex( "lock" )
  1324. local status, result
  1325. if(smb['extended_security'] == true) then
  1326. status, result = start_session_extended(smb, log_errors, overrides)
  1327. else
  1328. status, result = start_session_basic(smb, log_errors, overrides)
  1329. end
  1330. smb_auth_mutex( "done" )
  1331. return status, result
  1332. end
  1333. --- Sends out <code>SMB_COM_SESSION_TREE_CONNECT_ANDX</code>, which attempts to connect to a share.
  1334. -- Sends the following:
  1335. -- * Password (for share-level security, which we don't support)
  1336. -- * Share name
  1337. -- * Share type (or "?????" if it's unknown, that's what we do)
  1338. --
  1339. -- Receives the following:
  1340. -- * Tree ID
  1341. --
  1342. --@param smb The SMB object associated with the connection
  1343. --@param path The path to connect (eg, <code>"\\servername\C$"</code>)
  1344. --@param overrides [optional] Overrides for various fields
  1345. --@return (status, result) If status is false, result is an error message. Otherwise, result is a
  1346. -- table with the following elements:
  1347. -- * 'tid' The TreeID for the session
  1348. function tree_connect(smb, path, overrides)
  1349. local header, parameters, data, err, result
  1350. local pos
  1351. local header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, pid, mid
  1352. local andx_command, andx_reserved, andx_offset, action
  1353. -- Make sure we have overrides
  1354. overrides = overrides or {}
  1355. header = smb_encode_header(smb, command_codes['SMB_COM_TREE_CONNECT_ANDX'], overrides)
  1356. parameters = bin.pack("<CCSSS",
  1357. 0xFF, -- ANDX no further commands
  1358. 0x00, -- ANDX reserved
  1359. 0x0000, -- ANDX offset
  1360. (overrides['tree_connect_flags'] or 0x0000), -- flags
  1361. 0x0000 -- password length (for share-level security)
  1362. )
  1363. data = bin.pack("zz",
  1364. -- Share-level password
  1365. path, -- Path
  1366. (overrides['tree_type'] or "?????") -- Type of tree ("?????" = any)
  1367. )
  1368. -- Send the tree connect request
  1369. stdnse.print_debug(2, "SMB: Sending SMB_COM_TREE_CONNECT_ANDX")
  1370. result, err = smb_send(smb, header, parameters, data, overrides)
  1371. if(result == false) then
  1372. return false, err
  1373. end
  1374. -- Read the result
  1375. status, header, parameters, data = smb_read(smb)
  1376. if(status ~= true) then
  1377. return false, header
  1378. end
  1379. -- Check if we were allowed in
  1380. local uid, tid
  1381. pos, header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, tid, pid, uid, mid = bin.unpack("<CCCCCICSSlSSSSS", header)
  1382. if(header1 == nil or mid == nil) then
  1383. return false, "SMB: ERROR: Server returned less data than it was supposed to (one or more fields are missing); aborting [20]"
  1384. end
  1385. if(status ~= 0) then
  1386. return false, get_status_name(status)
  1387. end
  1388. if(tid == 0 or tonumber(tid) == 0) then
  1389. return false, "SMB: ERROR: Server didn't establish a proper tree connection (likely an embedded system)"
  1390. end
  1391. smb['tid'] = tid
  1392. return true
  1393. end
  1394. --- Disconnects a tree session. Should be called before logging off and disconnecting.
  1395. --@param smb The SMB object associated with the connection
  1396. --@param overrides THe overrides table
  1397. --@return (status, result) If status is false, result is an error message. If status is true,
  1398. -- the disconnect was successful.
  1399. function tree_disconnect(smb, overrides)
  1400. overrides = overrides or {}
  1401. local header
  1402. local header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, pid, mid
  1403. header = smb_encode_header(smb, command_codes['SMB_COM_TREE_DISCONNECT'], overrides)
  1404. -- Send the tree disconnect request
  1405. stdnse.print_debug(2, "SMB: Sending SMB_COM_TREE_DISCONNECT")
  1406. local result, err = smb_send(smb, header, "", "", overrides)
  1407. if(result == false) then
  1408. return false, err
  1409. end
  1410. -- Read the result
  1411. local status, header, parameters, data = smb_read(smb)
  1412. if(status ~= true) then
  1413. return false, header
  1414. end
  1415. -- Check if there was an error
  1416. local uid, tid, pos
  1417. pos, header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, tid, pid, uid, mid = bin.unpack("<CCCCCICSSlSSSSS", header)
  1418. if(header1 == nil or mid == nil) then
  1419. return false, "SMB: ERROR: Server returned less data than it was supposed to (one or more fields are missing); aborting [21]"
  1420. end
  1421. if(status ~= 0) then
  1422. return false, get_status_name(status)
  1423. end
  1424. smb['tid'] = 0
  1425. return true
  1426. end
  1427. ---Logs off the current user. Strictly speaking this isn't necessary, but it's the polite thing to do.
  1428. --
  1429. --@param smb The SMB object associated with the connection
  1430. --@param overrides THe overrides table
  1431. --@return (status, result) If status is false, result is an error message. If status is true,
  1432. -- the logoff was successful.
  1433. function logoff(smb, overrides)
  1434. overrides = overrides or {}
  1435. local header, parameters, data
  1436. local header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, pid, mid
  1437. header = smb_encode_header(smb, command_codes['SMB_COM_LOGOFF_ANDX'], overrides)
  1438. -- Parameters are a blank ANDX block
  1439. parameters = bin.pack("<CCS",
  1440. 0xFF, -- ANDX no further commands
  1441. 0x00, -- ANDX reserved
  1442. 0x0000 -- ANDX offset
  1443. )
  1444. -- Send the tree disconnect request
  1445. stdnse.print_debug(2, "SMB: Sending SMB_COM_LOGOFF_ANDX")
  1446. local result, err = smb_send(smb, header, parameters, "", overrides)
  1447. if(result == false) then
  1448. return false, err
  1449. end
  1450. -- Read the result
  1451. status, header, parameters, data = smb_read(smb)
  1452. if(status ~= true) then
  1453. return false, header
  1454. end
  1455. -- Reset session variables (note: this has to come after the smb_read(), otherwise the message signatures cause a problem
  1456. smb['uid'] = 0
  1457. smb['sequence'] = -1
  1458. smb['mac_key'] = nil
  1459. -- Check if there was an error
  1460. local uid, tid, pos
  1461. pos, header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, tid, pid, uid, mid = bin.unpack("<CCCCCICSSlSSSSS", header)
  1462. if(header1 == nil or mid == nil) then
  1463. return false, "SMB: ERROR: Server returned less data than it was supposed to (one or more fields are missing); aborting [22]"
  1464. end
  1465. if(status == 0xc0000022) then
  1466. stdnse.print_debug(1, "SMB: ERROR: Access was denied in 'logoff', indicating a problem with your message signatures")
  1467. return false, "SMB: ERROR: Access was denied in 'logoff', indicating a problem with your message signatures"
  1468. end
  1469. if(status ~= 0) then
  1470. return false, get_status_name(status)
  1471. end
  1472. return true
  1473. end
  1474. --- This sends a SMB request to open or create a file.
  1475. -- Most of the parameters I pass here are used directly from a packetlog, especially the various permissions fields and flags.
  1476. -- I might make this more adjustable in the future, but this has been working for me.
  1477. --
  1478. --@param smb The SMB object associated with the connection
  1479. --@param path The path of the file or pipe to open
  1480. --@param overrides [optional] Overrides for various fields
  1481. --@return (status, result) If status is false, result is an error message. Otherwise, result is a table
  1482. -- containing a lot of different elements, the most important one being 'fid', the handle to the opened file.
  1483. function create_file(smb, path, overrides)
  1484. local header, parameters, data
  1485. local pos
  1486. local header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, pid, mid
  1487. local andx_command, andx_reserved, andx_offset
  1488. local oplock_level, fid, create_action, created, last_access, last_write, last_change, attributes, allocation_size, end_of_file, filetype, ipc_state, is_directory
  1489. local error_count = 0
  1490. repeat
  1491. local mutex = nmap.mutex(smb['host'])
  1492. mutex "lock"
  1493. -- Make sure we have overrides
  1494. overrides = overrides or {}
  1495. header = smb_encode_header(smb, command_codes['SMB_COM_NT_CREATE_ANDX'], overrides)
  1496. parameters = bin.pack("<CCSCSIIILIIIIIC",
  1497. 0xFF, -- ANDX no further commands
  1498. 0x00, -- ANDX reserved
  1499. 0x0000, -- ANDX offset
  1500. 0x00, -- Reserved
  1501. #path, -- Path length
  1502. (overrides['file_create_flags'] or 0x00000016), -- Create flags
  1503. (overrides['file_create_root_fid'] or 0x00000000), -- Root FID
  1504. (overrides['file_create_access_mask'] or 0x02000000), -- Access mask
  1505. (overrides['file_create_allocation_size'] or 0x0000000000000000), -- Allocation size
  1506. (overrides['file_create_attributes'] or 0x00000000), -- File attributes
  1507. (overrides['file_create_share_attributes'] or 0x00000007), -- Share attributes
  1508. (overrides['file_create_disposition'] or 0x00000000), -- Disposition
  1509. (overrides['file_create_options'] or 0x00000000), -- Create options
  1510. (overrides['file_create_impersonation'] or 0x00000002), -- Impersonation
  1511. (overrides['file_create_security_flags'] or 0x01) -- Security flags
  1512. )
  1513. data = bin.pack("z", path)
  1514. -- Send the create file
  1515. stdnse.print_debug(2, "SMB: Sending SMB_COM_NT_CREATE_ANDX")
  1516. local result, err = smb_send(smb, header, parameters, data, overrides)
  1517. if(result == false) then
  1518. mutex "done"
  1519. return false, err
  1520. end
  1521. -- Read the result
  1522. status, header, parameters, data = smb_read(smb, false)
  1523. mutex "done"
  1524. if(status ~= true) then
  1525. return false, header
  1526. end
  1527. -- Check if we were allowed in
  1528. local uid, tid
  1529. pos, header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, tid, pid, uid, mid = bin.unpack("<CCCCCICSSlSSSSS", header)
  1530. if(header1 == nil or mid == nil) then
  1531. return false, "SMB: ERROR: Server returned less data than it was supposed to (one or more fields are missing); aborting [23]"
  1532. end
  1533. if(status == 0xc00000ac) then
  1534. error_count = error_count + 1
  1535. if(error_count > 10) then
  1536. return false, "SMB: ERROR: Server returned NT_STATUS_PIPE_NOT_AVAILABLE too many times; giving up."
  1537. end
  1538. stdnse.print_debug(1, "WARNING: Server refused connection with NT_STATUS_PIPE_NOT_AVAILABLE; trying again")
  1539. stdnse.sleep(.2)
  1540. end
  1541. until (status ~= 0xc00000ac)
  1542. if(status ~= 0) then
  1543. return false, get_status_name(status)
  1544. end
  1545. -- Parse the parameters
  1546. pos, andx_command, andx_reserved, andx_offset, oplock_level, fid, create_action, created, last_access, last_write, last_change, attributes, allocation_size, end_of_file, filetype, ipc_state, is_directory = bin.unpack("<CCSCSILLLLILLSSC", parameters)
  1547. if(andx_command == nil or is_directory == nil) then
  1548. return false, "SMB: ERROR: Server returned less data than it was supposed to (one or more fields are missing); aborting [24]"
  1549. end
  1550. -- Fill in the smb table
  1551. smb['oplock_level'] = oplock_level
  1552. smb['fid'] = fid
  1553. smb['create_action'] = create_action
  1554. smb['created'] = created
  1555. smb['last_access'] = last_access
  1556. smb['last_write'] = last_write
  1557. smb['last_change'] = last_change
  1558. smb['attributes'] = attributes
  1559. smb['allocation_size'] = allocation_size
  1560. smb['end_of_file'] = end_of_file
  1561. smb['filetype'] = filetype
  1562. smb['ipc_state'] = ipc_state
  1563. smb['is_directory'] = is_directory
  1564. return true
  1565. end
  1566. --- This sends a SMB request to read from a file (or a pipe).
  1567. --
  1568. --@param smb The SMB object associated with the connection
  1569. --@param offset The offset to read from (ignored if it's a pipe)
  1570. --@param count The maximum number of bytes to read
  1571. --@param overrides The overrides table
  1572. --@return (status, result) If status is false, result is an error message. Otherwise, result is a table
  1573. -- containing a lot of different elements.
  1574. function read_file(smb, offset, count, overrides)
  1575. overrides = overrides or {}
  1576. local header, parameters, data
  1577. local pos
  1578. local header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, pid, mid
  1579. local andx_command, andx_reserved, andx_offset
  1580. local remaining, data_compaction_mode, reserved_1, data_length_low, data_offset, data_length_high, reserved_2, reserved_3
  1581. local response = {}
  1582. header = smb_encode_header(smb, command_codes['SMB_COM_READ_ANDX'], overrides)
  1583. parameters = bin.pack("<CCSSISSISI",
  1584. 0xFF, -- ANDX no further commands
  1585. 0x00, -- ANDX reserved
  1586. 0x0000, -- ANDX offset
  1587. smb['fid'], -- FID
  1588. offset, -- Offset
  1589. count, -- Max count low
  1590. count, -- Min count
  1591. 0xFFFFFFFF, -- Reserved
  1592. 0, -- Remaining
  1593. 0x00000000 -- High offset
  1594. )
  1595. data = ""
  1596. -- Send the create file
  1597. stdnse.print_debug(2, "SMB: Sending SMB_COM_READ_ANDX")
  1598. local result, err = smb_send(smb, header, parameters, data, overrides)
  1599. if(result == false) then
  1600. return false, err
  1601. end
  1602. -- Read the result
  1603. status, header, parameters, data = smb_read(smb)
  1604. if(status ~= true) then
  1605. return false, header
  1606. end
  1607. -- Check if we were allowed in
  1608. local uid, tid
  1609. pos, header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, tid, pid, uid, mid = bin.unpack("<CCCCCICSSlSSSSS", header)
  1610. if(header1 == nil or mid == nil) then
  1611. return false, "SMB: ERROR: Server returned less data than it was supposed to (one or more fields are missing); aborting [25]"
  1612. end
  1613. if(status ~= 0 and
  1614. (status ~= status_codes.NT_STATUS_BUFFER_OVERFLOW and (smb['filetype'] == filetype_codes.FILE_TYPE_BYTE_MODE_PIPE or
  1615. smb['filetype'] == filetype_codes.FILE_TYPE_MESSAGE_MODE_PIPE) ) ) then
  1616. return false, get_status_name(status)
  1617. end
  1618. -- Parse the parameters
  1619. pos, andx_command, andx_reserved, andx_offset, remaining, data_compaction_mode, reserved_1, data_length_low, data_offset, data_length_high, reserved_2, reserved_3 = bin.unpack("<CCSSSSSSISI", parameters)
  1620. if(andx_command == nil or reserved_3 == nil) then
  1621. return false, "SMB: ERROR: Server returned less data than it was supposed to (one or more fields are missing); aborting [26]"
  1622. end
  1623. response['remaining'] = remaining
  1624. response['data_length'] = bit.bor(data_length_low, bit.lshift(data_length_high, 16))
  1625. response['status'] = status
  1626. -- data_start is the offset of the beginning of the data section -- we use this to calculate where the read data lives
  1627. if(response['data_length'] == 0) then
  1628. response['data'] = 0
  1629. else
  1630. local data_start = #header + 1 + #parameters + 2
  1631. if(data_offset < data_start) then
  1632. return false, "SMB: Start of data isn't in data section"
  1633. end
  1634. -- Figure out the offset into the data section
  1635. data_offset = data_offset - data_start
  1636. -- Make sure we don't run off the edge of the packet
  1637. if(data_offset + response['data_length'] > #data) then
  1638. return false, "SMB: Data returned runs off the end of the packet"
  1639. end
  1640. -- Pull the data string out of the data
  1641. response['data'] = string.sub(data, data_offset + 1, data_offset + response['data_length'])
  1642. end
  1643. return true, response
  1644. end
  1645. --- This sends a SMB request to write to a file (or a pipe).
  1646. --
  1647. --@param smb The SMB object associated with the connection
  1648. --@param write_data The data to write
  1649. --@param offset The offset to write it to (ignored for pipes)
  1650. --@param overrides The overrides table
  1651. --@return (status, result) If status is false, result is an error message. Otherwise, result is a table
  1652. -- containing a lot of different elements, the most important one being 'fid', the handle to the opened file.
  1653. function write_file(smb, write_data, offset, overrides)
  1654. overrides = overrides or {}
  1655. local header, parameters, data
  1656. local pos
  1657. local header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, pid, mid
  1658. local andx_command, andx_reserved, andx_offset
  1659. local response = {}
  1660. header = smb_encode_header(smb, command_codes['SMB_COM_WRITE_ANDX'], overrides)
  1661. parameters = bin.pack("<CCSSIISSSSSI",
  1662. 0xFF, -- ANDX no further commands
  1663. 0x00, -- ANDX reserved
  1664. 0x0000, -- ANDX offset
  1665. smb['fid'], -- FID
  1666. offset, -- Offset
  1667. 0xFFFFFFFF, -- Reserved
  1668. 0x0008, -- Write mode (Message start, don't write raw, don't return remaining, don't write through
  1669. #write_data,-- Remaining
  1670. 0x0000, -- Data length high
  1671. #write_data,-- Data length low -- TODO: set this properly (to the 2-byte value)
  1672. 0x003F, -- Data offset
  1673. 0x00000000 -- Data offset high
  1674. )
  1675. data = write_data
  1676. -- Send the create file
  1677. stdnse.print_debug(2, "SMB: Sending SMB_COM_WRITE_ANDX")
  1678. local result, err = smb_send(smb, header, parameters, data, overrides)
  1679. if(result == false) then
  1680. return false, err
  1681. end
  1682. -- Read the result
  1683. status, header, parameters, data = smb_read(smb)
  1684. if(status ~= true) then
  1685. return false, header
  1686. end
  1687. local uid, tid
  1688. -- Check if we were allowed in
  1689. pos, header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, tid, pid, uid, mid = bin.unpack("<CCCCCICSSlSSSSS", header)
  1690. if(header1 == nil or mid == nil) then
  1691. return false, "SMB: ERROR: Server returned less data than it was supposed to (one or more fields are missing); aborting [27]"
  1692. end
  1693. if(status ~= 0) then
  1694. return false, get_status_name(status)
  1695. end
  1696. -- Parse the parameters
  1697. local count_reserved, count_high, remaining, count_low
  1698. pos, andx_command, andx_reserved, andx_offset, count_low, remaining, count_high, count_reserved = bin.unpack("<CCSSSSS", parameters)
  1699. if(count_reserved == nil) then
  1700. return false, "SMB: ERROR: Server returned less data than it was supposed to (one or more fields are missing); aborting [28]"
  1701. end
  1702. response['count_low'] = count_low
  1703. response['remaining'] = remaining
  1704. response['count_high'] = count_high
  1705. response['reserved'] = count_reserved
  1706. return true, response
  1707. end
  1708. --- This sends a SMB request to close a file (or a pipe).
  1709. --
  1710. --@param smb The SMB object associated with the connection
  1711. --@param overrides The overrides table
  1712. --@return (status, result) If status is false, result is an error message. Otherwise, result is undefined.
  1713. function close_file(smb, overrides)
  1714. overrides = overrides or {}
  1715. local header, parameters, data
  1716. local pos
  1717. local header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, pid, mid
  1718. local andx_command, andx_reserved, andx_offset
  1719. local response = {}
  1720. header = smb_encode_header(smb, command_codes['SMB_COM_CLOSE'], overrides)
  1721. parameters = bin.pack("<SI",
  1722. smb['fid'], -- FID
  1723. 0xFFFFFFFF -- Last write (unspecified)
  1724. )
  1725. data = ""
  1726. -- Send the close file
  1727. stdnse.print_debug(2, "SMB: Sending SMB_CLOSE")
  1728. local result, err = smb_send(smb, header, parameters, data, overrides)
  1729. if(result == false) then
  1730. return false, err
  1731. end
  1732. -- Read the result
  1733. status, header, parameters, data = smb_read(smb)
  1734. if(status ~= true) then
  1735. return false, header
  1736. end
  1737. -- Check if the close was successful
  1738. local uid, tid
  1739. pos, header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, tid, pid, uid, mid = bin.unpack("<CCCCCICSSlSSSSS", header)
  1740. if(header1 == nil or mid == nil) then
  1741. return false, "SMB: ERROR: Server returned less data than it was supposed to (one or more fields are missing); aborting [27]"
  1742. end
  1743. if(status ~= 0) then
  1744. return false, get_status_name(status)
  1745. end
  1746. -- Close response has no parameters or data
  1747. return true, response
  1748. end
  1749. --- This sends a SMB request to delete a file (or a pipe).
  1750. --
  1751. --@param smb The SMB object associated with the connection
  1752. --@param path The path of the file to delete
  1753. --@param overrides The overrides table
  1754. --@return (status, result) If status is false, result is an error message. Otherwise, result is undefined.
  1755. function delete_file(smb, path, overrides)
  1756. overrides = overrides or {}
  1757. local header, parameters, data
  1758. local pos
  1759. local header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, pid, mid
  1760. local andx_command, andx_reserved, andx_offset
  1761. header = smb_encode_header(smb, command_codes['SMB_COM_DELETE'], overrides)
  1762. parameters = bin.pack("<S",
  1763. 0x0027 -- Search attributes (0x27 = include read only, hidden, system, and archive)
  1764. )
  1765. data = bin.pack("<Cz",
  1766. 0x04, -- Ascii formatted filename
  1767. path)
  1768. -- Send the close file
  1769. stdnse.print_debug(2, "SMB: Sending SMB_CLOSE")
  1770. local result, err = smb_send(smb, header, parameters, data, overrides)
  1771. if(result == false) then
  1772. return false, err
  1773. end
  1774. -- Read the result
  1775. status, header, parameters, data = smb_read(smb)
  1776. if(status ~= true) then
  1777. return false, header
  1778. end
  1779. -- Check if the close was successful
  1780. local uid, tid
  1781. pos, header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, tid, pid, uid, mid = bin.unpack("<CCCCCICSSlSSSSS", header)
  1782. if(header1 == nil or mid == nil) then
  1783. return false, "SMB: ERROR: Server returned less data than it was supposed to (one or more fields are missing); aborting [27]"
  1784. end
  1785. if(status ~= 0) then
  1786. return false, get_status_name(status)
  1787. end
  1788. -- Close response has no parameters or data
  1789. return true
  1790. end
  1791. ---
  1792. -- Implements SMB_COM_TRANSACTION2 to support the find_files function
  1793. -- This function has not been extensively tested
  1794. --
  1795. --@param smb The SMB object associated with the connection
  1796. --@param sub_command The SMB_COM_TRANSACTION2 sub command
  1797. --@param function_parameters The parameter data to pass to the function. This is untested, since none of the
  1798. -- transactions I've done have required parameters.
  1799. --@param function_data The data to send with the packet. This is basically the next protocol layer
  1800. --@param overrides The overrides table
  1801. --@return (status, result) If status is false, result is an error message. Otherwise, result is a table
  1802. -- containing 'parameters' and 'data', representing the parameters and data returned by the server.
  1803. local function send_transaction2(smb, sub_command, function_parameters, function_data, overrides)
  1804. overrides = overrides or {}
  1805. local header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, pid, mid
  1806. local header, parameters, data
  1807. local parameter_offset = 0
  1808. local parameter_size = 0
  1809. local data_offset = 0
  1810. local data_size = 0
  1811. local total_word_count, total_data_count, reserved1, parameter_count, parameter_displacement, data_count, data_displacement, setup_count, reserved2
  1812. local response = {}
  1813. -- Header is 0x20 bytes long (not counting NetBIOS header).
  1814. header = smb_encode_header(smb, command_codes['SMB_COM_TRANSACTION2'], overrides) -- 0x32 = SMB_COM_TRANSACTION2
  1815. if(function_parameters) then
  1816. parameter_offset = 0x44
  1817. parameter_size = #function_parameters
  1818. data_offset = #function_parameters + 33 + 32
  1819. end
  1820. -- Parameters are 0x20 bytes long.
  1821. parameters = bin.pack("<SSSSCCSISSSSSCCS",
  1822. parameter_size, -- Total parameter count.
  1823. data_size, -- Total data count.
  1824. 0x000a, -- Max parameter count.
  1825. 0x3984, -- Max data count.
  1826. 0x00, -- Max setup count.
  1827. 0x00, -- Reserved.
  1828. 0x0000, -- Flags (0x0000 = 2-way transaction, don't disconnect TIDs).
  1829. 0x00001388, -- Timeout (0x00000000 = return immediately).
  1830. 0x0000, -- Reserved.
  1831. parameter_size, -- Parameter bytes.
  1832. parameter_offset, -- Parameter offset.
  1833. data_size, -- Data bytes.
  1834. data_offset, -- Data offset.
  1835. 0x01, -- Setup Count
  1836. 0x00, -- Reserved
  1837. sub_command -- Sub command
  1838. )
  1839. local data = "\0\0\0" .. (function_parameters or '')
  1840. data = data .. (function_data or '')
  1841. -- Send the transaction request
  1842. stdnse.print_debug(2, "SMB: Sending SMB_COM_TRANSACTION2")
  1843. local result, err = smb_send(smb, header, parameters, data, overrides)
  1844. if(result == false) then
  1845. return false, err
  1846. end
  1847. return true
  1848. end
  1849. local function receive_transaction2(smb)
  1850. -- Read the result
  1851. local status, header, parameters, data = smb_read(smb)
  1852. if(status ~= true) then
  1853. return false, header
  1854. end
  1855. -- Check if it worked
  1856. local pos, header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, tid, pid, uid, mid = bin.unpack("<CCCCCICSSlSSSSS", header)
  1857. if(header1 == nil or mid == nil) then
  1858. return false, "SMB: ERROR: Server returned less data than it was supposed to (one or more fields are missing); aborting [29]"
  1859. end
  1860. if(status ~= 0) then
  1861. if(status_names[status] == nil) then
  1862. return false, string.format("Unknown SMB error: 0x%08x\n", status)
  1863. else
  1864. return false, status_names[status]
  1865. end
  1866. end
  1867. -- Parse the parameters
  1868. local pos, total_word_count, total_data_count, reserved1, parameter_count, parameter_offset, parameter_displacement, data_count, data_offset, data_displacement, setup_count, reserved2 = bin.unpack("<SSSSSSSSSCC", parameters)
  1869. if(total_word_count == nil or reserved2 == nil) then
  1870. return false, "SMB: ERROR: Server returned less data than it was supposed to (one or more fields are missing); aborting [30]"
  1871. end
  1872. -- Convert the parameter/data offsets into something more useful (the offset into the data section)
  1873. -- - 0x20 for the header, - 0x01 for the length.
  1874. parameter_offset = parameter_offset - 0x20 - 0x01 - #parameters - 0x02;
  1875. -- - 0x20 for the header, - 0x01 for parameter length, the parameter length, and - 0x02 for the data length.
  1876. data_offset = data_offset - 0x20 - 0x01 - #parameters - 0x02;
  1877. -- I'm not sure I entirely understand why the '+1' is here, but I think it has to do with the string starting at '1' and not '0'.
  1878. local function_parameters = string.sub(data, parameter_offset + 1, parameter_offset + parameter_count)
  1879. local function_data = string.sub(data, data_offset + 1, data_offset + data_count)
  1880. local response = {}
  1881. response['parameters'] = function_parameters
  1882. response['data'] = function_data
  1883. return true, response
  1884. end
  1885. ---This is the core of making MSRPC calls. It sends out a MSRPC packet with the given parameters and data.
  1886. -- Don't confuse these parameters and data with SMB's concepts of parameters and data -- they are completely
  1887. -- different. In fact, these parameters and data are both sent in the SMB packet's 'data' section.
  1888. --
  1889. -- It is probably best to think of this as another protocol layer. This function will wrap SMB stuff around a
  1890. -- MSRPC call, make the call, then unwrap the SMB stuff from it before returning.
  1891. --
  1892. --@param smb The SMB object associated with the connection
  1893. --@param function_parameters The parameter data to pass to the function. This is untested, since none of the
  1894. -- transactions I've done have required parameters.
  1895. --@param function_data The data to send with the packet. This is basically the next protocol layer
  1896. --@param pipe [optional] The pipe to transact on. Default: "\PIPE\".
  1897. --@param no_setup [optional] If set, the 'setup' is set to 0 and some parameters are left off. This occurs while
  1898. -- using the LANMAN Remote API. Default: false.
  1899. --@param overrides The overrides table
  1900. --@return (status, result) If status is false, result is an error message. Otherwise, result is a table
  1901. -- containing 'parameters' and 'data', representing the parameters and data returned by the server.
  1902. function send_transaction_named_pipe(smb, function_parameters, function_data, pipe, no_setup, overrides)
  1903. overrides = overrides or {}
  1904. local header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, pid, mid
  1905. local header, parameters, data
  1906. local parameter_offset = 0
  1907. local parameter_size = 0
  1908. local data_offset = 0
  1909. local data_size = 0
  1910. local total_word_count, total_data_count, reserved1, parameter_count, parameter_displacement, data_count, data_displacement, setup_count, reserved2
  1911. local response = {}
  1912. if(pipe == nil) then
  1913. pipe = "\\PIPE\\"
  1914. end
  1915. -- Header is 0x20 bytes long (not counting NetBIOS header).
  1916. header = smb_encode_header(smb, command_codes['SMB_COM_TRANSACTION'], overrides) -- 0x25 = SMB_COM_TRANSACTION
  1917. -- 0x20 for SMB header, 0x01 for parameters header, 0x20 for parameters length, 0x02 for data header, 0x07 for "\PIPE\"
  1918. if(function_parameters) then
  1919. parameter_offset = 0x20 + 0x01 + 0x20 + 0x02 + (#pipe + 1)
  1920. parameter_size = #function_parameters
  1921. end
  1922. if(function_data) then
  1923. data_offset = 0x20 + 0x01 + 0x20 + 0x02 + (#pipe + 1) + parameter_size
  1924. data_size = #function_data
  1925. end
  1926. -- Parameters are 0x20 bytes long.
  1927. parameters = bin.pack("<SSSSCCSISSSSS",
  1928. parameter_size, -- Total parameter count.
  1929. data_size, -- Total data count.
  1930. 0x0008, -- Max parameter count.
  1931. 0x3984, -- Max data count.
  1932. 0x00, -- Max setup count.
  1933. 0x00, -- Reserved.
  1934. 0x0000, -- Flags (0x0000 = 2-way transaction, don't disconnect TIDs).
  1935. 0x00001388, -- Timeout (0x00000000 = return immediately).
  1936. 0x0000, -- Reserved.
  1937. parameter_size, -- Parameter bytes.
  1938. parameter_offset, -- Parameter offset.
  1939. data_size, -- Data bytes.
  1940. data_offset -- Data offset.
  1941. )
  1942. if(no_setup) then
  1943. parameters = parameters .. bin.pack("<CC",
  1944. 0x00, -- Number of 'setup' words (none)
  1945. 0x00 -- Reserved.
  1946. )
  1947. else
  1948. parameters = parameters .. bin.pack("<CCSS",
  1949. 0x02, -- Number of 'setup' words
  1950. 0x00, -- Reserved.
  1951. 0x0026, -- Function to call.
  1952. smb['fid'] -- Handle to open file
  1953. )
  1954. end
  1955. data = bin.pack("<z", pipe)
  1956. data = data .. bin.pack("<I", 0) -- Padding
  1957. data = data .. (function_parameters or '')
  1958. data = data .. (function_data or '')
  1959. -- Send the transaction request
  1960. stdnse.print_debug(2, "SMB: Sending SMB_COM_TRANSACTION")
  1961. local result, err = smb_send(smb, header, parameters, data, overrides)
  1962. if(result == false) then
  1963. return false, err
  1964. end
  1965. -- Read the result
  1966. status, header, parameters, data = smb_read(smb)
  1967. if(status ~= true) then
  1968. return false, header
  1969. end
  1970. -- Check if it worked
  1971. local uid, tid, pos
  1972. pos, header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, tid, pid, uid, mid = bin.unpack("<CCCCCICSSlSSSSS", header)
  1973. if(header1 == nil or mid == nil) then
  1974. return false, "SMB: ERROR: Server returned less data than it was supposed to (one or more fields are missing); aborting [29]"
  1975. end
  1976. if(status ~= 0) then
  1977. if(status_names[status] == nil) then
  1978. return false, string.format("Unknown SMB error: 0x%08x\n", status)
  1979. else
  1980. return false, status_names[status]
  1981. end
  1982. end
  1983. -- Parse the parameters
  1984. pos, total_word_count, total_data_count, reserved1, parameter_count, parameter_offset, parameter_displacement, data_count, data_offset, data_displacement, setup_count, reserved2 = bin.unpack("<SSSSSSSSSCC", parameters)
  1985. if(total_word_count == nil or reserved2 == nil) then
  1986. return false, "SMB: ERROR: Server returned less data than it was supposed to (one or more fields are missing); aborting [30]"
  1987. end
  1988. -- Convert the parameter/data offsets into something more useful (the offset into the data section)
  1989. -- - 0x20 for the header, - 0x01 for the length.
  1990. parameter_offset = parameter_offset - 0x20 - 0x01 - #parameters - 0x02;
  1991. -- - 0x20 for the header, - 0x01 for parameter length, the parameter length, and - 0x02 for the data length.
  1992. data_offset = data_offset - 0x20 - 0x01 - #parameters - 0x02;
  1993. -- I'm not sure I entirely understand why the '+1' is here, but I think it has to do with the string starting at '1' and not '0'.
  1994. function_parameters = string.sub(data, parameter_offset + 1, parameter_offset + parameter_count)
  1995. function_data = string.sub(data, data_offset + 1, data_offset + data_count)
  1996. response['parameters'] = function_parameters
  1997. response['data'] = function_data
  1998. return true, response
  1999. end
  2000. function send_transaction_waitnamedpipe(smb, priority, pipe, overrides)
  2001. overrides = overrides or {}
  2002. local header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, pid, mid
  2003. local header, parameters, data
  2004. local parameter_offset, data_offset
  2005. local total_word_count, total_data_count, reserved1, parameter_count, parameter_offset, parameter_displacement, data_count, data_offset, data_displacement, setup_count, reserved2
  2006. local response = {}
  2007. local padding = ""
  2008. -- Header is 0x20 bytes long (not counting NetBIOS header).
  2009. header = smb_encode_header(smb, command_codes['SMB_COM_TRANSACTION'], overrides) -- 0x25 = SMB_COM_TRANSACTION
  2010. -- Parameters are 0x20 bytes long.
  2011. parameters = bin.pack("<SSSSCCSISSSSSCCSS",
  2012. 0, -- Total parameter count.
  2013. 0, -- Total data count.
  2014. 0x000, -- Max parameter count.
  2015. 0x400, -- Max data count.
  2016. 0x00, -- Max setup count.
  2017. 0x00, -- Reserved.
  2018. 0x0000, -- Flags (0x0000 = 2-way transaction, don't disconnect TIDs).
  2019. 30, -- Timeout (0x00000000 = return immediately).
  2020. 0x0000, -- Reserved.
  2021. 0, -- Parameter bytes.
  2022. 0, -- Parameter offset.
  2023. 0, -- Data bytes.
  2024. 0, -- Data offset.
  2025. 0x02, -- Number of 'setup' words (only ever seen '2').
  2026. 0x00, -- Reserved.
  2027. 0x0053, -- Function to call.
  2028. priority -- Handle to open file
  2029. )
  2030. while(((#pipe + 1 + #padding) % 4) ~= 0) do
  2031. padding = padding .. string.char(0)
  2032. end
  2033. data = bin.pack("<zA", pipe, padding);
  2034. -- Send the transaction request
  2035. stdnse.print_debug(2, "SMB: Sending SMB_COM_TRANSACTION (WaitNamedPipe)")
  2036. local result, err = smb_send(smb, header, parameters, data, overrides)
  2037. if(result == false) then
  2038. return false, err
  2039. end
  2040. -- Read the result
  2041. status, header, parameters, data = smb_read(smb)
  2042. if(status ~= true) then
  2043. return false, header
  2044. end
  2045. -- Check if it worked
  2046. local uid, tid, pos
  2047. pos, header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, tid, pid, uid, mid = bin.unpack("<CCCCCICSSlSSSSS", header)
  2048. if(header1 == nil or mid == nil) then
  2049. return false, "SMB: ERROR: Server returned less data than it was supposed to (one or more fields are missing); aborting [31]"
  2050. end
  2051. if(status ~= 0) then
  2052. if(status_names[status] == nil) then
  2053. return false, string.format("Unknown SMB error: 0x%08x\n", status)
  2054. else
  2055. return false, status_names[status]
  2056. end
  2057. end
  2058. -- Parse the parameters
  2059. pos, total_word_count, total_data_count, reserved1, parameter_count, parameter_offset, parameter_displacement, data_count, data_offset, data_displacement, setup_count, reserved2 = bin.unpack("<SSSSSSSSSCC", parameters)
  2060. if(total_word_count == nil or reserved2 == nil) then
  2061. return false, "SMB: ERROR: Server returned less data than it was supposed to (one or more fields are missing); aborting [32]"
  2062. end
  2063. return true, response
  2064. end
  2065. ---Upload a file from the local machine to the remote machine, on the given share.
  2066. --
  2067. --@param host The host object
  2068. --@param localfile The file on the local machine, relative to the nmap path
  2069. --@param share The share to upload it to (eg, C$).
  2070. --@param remotefile The remote file on the machine. It is relative to the share's root.
  2071. --@param overrides A table of override values that's passed to the smb functions.
  2072. --@param encoded Set to 'true' if the file is encoded (xor'ed with 0xFF), It will be decoded before upload. Default: false
  2073. --@return (status, err) If status is false, err is an error message. Otherwise, err is undefined.
  2074. function file_upload(host, localfile, share, remotefile, overrides, encoded)
  2075. local status, err, smbstate
  2076. local chunk = 1024
  2077. -- Attempt to open a handle to the file without adding a path to it
  2078. local handle = io.open(localfile, "r")
  2079. -- If the open failed, try to search for the file
  2080. if(not(handle)) then
  2081. stdnse.print_debug(1, "Couldn't open %s directly, searching Nmap's paths...", localfile)
  2082. local filename = nmap.fetchfile(localfile)
  2083. -- Check if it was found
  2084. if(filename == nil) then
  2085. return false, string.format("Couldn't find the file to upload (%s)", localfile)
  2086. end
  2087. handle = io.open(filename, "r")
  2088. end
  2089. -- Create the SMB session
  2090. status, smbstate = start_ex(host, true, true, share, remotefile, nil, overrides)
  2091. if(status == false) then
  2092. return false, smbstate
  2093. end
  2094. local i = 0
  2095. local data = handle:read(chunk)
  2096. while(data ~= nil and #data > 0) do
  2097. if(encoded) then
  2098. local new_data = ""
  2099. for j = 1, #data, 1 do
  2100. new_data = new_data .. string.char(bit.bxor(0xFF, string.byte(data, j)))
  2101. end
  2102. data = new_data
  2103. end
  2104. status, err = write_file(smbstate, data, i)
  2105. if(status == false) then
  2106. stop(smbstate)
  2107. return false, err
  2108. end
  2109. data = handle:read(chunk)
  2110. i = i + chunk
  2111. end
  2112. handle:close()
  2113. status, err = close_file(smbstate)
  2114. if(status == false) then
  2115. stop(smbstate)
  2116. return false, err
  2117. end
  2118. -- Stop the session
  2119. stop(smbstate)
  2120. return true
  2121. end
  2122. ---Write given data to the remote machine on the given share. This is similar to <code>file_upload</code>, except the
  2123. -- data is given as a string, not a file.
  2124. --
  2125. --@param host The host object
  2126. --@param share The share to upload it to (eg, C$).
  2127. --@param remotefile The remote file on the machine. It is relative to the share's root.
  2128. --@param use_anonymous [optional] If set to 'true', test is done by the anonymous user rather than the current user.
  2129. --@return (status, err) If status is false, err is an error message. Otherwise, err is undefined.
  2130. function file_write(host, data, share, remotefile, use_anonymous)
  2131. local status, err, smbstate
  2132. local chunk = 1024
  2133. local overrides = nil
  2134. -- If anonymous is being used, create some overrides
  2135. if(use_anonymous) then
  2136. overrides = get_overrides_anonymous()
  2137. end
  2138. -- Create the SMB sessioan
  2139. status, smbstate = start_ex(host, true, true, share, remotefile, nil, overrides)
  2140. if(status == false) then
  2141. return false, smbstate
  2142. end
  2143. local i = 1
  2144. while(i <= #data) do
  2145. local chunkdata = string.sub(data, i, i + chunk - 1)
  2146. status, err = write_file(smbstate, chunkdata, i - 1)
  2147. if(status == false) then
  2148. stop(smbstate)
  2149. return false, err
  2150. end
  2151. i = i + chunk
  2152. end
  2153. status, err = close_file(smbstate)
  2154. if(status == false) then
  2155. stop(smbstate)
  2156. return false, err
  2157. end
  2158. -- Stop the session
  2159. stop(smbstate)
  2160. return true
  2161. end
  2162. ---Write given data to the remote machine on the given share. This is similar to <code>file_upload</code>, except the
  2163. -- data is given as a string, not a file.
  2164. --
  2165. --@param host The host object
  2166. --@param share The share to read it from (eg, C$).
  2167. --@param remotefile The remote file on the machine. It is relative to the share's root.
  2168. --@param use_anonymous [optional] If set to 'true', test is done by the anonymous user rather than the current user.
  2169. --@param overrides [optional] Override various fields in the SMB packets.
  2170. --@return (status, err) If status is false, err is an error message. Otherwise, err is undefined.
  2171. function file_read(host, share, remotefile, use_anonymous, overrides)
  2172. local status, err, smbstate
  2173. local result
  2174. local chunk = 1024
  2175. local read = ""
  2176. -- Make sure we got overrides
  2177. overrides = overrides or {}
  2178. -- If anonymous is being used, create some overrides
  2179. if(use_anonymous) then
  2180. overrides = get_overrides_anonymous(overrides)
  2181. end
  2182. -- Create the SMB sessioan
  2183. status, smbstate = start_ex(host, true, true, share, remotefile, nil, overrides)
  2184. if(status == false) then
  2185. return false, smbstate
  2186. end
  2187. local i = 1
  2188. while true do
  2189. status, result = read_file(smbstate, i - 1, chunk)
  2190. if(status == false) then
  2191. stop(smbstate)
  2192. return false, result
  2193. end
  2194. if(result['data_length'] == 0) then
  2195. break
  2196. end
  2197. read = read .. result['data']
  2198. i = i + chunk
  2199. end
  2200. status, err = close_file(smbstate)
  2201. if(status == false) then
  2202. stop(smbstate)
  2203. return false, err
  2204. end
  2205. -- Stop the session
  2206. stop(smbstate)
  2207. return true, read
  2208. end
  2209. ---Check how many files, in a given list, exist on the given share.
  2210. --
  2211. --@param host The host object
  2212. --@param share The share to read it from (eg, C$).
  2213. --@param files A list of files to look for; it is relative to the share's root.
  2214. --@param overrides [optional] Override various fields in the SMB packets.
  2215. --@return status: A true/false value indicating success
  2216. --@return count: The number of files that existed, or an error message if status is 'false'
  2217. --@return files: A list of the files that existed.
  2218. function files_exist(host, share, files, overrides)
  2219. local status, smbstate, result, err
  2220. -- Make sure we got overrides
  2221. overrides = overrides or {}
  2222. -- We don't wan to be creating the files
  2223. overrides['file_create_disposition'] = 1
  2224. -- Create the SMB sessioan
  2225. status, smbstate = start_ex(host, true, true, share, nil, nil, overrides)
  2226. if(status == false) then
  2227. return false, smbstate
  2228. end
  2229. local exist = 0
  2230. local list = {}
  2231. for _, file in ipairs(files) do
  2232. -- Try and open the file
  2233. status, result = create_file(smbstate, file, overrides)
  2234. -- If there was an error other than 'file already exists', return an error
  2235. if(not(status) and result ~= 'NT_STATUS_OBJECT_NAME_NOT_FOUND') then
  2236. return false, result
  2237. end
  2238. -- If the file existed, count it and close it
  2239. if(status) then
  2240. exist = exist + 1
  2241. table.insert(list, file)
  2242. status, err = close_file(smbstate)
  2243. if(status == false) then
  2244. stop(smbstate)
  2245. return false, err
  2246. end
  2247. end
  2248. end
  2249. -- Stop the session
  2250. stop(smbstate)
  2251. return true, exist, list
  2252. end
  2253. ---Delete a file from the remote machine
  2254. --
  2255. --@param host The host object
  2256. --@param share The share to upload it to (eg, C$).
  2257. --@param remotefile The remote file on the machine. It is relative to the share's root. It can be a string, or an array.
  2258. --@return (status, err) If status is false, err is an error message. Otherwise, err is undefined.
  2259. function file_delete(host, share, remotefile)
  2260. local status, smbstate, err
  2261. -- Create the SMB session
  2262. status, smbstate = start_ex(host, true, true, share)
  2263. if(status == false) then
  2264. return false, smbstate
  2265. end
  2266. -- Make sure the remotefile is always a table, to save on duplicate code
  2267. if(type(remotefile) ~= "table") then
  2268. remotefile = {remotefile}
  2269. end
  2270. for _, file in ipairs(remotefile) do
  2271. status, err = delete_file(smbstate, file)
  2272. if(status == false) then
  2273. stdnse.print_debug(1, "SMB: Couldn't delete %s\\%s: %s", share, file, err)
  2274. if(err ~= 'NT_STATUS_OBJECT_NAME_NOT_FOUND') then
  2275. stop(smbstate)
  2276. return false, err
  2277. end
  2278. end
  2279. end
  2280. -- Stop the session
  2281. stop(smbstate)
  2282. return true
  2283. end
  2284. ---
  2285. -- List files based on a pattern withing a given share and directory
  2286. --
  2287. -- @param smbstate the SMB object associated with the connection
  2288. -- @param fname filename to search for, relative to share path
  2289. -- @param options table containing none or more of the following
  2290. -- <code>srch_attrs</code> table containing one or more of the following boolean attributes:
  2291. -- <code>ro</code> - find read only files
  2292. -- <code>hidden</code> - find hidden files
  2293. -- <code>system</code> - find system files
  2294. -- <code>volid</code> - include volume ids in result
  2295. -- <code>dir</code> - find directories
  2296. -- <code>archive</code> - find archived files
  2297. -- @return iterator function retreiving the next result
  2298. function find_files(smbstate, fname, options)
  2299. local TRANS2_FIND_FIRST2, TRANS2_FIND_NEXT2 = 1, 2
  2300. options = options or {}
  2301. if (not(options.srch_attrs)) then
  2302. options.srch_attrs = { ro = true, hidden = true, system = true, dir = true}
  2303. end
  2304. local nattrs = ( options.srch_attrs.ro and 1 or 0 ) + ( options.srch_attrs.hidden and 2 or 0 ) +
  2305. ( options.srch_attrs.hidden and 2 or 0 ) + ( options.srch_attrs.system and 4 or 0 ) +
  2306. ( options.srch_attrs.volid and 8 or 0 ) + ( options.srch_attrs.dir and 16 or 0 ) +
  2307. ( options.srch_attrs.archive and 32 or 0 )
  2308. if ( not(fname) ) then
  2309. fname = '\\*'
  2310. elseif( fname:sub(1,1) ~= '\\' ) then
  2311. fname = '\\' .. fname
  2312. end
  2313. fname = fname .. '\0'
  2314. -- Sends the request and takes care of short/fragmented responses
  2315. local function send_and_receive_find_request(smbstate, trans_type, function_parameters)
  2316. local status, err = send_transaction2(smbstate, trans_type, function_parameters, "")
  2317. if ( not(status) ) then
  2318. return false, "Failed to send data to server: send_transaction2"
  2319. end
  2320. local status, response = receive_transaction2(smbstate)
  2321. if ( not(status) ) then
  2322. return false, "Failed to receive data from server: receive_transaction2"
  2323. end
  2324. local pos = ( TRANS2_FIND_FIRST2 == trans_type and 9 or 7 )
  2325. local last_name_offset = select(2, bin.unpack("<S", response.parameters, pos))
  2326. if ( not(last_name_offset) ) then
  2327. return false, "Could not determine last_name_offset"
  2328. end
  2329. -- check if we need more packets to reassemble this transaction
  2330. local NE_UP_TO_FNAME_SIZE = 94
  2331. while ( last_name_offset > ( #response.data - NE_UP_TO_FNAME_SIZE ) ) do
  2332. local status, tmp = receive_transaction2(smbstate)
  2333. if ( not(status) ) then
  2334. return false, "Failed to receive data from receive_transaction2"
  2335. end
  2336. response.data = response.data .. tmp.data
  2337. end
  2338. return true, response
  2339. end
  2340. local srch_count = 173 -- picked up by wireshark
  2341. local flags = 6 -- Return RESUME keys, close search if END OF SEARCH is reached
  2342. local loi = 260 -- Level of interest, return SMB_FIND_FILE_BOTH_DIRECTORY_INFO
  2343. local storage_type = 0 -- despite the documentation of having to be either 0x01 or 0x40, wireshark reports 0
  2344. local function_parameters = bin.pack("<SSSSIA", nattrs, srch_count, flags, loi, storage_type, fname)
  2345. -- SMB header: 32
  2346. -- trans2 header: 36
  2347. -- FIND_FIRST2 parameters: #function_parameters
  2348. local pad = ( 32 + 36 + #function_parameters ) % 4
  2349. if ( pad > 0 ) then
  2350. for i=1, ( 4-pad ) do
  2351. function_parameters = function_parameters .. "\0"
  2352. end
  2353. end
  2354. local function next_item()
  2355. local status, response = send_and_receive_find_request(smbstate, TRANS2_FIND_FIRST2, function_parameters)
  2356. if ( not(status) ) then
  2357. return
  2358. end
  2359. local srch_id = select(2, bin.unpack("<S", response.parameters))
  2360. local stop_loop = ( select(2, bin.unpack("<S", response.parameters, 5)) ~= 0 )
  2361. local first = true
  2362. local last_name
  2363. repeat
  2364. local pos = 1
  2365. if ( not(first) ) then
  2366. local function_parameters = bin.pack("<SSSISA", srch_id, srch_count, loi, 0, flags, last_name .. "\0")
  2367. status, response = send_and_receive_find_request(smbstate, TRANS2_FIND_NEXT2, function_parameters)
  2368. if ( not(status) ) then
  2369. return
  2370. end
  2371. -- check whether END-OF-SEARCH was set
  2372. stop_loop = ( select(2, bin.unpack(">S", response.parameters, 3)) ~= 0 )
  2373. end
  2374. -- parse response, based on LOI == 260
  2375. repeat
  2376. local fe, last_pos, ne, f_len, ea_len, sf_len, _ = {}, pos
  2377. pos, ne, fe.fi, fe.created, fe.accessed, fe.write, fe.change,
  2378. fe.eof, fe.alloc_size, fe.attrs, f_len, ea_len, sf_len, _ = bin.unpack("<IILLLLLLIIICC", response.data, pos)
  2379. pos, fe.s_fname = bin.unpack("A24", response.data, pos)
  2380. local time = fe.created
  2381. time = (time / 10000000) - 11644473600
  2382. fe.created = os.date("%Y-%m-%d %H:%M:%S", time)
  2383. -- TODO: cleanup fe.s_fname
  2384. pos, fe.fname = bin.unpack("A" .. f_len, response.data, pos)
  2385. pos = last_pos + ne
  2386. -- removing trailing zero bytes from file name
  2387. fe.fname = fe.fname:sub(1, -2)
  2388. last_name = fe.fname
  2389. coroutine.yield(fe)
  2390. until ( ne == 0 )
  2391. first = false
  2392. until(stop_loop)
  2393. return
  2394. end
  2395. return coroutine.wrap(next_item)
  2396. end
  2397. ---Determine whether or not the anonymous user has write access on the share. This is done by creating then
  2398. -- deleting a file.
  2399. --
  2400. --@param host The host object
  2401. --@param share The share to test
  2402. --@return (status, result) If status is false, result is an error message. The error message 'NT_STATUS_OBJECT_NAME_NOT_FOUND'
  2403. -- should be handled gracefully; it indicates that the share isn't a fileshare. Otherwise, result is a boolean value:
  2404. -- true if the file was successfully written, false if it was not.
  2405. function share_anonymous_can_write(host, share)
  2406. local filename, status, err
  2407. -- First, choose a filename. This should be random.
  2408. filename = "nmap-test-file"
  2409. -- Next, attempt to write to that file
  2410. status, err = file_write(host, string.rep("ABCDEFGHIJKLMNOPQRSTUVWXYZ", 10), share, filename, true)
  2411. if(status == false) then
  2412. if(err == "NT_STATUS_OBJECT_NAME_NOT_FOUND") then
  2413. return false, err
  2414. end
  2415. if(err == "NT_STATUS_ACCESS_DENIED" or err == "NT_STATUS_INVALID_PARAMETER") then
  2416. return true, false
  2417. end
  2418. return false, "Error writing test file to disk as anonymous: " .. err
  2419. end
  2420. -- Now the important part: delete it
  2421. status, err = file_delete(host, share, filename)
  2422. if(status == false) then
  2423. return false, "Error deleting test file as anonymous: " .. err
  2424. end
  2425. return true, true
  2426. end
  2427. ---Determine whether or not the current user has read or read/write access on the share. This is done by creating then
  2428. -- deleting a file.
  2429. --
  2430. --@param host The host object
  2431. --@param share The share to test
  2432. --@return (status, result) If status is false, result is an error message. The error message 'NT_STATUS_OBJECT_NAME_NOT_FOUND'
  2433. -- should be handled gracefully; it indicates that the share isn't a fileshare. Otherwise, result is a boolean value:
  2434. -- true if the file was successfully written, false if it was not.
  2435. function share_user_can_write(host, share)
  2436. local filename, status, err
  2437. -- First, choose a filename. This should be random.
  2438. filename = "nmap-test-file"
  2439. -- Next, attempt to write to that file
  2440. status, err = file_write(host, string.rep("ABCDEFGHIJKLMNOPQRSTUVWXYZ", 10), share, filename)
  2441. if(status == false) then
  2442. if(err == "NT_STATUS_OBJECT_NAME_NOT_FOUND") then
  2443. return false, err
  2444. end
  2445. if(err == "NT_STATUS_ACCESS_DENIED" or err == "NT_STATUS_INVALID_PARAMETER") then
  2446. return true, false
  2447. end
  2448. return false, "Error writing test file to disk as user: " .. err
  2449. end
  2450. -- Now the important part: delete it
  2451. status, err = file_delete(host, share, filename)
  2452. if(status == false) then
  2453. return false, "Error deleting test file as user: " .. err
  2454. end
  2455. return true, true
  2456. end
  2457. ---Check whether or not a share is accessible by the anonymous user. Assumes that <code>share_host_returns_proper_error</code>
  2458. -- has been called and returns <code>true</code>.
  2459. --
  2460. --@param host The host object
  2461. --@param share The share to test
  2462. --@return (status, result) If status is false, result is an error message. Otherwise, result is a boolean value:
  2463. -- true if anonymous access is permitted, false otherwise.
  2464. function share_anonymous_can_read(host, share)
  2465. local status, smbstate, err
  2466. local overrides = get_overrides_anonymous()
  2467. -- Begin the SMB session
  2468. status, smbstate = start(host)
  2469. if(status == false) then
  2470. return false, smbstate
  2471. end
  2472. -- Negotiate the protocol
  2473. status, err = negotiate_protocol(smbstate, overrides)
  2474. if(status == false) then
  2475. stop(smbstate)
  2476. return false, err
  2477. end
  2478. -- Start up a null session
  2479. status, err = start_session(smbstate, overrides)
  2480. if(status == false) then
  2481. stop(smbstate)
  2482. return false, err
  2483. end
  2484. -- Attempt a connection to the share
  2485. status, err = tree_connect(smbstate, share, overrides)
  2486. if(status == false) then
  2487. -- Stop the session
  2488. stop(smbstate)
  2489. -- ACCESS_DENIED is the expected error: it tells us that the connection failed
  2490. if(err == 0xc0000022 or err == 'NT_STATUS_ACCESS_DENIED') then
  2491. return true, false
  2492. else
  2493. return false, err
  2494. end
  2495. end
  2496. stop(smbstate)
  2497. return true, true
  2498. end
  2499. ---Check whether or not a share is accessible by the current user. Assumes that <code>share_host_returns_proper_error</code>
  2500. -- has been called and returns <code>true</code>.
  2501. --
  2502. --@param host The host object
  2503. --@param share The share to test
  2504. --@return (status, result) If status is false, result is an error message. Otherwise, result is a boolean value:
  2505. -- true if anonymous access is permitted, false otherwise.
  2506. function share_user_can_read(host, share)
  2507. local status, smbstate, err
  2508. local overrides = {}
  2509. -- Begin the SMB session
  2510. status, smbstate = start(host)
  2511. if(status == false) then
  2512. return false, smbstate
  2513. end
  2514. -- Negotiate the protocol
  2515. status, err = negotiate_protocol(smbstate, overrides)
  2516. if(status == false) then
  2517. stop(smbstate)
  2518. return false, err
  2519. end
  2520. -- Start up a null session
  2521. status, err = start_session(smbstate, overrides)
  2522. if(status == false) then
  2523. stop(smbstate)
  2524. return false, err
  2525. end
  2526. -- Attempt a connection to the share
  2527. status, err = tree_connect(smbstate, share, overrides)
  2528. if(status == false) then
  2529. -- Stop the session
  2530. stop(smbstate)
  2531. -- ACCESS_DENIED is the expected error: it tells us that the connection failed
  2532. if(err == 0xc0000022 or err == 'NT_STATUS_ACCESS_DENIED') then
  2533. return true, false
  2534. else
  2535. return false, err
  2536. end
  2537. end
  2538. stop(smbstate)
  2539. return true, true
  2540. end
  2541. ---Determine whether or not a host will accept any share name (I've seen this on certain systems; it's
  2542. -- bad, because it means we cannot tell whether or not a share exists).
  2543. --
  2544. --@param host The host object
  2545. --@param use_anonymous [optional] If set to 'true', test is done by the anonymous user rather than the current user.
  2546. --@return (status, result) If status is false, result is an error message. Otherwise, result is a boolean value:
  2547. -- true if the file was successfully written, false if it was not.
  2548. function share_host_returns_proper_error(host, use_anonymous)
  2549. local status, smbstate, err
  2550. local share = "nmap-share-test"
  2551. local overrides
  2552. if ( use_anonymous ) then
  2553. overrides = get_overrides_anonymous()
  2554. end
  2555. -- Begin the SMB session
  2556. status, smbstate = start(host)
  2557. if(status == false) then
  2558. return false, smbstate
  2559. end
  2560. -- Negotiate the protocol
  2561. status, err = negotiate_protocol(smbstate, overrides)
  2562. if(status == false) then
  2563. stop(smbstate)
  2564. return false, err
  2565. end
  2566. -- Start up a null session
  2567. status, err = start_session(smbstate, overrides)
  2568. if(status == false) then
  2569. stop(smbstate)
  2570. return false, err
  2571. end
  2572. -- Connect to the share
  2573. stdnse.print_debug(1, "SMB: Trying a random share to see if server responds properly: %s", share)
  2574. status, err = tree_connect(smbstate, share, overrides)
  2575. if(status == false) then
  2576. -- If the error is NT_STATUS_ACCESS_DENIED (0xc0000022), that's bad -- we don't want non-existent shares
  2577. -- showing up as 'access denied'. Any other error is ok.
  2578. if(err == 0xc0000022 or err == 'NT_STATUS_ACCESS_DENIED') then
  2579. stdnse.print_debug(1, "SMB: Server doesn't return proper value for non-existent shares (returns ACCESS_DENIED)")
  2580. stop(smbstate)
  2581. return true, false
  2582. end
  2583. else
  2584. -- If we were actually able to connect to this share, then there's probably a serious issue
  2585. stdnse.print_debug(1, "SMB: Server doesn't return proper value for non-existent shares (accepts the connection)")
  2586. stop(smbstate)
  2587. return true, false
  2588. end
  2589. stop(smbstate)
  2590. return true, true
  2591. end
  2592. ---Get all the details we can about the share. These details are stored in a table and returned.
  2593. --
  2594. --@param host The host object.
  2595. --@param share An array of shares to check.
  2596. --@return (status, result) If status is false, result is an error message. Otherwise, result is a boolean value:
  2597. -- true if the file was successfully written, false if it was not.
  2598. function share_get_details(host, share)
  2599. local msrpc = require "msrpc" -- avoid require cycle
  2600. local smbstate, status, result
  2601. local i
  2602. local details = {}
  2603. -- Save the name
  2604. details['name'] = share
  2605. -- Check if the current user can read the share
  2606. stdnse.print_debug(1, "SMB: Checking if share %s can be read by the current user", share)
  2607. status, result = share_user_can_read(host, share)
  2608. if(status == false) then
  2609. return false, result
  2610. end
  2611. details['user_can_read'] = result
  2612. -- Check if the anonymous reader can read the share
  2613. stdnse.print_debug(1, "SMB: Checking if share %s can be read by the anonymous user", share)
  2614. status, result = share_anonymous_can_read(host, share)
  2615. if(status == true) then
  2616. details['anonymous_can_read'] = result
  2617. end
  2618. -- Check if the current user can write to the share
  2619. stdnse.print_debug(1, "SMB: Checking if share %s can be written by the current user", share)
  2620. status, result = share_user_can_write(host, share)
  2621. if(status == false) then
  2622. if(result == "NT_STATUS_OBJECT_NAME_NOT_FOUND") then
  2623. details['user_can_write'] = "NT_STATUS_OBJECT_NAME_NOT_FOUND"
  2624. else
  2625. return false, result
  2626. end
  2627. end
  2628. details['user_can_write'] = result
  2629. -- Check if the anonymous user can write to the share
  2630. stdnse.print_debug(1, "SMB: Checking if share %s can be written by the anonymous user", share)
  2631. status, result = share_anonymous_can_write(host, share)
  2632. if(status == false and result == "NT_STATUS_OBJECT_NAME_NOT_FOUND") then
  2633. details['anonymous_can_write'] = "NT_STATUS_OBJECT_NAME_NOT_FOUND"
  2634. elseif( status == true ) then
  2635. details['anonymous_can_write'] = result
  2636. end
  2637. -- Try and get full details about the share
  2638. status, result = msrpc.get_share_info(host, share)
  2639. if(status == false) then
  2640. -- We don't stop for this error (it's pretty common since administive privileges are required here)
  2641. stdnse.print_debug(1, "SMB: Failed to get share info for %s: %s", share, result)
  2642. details['details'] = result
  2643. else
  2644. -- Process the result a bit
  2645. result = result['info']
  2646. if(result['max_users'] == 0xFFFFFFFF) then
  2647. result['max_users'] = "<unlimited>"
  2648. end
  2649. details['details'] = result
  2650. end
  2651. return true, details
  2652. end
  2653. ---Retrieve a list of fileshares, along with any details that could be pulled. This is the core of smb-enum-shares.nse, but
  2654. -- can also be used by any script that needs to find an open share.
  2655. --
  2656. -- In the best care, the shares are determined by calling <code>msrpc.enum_shares</code>, and information is gathered by calling
  2657. -- <code>msrpc.get_share_info</code>. These require a certain level of access, though, so as a fallback, a pre-programmed list of
  2658. -- shares is used, and these are verified by attempting a connection.
  2659. --
  2660. --@param host The host object.
  2661. --@return (status, result, extra) If status is false, result is an error message. Otherwise, result is an array of shares with as much
  2662. -- detail as we could get. If extra isn't nil, it is set to extra information that should be displayed (such as a warning).
  2663. function share_get_list(host)
  2664. local msrpc = require "msrpc" -- avoid require cycle
  2665. local status, result
  2666. local enum_status
  2667. local extra = ""
  2668. local shares = {}
  2669. local share_details = {}
  2670. -- Try and do this the good way, make a MSRPC call to get the shares
  2671. stdnse.print_debug(1, "SMB: Attempting to log into the system to enumerate shares")
  2672. enum_status, shares = msrpc.enum_shares(host)
  2673. -- If that failed, try doing it with brute force. This almost certainly won't find everything, but it's the
  2674. -- best we can do.
  2675. if(enum_status == false) then
  2676. stdnse.print_debug(1, "SMB: Enumerating shares failed, guessing at common ones (%s)", shares)
  2677. extra = string.format("ERROR: Enumerating shares failed, guessing at common ones (%s)", shares)
  2678. -- Take some common share names I've seen (thanks to Brandon Enright for most of these, except the last few)
  2679. shares = {"ADMIN", "BACKUP", "DATA", "DESKTOP", "DOCS", "FILES", "GROUPS", "HD", "HOME", "INFO", "IPC", "MEDIA", "MY DOCUMENTS", "NETLOGON", "PICTURES", "PORN", "PR0N", "PRINT", "PROGRAMS", "PRON", "PUBLIC", "SHARE", "SHARED", "SOFTWARE", "STMP", "TEMP", "TEST", "TMP", "USERS", "WEB DOCUMENTS","WEBSERVER", "WWW", "XSERVE" }
  2680. -- Try every alphabetic share
  2681. for i = string.byte("A", 1), string.byte("Z", 1), 1 do
  2682. shares[#shares + 1] = string.char(i)
  2683. end
  2684. -- For each share, add one with the same name and a trailing '$'
  2685. local sharesLength = #shares
  2686. for shareItr = 1, sharesLength, 1 do
  2687. shares[ sharesLength + shareItr ] = shares[ shareItr ] .. '$'
  2688. end
  2689. else
  2690. stdnse.print_debug(1, "SMB: Found %d shares, will attempt to find more information", #shares)
  2691. end
  2692. -- Sort the shares
  2693. table.sort(shares)
  2694. -- Ensure that the server returns the proper error message
  2695. -- first try anonymously, then using a user account (in case anonymous connections are not supported)
  2696. for _, anon in ipairs({true, false}) do
  2697. status, result = share_host_returns_proper_error(host)
  2698. if(status == true and result == false) then
  2699. return false, "Server doesn't return proper value for non-existent shares; can't enumerate shares"
  2700. end
  2701. end
  2702. if(status == false) then
  2703. return false, result
  2704. end
  2705. -- Get more information on each share
  2706. for i = 1, #shares, 1 do
  2707. local status, result
  2708. stdnse.print_debug(1, "SMB: Getting information for share: %s", shares[i])
  2709. status, result = share_get_details(host, shares[i])
  2710. if(status == false and result == 'NT_STATUS_BAD_NETWORK_NAME') then
  2711. stdnse.print_debug(1, "SMB: Share doesn't exist: %s", shares[i])
  2712. elseif(status == false) then
  2713. stdnse.print_debug(1, "SMB: Error while getting share details: %s", result)
  2714. return false, result
  2715. else
  2716. -- Save the share details
  2717. table.insert(share_details, result)
  2718. end
  2719. end
  2720. return true, share_details, extra
  2721. end
  2722. ---Find a share that the current user can write to. Return it, along with its path. If no share could be found,
  2723. -- an error is returned. If the path cannot be determined, the returned path is nil.
  2724. --
  2725. --@param host The host object.
  2726. --@return (status, name, path, names) If status is false, result is an error message. Otherwise, name is the name of the share,
  2727. -- path is its path, if it could be determined, and names is a list of all writable shares.
  2728. function share_find_writable(host)
  2729. local i
  2730. local status, shares
  2731. local main_name, main_path
  2732. local names = {}
  2733. local writable = {}
  2734. status, shares = share_get_list(host)
  2735. if(status == false) then
  2736. return false, shares
  2737. end
  2738. for i = 1, #shares, 1 do
  2739. if(shares[i]['user_can_write'] == true) then
  2740. if(main_name == nil) then
  2741. main_name = shares[i]['name']
  2742. if(shares[i]['details'] ~= nil) then
  2743. main_path = shares[i]['details']['path']
  2744. end
  2745. end
  2746. table.insert(names, shares[i]['name'])
  2747. end
  2748. end
  2749. if(main_name == nil) then
  2750. return false, "Couldn't find a writable share!"
  2751. else
  2752. return true, main_name, main_path, names
  2753. end
  2754. end
  2755. --- Converts numbered Windows version strings (<code>"Windows 5.0"</code>, <code>"Windows 5.1"</code>) to names (<code>"Windows 2000"</code>, <code>"Windows XP"</code>).
  2756. --@param os The numbered OS version.
  2757. --@return The actual name of the OS (or the same as the <code>os</code> parameter if no match was found).
  2758. function get_windows_version(os)
  2759. if(os == "Windows 5.0") then
  2760. return "Windows 2000"
  2761. elseif(os == "Windows 5.1")then
  2762. return "Windows XP"
  2763. end
  2764. return os
  2765. end
  2766. ---Retrieve information about the host's operating system. This should always be possible to call, as long as there isn't already
  2767. -- a SMB session established.
  2768. --
  2769. -- The returned table has the following keys (shown here with sample values).
  2770. -- * <code>os</code>: <code>"Windows 7 Professional 7601 Service Pack 1"</code>
  2771. -- * <code>lanmanager</code>: <code>"Windows 7 Professional 6.1"</code>
  2772. -- * <code>domain</code>: <code>"WORKGROUP"</code>
  2773. -- * <code>server</code>: <code>"COMPUTERNAME"</code>
  2774. -- * <code>time</code>: <code>1347121470.0462</code>
  2775. -- * <code>date</code>: <code>"2012-09-08 09:24:30"</code>
  2776. -- * <code>timezone</code>: <code>-7</code>
  2777. -- * <code>timezone_str</code>: <code>UTC-7</code>
  2778. -- The table may also contain these additional keys:
  2779. -- * <code>fqdn</code>: <code>"Sql2008.lab.test.local"</code>
  2780. -- * <code>domain_dns</code>: <code>"lab.test.local"</code>
  2781. -- * <code>forest_dns</code>: <code>"test.local"</code>
  2782. -- * <code>workgroup</code>
  2783. --
  2784. --@param host The host object
  2785. --@return (status, data) If status is true, data is a table of values; otherwise, data is an error message.
  2786. function get_os(host)
  2787. local state
  2788. local status, smbstate
  2789. local response = {}
  2790. -- Start up SMB
  2791. status, smbstate = start_ex(host, true, true, nil, nil, true)
  2792. if(status == false) then
  2793. return false, smbstate
  2794. end
  2795. -- See if we actually got something
  2796. if(smbstate['os'] == nil and smbstate['lanmanager'] == nil) then
  2797. return false, "Server didn't return OS details"
  2798. end
  2799. response['os'] = smbstate['os']
  2800. response['lanmanager'] = smbstate['lanmanager']
  2801. response['domain'] = smbstate['domain']
  2802. response['server'] = smbstate['server']
  2803. response['date'] = smbstate['date']
  2804. response['time'] = smbstate['time']
  2805. response['timezone_str'] = smbstate['timezone_str']
  2806. response['timezone'] = smbstate['timezone']
  2807. -- Kill SMB
  2808. stop(smbstate)
  2809. -- Start another session with extended security. This will allow us to get
  2810. -- additional information about the target.
  2811. status, smbstate = start_ex(host, true, true, nil, nil, false)
  2812. if(status == true) then
  2813. -- See if we actually got something
  2814. if (smbstate['fqdn'] or smbstate['domain_dns'] or smbstate['forest_dns']) then
  2815. response['fqdn'] = smbstate['fqdn']
  2816. response['domain_dns'] = smbstate['domain_dns']
  2817. response['forest_dns'] = smbstate['forest_dns']
  2818. -- After a non-extended security negotiation, smbstate['domain'] will
  2819. -- contain the NetBIOS domain name, or the workgroup name. However,
  2820. -- after an extended-security session setup, smbstate['domain'] will
  2821. -- contain the NetBIOS domain name. For hosts in a workgroup, Windows
  2822. -- uses the NetBIOS hostname as the NetBIOS domain name. Comparing the
  2823. -- two will reveal whether the target is in a domain or a workgroup.
  2824. if ( smbstate['domain'] ~= nil and response['domain'] ~= smbstate['domain'] ) then
  2825. response['workgroup'] = response['domain']
  2826. response['domain'] = nil
  2827. end
  2828. end
  2829. -- Kill SMB again
  2830. stop(smbstate)
  2831. end
  2832. return true, response
  2833. end
  2834. ---Basically a wrapper around <code>socket:get_info</code>, except that it also makes a SMB connection before calling the
  2835. -- <code>get_info</code> function. Returns the mac address as well, for convenience.
  2836. --
  2837. --@param host The host object
  2838. --@return status: true for successful, false otherwise.
  2839. --@return If status is true, the local ip address; otherwise, an error message.
  2840. --@return The local port (not really meaningful, since it'll change next time).
  2841. --@return The remote ip address.
  2842. --@return The report port.
  2843. --@return The mac address, if possible; nil otherwise.
  2844. function get_socket_info(host)
  2845. local status, lhost, lport, rhost, rport
  2846. local smbstate, socket
  2847. -- Start SMB (we need a socket to get the proper local ip
  2848. status, smbstate = start_ex(host)
  2849. if(status == false) then
  2850. return false, smbstate
  2851. end
  2852. socket = smbstate['socket']
  2853. status, lhost, lport, rhost, rport = socket:get_info()
  2854. if(status == false) then
  2855. return false, lhost
  2856. end
  2857. -- Stop SMB
  2858. stop(smbstate)
  2859. -- Get the mac in hex format, if possible
  2860. local lmac = nil
  2861. if(host.mac_addr_src) then
  2862. lmac = stdnse.tohex(host.mac_addr_src, {separator = ":"})
  2863. end
  2864. return true, lhost, lport, rhost, rport, lmac
  2865. end
  2866. ---Generate a string that's somewhat unique, but is based on factors that won't change on a host. At the moment, this is a very simple
  2867. -- hash based on the IP address. This hash is *very* likely to have collisions, and that's by design -- while it should be somewhat unique,
  2868. -- I don't want it to be trivial to uniquely determine who it originated from.
  2869. --
  2870. -- TODO: At some point, I should re-do this function properly, with a method of hashing that's somewhat proven.
  2871. --
  2872. --@param host The host object
  2873. --@param extension [optional] The extension to add on the end of the file. Default: none.
  2874. --@param seed [optional] Some randomness on which to base the name. If you want to do multiple files, each with its
  2875. -- own uniqueish name, this can be used.
  2876. --@return (status, data) If status is true, data is a table of values; otherwise, data is an error message. Can be any kind of string.
  2877. function get_uniqueish_name(host, extension, seed)
  2878. local status
  2879. local lhost, lport, rhost, rport
  2880. if(type(host) == "table") then
  2881. status, lhost = get_socket_info(host)
  2882. else
  2883. lhost = host
  2884. end
  2885. -- Create our ultra-weak hash by using a simple xor/shift algorithm
  2886. -- I tested this, and in 255 tests, there were roughly 10 collisions. That's about what I'm looking for.
  2887. local hash = 0
  2888. local i
  2889. local str = lhost .. (seed or "") .. (extension or "") .. (nmap.registry.args.randomseed or "")
  2890. for i = 1, #str, 1 do
  2891. local chr = string.byte(string.sub(str, i, i), 1)
  2892. hash = bit.bxor(hash, chr)
  2893. hash = bit.bor(bit.lshift(hash, 3), bit.rshift(hash, 29))
  2894. hash = bit.bxor(hash, 3)
  2895. hash = bit.band(hash, 0xFFFFFFFF)
  2896. end
  2897. local response
  2898. if(extension) then
  2899. response = string.format("%x.%s", hash, extension)
  2900. else
  2901. response = string.format("%x", hash)
  2902. end
  2903. return true, response
  2904. end
  2905. ---Determines, as accurately as possible, whether or not an account is an administrator. If there is an error,
  2906. -- 'false' is simply returned.
  2907. function is_admin(host, username, domain, password, password_hash, hash_type)
  2908. local msrpc = require "msrpc" -- avoid require cycle
  2909. local status, smbstate, err, result
  2910. local overrides = get_overrides(username, domain, password, password_hash, hash_type)
  2911. stdnse.print_debug("SMB: Checking if %s is an administrator", username)
  2912. status, smbstate = start(host)
  2913. if(status == false) then
  2914. stdnse.print_debug("SMB; is_admin: Failed to start SMB: %s [%s]", smbstate, username)
  2915. stop(smbstate)
  2916. return false
  2917. end
  2918. status, err = negotiate_protocol(smbstate, overrides)
  2919. if(status == false) then
  2920. stdnse.print_debug("SMB; is_admin: Failed to negotiatie protocol: %s [%s]", err, username)
  2921. stop(smbstate)
  2922. return false
  2923. end
  2924. status, err = start_session(smbstate, overrides)
  2925. if(status == false) then
  2926. stdnse.print_debug("SMB; is_admin: Failed to start session %s [%s]", err, username)
  2927. stop(smbstate)
  2928. return false
  2929. end
  2930. status, err = tree_connect(smbstate, "IPC$", overrides)
  2931. if(status == false) then
  2932. stdnse.print_debug("SMB; is_admin: Failed to connect tree: %s [%s]", err, username)
  2933. stop(smbstate)
  2934. return false
  2935. end
  2936. status, err = create_file(smbstate, msrpc.SRVSVC_PATH, overrides)
  2937. if(status == false) then
  2938. stdnse.print_debug("SMB; is_admin: Failed to create file: %s [%s]", err, username)
  2939. stop(smbstate)
  2940. return false
  2941. end
  2942. status, err = msrpc.bind(smbstate, msrpc.SRVSVC_UUID, msrpc.SRVSVC_VERSION, nil)
  2943. if(status == false) then
  2944. stdnse.print_debug("SMB; is_admin: Failed to bind: %s [%s]", err, username)
  2945. stop(smbstate)
  2946. return false
  2947. end
  2948. -- Call netservergetstatistics for 'server'
  2949. status, err = msrpc.srvsvc_netservergetstatistics(smbstate, host.ip)
  2950. if(status == false) then
  2951. stdnse.print_debug("SMB; is_admin: Couldn't get server stats (may be normal): %s [%s]", err, username)
  2952. stop(smbstate)
  2953. return false
  2954. end
  2955. stop(smbstate)
  2956. return true
  2957. end
  2958. command_codes =
  2959. {
  2960. SMB_COM_CREATE_DIRECTORY = 0x00,
  2961. SMB_COM_DELETE_DIRECTORY = 0x01,
  2962. SMB_COM_OPEN = 0x02,
  2963. SMB_COM_CREATE = 0x03,
  2964. SMB_COM_CLOSE = 0x04,
  2965. SMB_COM_FLUSH = 0x05,
  2966. SMB_COM_DELETE = 0x06,
  2967. SMB_COM_RENAME = 0x07,
  2968. SMB_COM_QUERY_INFORMATION = 0x08,
  2969. SMB_COM_SET_INFORMATION = 0x09,
  2970. SMB_COM_READ = 0x0A,
  2971. SMB_COM_WRITE = 0x0B,
  2972. SMB_COM_LOCK_BYTE_RANGE = 0x0C,
  2973. SMB_COM_UNLOCK_BYTE_RANGE = 0x0D,
  2974. SMB_COM_CREATE_TEMPORARY = 0x0E,
  2975. SMB_COM_CREATE_NEW = 0x0F,
  2976. SMB_COM_CHECK_DIRECTORY = 0x10,
  2977. SMB_COM_PROCESS_EXIT = 0x11,
  2978. SMB_COM_SEEK = 0x12,
  2979. SMB_COM_LOCK_AND_READ = 0x13,
  2980. SMB_COM_WRITE_AND_UNLOCK = 0x14,
  2981. SMB_COM_READ_RAW = 0x1A,
  2982. SMB_COM_READ_MPX = 0x1B,
  2983. SMB_COM_READ_MPX_SECONDARY = 0x1C,
  2984. SMB_COM_WRITE_RAW = 0x1D,
  2985. SMB_COM_WRITE_MPX = 0x1E,
  2986. SMB_COM_WRITE_MPX_SECONDARY = 0x1F,
  2987. SMB_COM_WRITE_COMPLETE = 0x20,
  2988. SMB_COM_QUERY_SERVER = 0x21,
  2989. SMB_COM_SET_INFORMATION2 = 0x22,
  2990. SMB_COM_QUERY_INFORMATION2 = 0x23,
  2991. SMB_COM_LOCKING_ANDX = 0x24,
  2992. SMB_COM_TRANSACTION = 0x25,
  2993. SMB_COM_TRANSACTION_SECONDARY = 0x26,
  2994. SMB_COM_IOCTL = 0x27,
  2995. SMB_COM_IOCTL_SECONDARY = 0x28,
  2996. SMB_COM_COPY = 0x29,
  2997. SMB_COM_MOVE = 0x2A,
  2998. SMB_COM_ECHO = 0x2B,
  2999. SMB_COM_WRITE_AND_CLOSE = 0x2C,
  3000. SMB_COM_OPEN_ANDX = 0x2D,
  3001. SMB_COM_READ_ANDX = 0x2E,
  3002. SMB_COM_WRITE_ANDX = 0x2F,
  3003. SMB_COM_NEW_FILE_SIZE = 0x30,
  3004. SMB_COM_CLOSE_AND_TREE_DISC = 0x31,
  3005. SMB_COM_TRANSACTION2 = 0x32,
  3006. SMB_COM_TRANSACTION2_SECONDARY = 0x33,
  3007. SMB_COM_FIND_CLOSE2 = 0x34,
  3008. SMB_COM_FIND_NOTIFY_CLOSE = 0x35,
  3009. SMB_COM_TREE_CONNECT = 0x70,
  3010. SMB_COM_TREE_DISCONNECT = 0x71,
  3011. SMB_COM_NEGOTIATE = 0x72,
  3012. SMB_COM_SESSION_SETUP_ANDX = 0x73,
  3013. SMB_COM_LOGOFF_ANDX = 0x74,
  3014. SMB_COM_TREE_CONNECT_ANDX = 0x75,
  3015. SMB_COM_QUERY_INFORMATION_DISK = 0x80,
  3016. SMB_COM_SEARCH = 0x81,
  3017. SMB_COM_FIND = 0x82,
  3018. SMB_COM_FIND_UNIQUE = 0x83,
  3019. SMB_COM_FIND_CLOSE = 0x84,
  3020. SMB_COM_NT_TRANSACT = 0xA0,
  3021. SMB_COM_NT_TRANSACT_SECONDARY = 0xA1,
  3022. SMB_COM_NT_CREATE_ANDX = 0xA2,
  3023. SMB_COM_NT_CANCEL = 0xA4,
  3024. SMB_COM_NT_RENAME = 0xA5,
  3025. SMB_COM_OPEN_PRINT_FILE = 0xC0,
  3026. SMB_COM_WRITE_PRINT_FILE = 0xC1,
  3027. SMB_COM_CLOSE_PRINT_FILE = 0xC2,
  3028. SMB_COM_GET_PRINT_QUEUE = 0xC3,
  3029. SMB_COM_READ_BULK = 0xD8,
  3030. SMB_COM_WRITE_BULK = 0xD9,
  3031. SMB_COM_WRITE_BULK_DATA = 0xDA,
  3032. SMB_NO_FURTHER_COMMANDS = 0xFF
  3033. }
  3034. for i, v in pairs(command_codes) do
  3035. command_names[v] = i
  3036. end
  3037. -- see http://msdn.microsoft.com/en-us/library/cc231196(v=prot.10).aspx
  3038. status_codes =
  3039. {
  3040. NT_STATUS_SUCCESS = 0x00000000,
  3041. NT_STATUS_WERR_BADFILE = 0x00000002,
  3042. NT_STATUS_WERR_ACCESS_DENIED = 0x00000005,
  3043. NT_STATUS_WERR_INVALID_PARAMETER = 0x00000057,
  3044. NT_STATUS_WERR_INVALID_NAME = 0x0000007b,
  3045. NT_STATUS_WERR_UNKNOWN_LEVEL = 0x0000007c,
  3046. NT_STATUS_WERR_MORE_DATA = 0x000000ea,
  3047. NT_STATUS_NO_MORE_ITEMS = 0x00000103,
  3048. NT_STATUS_MORE_ENTRIES = 0x00000105,
  3049. NT_STATUS_SOME_NOT_MAPPED = 0x00000107,
  3050. NT_STATUS_SERVICE_REQUEST_TIMEOUT = 0x0000041D,
  3051. NT_STATUS_SERVICE_NO_THREAD = 0x0000041E,
  3052. NT_STATUS_SERVICE_DATABASE_LOCKED = 0x0000041F,
  3053. NT_STATUS_SERVICE_ALREADY_RUNNING = 0x00000420,
  3054. NT_STATUS_INVALID_SERVICE_ACCOUNT = 0x00000421,
  3055. NT_STATUS_SERVICE_DISABLED = 0x00000422,
  3056. NT_STATUS_CIRCULAR_DEPENDENCY = 0x00000423,
  3057. NT_STATUS_SERVICE_DOES_NOT_EXIST = 0x00000424,
  3058. NT_STATUS_SERVICE_CANNOT_ACCEPT_CTRL = 0x00000425,
  3059. NT_STATUS_SERVICE_NOT_ACTIVE = 0x00000426,
  3060. NT_STATUS_FAILED_SERVICE_CONTROLLER_CONNECT = 0x00000427,
  3061. NT_STATUS_EXCEPTION_IN_SERVICE = 0x00000428,
  3062. NT_STATUS_DATABASE_DOES_NOT_EXIST = 0x00000429,
  3063. NT_STATUS_SERVICE_SPECIFIC_ERROR = 0x0000042a,
  3064. NT_STATUS_PROCESS_ABORTED = 0x0000042b,
  3065. NT_STATUS_SERVICE_DEPENDENCY_FAIL = 0x0000042c,
  3066. NT_STATUS_SERVICE_LOGON_FAILED = 0x0000042d,
  3067. NT_STATUS_SERVICE_START_HANG = 0x0000042e,
  3068. NT_STATUS_INVALID_SERVICE_LOCK = 0x0000042f,
  3069. NT_STATUS_SERVICE_MARKED_FOR_DELETE = 0x00000430,
  3070. NT_STATUS_SERVICE_EXISTS = 0x00000431,
  3071. NT_STATUS_ALREADY_RUNNING_LKG = 0x00000432,
  3072. NT_STATUS_SERVICE_DEPENDENCY_DELETED = 0x00000433,
  3073. NT_STATUS_BOOT_ALREADY_ACCEPTED = 0x00000434,
  3074. NT_STATUS_SERVICE_NEVER_STARTED = 0x00000435,
  3075. NT_STATUS_DUPLICATE_SERVICE_NAME = 0x00000436,
  3076. NT_STATUS_DIFFERENT_SERVICE_ACCOUNT = 0x00000437,
  3077. NT_STATUS_CANNOT_DETECT_DRIVER_FAILURE = 0x00000438,
  3078. DOS_STATUS_UNKNOWN_ERROR = 0x00010001,
  3079. DOS_STATUS_NONSPECIFIC_ERROR = 0x00010002,
  3080. DOS_STATUS_DIRECTORY_NOT_FOUND = 0x00030001,
  3081. DOS_STATUS_ACCESS_DENIED = 0x00050001,
  3082. DOS_STATUS_INVALID_FID = 0x00060001,
  3083. DOS_STATUS_INVALID_NETWORK_NAME = 0x00060002,
  3084. NT_STATUS_BUFFER_OVERFLOW = 0x80000005,
  3085. NT_STATUS_UNSUCCESSFUL = 0xc0000001,
  3086. NT_STATUS_NOT_IMPLEMENTED = 0xc0000002,
  3087. NT_STATUS_INVALID_INFO_CLASS = 0xc0000003,
  3088. NT_STATUS_INFO_LENGTH_MISMATCH = 0xc0000004,
  3089. NT_STATUS_ACCESS_VIOLATION = 0xc0000005,
  3090. NT_STATUS_IN_PAGE_ERROR = 0xc0000006,
  3091. NT_STATUS_PAGEFILE_QUOTA = 0xc0000007,
  3092. NT_STATUS_INVALID_HANDLE = 0xc0000008,
  3093. NT_STATUS_BAD_INITIAL_STACK = 0xc0000009,
  3094. NT_STATUS_BAD_INITIAL_PC = 0xc000000a,
  3095. NT_STATUS_INVALID_CID = 0xc000000b,
  3096. NT_STATUS_TIMER_NOT_CANCELED = 0xc000000c,
  3097. NT_STATUS_INVALID_PARAMETER = 0xc000000d,
  3098. NT_STATUS_NO_SUCH_DEVICE = 0xc000000e,
  3099. NT_STATUS_NO_SUCH_FILE = 0xc000000f,
  3100. NT_STATUS_INVALID_DEVICE_REQUEST = 0xc0000010,
  3101. NT_STATUS_END_OF_FILE = 0xc0000011,
  3102. NT_STATUS_WRONG_VOLUME = 0xc0000012,
  3103. NT_STATUS_NO_MEDIA_IN_DEVICE = 0xc0000013,
  3104. NT_STATUS_UNRECOGNIZED_MEDIA = 0xc0000014,
  3105. NT_STATUS_NONEXISTENT_SECTOR = 0xc0000015,
  3106. NT_STATUS_MORE_PROCESSING_REQUIRED = 0xc0000016,
  3107. NT_STATUS_NO_MEMORY = 0xc0000017,
  3108. NT_STATUS_CONFLICTING_ADDRESSES = 0xc0000018,
  3109. NT_STATUS_NOT_MAPPED_VIEW = 0xc0000019,
  3110. NT_STATUS_UNABLE_TO_FREE_VM = 0xc000001a,
  3111. NT_STATUS_UNABLE_TO_DELETE_SECTION = 0xc000001b,
  3112. NT_STATUS_INVALID_SYSTEM_SERVICE = 0xc000001c,
  3113. NT_STATUS_ILLEGAL_INSTRUCTION = 0xc000001d,
  3114. NT_STATUS_INVALID_LOCK_SEQUENCE = 0xc000001e,
  3115. NT_STATUS_INVALID_VIEW_SIZE = 0xc000001f,
  3116. NT_STATUS_INVALID_FILE_FOR_SECTION = 0xc0000020,
  3117. NT_STATUS_ALREADY_COMMITTED = 0xc0000021,
  3118. NT_STATUS_ACCESS_DENIED = 0xc0000022,
  3119. NT_STATUS_BUFFER_TOO_SMALL = 0xc0000023,
  3120. NT_STATUS_OBJECT_TYPE_MISMATCH = 0xc0000024,
  3121. NT_STATUS_NONCONTINUABLE_EXCEPTION = 0xc0000025,
  3122. NT_STATUS_INVALID_DISPOSITION = 0xc0000026,
  3123. NT_STATUS_UNWIND = 0xc0000027,
  3124. NT_STATUS_BAD_STACK = 0xc0000028,
  3125. NT_STATUS_INVALID_UNWIND_TARGET = 0xc0000029,
  3126. NT_STATUS_NOT_LOCKED = 0xc000002a,
  3127. NT_STATUS_PARITY_ERROR = 0xc000002b,
  3128. NT_STATUS_UNABLE_TO_DECOMMIT_VM = 0xc000002c,
  3129. NT_STATUS_NOT_COMMITTED = 0xc000002d,
  3130. NT_STATUS_INVALID_PORT_ATTRIBUTES = 0xc000002e,
  3131. NT_STATUS_PORT_MESSAGE_TOO_LONG = 0xc000002f,
  3132. NT_STATUS_INVALID_PARAMETER_MIX = 0xc0000030,
  3133. NT_STATUS_INVALID_QUOTA_LOWER = 0xc0000031,
  3134. NT_STATUS_DISK_CORRUPT_ERROR = 0xc0000032,
  3135. NT_STATUS_OBJECT_NAME_INVALID = 0xc0000033,
  3136. NT_STATUS_OBJECT_NAME_NOT_FOUND = 0xc0000034,
  3137. NT_STATUS_OBJECT_NAME_COLLISION = 0xc0000035,
  3138. NT_STATUS_HANDLE_NOT_WAITABLE = 0xc0000036,
  3139. NT_STATUS_PORT_DISCONNECTED = 0xc0000037,
  3140. NT_STATUS_DEVICE_ALREADY_ATTACHED = 0xc0000038,
  3141. NT_STATUS_OBJECT_PATH_INVALID = 0xc0000039,
  3142. NT_STATUS_OBJECT_PATH_NOT_FOUND = 0xc000003a,
  3143. NT_STATUS_OBJECT_PATH_SYNTAX_BAD = 0xc000003b,
  3144. NT_STATUS_DATA_OVERRUN = 0xc000003c,
  3145. NT_STATUS_DATA_LATE_ERROR = 0xc000003d,
  3146. NT_STATUS_DATA_ERROR = 0xc000003e,
  3147. NT_STATUS_CRC_ERROR = 0xc000003f,
  3148. NT_STATUS_SECTION_TOO_BIG = 0xc0000040,
  3149. NT_STATUS_PORT_CONNECTION_REFUSED = 0xc0000041,
  3150. NT_STATUS_INVALID_PORT_HANDLE = 0xc0000042,
  3151. NT_STATUS_SHARING_VIOLATION = 0xc0000043,
  3152. NT_STATUS_QUOTA_EXCEEDED = 0xc0000044,
  3153. NT_STATUS_INVALID_PAGE_PROTECTION = 0xc0000045,
  3154. NT_STATUS_MUTANT_NOT_OWNED = 0xc0000046,
  3155. NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED = 0xc0000047,
  3156. NT_STATUS_PORT_ALREADY_SET = 0xc0000048,
  3157. NT_STATUS_SECTION_NOT_IMAGE = 0xc0000049,
  3158. NT_STATUS_SUSPEND_COUNT_EXCEEDED = 0xc000004a,
  3159. NT_STATUS_THREAD_IS_TERMINATING = 0xc000004b,
  3160. NT_STATUS_BAD_WORKING_SET_LIMIT = 0xc000004c,
  3161. NT_STATUS_INCOMPATIBLE_FILE_MAP = 0xc000004d,
  3162. NT_STATUS_SECTION_PROTECTION = 0xc000004e,
  3163. NT_STATUS_EAS_NOT_SUPPORTED = 0xc000004f,
  3164. NT_STATUS_EA_TOO_LARGE = 0xc0000050,
  3165. NT_STATUS_NONEXISTENT_EA_ENTRY = 0xc0000051,
  3166. NT_STATUS_NO_EAS_ON_FILE = 0xc0000052,
  3167. NT_STATUS_EA_CORRUPT_ERROR = 0xc0000053,
  3168. NT_STATUS_FILE_LOCK_CONFLICT = 0xc0000054,
  3169. NT_STATUS_LOCK_NOT_GRANTED = 0xc0000055,
  3170. NT_STATUS_DELETE_PENDING = 0xc0000056,
  3171. NT_STATUS_CTL_FILE_NOT_SUPPORTED = 0xc0000057,
  3172. NT_STATUS_UNKNOWN_REVISION = 0xc0000058,
  3173. NT_STATUS_REVISION_MISMATCH = 0xc0000059,
  3174. NT_STATUS_INVALID_OWNER = 0xc000005a,
  3175. NT_STATUS_INVALID_PRIMARY_GROUP = 0xc000005b,
  3176. NT_STATUS_NO_IMPERSONATION_TOKEN = 0xc000005c,
  3177. NT_STATUS_CANT_DISABLE_MANDATORY = 0xc000005d,
  3178. NT_STATUS_NO_LOGON_SERVERS = 0xc000005e,
  3179. NT_STATUS_NO_SUCH_LOGON_SESSION = 0xc000005f,
  3180. NT_STATUS_NO_SUCH_PRIVILEGE = 0xc0000060,
  3181. NT_STATUS_PRIVILEGE_NOT_HELD = 0xc0000061,
  3182. NT_STATUS_INVALID_ACCOUNT_NAME = 0xc0000062,
  3183. NT_STATUS_USER_EXISTS = 0xc0000063,
  3184. NT_STATUS_NO_SUCH_USER = 0xc0000064,
  3185. NT_STATUS_GROUP_EXISTS = 0xc0000065,
  3186. NT_STATUS_NO_SUCH_GROUP = 0xc0000066,
  3187. NT_STATUS_MEMBER_IN_GROUP = 0xc0000067,
  3188. NT_STATUS_MEMBER_NOT_IN_GROUP = 0xc0000068,
  3189. NT_STATUS_LAST_ADMIN = 0xc0000069,
  3190. NT_STATUS_WRONG_PASSWORD = 0xc000006a,
  3191. NT_STATUS_ILL_FORMED_PASSWORD = 0xc000006b,
  3192. NT_STATUS_PASSWORD_RESTRICTION = 0xc000006c,
  3193. NT_STATUS_LOGON_FAILURE = 0xc000006d,
  3194. NT_STATUS_ACCOUNT_RESTRICTION = 0xc000006e,
  3195. NT_STATUS_INVALID_LOGON_HOURS = 0xc000006f,
  3196. NT_STATUS_INVALID_WORKSTATION = 0xc0000070,
  3197. NT_STATUS_PASSWORD_EXPIRED = 0xc0000071,
  3198. NT_STATUS_ACCOUNT_DISABLED = 0xc0000072,
  3199. NT_STATUS_NONE_MAPPED = 0xc0000073,
  3200. NT_STATUS_TOO_MANY_LUIDS_REQUESTED = 0xc0000074,
  3201. NT_STATUS_LUIDS_EXHAUSTED = 0xc0000075,
  3202. NT_STATUS_INVALID_SUB_AUTHORITY = 0xc0000076,
  3203. NT_STATUS_INVALID_ACL = 0xc0000077,
  3204. NT_STATUS_INVALID_SID = 0xc0000078,
  3205. NT_STATUS_INVALID_SECURITY_DESCR = 0xc0000079,
  3206. NT_STATUS_PROCEDURE_NOT_FOUND = 0xc000007a,
  3207. NT_STATUS_INVALID_IMAGE_FORMAT = 0xc000007b,
  3208. NT_STATUS_NO_TOKEN = 0xc000007c,
  3209. NT_STATUS_BAD_INHERITANCE_ACL = 0xc000007d,
  3210. NT_STATUS_RANGE_NOT_LOCKED = 0xc000007e,
  3211. NT_STATUS_DISK_FULL = 0xc000007f,
  3212. NT_STATUS_SERVER_DISABLED = 0xc0000080,
  3213. NT_STATUS_SERVER_NOT_DISABLED = 0xc0000081,
  3214. NT_STATUS_TOO_MANY_GUIDS_REQUESTED = 0xc0000082,
  3215. NT_STATUS_GUIDS_EXHAUSTED = 0xc0000083,
  3216. NT_STATUS_INVALID_ID_AUTHORITY = 0xc0000084,
  3217. NT_STATUS_AGENTS_EXHAUSTED = 0xc0000085,
  3218. NT_STATUS_INVALID_VOLUME_LABEL = 0xc0000086,
  3219. NT_STATUS_SECTION_NOT_EXTENDED = 0xc0000087,
  3220. NT_STATUS_NOT_MAPPED_DATA = 0xc0000088,
  3221. NT_STATUS_RESOURCE_DATA_NOT_FOUND = 0xc0000089,
  3222. NT_STATUS_RESOURCE_TYPE_NOT_FOUND = 0xc000008a,
  3223. NT_STATUS_RESOURCE_NAME_NOT_FOUND = 0xc000008b,
  3224. NT_STATUS_ARRAY_BOUNDS_EXCEEDED = 0xc000008c,
  3225. NT_STATUS_FLOAT_DENORMAL_OPERAND = 0xc000008d,
  3226. NT_STATUS_FLOAT_DIVIDE_BY_ZERO = 0xc000008e,
  3227. NT_STATUS_FLOAT_INEXACT_RESULT = 0xc000008f,
  3228. NT_STATUS_FLOAT_INVALID_OPERATION = 0xc0000090,
  3229. NT_STATUS_FLOAT_OVERFLOW = 0xc0000091,
  3230. NT_STATUS_FLOAT_STACK_CHECK = 0xc0000092,
  3231. NT_STATUS_FLOAT_UNDERFLOW = 0xc0000093,
  3232. NT_STATUS_INTEGER_DIVIDE_BY_ZERO = 0xc0000094,
  3233. NT_STATUS_INTEGER_OVERFLOW = 0xc0000095,
  3234. NT_STATUS_PRIVILEGED_INSTRUCTION = 0xc0000096,
  3235. NT_STATUS_TOO_MANY_PAGING_FILES = 0xc0000097,
  3236. NT_STATUS_FILE_INVALID = 0xc0000098,
  3237. NT_STATUS_ALLOTTED_SPACE_EXCEEDED = 0xc0000099,
  3238. NT_STATUS_INSUFFICIENT_RESOURCES = 0xc000009a,
  3239. NT_STATUS_DFS_EXIT_PATH_FOUND = 0xc000009b,
  3240. NT_STATUS_DEVICE_DATA_ERROR = 0xc000009c,
  3241. NT_STATUS_DEVICE_NOT_CONNECTED = 0xc000009d,
  3242. NT_STATUS_DEVICE_POWER_FAILURE = 0xc000009e,
  3243. NT_STATUS_FREE_VM_NOT_AT_BASE = 0xc000009f,
  3244. NT_STATUS_MEMORY_NOT_ALLOCATED = 0xc00000a0,
  3245. NT_STATUS_WORKING_SET_QUOTA = 0xc00000a1,
  3246. NT_STATUS_MEDIA_WRITE_PROTECTED = 0xc00000a2,
  3247. NT_STATUS_DEVICE_NOT_READY = 0xc00000a3,
  3248. NT_STATUS_INVALID_GROUP_ATTRIBUTES = 0xc00000a4,
  3249. NT_STATUS_BAD_IMPERSONATION_LEVEL = 0xc00000a5,
  3250. NT_STATUS_CANT_OPEN_ANONYMOUS = 0xc00000a6,
  3251. NT_STATUS_BAD_VALIDATION_CLASS = 0xc00000a7,
  3252. NT_STATUS_BAD_TOKEN_TYPE = 0xc00000a8,
  3253. NT_STATUS_BAD_MASTER_BOOT_RECORD = 0xc00000a9,
  3254. NT_STATUS_INSTRUCTION_MISALIGNMENT = 0xc00000aa,
  3255. NT_STATUS_INSTANCE_NOT_AVAILABLE = 0xc00000ab,
  3256. NT_STATUS_PIPE_NOT_AVAILABLE = 0xc00000ac,
  3257. NT_STATUS_INVALID_PIPE_STATE = 0xc00000ad,
  3258. NT_STATUS_PIPE_BUSY = 0xc00000ae,
  3259. NT_STATUS_ILLEGAL_FUNCTION = 0xc00000af,
  3260. NT_STATUS_PIPE_DISCONNECTED = 0xc00000b0,
  3261. NT_STATUS_PIPE_CLOSING = 0xc00000b1,
  3262. NT_STATUS_PIPE_CONNECTED = 0xc00000b2,
  3263. NT_STATUS_PIPE_LISTENING = 0xc00000b3,
  3264. NT_STATUS_INVALID_READ_MODE = 0xc00000b4,
  3265. NT_STATUS_IO_TIMEOUT = 0xc00000b5,
  3266. NT_STATUS_FILE_FORCED_CLOSED = 0xc00000b6,
  3267. NT_STATUS_PROFILING_NOT_STARTED = 0xc00000b7,
  3268. NT_STATUS_PROFILING_NOT_STOPPED = 0xc00000b8,
  3269. NT_STATUS_COULD_NOT_INTERPRET = 0xc00000b9,
  3270. NT_STATUS_FILE_IS_A_DIRECTORY = 0xc00000ba,
  3271. NT_STATUS_NOT_SUPPORTED = 0xc00000bb,
  3272. NT_STATUS_REMOTE_NOT_LISTENING = 0xc00000bc,
  3273. NT_STATUS_DUPLICATE_NAME = 0xc00000bd,
  3274. NT_STATUS_BAD_NETWORK_PATH = 0xc00000be,
  3275. NT_STATUS_NETWORK_BUSY = 0xc00000bf,
  3276. NT_STATUS_DEVICE_DOES_NOT_EXIST = 0xc00000c0,
  3277. NT_STATUS_TOO_MANY_COMMANDS = 0xc00000c1,
  3278. NT_STATUS_ADAPTER_HARDWARE_ERROR = 0xc00000c2,
  3279. NT_STATUS_INVALID_NETWORK_RESPONSE = 0xc00000c3,
  3280. NT_STATUS_UNEXPECTED_NETWORK_ERROR = 0xc00000c4,
  3281. NT_STATUS_BAD_REMOTE_ADAPTER = 0xc00000c5,
  3282. NT_STATUS_PRINT_QUEUE_FULL = 0xc00000c6,
  3283. NT_STATUS_NO_SPOOL_SPACE = 0xc00000c7,
  3284. NT_STATUS_PRINT_CANCELLED = 0xc00000c8,
  3285. NT_STATUS_NETWORK_NAME_DELETED = 0xc00000c9,
  3286. NT_STATUS_NETWORK_ACCESS_DENIED = 0xc00000ca,
  3287. NT_STATUS_BAD_DEVICE_TYPE = 0xc00000cb,
  3288. NT_STATUS_BAD_NETWORK_NAME = 0xc00000cc,
  3289. NT_STATUS_TOO_MANY_NAMES = 0xc00000cd,
  3290. NT_STATUS_TOO_MANY_SESSIONS = 0xc00000ce,
  3291. NT_STATUS_SHARING_PAUSED = 0xc00000cf,
  3292. NT_STATUS_REQUEST_NOT_ACCEPTED = 0xc00000d0,
  3293. NT_STATUS_REDIRECTOR_PAUSED = 0xc00000d1,
  3294. NT_STATUS_NET_WRITE_FAULT = 0xc00000d2,
  3295. NT_STATUS_PROFILING_AT_LIMIT = 0xc00000d3,
  3296. NT_STATUS_NOT_SAME_DEVICE = 0xc00000d4,
  3297. NT_STATUS_FILE_RENAMED = 0xc00000d5,
  3298. NT_STATUS_VIRTUAL_CIRCUIT_CLOSED = 0xc00000d6,
  3299. NT_STATUS_NO_SECURITY_ON_OBJECT = 0xc00000d7,
  3300. NT_STATUS_CANT_WAIT = 0xc00000d8,
  3301. NT_STATUS_PIPE_EMPTY = 0xc00000d9,
  3302. NT_STATUS_CANT_ACCESS_DOMAIN_INFO = 0xc00000da,
  3303. NT_STATUS_CANT_TERMINATE_SELF = 0xc00000db,
  3304. NT_STATUS_INVALID_SERVER_STATE = 0xc00000dc,
  3305. NT_STATUS_INVALID_DOMAIN_STATE = 0xc00000dd,
  3306. NT_STATUS_INVALID_DOMAIN_ROLE = 0xc00000de,
  3307. NT_STATUS_NO_SUCH_DOMAIN = 0xc00000df,
  3308. NT_STATUS_DOMAIN_EXISTS = 0xc00000e0,
  3309. NT_STATUS_DOMAIN_LIMIT_EXCEEDED = 0xc00000e1,
  3310. NT_STATUS_OPLOCK_NOT_GRANTED = 0xc00000e2,
  3311. NT_STATUS_INVALID_OPLOCK_PROTOCOL = 0xc00000e3,
  3312. NT_STATUS_INTERNAL_DB_CORRUPTION = 0xc00000e4,
  3313. NT_STATUS_INTERNAL_ERROR = 0xc00000e5,
  3314. NT_STATUS_GENERIC_NOT_MAPPED = 0xc00000e6,
  3315. NT_STATUS_BAD_DESCRIPTOR_FORMAT = 0xc00000e7,
  3316. NT_STATUS_INVALID_USER_BUFFER = 0xc00000e8,
  3317. NT_STATUS_UNEXPECTED_IO_ERROR = 0xc00000e9,
  3318. NT_STATUS_UNEXPECTED_MM_CREATE_ERR = 0xc00000ea,
  3319. NT_STATUS_UNEXPECTED_MM_MAP_ERROR = 0xc00000eb,
  3320. NT_STATUS_UNEXPECTED_MM_EXTEND_ERR = 0xc00000ec,
  3321. NT_STATUS_NOT_LOGON_PROCESS = 0xc00000ed,
  3322. NT_STATUS_LOGON_SESSION_EXISTS = 0xc00000ee,
  3323. NT_STATUS_INVALID_PARAMETER_1 = 0xc00000ef,
  3324. NT_STATUS_INVALID_PARAMETER_2 = 0xc00000f0,
  3325. NT_STATUS_INVALID_PARAMETER_3 = 0xc00000f1,
  3326. NT_STATUS_INVALID_PARAMETER_4 = 0xc00000f2,
  3327. NT_STATUS_INVALID_PARAMETER_5 = 0xc00000f3,
  3328. NT_STATUS_INVALID_PARAMETER_6 = 0xc00000f4,
  3329. NT_STATUS_INVALID_PARAMETER_7 = 0xc00000f5,
  3330. NT_STATUS_INVALID_PARAMETER_8 = 0xc00000f6,
  3331. NT_STATUS_INVALID_PARAMETER_9 = 0xc00000f7,
  3332. NT_STATUS_INVALID_PARAMETER_10 = 0xc00000f8,
  3333. NT_STATUS_INVALID_PARAMETER_11 = 0xc00000f9,
  3334. NT_STATUS_INVALID_PARAMETER_12 = 0xc00000fa,
  3335. NT_STATUS_REDIRECTOR_NOT_STARTED = 0xc00000fb,
  3336. NT_STATUS_REDIRECTOR_STARTED = 0xc00000fc,
  3337. NT_STATUS_STACK_OVERFLOW = 0xc00000fd,
  3338. NT_STATUS_NO_SUCH_PACKAGE = 0xc00000fe,
  3339. NT_STATUS_BAD_FUNCTION_TABLE = 0xc00000ff,
  3340. NT_STATUS_DIRECTORY_NOT_EMPTY = 0xc0000101,
  3341. NT_STATUS_FILE_CORRUPT_ERROR = 0xc0000102,
  3342. NT_STATUS_NOT_A_DIRECTORY = 0xc0000103,
  3343. NT_STATUS_BAD_LOGON_SESSION_STATE = 0xc0000104,
  3344. NT_STATUS_LOGON_SESSION_COLLISION = 0xc0000105,
  3345. NT_STATUS_NAME_TOO_LONG = 0xc0000106,
  3346. NT_STATUS_FILES_OPEN = 0xc0000107,
  3347. NT_STATUS_CONNECTION_IN_USE = 0xc0000108,
  3348. NT_STATUS_MESSAGE_NOT_FOUND = 0xc0000109,
  3349. NT_STATUS_PROCESS_IS_TERMINATING = 0xc000010a,
  3350. NT_STATUS_INVALID_LOGON_TYPE = 0xc000010b,
  3351. NT_STATUS_NO_GUID_TRANSLATION = 0xc000010c,
  3352. NT_STATUS_CANNOT_IMPERSONATE = 0xc000010d,
  3353. NT_STATUS_IMAGE_ALREADY_LOADED = 0xc000010e,
  3354. NT_STATUS_ABIOS_NOT_PRESENT = 0xc000010f,
  3355. NT_STATUS_ABIOS_LID_NOT_EXIST = 0xc0000110,
  3356. NT_STATUS_ABIOS_LID_ALREADY_OWNED = 0xc0000111,
  3357. NT_STATUS_ABIOS_NOT_LID_OWNER = 0xc0000112,
  3358. NT_STATUS_ABIOS_INVALID_COMMAND = 0xc0000113,
  3359. NT_STATUS_ABIOS_INVALID_LID = 0xc0000114,
  3360. NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE = 0xc0000115,
  3361. NT_STATUS_ABIOS_INVALID_SELECTOR = 0xc0000116,
  3362. NT_STATUS_NO_LDT = 0xc0000117,
  3363. NT_STATUS_INVALID_LDT_SIZE = 0xc0000118,
  3364. NT_STATUS_INVALID_LDT_OFFSET = 0xc0000119,
  3365. NT_STATUS_INVALID_LDT_DESCRIPTOR = 0xc000011a,
  3366. NT_STATUS_INVALID_IMAGE_NE_FORMAT = 0xc000011b,
  3367. NT_STATUS_RXACT_INVALID_STATE = 0xc000011c,
  3368. NT_STATUS_RXACT_COMMIT_FAILURE = 0xc000011d,
  3369. NT_STATUS_MAPPED_FILE_SIZE_ZERO = 0xc000011e,
  3370. NT_STATUS_TOO_MANY_OPENED_FILES = 0xc000011f,
  3371. NT_STATUS_CANCELLED = 0xc0000120,
  3372. NT_STATUS_CANNOT_DELETE = 0xc0000121,
  3373. NT_STATUS_INVALID_COMPUTER_NAME = 0xc0000122,
  3374. NT_STATUS_FILE_DELETED = 0xc0000123,
  3375. NT_STATUS_SPECIAL_ACCOUNT = 0xc0000124,
  3376. NT_STATUS_SPECIAL_GROUP = 0xc0000125,
  3377. NT_STATUS_SPECIAL_USER = 0xc0000126,
  3378. NT_STATUS_MEMBERS_PRIMARY_GROUP = 0xc0000127,
  3379. NT_STATUS_FILE_CLOSED = 0xc0000128,
  3380. NT_STATUS_TOO_MANY_THREADS = 0xc0000129,
  3381. NT_STATUS_THREAD_NOT_IN_PROCESS = 0xc000012a,
  3382. NT_STATUS_TOKEN_ALREADY_IN_USE = 0xc000012b,
  3383. NT_STATUS_PAGEFILE_QUOTA_EXCEEDED = 0xc000012c,
  3384. NT_STATUS_COMMITMENT_LIMIT = 0xc000012d,
  3385. NT_STATUS_INVALID_IMAGE_LE_FORMAT = 0xc000012e,
  3386. NT_STATUS_INVALID_IMAGE_NOT_MZ = 0xc000012f,
  3387. NT_STATUS_INVALID_IMAGE_PROTECT = 0xc0000130,
  3388. NT_STATUS_INVALID_IMAGE_WIN_16 = 0xc0000131,
  3389. NT_STATUS_LOGON_SERVER_CONFLICT = 0xc0000132,
  3390. NT_STATUS_TIME_DIFFERENCE_AT_DC = 0xc0000133,
  3391. NT_STATUS_SYNCHRONIZATION_REQUIRED = 0xc0000134,
  3392. NT_STATUS_DLL_NOT_FOUND = 0xc0000135,
  3393. NT_STATUS_OPEN_FAILED = 0xc0000136,
  3394. NT_STATUS_IO_PRIVILEGE_FAILED = 0xc0000137,
  3395. NT_STATUS_ORDINAL_NOT_FOUND = 0xc0000138,
  3396. NT_STATUS_ENTRYPOINT_NOT_FOUND = 0xc0000139,
  3397. NT_STATUS_CONTROL_C_EXIT = 0xc000013a,
  3398. NT_STATUS_LOCAL_DISCONNECT = 0xc000013b,
  3399. NT_STATUS_REMOTE_DISCONNECT = 0xc000013c,
  3400. NT_STATUS_REMOTE_RESOURCES = 0xc000013d,
  3401. NT_STATUS_LINK_FAILED = 0xc000013e,
  3402. NT_STATUS_LINK_TIMEOUT = 0xc000013f,
  3403. NT_STATUS_INVALID_CONNECTION = 0xc0000140,
  3404. NT_STATUS_INVALID_ADDRESS = 0xc0000141,
  3405. NT_STATUS_DLL_INIT_FAILED = 0xc0000142,
  3406. NT_STATUS_MISSING_SYSTEMFILE = 0xc0000143,
  3407. NT_STATUS_UNHANDLED_EXCEPTION = 0xc0000144,
  3408. NT_STATUS_APP_INIT_FAILURE = 0xc0000145,
  3409. NT_STATUS_PAGEFILE_CREATE_FAILED = 0xc0000146,
  3410. NT_STATUS_NO_PAGEFILE = 0xc0000147,
  3411. NT_STATUS_INVALID_LEVEL = 0xc0000148,
  3412. NT_STATUS_WRONG_PASSWORD_CORE = 0xc0000149,
  3413. NT_STATUS_ILLEGAL_FLOAT_CONTEXT = 0xc000014a,
  3414. NT_STATUS_PIPE_BROKEN = 0xc000014b,
  3415. NT_STATUS_REGISTRY_CORRUPT = 0xc000014c,
  3416. NT_STATUS_REGISTRY_IO_FAILED = 0xc000014d,
  3417. NT_STATUS_NO_EVENT_PAIR = 0xc000014e,
  3418. NT_STATUS_UNRECOGNIZED_VOLUME = 0xc000014f,
  3419. NT_STATUS_SERIAL_NO_DEVICE_INITED = 0xc0000150,
  3420. NT_STATUS_NO_SUCH_ALIAS = 0xc0000151,
  3421. NT_STATUS_MEMBER_NOT_IN_ALIAS = 0xc0000152,
  3422. NT_STATUS_MEMBER_IN_ALIAS = 0xc0000153,
  3423. NT_STATUS_ALIAS_EXISTS = 0xc0000154,
  3424. NT_STATUS_LOGON_NOT_GRANTED = 0xc0000155,
  3425. NT_STATUS_TOO_MANY_SECRETS = 0xc0000156,
  3426. NT_STATUS_SECRET_TOO_LONG = 0xc0000157,
  3427. NT_STATUS_INTERNAL_DB_ERROR = 0xc0000158,
  3428. NT_STATUS_FULLSCREEN_MODE = 0xc0000159,
  3429. NT_STATUS_TOO_MANY_CONTEXT_IDS = 0xc000015a,
  3430. NT_STATUS_LOGON_TYPE_NOT_GRANTED = 0xc000015b,
  3431. NT_STATUS_NOT_REGISTRY_FILE = 0xc000015c,
  3432. NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED = 0xc000015d,
  3433. NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR = 0xc000015e,
  3434. NT_STATUS_FT_MISSING_MEMBER = 0xc000015f,
  3435. NT_STATUS_ILL_FORMED_SERVICE_ENTRY = 0xc0000160,
  3436. NT_STATUS_ILLEGAL_CHARACTER = 0xc0000161,
  3437. NT_STATUS_UNMAPPABLE_CHARACTER = 0xc0000162,
  3438. NT_STATUS_UNDEFINED_CHARACTER = 0xc0000163,
  3439. NT_STATUS_FLOPPY_VOLUME = 0xc0000164,
  3440. NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND = 0xc0000165,
  3441. NT_STATUS_FLOPPY_WRONG_CYLINDER = 0xc0000166,
  3442. NT_STATUS_FLOPPY_UNKNOWN_ERROR = 0xc0000167,
  3443. NT_STATUS_FLOPPY_BAD_REGISTERS = 0xc0000168,
  3444. NT_STATUS_DISK_RECALIBRATE_FAILED = 0xc0000169,
  3445. NT_STATUS_DISK_OPERATION_FAILED = 0xc000016a,
  3446. NT_STATUS_DISK_RESET_FAILED = 0xc000016b,
  3447. NT_STATUS_SHARED_IRQ_BUSY = 0xc000016c,
  3448. NT_STATUS_FT_ORPHANING = 0xc000016d,
  3449. NT_STATUS_PARTITION_FAILURE = 0xc0000172,
  3450. NT_STATUS_INVALID_BLOCK_LENGTH = 0xc0000173,
  3451. NT_STATUS_DEVICE_NOT_PARTITIONED = 0xc0000174,
  3452. NT_STATUS_UNABLE_TO_LOCK_MEDIA = 0xc0000175,
  3453. NT_STATUS_UNABLE_TO_UNLOAD_MEDIA = 0xc0000176,
  3454. NT_STATUS_EOM_OVERFLOW = 0xc0000177,
  3455. NT_STATUS_NO_MEDIA = 0xc0000178,
  3456. NT_STATUS_NO_SUCH_MEMBER = 0xc000017a,
  3457. NT_STATUS_INVALID_MEMBER = 0xc000017b,
  3458. NT_STATUS_KEY_DELETED = 0xc000017c,
  3459. NT_STATUS_NO_LOG_SPACE = 0xc000017d,
  3460. NT_STATUS_TOO_MANY_SIDS = 0xc000017e,
  3461. NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED = 0xc000017f,
  3462. NT_STATUS_KEY_HAS_CHILDREN = 0xc0000180,
  3463. NT_STATUS_CHILD_MUST_BE_VOLATILE = 0xc0000181,
  3464. NT_STATUS_DEVICE_CONFIGURATION_ERROR = 0xc0000182,
  3465. NT_STATUS_DRIVER_INTERNAL_ERROR = 0xc0000183,
  3466. NT_STATUS_INVALID_DEVICE_STATE = 0xc0000184,
  3467. NT_STATUS_IO_DEVICE_ERROR = 0xc0000185,
  3468. NT_STATUS_DEVICE_PROTOCOL_ERROR = 0xc0000186,
  3469. NT_STATUS_BACKUP_CONTROLLER = 0xc0000187,
  3470. NT_STATUS_LOG_FILE_FULL = 0xc0000188,
  3471. NT_STATUS_TOO_LATE = 0xc0000189,
  3472. NT_STATUS_NO_TRUST_LSA_SECRET = 0xc000018a,
  3473. NT_STATUS_NO_TRUST_SAM_ACCOUNT = 0xc000018b,
  3474. NT_STATUS_TRUSTED_DOMAIN_FAILURE = 0xc000018c,
  3475. NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE = 0xc000018d,
  3476. NT_STATUS_EVENTLOG_FILE_CORRUPT = 0xc000018e,
  3477. NT_STATUS_EVENTLOG_CANT_START = 0xc000018f,
  3478. NT_STATUS_TRUST_FAILURE = 0xc0000190,
  3479. NT_STATUS_MUTANT_LIMIT_EXCEEDED = 0xc0000191,
  3480. NT_STATUS_NETLOGON_NOT_STARTED = 0xc0000192,
  3481. NT_STATUS_ACCOUNT_EXPIRED = 0xc0000193,
  3482. NT_STATUS_POSSIBLE_DEADLOCK = 0xc0000194,
  3483. NT_STATUS_NETWORK_CREDENTIAL_CONFLICT = 0xc0000195,
  3484. NT_STATUS_REMOTE_SESSION_LIMIT = 0xc0000196,
  3485. NT_STATUS_EVENTLOG_FILE_CHANGED = 0xc0000197,
  3486. NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT = 0xc0000198,
  3487. NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT = 0xc0000199,
  3488. NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT = 0xc000019a,
  3489. NT_STATUS_DOMAIN_TRUST_INCONSISTENT = 0xc000019b,
  3490. NT_STATUS_FS_DRIVER_REQUIRED = 0xc000019c,
  3491. NT_STATUS_NO_USER_SESSION_KEY = 0xc0000202,
  3492. NT_STATUS_USER_SESSION_DELETED = 0xc0000203,
  3493. NT_STATUS_RESOURCE_LANG_NOT_FOUND = 0xc0000204,
  3494. NT_STATUS_INSUFF_SERVER_RESOURCES = 0xc0000205,
  3495. NT_STATUS_INVALID_BUFFER_SIZE = 0xc0000206,
  3496. NT_STATUS_INVALID_ADDRESS_COMPONENT = 0xc0000207,
  3497. NT_STATUS_INVALID_ADDRESS_WILDCARD = 0xc0000208,
  3498. NT_STATUS_TOO_MANY_ADDRESSES = 0xc0000209,
  3499. NT_STATUS_ADDRESS_ALREADY_EXISTS = 0xc000020a,
  3500. NT_STATUS_ADDRESS_CLOSED = 0xc000020b,
  3501. NT_STATUS_CONNECTION_DISCONNECTED = 0xc000020c,
  3502. NT_STATUS_CONNECTION_RESET = 0xc000020d,
  3503. NT_STATUS_TOO_MANY_NODES = 0xc000020e,
  3504. NT_STATUS_TRANSACTION_ABORTED = 0xc000020f,
  3505. NT_STATUS_TRANSACTION_TIMED_OUT = 0xc0000210,
  3506. NT_STATUS_TRANSACTION_NO_RELEASE = 0xc0000211,
  3507. NT_STATUS_TRANSACTION_NO_MATCH = 0xc0000212,
  3508. NT_STATUS_TRANSACTION_RESPONDED = 0xc0000213,
  3509. NT_STATUS_TRANSACTION_INVALID_ID = 0xc0000214,
  3510. NT_STATUS_TRANSACTION_INVALID_TYPE = 0xc0000215,
  3511. NT_STATUS_NOT_SERVER_SESSION = 0xc0000216,
  3512. NT_STATUS_NOT_CLIENT_SESSION = 0xc0000217,
  3513. NT_STATUS_CANNOT_LOAD_REGISTRY_FILE = 0xc0000218,
  3514. NT_STATUS_DEBUG_ATTACH_FAILED = 0xc0000219,
  3515. NT_STATUS_SYSTEM_PROCESS_TERMINATED = 0xc000021a,
  3516. NT_STATUS_DATA_NOT_ACCEPTED = 0xc000021b,
  3517. NT_STATUS_NO_BROWSER_SERVERS_FOUND = 0xc000021c,
  3518. NT_STATUS_VDM_HARD_ERROR = 0xc000021d,
  3519. NT_STATUS_DRIVER_CANCEL_TIMEOUT = 0xc000021e,
  3520. NT_STATUS_REPLY_MESSAGE_MISMATCH = 0xc000021f,
  3521. NT_STATUS_MAPPED_ALIGNMENT = 0xc0000220,
  3522. NT_STATUS_IMAGE_CHECKSUM_MISMATCH = 0xc0000221,
  3523. NT_STATUS_LOST_WRITEBEHIND_DATA = 0xc0000222,
  3524. NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID = 0xc0000223,
  3525. NT_STATUS_PASSWORD_MUST_CHANGE = 0xc0000224,
  3526. NT_STATUS_NOT_FOUND = 0xc0000225,
  3527. NT_STATUS_NOT_TINY_STREAM = 0xc0000226,
  3528. NT_STATUS_RECOVERY_FAILURE = 0xc0000227,
  3529. NT_STATUS_STACK_OVERFLOW_READ = 0xc0000228,
  3530. NT_STATUS_FAIL_CHECK = 0xc0000229,
  3531. NT_STATUS_DUPLICATE_OBJECTID = 0xc000022a,
  3532. NT_STATUS_OBJECTID_EXISTS = 0xc000022b,
  3533. NT_STATUS_CONVERT_TO_LARGE = 0xc000022c,
  3534. NT_STATUS_RETRY = 0xc000022d,
  3535. NT_STATUS_FOUND_OUT_OF_SCOPE = 0xc000022e,
  3536. NT_STATUS_ALLOCATE_BUCKET = 0xc000022f,
  3537. NT_STATUS_PROPSET_NOT_FOUND = 0xc0000230,
  3538. NT_STATUS_MARSHALL_OVERFLOW = 0xc0000231,
  3539. NT_STATUS_INVALID_VARIANT = 0xc0000232,
  3540. NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND = 0xc0000233,
  3541. NT_STATUS_ACCOUNT_LOCKED_OUT = 0xc0000234,
  3542. NT_STATUS_HANDLE_NOT_CLOSABLE = 0xc0000235,
  3543. NT_STATUS_CONNECTION_REFUSED = 0xc0000236,
  3544. NT_STATUS_GRACEFUL_DISCONNECT = 0xc0000237,
  3545. NT_STATUS_ADDRESS_ALREADY_ASSOCIATED = 0xc0000238,
  3546. NT_STATUS_ADDRESS_NOT_ASSOCIATED = 0xc0000239,
  3547. NT_STATUS_CONNECTION_INVALID = 0xc000023a,
  3548. NT_STATUS_CONNECTION_ACTIVE = 0xc000023b,
  3549. NT_STATUS_NETWORK_UNREACHABLE = 0xc000023c,
  3550. NT_STATUS_HOST_UNREACHABLE = 0xc000023d,
  3551. NT_STATUS_PROTOCOL_UNREACHABLE = 0xc000023e,
  3552. NT_STATUS_PORT_UNREACHABLE = 0xc000023f,
  3553. NT_STATUS_REQUEST_ABORTED = 0xc0000240,
  3554. NT_STATUS_CONNECTION_ABORTED = 0xc0000241,
  3555. NT_STATUS_BAD_COMPRESSION_BUFFER = 0xc0000242,
  3556. NT_STATUS_USER_MAPPED_FILE = 0xc0000243,
  3557. NT_STATUS_AUDIT_FAILED = 0xc0000244,
  3558. NT_STATUS_TIMER_RESOLUTION_NOT_SET = 0xc0000245,
  3559. NT_STATUS_CONNECTION_COUNT_LIMIT = 0xc0000246,
  3560. NT_STATUS_LOGIN_TIME_RESTRICTION = 0xc0000247,
  3561. NT_STATUS_LOGIN_WKSTA_RESTRICTION = 0xc0000248,
  3562. NT_STATUS_IMAGE_MP_UP_MISMATCH = 0xc0000249,
  3563. NT_STATUS_INSUFFICIENT_LOGON_INFO = 0xc0000250,
  3564. NT_STATUS_BAD_DLL_ENTRYPOINT = 0xc0000251,
  3565. NT_STATUS_BAD_SERVICE_ENTRYPOINT = 0xc0000252,
  3566. NT_STATUS_LPC_REPLY_LOST = 0xc0000253,
  3567. NT_STATUS_IP_ADDRESS_CONFLICT1 = 0xc0000254,
  3568. NT_STATUS_IP_ADDRESS_CONFLICT2 = 0xc0000255,
  3569. NT_STATUS_REGISTRY_QUOTA_LIMIT = 0xc0000256,
  3570. NT_STATUS_PATH_NOT_COVERED = 0xc0000257,
  3571. NT_STATUS_NO_CALLBACK_ACTIVE = 0xc0000258,
  3572. NT_STATUS_LICENSE_QUOTA_EXCEEDED = 0xc0000259,
  3573. NT_STATUS_PWD_TOO_SHORT = 0xc000025a,
  3574. NT_STATUS_PWD_TOO_RECENT = 0xc000025b,
  3575. NT_STATUS_PWD_HISTORY_CONFLICT = 0xc000025c,
  3576. NT_STATUS_PLUGPLAY_NO_DEVICE = 0xc000025e,
  3577. NT_STATUS_UNSUPPORTED_COMPRESSION = 0xc000025f,
  3578. NT_STATUS_INVALID_HW_PROFILE = 0xc0000260,
  3579. NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH = 0xc0000261,
  3580. NT_STATUS_DRIVER_ORDINAL_NOT_FOUND = 0xc0000262,
  3581. NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND = 0xc0000263,
  3582. NT_STATUS_RESOURCE_NOT_OWNED = 0xc0000264,
  3583. NT_STATUS_TOO_MANY_LINKS = 0xc0000265,
  3584. NT_STATUS_QUOTA_LIST_INCONSISTENT = 0xc0000266,
  3585. NT_STATUS_FILE_IS_OFFLINE = 0xc0000267,
  3586. NT_STATUS_DS_NO_MORE_RIDS = 0xc00002a8,
  3587. NT_STATUS_NOT_A_REPARSE_POINT = 0xc0000275,
  3588. NT_STATUS_NO_SUCH_JOB = 0xc000EDE
  3589. }
  3590. for i, v in pairs(status_codes) do
  3591. status_names[v] = i
  3592. end
  3593. local NP_LIBRARY_NAME = "PIPE"
  3594. namedpipes =
  3595. {
  3596. get_pipe_subpath = function( pipeName, writeToDebugLog )
  3597. local status, pipeSubPath
  3598. if not pipeName then return false end
  3599. local _, _, match = pipeName:match( "^(\\+)(.-)\\pipe(\\.-)$" )
  3600. if match then
  3601. pipeSubPath = match
  3602. status = true
  3603. if writeToDebugLog then
  3604. stdnse.print_debug( 2, "%s: Converting %s to subpath %s", NP_LIBRARY_NAME, pipeName, match )
  3605. end
  3606. else
  3607. status = false
  3608. pipeSubPath = pipeName
  3609. end
  3610. return status, pipeSubPath
  3611. end,
  3612. make_pipe_name = function( hostnameOrIp, pipeSubPath )
  3613. if pipeSubPath:sub(1,1) ~= "\\" then
  3614. pipeSubPath = "\\" .. pipeSubPath
  3615. end
  3616. return string.format( "\\\\%s\\pipe%s", hostnameOrIp, pipeSubPath )
  3617. end,
  3618. named_pipe = {
  3619. _smbstate = nil,
  3620. _host = nil,
  3621. _pipeSubPath = nil,
  3622. _overrides = nil,
  3623. name = nil,
  3624. new = function(self,o)
  3625. o = o or {}
  3626. setmetatable(o, self)
  3627. self.__index = self
  3628. return o
  3629. end,
  3630. connect = function( self, host, pipeSubPath, overrides )
  3631. stdnse.print_debug( 2, "%s: connect() called with %s", NP_LIBRARY_NAME, tostring( pipeSubPath ) )
  3632. self._overrides = overrides or {}
  3633. self._host = host
  3634. self._pipeSubPath = pipeSubPath
  3635. if not host and not host.ip then return false, "host table is required" end
  3636. if not pipeSubPath then return false, "pipeSubPath is required" end
  3637. -- If we got a full pipe name, not a sub-path, fix it
  3638. if ( pipeSubPath:match( "^\\\\(.-)$" ) ) then
  3639. local status
  3640. status, self._pipeSubPath = namedpipes.get_pipe_subpath( self._pipeSubPath, true )
  3641. if ( not status ) then
  3642. stdnse.print_debug( 1, "%s: Attempt to connect to invalid pipe name: %s", NP_LIBRARY_NAME, tostring( pipeSubPath ) )
  3643. return false, "Invalid pipe name"
  3644. end
  3645. end
  3646. self.name = namedpipes.make_pipe_name( self._host.ip, self._pipeSubPath )
  3647. stdnse.print_debug( 2, "%s: Connecting to named pipe: %s", NP_LIBRARY_NAME, self.name )
  3648. local status, result, errorMessage
  3649. local bool_negotiate_protocol, bool_start_session, bool_disable_extended = true, true, false
  3650. status, result = start_ex( self._host, bool_negotiate_protocol, bool_start_session,
  3651. "IPC$", self._pipeSubPath, bool_disable_extended, self._overrides )
  3652. if status then
  3653. self._smbstate = result
  3654. else
  3655. errorMessage = string.format( "Connection failed: %s", result )
  3656. stdnse.print_debug( 2, "%s: Connection to named pipe (%s) failed: %s",
  3657. NP_LIBRARY_NAME, self.name, errorMessage )
  3658. end
  3659. return status, errorMessage, result
  3660. end,
  3661. disconnect = function( self )
  3662. if ( self._smbstate ) then
  3663. stdnse.print_debug( 2, "%s: Disconnecting named pipe: %s", NP_LIBRARY_NAME, self.name )
  3664. return stop( self._smbstate )
  3665. else
  3666. stdnse.print_debug( 2, "%s: disconnect() called, but SMB connection is already closed: %s", NP_LIBRARY_NAME, self.name )
  3667. end
  3668. end,
  3669. send = function( self, messageData )
  3670. if not self._smbstate then
  3671. stdnse.print_debug( 2, "%s: send() called on closed pipe (%s)", NP_LIBRARY_NAME, self.name )
  3672. return false, "Failed to send message on named pipe"
  3673. end
  3674. local offset = 0 -- offset is actually ignored for named pipes, but we'll define the argument for clarity
  3675. local status, result, errorMessage
  3676. status, result = write_file( self._smbstate, messageData, offset, self._overrides )
  3677. -- if status is true, result is data that we don't need to pay attention to
  3678. if not status then
  3679. stdnse.print_debug( 2, "%s: Write to named pipe (%s) failed: %s",
  3680. NP_LIBRARY_NAME, self.name, result )
  3681. errorMessage = "Failed to send message on named pipe", result
  3682. end
  3683. return status, errorMessage
  3684. end,
  3685. receive = function( self )
  3686. if not self._smbstate then
  3687. stdnse.print_debug( 2, "%s: receive() called on closed pipe (%s)", NP_LIBRARY_NAME, self.name )
  3688. return false, "Failed to read from named pipe"
  3689. end
  3690. local status, result, messageData
  3691. -- Packet header values
  3692. local offset = 0 -- offset is actually ignored for named pipes, but we'll define the argument for clarity
  3693. local MAX_BYTES_PER_READ = 4096
  3694. status, result = read_file( self._smbstate, offset, MAX_BYTES_PER_READ, self._overrides )
  3695. if status and result.data then
  3696. messageData = result.data
  3697. else
  3698. stdnse.print_debug( 2, "%s: Read from named pipe (%s) failed: %s",
  3699. NP_LIBRARY_NAME, self.name, result )
  3700. return false, "Failed to read from named pipe", result
  3701. end
  3702. while (result["status"] == status_codes.NT_STATUS_BUFFER_OVERFLOW) do
  3703. status, result = read_file( self._smbstate, offset, MAX_BYTES_PER_READ, self._overrides )
  3704. if status and result.data then
  3705. messageData = messageData .. result.data
  3706. else
  3707. stdnse.print_debug( 2, "%s: Read additional data from named pipe (%s) failed: %s",
  3708. NP_LIBRARY_NAME, self.name, result )
  3709. return false, "Failed to read from named pipe", result
  3710. end
  3711. end
  3712. return status, messageData
  3713. end,
  3714. }
  3715. }
  3716. filetype_codes =
  3717. {
  3718. FILE_TYPE_DISK = 0x00,
  3719. FILE_TYPE_BYTE_MODE_PIPE = 0x01,
  3720. FILE_TYPE_MESSAGE_MODE_PIPE = 0x02,
  3721. FILE_TYPE_PRINTER = 0x03,
  3722. FILE_TYPE_UNKNOWN = 0xFF
  3723. }
  3724. for i, v in pairs(filetype_codes) do
  3725. filetype_names[v] = i
  3726. end
  3727. return _ENV;