PageRenderTime 73ms CodeModel.GetById 27ms 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

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

  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_ty…

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