PageRenderTime 36ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 1ms

/linkedfs/usr/share/nmap/nselib/smb.lua

https://bitbucket.org/harakiri/trk
Lua | 3684 lines | 2727 code | 341 blank | 616 comment | 379 complexity | d23a796b39a061c1c3b8e3752365c373 MD5 | raw file
Possible License(s): GPL-2.0, MIT, LGPL-3.0
  1. ---Implements functionality related to Server Message Block (SMB, also known
  2. -- as CIFS) traffic, which is a Windows protocol.
  3. --
  4. -- SMB traffic is normally sent to/from ports 139 or 445 of Windows systems. Other systems
  5. -- implement SMB as well, including Samba and a lot of embedded devices. Some of them implement
  6. -- it properly and many of them not. Although the protocol has been documented decently
  7. -- well by Samba and others, many 3rd party implementations are broken or make assumptions.
  8. -- Even Samba's and Windows' implementations aren't completely compatiable. As a result,
  9. -- creating an implementation that accepts everything is a bit of a minefield.
  10. --
  11. -- Where possible, this implementation, since it's intended for scanning, will attempt to
  12. -- accept any invalid implementations it can, and fail gracefully if it can't. This has
  13. -- been tested against a great number of weird implementations, and it now works against
  14. -- all of them.
  15. --
  16. -- The intention of this library is to eventually handle all aspects of the SMB protocol.
  17. -- That being said, I'm only implementing the pieces that I (Ron Bowes) need. If you
  18. -- require something more, let me know and I'll put it on my todo list.
  19. --
  20. -- A programmer using this library should already have some knowledge of the SMB protocol,
  21. -- although a lot isn't necessary. You can pick up a lot by looking at the code. The basic
  22. -- login/logoff is this:
  23. --
  24. --<code>
  25. -- [connect]
  26. -- C->S SMB_COM_NEGOTIATE
  27. -- S->C SMB_COM_NEGOTIATE
  28. -- C->S SMB_COM_SESSION_SETUP_ANDX
  29. -- S->C SMB_COM_SESSION_SETUP_ANDX
  30. -- C->S SMB_COM_TREE_CONNECT_ANDX
  31. -- S->C SMB_COM_TREE_CONNECT_ANDX
  32. -- ...
  33. -- C->S SMB_COM_TREE_DISCONNECT
  34. -- S->C SMB_COM_TREE_DISCONNECT
  35. -- C->S SMB_COM_LOGOFF_ANDX
  36. -- S->C SMB_COM_LOGOFF_ANDX
  37. -- [disconnect]
  38. --</code>
  39. --
  40. -- In terms of functions here, the protocol is:
  41. --
  42. --<code>
  43. -- status, smbstate = smb.start(host)
  44. -- status, err = smb.negotiate_protocol(smbstate, {})
  45. -- status, err = smb.start_session(smbstate, {})
  46. -- status, err = smb.tree_connect(smbstate, path, {})
  47. -- ...
  48. -- status, err = smb.tree_disconnect(smbstate)
  49. -- status, err = smb.logoff(smbstate)
  50. -- status, err = smb.stop(smbstate)
  51. --</code>
  52. --
  53. -- The <code>stop</code> function will automatically call tree_disconnect and logoff,
  54. -- cleaning up the session, if it hasn't been done already.
  55. --
  56. -- To initially begin the connection, there are two options:
  57. --
  58. -- 1) Attempt to start a raw session over 445, if it's open.
  59. --
  60. -- 2) Attempt to start a NetBIOS session over 139. Although the
  61. -- protocol's the same, it requires a <code>session request</code> packet.
  62. -- That packet requires the computer's name, which is requested
  63. -- using a NBSTAT probe over UDP port 137.
  64. --
  65. -- Once it's connected, a <code>SMB_COM_NEGOTIATE</code> packet is sent, requesting the protocol
  66. -- "NT LM 0.12", which is the most commonly supported one. Among other things, the server's
  67. -- response contains the host's security level, the system time, and the computer/domain name.
  68. -- Some systems will refuse to use that protocol and return "-1" or "1" instead of 0. If that's
  69. -- detected, we kill the connection (because the protocol following won't work).
  70. --
  71. -- If that's successful, <code>SMB_COM_SESSION_SETUP_ANDX</code> is sent. It is essentially the logon
  72. -- packet, where the username, domain, and password are sent to the server for verification.
  73. -- The username and password are generally picked up from the program parameters, which are
  74. -- set when running a script, or from the registry where it can be set by other scripts (for
  75. -- example, <code>smb-brute.nse</code>). However, they can also be passed as parameters to the
  76. -- function, which will override any other username/password set.
  77. --
  78. -- If a username and password are set, they are used for the first login attempt. If a login fails,
  79. -- or they weren't set, a connection as the 'GUEST' account with a blank password is attempted. If
  80. -- that fails, then a NULL session is established, which should always work. The username/password
  81. -- will give the highest access level, GUEST will give lower access, and NULL will give the lowest
  82. -- (often, NULL will give no access).
  83. --
  84. -- The actual login protocol used by <code>SMB_COM_SESSION_SETUP_ANDX</code> is explained in detail
  85. -- in <code>smbauth.lua</code>.
  86. --
  87. -- Thanks go to Christopher R. Hertel and his book Implementing CIFS, which
  88. -- taught me everything I know about Microsoft's protocols. Additionally, I used Samba's
  89. -- list of error codes for my constants. Although I don't believe they would be covered
  90. -- by GPL, since they're public now anyways, but I'm not a lawyer and, if somebody feels
  91. -- differently, let me know and we can sort this out.
  92. --
  93. -- Scripts that use this module can use the script arguments listed below
  94. -- example of using these script arguments:
  95. -- <code>
  96. -- nmap --script=smb-<script>.nse --script-args=smbuser=ron,smbpass=iagotest2k3,smbbasic=1,smbsign=force <host>
  97. -- </code>
  98. --
  99. --@args smbbasic Forces the authentication to use basic security, as opposed to "extended security".
  100. -- Against most modern systems, extended security should work, but there may be cases
  101. -- where you want to force basic. There's a chance that you'll get better results for
  102. -- enumerating users if you turn on basic authentication.
  103. --@args smbsign Controls whether or not server signatures are checked in SMB packets. By default, on Windows,
  104. -- server signatures aren't enabled or required. By default, this library will always sign
  105. -- packets if it knows how, and will check signatures if the server says to. Possible values are:
  106. -- * <code>force</code>: Always check server signatures, even if server says it doesn't support them (will
  107. -- probably fail, but is technically more secure).
  108. -- * <code>negotiate</code>: [default] Use signatures if server supports them.
  109. -- * <code>ignore</code>: Never check server signatures. Not recommended.
  110. -- * <code>disable</code>: Don't send signatures, at all, and don't check the server's. not recommended.
  111. -- More information on signatures can be found in <code>smbauth.lua</code>.
  112. --@args smbport Override the default port choice. If <code>smbport</code> is open, it's used. It's assumed
  113. -- to be the same protocol as port 445, not port 139. Since it probably isn't possible to change
  114. -- Windows' ports normally, this is mostly useful if you're bouncing through a relay or something.
  115. --@args randomseed Set to a value to change the filenames/service names that are randomly generated.
  116. --
  117. --@author Ron Bowes <ron@skullsecurity.net>
  118. --@copyright Same as Nmap--See http://nmap.org/book/man-legal.html
  119. -----------------------------------------------------------------------
  120. module(... or "smb", package.seeall)
  121. require 'bit'
  122. require 'bin'
  123. require 'netbios'
  124. require 'smbauth'
  125. require 'stdnse'
  126. -- These arrays are filled in with constants at the bottom of this file
  127. command_codes = {}
  128. command_names = {}
  129. status_codes = {}
  130. status_names = {}
  131. local mutexes = setmetatable({}, {__mode = "k"});
  132. --local debug_mutex = nmap.mutex("SMB-DEBUG")
  133. local TIMEOUT = 10000
  134. ---Wrapper around <code>smbauth.add_account</code>.
  135. function add_account(host, username, domain, password, password_hash, hash_type, is_admin)
  136. smbauth.add_account(host, username, domain, password, password_hash, hash_type, is_admin)
  137. end
  138. ---Wrapper around <code>smbauth.get_account</code>.
  139. function get_account(host)
  140. return smbauth.get_account(host)
  141. end
  142. ---Create an 'overrides' table
  143. function get_overrides(username, domain, password, password_hash, hash_type, overrides)
  144. if(not(overrides)) then
  145. return {username=username, domain=domain, password=password, password_hash=password_hash, hash_type=hash_type}
  146. else
  147. overrides['username'] = username
  148. overrides['domain'] = domain
  149. overrides['password'] = password
  150. overrides['password_hash'] = password_hash
  151. overrides['hash_type'] = hash_type
  152. end
  153. end
  154. ---Get an 'overrides' table for the anonymous user
  155. --
  156. --@param overrides [optional] A base table of overrides. The appropriate fields will be added.
  157. function get_overrides_anonymous(overrides)
  158. if(not(overrides)) then
  159. return {username='', domain='', password='', password_hash=nil, hash_type='none'}
  160. else
  161. overrides['username'] = ''
  162. overrides['domain'] = ''
  163. overrides['password'] = ''
  164. overrides['password_hash'] = ''
  165. overrides['hash_type'] = 'none'
  166. end
  167. end
  168. ---Returns the mutex that should be used by the current connection. This mutex attempts
  169. -- to use the name, first, then falls back to the IP if no name was returned.
  170. --
  171. --@param smbstate The SMB object associated with the connection
  172. --@return A mutex
  173. local function get_mutex(smbstate)
  174. local mutex_name = "SMB-"
  175. local mutex
  176. -- if(nmap.debugging() > 0) then
  177. -- return debug_mutex
  178. -- end
  179. -- Decide whether to use the name or the ip address as the unique identifier
  180. if(smbstate['name'] ~= nil) then
  181. mutex_name = mutex_name .. smbstate['name']
  182. else
  183. mutex_name = mutex_name .. smbstate['ip']
  184. end
  185. if(mutexes[smbstate] == nil) then
  186. mutex = nmap.mutex(mutex_name)
  187. mutexes[smbstate] = mutex
  188. else
  189. mutex = mutexes[smbstate]
  190. end
  191. stdnse.print_debug(3, "SMB: Using mutex named '%s'", mutex_name)
  192. return mutex
  193. end
  194. ---Locks the mutex being used by this host. Doesn't return until it successfully
  195. -- obtains a lock.
  196. --
  197. --@param smbstate The SMB object associated with the connection
  198. --@param func A name to associate with this call (used purely for debugging
  199. -- and logging)
  200. local function lock_mutex(smbstate, func)
  201. local mutex
  202. stdnse.print_debug(3, "SMB: Attempting to lock mutex [%s]", func)
  203. mutex = get_mutex(smbstate)
  204. mutex "lock"
  205. stdnse.print_debug(3, "SMB: Mutex lock obtained [%s]", func)
  206. end
  207. ---Unlocks the mutex being used by this host.
  208. --
  209. --@param smbstate The SMB object associated with the connection
  210. --@param func A name to associate with this call (used purely for debugging
  211. -- and logging)
  212. local function unlock_mutex(smbstate, func)
  213. local mutex
  214. stdnse.print_debug(3, "SMB: Attempting to release mutex [%s]", func)
  215. mutex = get_mutex(smbstate)
  216. mutex "done"
  217. stdnse.print_debug(3, "SMB: Mutex released [%s]", func)
  218. end
  219. ---Convert a status number from the SMB header into a status name, returning an error message (not nil) if
  220. -- it wasn't found.
  221. --
  222. --@param status The numerical status.
  223. --@return A string representing the error. Never nil.
  224. function get_status_name(status)
  225. if(status_names[status] == nil) then
  226. -- If the name wasn't found in the array, do a linear search on it
  227. for i, v in pairs(status_names) do
  228. if(v == status) then
  229. return i
  230. end
  231. end
  232. return string.format("NT_STATUS_UNKNOWN (0x%08x)", status)
  233. else
  234. return status_names[status]
  235. end
  236. end
  237. --- Determines whether or not SMB checks are possible on this host, and, if they are,
  238. -- which port is best to use. This is how it decides:
  239. --
  240. -- * If port tcp/445 is open, use it for a raw connection
  241. -- * Otherwise, if ports tcp/139 and udp/137 are open, do a NetBIOS connection. Since
  242. -- UDP scanning isn't default, we're also ok with udp/137 in an unknown state.
  243. --
  244. --@param host The host object.
  245. --@return The port number to use, or nil if we don't have an SMB port
  246. function get_port(host)
  247. local port_u137 = nmap.get_port_state(host, {number=137, protocol="udp"})
  248. local port_t139 = nmap.get_port_state(host, {number=139, protocol="tcp"})
  249. local port_t445 = nmap.get_port_state(host, {number=445, protocol="tcp"})
  250. local custom_port = nil
  251. if(nmap.registry.args.smbport ~= nil) then
  252. custom_port = nmap.get_port_state(host, {number=tonumber(nmap.registry.args.smbport), protocol="tcp"})
  253. end
  254. -- Try a user-defined port first
  255. if(custom_port ~= nil and custom_port.state == "open") then
  256. return custom_port.number
  257. end
  258. if(port_t445 ~= nil and port_t445.state == "open") then
  259. -- tcp/445 is open, we're good
  260. return 445
  261. end
  262. if(port_t139 ~= nil and port_t139.state == "open") then
  263. -- tcp/139 is open, check uf udp/137 is open or unknown
  264. if(port_u137 == nil or port_u137.state == "open" or port_u137.state == "open|filtered") then
  265. return 139
  266. end
  267. end
  268. return nil
  269. end
  270. ---Turn off extended security negotiations for this connection. There are a few reasons you might want to
  271. -- do that, the main ones being that extended security is going to be marginally slower and it's not going
  272. -- to give the same level of information in some cases (namely, it doesn't present the server's name).
  273. --@param smb The SMB state table.
  274. function disable_extended(smb)
  275. smb['extended_security'] = false
  276. end
  277. --- Begins a SMB session, automatically determining the best way to connect. Also starts a mutex
  278. -- with mutex_id. This prevents multiple threads from making queries at the same time (which breaks
  279. -- SMB).
  280. --
  281. -- @param host The host object
  282. -- @param overrides [optional] Overrides for various fields
  283. -- @return (status, smb) if the status is true, result is the newly crated smb object;
  284. -- otherwise, socket is the error message.
  285. function start(host)
  286. local port = get_port(host)
  287. local status, result
  288. local state = {}
  289. state['uid'] = 0
  290. state['tid'] = 0
  291. state['host'] = host
  292. state['ip'] = host.ip
  293. state['sequence'] = -1
  294. -- Check whether or not the user requested basic authentication
  295. if(nmap.registry.args.smbbasic == nil) then
  296. state['extended_security'] = true
  297. else
  298. state['extended_security'] = false
  299. end
  300. -- Store the name of the server
  301. status, result = netbios.get_server_name(host.ip)
  302. if(status == true) then
  303. state['name'] = result
  304. end
  305. stdnse.print_debug(2, "SMB: Starting SMB session for %s (%s)", host.name, host.ip)
  306. if(port == nil) then
  307. return false, "SMB: Couldn't find a valid port to check"
  308. end
  309. -- Initialize the accounts for logging on (note: this has to be outside the mutex, or things break)
  310. smbauth.init_account(host)
  311. lock_mutex(state, "start(1)")
  312. if(port ~= 139) then
  313. status, state['socket'] = start_raw(host, port)
  314. state['port'] = port
  315. if(status == false) then
  316. unlock_mutex(state, "start(1)")
  317. return false, state['socket']
  318. end
  319. return true, state
  320. else
  321. status, state['socket'] = start_netbios(host, port)
  322. state['port'] = port
  323. if(status == false) then
  324. unlock_mutex(state, "start(2)")
  325. return false, state['socket']
  326. end
  327. return true, state
  328. end
  329. unlock_mutex(state, "start(3)")
  330. return false, "SMB: Couldn't find a valid port to check"
  331. end
  332. ---Initiates a SMB connection over whichever port it can, then optionally sends the common
  333. -- initialization packets. Note that each packet depends on the previous one, so if you want
  334. -- to go all the way up to create_file, you have to set all parameters.
  335. --
  336. -- If anything fails, we back out of the connection and return an error, so the calling functino
  337. -- doesn't have to call smb.stop().
  338. --
  339. --@param host The host object.
  340. --@param negotiate_protocol [optional] If 'true', send the protocol negotiation. Default: false.
  341. --@param start_session [optional] If 'true', start the session. Default: false.
  342. --@param tree_connect [optional] The tree to connect to, if given (eg. "IPC$" or "C$"). If not given,
  343. -- packet isn't sent.
  344. --@param create_file [optional] The path and name of the file (or pipe) that's created, if given. If
  345. -- not given, packet isn't sent.
  346. --@param overrides [optional] A table of overrides (for, for example, username, password, etc.) to pass
  347. -- to all functions.
  348. --@param disable_extended [optional] If set to true, disables extended security negotiations.
  349. function start_ex(host, negotiate_protocol, start_session, tree_connect, create_file, disable_extended, overrides)
  350. local smbstate
  351. local status, err
  352. -- Make sure we have overrides
  353. overrides = overrides or {}
  354. -- Begin the SMB session
  355. status, smbstate = smb.start(host)
  356. if(status == false) then
  357. return false, smbstate
  358. end
  359. -- Disable extended security if it was requested
  360. if(disable_extended == true) then
  361. smb.disable_extended(smbstate)
  362. end
  363. if(negotiate_protocol == true) then
  364. -- Negotiate the protocol
  365. status, err = smb.negotiate_protocol(smbstate, overrides)
  366. if(status == false) then
  367. smb.stop(smbstate)
  368. return false, err
  369. end
  370. if(start_session == true) then
  371. -- Start up a session
  372. status, err = smb.start_session(smbstate, overrides)
  373. if(status == false) then
  374. smb.stop(smbstate)
  375. return false, err
  376. end
  377. if(tree_connect ~= nil) then
  378. -- Connect to share
  379. status, err = smb.tree_connect(smbstate, tree_connect, overrides)
  380. if(status == false) then
  381. smb.stop(smbstate)
  382. return false, err
  383. end
  384. if(create_file ~= nil) then
  385. -- Try to connect to requested pipe
  386. status, err = smb.create_file(smbstate, create_file, overrides)
  387. if(status == false) then
  388. smb.stop(smbstate)
  389. return false, err
  390. end
  391. end
  392. end
  393. end
  394. end
  395. -- Return everything
  396. return true, smbstate
  397. end
  398. --- Kills the SMB connection, closes the socket, and releases the mutex. Because of the mutex
  399. -- being released, a script HAS to call <code>stop</code> before it exits, no matter why it's exiting!
  400. --
  401. -- In addition to killing the connection, this function will log off the user and disconnect
  402. -- the connected tree, if possible.
  403. --
  404. --@param smb The SMB object associated with the connection
  405. --@return (status, result) If status is false, result is an error message. Otherwise, result
  406. -- is undefined.
  407. function stop(smb)
  408. if(smb['tid'] ~= 0) then
  409. tree_disconnect(smb)
  410. end
  411. if(smb['uid'] ~= 0) then
  412. logoff(smb)
  413. end
  414. unlock_mutex(smb, "stop()")
  415. stdnse.print_debug(2, "SMB: Closing socket")
  416. if(smb['socket'] ~= nil) then
  417. local status, err = smb['socket']:close()
  418. if(status == false) then
  419. return false, "SMB: Failed to close socket: " .. err
  420. end
  421. end
  422. return true
  423. end
  424. --- Begins a raw SMB session, likely over port 445. Since nothing extra is required, this
  425. -- function simply makes a connection and returns the socket.
  426. --
  427. --@param host The host object to check.
  428. --@param port The port to use (most likely 445).
  429. --@return (status, socket) if status is true, result is the newly created socket.
  430. -- Otherwise, socket is the error message.
  431. function start_raw(host, port)
  432. local status, err
  433. local socket = nmap.new_socket()
  434. socket:set_timeout(TIMEOUT)
  435. status, err = socket:connect(host.ip, port, "tcp")
  436. if(status == false) then
  437. return false, "SMB: Failed to connect to host: " .. err
  438. end
  439. return true, socket
  440. end
  441. --- This function will take a string like "a.b.c.d" and return "a", "a.b", "a.b.c", and "a.b.c.d".
  442. -- This is used for discovering NetBIOS names. If a NetBIOS name is unknown, the substrings of the
  443. -- DNS name can be used in this way.
  444. --
  445. --@param name The name to take apart
  446. --@return An array of the sub names
  447. local function get_subnames(name)
  448. local i = -1
  449. local list = {}
  450. repeat
  451. local subname = name
  452. i = string.find(name, "[.]", i + 1)
  453. if(i ~= nil) then
  454. subname = string.sub(name, 1, i - 1)
  455. end
  456. list[#list + 1] = string.upper(subname)
  457. until i == nil
  458. return list
  459. end
  460. --- Begins a SMB session over NetBIOS. This requires a NetBIOS Session Start message to
  461. -- be sent first, which in turn requires the NetBIOS name. The name can be provided as
  462. -- a parameter, or it can be automatically determined.
  463. --
  464. -- Automatically determining the name is interesting, to say the least. Here are the names
  465. -- it tries, and the order it tries them in:
  466. -- * The name the user provided, if present
  467. -- * The name pulled from NetBIOS (udp/137), if possible
  468. -- * The generic name "*SMBSERVER"
  469. -- * Each subset of the domain name (for example, scanme.insecure.org would attempt "scanme",
  470. -- "scanme.insecure", and "scanme.insecure.org")
  471. --
  472. -- This whole sequence is a little hackish, but it's the standard way of doing it.
  473. --
  474. --@param host The host object to check.
  475. --@param port The port to use (most likely 139).
  476. --@param name [optional] The NetBIOS name of the host. Will attempt to automatically determine
  477. -- if it isn't given.
  478. --@return (status, socket) if status is true, result is the port
  479. -- Otherwise, socket is the error message.
  480. function start_netbios(host, port, name)
  481. local i
  482. local status, err
  483. local pos, result, flags, length
  484. local socket = nmap.new_socket()
  485. -- First, populate the name array with all possible names, in order of significance
  486. local names = {}
  487. -- Use the name parameter
  488. if(name ~= nil) then
  489. names[#names + 1] = name
  490. end
  491. -- Get the name of the server from NetBIOS
  492. status, name = netbios.get_server_name(host.ip)
  493. if(status == true) then
  494. names[#names + 1] = name
  495. end
  496. -- "*SMBSERVER" is a special name that any server should respond to
  497. names[#names + 1] = "*SMBSERVER"
  498. -- If all else fails, use each substring of the DNS name (this is a HUGE hack, but is actually
  499. -- a recommended way of doing this!)
  500. if(host.name ~= nil and host.name ~= "") then
  501. local new_names = get_subnames(host.name)
  502. for i = 1, #new_names, 1 do
  503. names[#names + 1] = new_names[i]
  504. end
  505. end
  506. -- This loop will try all the NetBIOS names we've collected, hoping one of them will work. Yes,
  507. -- this is a hackish way, but it's actually the recommended way.
  508. i = 1
  509. repeat
  510. -- Use the current name
  511. name = names[i]
  512. -- Some debug information
  513. stdnse.print_debug(1, "SMB: Trying to start NetBIOS session with name = '%s'", name)
  514. -- Request a NetBIOS session
  515. local session_request = bin.pack(">CCSzz",
  516. 0x81, -- session request
  517. 0x00, -- flags
  518. 0x44, -- length
  519. netbios.name_encode(name), -- server name
  520. netbios.name_encode("NMAP") -- client name
  521. );
  522. stdnse.print_debug(3, "SMB: Connecting to %s", host.ip)
  523. socket:set_timeout(TIMEOUT)
  524. status, err = socket:connect(host.ip, port, "tcp")
  525. if(status == false) then
  526. socket:close()
  527. return false, "SMB: Failed to connect: " .. err
  528. end
  529. -- Send the session request
  530. stdnse.print_debug(3, "SMB: Sending NetBIOS session request with name %s", name)
  531. status, err = socket:send(session_request)
  532. if(status == false) then
  533. socket:close()
  534. return false, "SMB: Failed to send: " .. err
  535. end
  536. socket:set_timeout(TIMEOUT)
  537. -- Receive the session response
  538. stdnse.print_debug(3, "SMB: Receiving NetBIOS session response")
  539. status, result = socket:receive_bytes(4);
  540. if(status == false) then
  541. socket:close()
  542. return false, "SMB: Failed to close socket: " .. result
  543. end
  544. pos, result, flags, length = bin.unpack(">CCS", result)
  545. if(length == nil) then
  546. return false, "SMB: ERROR: Ran off the end of SMB packet; likely due to server truncation [1]"
  547. end
  548. -- Check for a position session response (0x82)
  549. if result == 0x82 then
  550. stdnse.print_debug(3, "SMB: Successfully established NetBIOS session with server name %s", name)
  551. return true, socket
  552. end
  553. -- If the session failed, close the socket and try the next name
  554. stdnse.print_debug(1, "SMB: Session request failed, trying next name")
  555. socket:close()
  556. -- Try the next name
  557. i = i + 1
  558. until i > #names
  559. -- We reached the end of our names list
  560. stdnse.print_debug(1, "SMB: None of the NetBIOS names worked!")
  561. return false, "SMB: Couldn't find a NetBIOS name that works for the server. Sorry!"
  562. end
  563. --- Creates a string containing a SMB packet header. The header looks like this:
  564. --
  565. --<code>
  566. -- --------------------------------------------------------------------------------------------------
  567. -- | 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 |
  568. -- --------------------------------------------------------------------------------------------------
  569. -- | 0xFF | 'S' | 'M' | 'B' |
  570. -- --------------------------------------------------------------------------------------------------
  571. -- | Command | Status... |
  572. -- --------------------------------------------------------------------------------------------------
  573. -- | ...Status | Flags | Flags2 |
  574. -- --------------------------------------------------------------------------------------------------
  575. -- | PID_high | Signature..... |
  576. -- --------------------------------------------------------------------------------------------------
  577. -- | ....Signature.... |
  578. -- --------------------------------------------------------------------------------------------------
  579. -- | ....Signature | Unused |
  580. -- --------------------------------------------------------------------------------------------------
  581. -- | TID | PID |
  582. -- --------------------------------------------------------------------------------------------------
  583. -- | UID | MID |
  584. -- -------------------------------------------------------------------------------------------------
  585. --</code>
  586. --
  587. -- All fields are, incidentally, encoded in little endian byte order.
  588. --
  589. -- For the purposes here, the program doesn't care about most of the fields so they're given default
  590. -- values. The "command" field is the only one we ever have to set manually, in my experience. The TID
  591. -- and UID need to be set, but those are stored in the smb state and don't require user intervention.
  592. --
  593. --@param smb The smb state table.
  594. --@param command The command to use.
  595. --@return A binary string containing the packed packet header.
  596. local function smb_encode_header(smb, command)
  597. -- Used for the header
  598. local sig = string.char(0xFF) .. "SMB"
  599. -- Pretty much every flags is deprecated. We set these two because they're required to be on.
  600. local flags = bit.bor(0x10, 0x08) -- SMB_FLAGS_CANONICAL_PATHNAMES | SMB_FLAGS_CASELESS_PATHNAMES
  601. -- These flags are less deprecated. We negotiate 32-bit status codes and long names. We also don't include Unicode, which tells
  602. -- the server that we deal in ASCII.
  603. 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
  604. -- Unless the user's disabled the security signature, add it
  605. if(nmap.registry.args.smbsign ~= "disable") then
  606. flags2 = bit.bor(flags2, 0x0004) -- SMB_FLAGS2_SECURITY_SIGNATURE
  607. end
  608. if(smb['extended_security'] == true) then
  609. flags2 = bit.bor(flags2, 0x0800) -- SMB_EXTENDED_SECURITY
  610. end
  611. -- TreeID should never ever be 'nil', but it seems to happen once in awhile so print an error
  612. if(smb['tid'] == nil) then
  613. return false, string.format("SMB: ERROR: TreeID value was set to nil on host %s", smb['ip'])
  614. end
  615. local header = bin.pack("<CCCCCICSSLSSSSS",
  616. sig:byte(1), -- Header
  617. sig:byte(2), -- Header
  618. sig:byte(3), -- Header
  619. sig:byte(4), -- Header
  620. command, -- Command
  621. 0, -- status
  622. flags, -- flags
  623. flags2, -- flags2
  624. 0, -- extra (pid_high)
  625. 0, -- extra (signature)
  626. 0, -- extra (unused)
  627. smb['tid'], -- tid
  628. 12345, -- pid
  629. smb['uid'], -- uid
  630. 0 -- mid
  631. )
  632. return header
  633. end
  634. --- Converts a string containing the parameters section into the encoded parameters string.
  635. -- The encoding is simple:
  636. -- * (1 byte) The number of 2-byte values in the parameters section
  637. -- * (variable) The parameter section
  638. -- This is automatically done by <code>smb_send</code>.
  639. --
  640. -- @param parameters The parameters section.
  641. -- @return The encoded parameters.
  642. local function smb_encode_parameters(parameters)
  643. return bin.pack("<CA", string.len(parameters) / 2, parameters)
  644. end
  645. --- Converts a string containing the data section into the encoded data string.
  646. -- The encoding is simple:
  647. -- * (2 bytes) The number of bytes in the data section
  648. -- * (variable) The data section
  649. -- This is automatically done by <code>smb_send</code>.
  650. --
  651. -- @param data The data section.
  652. -- @return The encoded data.
  653. local function smb_encode_data(data)
  654. return bin.pack("<SA", string.len(data), data)
  655. end
  656. ---Sign the message, if possible. This is done by replacing the signature with the sequence
  657. -- number, creating a hash, then putting that hash in the signature location.
  658. --@param smb The smb state object.
  659. --@param body The body of the packet that's being signed.
  660. --@return The body of the packet, with the signature in place.
  661. local function message_sign(smb, body)
  662. smb['sequence'] = smb['sequence'] + 1
  663. if(smb['mac_key'] == nil) then
  664. stdnse.print_debug(3, "SMB: Not signing message (missing mac_key)")
  665. return body
  666. elseif(nmap.registry.args.smbsign == "disable") then
  667. stdnse.print_debug(3, "SMB: Not signing message (disabled by user)")
  668. return body
  669. end
  670. -- Convert the sequence number to 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 signature
  675. local signature = smbauth.calculate_signature(smb['mac_key'], new_packet)
  676. return string.sub(body, 1, 14) .. signature .. string.sub(body, 23)
  677. end
  678. ---Check the signature of the message. This is the opposite of <code>message_sign</code>,
  679. -- and works the same way (replaces the signature with the sequence number, calculates
  680. -- hash, checks)
  681. --@param smb The smb state object.
  682. --@param body The body of the packet that's being checked.
  683. --@return A true/false value -- true if the packet was signed properly, false if it wasn't.
  684. local function message_check_signature(smb, body)
  685. smb['sequence'] = smb['sequence'] + 1
  686. if(smb['mac_key'] == nil) then
  687. stdnse.print_debug(3, "SMB: Not signing message (missing mac_key)")
  688. return true
  689. elseif(nmap.registry.args.smbsign ~= "force" and bit.band(smb['security_mode'], 0x0A) ~= 0) then
  690. stdnse.print_debug(3, "SMB: Not signing message (server doesn't support it -- default)")
  691. return true
  692. elseif(nmap.registry.args.smbsign == "disable" or nmap.registry.args.smbsign == "ignore") then
  693. stdnse.print_debug(3, "SMB: Not signing message (disabled by user)")
  694. return true
  695. end
  696. -- Pull out the signature that they used
  697. local signature = string.sub(body, 15, 22)
  698. -- Turn the sequence into a string
  699. local sequence = bin.pack("<L", smb['sequence'])
  700. -- Create a new string, with the sequence number in place
  701. local new_packet = string.sub(body, 1, 14) .. sequence .. string.sub(body, 23)
  702. -- Calculate the proper signature
  703. local real_signature = smbauth.calculate_signature(smb['mac_key'], new_packet)
  704. -- Validate the signature
  705. return signature == real_signature
  706. end
  707. --- Prepends the NetBIOS header to the packet, which is essentially the length, encoded
  708. -- in 4 bytes of big endian, and sends it out. The length field is actually 17 or 24 bits
  709. -- wide, depending on whether or not we're using raw, but that shouldn't matter.
  710. --
  711. --@param smb The SMB object associated with the connection
  712. --@param header The header, encoded with <code>smb_get_header</code>.
  713. --@param parameters The parameters.
  714. --@param data The data.
  715. --@return (result, err) If result is false, err is the error message. Otherwise, err is
  716. -- undefined
  717. function smb_send(smb, header, parameters, data)
  718. local encoded_parameters = smb_encode_parameters(parameters)
  719. local encoded_data = smb_encode_data(data)
  720. local body = header .. encoded_parameters .. encoded_data
  721. local attempts = 5
  722. local status, err
  723. -- Calculate the message signature
  724. body = message_sign(smb, body)
  725. local out = bin.pack(">I<A", string.len(body), body)
  726. repeat
  727. attempts = attempts - 1
  728. stdnse.print_debug(3, "SMB: Sending SMB packet (len: %d, attempts remaining: %d)", string.len(out), attempts)
  729. status, err = smb['socket']:send(out)
  730. until(status or (attempts == 0))
  731. if(attempts == 0) then
  732. stdnse.print_debug(1, "SMB: Sending packet failed after 5 tries! Giving up.")
  733. end
  734. return status, err
  735. end
  736. --- Reads the next packet from the socket, and parses it into the header, parameters,
  737. -- and data.
  738. --
  739. --@param smb The SMB object associated with the connection
  740. --@param read_data [optional] This function will read the data section if and only if
  741. -- this value is true. This is a workaround for a bug in the tree connect packet,
  742. -- where the length is set incorrectly. Default: true.
  743. --@return (status, header, parameters, data) If status is true, the header,
  744. -- parameters, and data are all the raw arrays (with the lengths already
  745. -- removed). If status is false, header contains an error message and parameters/
  746. -- data are undefined.
  747. function smb_read(smb, read_data)
  748. local status, result
  749. local pos, netbios_length, length, header, parameter_length, parameters, data_length, data
  750. local attempts = 5
  751. stdnse.print_debug(3, "SMB: Receiving SMB packet")
  752. -- Receive the response -- we make sure to receive at least 4 bytes, the length of the NetBIOS length
  753. smb['socket']:set_timeout(TIMEOUT)
  754. repeat
  755. attempts = attempts - 1
  756. status, result = smb['socket']:receive_bytes(4);
  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: " .. result
  761. end
  762. -- The length of the packet is 4 bytes of big endian (for our purposes).
  763. -- The NetBIOS header is 24 bits, big endian
  764. pos, netbios_length = bin.unpack(">I", result)
  765. if(netbios_length == nil) then
  766. return false, "SMB: ERROR: Ran off the end of SMB packet; likely due to server truncation [2]"
  767. end
  768. -- Make the length 24 bits
  769. netbios_length = bit.band(netbios_length, 0x00FFFFFF)
  770. -- The total length is the netbios_length, plus 4 (for the length itself)
  771. length = netbios_length + 4
  772. -- If we haven't received enough bytes, try and get the rest (fragmentation!)
  773. if(#result < length) then
  774. local new_result
  775. local attempts = 5
  776. stdnse.print_debug(1, "SMB: Received a fragmented packet, attempting to receive the rest of it (got %d bytes, need %d)", #result, length)
  777. repeat
  778. attempts = attempts - 1
  779. status, new_result = smb['socket']:receive_bytes(netbios_length - #result)
  780. until(status or (attempts == 0))
  781. -- Make sure the connection is still alive
  782. if(status ~= true) then
  783. return false, "SMB: Failed to receive bytes after 5 attempts: " .. result
  784. end
  785. -- Append the new data to the old stuff
  786. result = result .. new_result
  787. stdnse.print_debug(1, "SMB: Finished receiving fragmented packet (got %d bytes, needed %d)", #result, length)
  788. end
  789. if(#result ~= length) then
  790. stdnse.print_debug(1, "SMB: ERROR: Received wrong number of bytes, there will likely be issues (recieved %d, expected %d)", #result, length)
  791. 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)
  792. end
  793. -- Check the message signature (ignoring the first four bytes, which are the netbios header)
  794. local good_signature = message_check_signature(smb, string.sub(result, 5))
  795. if(good_signature == false) then
  796. return false, "SMB: ERROR: Server returned invalid signature"
  797. end
  798. -- The header is 32 bytes.
  799. pos, header = bin.unpack("<A32", result, pos)
  800. if(header == nil) then
  801. return false, "SMB: ERROR: Ran off the end of SMB packet; likely due to server truncation [3]"
  802. end
  803. -- The parameters length is a 1-byte value.
  804. pos, parameter_length = bin.unpack("<C", result, pos)
  805. if(parameter_length == nil) then
  806. return false, "SMB: ERROR: Ran off the end of SMB packet; likely due to server truncation [4]"
  807. end
  808. -- Double the length parameter, since parameters are two-byte values.
  809. pos, parameters = bin.unpack(string.format("<A%d", parameter_length*2), result, pos)
  810. if(parameters == nil) then
  811. return false, "SMB: ERROR: Ran off the end of SMB packet; likely due to server truncation [5]"
  812. end
  813. -- The data length is a 2-byte value.
  814. pos, data_length = bin.unpack("<S", result, pos)
  815. if(data_length == nil) then
  816. return false, "SMB: ERROR: Ran off the end of SMB packet; likely due to server truncation [6]"
  817. end
  818. -- Read that many bytes of data.
  819. if(read_data == nil or read_data == true) then
  820. pos, data = bin.unpack(string.format("<A%d", data_length), result, pos)
  821. if(data == nil) then
  822. return false, "SMB: ERROR: Ran off the end of SMB packet; likely due to server truncation [7]"
  823. end
  824. else
  825. data = nil
  826. end
  827. stdnse.print_debug(3, "SMB: Received %d bytes", string.len(result))
  828. return true, header, parameters, data
  829. end
  830. --- Sends out <code>SMB_COM_NEGOTIATE</code>, which is typically the first SMB packet sent out.
  831. -- Sends the following:
  832. -- * List of known protocols
  833. --
  834. -- Receives:
  835. -- * The prefered dialect
  836. -- * The security mode
  837. -- * Max number of multiplexed connectiosn, virtual circuits, and buffer sizes
  838. -- * The server's system time and timezone
  839. -- * The "encryption key" (aka, the server challenge)
  840. -- * The capabilities
  841. -- * The server and domain names
  842. --
  843. --@param smb The SMB object associated with the connection
  844. --@param overrides [optional] Overrides for various fields
  845. --@return (status, result) If status is false, result is an error message. Otherwise, result is
  846. -- nil and the following elements are added to <code>smb</code>:
  847. -- * 'security_mode' Whether or not to use cleartext passwords, message signatures, etc.
  848. -- * 'max_mpx' Maximum number of multiplexed connections
  849. -- * 'max_vc' Maximum number of virtual circuits
  850. -- * 'max_buffer' Maximum buffer size
  851. -- * 'max_raw_buffer' Maximum buffer size for raw connections (considered obsolete)
  852. -- * 'session_key' A value that's basically just echoed back
  853. -- * 'capabilities' The server's capabilities
  854. -- * 'time' The server's time (in UNIX-style seconds since 1970)
  855. -- * 'date' The server's date in a user-readable format
  856. -- * 'timezone' The server's timezone, in hours from UTC
  857. -- * 'timezone_str' The server's timezone, as a string
  858. -- * 'server_challenge' A random string used for challenge/response
  859. -- * 'domain' The server's primary domain
  860. -- * 'server' The server's name
  861. function negotiate_protocol(smb, overrides)
  862. local header, parameters, data
  863. local pos
  864. local header1, header2, header3, ehader4, command, status, flags, flags2, pid_high, signature, unused, pid, mid
  865. header = smb_encode_header(smb, command_codes['SMB_COM_NEGOTIATE'])
  866. -- Make sure we have overrides
  867. overrides = overrides or {}
  868. -- Parameters are blank
  869. parameters = ""
  870. -- Data is a list of strings, terminated by a blank one.
  871. if(overrides['dialects'] == nil) then
  872. data = bin.pack("<CzCz", 2, (overrides['dialect'] or "NT LM 0.12"), 2, "")
  873. else
  874. data = ""
  875. for _, v in ipairs(overrides['dialects']) do
  876. data = data .. bin.pack("<Cz", 2, v)
  877. end
  878. data = data .. bin.pack("Cz", 2, "")
  879. end
  880. -- Send the negotiate request
  881. stdnse.print_debug(2, "SMB: Sending SMB_COM_NEGOTIATE")
  882. local result, err = smb_send(smb, header, parameters, data)
  883. if(status == false) then
  884. return false, err
  885. end
  886. -- Read the result
  887. status, header, parameters, data = smb_read(smb)
  888. if(status ~= true) then
  889. return false, header
  890. end
  891. -- Parse out the header
  892. local uid, tid, header4
  893. pos, header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, tid, pid, uid, mid = bin.unpack("<CCCCCICSSlSSSSS", header)
  894. -- Get the protocol version
  895. local protocol_version = string.char(header1, header2, header3, header4)
  896. if(protocol_version == (string.char(0xFE) .. "SMB")) then
  897. return false, "SMB: Server returned a SMBv2 packet, don't know how to handle"
  898. end
  899. -- Check if we fell off the packet (if that happened, the last parameter will be nil)
  900. if(mid == nil) then
  901. return false, "SMB: ERROR: Ran off the end of SMB packet; likely due to server truncation [8]"
  902. end
  903. -- Since this is the first response seen, check any necessary flags here
  904. if(bit.band(flags2, 0x0800) ~= 0x0800) then
  905. smb['extended_security'] = false
  906. end
  907. -- Parse the parameter section
  908. pos, smb['dialect'] = bin.unpack("<S", parameters)
  909. if(smb['dialect'] == nil) then
  910. return false, "SMB: ERROR: Ran off the end of SMB packet; likely due to server truncation [9]"
  911. end
  912. -- Check if we ran off the packet
  913. if(smb['dialect'] == nil) then
  914. return false, "SMB: ERROR: Ran off the end of SMB packet; likely due to server truncation [10]"
  915. end
  916. -- Check if the server didn't like our requested protocol
  917. if(smb['dialect'] ~= 0) then
  918. return false, string.format("Server negotiated an unknown protocol (#%d) -- aborting", smb['dialect'])
  919. end
  920. 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)
  921. if(smb['capabilities'] == nil) then
  922. return false, "SMB: ERROR: Ran off the end of SMB packet; likely due to server truncation [11]"
  923. end
  924. -- Some broken implementations of SMB don't send these variables
  925. if(smb['time'] == nil) then
  926. smb['time'] = 0
  927. end
  928. if(smb['timezone'] == nil) then
  929. smb['timezone'] = 0
  930. end
  931. if(smb['key_length'] == nil) then
  932. smb['key_length'] = 0
  933. end
  934. -- Convert the time and timezone to more useful values
  935. smb['time'] = (smb['time'] / 10000000) - 11644473600
  936. smb['date'] = os.date("%Y-%m-%d %H:%M:%S", smb['time'])
  937. smb['timezone'] = -(smb['timezone'] / 60)
  938. if(smb['timezone'] == 0) then
  939. smb['timezone_str'] = "UTC+0"
  940. elseif(smb['timezone'] < 0) then
  941. smb['timezone_str'] = "UTC-" .. math.abs(smb['timezone'])
  942. else
  943. smb['timezone_str'] = "UTC+" .. smb['timezone']
  944. end
  945. -- Data section
  946. if(smb['extended_security'] == true) then
  947. pos, smb['server_challenge'] = bin.unpack(string.format("<A%d", smb['key_length']), data)
  948. if(smb['server_challenge'] == nil) then
  949. return false, "SMB: ERROR: Ran off the end of SMB packet; likely due to server truncation [12]"
  950. end
  951. pos, smb['server_guid'] = bin.unpack("<A16", data, pos)
  952. if(smb['server_guid'] == nil) then
  953. return false, "SMB: ERROR: Ran off the end of SMB packet; likely due to server truncation [12]"
  954. end
  955. else
  956. pos, smb['server_challenge'] = bin.unpack(string.format("<A%d", smb['key_length']), data)
  957. if(smb['server_challenge'] == nil) then
  958. return false, "SMB: ERROR: Ran off the end of SMB packet; likely due to server truncation [12]"
  959. end
  960. -- Get the domain as a Unicode string
  961. local ch, dummy
  962. smb['domain'] = ""
  963. smb['server'] = ""
  964. pos, ch, dummy = bin.unpack("<CC", data, pos)
  965. -- if(dummy == nil) then
  966. -- return false, "SMB: ERROR: Ran off the end of SMB packet; likely due to server truncation [13]"
  967. -- end
  968. while ch ~= nil and ch ~= 0 do
  969. smb['domain'] = smb['domain'] .. string.char(ch)
  970. pos, ch, dummy = bin.unpack("<CC", data, pos)
  971. if(dummy == nil) then
  972. return false, "SMB: ERROR: Ran off the end of SMB packet; likely due to server truncation [14]"
  973. end
  974. end
  975. -- Get the server name as a Unicode string
  976. -- Note: This can be nil, Samba leaves this off
  977. pos, ch, dummy = bin.unpack("<CC", data, pos)
  978. while ch ~= nil and ch ~= 0 do
  979. smb['server'] = smb['server'] .. string.char(ch)
  980. pos, ch, dummy = bin.unpack("<CC", data, pos)
  981. end
  982. end
  983. return true
  984. end
  985. function start_session_basic(smb, log_errors, overrides)
  986. local i, err
  987. local status, result
  988. local header, parameters, data, domain
  989. local pos
  990. local header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, tid, pid, uid, mid
  991. local andx_command, andx_reserved, andx_offset, action
  992. local os, lanmanager
  993. local username, domain, password, password_hash, hash_type
  994. header = smb_encode_header(smb, command_codes['SMB_COM_SESSION_SETUP_ANDX'])
  995. -- Get the first account, unless they overrode it
  996. if(overrides ~= nil and overrides['username'] ~= nil) then
  997. result = true
  998. username = overrides['username']
  999. domain = overrides['domain']
  1000. password = overrides['password']
  1001. password_hash = overrides['password_hash']
  1002. hash_type = overrides['hash_type']
  1003. else
  1004. result, username, domain, password, password_hash, hash_type = smbauth.get_account(smb['host'])
  1005. end
  1006. while result ~= false do
  1007. local lanman, ntlm
  1008. lanman, ntlm, smb['mac_key'] = smbauth.get_password_response(smb['ip'], username, domain, password, password_hash, hash_type, smb['server_challenge'], false)
  1009. -- Parameters
  1010. parameters = bin.pack("<CCSSSSISSII",
  1011. 0xFF, -- ANDX -- no further commands
  1012. 0x00, -- ANDX -- Reserved (0)
  1013. 0x0000, -- ANDX -- next offset
  1014. 0xFFFF, -- Max buffer size
  1015. 0x0001, -- Max multiplexes
  1016. 0x0000, -- Virtual circuit num
  1017. smb['session_key'], -- The session key
  1018. #lanman, -- ANSI/Lanman password length
  1019. #ntlm, -- Unicode/NTLM password length
  1020. 0x00000000, -- Reserved
  1021. 0x00000050 -- Capabilities
  1022. )
  1023. -- Data is a list of strings, terminated by a blank one.
  1024. data = bin.pack("<AAzzzz",
  1025. lanman, -- ANSI/Lanman password
  1026. ntlm, -- Unicode/NTLM password
  1027. username, -- Account
  1028. domain, -- Domain
  1029. "Nmap", -- OS
  1030. "Native Lanman" -- Native LAN Manager
  1031. )
  1032. -- Send the session setup request
  1033. stdnse.print_debug(2, "SMB: Sending SMB_COM_SESSION_SETUP_ANDX")
  1034. result, err = smb_send(smb, header, parameters, data)
  1035. if(result == false) then
  1036. return false, err
  1037. end
  1038. -- Read the result
  1039. status, header, parameters, data = smb_read(smb)
  1040. if(status ~= true) then
  1041. return false, header
  1042. end
  1043. -- Check if we were allowed in
  1044. pos, header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, tid, pid, uid, mid = bin.unpack("<CCCCCICSSlSSSSS", header)
  1045. if(mid == nil) then
  1046. return false, "SMB: ERROR: Ran off the end of SMB packet; likely due to server truncation [17]"
  1047. end
  1048. -- Check if we're successful
  1049. if(status == 0) then
  1050. -- Parse the parameters
  1051. pos, andx_command, andx_reserved, andx_offset, action = bin.unpack("<CCSS", parameters)
  1052. if(action == nil) then
  1053. return false, "SMB: ERROR: Ran off the end of SMB packet; likely due to server truncation [18]"
  1054. end
  1055. -- Parse the data
  1056. pos, os, lanmanager, domain = bin.unpack("<zzz", data)
  1057. if(domain == nil) then
  1058. return false, "SMB: ERROR: Ran off the end of SMB packet; likely due to server truncation [19]"
  1059. end
  1060. -- Fill in the smb object and smb string
  1061. smb['uid'] = uid
  1062. smb['is_guest'] = bit.band(action, 1)
  1063. smb['os'] = os
  1064. smb['lanmanager'] = lanmanager
  1065. -- Check if they're using an un-supported system
  1066. if(os == nil or lanmanager == nil or domain == nil) then
  1067. stdnse.print_debug(1, "SMB: WARNING: the server is using a non-standard SMB implementation; your mileage may vary (%s)", smb['ip'])
  1068. elseif(os == "Unix" or string.sub(lanmanager, 1, 5) == "Samba") then
  1069. stdnse.print_debug(1, "SMB: WARNING: the server appears to be Unix; your mileage may vary.")
  1070. end
  1071. -- Check if they were logged in as a guest
  1072. if(log_errors == nil or log_errors == true) then
  1073. if(smb['is_guest'] == 1) then
  1074. 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))
  1075. else
  1076. stdnse.print_debug(2, "SMB: Login as %s\\%s succeeded", domain, stdnse.string_or_blank(username))
  1077. end
  1078. end
  1079. -- Set the initial sequence number
  1080. smb['sequence'] = 1
  1081. return true
  1082. else
  1083. -- This username failed, print a warning and keep going
  1084. if(log_errors == nil or log_errors == true) then
  1085. stdnse.print_debug(1, "SMB: Login as %s\\%s failed (%s)", domain, stdnse.string_or_blank(username), get_status_name(status))
  1086. end
  1087. -- Go to the next account
  1088. if(overrides == nil or overrides['username'] == nil) then
  1089. smbauth.next_account(smb['host'])
  1090. result, username, domain, password, password_hash, hash_type = smbauth.get_account(smb['host'])
  1091. else
  1092. result = false
  1093. end
  1094. end
  1095. end
  1096. if(log_errors ~= false) then
  1097. stdnse.print_debug(1, "SMB: ERROR: %s", username)
  1098. end
  1099. return false, get_status_name(status)
  1100. end
  1101. function start_session_extended(smb, log_errors, overrides)
  1102. local i
  1103. local status, status_name, result, err
  1104. local header, parameters, data
  1105. local pos
  1106. local header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, tid, pid, uid, mid
  1107. local andx_command, andx_reserved, andx_offset, action, security_blob_length
  1108. local os, lanmanager
  1109. local username, domain, password, password_hash, hash_type
  1110. -- Get the first account, unless they overrode it
  1111. if(overrides ~= nil and overrides['username'] ~= nil) then
  1112. result = true
  1113. username = overrides['username']
  1114. domain = overrides['domain']
  1115. password = overrides['password']
  1116. password_hash = overrides['password_hash']
  1117. hash_type = overrides['hash_type']
  1118. else
  1119. result, username, domain, password, password_hash, hash_type = smbauth.get_account(smb['host'])
  1120. end
  1121. while result ~= false do
  1122. -- These are loop variables
  1123. local security_blob = nil
  1124. local security_blob_length = 0
  1125. -- This loop takes care of the multiple packets that "extended security" requires
  1126. repeat
  1127. -- 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
  1128. status, security_blob, smb['mac_key'] = smbauth.get_security_blob(security_blob, smb['ip'], username, domain, password, password_hash, hash_type)
  1129. -- There was an error processing the security blob
  1130. if(status == false) then
  1131. return false, string.format("SMB: ERROR: Security blob: %s", security_blob)
  1132. end
  1133. header = smb_encode_header(smb, command_codes['SMB_COM_SESSION_SETUP_ANDX'])
  1134. -- Parameters
  1135. parameters = bin.pack("<CCSSSSISII",
  1136. 0xFF, -- ANDX -- no further commands
  1137. 0x00, -- ANDX -- Reserved (0)
  1138. 0x0000, -- ANDX -- next offset
  1139. 0xFFFF, -- Max buffer size
  1140. 0x0001, -- Max multiplexes
  1141. 0x0000, -- Virtual circuit num
  1142. smb['session_key'], -- The session key
  1143. #security_blob, -- Security blob length
  1144. 0x00000000, -- Reserved
  1145. 0x80000050 -- Capabilities
  1146. )
  1147. -- Data is a list of strings, terminated by a blank one.
  1148. data = bin.pack("<Azzz",
  1149. security_blob, -- Security blob
  1150. "Nmap", -- OS
  1151. "Native Lanman", -- Native LAN Manager
  1152. "" -- Primary domain
  1153. )
  1154. -- Send the session setup request
  1155. stdnse.print_debug(2, "SMB: Sending SMB_COM_SESSION_SETUP_ANDX")
  1156. result, err = smb_send(smb, header, parameters, data)
  1157. if(result == false) then
  1158. return false, err
  1159. end
  1160. -- Read the result
  1161. status, header, parameters, data = smb_read(smb)
  1162. if(status ~= true) then
  1163. return false, header
  1164. end
  1165. -- Check if we were allowed in
  1166. pos, header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, tid, pid, uid, mid = bin.unpack("<CCCCCICSSlSSSSS", header)
  1167. if(mid == nil) then
  1168. return false, "SMB: ERROR: Ran off the end of SMB packet; likely due to server truncation [17]"
  1169. end
  1170. smb['uid'] = uid
  1171. -- Get a human readable name
  1172. status_name = get_status_name(status)
  1173. -- Only parse the parameters if it's ok or if we're going to keep going
  1174. if(status_name == "NT_STATUS_OK" or status_name == "NT_STATUS_MORE_PROCESSING_REQUIRED") then
  1175. -- Parse the parameters
  1176. pos, andx_command, andx_reserved, andx_offset, action, security_blob_length = bin.unpack("<CCSSS", parameters)
  1177. if(security_blob_length == nil) then
  1178. return false, "SMB: ERROR: Ran off the end of SMB packet; likely due to server truncation [18]"
  1179. end
  1180. smb['is_guest'] = bit.band(action, 1)
  1181. -- Parse the data
  1182. pos, security_blob, os, lanmanager = bin.unpack(string.format("<A%dzz", security_blob_length), data)
  1183. if(lanmanager == nil) then
  1184. return false, "SMB: ERROR: Ran off the end of SMB packet; likely due to server truncation [19]"
  1185. end
  1186. smb['os'] = os
  1187. smb['lanmanager'] = lanmanager
  1188. -- If it's ok, do a cleanup and return true
  1189. if(status_name == "NT_STATUS_OK") then
  1190. -- Check if they're using an un-supported system
  1191. if(os == nil or lanmanager == nil) then
  1192. stdnse.print_debug(1, "SMB: WARNING: the server is using a non-standard SMB implementation; your mileage may vary (%s)", smb['ip'])
  1193. elseif(os == "Unix" or string.sub(lanmanager, 1, 5) == "Samba") then
  1194. stdnse.print_debug(1, "SMB: WARNING: the server appears to be Unix; your mileage may vary.")
  1195. end
  1196. -- Check if they were logged in as a guest
  1197. if(log_errors == nil or log_errors == true) then
  1198. if(smb['is_guest'] == 1) then
  1199. stdnse.print_debug(1, string.format("SMB: Extended 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)))
  1200. else
  1201. stdnse.print_debug(2, string.format("SMB: Extended login as %s\\%s succeeded", domain, stdnse.string_or_blank(username)))
  1202. end
  1203. end
  1204. -- Set the initial sequence number
  1205. smb['sequence'] = 1
  1206. return true
  1207. end -- Status is ok
  1208. end -- Should we parse the parameters/data?
  1209. until status_name ~= "NT_STATUS_MORE_PROCESSING_REQUIRED"
  1210. -- Display a message to the user, and try the next account
  1211. if(log_errors == nil or log_errors == true) then
  1212. stdnse.print_debug(1, "SMB: Extended login as %s\\%s failed (%s)", domain, stdnse.string_or_blank(username), status_name)
  1213. end
  1214. -- Reset the user id and security_blob
  1215. smb['uid'] = 0
  1216. -- Go to the next account
  1217. if(overrides == nil or overrides['username'] == nil) then
  1218. smbauth.next_account(smb['host'])
  1219. result, username, domain, password, password_hash, hash_type = smbauth.get_account(smb['host'])
  1220. else
  1221. result = false
  1222. end
  1223. end -- Loop over the accounts
  1224. if(log_errors == nil or log_errors == true) then
  1225. stdnse.print_debug(1, "SMB: ERROR: All logins failed, sorry it didn't work out!")
  1226. end
  1227. return false, status_name
  1228. end
  1229. --- Sends out SMB_COM_SESSION_SETUP_ANDX, which attempts to log a user in.
  1230. -- Sends the following:
  1231. -- * Negotiated parameters (multiplexed connections, virtual circuit, capabilities)
  1232. -- * Passwords (plaintext, unicode, lanman, ntlm, lmv2, ntlmv2, etc)
  1233. -- * Account name
  1234. -- * OS (I just send "Nmap")
  1235. -- * Native LAN Manager (no clue what that is, but it seems to be ignored)
  1236. --
  1237. -- Receives the following:
  1238. -- * User ID
  1239. -- * Server OS
  1240. --
  1241. --@param smb The SMB object associated with the connection
  1242. --@param overrides [optional] A table of overrides for username, domain, password, password_hash, and hash_type.
  1243. -- If any of these are given, it's used first. If they aren't, then Nmap parameters, Nmap registry entries,
  1244. -- guest, and NULL sessions are used.
  1245. --@param log_errors [optional] If set, will display login. Default: true.
  1246. --@return (status, result) If status is false, result is an error message. Otherwise, result is nil and the following
  1247. -- elements are added to the smb table:
  1248. -- * 'uid' The UserID for the session
  1249. -- * 'is_guest' If set, the username wasn't found so the user was automatically logged in as the guest account
  1250. -- * 'os' The operating system
  1251. -- * 'lanmanager' The servers's LAN Manager
  1252. function start_session(smb, overrides, log_errors)
  1253. if(smb['extended_security'] == true) then
  1254. return start_session_extended(smb, log_errors, overrides)
  1255. else
  1256. return start_session_basic(smb, log_errors, overrides)
  1257. end
  1258. end
  1259. --- Sends out <code>SMB_COM_SESSION_TREE_CONNECT_ANDX</code>, which attempts to connect to a share.
  1260. -- Sends the following:
  1261. -- * Password (for share-level security, which we don't support)
  1262. -- * Share name
  1263. -- * Share type (or "?????" if it's unknown, that's what we do)
  1264. --
  1265. -- Receives the following:
  1266. -- * Tree ID
  1267. --
  1268. --@param smb The SMB object associated with the connection
  1269. --@param path The path to connect (eg, <code>"\\servername\C$"</code>)
  1270. --@param overrides [optional] Overrides for various fields
  1271. --@return (status, result) If status is false, result is an error message. Otherwise, result is a
  1272. -- table with the following elements:
  1273. -- * 'tid' The TreeID for the session
  1274. function tree_connect(smb, path, overrides)
  1275. local header, parameters, data, err, result
  1276. local pos
  1277. local header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, pid, mid
  1278. local andx_command, andx_reserved, andx_offset, action
  1279. -- Make sure we have overrides
  1280. overrides = overrides or {}
  1281. header = smb_encode_header(smb, command_codes['SMB_COM_TREE_CONNECT_ANDX'])
  1282. parameters = bin.pack("<CCSSS",
  1283. 0xFF, -- ANDX no further commands
  1284. 0x00, -- ANDX reserved
  1285. 0x0000, -- ANDX offset
  1286. (overrides['tree_connect_flags'] or 0x0000), -- flags
  1287. 0x0000 -- password length (for share-level security)
  1288. )
  1289. data = bin.pack("zz",
  1290. -- Share-level password
  1291. path, -- Path
  1292. (overrides['tree_type'] or "?????") -- Type of tree ("?????" = any)
  1293. )
  1294. -- Send the tree connect request
  1295. stdnse.print_debug(2, "SMB: Sending SMB_COM_TREE_CONNECT_ANDX")
  1296. result, err = smb_send(smb, header, parameters, data)
  1297. if(result == false) then
  1298. return false, err
  1299. end
  1300. -- Read the result
  1301. status, header, parameters, data = smb_read(smb)
  1302. if(status ~= true) then
  1303. return false, header
  1304. end
  1305. -- Check if we were allowed in
  1306. local uid, tid
  1307. pos, header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, tid, pid, uid, mid = bin.unpack("<CCCCCICSSlSSSSS", header)
  1308. if(mid == nil) then
  1309. return false, "SMB: ERROR: Ran off the end of SMB packet; likely due to server truncation [20]"
  1310. end
  1311. if(status ~= 0) then
  1312. return false, get_status_name(status)
  1313. end
  1314. if(tid == 0 or tonumber(tid) == 0) then
  1315. return false, "SMB: ERROR: Server didn't establish a proper tree connection (likely an embedded system)"
  1316. end
  1317. smb['tid'] = tid
  1318. return true
  1319. end
  1320. --- Disconnects a tree session. Should be called before logging off and disconnecting.
  1321. --@param smb The SMB object associated with the connection
  1322. --@return (status, result) If status is false, result is an error message. If status is true,
  1323. -- the disconnect was successful.
  1324. function tree_disconnect(smb)
  1325. local header
  1326. local header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, pid, mid
  1327. header = smb_encode_header(smb, command_codes['SMB_COM_TREE_DISCONNECT'])
  1328. -- Send the tree disconnect request
  1329. stdnse.print_debug(2, "SMB: Sending SMB_COM_TREE_DISCONNECT")
  1330. local result, err = smb_send(smb, header, "", "")
  1331. if(result == false) then
  1332. return false, err
  1333. end
  1334. -- Read the result
  1335. local status, header, parameters, data = smb_read(smb)
  1336. if(status ~= true) then
  1337. return false, header
  1338. end
  1339. -- Check if there was an error
  1340. local uid, tid, pos
  1341. pos, header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, tid, pid, uid, mid = bin.unpack("<CCCCCICSSlSSSSS", header)
  1342. if(mid == nil) then
  1343. return false, "SMB: ERROR: Ran off the end of SMB packet; likely due to server truncation [21]"
  1344. end
  1345. if(status ~= 0) then
  1346. return false, get_status_name(status)
  1347. end
  1348. smb['tid'] = 0
  1349. return true
  1350. end
  1351. ---Logs off the current user. Strictly speaking this isn't necessary, but it's the polite thing to do.
  1352. --
  1353. --@param smb The SMB object associated with the connection
  1354. --@return (status, result) If statis is false, result is an error message. If status is true,
  1355. -- the logoff was successful.
  1356. function logoff(smb)
  1357. local header, parameters, data
  1358. local header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, pid, mid
  1359. header = smb_encode_header(smb, command_codes['SMB_COM_LOGOFF_ANDX'])
  1360. -- Parameters are a blank ANDX block
  1361. parameters = bin.pack("<CCS",
  1362. 0xFF, -- ANDX no further commands
  1363. 0x00, -- ANDX reserved
  1364. 0x0000 -- ANDX offset
  1365. )
  1366. -- Send the tree disconnect request
  1367. stdnse.print_debug(2, "SMB: Sending SMB_COM_LOGOFF_ANDX")
  1368. local result, err = smb_send(smb, header, parameters, "")
  1369. if(result == false) then
  1370. return false, err
  1371. end
  1372. -- Read the result
  1373. status, header, parameters, data = smb_read(smb)
  1374. if(status ~= true) then
  1375. return false, header
  1376. end
  1377. -- Reset session variables (note: this has to come after the smb_read(), otherwise the message signatures cause a problem
  1378. smb['uid'] = 0
  1379. smb['sequence'] = -1
  1380. smb['mac_key'] = nil
  1381. -- Check if there was an error
  1382. local uid, tid, pos
  1383. pos, header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, tid, pid, uid, mid = bin.unpack("<CCCCCICSSlSSSSS", header)
  1384. if(mid == nil) then
  1385. return false, "SMB: ERROR: Ran off the end of SMB packet; likely due to server truncation [22]"
  1386. end
  1387. if(status == 0xc0000022) then
  1388. stdnse.print_debug(1, "SMB: ERROR: Access was denied in 'logoff', indicating a problem with your message signatures")
  1389. return false, "SMB: ERROR: Access was denied in 'logoff', indicating a problem with your message signatures"
  1390. end
  1391. if(status ~= 0) then
  1392. return false, get_status_name(status)
  1393. end
  1394. return true
  1395. end
  1396. --- This sends a SMB request to open or create a file.
  1397. -- Most of the parameters I pass here are used directly from a packetlog, especially the various permissions fields and flags.
  1398. -- I might make this more adjustable in the future, but this has been working for me.
  1399. --
  1400. --@param smb The SMB object associated with the connection
  1401. --@param path The path of the file or pipe to open
  1402. --@param overrides [optional] Overrides for various fields
  1403. --@return (status, result) If status is false, result is an error message. Otherwise, result is a table
  1404. -- containing a lot of different elements, the most important one being 'fid', the handle to the opened file.
  1405. function create_file(smb, path, overrides)
  1406. local header, parameters, data
  1407. local pos
  1408. local header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, pid, mid
  1409. local andx_command, andx_reserved, andx_offset
  1410. local oplock_level, fid, create_action, created, last_access, last_write, last_change, attributes, allocation_size, end_of_file, filetype, ipc_state, is_directory
  1411. -- Make sure we have overrides
  1412. overrides = overrides or {}
  1413. header = smb_encode_header(smb, command_codes['SMB_COM_NT_CREATE_ANDX'])
  1414. parameters = bin.pack("<CCSCSIIILIIIIIC",
  1415. 0xFF, -- ANDX no further commands
  1416. 0x00, -- ANDX reserved
  1417. 0x0000, -- ANDX offset
  1418. 0x00, -- Reserved
  1419. string.len(path), -- Path length
  1420. (overrides['file_create_flags'] or 0x00000016), -- Create flags
  1421. (overrides['file_create_root_fid'] or 0x00000000), -- Root FID
  1422. (overrides['file_create_access_mask'] or 0x02000000), -- Access mask
  1423. (overrides['file_create_allocation_size'] or 0x0000000000000000), -- Allocation size
  1424. (overrides['file_create_attributes'] or 0x00000000), -- File attributes
  1425. (overrides['file_create_share_attributes'] or 0x00000007), -- Share attributes
  1426. (overrides['file_create_disposition'] or 0x00000000), -- Disposition
  1427. (overrides['file_create_options'] or 0x00000000), -- Create options
  1428. (overrides['file_create_impersonation'] or 0x00000002), -- Impersonation
  1429. (overrides['file_create_security_flags'] or 0x01) -- Security flags
  1430. )
  1431. data = bin.pack("z", path)
  1432. -- Send the create file
  1433. stdnse.print_debug(2, "SMB: Sending SMB_COM_NT_CREATE_ANDX")
  1434. local result, err = smb_send(smb, header, parameters, data)
  1435. if(result == false) then
  1436. return false, err
  1437. end
  1438. -- Read the result
  1439. status, header, parameters, data = smb_read(smb, false)
  1440. if(status ~= true) then
  1441. return false, header
  1442. end
  1443. -- Check if we were allowed in
  1444. local uid, tid
  1445. pos, header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, tid, pid, uid, mid = bin.unpack("<CCCCCICSSlSSSSS", header)
  1446. if(mid == nil) then
  1447. return false, "SMB: ERROR: Ran off the end of SMB packet; likely due to server truncation [23]"
  1448. end
  1449. if(status ~= 0) then
  1450. return false, get_status_name(status)
  1451. end
  1452. -- Parse the parameters
  1453. 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)
  1454. if(is_directory == nil) then
  1455. return false, "SMB: ERROR: Ran off the end of SMB packet; likely due to server truncation [24]"
  1456. end
  1457. -- Fill in the smb table
  1458. smb['oplock_level'] = oplock_level
  1459. smb['fid'] = fid
  1460. smb['create_action'] = create_action
  1461. smb['created'] = created
  1462. smb['last_access'] = last_access
  1463. smb['last_write'] = last_write
  1464. smb['last_change'] = last_change
  1465. smb['attributes'] = attributes
  1466. smb['allocation_size'] = allocation_size
  1467. smb['end_of_file'] = end_of_file
  1468. smb['filetype'] = filetype
  1469. smb['ipc_state'] = ipc_state
  1470. smb['is_directory'] = is_directory
  1471. return true
  1472. end
  1473. --- This sends a SMB request to read from a file (or a pipe).
  1474. --
  1475. --@param smb The SMB object associated with the connection
  1476. --@param offset The offset to read from (ignored if it's a pipe)
  1477. --@param count The maximum number of bytes to read
  1478. --@return (status, result) If status is false, result is an error message. Otherwise, result is a table
  1479. -- containing a lot of different elements.
  1480. function read_file(smb, offset, count)
  1481. local header, parameters, data
  1482. local pos
  1483. local header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, pid, mid
  1484. local andx_command, andx_reserved, andx_offset
  1485. local remaining, data_compaction_mode, reserved_1, data_length_low, data_offset, data_length_high, reserved_2, reserved_3
  1486. local response = {}
  1487. header = smb_encode_header(smb, command_codes['SMB_COM_READ_ANDX'])
  1488. parameters = bin.pack("<CCSSISSISI",
  1489. 0xFF, -- ANDX no further commands
  1490. 0x00, -- ANDX reserved
  1491. 0x0000, -- ANDX offset
  1492. smb['fid'], -- FID
  1493. offset, -- Offset
  1494. count, -- Max count low
  1495. count, -- Min count
  1496. 0xFFFFFFFF, -- Reserved
  1497. 0, -- Remaining
  1498. 0x00000000 -- High offset
  1499. )
  1500. data = ""
  1501. -- Send the create file
  1502. stdnse.print_debug(2, "SMB: Sending SMB_COM_READ_ANDX")
  1503. local result, err = smb_send(smb, header, parameters, data)
  1504. if(result == false) then
  1505. return false, err
  1506. end
  1507. -- Read the result
  1508. status, header, parameters, data = smb_read(smb)
  1509. if(status ~= true) then
  1510. return false, header
  1511. end
  1512. -- Check if we were allowed in
  1513. local uid, tid
  1514. pos, header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, tid, pid, uid, mid = bin.unpack("<CCCCCICSSlSSSSS", header)
  1515. if(mid == nil) then
  1516. return false, "SMB: ERROR: Ran off the end of SMB packet; likely due to server truncation [25]"
  1517. end
  1518. if(status ~= 0) then
  1519. return false, get_status_name(status)
  1520. end
  1521. -- Parse the parameters
  1522. 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)
  1523. if(reserved_3 == nil) then
  1524. return false, "SMB: ERROR: Ran off the end of SMB packet; likely due to server truncation [26]"
  1525. end
  1526. response['remaining'] = remaining
  1527. response['data_length'] = bit.bor(data_length_low, bit.lshift(data_length_high, 16))
  1528. -- data_start is the offset of the beginning of the data section -- we use this to calculate where the read data lives
  1529. if(response['data_length'] == 0) then
  1530. response['data'] = 0
  1531. else
  1532. local data_start = #header + 1 + #parameters + 2
  1533. if(data_offset < data_start) then
  1534. return false, "SMB: Start of data isn't in data section"
  1535. end
  1536. -- Figure out the offset into the data section
  1537. data_offset = data_offset - data_start
  1538. -- Make sure we don't run off the edge of the packet
  1539. if(data_offset + response['data_length'] > #data) then
  1540. return false, "SMB: Data returned runs off the end of the packet"
  1541. end
  1542. -- Pull the data string out of the data
  1543. response['data'] = string.sub(data, data_offset + 1, data_offset + response['data_length'])
  1544. end
  1545. return true, response
  1546. end
  1547. --- This sends a SMB request to write to a file (or a pipe).
  1548. --
  1549. --@param smb The SMB object associated with the connection
  1550. --@param write_data The data to write
  1551. --@param offset The offset to write it to (ignored for pipes)
  1552. --@return (status, result) If status is false, result is an error message. Otherwise, result is a table
  1553. -- containing a lot of different elements, the most important one being 'fid', the handle to the opened file.
  1554. function write_file(smb, write_data, offset)
  1555. local header, parameters, data
  1556. local pos
  1557. local header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, pid, mid
  1558. local andx_command, andx_reserved, andx_offset
  1559. local response = {}
  1560. header = smb_encode_header(smb, command_codes['SMB_COM_WRITE_ANDX'])
  1561. parameters = bin.pack("<CCSSIISSSSSI",
  1562. 0xFF, -- ANDX no further commands
  1563. 0x00, -- ANDX reserved
  1564. 0x0000, -- ANDX offset
  1565. smb['fid'], -- FID
  1566. offset, -- Offset
  1567. 0xFFFFFFFF, -- Reserved
  1568. 0x0008, -- Write mode (Message start, don't write raw, don't return remaining, don't write through
  1569. #write_data,-- Remaining
  1570. 0x0000, -- Data length high
  1571. #write_data,-- Data length low -- TODO: set this properly (to the 2-byte value)
  1572. 0x003F, -- Data offset
  1573. 0x00000000 -- Data offset high
  1574. )
  1575. data = write_data
  1576. -- Send the create file
  1577. stdnse.print_debug(2, "SMB: Sending SMB_COM_WRITE_ANDX")
  1578. local result, err = smb_send(smb, header, parameters, data)
  1579. if(result == false) then
  1580. return false, err
  1581. end
  1582. -- Read the result
  1583. status, header, parameters, data = smb_read(smb)
  1584. if(status ~= true) then
  1585. return false, header
  1586. end
  1587. local uid, tid
  1588. -- Check if we were allowed in
  1589. pos, header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, tid, pid, uid, mid = bin.unpack("<CCCCCICSSlSSSSS", header)
  1590. if(mid == nil) then
  1591. return false, "SMB: ERROR: Ran off the end of SMB packet; likely due to server truncation [27]"
  1592. end
  1593. if(status ~= 0) then
  1594. return false, get_status_name(status)
  1595. end
  1596. -- Parse the parameters
  1597. local count_reserved, count_high, remaining, count_low
  1598. pos, andx_command, andx_reserved, andx_offset, count_low, remaining, count_high, count_reserved = bin.unpack("<CCSSSSS", parameters)
  1599. if(count_reserved == nil) then
  1600. return false, "SMB: ERROR: Ran off the end of SMB packet; likely due to server truncation [28]"
  1601. end
  1602. response['count_low'] = count_low
  1603. response['remaining'] = remaining
  1604. response['count_high'] = count_high
  1605. response['reserved'] = count_reserved
  1606. return true, response
  1607. end
  1608. --- This sends a SMB request to close a file (or a pipe).
  1609. --
  1610. --@param smb The SMB object associated with the connection
  1611. --@return (status, result) If status is false, result is an error message. Otherwise, result is undefined.
  1612. function close_file(smb)
  1613. local header, parameters, data
  1614. local pos
  1615. local header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, pid, mid
  1616. local andx_command, andx_reserved, andx_offset
  1617. local response = {}
  1618. header = smb_encode_header(smb, command_codes['SMB_COM_CLOSE'])
  1619. parameters = bin.pack("<SI",
  1620. smb['fid'], -- FID
  1621. 0xFFFFFFFF -- Last write (unspecified)
  1622. )
  1623. data = ""
  1624. -- Send the close file
  1625. stdnse.print_debug(2, "SMB: Sending SMB_CLOSE")
  1626. local result, err = smb_send(smb, header, parameters, data)
  1627. if(result == false) then
  1628. return false, err
  1629. end
  1630. -- Read the result
  1631. status, header, parameters, data = smb_read(smb)
  1632. if(status ~= true) then
  1633. return false, header
  1634. end
  1635. -- Check if the close was successful
  1636. local uid, tid
  1637. pos, header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, tid, pid, uid, mid = bin.unpack("<CCCCCICSSlSSSSS", header)
  1638. if(mid == nil) then
  1639. return false, "SMB: ERROR: Ran off the end of SMB packet; likely due to server truncation [27]"
  1640. end
  1641. if(status ~= 0) then
  1642. return false, get_status_name(status)
  1643. end
  1644. -- Close response has no parameters or data
  1645. return true, response
  1646. end
  1647. --- This sends a SMB request to delete a file (or a pipe).
  1648. --
  1649. --@param smb The SMB object associated with the connection
  1650. --@param path The path of the file to delete
  1651. --@return (status, result) If status is false, result is an error message. Otherwise, result is undefined.
  1652. function delete_file(smb, path)
  1653. local header, parameters, data
  1654. local pos
  1655. local header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, pid, mid
  1656. local andx_command, andx_reserved, andx_offset
  1657. header = smb_encode_header(smb, command_codes['SMB_COM_DELETE'])
  1658. parameters = bin.pack("<S",
  1659. 0x0027 -- Search attributes (0x27 = include read only, hidden, system, and archive)
  1660. )
  1661. data = bin.pack("<Cz",
  1662. 0x04, -- Ascii formatted filename
  1663. path)
  1664. -- Send the close file
  1665. stdnse.print_debug(2, "SMB: Sending SMB_CLOSE")
  1666. local result, err = smb_send(smb, header, parameters, data)
  1667. if(result == false) then
  1668. return false, err
  1669. end
  1670. -- Read the result
  1671. status, header, parameters, data = smb_read(smb)
  1672. if(status ~= true) then
  1673. return false, header
  1674. end
  1675. -- Check if the close was successful
  1676. local uid, tid
  1677. pos, header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, tid, pid, uid, mid = bin.unpack("<CCCCCICSSlSSSSS", header)
  1678. if(mid == nil) then
  1679. return false, "SMB: ERROR: Ran off the end of SMB packet; likely due to server truncation [27]"
  1680. end
  1681. if(status ~= 0) then
  1682. return false, get_status_name(status)
  1683. end
  1684. -- Close response has no parameters or data
  1685. return true
  1686. end
  1687. ---This is the core of making MSRPC calls. It sends out a MSRPC packet with the given parameters and data.
  1688. -- Don't confuse these parameters and data with SMB's concepts of parameters and data -- they are completely
  1689. -- different. In fact, these parameters and data are both sent in the SMB packet's 'data' section.
  1690. --
  1691. -- It is probably best to think of this as another protocol layer. This function will wrap SMB stuff around a
  1692. -- MSRPC call, make the call, then unwrap the SMB stuff from it before returning.
  1693. --
  1694. --@param smb The SMB object associated with the connection
  1695. --@param function_parameters The parameter data to pass to the function. This is untested, since none of the
  1696. -- transactions I've done have required parameters.
  1697. --@param function_data The data to send with the packet. This is basically the next protocol layer
  1698. --@param pipe [optional] The pipe to transact on. Default: "\PIPE\".
  1699. --@param no_setup [optional] If set, the 'setup' is set to 0 and some parameters are left off. This occurs while
  1700. -- using the LANMAN Remote API. Default: false.
  1701. --@return (status, result) If status is false, result is an error message. Otherwise, result is a table
  1702. -- containing 'parameters' and 'data', representing the parameters and data returned by the server.
  1703. function send_transaction_named_pipe(smb, function_parameters, function_data, pipe, no_setup)
  1704. local header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, pid, mid
  1705. local header, parameters, data
  1706. local parameter_offset = 0
  1707. local parameter_size = 0
  1708. local data_offset = 0
  1709. local data_size = 0
  1710. local total_word_count, total_data_count, reserved1, parameter_count, parameter_displacement, data_count, data_displacement, setup_count, reserved2
  1711. local response = {}
  1712. if(pipe == nil) then
  1713. pipe = "\\PIPE\\"
  1714. end
  1715. -- Header is 0x20 bytes long (not counting NetBIOS header).
  1716. header = smb_encode_header(smb, command_codes['SMB_COM_TRANSACTION']) -- 0x25 = SMB_COM_TRANSACTION
  1717. -- 0x20 for SMB header, 0x01 for parameters header, 0x20 for parameters length, 0x02 for data header, 0x07 for "\PIPE\"
  1718. if(function_parameters) then
  1719. parameter_offset = 0x20 + 0x01 + 0x20 + 0x02 + (#pipe + 1)
  1720. parameter_size = #function_parameters
  1721. end
  1722. if(function_data) then
  1723. data_offset = 0x20 + 0x01 + 0x20 + 0x02 + (#pipe + 1) + parameter_size
  1724. data_size = #function_data
  1725. end
  1726. -- Parameters are 0x20 bytes long.
  1727. parameters = bin.pack("<SSSSCCSISSSSS",
  1728. parameter_size, -- Total parameter count.
  1729. data_size, -- Total data count.
  1730. 0x0008, -- Max parameter count.
  1731. 0x3984, -- Max data count.
  1732. 0x00, -- Max setup count.
  1733. 0x00, -- Reserved.
  1734. 0x0000, -- Flags (0x0000 = 2-way transaction, don't disconnect TIDs).
  1735. 0x00001388, -- Timeout (0x00000000 = return immediately).
  1736. 0x0000, -- Reserved.
  1737. parameter_size, -- Parameter bytes.
  1738. parameter_offset, -- Parameter offset.
  1739. data_size, -- Data bytes.
  1740. data_offset -- Data offset.
  1741. )
  1742. if(no_setup) then
  1743. parameters = parameters .. bin.pack("<CC",
  1744. 0x00, -- Number of 'setup' words (none)
  1745. 0x00 -- Reserved.
  1746. )
  1747. else
  1748. parameters = parameters .. bin.pack("<CCSS",
  1749. 0x02, -- Number of 'setup' words
  1750. 0x00, -- Reserved.
  1751. 0x0026, -- Function to call.
  1752. smb['fid'] -- Handle to open file
  1753. )
  1754. end
  1755. data = bin.pack("<z", pipe)
  1756. data = data .. bin.pack("<I", 0) -- Padding
  1757. data = data .. (function_parameters or '')
  1758. data = data .. (function_data or '')
  1759. -- Send the transaction request
  1760. stdnse.print_debug(2, "SMB: Sending SMB_COM_TRANSACTION")
  1761. local result, err = smb_send(smb, header, parameters, data)
  1762. if(result == false) then
  1763. return false, err
  1764. end
  1765. -- Read the result
  1766. status, header, parameters, data = smb_read(smb)
  1767. if(status ~= true) then
  1768. return false, header
  1769. end
  1770. -- Check if it worked
  1771. local uid, tid, pos
  1772. pos, header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, tid, pid, uid, mid = bin.unpack("<CCCCCICSSlSSSSS", header)
  1773. if(mid == nil) then
  1774. return false, "SMB: ERROR: Ran off the end of SMB packet; likely due to server truncation [29]"
  1775. end
  1776. if(status ~= 0) then
  1777. if(status_names[status] == nil) then
  1778. return false, string.format("Unknown SMB error: 0x%08x\n", status)
  1779. else
  1780. return false, status_names[status]
  1781. end
  1782. end
  1783. -- Parse the parameters
  1784. 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)
  1785. if(reserved2 == nil) then
  1786. return false, "SMB: ERROR: Ran off the end of SMB packet; likely due to server truncation [30]"
  1787. end
  1788. -- Convert the parameter/data offsets into something more useful (the offset into the data section)
  1789. -- - 0x20 for the header, - 0x01 for the length.
  1790. parameter_offset = parameter_offset - 0x20 - 0x01 - string.len(parameters) - 0x02;
  1791. -- - 0x20 for the header, - 0x01 for parameter length, the parameter length, and - 0x02 for the data length.
  1792. data_offset = data_offset - 0x20 - 0x01 - string.len(parameters) - 0x02;
  1793. -- 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'.
  1794. function_parameters = string.sub(data, parameter_offset + 1, parameter_offset + parameter_count)
  1795. function_data = string.sub(data, data_offset + 1, data_offset + data_count)
  1796. response['parameters'] = function_parameters
  1797. response['data'] = function_data
  1798. return true, response
  1799. end
  1800. function send_transaction_waitnamedpipe(smb, priority, pipe)
  1801. local header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, pid, mid
  1802. local header, parameters, data
  1803. local parameter_offset, data_offset
  1804. local total_word_count, total_data_count, reserved1, parameter_count, parameter_offset, parameter_displacement, data_count, data_offset, data_displacement, setup_count, reserved2
  1805. local response = {}
  1806. local padding = ""
  1807. -- Header is 0x20 bytes long (not counting NetBIOS header).
  1808. header = smb_encode_header(smb, command_codes['SMB_COM_TRANSACTION']) -- 0x25 = SMB_COM_TRANSACTION
  1809. -- Parameters are 0x20 bytes long.
  1810. parameters = bin.pack("<SSSSCCSISSSSSCCSS",
  1811. 0, -- Total parameter count.
  1812. 0, -- Total data count.
  1813. 0x000, -- Max parameter count.
  1814. 0x400, -- Max data count.
  1815. 0x00, -- Max setup count.
  1816. 0x00, -- Reserved.
  1817. 0x0000, -- Flags (0x0000 = 2-way transaction, don't disconnect TIDs).
  1818. 30, -- Timeout (0x00000000 = return immediately).
  1819. 0x0000, -- Reserved.
  1820. 0, -- Parameter bytes.
  1821. 0, -- Parameter offset.
  1822. 0, -- Data bytes.
  1823. 0, -- Data offset.
  1824. 0x02, -- Number of 'setup' words (only ever seen '2').
  1825. 0x00, -- Reserved.
  1826. 0x0053, -- Function to call.
  1827. priority -- Handle to open file
  1828. )
  1829. while(((#pipe + 1 + #padding) % 4) ~= 0) do
  1830. padding = padding .. string.char(0)
  1831. end
  1832. data = bin.pack("<zA", pipe, padding);
  1833. -- Send the transaction request
  1834. stdnse.print_debug(2, "SMB: Sending SMB_COM_TRANSACTION (WaitNamedPipe)")
  1835. local result, err = smb_send(smb, header, parameters, data)
  1836. if(result == false) then
  1837. return false, err
  1838. end
  1839. -- Read the result
  1840. status, header, parameters, data = smb_read(smb)
  1841. if(status ~= true) then
  1842. return false, header
  1843. end
  1844. -- Check if it worked
  1845. local uid, tid, pos
  1846. pos, header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, tid, pid, uid, mid = bin.unpack("<CCCCCICSSlSSSSS", header)
  1847. if(mid == nil) then
  1848. return false, "SMB: ERROR: Ran off the end of SMB packet; likely due to server truncation [31]"
  1849. end
  1850. if(status ~= 0) then
  1851. if(status_names[status] == nil) then
  1852. return false, string.format("Unknown SMB error: 0x%08x\n", status)
  1853. else
  1854. return false, status_names[status]
  1855. end
  1856. end
  1857. -- Parse the parameters
  1858. 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)
  1859. if(reserved2 == nil) then
  1860. return false, "SMB: ERROR: Ran off the end of SMB packet; likely due to server truncation [32]"
  1861. end
  1862. return true, response
  1863. end
  1864. ---Upload a file from the local machine to the remote machine, on the given share.
  1865. --
  1866. --@param host The host object
  1867. --@param localfile The file on the local machine, relative to the nmap path
  1868. --@param share The share to upload it to (eg, C$).
  1869. --@param remotefile The remote file on the machine. It is relative to the share's root.
  1870. --@param overrides A table of override values that's passed to the smb functions.
  1871. --@param encoded Set to 'true' if the file is encoded (xor'ed with 0xFF), It will be decoded before upload. Default: false
  1872. --@return (status, err) If status is false, err is an error message. Otherwise, err is undefined.
  1873. require 'nsedebug'
  1874. function file_upload(host, localfile, share, remotefile, overrides, encoded)
  1875. local status, err, smbstate
  1876. local chunk = 1024
  1877. local filename = nmap.fetchfile(localfile)
  1878. if(filename == nil) then
  1879. return false, "Couldn't find the file"
  1880. end
  1881. -- Create the SMB session
  1882. status, smbstate = smb.start_ex(host, true, true, share, remotefile, nil, overrides)
  1883. if(status == false) then
  1884. return false, smbstate
  1885. end
  1886. local handle = io.open(filename, "r")
  1887. local data = handle:read(chunk)
  1888. local i = 0
  1889. while(data ~= nil and #data > 0) do
  1890. if(encoded) then
  1891. local new_data = ""
  1892. for j = 1, #data, 1 do
  1893. new_data = new_data .. string.char(bit.bxor(0xFF, string.byte(data, j)))
  1894. end
  1895. data = new_data
  1896. end
  1897. status, err = smb.write_file(smbstate, data, i)
  1898. if(status == false) then
  1899. smb.stop(smbstate)
  1900. return false, err
  1901. end
  1902. data = handle:read(chunk)
  1903. i = i + chunk
  1904. end
  1905. handle:close()
  1906. status, err = smb.close_file(smbstate)
  1907. if(status == false) then
  1908. smb.stop(smbstate)
  1909. return false, err
  1910. end
  1911. -- Stop the session
  1912. smb.stop(smbstate)
  1913. return true
  1914. end
  1915. ---Write given data to the remote machine on the given share. This is similar to <code>file_upload</code>, except the
  1916. -- data is given as a string, not a file.
  1917. --
  1918. --@param host The host object
  1919. --@param share The share to upload it to (eg, C$).
  1920. --@param remotefile The remote file on the machine. It is relative to the share's root.
  1921. --@param use_anonymous [optional] If set to 'true', test is done by the anonymous user rather than the current user.
  1922. --@return (status, err) If status is false, err is an error message. Otherwise, err is undefined.
  1923. function file_write(host, data, share, remotefile, use_anonymous)
  1924. local status, err, smbstate
  1925. local chunk = 1024
  1926. local overrides = nil
  1927. -- If anonymous is being used, create some overrides
  1928. if(use_anonymous) then
  1929. overrides = get_overrides_anonymous()
  1930. end
  1931. -- Create the SMB sessioan
  1932. status, smbstate = smb.start_ex(host, true, true, share, remotefile, nil, overrides)
  1933. if(status == false) then
  1934. return false, smbstate
  1935. end
  1936. local i = 1
  1937. while(i <= #data) do
  1938. local chunkdata = string.sub(data, i, i + chunk - 1)
  1939. status, err = smb.write_file(smbstate, chunkdata, i - 1)
  1940. if(status == false) then
  1941. smb.stop(smbstate)
  1942. return false, err
  1943. end
  1944. i = i + chunk
  1945. end
  1946. status, err = smb.close_file(smbstate)
  1947. if(status == false) then
  1948. smb.stop(smbstate)
  1949. return false, err
  1950. end
  1951. -- Stop the session
  1952. smb.stop(smbstate)
  1953. return true
  1954. end
  1955. ---Write given data to the remote machine on the given share. This is similar to <code>file_upload</code>, except the
  1956. -- data is given as a string, not a file.
  1957. --
  1958. --@param host The host object
  1959. --@param share The share to read it from (eg, C$).
  1960. --@param remotefile The remote file on the machine. It is relative to the share's root.
  1961. --@param use_anonymous [optional] If set to 'true', test is done by the anonymous user rather than the current user.
  1962. --@param overrides [optional] Override various fields in the SMB packets.
  1963. --@return (status, err) If status is false, err is an error message. Otherwise, err is undefined.
  1964. function file_read(host, share, remotefile, use_anonymous, overrides)
  1965. local status, err, smbstate
  1966. local result
  1967. local chunk = 1024
  1968. local read = ""
  1969. -- Make sure we got overrides
  1970. overrides = overrides or {}
  1971. -- If anonymous is being used, create some overrides
  1972. if(use_anonymous) then
  1973. overrides = get_overrides_anonymous(overrides)
  1974. end
  1975. -- Create the SMB sessioan
  1976. status, smbstate = smb.start_ex(host, true, true, share, remotefile, nil, overrides)
  1977. if(status == false) then
  1978. return false, smbstate
  1979. end
  1980. local i = 1
  1981. while true do
  1982. status, result = smb.read_file(smbstate, i - 1, chunk)
  1983. if(status == false) then
  1984. smb.stop(smbstate)
  1985. return false, result
  1986. end
  1987. if(result['data_length'] == 0) then
  1988. break
  1989. end
  1990. read = read .. result['data']
  1991. i = i + chunk
  1992. end
  1993. status, err = smb.close_file(smbstate)
  1994. if(status == false) then
  1995. smb.stop(smbstate)
  1996. return false, err
  1997. end
  1998. -- Stop the session
  1999. smb.stop(smbstate)
  2000. return true, read
  2001. end
  2002. ---Check how many files, in a given list, exist on the given share.
  2003. --
  2004. --@param host The host object
  2005. --@param share The share to read it from (eg, C$).
  2006. --@param fo;es A list of files to look for; it is relative to the share's root.
  2007. --@param overrides [optional] Override various fields in the SMB packets.
  2008. --@return status: A true/false value indicating success
  2009. --@return count: The number of files that existed, or an error message if status is 'false'
  2010. --@return files: A list of the files that existed.
  2011. function files_exist(host, share, files, overrides)
  2012. local status, smbstate, result, err
  2013. -- Make sure we got overrides
  2014. overrides = overrides or {}
  2015. -- We don't wan to be creating the files
  2016. overrides['file_create_disposition'] = 1
  2017. -- Create the SMB sessioan
  2018. status, smbstate = smb.start_ex(host, true, true, share, nil, nil, overrides)
  2019. if(status == false) then
  2020. return false, smbstate
  2021. end
  2022. local exist = 0
  2023. local list = {}
  2024. for _, file in ipairs(files) do
  2025. -- Try and open the file
  2026. status, result = create_file(smbstate, file, overrides)
  2027. -- If there was an error other than 'file already exists', return an error
  2028. if(not(status) and result ~= 'NT_STATUS_OBJECT_NAME_NOT_FOUND') then
  2029. return false, result
  2030. end
  2031. -- If the file existed, count it and close it
  2032. if(status) then
  2033. exist = exist + 1
  2034. table.insert(list, file)
  2035. status, err = smb.close_file(smbstate)
  2036. if(status == false) then
  2037. smb.stop(smbstate)
  2038. return false, err
  2039. end
  2040. end
  2041. end
  2042. -- Stop the session
  2043. smb.stop(smbstate)
  2044. return true, exist, list
  2045. end
  2046. ---Delete a file from the remote machine
  2047. --
  2048. --@param host The host object
  2049. --@param share The share to upload it to (eg, C$).
  2050. --@param remotefile The remote file on the machine. It is relative to the share's root. It can be a string, or an array.
  2051. --@return (status, err) If status is false, err is an error message. Otherwise, err is undefined.
  2052. function file_delete(host, share, remotefile)
  2053. local status, smbstate, err
  2054. -- Create the SMB session
  2055. status, smbstate = smb.start_ex(host, true, true, share)
  2056. if(status == false) then
  2057. return false, smbstate
  2058. end
  2059. -- Make sure the remotefile is always a table, to save on duplicate code
  2060. if(type(remotefile) ~= "table") then
  2061. remotefile = {remotefile}
  2062. end
  2063. for _, file in ipairs(remotefile) do
  2064. status, err = smb.delete_file(smbstate, file)
  2065. if(status == false) then
  2066. stdnse.print_debug(1, "SMB: Couldn't delete %s\\%s: %s", share, file, err)
  2067. if(err ~= 'NT_STATUS_OBJECT_NAME_NOT_FOUND') then
  2068. smb.stop(smbstate)
  2069. return false, err
  2070. end
  2071. end
  2072. end
  2073. -- Stop the session
  2074. smb.stop(smbstate)
  2075. return true
  2076. end
  2077. ---Determine whether or not the anonymous user has write access on the share. This is done by creating then
  2078. -- deleting a file.
  2079. --
  2080. --@param host The host object
  2081. --@param share The share to test
  2082. --@return (status, result) If status is false, result is an error message. The error message 'NT_STATUS_OBJECT_NAME_NOT_FOUND'
  2083. -- should be handled gracefully; it indicates that the share isn't a fileshare. Otherwise, result is a boolean value:
  2084. -- true if the file was successfully written, false if it was not.
  2085. function share_anonymous_can_write(host, share)
  2086. local filename, status, err
  2087. -- First, choose a filename. This should be random.
  2088. filename = "nmap-test-file"
  2089. -- Next, attempt to write to that file
  2090. status, err = file_write(host, string.rep("ABCDEFGHIJKLMNOPQRSTUVWXYZ", 10), share, filename, true)
  2091. if(status == false) then
  2092. if(err == "NT_STATUS_OBJECT_NAME_NOT_FOUND") then
  2093. return false, err
  2094. end
  2095. if(err == "NT_STATUS_ACCESS_DENIED") then
  2096. return true, false
  2097. end
  2098. return false, "Error writing test file to disk as anonymous: " .. err
  2099. end
  2100. -- Now the important part: delete it
  2101. status, err = file_delete(host, share, filename)
  2102. if(status == false) then
  2103. return false, "Error deleting test file as anonymous: " .. err
  2104. end
  2105. return true, true
  2106. end
  2107. ---Determine whether or not the current user has read or read/write access on the share. This is done by creating then
  2108. -- deleting a file.
  2109. --
  2110. --@param host The host object
  2111. --@param share The share to test
  2112. --@return (status, result) If status is false, result is an error message. The error message 'NT_STATUS_OBJECT_NAME_NOT_FOUND'
  2113. -- should be handled gracefully; it indicates that the share isn't a fileshare. Otherwise, result is a boolean value:
  2114. -- true if the file was successfully written, false if it was not.
  2115. function share_user_can_write(host, share)
  2116. local filename, status, err
  2117. -- First, choose a filename. This should be random.
  2118. filename = "nmap-test-file"
  2119. -- Next, attempt to write to that file
  2120. status, err = file_write(host, string.rep("ABCDEFGHIJKLMNOPQRSTUVWXYZ", 10), share, filename)
  2121. if(status == false) then
  2122. if(err == "NT_STATUS_OBJECT_NAME_NOT_FOUND") then
  2123. return false, err
  2124. end
  2125. if(err == "NT_STATUS_ACCESS_DENIED") then
  2126. return true, false
  2127. end
  2128. return false, "Error writing test file to disk as user: " .. err
  2129. end
  2130. -- Now the important part: delete it
  2131. status, err = file_delete(host, share, filename)
  2132. if(status == false) then
  2133. return false, "Error deleting test file as user: " .. err
  2134. end
  2135. return true, true
  2136. end
  2137. ---Check whether or not a share is accessible by the anonymous user. Assumes that <code>share_host_returns_proper_error</code>
  2138. -- has been called and returns <code>true</code>.
  2139. --
  2140. --@param host The host object
  2141. --@param share The share to test
  2142. --@return (status, result) If status is false, result is an error message. Otherwise, result is a boolean value:
  2143. -- true if anonymous access is permitted, false otherwise.
  2144. function share_anonymous_can_read(host, share)
  2145. local status, smbstate, err
  2146. local overrides = get_overrides_anonymous()
  2147. -- Begin the SMB session
  2148. status, smbstate = smb.start(host)
  2149. if(status == false) then
  2150. return false, smbstate
  2151. end
  2152. -- Negotiate the protocol
  2153. status, err = smb.negotiate_protocol(smbstate, overrides)
  2154. if(status == false) then
  2155. smb.stop(smbstate)
  2156. return false, err
  2157. end
  2158. -- Start up a null session
  2159. status, err = smb.start_session(smbstate, overrides)
  2160. if(status == false) then
  2161. smb.stop(smbstate)
  2162. return false, err
  2163. end
  2164. -- Attempt a connection to the share
  2165. status, err = smb.tree_connect(smbstate, share, overrides)
  2166. if(status == false) then
  2167. -- Stop the session
  2168. smb.stop(smbstate)
  2169. -- ACCESS_DENIED is the expected error: it tells us that the connection failed
  2170. if(err == 0xc0000022 or err == 'NT_STATUS_ACCESS_DENIED') then
  2171. return true, false
  2172. else
  2173. return false, err
  2174. end
  2175. end
  2176. smb.stop(smbstate)
  2177. return true, true
  2178. end
  2179. ---Check whether or not a share is accessible by the current user. Assumes that <code>share_host_returns_proper_error</code>
  2180. -- has been called and returns <code>true</code>.
  2181. --
  2182. --@param host The host object
  2183. --@param share The share to test
  2184. --@return (status, result) If status is false, result is an error message. Otherwise, result is a boolean value:
  2185. -- true if anonymous access is permitted, false otherwise.
  2186. function share_user_can_read(host, share)
  2187. local status, smbstate, err
  2188. local overrides = {}
  2189. -- Begin the SMB session
  2190. status, smbstate = smb.start(host)
  2191. if(status == false) then
  2192. return false, smbstate
  2193. end
  2194. -- Negotiate the protocol
  2195. status, err = smb.negotiate_protocol(smbstate, overrides)
  2196. if(status == false) then
  2197. smb.stop(smbstate)
  2198. return false, err
  2199. end
  2200. -- Start up a null session
  2201. status, err = smb.start_session(smbstate, overrides)
  2202. if(status == false) then
  2203. smb.stop(smbstate)
  2204. return false, err
  2205. end
  2206. -- Attempt a connection to the share
  2207. status, err = smb.tree_connect(smbstate, share, overrides)
  2208. if(status == false) then
  2209. -- Stop the session
  2210. smb.stop(smbstate)
  2211. -- ACCESS_DENIED is the expected error: it tells us that the connection failed
  2212. if(err == 0xc0000022 or err == 'NT_STATUS_ACCESS_DENIED') then
  2213. return true, false
  2214. else
  2215. return false, err
  2216. end
  2217. end
  2218. smb.stop(smbstate)
  2219. return true, true
  2220. end
  2221. ---Determine whether or not a host will accept any share name (I've seen this on certain systems; it's
  2222. -- bad, because it means we cannot tell whether or not a share exists).
  2223. --
  2224. --@param host The host object
  2225. --@param share The share to test
  2226. --@return (status, result) If status is false, result is an error message. Otherwise, result is a boolean value:
  2227. -- true if the file was successfully written, false if it was not.
  2228. function share_host_returns_proper_error(host)
  2229. local status, smbstate, err
  2230. local share = "nmap-share-test"
  2231. local overrides = get_overrides_anonymous()
  2232. -- Begin the SMB session
  2233. status, smbstate = smb.start(host)
  2234. if(status == false) then
  2235. return false, smbstate
  2236. end
  2237. -- Negotiate the protocol
  2238. status, err = smb.negotiate_protocol(smbstate, overrides)
  2239. if(status == false) then
  2240. smb.stop(smbstate)
  2241. return false, err
  2242. end
  2243. -- Start up a null session
  2244. status, err = smb.start_session(smbstate, overrides)
  2245. if(status == false) then
  2246. smb.stop(smbstate)
  2247. return false, err
  2248. end
  2249. -- Connect to the share
  2250. stdnse.print_debug(1, "SMB: Trying a random share to see if server responds properly: %s", share)
  2251. status, err = smb.tree_connect(smbstate, share, overrides)
  2252. if(status == false) then
  2253. -- If the error is NT_STATUS_ACCESS_DENIED (0xc0000022), that's bad -- we don't want non-existent shares
  2254. -- showing up as 'access denied'. Any other error is ok.
  2255. if(err == 0xc0000022 or err == 'NT_STATUS_ACCESS_DENIED') then
  2256. stdnse.print_debug(1, "SMB: Server doesn't return proper value for non-existent shares (returns ACCESS_DENIED)")
  2257. smb.stop(smbstate)
  2258. return true, false
  2259. end
  2260. else
  2261. -- If we were actually able to connect to this share, then there's probably a serious issue
  2262. stdnse.print_debug(1, "SMB: Server doesn't return proper value for non-existent shares (accepts the connection)")
  2263. smb.stop(smbstate)
  2264. return true, false
  2265. end
  2266. smb.stop(smbstate)
  2267. return true, true
  2268. end
  2269. ---Get all the details we can about the share. These details are stored in a table and returned.
  2270. --
  2271. --@param host The host object.
  2272. --@param shares An array of shares to check.
  2273. --@return (status, result) If status is false, result is an error message. Otherwise, result is a boolean value:
  2274. -- true if the file was successfully written, false if it was not.
  2275. function share_get_details(host, share)
  2276. local smbstate, status, result
  2277. local i
  2278. local details = {}
  2279. -- Save the name
  2280. details['name'] = share
  2281. -- Check if the current user can read the share
  2282. stdnse.print_debug(1, "SMB: Checking if share %s can be read by the current user", share)
  2283. status, result = share_user_can_read(host, share)
  2284. if(status == false) then
  2285. return false, result
  2286. end
  2287. details['user_can_read'] = result
  2288. -- Check if the anonymous reader can read the share
  2289. stdnse.print_debug(1, "SMB: Checking if share %s can be read by the anonymous user", share)
  2290. status, result = share_anonymous_can_read(host, share)
  2291. if(status == false) then
  2292. return false, result
  2293. end
  2294. details['anonymous_can_read'] = result
  2295. -- Check if the current user can write to the share
  2296. stdnse.print_debug(1, "SMB: Checking if share %s can be written by the current user", share)
  2297. status, result = share_user_can_write(host, share)
  2298. if(status == false) then
  2299. if(result == "NT_STATUS_OBJECT_NAME_NOT_FOUND") then
  2300. details['user_can_write'] = "NT_STATUS_OBJECT_NAME_NOT_FOUND"
  2301. else
  2302. return false, result
  2303. end
  2304. end
  2305. details['user_can_write'] = result
  2306. -- Check if the anonymous user can write to the share
  2307. stdnse.print_debug(1, "SMB: Checking if share %s can be written by the anonymous user", share)
  2308. status, result = share_anonymous_can_write(host, share)
  2309. if(status == false) then
  2310. if(result == "NT_STATUS_OBJECT_NAME_NOT_FOUND") then
  2311. details['anonymous_can_write'] = "NT_STATUS_OBJECT_NAME_NOT_FOUND"
  2312. else
  2313. return false, result
  2314. end
  2315. end
  2316. details['anonymous_can_write'] = result
  2317. -- Try and get full details about the share
  2318. status, result = msrpc.get_share_info(host, share)
  2319. if(status == false) then
  2320. -- We don't stop for this error (it's pretty common since administive privileges are required here)
  2321. stdnse.print_debug(1, "SMB: Failed to get share info for %s: %s", share, result)
  2322. details['details'] = result
  2323. else
  2324. -- Process the result a bit
  2325. result = result['info']
  2326. if(result['max_users'] == 0xFFFFFFFF) then
  2327. result['max_users'] = "<unlimited>"
  2328. end
  2329. details['details'] = result
  2330. end
  2331. return true, details
  2332. end
  2333. ---Retrieve a list of fileshares, along with any details that could be pulled. This is the core of smb-enum-shares.nse, but
  2334. -- can also be used by any script that needs to find an open share.
  2335. --
  2336. -- In the best care, the shares are determined by calling <code>msrpc.enum_shares</code>, and information is gathered by calling
  2337. -- <code>msrpc.get_share_info</code>. These require a certain level of access, though, so as a fallback, a pre-programmed list of
  2338. -- shares is used, and these are verified by attempting a connection.
  2339. --
  2340. --@param host The host object.
  2341. --@return (status, result, extra) If status is false, result is an error message. Otherwise, result is an array of shares with as much
  2342. -- detail as we could get. If extra isn't nil, it is set to extra information that should be displayed (such as a warning).
  2343. function share_get_list(host)
  2344. local status, result
  2345. local enum_status
  2346. local extra = ""
  2347. local shares = {}
  2348. local share_details = {}
  2349. -- Try and do this the good way, make a MSRPC call to get the shares
  2350. stdnse.print_debug(1, "SMB: Attempting to log into the system to enumerate shares")
  2351. enum_status, shares = msrpc.enum_shares(host)
  2352. -- If that failed, try doing it with brute force. This almost certainly won't find everything, but it's the
  2353. -- best we can do.
  2354. if(enum_status == false) then
  2355. stdnse.print_debug(1, "SMB: Enumerating shares failed, guessing at common ones (%s)", shares)
  2356. extra = string.format("ERROR: Enumerating shares failed, guessing at common ones (%s)", shares)
  2357. -- Take some common share names I've seen (thanks to Brandon Enright for most of these, except the last few)
  2358. shares = {"IPC$", "ADMIN$", "TEST", "TEST$", "HOME", "HOME$", "PUBLIC", "PRINT", "PRINT$", "GROUPS", "USERS", "MEDIA", "SOFTWARE", "XSERVE", "NETLOGON", "INFO", "PROGRAMS", "FILES", "WWW", "STMP", "TMP", "DATA", "BACKUP", "DOCS", "HD", "WEBSERVER", "WEB DOCUMENTS", "SHARED", "DESKTOP", "MY DOCUMENTS", "PORN", "PRON", "PR0N"}
  2359. -- Try every alphabetic share, with and without a trailing '$'
  2360. for i = string.byte("A", 1), string.byte("Z", 1), 1 do
  2361. shares[#shares + 1] = string.char(i)
  2362. shares[#shares + 1] = string.char(i) .. "$"
  2363. end
  2364. else
  2365. stdnse.print_debug(1, "SMB: Found %d shares, will attempt to find more information", #shares)
  2366. end
  2367. -- Sort the shares
  2368. table.sort(shares)
  2369. -- Ensure that the server returns the proper error message
  2370. status, result = share_host_returns_proper_error(host)
  2371. if(status == false) then
  2372. return false, result
  2373. end
  2374. if(status == true and result == false) then
  2375. return false, "Server doesn't return proper value for non-existent shares; can't enumerate shares"
  2376. end
  2377. -- Get more information on each share
  2378. for i = 1, #shares, 1 do
  2379. local status, result
  2380. stdnse.print_debug(1, "SMB: Getting information for share: %s", shares[i])
  2381. status, result = smb.share_get_details(host, shares[i])
  2382. if(status == false and result == 'NT_STATUS_BAD_NETWORK_NAME') then
  2383. stdnse.print_debug(1, "SMB: Share doesn't exist: %s", shares[i])
  2384. elseif(status == false) then
  2385. stdnse.print_debug(1, "SMB: Error while getting share details: %s", result)
  2386. return false, result
  2387. else
  2388. -- Save the share details
  2389. table.insert(share_details, result)
  2390. end
  2391. end
  2392. return true, share_details, extra
  2393. end
  2394. ---Find a share that the current user can write to. Return it, along with its path. If no share could be found,
  2395. -- an error is returned. If the path cannot be determined, the returned path is nil.
  2396. --
  2397. --@param host The host object.
  2398. --@return (status, name, path, names) If status is false, result is an error message. Otherwise, name is the name of the share,
  2399. -- path is its path, if it could be determined, and names is a list of all writable shares.
  2400. function share_find_writable(host)
  2401. local i
  2402. local status, shares
  2403. local main_name, main_path
  2404. local names = {}
  2405. local writable = {}
  2406. status, shares = share_get_list(host)
  2407. if(status == false) then
  2408. return false, shares
  2409. end
  2410. for i = 1, #shares, 1 do
  2411. if(shares[i]['user_can_write'] == true) then
  2412. if(main_name == nil) then
  2413. main_name = shares[i]['name']
  2414. if(shares[i]['details'] ~= nil) then
  2415. main_path = shares[i]['details']['path']
  2416. end
  2417. end
  2418. table.insert(names, shares[i]['name'])
  2419. end
  2420. end
  2421. if(main_name == nil) then
  2422. return false, "Couldn't find a writable share!"
  2423. else
  2424. return true, main_name, main_path, names
  2425. end
  2426. end
  2427. --- 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>).
  2428. --@param os The numbered OS version.
  2429. --@return The actual name of the OS (or the same as the <code>os</code> parameter if no match was found).
  2430. function get_windows_version(os)
  2431. if(os == "Windows 5.0") then
  2432. return "Windows 2000"
  2433. elseif(os == "Windows 5.1")then
  2434. return "Windows XP"
  2435. end
  2436. return os
  2437. end
  2438. ---Retrieve information about the host's operating system. This should always be possible to call, as long as there isn't already
  2439. -- a SMB session established.
  2440. --
  2441. --@param host The host object
  2442. --@return (status, data) If status is true, data is a table of values; otherwise, data is an error message.
  2443. function get_os(host)
  2444. local state
  2445. local status, smbstate
  2446. local response = {}
  2447. -- Start up SMB
  2448. status, smbstate = smb.start_ex(host, true, true, nil, nil, true)
  2449. if(status == false) then
  2450. return false, smbstate
  2451. end
  2452. -- See if we actually got something
  2453. if(smbstate['os'] == nil and smbstate['lanmanager'] == nil) then
  2454. return false, "Server didn't return OS details"
  2455. end
  2456. -- Convert blank values to something useful
  2457. response['os'] = stdnse.string_or_blank(smbstate['os'], "Unknown")
  2458. response['lanmanager'] = stdnse.string_or_blank(smbstate['lanmanager'], "Unknown")
  2459. response['domain'] = stdnse.string_or_blank(smbstate['domain'], "Unknown")
  2460. response['server'] = stdnse.string_or_blank(smbstate['server'], "Unknown")
  2461. response['date'] = stdnse.string_or_blank(smbstate['date'], "Unknown")
  2462. response['timezone_str'] = stdnse.string_or_blank(smbstate['timezone_str'], "Unknown")
  2463. -- Kill SMB
  2464. smb.stop(smbstate)
  2465. return true, response
  2466. end
  2467. ---Basically a wrapper around <code>socket:get_info</code>, except that it also makes a SMB connection before calling the
  2468. -- <code>get_info</code> function. Returns the mac address as well, for convenience.
  2469. --
  2470. --@param host The host object
  2471. --@return status: true for successful, false otherwise.
  2472. --@return If status is true, the local ip address; otherwise, an error message.
  2473. --@return The local port (not really meaningful, since it'll change next time).
  2474. --@return The remote ip address.
  2475. --@return The report port.
  2476. --@return The mac address, if possible; nil otherwise.
  2477. function get_socket_info(host)
  2478. local status, lhost, lport, rhost, rport
  2479. local smbstate, socket
  2480. -- Start SMB (we need a socket to get the proper local ip
  2481. status, smbstate = smb.start_ex(host)
  2482. if(status == false) then
  2483. return false, smbstate
  2484. end
  2485. socket = smbstate['socket']
  2486. status, lhost, lport, rhost, rport = socket:get_info()
  2487. if(status == false) then
  2488. return false, lhost
  2489. end
  2490. -- Stop SMB
  2491. smb.stop(smbstate)
  2492. -- Get the mac in hex format, if possible
  2493. local lmac = nil
  2494. if(host.mac_addr_src) then
  2495. lmac = stdnse.tohex(host.mac_addr_src, {separator = ":"})
  2496. end
  2497. return true, lhost, lport, rhost, rport, lmac
  2498. end
  2499. ---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
  2500. -- 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,
  2501. -- I don't want it to be trivial to uniquely determine who it originated from.
  2502. --
  2503. -- TODO: At some point, I should re-do this function properly, with a method of hashing that's somewhat proven.
  2504. --
  2505. --@param host The host object
  2506. --@param extension [optional] The extension to add on the end of the file. Default: none.
  2507. --@param seed [optional] Some randomness on which to base the name. If you want to do multiple files, each with its
  2508. -- own uniqueish name, this can be used.
  2509. --@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.
  2510. function get_uniqueish_name(host, extension, seed)
  2511. local status
  2512. local lhost, lport, rhost, rport
  2513. if(type(host) == "table") then
  2514. status, lhost = get_socket_info(host)
  2515. else
  2516. lhost = host
  2517. end
  2518. -- Create our ultra-weak hash by using a simple xor/shift algorithm
  2519. -- I tested this, and in 255 tests, there were roughly 10 collisions. That's about what I'm looking for.
  2520. local hash = 0
  2521. local i
  2522. local str = lhost .. (seed or "") .. (extension or "") .. (nmap.registry.args.randomseed or "")
  2523. for i = 1, #str, 1 do
  2524. local chr = string.byte(string.sub(str, i, i), 1)
  2525. hash = bit.bxor(hash, chr)
  2526. hash = bit.bor(bit.lshift(hash, 3), bit.rshift(hash, 29))
  2527. hash = bit.bxor(hash, 3)
  2528. hash = bit.band(hash, 0xFFFFFFFF)
  2529. end
  2530. local response
  2531. if(extension) then
  2532. response = string.format("%x.%s", hash, extension)
  2533. else
  2534. response = string.format("%x", hash)
  2535. end
  2536. return true, response
  2537. end
  2538. ---Determines, as accurately as possible, whether or not an account is an administrator. If there is an error,
  2539. -- 'false' is simply returned.
  2540. function is_admin(host, username, domain, password, password_hash, hash_type)
  2541. local status, smbstate, err, result
  2542. local overrides = get_overrides(username, domain, password, password_hash, hash_type)
  2543. stdnse.print_debug("SMB: Checking if %s is an administrator", username)
  2544. status, smbstate = smb.start(host)
  2545. if(status == false) then
  2546. stdnse.print_debug("SMB; is_admin: Failed to start SMB: %s [%s]", smbstate, username)
  2547. smb.stop(smbstate)
  2548. return false
  2549. end
  2550. status, err = smb.negotiate_protocol(smbstate, overrides)
  2551. if(status == false) then
  2552. stdnse.print_debug("SMB; is_admin: Failed to negotiatie protocol: %s [%s]", err, username)
  2553. smb.stop(smbstate)
  2554. return false
  2555. end
  2556. status, err = smb.start_session(smbstate, overrides)
  2557. if(status == false) then
  2558. stdnse.print_debug("SMB; is_admin: Failed to start session %s [%s]", err, username)
  2559. smb.stop(smbstate)
  2560. return false
  2561. end
  2562. status, err = smb.tree_connect(smbstate, "IPC$", overrides)
  2563. if(status == false) then
  2564. stdnse.print_debug("SMB; is_admin: Failed to connect tree: %s [%s]", err, username)
  2565. smb.stop(smbstate)
  2566. return false
  2567. end
  2568. status, err = smb.create_file(smbstate, msrpc.SRVSVC_PATH, overrides)
  2569. if(status == false) then
  2570. stdnse.print_debug("SMB; is_admin: Failed to create file: %s [%s]", err, username)
  2571. smb.stop(smbstate)
  2572. return false
  2573. end
  2574. status, err = msrpc.bind(smbstate, msrpc.SRVSVC_UUID, msrpc.SRVSVC_VERSION, nil)
  2575. if(status == false) then
  2576. stdnse.print_debug("SMB; is_admin: Failed to bind: %s [%s]", err, username)
  2577. smb.stop(smbstate)
  2578. return false
  2579. end
  2580. -- Call netservergetstatistics for 'server'
  2581. status, err = msrpc.srvsvc_netservergetstatistics(smbstate, host.ip)
  2582. if(status == false) then
  2583. stdnse.print_debug("SMB; is_admin: Couldn't get server stats (may be normal): %s [%s]", err, username)
  2584. smb.stop(smbstate)
  2585. return false
  2586. end
  2587. smb.stop(smbstate)
  2588. return true
  2589. end
  2590. command_codes =
  2591. {
  2592. SMB_COM_CREATE_DIRECTORY = 0x00,
  2593. SMB_COM_DELETE_DIRECTORY = 0x01,
  2594. SMB_COM_OPEN = 0x02,
  2595. SMB_COM_CREATE = 0x03,
  2596. SMB_COM_CLOSE = 0x04,
  2597. SMB_COM_FLUSH = 0x05,
  2598. SMB_COM_DELETE = 0x06,
  2599. SMB_COM_RENAME = 0x07,
  2600. SMB_COM_QUERY_INFORMATION = 0x08,
  2601. SMB_COM_SET_INFORMATION = 0x09,
  2602. SMB_COM_READ = 0x0A,
  2603. SMB_COM_WRITE = 0x0B,
  2604. SMB_COM_LOCK_BYTE_RANGE = 0x0C,
  2605. SMB_COM_UNLOCK_BYTE_RANGE = 0x0D,
  2606. SMB_COM_CREATE_TEMPORARY = 0x0E,
  2607. SMB_COM_CREATE_NEW = 0x0F,
  2608. SMB_COM_CHECK_DIRECTORY = 0x10,
  2609. SMB_COM_PROCESS_EXIT = 0x11,
  2610. SMB_COM_SEEK = 0x12,
  2611. SMB_COM_LOCK_AND_READ = 0x13,
  2612. SMB_COM_WRITE_AND_UNLOCK = 0x14,
  2613. SMB_COM_READ_RAW = 0x1A,
  2614. SMB_COM_READ_MPX = 0x1B,
  2615. SMB_COM_READ_MPX_SECONDARY = 0x1C,
  2616. SMB_COM_WRITE_RAW = 0x1D,
  2617. SMB_COM_WRITE_MPX = 0x1E,
  2618. SMB_COM_WRITE_MPX_SECONDARY = 0x1F,
  2619. SMB_COM_WRITE_COMPLETE = 0x20,
  2620. SMB_COM_QUERY_SERVER = 0x21,
  2621. SMB_COM_SET_INFORMATION2 = 0x22,
  2622. SMB_COM_QUERY_INFORMATION2 = 0x23,
  2623. SMB_COM_LOCKING_ANDX = 0x24,
  2624. SMB_COM_TRANSACTION = 0x25,
  2625. SMB_COM_TRANSACTION_SECONDARY = 0x26,
  2626. SMB_COM_IOCTL = 0x27,
  2627. SMB_COM_IOCTL_SECONDARY = 0x28,
  2628. SMB_COM_COPY = 0x29,
  2629. SMB_COM_MOVE = 0x2A,
  2630. SMB_COM_ECHO = 0x2B,
  2631. SMB_COM_WRITE_AND_CLOSE = 0x2C,
  2632. SMB_COM_OPEN_ANDX = 0x2D,
  2633. SMB_COM_READ_ANDX = 0x2E,
  2634. SMB_COM_WRITE_ANDX = 0x2F,
  2635. SMB_COM_NEW_FILE_SIZE = 0x30,
  2636. SMB_COM_CLOSE_AND_TREE_DISC = 0x31,
  2637. SMB_COM_TRANSACTION2 = 0x32,
  2638. SMB_COM_TRANSACTION2_SECONDARY = 0x33,
  2639. SMB_COM_FIND_CLOSE2 = 0x34,
  2640. SMB_COM_FIND_NOTIFY_CLOSE = 0x35,
  2641. SMB_COM_TREE_CONNECT = 0x70,
  2642. SMB_COM_TREE_DISCONNECT = 0x71,
  2643. SMB_COM_NEGOTIATE = 0x72,
  2644. SMB_COM_SESSION_SETUP_ANDX = 0x73,
  2645. SMB_COM_LOGOFF_ANDX = 0x74,
  2646. SMB_COM_TREE_CONNECT_ANDX = 0x75,
  2647. SMB_COM_QUERY_INFORMATION_DISK = 0x80,
  2648. SMB_COM_SEARCH = 0x81,
  2649. SMB_COM_FIND = 0x82,
  2650. SMB_COM_FIND_UNIQUE = 0x83,
  2651. SMB_COM_FIND_CLOSE = 0x84,
  2652. SMB_COM_NT_TRANSACT = 0xA0,
  2653. SMB_COM_NT_TRANSACT_SECONDARY = 0xA1,
  2654. SMB_COM_NT_CREATE_ANDX = 0xA2,
  2655. SMB_COM_NT_CANCEL = 0xA4,
  2656. SMB_COM_NT_RENAME = 0xA5,
  2657. SMB_COM_OPEN_PRINT_FILE = 0xC0,
  2658. SMB_COM_WRITE_PRINT_FILE = 0xC1,
  2659. SMB_COM_CLOSE_PRINT_FILE = 0xC2,
  2660. SMB_COM_GET_PRINT_QUEUE = 0xC3,
  2661. SMB_COM_READ_BULK = 0xD8,
  2662. SMB_COM_WRITE_BULK = 0xD9,
  2663. SMB_COM_WRITE_BULK_DATA = 0xDA,
  2664. SMB_NO_FURTHER_COMMANDS = 0xFF
  2665. }
  2666. for i, v in pairs(command_codes) do
  2667. command_names[v] = i
  2668. end
  2669. status_codes =
  2670. {
  2671. NT_STATUS_OK = 0x0000,
  2672. NT_STATUS_WERR_BADFILE = 0x00000002,
  2673. NT_STATUS_WERR_ACCESS_DENIED = 0x00000005,
  2674. NT_STATUS_WERR_UNKNOWN_57 = 0x00000057,
  2675. NT_STATUS_WERR_INVALID_NAME = 0x0000007b,
  2676. NT_STATUS_WERR_UNKNOWN_LEVEL = 0x0000007c,
  2677. NT_STATUS_WERR_MORE_DATA = 0x000000ea,
  2678. NT_STATUS_NO_MORE_ITEMS = 0x00000103,
  2679. NT_STATUS_MORE_ENTRIES = 0x00000105,
  2680. NT_STATUS_SOME_NOT_MAPPED = 0x00000107,
  2681. NT_STATUS_SERVICE_REQUEST_TIMEOUT = 0x0000041D,
  2682. NT_STATUS_SERVICE_NO_THREAD = 0x0000041E,
  2683. NT_STATUS_SERVICE_DATABASE_LOCKED = 0x0000041F,
  2684. NT_STATUS_SERVICE_ALREADY_RUNNING = 0x00000420,
  2685. NT_STATUS_INVALID_SERVICE_ACCOUNT = 0x00000421,
  2686. NT_STATUS_SERVICE_DISABLED = 0x00000422,
  2687. NT_STATUS_CIRCULAR_DEPENDENCY = 0x00000423,
  2688. NT_STATUS_SERVICE_DOES_NOT_EXIST = 0x00000424,
  2689. NT_STATUS_SERVICE_CANNOT_ACCEPT_CTRL = 0x00000425,
  2690. NT_STATUS_SERVICE_NOT_ACTIVE = 0x00000426,
  2691. NT_STATUS_FAILED_SERVICE_CONTROLLER_CONNECT = 0x00000427,
  2692. NT_STATUS_EXCEPTION_IN_SERVICE = 0x00000428,
  2693. NT_STATUS_DATABASE_DOES_NOT_EXIST = 0x00000429,
  2694. NT_STATUS_SERVICE_SPECIFIC_ERROR = 0x0000042a,
  2695. NT_STATUS_PROCESS_ABORTED = 0x0000042b,
  2696. NT_STATUS_SERVICE_DEPENDENCY_FAIL = 0x0000042c,
  2697. NT_STATUS_SERVICE_LOGON_FAILED = 0x0000042d,
  2698. NT_STATUS_SERVICE_START_HANG = 0x0000042e,
  2699. NT_STATUS_INVALID_SERVICE_LOCK = 0x0000042f,
  2700. NT_STATUS_SERVICE_MARKED_FOR_DELETE = 0x00000430,
  2701. NT_STATUS_SERVICE_EXISTS = 0x00000431,
  2702. NT_STATUS_ALREADY_RUNNING_LKG = 0x00000432,
  2703. NT_STATUS_SERVICE_DEPENDENCY_DELETED = 0x00000433,
  2704. NT_STATUS_BOOT_ALREADY_ACCEPTED = 0x00000434,
  2705. NT_STATUS_SERVICE_NEVER_STARTED = 0x00000435,
  2706. NT_STATUS_DUPLICATE_SERVICE_NAME = 0x00000436,
  2707. NT_STATUS_DIFFERENT_SERVICE_ACCOUNT = 0x00000437,
  2708. NT_STATUS_CANNOT_DETECT_DRIVER_FAILURE = 0x00000438,
  2709. DOS_STATUS_UNKNOWN_ERROR = 0x00010001,
  2710. DOS_STATUS_NONSPECIFIC_ERROR = 0x00010002,
  2711. DOS_STATUS_DIRECTORY_NOT_FOUND = 0x00030001,
  2712. DOS_STATUS_ACCESS_DENIED = 0x00050001,
  2713. DOS_STATUS_INVALID_FID = 0x00060001,
  2714. DOS_STATUS_INVALID_NETWORK_NAME = 0x00060002,
  2715. NT_STATUS_BUFFER_OVERFLOW = 0x80000005,
  2716. NT_STATUS_UNSUCCESSFUL = 0xc0000001,
  2717. NT_STATUS_NOT_IMPLEMENTED = 0xc0000002,
  2718. NT_STATUS_INVALID_INFO_CLASS = 0xc0000003,
  2719. NT_STATUS_INFO_LENGTH_MISMATCH = 0xc0000004,
  2720. NT_STATUS_ACCESS_VIOLATION = 0xc0000005,
  2721. NT_STATUS_IN_PAGE_ERROR = 0xc0000006,
  2722. NT_STATUS_PAGEFILE_QUOTA = 0xc0000007,
  2723. NT_STATUS_INVALID_HANDLE = 0xc0000008,
  2724. NT_STATUS_BAD_INITIAL_STACK = 0xc0000009,
  2725. NT_STATUS_BAD_INITIAL_PC = 0xc000000a,
  2726. NT_STATUS_INVALID_CID = 0xc000000b,
  2727. NT_STATUS_TIMER_NOT_CANCELED = 0xc000000c,
  2728. NT_STATUS_INVALID_PARAMETER = 0xc000000d,
  2729. NT_STATUS_NO_SUCH_DEVICE = 0xc000000e,
  2730. NT_STATUS_NO_SUCH_FILE = 0xc000000f,
  2731. NT_STATUS_INVALID_DEVICE_REQUEST = 0xc0000010,
  2732. NT_STATUS_END_OF_FILE = 0xc0000011,
  2733. NT_STATUS_WRONG_VOLUME = 0xc0000012,
  2734. NT_STATUS_NO_MEDIA_IN_DEVICE = 0xc0000013,
  2735. NT_STATUS_UNRECOGNIZED_MEDIA = 0xc0000014,
  2736. NT_STATUS_NONEXISTENT_SECTOR = 0xc0000015,
  2737. NT_STATUS_MORE_PROCESSING_REQUIRED = 0xc0000016,
  2738. NT_STATUS_NO_MEMORY = 0xc0000017,
  2739. NT_STATUS_CONFLICTING_ADDRESSES = 0xc0000018,
  2740. NT_STATUS_NOT_MAPPED_VIEW = 0xc0000019,
  2741. NT_STATUS_UNABLE_TO_FREE_VM = 0xc000001a,
  2742. NT_STATUS_UNABLE_TO_DELETE_SECTION = 0xc000001b,
  2743. NT_STATUS_INVALID_SYSTEM_SERVICE = 0xc000001c,
  2744. NT_STATUS_ILLEGAL_INSTRUCTION = 0xc000001d,
  2745. NT_STATUS_INVALID_LOCK_SEQUENCE = 0xc000001e,
  2746. NT_STATUS_INVALID_VIEW_SIZE = 0xc000001f,
  2747. NT_STATUS_INVALID_FILE_FOR_SECTION = 0xc0000020,
  2748. NT_STATUS_ALREADY_COMMITTED = 0xc0000021,
  2749. NT_STATUS_ACCESS_DENIED = 0xc0000022,
  2750. NT_STATUS_BUFFER_TOO_SMALL = 0xc0000023,
  2751. NT_STATUS_OBJECT_TYPE_MISMATCH = 0xc0000024,
  2752. NT_STATUS_NONCONTINUABLE_EXCEPTION = 0xc0000025,
  2753. NT_STATUS_INVALID_DISPOSITION = 0xc0000026,
  2754. NT_STATUS_UNWIND = 0xc0000027,
  2755. NT_STATUS_BAD_STACK = 0xc0000028,
  2756. NT_STATUS_INVALID_UNWIND_TARGET = 0xc0000029,
  2757. NT_STATUS_NOT_LOCKED = 0xc000002a,
  2758. NT_STATUS_PARITY_ERROR = 0xc000002b,
  2759. NT_STATUS_UNABLE_TO_DECOMMIT_VM = 0xc000002c,
  2760. NT_STATUS_NOT_COMMITTED = 0xc000002d,
  2761. NT_STATUS_INVALID_PORT_ATTRIBUTES = 0xc000002e,
  2762. NT_STATUS_PORT_MESSAGE_TOO_LONG = 0xc000002f,
  2763. NT_STATUS_INVALID_PARAMETER_MIX = 0xc0000030,
  2764. NT_STATUS_INVALID_QUOTA_LOWER = 0xc0000031,
  2765. NT_STATUS_DISK_CORRUPT_ERROR = 0xc0000032,
  2766. NT_STATUS_OBJECT_NAME_INVALID = 0xc0000033,
  2767. NT_STATUS_OBJECT_NAME_NOT_FOUND = 0xc0000034,
  2768. NT_STATUS_OBJECT_NAME_COLLISION = 0xc0000035,
  2769. NT_STATUS_HANDLE_NOT_WAITABLE = 0xc0000036,
  2770. NT_STATUS_PORT_DISCONNECTED = 0xc0000037,
  2771. NT_STATUS_DEVICE_ALREADY_ATTACHED = 0xc0000038,
  2772. NT_STATUS_OBJECT_PATH_INVALID = 0xc0000039,
  2773. NT_STATUS_OBJECT_PATH_NOT_FOUND = 0xc000003a,
  2774. NT_STATUS_OBJECT_PATH_SYNTAX_BAD = 0xc000003b,
  2775. NT_STATUS_DATA_OVERRUN = 0xc000003c,
  2776. NT_STATUS_DATA_LATE_ERROR = 0xc000003d,
  2777. NT_STATUS_DATA_ERROR = 0xc000003e,
  2778. NT_STATUS_CRC_ERROR = 0xc000003f,
  2779. NT_STATUS_SECTION_TOO_BIG = 0xc0000040,
  2780. NT_STATUS_PORT_CONNECTION_REFUSED = 0xc0000041,
  2781. NT_STATUS_INVALID_PORT_HANDLE = 0xc0000042,
  2782. NT_STATUS_SHARING_VIOLATION = 0xc0000043,
  2783. NT_STATUS_QUOTA_EXCEEDED = 0xc0000044,
  2784. NT_STATUS_INVALID_PAGE_PROTECTION = 0xc0000045,
  2785. NT_STATUS_MUTANT_NOT_OWNED = 0xc0000046,
  2786. NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED = 0xc0000047,
  2787. NT_STATUS_PORT_ALREADY_SET = 0xc0000048,
  2788. NT_STATUS_SECTION_NOT_IMAGE = 0xc0000049,
  2789. NT_STATUS_SUSPEND_COUNT_EXCEEDED = 0xc000004a,
  2790. NT_STATUS_THREAD_IS_TERMINATING = 0xc000004b,
  2791. NT_STATUS_BAD_WORKING_SET_LIMIT = 0xc000004c,
  2792. NT_STATUS_INCOMPATIBLE_FILE_MAP = 0xc000004d,
  2793. NT_STATUS_SECTION_PROTECTION = 0xc000004e,
  2794. NT_STATUS_EAS_NOT_SUPPORTED = 0xc000004f,
  2795. NT_STATUS_EA_TOO_LARGE = 0xc0000050,
  2796. NT_STATUS_NONEXISTENT_EA_ENTRY = 0xc0000051,
  2797. NT_STATUS_NO_EAS_ON_FILE = 0xc0000052,
  2798. NT_STATUS_EA_CORRUPT_ERROR = 0xc0000053,
  2799. NT_STATUS_FILE_LOCK_CONFLICT = 0xc0000054,
  2800. NT_STATUS_LOCK_NOT_GRANTED = 0xc0000055,
  2801. NT_STATUS_DELETE_PENDING = 0xc0000056,
  2802. NT_STATUS_CTL_FILE_NOT_SUPPORTED = 0xc0000057,
  2803. NT_STATUS_UNKNOWN_REVISION = 0xc0000058,
  2804. NT_STATUS_REVISION_MISMATCH = 0xc0000059,
  2805. NT_STATUS_INVALID_OWNER = 0xc000005a,
  2806. NT_STATUS_INVALID_PRIMARY_GROUP = 0xc000005b,
  2807. NT_STATUS_NO_IMPERSONATION_TOKEN = 0xc000005c,
  2808. NT_STATUS_CANT_DISABLE_MANDATORY = 0xc000005d,
  2809. NT_STATUS_NO_LOGON_SERVERS = 0xc000005e,
  2810. NT_STATUS_NO_SUCH_LOGON_SESSION = 0xc000005f,
  2811. NT_STATUS_NO_SUCH_PRIVILEGE = 0xc0000060,
  2812. NT_STATUS_PRIVILEGE_NOT_HELD = 0xc0000061,
  2813. NT_STATUS_INVALID_ACCOUNT_NAME = 0xc0000062,
  2814. NT_STATUS_USER_EXISTS = 0xc0000063,
  2815. NT_STATUS_NO_SUCH_USER = 0xc0000064,
  2816. NT_STATUS_GROUP_EXISTS = 0xc0000065,
  2817. NT_STATUS_NO_SUCH_GROUP = 0xc0000066,
  2818. NT_STATUS_MEMBER_IN_GROUP = 0xc0000067,
  2819. NT_STATUS_MEMBER_NOT_IN_GROUP = 0xc0000068,
  2820. NT_STATUS_LAST_ADMIN = 0xc0000069,
  2821. NT_STATUS_WRONG_PASSWORD = 0xc000006a,
  2822. NT_STATUS_ILL_FORMED_PASSWORD = 0xc000006b,
  2823. NT_STATUS_PASSWORD_RESTRICTION = 0xc000006c,
  2824. NT_STATUS_LOGON_FAILURE = 0xc000006d,
  2825. NT_STATUS_ACCOUNT_RESTRICTION = 0xc000006e,
  2826. NT_STATUS_INVALID_LOGON_HOURS = 0xc000006f,
  2827. NT_STATUS_INVALID_WORKSTATION = 0xc0000070,
  2828. NT_STATUS_PASSWORD_EXPIRED = 0xc0000071,
  2829. NT_STATUS_ACCOUNT_DISABLED = 0xc0000072,
  2830. NT_STATUS_NONE_MAPPED = 0xc0000073,
  2831. NT_STATUS_TOO_MANY_LUIDS_REQUESTED = 0xc0000074,
  2832. NT_STATUS_LUIDS_EXHAUSTED = 0xc0000075,
  2833. NT_STATUS_INVALID_SUB_AUTHORITY = 0xc0000076,
  2834. NT_STATUS_INVALID_ACL = 0xc0000077,
  2835. NT_STATUS_INVALID_SID = 0xc0000078,
  2836. NT_STATUS_INVALID_SECURITY_DESCR = 0xc0000079,
  2837. NT_STATUS_PROCEDURE_NOT_FOUND = 0xc000007a,
  2838. NT_STATUS_INVALID_IMAGE_FORMAT = 0xc000007b,
  2839. NT_STATUS_NO_TOKEN = 0xc000007c,
  2840. NT_STATUS_BAD_INHERITANCE_ACL = 0xc000007d,
  2841. NT_STATUS_RANGE_NOT_LOCKED = 0xc000007e,
  2842. NT_STATUS_DISK_FULL = 0xc000007f,
  2843. NT_STATUS_SERVER_DISABLED = 0xc0000080,
  2844. NT_STATUS_SERVER_NOT_DISABLED = 0xc0000081,
  2845. NT_STATUS_TOO_MANY_GUIDS_REQUESTED = 0xc0000082,
  2846. NT_STATUS_GUIDS_EXHAUSTED = 0xc0000083,
  2847. NT_STATUS_INVALID_ID_AUTHORITY = 0xc0000084,
  2848. NT_STATUS_AGENTS_EXHAUSTED = 0xc0000085,
  2849. NT_STATUS_INVALID_VOLUME_LABEL = 0xc0000086,
  2850. NT_STATUS_SECTION_NOT_EXTENDED = 0xc0000087,
  2851. NT_STATUS_NOT_MAPPED_DATA = 0xc0000088,
  2852. NT_STATUS_RESOURCE_DATA_NOT_FOUND = 0xc0000089,
  2853. NT_STATUS_RESOURCE_TYPE_NOT_FOUND = 0xc000008a,
  2854. NT_STATUS_RESOURCE_NAME_NOT_FOUND = 0xc000008b,
  2855. NT_STATUS_ARRAY_BOUNDS_EXCEEDED = 0xc000008c,
  2856. NT_STATUS_FLOAT_DENORMAL_OPERAND = 0xc000008d,
  2857. NT_STATUS_FLOAT_DIVIDE_BY_ZERO = 0xc000008e,
  2858. NT_STATUS_FLOAT_INEXACT_RESULT = 0xc000008f,
  2859. NT_STATUS_FLOAT_INVALID_OPERATION = 0xc0000090,
  2860. NT_STATUS_FLOAT_OVERFLOW = 0xc0000091,
  2861. NT_STATUS_FLOAT_STACK_CHECK = 0xc0000092,
  2862. NT_STATUS_FLOAT_UNDERFLOW = 0xc0000093,
  2863. NT_STATUS_INTEGER_DIVIDE_BY_ZERO = 0xc0000094,
  2864. NT_STATUS_INTEGER_OVERFLOW = 0xc0000095,
  2865. NT_STATUS_PRIVILEGED_INSTRUCTION = 0xc0000096,
  2866. NT_STATUS_TOO_MANY_PAGING_FILES = 0xc0000097,
  2867. NT_STATUS_FILE_INVALID = 0xc0000098,
  2868. NT_STATUS_ALLOTTED_SPACE_EXCEEDED = 0xc0000099,
  2869. NT_STATUS_INSUFFICIENT_RESOURCES = 0xc000009a,
  2870. NT_STATUS_DFS_EXIT_PATH_FOUND = 0xc000009b,
  2871. NT_STATUS_DEVICE_DATA_ERROR = 0xc000009c,
  2872. NT_STATUS_DEVICE_NOT_CONNECTED = 0xc000009d,
  2873. NT_STATUS_DEVICE_POWER_FAILURE = 0xc000009e,
  2874. NT_STATUS_FREE_VM_NOT_AT_BASE = 0xc000009f,
  2875. NT_STATUS_MEMORY_NOT_ALLOCATED = 0xc00000a0,
  2876. NT_STATUS_WORKING_SET_QUOTA = 0xc00000a1,
  2877. NT_STATUS_MEDIA_WRITE_PROTECTED = 0xc00000a2,
  2878. NT_STATUS_DEVICE_NOT_READY = 0xc00000a3,
  2879. NT_STATUS_INVALID_GROUP_ATTRIBUTES = 0xc00000a4,
  2880. NT_STATUS_BAD_IMPERSONATION_LEVEL = 0xc00000a5,
  2881. NT_STATUS_CANT_OPEN_ANONYMOUS = 0xc00000a6,
  2882. NT_STATUS_BAD_VALIDATION_CLASS = 0xc00000a7,
  2883. NT_STATUS_BAD_TOKEN_TYPE = 0xc00000a8,
  2884. NT_STATUS_BAD_MASTER_BOOT_RECORD = 0xc00000a9,
  2885. NT_STATUS_INSTRUCTION_MISALIGNMENT = 0xc00000aa,
  2886. NT_STATUS_INSTANCE_NOT_AVAILABLE = 0xc00000ab,
  2887. NT_STATUS_PIPE_NOT_AVAILABLE = 0xc00000ac,
  2888. NT_STATUS_INVALID_PIPE_STATE = 0xc00000ad,
  2889. NT_STATUS_PIPE_BUSY = 0xc00000ae,
  2890. NT_STATUS_ILLEGAL_FUNCTION = 0xc00000af,
  2891. NT_STATUS_PIPE_DISCONNECTED = 0xc00000b0,
  2892. NT_STATUS_PIPE_CLOSING = 0xc00000b1,
  2893. NT_STATUS_PIPE_CONNECTED = 0xc00000b2,
  2894. NT_STATUS_PIPE_LISTENING = 0xc00000b3,
  2895. NT_STATUS_INVALID_READ_MODE = 0xc00000b4,
  2896. NT_STATUS_IO_TIMEOUT = 0xc00000b5,
  2897. NT_STATUS_FILE_FORCED_CLOSED = 0xc00000b6,
  2898. NT_STATUS_PROFILING_NOT_STARTED = 0xc00000b7,
  2899. NT_STATUS_PROFILING_NOT_STOPPED = 0xc00000b8,
  2900. NT_STATUS_COULD_NOT_INTERPRET = 0xc00000b9,
  2901. NT_STATUS_FILE_IS_A_DIRECTORY = 0xc00000ba,
  2902. NT_STATUS_NOT_SUPPORTED = 0xc00000bb,
  2903. NT_STATUS_REMOTE_NOT_LISTENING = 0xc00000bc,
  2904. NT_STATUS_DUPLICATE_NAME = 0xc00000bd,
  2905. NT_STATUS_BAD_NETWORK_PATH = 0xc00000be,
  2906. NT_STATUS_NETWORK_BUSY = 0xc00000bf,
  2907. NT_STATUS_DEVICE_DOES_NOT_EXIST = 0xc00000c0,
  2908. NT_STATUS_TOO_MANY_COMMANDS = 0xc00000c1,
  2909. NT_STATUS_ADAPTER_HARDWARE_ERROR = 0xc00000c2,
  2910. NT_STATUS_INVALID_NETWORK_RESPONSE = 0xc00000c3,
  2911. NT_STATUS_UNEXPECTED_NETWORK_ERROR = 0xc00000c4,
  2912. NT_STATUS_BAD_REMOTE_ADAPTER = 0xc00000c5,
  2913. NT_STATUS_PRINT_QUEUE_FULL = 0xc00000c6,
  2914. NT_STATUS_NO_SPOOL_SPACE = 0xc00000c7,
  2915. NT_STATUS_PRINT_CANCELLED = 0xc00000c8,
  2916. NT_STATUS_NETWORK_NAME_DELETED = 0xc00000c9,
  2917. NT_STATUS_NETWORK_ACCESS_DENIED = 0xc00000ca,
  2918. NT_STATUS_BAD_DEVICE_TYPE = 0xc00000cb,
  2919. NT_STATUS_BAD_NETWORK_NAME = 0xc00000cc,
  2920. NT_STATUS_TOO_MANY_NAMES = 0xc00000cd,
  2921. NT_STATUS_TOO_MANY_SESSIONS = 0xc00000ce,
  2922. NT_STATUS_SHARING_PAUSED = 0xc00000cf,
  2923. NT_STATUS_REQUEST_NOT_ACCEPTED = 0xc00000d0,
  2924. NT_STATUS_REDIRECTOR_PAUSED = 0xc00000d1,
  2925. NT_STATUS_NET_WRITE_FAULT = 0xc00000d2,
  2926. NT_STATUS_PROFILING_AT_LIMIT = 0xc00000d3,
  2927. NT_STATUS_NOT_SAME_DEVICE = 0xc00000d4,
  2928. NT_STATUS_FILE_RENAMED = 0xc00000d5,
  2929. NT_STATUS_VIRTUAL_CIRCUIT_CLOSED = 0xc00000d6,
  2930. NT_STATUS_NO_SECURITY_ON_OBJECT = 0xc00000d7,
  2931. NT_STATUS_CANT_WAIT = 0xc00000d8,
  2932. NT_STATUS_PIPE_EMPTY = 0xc00000d9,
  2933. NT_STATUS_CANT_ACCESS_DOMAIN_INFO = 0xc00000da,
  2934. NT_STATUS_CANT_TERMINATE_SELF = 0xc00000db,
  2935. NT_STATUS_INVALID_SERVER_STATE = 0xc00000dc,
  2936. NT_STATUS_INVALID_DOMAIN_STATE = 0xc00000dd,
  2937. NT_STATUS_INVALID_DOMAIN_ROLE = 0xc00000de,
  2938. NT_STATUS_NO_SUCH_DOMAIN = 0xc00000df,
  2939. NT_STATUS_DOMAIN_EXISTS = 0xc00000e0,
  2940. NT_STATUS_DOMAIN_LIMIT_EXCEEDED = 0xc00000e1,
  2941. NT_STATUS_OPLOCK_NOT_GRANTED = 0xc00000e2,
  2942. NT_STATUS_INVALID_OPLOCK_PROTOCOL = 0xc00000e3,
  2943. NT_STATUS_INTERNAL_DB_CORRUPTION = 0xc00000e4,
  2944. NT_STATUS_INTERNAL_ERROR = 0xc00000e5,
  2945. NT_STATUS_GENERIC_NOT_MAPPED = 0xc00000e6,
  2946. NT_STATUS_BAD_DESCRIPTOR_FORMAT = 0xc00000e7,
  2947. NT_STATUS_INVALID_USER_BUFFER = 0xc00000e8,
  2948. NT_STATUS_UNEXPECTED_IO_ERROR = 0xc00000e9,
  2949. NT_STATUS_UNEXPECTED_MM_CREATE_ERR = 0xc00000ea,
  2950. NT_STATUS_UNEXPECTED_MM_MAP_ERROR = 0xc00000eb,
  2951. NT_STATUS_UNEXPECTED_MM_EXTEND_ERR = 0xc00000ec,
  2952. NT_STATUS_NOT_LOGON_PROCESS = 0xc00000ed,
  2953. NT_STATUS_LOGON_SESSION_EXISTS = 0xc00000ee,
  2954. NT_STATUS_INVALID_PARAMETER_1 = 0xc00000ef,
  2955. NT_STATUS_INVALID_PARAMETER_2 = 0xc00000f0,
  2956. NT_STATUS_INVALID_PARAMETER_3 = 0xc00000f1,
  2957. NT_STATUS_INVALID_PARAMETER_4 = 0xc00000f2,
  2958. NT_STATUS_INVALID_PARAMETER_5 = 0xc00000f3,
  2959. NT_STATUS_INVALID_PARAMETER_6 = 0xc00000f4,
  2960. NT_STATUS_INVALID_PARAMETER_7 = 0xc00000f5,
  2961. NT_STATUS_INVALID_PARAMETER_8 = 0xc00000f6,
  2962. NT_STATUS_INVALID_PARAMETER_9 = 0xc00000f7,
  2963. NT_STATUS_INVALID_PARAMETER_10 = 0xc00000f8,
  2964. NT_STATUS_INVALID_PARAMETER_11 = 0xc00000f9,
  2965. NT_STATUS_INVALID_PARAMETER_12 = 0xc00000fa,
  2966. NT_STATUS_REDIRECTOR_NOT_STARTED = 0xc00000fb,
  2967. NT_STATUS_REDIRECTOR_STARTED = 0xc00000fc,
  2968. NT_STATUS_STACK_OVERFLOW = 0xc00000fd,
  2969. NT_STATUS_NO_SUCH_PACKAGE = 0xc00000fe,
  2970. NT_STATUS_BAD_FUNCTION_TABLE = 0xc00000ff,
  2971. NT_STATUS_DIRECTORY_NOT_EMPTY = 0xc0000101,
  2972. NT_STATUS_FILE_CORRUPT_ERROR = 0xc0000102,
  2973. NT_STATUS_NOT_A_DIRECTORY = 0xc0000103,
  2974. NT_STATUS_BAD_LOGON_SESSION_STATE = 0xc0000104,
  2975. NT_STATUS_LOGON_SESSION_COLLISION = 0xc0000105,
  2976. NT_STATUS_NAME_TOO_LONG = 0xc0000106,
  2977. NT_STATUS_FILES_OPEN = 0xc0000107,
  2978. NT_STATUS_CONNECTION_IN_USE = 0xc0000108,
  2979. NT_STATUS_MESSAGE_NOT_FOUND = 0xc0000109,
  2980. NT_STATUS_PROCESS_IS_TERMINATING = 0xc000010a,
  2981. NT_STATUS_INVALID_LOGON_TYPE = 0xc000010b,
  2982. NT_STATUS_NO_GUID_TRANSLATION = 0xc000010c,
  2983. NT_STATUS_CANNOT_IMPERSONATE = 0xc000010d,
  2984. NT_STATUS_IMAGE_ALREADY_LOADED = 0xc000010e,
  2985. NT_STATUS_ABIOS_NOT_PRESENT = 0xc000010f,
  2986. NT_STATUS_ABIOS_LID_NOT_EXIST = 0xc0000110,
  2987. NT_STATUS_ABIOS_LID_ALREADY_OWNED = 0xc0000111,
  2988. NT_STATUS_ABIOS_NOT_LID_OWNER = 0xc0000112,
  2989. NT_STATUS_ABIOS_INVALID_COMMAND = 0xc0000113,
  2990. NT_STATUS_ABIOS_INVALID_LID = 0xc0000114,
  2991. NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE = 0xc0000115,
  2992. NT_STATUS_ABIOS_INVALID_SELECTOR = 0xc0000116,
  2993. NT_STATUS_NO_LDT = 0xc0000117,
  2994. NT_STATUS_INVALID_LDT_SIZE = 0xc0000118,
  2995. NT_STATUS_INVALID_LDT_OFFSET = 0xc0000119,
  2996. NT_STATUS_INVALID_LDT_DESCRIPTOR = 0xc000011a,
  2997. NT_STATUS_INVALID_IMAGE_NE_FORMAT = 0xc000011b,
  2998. NT_STATUS_RXACT_INVALID_STATE = 0xc000011c,
  2999. NT_STATUS_RXACT_COMMIT_FAILURE = 0xc000011d,
  3000. NT_STATUS_MAPPED_FILE_SIZE_ZERO = 0xc000011e,
  3001. NT_STATUS_TOO_MANY_OPENED_FILES = 0xc000011f,
  3002. NT_STATUS_CANCELLED = 0xc0000120,
  3003. NT_STATUS_CANNOT_DELETE = 0xc0000121,
  3004. NT_STATUS_INVALID_COMPUTER_NAME = 0xc0000122,
  3005. NT_STATUS_FILE_DELETED = 0xc0000123,
  3006. NT_STATUS_SPECIAL_ACCOUNT = 0xc0000124,
  3007. NT_STATUS_SPECIAL_GROUP = 0xc0000125,
  3008. NT_STATUS_SPECIAL_USER = 0xc0000126,
  3009. NT_STATUS_MEMBERS_PRIMARY_GROUP = 0xc0000127,
  3010. NT_STATUS_FILE_CLOSED = 0xc0000128,
  3011. NT_STATUS_TOO_MANY_THREADS = 0xc0000129,
  3012. NT_STATUS_THREAD_NOT_IN_PROCESS = 0xc000012a,
  3013. NT_STATUS_TOKEN_ALREADY_IN_USE = 0xc000012b,
  3014. NT_STATUS_PAGEFILE_QUOTA_EXCEEDED = 0xc000012c,
  3015. NT_STATUS_COMMITMENT_LIMIT = 0xc000012d,
  3016. NT_STATUS_INVALID_IMAGE_LE_FORMAT = 0xc000012e,
  3017. NT_STATUS_INVALID_IMAGE_NOT_MZ = 0xc000012f,
  3018. NT_STATUS_INVALID_IMAGE_PROTECT = 0xc0000130,
  3019. NT_STATUS_INVALID_IMAGE_WIN_16 = 0xc0000131,
  3020. NT_STATUS_LOGON_SERVER_CONFLICT = 0xc0000132,
  3021. NT_STATUS_TIME_DIFFERENCE_AT_DC = 0xc0000133,
  3022. NT_STATUS_SYNCHRONIZATION_REQUIRED = 0xc0000134,
  3023. NT_STATUS_DLL_NOT_FOUND = 0xc0000135,
  3024. NT_STATUS_OPEN_FAILED = 0xc0000136,
  3025. NT_STATUS_IO_PRIVILEGE_FAILED = 0xc0000137,
  3026. NT_STATUS_ORDINAL_NOT_FOUND = 0xc0000138,
  3027. NT_STATUS_ENTRYPOINT_NOT_FOUND = 0xc0000139,
  3028. NT_STATUS_CONTROL_C_EXIT = 0xc000013a,
  3029. NT_STATUS_LOCAL_DISCONNECT = 0xc000013b,
  3030. NT_STATUS_REMOTE_DISCONNECT = 0xc000013c,
  3031. NT_STATUS_REMOTE_RESOURCES = 0xc000013d,
  3032. NT_STATUS_LINK_FAILED = 0xc000013e,
  3033. NT_STATUS_LINK_TIMEOUT = 0xc000013f,
  3034. NT_STATUS_INVALID_CONNECTION = 0xc0000140,
  3035. NT_STATUS_INVALID_ADDRESS = 0xc0000141,
  3036. NT_STATUS_DLL_INIT_FAILED = 0xc0000142,
  3037. NT_STATUS_MISSING_SYSTEMFILE = 0xc0000143,
  3038. NT_STATUS_UNHANDLED_EXCEPTION = 0xc0000144,
  3039. NT_STATUS_APP_INIT_FAILURE = 0xc0000145,
  3040. NT_STATUS_PAGEFILE_CREATE_FAILED = 0xc0000146,
  3041. NT_STATUS_NO_PAGEFILE = 0xc0000147,
  3042. NT_STATUS_INVALID_LEVEL = 0xc0000148,
  3043. NT_STATUS_WRONG_PASSWORD_CORE = 0xc0000149,
  3044. NT_STATUS_ILLEGAL_FLOAT_CONTEXT = 0xc000014a,
  3045. NT_STATUS_PIPE_BROKEN = 0xc000014b,
  3046. NT_STATUS_REGISTRY_CORRUPT = 0xc000014c,
  3047. NT_STATUS_REGISTRY_IO_FAILED = 0xc000014d,
  3048. NT_STATUS_NO_EVENT_PAIR = 0xc000014e,
  3049. NT_STATUS_UNRECOGNIZED_VOLUME = 0xc000014f,
  3050. NT_STATUS_SERIAL_NO_DEVICE_INITED = 0xc0000150,
  3051. NT_STATUS_NO_SUCH_ALIAS = 0xc0000151,
  3052. NT_STATUS_MEMBER_NOT_IN_ALIAS = 0xc0000152,
  3053. NT_STATUS_MEMBER_IN_ALIAS = 0xc0000153,
  3054. NT_STATUS_ALIAS_EXISTS = 0xc0000154,
  3055. NT_STATUS_LOGON_NOT_GRANTED = 0xc0000155,
  3056. NT_STATUS_TOO_MANY_SECRETS = 0xc0000156,
  3057. NT_STATUS_SECRET_TOO_LONG = 0xc0000157,
  3058. NT_STATUS_INTERNAL_DB_ERROR = 0xc0000158,
  3059. NT_STATUS_FULLSCREEN_MODE = 0xc0000159,
  3060. NT_STATUS_TOO_MANY_CONTEXT_IDS = 0xc000015a,
  3061. NT_STATUS_LOGON_TYPE_NOT_GRANTED = 0xc000015b,
  3062. NT_STATUS_NOT_REGISTRY_FILE = 0xc000015c,
  3063. NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED = 0xc000015d,
  3064. NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR = 0xc000015e,
  3065. NT_STATUS_FT_MISSING_MEMBER = 0xc000015f,
  3066. NT_STATUS_ILL_FORMED_SERVICE_ENTRY = 0xc0000160,
  3067. NT_STATUS_ILLEGAL_CHARACTER = 0xc0000161,
  3068. NT_STATUS_UNMAPPABLE_CHARACTER = 0xc0000162,
  3069. NT_STATUS_UNDEFINED_CHARACTER = 0xc0000163,
  3070. NT_STATUS_FLOPPY_VOLUME = 0xc0000164,
  3071. NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND = 0xc0000165,
  3072. NT_STATUS_FLOPPY_WRONG_CYLINDER = 0xc0000166,
  3073. NT_STATUS_FLOPPY_UNKNOWN_ERROR = 0xc0000167,
  3074. NT_STATUS_FLOPPY_BAD_REGISTERS = 0xc0000168,
  3075. NT_STATUS_DISK_RECALIBRATE_FAILED = 0xc0000169,
  3076. NT_STATUS_DISK_OPERATION_FAILED = 0xc000016a,
  3077. NT_STATUS_DISK_RESET_FAILED = 0xc000016b,
  3078. NT_STATUS_SHARED_IRQ_BUSY = 0xc000016c,
  3079. NT_STATUS_FT_ORPHANING = 0xc000016d,
  3080. NT_STATUS_PARTITION_FAILURE = 0xc0000172,
  3081. NT_STATUS_INVALID_BLOCK_LENGTH = 0xc0000173,
  3082. NT_STATUS_DEVICE_NOT_PARTITIONED = 0xc0000174,
  3083. NT_STATUS_UNABLE_TO_LOCK_MEDIA = 0xc0000175,
  3084. NT_STATUS_UNABLE_TO_UNLOAD_MEDIA = 0xc0000176,
  3085. NT_STATUS_EOM_OVERFLOW = 0xc0000177,
  3086. NT_STATUS_NO_MEDIA = 0xc0000178,
  3087. NT_STATUS_NO_SUCH_MEMBER = 0xc000017a,
  3088. NT_STATUS_INVALID_MEMBER = 0xc000017b,
  3089. NT_STATUS_KEY_DELETED = 0xc000017c,
  3090. NT_STATUS_NO_LOG_SPACE = 0xc000017d,
  3091. NT_STATUS_TOO_MANY_SIDS = 0xc000017e,
  3092. NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED = 0xc000017f,
  3093. NT_STATUS_KEY_HAS_CHILDREN = 0xc0000180,
  3094. NT_STATUS_CHILD_MUST_BE_VOLATILE = 0xc0000181,
  3095. NT_STATUS_DEVICE_CONFIGURATION_ERROR = 0xc0000182,
  3096. NT_STATUS_DRIVER_INTERNAL_ERROR = 0xc0000183,
  3097. NT_STATUS_INVALID_DEVICE_STATE = 0xc0000184,
  3098. NT_STATUS_IO_DEVICE_ERROR = 0xc0000185,
  3099. NT_STATUS_DEVICE_PROTOCOL_ERROR = 0xc0000186,
  3100. NT_STATUS_BACKUP_CONTROLLER = 0xc0000187,
  3101. NT_STATUS_LOG_FILE_FULL = 0xc0000188,
  3102. NT_STATUS_TOO_LATE = 0xc0000189,
  3103. NT_STATUS_NO_TRUST_LSA_SECRET = 0xc000018a,
  3104. NT_STATUS_NO_TRUST_SAM_ACCOUNT = 0xc000018b,
  3105. NT_STATUS_TRUSTED_DOMAIN_FAILURE = 0xc000018c,
  3106. NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE = 0xc000018d,
  3107. NT_STATUS_EVENTLOG_FILE_CORRUPT = 0xc000018e,
  3108. NT_STATUS_EVENTLOG_CANT_START = 0xc000018f,
  3109. NT_STATUS_TRUST_FAILURE = 0xc0000190,
  3110. NT_STATUS_MUTANT_LIMIT_EXCEEDED = 0xc0000191,
  3111. NT_STATUS_NETLOGON_NOT_STARTED = 0xc0000192,
  3112. NT_STATUS_ACCOUNT_EXPIRED = 0xc0000193,
  3113. NT_STATUS_POSSIBLE_DEADLOCK = 0xc0000194,
  3114. NT_STATUS_NETWORK_CREDENTIAL_CONFLICT = 0xc0000195,
  3115. NT_STATUS_REMOTE_SESSION_LIMIT = 0xc0000196,
  3116. NT_STATUS_EVENTLOG_FILE_CHANGED = 0xc0000197,
  3117. NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT = 0xc0000198,
  3118. NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT = 0xc0000199,
  3119. NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT = 0xc000019a,
  3120. NT_STATUS_DOMAIN_TRUST_INCONSISTENT = 0xc000019b,
  3121. NT_STATUS_FS_DRIVER_REQUIRED = 0xc000019c,
  3122. NT_STATUS_NO_USER_SESSION_KEY = 0xc0000202,
  3123. NT_STATUS_USER_SESSION_DELETED = 0xc0000203,
  3124. NT_STATUS_RESOURCE_LANG_NOT_FOUND = 0xc0000204,
  3125. NT_STATUS_INSUFF_SERVER_RESOURCES = 0xc0000205,
  3126. NT_STATUS_INVALID_BUFFER_SIZE = 0xc0000206,
  3127. NT_STATUS_INVALID_ADDRESS_COMPONENT = 0xc0000207,
  3128. NT_STATUS_INVALID_ADDRESS_WILDCARD = 0xc0000208,
  3129. NT_STATUS_TOO_MANY_ADDRESSES = 0xc0000209,
  3130. NT_STATUS_ADDRESS_ALREADY_EXISTS = 0xc000020a,
  3131. NT_STATUS_ADDRESS_CLOSED = 0xc000020b,
  3132. NT_STATUS_CONNECTION_DISCONNECTED = 0xc000020c,
  3133. NT_STATUS_CONNECTION_RESET = 0xc000020d,
  3134. NT_STATUS_TOO_MANY_NODES = 0xc000020e,
  3135. NT_STATUS_TRANSACTION_ABORTED = 0xc000020f,
  3136. NT_STATUS_TRANSACTION_TIMED_OUT = 0xc0000210,
  3137. NT_STATUS_TRANSACTION_NO_RELEASE = 0xc0000211,
  3138. NT_STATUS_TRANSACTION_NO_MATCH = 0xc0000212,
  3139. NT_STATUS_TRANSACTION_RESPONDED = 0xc0000213,
  3140. NT_STATUS_TRANSACTION_INVALID_ID = 0xc0000214,
  3141. NT_STATUS_TRANSACTION_INVALID_TYPE = 0xc0000215,
  3142. NT_STATUS_NOT_SERVER_SESSION = 0xc0000216,
  3143. NT_STATUS_NOT_CLIENT_SESSION = 0xc0000217,
  3144. NT_STATUS_CANNOT_LOAD_REGISTRY_FILE = 0xc0000218,
  3145. NT_STATUS_DEBUG_ATTACH_FAILED = 0xc0000219,
  3146. NT_STATUS_SYSTEM_PROCESS_TERMINATED = 0xc000021a,
  3147. NT_STATUS_DATA_NOT_ACCEPTED = 0xc000021b,
  3148. NT_STATUS_NO_BROWSER_SERVERS_FOUND = 0xc000021c,
  3149. NT_STATUS_VDM_HARD_ERROR = 0xc000021d,
  3150. NT_STATUS_DRIVER_CANCEL_TIMEOUT = 0xc000021e,
  3151. NT_STATUS_REPLY_MESSAGE_MISMATCH = 0xc000021f,
  3152. NT_STATUS_MAPPED_ALIGNMENT = 0xc0000220,
  3153. NT_STATUS_IMAGE_CHECKSUM_MISMATCH = 0xc0000221,
  3154. NT_STATUS_LOST_WRITEBEHIND_DATA = 0xc0000222,
  3155. NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID = 0xc0000223,
  3156. NT_STATUS_PASSWORD_MUST_CHANGE = 0xc0000224,
  3157. NT_STATUS_NOT_FOUND = 0xc0000225,
  3158. NT_STATUS_NOT_TINY_STREAM = 0xc0000226,
  3159. NT_STATUS_RECOVERY_FAILURE = 0xc0000227,
  3160. NT_STATUS_STACK_OVERFLOW_READ = 0xc0000228,
  3161. NT_STATUS_FAIL_CHECK = 0xc0000229,
  3162. NT_STATUS_DUPLICATE_OBJECTID = 0xc000022a,
  3163. NT_STATUS_OBJECTID_EXISTS = 0xc000022b,
  3164. NT_STATUS_CONVERT_TO_LARGE = 0xc000022c,
  3165. NT_STATUS_RETRY = 0xc000022d,
  3166. NT_STATUS_FOUND_OUT_OF_SCOPE = 0xc000022e,
  3167. NT_STATUS_ALLOCATE_BUCKET = 0xc000022f,
  3168. NT_STATUS_PROPSET_NOT_FOUND = 0xc0000230,
  3169. NT_STATUS_MARSHALL_OVERFLOW = 0xc0000231,
  3170. NT_STATUS_INVALID_VARIANT = 0xc0000232,
  3171. NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND = 0xc0000233,
  3172. NT_STATUS_ACCOUNT_LOCKED_OUT = 0xc0000234,
  3173. NT_STATUS_HANDLE_NOT_CLOSABLE = 0xc0000235,
  3174. NT_STATUS_CONNECTION_REFUSED = 0xc0000236,
  3175. NT_STATUS_GRACEFUL_DISCONNECT = 0xc0000237,
  3176. NT_STATUS_ADDRESS_ALREADY_ASSOCIATED = 0xc0000238,
  3177. NT_STATUS_ADDRESS_NOT_ASSOCIATED = 0xc0000239,
  3178. NT_STATUS_CONNECTION_INVALID = 0xc000023a,
  3179. NT_STATUS_CONNECTION_ACTIVE = 0xc000023b,
  3180. NT_STATUS_NETWORK_UNREACHABLE = 0xc000023c,
  3181. NT_STATUS_HOST_UNREACHABLE = 0xc000023d,
  3182. NT_STATUS_PROTOCOL_UNREACHABLE = 0xc000023e,
  3183. NT_STATUS_PORT_UNREACHABLE = 0xc000023f,
  3184. NT_STATUS_REQUEST_ABORTED = 0xc0000240,
  3185. NT_STATUS_CONNECTION_ABORTED = 0xc0000241,
  3186. NT_STATUS_BAD_COMPRESSION_BUFFER = 0xc0000242,
  3187. NT_STATUS_USER_MAPPED_FILE = 0xc0000243,
  3188. NT_STATUS_AUDIT_FAILED = 0xc0000244,
  3189. NT_STATUS_TIMER_RESOLUTION_NOT_SET = 0xc0000245,
  3190. NT_STATUS_CONNECTION_COUNT_LIMIT = 0xc0000246,
  3191. NT_STATUS_LOGIN_TIME_RESTRICTION = 0xc0000247,
  3192. NT_STATUS_LOGIN_WKSTA_RESTRICTION = 0xc0000248,
  3193. NT_STATUS_IMAGE_MP_UP_MISMATCH = 0xc0000249,
  3194. NT_STATUS_INSUFFICIENT_LOGON_INFO = 0xc0000250,
  3195. NT_STATUS_BAD_DLL_ENTRYPOINT = 0xc0000251,
  3196. NT_STATUS_BAD_SERVICE_ENTRYPOINT = 0xc0000252,
  3197. NT_STATUS_LPC_REPLY_LOST = 0xc0000253,
  3198. NT_STATUS_IP_ADDRESS_CONFLICT1 = 0xc0000254,
  3199. NT_STATUS_IP_ADDRESS_CONFLICT2 = 0xc0000255,
  3200. NT_STATUS_REGISTRY_QUOTA_LIMIT = 0xc0000256,
  3201. NT_STATUS_PATH_NOT_COVERED = 0xc0000257,
  3202. NT_STATUS_NO_CALLBACK_ACTIVE = 0xc0000258,
  3203. NT_STATUS_LICENSE_QUOTA_EXCEEDED = 0xc0000259,
  3204. NT_STATUS_PWD_TOO_SHORT = 0xc000025a,
  3205. NT_STATUS_PWD_TOO_RECENT = 0xc000025b,
  3206. NT_STATUS_PWD_HISTORY_CONFLICT = 0xc000025c,
  3207. NT_STATUS_PLUGPLAY_NO_DEVICE = 0xc000025e,
  3208. NT_STATUS_UNSUPPORTED_COMPRESSION = 0xc000025f,
  3209. NT_STATUS_INVALID_HW_PROFILE = 0xc0000260,
  3210. NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH = 0xc0000261,
  3211. NT_STATUS_DRIVER_ORDINAL_NOT_FOUND = 0xc0000262,
  3212. NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND = 0xc0000263,
  3213. NT_STATUS_RESOURCE_NOT_OWNED = 0xc0000264,
  3214. NT_STATUS_TOO_MANY_LINKS = 0xc0000265,
  3215. NT_STATUS_QUOTA_LIST_INCONSISTENT = 0xc0000266,
  3216. NT_STATUS_FILE_IS_OFFLINE = 0xc0000267,
  3217. NT_STATUS_DS_NO_MORE_RIDS = 0xc00002a8,
  3218. NT_STATUS_NOT_A_REPARSE_POINT = 0xc0000275,
  3219. NT_STATUS_NO_SUCH_JOB = 0xc000EDE
  3220. }
  3221. for i, v in pairs(status_codes) do
  3222. status_names[v] = i
  3223. end