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

  1. --- By making heavy use of the 'smb' library, this library will call various MSRPC 
  2. --  functions. The functions used here can be accessed over TCP ports 445 and 139, 
  3. --  with an established session. A NULL session (the default) will work for some 
  4. --  functions and operating systems (or configurations), but not for others. 
  5. --
  6. -- To make use of these function calls, a SMB session with the server has to be
  7. -- established. This can be done manually with the <code>smb</code> library, or the function
  8. -- <code>start_smb</code> can be called. A session has to be created, then the IPC$ 
  9. -- tree opened. 
  10. --
  11. -- Next, the interface has to be bound. The bind() function will take care of that. 
  12. --
  13. -- After that, you're free to call any function that's part of that interface. In
  14. -- other words, if you bind to the SAMR interface, you can only call the samr_
  15. -- functions, for lsa_ functions, bind to the LSA interface, etc.  Although functions 
  16. -- can technically be called in any order, many functions depend on the
  17. -- value returned by other functions. I indicate those in the function comments, 
  18. -- so keep an eye out. SAMR functions, for example, require a call to 
  19. -- <code>connect4</code>. 
  20. --
  21. -- Something to note is that these functions, for the most part, return a whole ton
  22. -- of stuff in a table; basically, everything that is returned by the function. 
  23. -- Generally, if you want to know exactly what you have access to, either display the
  24. -- returned data with a print_table-type function, or check the documentation (Samba 4.0's
  25. -- .idl files (in samba_4.0/source/librpc/idl; see below for link) are what I based 
  26. -- the names on). 
  27. --
  28. -- The parameters for each function are converted to a string of bytes in a process
  29. -- called "marshalling". Functions here take arguments that match what a user would
  30. -- logically want to send. These are marshalled by using functions in the 
  31. -- <code>msrpctypes</code> module. Those functions require a table of values that 
  32. -- isn't very use friendly; as such, it's generated, when possible, in the functions
  33. -- in this module. The value returned, on the other hand, is returned directly to the
  34. -- user; I don't want to limit what data they can use, and it's difficult to rely on 
  35. -- servers to format it consistently (sometimes a <code>null</code> is returned, and
  36. -- other times an empty array or blank string), so I put the onus on the scripts to 
  37. -- deal with the returned values. 
  38. --
  39. -- When implementing this, I used Wireshark's output significantly, as well as Samba's
  40. -- "idl" files for reference:
  41. --  http://websvn.samba.org/cgi-bin/viewcvs.cgi/branches/SAMBA_4_0/source/librpc/idl/ 
  42. -- I'm not a lawyer, but I don't expect that this is a breach of Samba's copyright -- 
  43. -- if it is, please talk to me and I'll make arrangements to re-license this or to 
  44. -- remove references to Samba. 
  45. --
  46. --@author Ron Bowes <ron@skullsecurity.net>
  47. --@copyright Same as Nmap--See http://nmap.org/book/man-legal.html
  48. -----------------------------------------------------------------------
  49. module(... or "msrpc", package.seeall)
  50.  
  51. require 'bit'
  52. require 'bin'
  53. require 'msrpctypes'
  54. require 'netbios'
  55. require 'smb'
  56. require 'stdnse'
  57.  
  58. -- The path, UUID, and version for SAMR
  59. SAMR_PATH       = "\\samr"
  60. SAMR_UUID       = string.char(0x78, 0x57, 0x34, 0x12, 0x34, 0x12, 0xcd, 0xab, 0xef, 0x00, 0x01, 0x23, 0x45, 0x67, 0x89, 0xac)
  61. SAMR_VERSION    = 0x01
  62.  
  63. -- The path, UUID, and version for SRVSVC
  64. SRVSVC_PATH     = "\\srvsvc"
  65. SRVSVC_UUID     = string.char(0xc8, 0x4f, 0x32, 0x4b, 0x70, 0x16, 0xd3, 0x01, 0x12, 0x78, 0x5a, 0x47, 0xbf, 0x6e, 0xe1, 0x88)
  66. SRVSVC_VERSION  = 0x03
  67.  
  68. -- The path, UUID, and version for LSA
  69. LSA_PATH        = "\\lsarpc"
  70. LSA_UUID        = string.char(0x78, 0x57, 0x34, 0x12, 0x34, 0x12, 0xcd, 0xab, 0xef, 0x00, 0x01, 0x23, 0x45, 0x67, 0x89, 0xab)
  71. LSA_VERSION     = 0
  72.  
  73. -- The path, UUID, and version for WINREG
  74. WINREG_PATH     = "\\winreg"
  75. WINREG_UUID     = string.char(0x01, 0xd0, 0x8c, 0x33, 0x44, 0x22, 0xf1, 0x31, 0xaa, 0xaa, 0x90, 0x00, 0x38, 0x00, 0x10, 0x03)
  76. WINREG_VERSION  = 1
  77.  
  78. -- The path, UUID, and version for SVCCTL
  79. SVCCTL_PATH    = "\\svcctl"
  80. SVCCTL_UUID    = string.char(0x81, 0xbb, 0x7a, 0x36, 0x44, 0x98, 0xf1, 0x35, 0xad, 0x32, 0x98, 0xf0, 0x38, 0x00, 0x10, 0x03)
  81. SVCCTL_VERSION = 2
  82.  
  83. -- The path, UUID, and version for ATSVC
  84. ATSVC_PATH     = "\\atsvc"
  85. ATSVC_UUID     = string.char(0x82, 0x06, 0xf7, 0x1f, 0x51, 0x0a, 0xe8, 0x30, 0x07, 0x6d, 0x74, 0x0b, 0xe8, 0xce, 0xe9, 0x8b)
  86. ATSVC_VERSION  = 1
  87.  
  88. -- This is the only transfer syntax I've seen in the wild, not that I've looked hard. It seems to work well. 
  89. TRANSFER_SYNTAX = string.char(0x04, 0x5d, 0x88, 0x8a, 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, 0x2b, 0x10, 0x48, 0x60)
  90.  
  91. -- The 'referent_id' value is ignored, as far as I can tell, so this value is passed for it. No, it isn't random. :)
  92. REFERENT_ID = 0x50414d4e
  93.  
  94. -- The maximum length of a packet fragment
  95. MAX_FRAGMENT = 0x800
  96.  
  97. ---The number of SAMR records to pull at once. This was originally 1, but since I've written 
  98. -- proper fragmentation code, I've successfully done it with 110 users, although I'd be surprised
  99. -- if you couldn't go a lot higher. I had some issues that I suspect was UNIX truncating packets, 
  100. -- so I scaled it back. 
  101. local SAMR_GROUPSIZE = 20
  102.  
  103. ---The number of LSA RIDs to check at once. I've successfully tested with up to about 110. Note that
  104. -- due to very long message sizes, Wireshark might truncate packets if you have more than 30 together, 
  105. -- so for debugging, setting this to 30 might be a plan. Like SAMR, I scaled this back due to UNIX
  106. -- truncation. 
  107. local LSA_GROUPSIZE  = 20
  108.  
  109. ---The number of consecutive empty groups to stop after. Basically, this means that after 
  110. -- <code>LSA_MINEMPTY</code> groups of <code>LSA_GROUPSIZE</code> users come back empty, we give
  111. -- up. Raising this could find more users, but at the expense of more packets. 
  112. local LSA_MINEMPTY = 10
  113.  
  114. --- This is a wrapper around the SMB class, designed to get SMB going quickly for MSRPC calls. This will
  115. --  connect to the SMB server, negotiate the protocol, open a session, connect to the IPC$ share, and
  116. --  open the named pipe given by 'path'. When this successfully returns, the 'smbstate' table can be immediately 
  117. --  used for MSRPC (the <code>bind</code> function should be called right after). 
  118. --
  119. -- Note that the smbstate table is the same one used in the SMB files (obviously), so it will contain
  120. -- the various results/information places in there by SMB functions. 
  121. --
  122. --@param host The host object. 
  123. --@param path The path to the named pipe; for example, msrpc.SAMR_PATH or msrpc.SRVSVC_PATH. 
  124. --@param disable_extended [optional] If set to 'true', disables extended security negotiations. 
  125. --@return (status, smbstate) if status is false, smbstate is an error message. Otherwise, smbstate is
  126. --        required for all further calls. 
  127. function start_smb(host, path, disable_extended)
  128.     return smb.start_ex(host, true, true, "IPC$", path, disable_extended)
  129. end
  130.  
  131. --- A wrapper around the <code>smb.stop</code> function. I only created it to add symmetry, so client code
  132. --  doesn't have to call both msrpc and smb functions.
  133. --
  134. --@param state The SMB state table. 
  135. function stop_smb(state)
  136.     smb.stop(state)
  137. end
  138.  
  139. --- Bind to a MSRPC interface. Two common interfaces are SAML and SRVSVC, and can be found as
  140. --  constants at the top of this file. Once this function has successfully returned, any MSRPC
  141. --  call can be made (provided it doesn't depend on results from other MSRPC calls). 
  142. --
  143. --@param smbstate The SMB state table
  144. --@param interface_uuid The interface to bind to. There are constants defined for these (<code>SAMR_UUID</code>, 
  145. --       etc.)
  146. --@param interface_version The interface version to use. There are constants at the top (<code>SAMR_VERSION</code>, 
  147. --       etc.)
  148. --@param transfer_syntax The transfer syntax to use. I don't really know what this is, but the value
  149. --       was always the same on my tests. You can use the constant at the top (<code>TRANSFER_SYNTAX</code>), or
  150. --       just set this parameter to 'nil'. 
  151. --@return (status, result) If status is false, result is an error message. Otherwise, result is a 
  152. --        table of values, none of which are especially useful. 
  153. function bind(smbstate, interface_uuid, interface_version, transfer_syntax)
  154.     local i
  155.     local status, result
  156.     local parameters, data
  157.     local pos, align
  158.     local result
  159.  
  160.     stdnse.print_debug(2, "MSRPC: Sending Bind() request")
  161.  
  162.     -- Use the only transfer_syntax value I know of. 
  163.     if(transfer_syntax == nil) then
  164.         transfer_syntax = TRANSFER_SYNTAX
  165.     end
  166.  
  167.     data = bin.pack("<CCCC>I<SSISSICCCC",
  168.                 0x05, -- Version (major)
  169.                 0x00, -- Version (minor)
  170.                 0x0B, -- Packet type (0x0B = bind)
  171.                 0x03, -- Packet flags (0x03 = first frag + last frag)
  172.                 0x10000000, -- Data representation (big endian)
  173.                 0x0048,     -- Frag length
  174.                 0x0000,     -- Auth length
  175.                 0x41414141, -- Call ID (I use 'AAAA' because it's easy to recognize)
  176.                 MAX_FRAGMENT, -- Max transmit frag
  177.                 MAX_FRAGMENT, -- Max receive frag
  178.                 0x00000000, -- Assoc group
  179.                 0x01,       -- Number of items
  180.                 0x00,       -- Padding/alignment
  181.                 0x00,       -- Padding/alignment
  182.                 0x00        -- Padding/alignment
  183.             )
  184.  
  185.     data = data .. bin.pack("<SCCASSAI",
  186.                 0x0000,            -- Context ID
  187.                 0x01,              -- Number of transaction items. */
  188.                 0x00,              -- Padding/alignment
  189.                 interface_uuid,    -- Interface (eg. SRVSVC UUID: 4b324fc8-1670-01d3-1278-5a47bf6ee188)
  190.                 interface_version, -- Interface version (major)
  191.                 0x0000,            -- Interface version (minor)
  192.                 transfer_syntax,   -- Transfer syntax
  193.                 2                  -- Syntax version
  194.             )
  195.  
  196.     status, result = smb.write_file(smbstate, data, 0)
  197.     if(status ~= true) then
  198.         return false, result
  199.     end
  200.  
  201.     status, result = smb.read_file(smbstate, 0, MAX_FRAGMENT)
  202.     if(status ~= true) then
  203.         return false, result
  204.     end
  205.  
  206.     stdnse.print_debug(3, "MSRPC: Received Bind() result")
  207.  
  208.     -- Make these easier to access. 
  209.     parameters = result['parameters']
  210.     data = result['data']
  211.  
  212.     -- Extract the first part from the resposne
  213.     pos, result['version_major'], result['version_minor'], result['packet_type'], result['packet_flags'], result['data_representation'], result['frag_length'], result['auth_length'], result['call_id'] = bin.unpack("<CCCC>I<SSI", data)
  214.     if(result['call_id'] == nil) then
  215.         return false, "MSRPC: ERROR: Ran off the end of SMB packet; likely due to server truncation"
  216.     end
  217.  
  218.     -- Check if the packet tyep was a fault
  219.     if(result['packet_type'] == 0x03) then -- MSRPC_FAULT
  220.         return false, "Bind() returned a fault (packet type)"
  221.     end
  222.     -- Check if the flags indicate DID_NOT_EXECUTE
  223.     if(bit.band(result['packet_flags'], 0x20) == 0x20) then
  224.         return false, "Bind() returned a fault (flags)"
  225.     end
  226.     -- Check if it requested authorization (I've never seen this, but wouldn't know how to handle it)
  227.     if(result['auth_length'] ~= 0) then
  228.         return false, "Bind() returned an 'auth length', which we don't know how to deal with"
  229.     end
  230.     -- Check if the packet was fragmented (I've never seen this, but wouldn't know how to handle it)
  231.     if(bit.band(result['packet_flags'], 0x03) ~= 0x03) then
  232.         return false, "Bind() returned a fragmented packet, which we don't know how to handle"
  233.     end
  234.     -- Check if the wrong message type was returned
  235.     if(result['packet_type'] ~= 0x0c) then
  236.         return false, "Bind() returned an unexpected packet type (not BIND_ACK)"
  237.     end
  238.     -- Ensure the proper call_id was echoed back (if this is wrong, it's likely because our read is out of sync, not a bad server)
  239.     if(result['call_id'] ~= 0x41414141) then
  240.         return false, "MSRPC call returned an incorrect 'call_id' value"
  241.     end
  242.  
  243.     -- If we made it this far, then we have a valid Bind() result. Pull out some more parameters. 
  244.     pos, result['max_transmit_frag'], result['max_receive_frag'], result['assoc_group'], result['secondary_address_length'] = bin.unpack("<SSIS", data, pos)
  245.     if(result['secondary_address_length'] == nil) then
  246.         return false, "MSRPC: ERROR: Ran off the end of SMB packet; likely due to server truncation"
  247.     end
  248.  
  249.     -- Read the secondary address
  250.     pos, result['secondary_address'] = bin.unpack(string.format("<A%d", result['secondary_address_length']), data, pos)
  251.     if(result['secondary_address'] == nil) then
  252.         return false, "MSRPC: ERROR: Ran off the end of SMB packet; likely due to server truncation"
  253.     end
  254.     pos = pos + ((4 - ((pos - 1) % 4)) % 4); -- Alignment -- don't ask how I came up with this, it was a lot of drawing, and there's probably a far better way
  255.  
  256.     -- Read the number of results
  257.     pos, result['num_results'] = bin.unpack("<C", data, pos)
  258.     if(result['num_results'] == nil) then
  259.         return false, "MSRPC: ERROR: Ran off the end of SMB packet; likely due to server truncation"
  260.     end
  261.     pos = pos + ((4 - ((pos - 1) % 4)) % 4); -- Alignment
  262.  
  263.     -- Verify we got back what we expected
  264.     if(result['num_results'] ~= 1) then
  265.         return false, "Bind() returned the incorrect number of result"
  266.     end
  267.  
  268.     -- Read in the last bits
  269.     pos, result['ack_result'], result['align'], result['transfer_syntax'], result['syntax_version'] = bin.unpack("<SSA16I", data, pos)
  270.     if(result['syntax_version'] == nil) then
  271.         return false, "MSRPC: ERROR: Ran off the end of SMB packet; likely due to server truncation"
  272.     end
  273.  
  274.     return true, result
  275. end
  276.  
  277. --- Call a MSRPC function on the remote sever, with the given opnum and arguments. I opted to make this a local function
  278. --  for design reasons -- scripts shouldn't be directly calling a function, if a function I haven't written is needed, it
  279. --  ought to be added to this file. 
  280. --
  281. -- Anyways, this function takes the opnum and marshalled arguments, and passes it down to the SMB layer. The SMB layer sends
  282. -- out a <code>SMB_COM_TRANSACTION</code> packet, and parses the result. Once the SMB stuff has been stripped off the result, it's 
  283. -- passed down here, cleaned up some more, and returned to the caller.
  284. --
  285. -- There's a reason that SMB is sometimes considered to be between layer 4 and 7 on the OSI model. :)
  286. --
  287. --@param smbstate  The SMB state table (after <code>bind</code> has been called). 
  288. --@param opnum     The operating number (ie, the function). Find this in the MSRPC documentation or with a packet logger. 
  289. --@param arguments The marshalled arguments to pass to the function. Currently, marshalling is all done manually. 
  290. --@return (status, result) If status is false, result is an error message. Otherwise, result is a table of values, the most
  291. --        useful one being 'arguments', which are the values returned by the server. If the packet is fragmented, the fragments
  292. --        will be reassembled and 'arguments' will represent all the arguments; however, the rest of the result table will represent
  293. --        the most recent fragment. 
  294. local function call_function(smbstate, opnum, arguments)
  295.     local i
  296.     local status, result
  297.     local parameters, data
  298.     local pos, align
  299.     local result
  300.     local first = true
  301.     local is_first, is_last
  302.  
  303.     data = bin.pack("<CCCC>I<SSIISSA",
  304.                 0x05,        -- Version (major)
  305.                 0x00,        -- Version (minor)
  306.                 0x00,        -- Packet type (0x00 = request)
  307.                 0x03,        -- Packet flags (0x03 = first frag + last frag)
  308.                 0x10000000,  -- Data representation (big endian)
  309.                 0x18 + string.len(arguments), -- Frag length (0x18 = the size of this data)
  310.                 0x0000,      -- Auth length
  311.                 0x41414141,  -- Call ID (I use 'AAAA' because it's easy to recognize)
  312.                 0x00000038,  -- Alloc hint
  313.                 0x0000,      -- Context ID
  314.                 opnum,       -- Opnum
  315.                 arguments
  316.             )
  317.  
  318.     stdnse.print_debug(3, "MSRPC: Calling function 0x%02x with %d bytes of arguments", string.len(arguments), opnum)
  319.  
  320.     -- Pass the information up to the smb layer
  321.     status, result = smb.write_file(smbstate, data, 0)
  322.     if(status ~= true) then
  323.         return false, result
  324.     end
  325.  
  326.     -- Loop over the fragments
  327.     local arguments = ""
  328.     repeat
  329.         -- Read the information from the smb layer
  330.         status, result = smb.read_file(smbstate, 0, 0x1001)
  331.         if(status ~= true) then
  332.             return false, result
  333.         end
  334.     
  335.         -- Make these easier to access. 
  336.         parameters = result['parameters']
  337.         data       = result['data']
  338.     
  339.         -- Extract the first part from the resposne
  340.         pos, result['version_major'], result['version_minor'], result['packet_type'], result['packet_flags'], result['data_representation'], result['frag_length'], result['auth_length'], result['call_id'] = bin.unpack("<CCCC>I<SSI", data)
  341.         if(result['call_id'] == nil) then
  342.             return false, "MSRPC: ERROR: Ran off the end of SMB packet; likely due to server truncation"
  343.         end
  344.  
  345.         -- Check if we're fragmented
  346.         is_first = (bit.band(result['packet_flags'], 0x01) == 0x01)
  347.         is_last  = (bit.band(result['packet_flags'], 0x02) == 0x02)
  348.  
  349.         -- We have a fragmented packet, make sure it's the first (if we're on the first)
  350.         if(first == true and is_first == false) then
  351.             return false, "MSRPC: First fragment doesn't have proper 'first' (0x01) flag set"
  352.         end
  353.  
  354.         -- We have a fragmented packet, make sure it isn't the first (if we aren't on the first)
  355.         if(first == false and is_first) then
  356.             return false, "MSRPC: Middle (or last) fragment doesn't have proper 'first' (0x01) flag set"
  357.         end
  358.  
  359.         -- Check if there was an error
  360.         if(result['packet_type'] == 0x03) then -- MSRPC_FAULT
  361.             return false, "MSRPC call returned a fault (packet type)"
  362.         end
  363.         if(bit.band(result['packet_flags'], 0x20) == 0x20) then
  364.             return false, "MSRPC call returned a fault (flags)"
  365.         end
  366.         if(result['auth_length'] ~= 0) then
  367.             return false, "MSRPC call returned an 'auth length', which we don't know how to deal with"
  368.         end
  369.         if(result['packet_type'] ~= 0x02) then
  370.             return false, "MSRPC call returned an unexpected packet type (not RESPONSE)"
  371.         end
  372.         if(result['call_id'] ~= 0x41414141) then
  373.             return false, "MSRPC call returned an incorrect 'call_id' value"
  374.         end
  375.     
  376.         -- Extract some more
  377.         pos, result['alloc_hint'], result['context_id'], result['cancel_count'], align = bin.unpack("<ISCC", data, pos)
  378.         if(align == nil) then
  379.             return false, "MSRPC: ERROR: Ran off the end of SMB packet; likely due to server truncation"
  380.         end
  381.  
  382.         -- Rest is the arguments
  383.         arguments = arguments .. string.sub(data, pos)
  384.  
  385.         -- No longer the 'first'
  386.         first = false
  387.     until is_last == true
  388.  
  389.     result['arguments'] = arguments
  390.  
  391.     stdnse.print_debug(3, "MSRPC: Function call successful, %d bytes of returned argumenst", string.len(result['arguments']))
  392.  
  393.     return true, result
  394. end
  395.  
  396. ---A proxy to a <code>msrpctypes</code> function that converts a ShareType to an english string. 
  397. -- I implemented this as a proxy so scripts don't have to make direct calls to <code>msrpctypes</code>
  398. -- functions.
  399. --
  400. --@param val The value to convert.
  401. --@return A string that can be displayed to the user. 
  402. function srvsvc_ShareType_tostr(val)
  403.     return msrpctypes.srvsvc_ShareType_tostr(val)
  404. end
  405.  
  406. ---Call the MSRPC function <code>netshareenumall</code> on the remote system. This function basically returns a list of all the shares
  407. -- on the system. 
  408. --
  409. --@param smbstate The SMB state table
  410. --@param server   The IP or Hostname of the server (seems to be ignored but it's a good idea to have it)
  411. --@return (status, result) If status is false, result is an error message. Otherwise, result is a table of values, the most
  412. --        useful one being 'shares', which is a list of the system's shares. 
  413. function srvsvc_netshareenumall(smbstate, server)
  414.     local i, j
  415.     local status, result
  416.     local arguments
  417.     local pos, align
  418.  
  419.     local level
  420.     local ctr, referent, count, max_count
  421.  
  422.     stdnse.print_debug(2, "MSRPC: Calling NetShareEnumAll() [%s]", smbstate['ip'])
  423.  
  424. -- [in]   [string,charset(UTF16)] uint16 *server_unc
  425.     arguments = msrpctypes.marshall_unicode_ptr("\\\\" .. server, true)
  426.  
  427. -- [in,out]   uint32 level
  428.     arguments = arguments .. msrpctypes.marshall_int32(0)
  429.  
  430. -- [in,out,switch_is(level)] srvsvc_NetShareCtr ctr
  431.     arguments = arguments .. msrpctypes.marshall_srvsvc_NetShareCtr(0, {array=nil})
  432.  
  433. -- [in]   uint32 max_buffer,
  434.     arguments = arguments .. msrpctypes.marshall_int32(4096)
  435.  
  436. -- [out]  uint32 totalentries
  437. -- [in,out]   uint32 *resume_handle*
  438.     arguments = arguments .. msrpctypes.marshall_int32_ptr(0)
  439.  
  440.  
  441.     -- Do the call
  442.     status, result = call_function(smbstate, 0x0F, arguments)
  443.     if(status ~= true) then
  444.         return false, result
  445.     end
  446.  
  447.     stdnse.print_debug(3, "MSRPC: NetShareEnumAll() returned successfully")
  448.  
  449.     -- Make arguments easier to use
  450.     arguments = result['arguments']
  451.     pos = 1
  452.  
  453. -- [in]   [string,charset(UTF16)] uint16 *server_unc
  454. -- [in,out]   uint32 level
  455.     pos, result['level'] = msrpctypes.unmarshall_int32(arguments, pos)
  456.  
  457. -- [in,out,switch_is(level)] srvsvc_NetShareCtr ctr
  458.     pos, result['ctr'] = msrpctypes.unmarshall_srvsvc_NetShareCtr(arguments, pos, level)
  459.     if(pos == nil) then
  460.         return false, "unmarshall_srvsvc_NetShareCtr() returned an error"
  461.     end
  462.  
  463. -- [out]  uint32 totalentries
  464.     pos, result['totalentries'] = msrpctypes.unmarshall_int32(arguments, pos)
  465.  
  466. -- [in,out]   uint32 *resume_handle
  467.     pos, result['resume_handle'] = msrpctypes.unmarshall_int32_ptr(arguments, pos)
  468.  
  469.     -- The return value
  470.     pos, result['return'] = msrpctypes.unmarshall_int32(arguments, pos)
  471.     if(result['return'] == nil) then
  472.         return false, "Read off the end of the packet (srvsvc.netshareenumall)"
  473.     end
  474.     if(result['return'] ~= 0) then
  475.         return false, smb.get_status_name(result['return']) .. " (srvsvc.netshareenumall)"
  476.     end
  477.  
  478.     return true, result
  479. end
  480.  
  481. ---Call the MSRPC function <code>netsharegetinfo</code> on the remote system. This function retrieves extra information about a share
  482. -- on the system. 
  483. --
  484. --@param smbstate The SMB state table
  485. --@param server   The IP or Hostname of the server (seems to be ignored but it's a good idea to have it)
  486. --@return (status, result) If status is false, result is an error message. Otherwise, result is a table of values, the most
  487. --        useful one being 'shares', which is a list of the system's shares. 
  488. function srvsvc_netsharegetinfo(smbstate, server, share, level)
  489.     local i, j
  490.     local status, result
  491.     local arguments
  492.     local pos, align
  493.  
  494. --        [in]   [string,charset(UTF16)] uint16 *server_unc,
  495.     arguments = msrpctypes.marshall_unicode_ptr("\\\\" .. server, true)
  496.  
  497. --        [in]   [string,charset(UTF16)] uint16 share_name[],
  498.     arguments = arguments .. msrpctypes.marshall_unicode(share, true)
  499.  
  500. --        [in]   uint32 level,
  501.     arguments = arguments .. msrpctypes.marshall_int32(level)
  502.  
  503. --        [out,switch_is(level)] srvsvc_NetShareInfo info
  504.  
  505.  
  506.     -- Do the call
  507.     status, result = call_function(smbstate, 0x10, arguments)
  508.     if(status ~= true) then
  509.         return false, result
  510.     end
  511.  
  512.     stdnse.print_debug(3, "MSRPC: NetShareGetInfo() returned successfully")
  513.  
  514.     -- Make arguments easier to use
  515.     arguments = result['arguments']
  516.     pos = 1
  517.  
  518. --        [in]   [string,charset(UTF16)] uint16 *server_unc,
  519. --        [in]   [string,charset(UTF16)] uint16 share_name[],
  520. --        [in]   uint32 level,
  521. --        [out,switch_is(level)] srvsvc_NetShareInfo info
  522.     pos, result['info'] = msrpctypes.unmarshall_srvsvc_NetShareInfo(arguments, pos)
  523.     if(pos == nil) then
  524.         return false, "unmarshall_srvsvc_NetShareInfo() returned an error"
  525.     end
  526.  
  527.     -- The return value
  528.     pos, result['return'] = msrpctypes.unmarshall_int32(arguments, pos)
  529.     if(result['return'] == nil) then
  530.         return false, "Read off the end of the packet (srvsvc.netsharegetinfo)"
  531.     end
  532.     if(result['return'] ~= 0) then
  533.         return false, smb.get_status_name(result['return']) .. " (srvsvc.netsharegetinfo)"
  534.     end
  535.  
  536.     return true, result
  537. end
  538.  
  539.  
  540. ---Call the <code>NetSessEnum</code> function, which gets a list of active sessions on the host. For this function, 
  541. -- a session is defined as a connection to a file share. 
  542. --
  543. --@param smbstate The SMB state table
  544. --@param server   The IP or Hostname of the server (seems to be ignored but it's a good idea to have it)
  545. --@return (status, result) If status is false, result is an error message. Otherwise, result is an array of tables.
  546. --        Each table contains the elements 'user', 'client', 'active', and 'idle'.
  547. function srvsvc_netsessenum(smbstate, server)
  548.     local i, j
  549.     local status, result
  550.     local arguments
  551.     local pos, align
  552.  
  553.     stdnse.print_debug(2, "MSRPC: Calling NetSessEnum() [%s]", smbstate['ip'])
  554.  
  555. --        [in]   [string,charset(UTF16)] uint16 *server_unc,
  556.     arguments = msrpctypes.marshall_unicode_ptr(server, true)
  557.     
  558. --        [in]   [string,charset(UTF16)] uint16 *client,
  559.     arguments = arguments .. msrpctypes.marshall_unicode_ptr(nil)
  560.  
  561. --        [in]   [string,charset(UTF16)] uint16 *user,
  562.     arguments = arguments .. msrpctypes.marshall_unicode_ptr(nil)
  563.  
  564. --        [in,out]   uint32 level,
  565.     arguments = arguments .. msrpctypes.marshall_int32(10) -- 10 seems to be the only useful one allowed anonymously
  566.  
  567. --        [in,out,switch_is(level)]   srvsvc_NetSessCtr ctr,
  568.     arguments = arguments .. msrpctypes.marshall_srvsvc_NetSessCtr(10, {array=nil})
  569.  
  570. --        [in]   uint32 max_buffer,
  571.     arguments = arguments .. msrpctypes.marshall_int32(0xFFFFFFFF)
  572.  
  573. --        [out]   uint32 totalentries,
  574. --        [in,out]   uint32 *resume_handle
  575.     arguments = arguments .. msrpctypes.marshall_int32_ptr(0)
  576.  
  577.  
  578.     -- Do the call
  579.     status, result = call_function(smbstate, 0x0C, arguments)
  580.     if(status ~= true) then
  581.         return false, result
  582.     end
  583.  
  584.     stdnse.print_debug(3, "MSRPC: NetSessEnum() returned successfully")
  585.  
  586.     -- Make arguments easier to use
  587.     arguments = result['arguments']
  588.     pos = 1
  589.  
  590.     local count
  591.     local sessions = {}
  592.     local referent_id
  593. --        [in]   [string,charset(UTF16)] uint16 *server_unc,
  594. --        [in]   [string,charset(UTF16)] uint16 *client,
  595. --        [in]   [string,charset(UTF16)] uint16 *user,
  596. --        [in,out]   uint32 level,
  597.     pos, result['level'] = msrpctypes.unmarshall_int32(arguments, pos)
  598.  
  599. --        [in,out,switch_is(level)]   srvsvc_NetSessCtr ctr,
  600.     pos, result['ctr'] = msrpctypes.unmarshall_srvsvc_NetSessCtr(arguments, pos)
  601.     if(pos == nil) then
  602.         return false, "unmarshall_srvsvc_NetSessCtr() returned an error"
  603.     end
  604.  
  605. --        [in]   uint32 max_buffer,
  606. --        [out]   uint32 totalentries,
  607.     pos, result['totalentries'] = msrpctypes.unmarshall_int32(arguments, pos)
  608.  
  609. --        [in,out]   uint32 *resume_handle
  610.     pos, result['resume_handle'] = msrpctypes.unmarshall_int32_ptr(arguments, pos)
  611.  
  612.  
  613.     pos, result['return'] = msrpctypes.unmarshall_int32(arguments, pos)
  614.     if(result['return'] == nil) then
  615.         return false, "Read off the end of the packet (srvsvc.netsessenum)"
  616.     end
  617.     if(result['return'] ~= 0) then
  618.         return false, smb.get_status_name(result['return']) .. " (srvsvc.netsessenum)"
  619.     end
  620.  
  621.     return true, result
  622. end
  623.  
  624. --- Calls the <code>NetServerGetStatistics</code> function, which grabs a bunch of statistics on the server. 
  625. --  This function requires administrator access to call.
  626. --
  627. -- Note: Wireshark 1.0.3 doesn't parse this packet properly. 
  628. --
  629. --@param smbstate The SMB state table
  630. --@param server   The IP or name of the server (I don't think this is actually used, but it's
  631. --                good practice to send it). 
  632. --
  633. --@return A table containing the following values:
  634. --  * 'start'       The time when statistics collection started (or when the statistics were last cleared). The value is 
  635. --                stored as the number of seconds that have elapsed since 00:00:00, January 1, 1970, GMT. To calculate 
  636. --                the length of time that statistics have been collected, subtract the value of this member from the 
  637. --                present time. 'start_date' is the date as a string. 
  638. --  * 'fopens'      The number of times a file is opened on a server. This includes the number of times named pipes are opened.
  639. --  * 'devopens'    The number of times a server device is opened.
  640. --  * 'jobsqueued'  The number of server print jobs spooled.
  641. --  * 'sopens'      The number of times the server session started.
  642. --  * 'stimedout'   The number of times the server session automatically disconnected.
  643. --  * 'serrorout'   The number of times the server sessions failed with an error.
  644. --  * 'pwerrors'    The number of server password violations.
  645. --  * 'permerrors'  The number of server access permission errors.
  646. --  * 'syserrors'   The number of server system errors.
  647. --  * 'bytessent'   The number of server bytes sent to the network.
  648. --  * 'bytesrcvd'   The number of server bytes received from the network.
  649. --  * 'avresult'  The average server result time (in milliseconds).
  650. --  * 'reqbufneed'  The number of times the server required a request buffer but failed to allocate one. This value indicates that the server parameters may need adjustment.
  651. --  * 'bigbufneed'  The number of times the server required a big buffer but failed to allocate one. This value indicates that the server parameters may need adjustment.
  652. function srvsvc_netservergetstatistics(smbstate, server)
  653.     local i, j
  654.     local status, result
  655.     local arguments
  656.     local pos, align
  657.  
  658.     local service = "SERVICE_SERVER"
  659.  
  660.     stdnse.print_debug(2, "MSRPC: Calling NetServerGetStatistics() [%s]", smbstate['ip'])
  661.  
  662. --        [in]      [string,charset(UTF16)] uint16 *server_unc,
  663.     arguments = msrpctypes.marshall_unicode_ptr(server_unc, true)
  664.  
  665. --        [in]      [string,charset(UTF16)] uint16 *service,
  666.     arguments = arguments .. msrpctypes.marshall_unicode_ptr(service, true)
  667.  
  668. --        [in]      uint32 level,
  669.     arguments = arguments .. msrpctypes.marshall_int32(0)
  670.  
  671. --        [in]      uint32 options,
  672.     arguments = arguments .. msrpctypes.marshall_int32(0)
  673.  
  674. --        [out]     srvsvc_Statistics stat
  675.  
  676.  
  677.     -- Do the call
  678.     status, result = call_function(smbstate, 0x18, arguments)
  679.     if(status ~= true) then
  680.         return false, result
  681.     end
  682.  
  683.     stdnse.print_debug(3, "MSRPC: NetServerGetStatistics() returned successfully")
  684.  
  685.     -- Make arguments easier to use
  686.     arguments = result['arguments']
  687.     pos = 1
  688.  
  689. --        [in]      [string,charset(UTF16)] uint16 *server_unc,
  690. --        [in]      [string,charset(UTF16)] uint16 *service,
  691. --        [in]      uint32 level,
  692. --        [in]      uint32 options,
  693. --        [out]     srvsvc_Statistics stat
  694.     pos, result['stat'] = msrpctypes.unmarshall_srvsvc_Statistics_ptr(arguments, pos)
  695.  
  696.     pos, result['return'] = msrpctypes.unmarshall_int32(arguments, pos)
  697.     if(result['return'] == nil) then
  698.         return false, "Read off the end of the packet (srvsvc.netservergetstatistics)"
  699.     end
  700.     if(result['return'] ~= 0) then
  701.         return false, smb.get_status_name(result['return']) .. " (srvsvc.netservergetstatistics)"
  702.     end
  703.  
  704.     return true, result
  705. end
  706.  
  707. ---Call the NetPathCompare() function, which indirectly calls NetPathCanonicalize(), 
  708. -- the target of ms08-067. I'm currently only using this to trigger ms08-067. 
  709. --
  710. -- The string used by Metasploit and other free tools to check for this vulnerability is
  711. -- '\AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\..\n'. On vulnerable systems, this will be
  712. -- accepted and this function will return '0'. On patched systems, this will be rejected
  713. -- and return <code>ERROR_INVALID_PARAMETER</code>. 
  714. --
  715. -- Note that the srvsvc.exe process occasionally crashes when attempting this. 
  716. --
  717. --@param smbstate  The SMB state table
  718. --@param server    The IP or Hostname of the server (seems to be ignored but it's a good idea to have it)
  719. --@param path1     The first path to compare
  720. --@param path2     The second path to compare
  721. --@param pathtype  The pathtype to pass to the function (I always use '1')
  722. --@param pathflags The pathflags to pass to the function (I always use '0')
  723. --@return (status, result) If status is false, result is an error message. Otherwise, result is a table of values containing
  724. -- 'return'. 
  725. function srvsvc_netpathcompare(smbstate, server, path1, path2, pathtype, pathflags)
  726.     local i, j
  727.     local status, result
  728.     local arguments
  729.     local pos, align
  730.  
  731.     stdnse.print_debug(2, "MSRPC: Calling NetPathCompare(%s, %s) [%s]", path1, path2, smbstate['ip'])
  732.  
  733. --      [in]   [string,charset(UTF16)] uint16 *server_unc,
  734.     arguments = msrpctypes.marshall_unicode_ptr(server, true)
  735.  
  736. --      [in]   [string,charset(UTF16)] uint16 path1[],
  737.     arguments = arguments .. msrpctypes.marshall_unicode(path1, true)
  738.  
  739. --      [in]   [string,charset(UTF16)] uint16 path2[],
  740.     arguments = arguments .. msrpctypes.marshall_unicode(path2, true)
  741.  
  742. --      [in]    uint32 pathtype,
  743.     arguments = arguments .. msrpctypes.marshall_int32(pathtype)
  744.  
  745. --      [in]    uint32 pathflags
  746.     arguments = arguments .. msrpctypes.marshall_int32(pathflags)
  747.  
  748.     -- Do the call
  749.     status, result = call_function(smbstate, 0x20, arguments)
  750.     if(status ~= true) then
  751.         return false, result
  752.     end
  753.  
  754.     stdnse.print_debug(3, "MSRPC: NetPathCompare() returned successfully")
  755.  
  756.     -- Make arguments easier to use
  757.     arguments = result['arguments']
  758.     pos = 1
  759.  
  760.  
  761. --      [in]   [string,charset(UTF16)] uint16 *server_unc,
  762. --      [in]   [string,charset(UTF16)] uint16 path1[],
  763. --      [in]   [string,charset(UTF16)] uint16 path2[],
  764. --      [in]    uint32 pathtype,
  765. --      [in]    uint32 pathflags
  766.  
  767.     pos, result['return'] = msrpctypes.unmarshall_int32(arguments, pos)
  768.  
  769.     if(result['return'] == nil) then
  770.         return false, "Read off the end of the packet (srvsvc.netpathcompare)"
  771.     end
  772.     if(result['return'] ~= 0) then
  773.         return false, smb.get_status_name(result['return']) .. " (srvsvc.netpathcompare)"
  774.     end
  775.  
  776.     return true, result
  777.  
  778. end
  779.  
  780.  
  781. ---Call the NetPathCanonicalize() function, which is the target of ms08-067. 
  782. --
  783. --@param smbstate  The SMB state table
  784. --@param server    The IP or Hostname of the server (seems to be ignored but it's a good idea to have it)
  785. --@param path      The path to canonicalize
  786. --@return (status, result, error_result) If status is false, result is an error message and error_result is
  787. --        the result table. Otherwise, result is a table of values. 
  788. function srvsvc_netpathcanonicalize(smbstate, server, path)
  789.     local i, j
  790.     local status, result
  791.     local arguments
  792.     local pos, align
  793.  
  794.     stdnse.print_debug(2, "MSRPC: Calling NetPathCanonicalize(%s) [%s]", path, smbstate['ip'])
  795.  
  796. --        [in]   [string,charset(UTF16)] uint16 *server_unc,
  797.     arguments = msrpctypes.marshall_unicode_ptr(server, true)
  798. --        [in]   [string,charset(UTF16)] uint16 path[],
  799.     arguments = arguments .. msrpctypes.marshall_unicode(path, true)
  800. --        [out]  [size_is(maxbuf)] uint8 can_path[],
  801. --        [in]   uint32 maxbuf,
  802.     arguments = arguments .. msrpctypes.marshall_int32(2)
  803.  
  804. --        [in]   [string,charset(UTF16)] uint16 prefix[],
  805.     arguments = arguments .. msrpctypes.marshall_unicode("\\", true)
  806.  
  807. --        [in,out] uint32 pathtype,
  808.     arguments = arguments .. msrpctypes.marshall_int32(1)
  809. --        [in]    uint32 pathflags
  810.     arguments = arguments .. msrpctypes.marshall_int32(1)
  811.  
  812.  
  813.     -- Do the call
  814.     status, result = call_function(smbstate, 0x1F, arguments)
  815.     if(status ~= true) then
  816.         return false, result
  817.     end
  818.  
  819.     stdnse.print_debug(3, "MSRPC: NetPathCanonicalize() returned successfully")
  820.  
  821.     -- Make arguments easier to use
  822.     arguments = result['arguments']
  823.     pos = 1
  824.  
  825. --        [in]   [string,charset(UTF16)] uint16 *server_unc,
  826. --        [in]   [string,charset(UTF16)] uint16 path[],
  827. --        [out]  [size_is(maxbuf)] uint8 can_path[],A
  828. --        [in]   uint32 maxbuf,
  829. --        [in]   [string,charset(UTF16)] uint16 prefix[],
  830. --        [in,out] uint32 pathtype,
  831. --        [in]    uint32 pathflags
  832.  
  833.     -- NOTE: This isn't being done correctly.. due to Wireshark's broken parsing, 
  834.     -- and Samba's possibly-broken definition, I'm not sure how this is supposed
  835.     -- to be parsed. 
  836.     pos, result['max_count'] = msrpctypes.unmarshall_int32(arguments, pos)
  837.     pos, result['can_path']  = msrpctypes.unmarshall_int32(arguments, pos)
  838.     pos, result['type']      = msrpctypes.unmarshall_int32(arguments, pos) 
  839.     pos, result['return']    = msrpctypes.unmarshall_int32(arguments, pos)
  840.  
  841.     if(result['return'] == nil) then
  842.         return false, "Read off the end of the packet (srvsvc.netpathcanonicalize)"
  843.     end
  844.     if(result['return'] ~= 0) then
  845.         return false, smb.get_status_name(result['return']) .. " (srvsvc.netpathcanonicalize)", result
  846.     end
  847.  
  848.     return true, result
  849.  
  850. end
  851.  
  852.  
  853.  
  854.  
  855.  
  856. ---A proxy to a <code>msrpctypes</code> function that converts a PasswordProperties to an english string. 
  857. -- I implemented this as a proxy so scripts don't have to make direct calls to <code>msrpctypes</code>
  858. -- functions.
  859. --
  860. --@param val The value to convert.
  861. --@return A string that can be displayed to the user. 
  862. function samr_PasswordProperties_tostr(val)
  863.     return msrpctypes.samr_PasswordProperties_tostr(val)
  864. end
  865.  
  866. ---A proxy to a <code>msrpctypes</code> function that converts a AcctFlags to an english string. 
  867. -- I implemented this as a proxy so scripts don't have to make direct calls to <code>msrpctypes</code>
  868. -- functions.
  869. --
  870. --@param val The value to convert.
  871. --@return A string that can be displayed to the user. 
  872. function samr_AcctFlags_tostr(val)
  873.     return msrpctypes.samr_AcctFlags_tostr(val)
  874. end
  875.  
  876. ---Call the <code>connect4</code> function, to obtain a "connect handle". This must be done before calling many 
  877. -- of the SAMR functions. 
  878. --
  879. --@param smbstate  The SMB state table
  880. --@param server    The IP or Hostname of the server (seems to be ignored but it's a good idea to have it)
  881. --@return (status, result) If status is false, result is an error message. Otherwise, result is a table of values, the most
  882. --        useful one being 'connect_handle', which is required to call other functions. 
  883. function samr_connect4(smbstate, server)
  884.     local i, j
  885.     local status, result
  886.     local arguments
  887.     local pos, align
  888.  
  889.     stdnse.print_debug(2, "MSRPC: Calling Connect4() [%s]", smbstate['ip'])
  890.  
  891. -- [in,string,charset(UTF16)] uint16 *system_name,
  892.     arguments = msrpctypes.marshall_unicode_ptr("\\\\" .. server, true)
  893.     
  894. -- [in] uint32 unknown,
  895.     arguments = arguments .. msrpctypes.marshall_int32(0x02)
  896.  
  897. -- [in] samr_ConnectAccessMask access_mask,
  898.     arguments = arguments .. msrpctypes.marshall_samr_ConnectAccessMask("SAMR_ACCESS_ENUM_DOMAINS|SAMR_ACCESS_OPEN_DOMAIN")
  899. -- [out,ref]  policy_handle *connect_handle
  900.  
  901.  
  902.     -- Do the call
  903.     status, result = call_function(smbstate, 0x3E, arguments)
  904.     if(status ~= true) then
  905.         return false, result
  906.     end
  907.  
  908.     stdnse.print_debug(3, "MSRPC: Connect4() returned successfully")
  909.  
  910.     -- Make arguments easier to use
  911.     arguments = result['arguments']
  912.     pos = 1
  913. -- [in,string,charset(UTF16)] uint16 *system_name,
  914. -- [in] uint32 unknown,
  915. -- [in] samr_ConnectAccessMask access_mask,
  916. -- [out,ref]  policy_handle *connect_handle
  917.     pos, result['connect_handle'] = msrpctypes.unmarshall_policy_handle(arguments, pos)
  918.  
  919.     pos, result['return'] = msrpctypes.unmarshall_int32(arguments, pos)
  920.     if(result['return'] == nil) then
  921.         return false, "Read off the end of the packet (samr.connect4)"
  922.     end
  923.     if(result['return'] ~= 0) then
  924.         return false, smb.get_status_name(result['return']) .. " (samr.connect4)"
  925.     end
  926.  
  927.     return true, result
  928. end
  929.  
  930. ---Call the <code>enumdomains</code> function, which returns a list of all domains in use by the system. 
  931. --
  932. --@param smbstate       The SMB state table
  933. --@param connect_handle The connect_handle, returned by samr_connect4()
  934. --@return (status, result) If status is false, result is an error message. Otherwise, result is a table of values, the most
  935. --        useful one being 'domains', which is a list of the domains. 
  936. function samr_enumdomains(smbstate, connect_handle)
  937.     local i, j
  938.     local status, result
  939.     local arguments
  940.     local result
  941.     local pos, align
  942.  
  943.     stdnse.print_debug(2, "MSRPC: Calling EnumDomains() [%s]", smbstate['ip'])
  944.  
  945. --        [in,ref]      policy_handle *connect_handle,
  946.     arguments = msrpctypes.marshall_policy_handle(connect_handle)
  947.     
  948. --        [in,out,ref]  uint32 *resume_handle,
  949.     arguments = arguments .. msrpctypes.marshall_int32(0)
  950.  
  951. --        [in]          uint32 buf_size,
  952.     arguments = arguments .. msrpctypes.marshall_int32(0x2000)
  953.  
  954. --        [out]         samr_SamArray *sam,
  955. --        [out]         uint32 num_entries
  956.  
  957.  
  958.     -- Do the call
  959.     status, result = call_function(smbstate, 0x06, arguments)
  960.     if(status ~= true) then
  961.         return false, result
  962.     end
  963.  
  964.     stdnse.print_debug(3, "MSRPC: EnumDomains() returned successfully")
  965.  
  966.     -- Make arguments easier to use
  967.     arguments = result['arguments']
  968.  
  969. --        [in,ref]      policy_handle *connect_handle,
  970. --        [in,out,ref]  uint32 *resume_handle,
  971.     pos, result['resume_handle'] = msrpctypes.unmarshall_int32(arguments, pos)
  972.  
  973. --        [in]          uint32 buf_size,
  974. --        [out]         samr_SamArray *sam,
  975.     pos, result['sam'] = msrpctypes.unmarshall_samr_SamArray_ptr(arguments, pos)
  976.  
  977. --        [out]         uint32 num_entries
  978.     pos, result['num_entries'] = msrpctypes.unmarshall_int32(arguments, pos)
  979.  
  980.     pos, result['return'] = msrpctypes.unmarshall_int32(arguments, pos)
  981.     if(result['return'] == nil) then
  982.         return false, "Read off the end of the packet (samr.enumdomains)"
  983.     end
  984.     if(result['return'] ~= 0) then
  985.         return false, smb.get_status_name(result['return']) .. " (samr.enumdomains)"
  986.     end
  987.  
  988.     return true, result
  989. end
  990.  
  991. ---Call the <code>LookupDomain</code> function, which converts a domain's name into its sid, which is
  992. -- required to do operations on the domain. 
  993. --
  994. --@param smbstate       The SMB state table
  995. --@param connect_handle The connect_handle, returned by <code>samr_connect4</code>
  996. --@param domain         The name of the domain (all domain names can be obtained with <code>samr_enumdomains</code>)
  997. --@return (status, result) If status is false, result is an error message. Otherwise, result is a table of values, the most
  998. --        useful one being 'sid', which is required to call other functions. 
  999. function samr_lookupdomain(smbstate, connect_handle, domain)
  1000.     local i, j
  1001.     local status, result
  1002.     local arguments
  1003.     local pos, align
  1004.     local referent_id
  1005.  
  1006.     stdnse.print_debug(2, "MSRPC: Calling LookupDomain(%s) [%s]", domain, smbstate['ip'])
  1007.  
  1008. --        [in,ref]  policy_handle *connect_handle,        
  1009.     arguments = msrpctypes.marshall_policy_handle(connect_handle)
  1010.  
  1011. --        [in,ref]  lsa_String *domain_name,
  1012.     arguments = arguments .. msrpctypes.marshall_lsa_String(domain)
  1013.  
  1014. --        [out]     dom_sid2 *sid
  1015.  
  1016.  
  1017.     -- Do the call
  1018.     status, result = call_function(smbstate, 0x05, arguments)
  1019.     if(status ~= true) then
  1020.         return false, result
  1021.     end
  1022.  
  1023.     stdnse.print_debug(3, "MSRPC: LookupDomain() returned successfully")
  1024.  
  1025.     -- Make arguments easier to use
  1026.     arguments = result['arguments']
  1027.  
  1028.  
  1029. --        [in,ref]  policy_handle *connect_handle,
  1030. --        [in,ref]  lsa_String *domain_name,
  1031. --        [out]     dom_sid2 *sid
  1032.     pos, result['sid'] = msrpctypes.unmarshall_dom_sid2_ptr(arguments, pos)
  1033.  
  1034.     pos, result['return'] = msrpctypes.unmarshall_int32(arguments, pos)
  1035.     if(result['return'] == nil) then
  1036.         return false, "Read off the end of the packet (samr.lookupdomain)"
  1037.     end
  1038.     if(result['return'] ~= 0) then
  1039.         return false, smb.get_status_name(result['return']) .. " (samr.lookupdomain)"
  1040.     end
  1041.  
  1042.     return true, result
  1043. end
  1044.  
  1045. ---Call <code>OpenDomain</code>, which returns a handle to the domain identified by the given sid. 
  1046. -- This is required before calling certain functions. 
  1047. --
  1048. --@param smbstate       The SMB state table
  1049. --@param connect_handle The connect_handle, returned by <code>samr_connect4</code>
  1050. --@param sid            The sid for the domain, returned by <code>samr_lookupdomain</code>
  1051. --@return (status, result) If status is false, result is an error message. Otherwise, result is a table of values, the most
  1052. --        useful one being 'domain_handle', which is used to call other functions. 
  1053. function samr_opendomain(smbstate, connect_handle, sid)
  1054.     local i, j
  1055.     local status, result
  1056.     local arguments
  1057.     local pos, align
  1058.  
  1059.     stdnse.print_debug(2, "MSRPC: Calling OpenDomain(%s) [%s]", sid, smbstate['ip'])
  1060.  
  1061. --        [in,ref]      policy_handle *connect_handle,
  1062.     arguments = msrpctypes.marshall_policy_handle(connect_handle)
  1063.  
  1064. --        [in]          samr_DomainAccessMask access_mask,
  1065.     arguments = arguments .. msrpctypes.marshall_samr_DomainAccessMask("DOMAIN_ACCESS_LOOKUP_INFO_1|DOMAIN_ACCESS_LOOKUP_INFO_2|DOMAIN_ACCESS_ENUM_ACCOUNTS|DOMAIN_ACCESS_OPEN_ACCOUNT")
  1066.  
  1067. --        [in,ref]      dom_sid2 *sid,
  1068.     arguments = arguments .. msrpctypes.marshall_dom_sid2(sid)
  1069.  
  1070. --        [out,ref]     policy_handle *domain_handle
  1071.  
  1072.  
  1073.     -- Do the call
  1074.     status, result = call_function(smbstate, 0x07, arguments)
  1075.     if(status ~= true) then
  1076.         return false, result
  1077.     end
  1078.  
  1079.     stdnse.print_debug(3, "MSRPC: OpenDomain() returned successfully")
  1080.  
  1081.     -- Make arguments easier to use
  1082.     arguments = result['arguments']
  1083.     pos = 1
  1084.  
  1085. --        [in,ref]      policy_handle *connect_handle,
  1086. --        [in]          samr_DomainAccessMask access_mask,
  1087. --        [in,ref]      dom_sid2 *sid,
  1088. --        [out,ref]     policy_handle *domain_handle
  1089.     pos, result['domain_handle'] = msrpctypes.unmarshall_policy_handle(arguments, pos)
  1090.  
  1091.     pos, result['return'] = msrpctypes.unmarshall_int32(arguments, pos)
  1092.     if(result['return'] == nil) then
  1093.         return false, "Read off the end of the packet (samr.opendomain)"
  1094.     end
  1095.     if(result['return'] ~= 0) then
  1096.         return false, smb.get_status_name(result['return']) .. " (samr.opendomain)"
  1097.     end
  1098.     
  1099.     return true, result
  1100. end
  1101.  
  1102. ---Call <code>EnumDomainUsers</code>, which returns a list of users only. To get more information about the users, the 
  1103. -- QueryDisplayInfo() function can be used. 
  1104. --
  1105. --@param smbstate       The SMB state table
  1106. --@param domain_handle  The domain_handle, returned by <code>samr_opendomain</code>
  1107. --@return (status, result) If status is false, result is an error message. Otherwise, result is a table of values, the most
  1108. --        useful one being 'names', which is a list of usernames in that domain. 
  1109. function samr_enumdomainusers(smbstate, domain_handle)
  1110.     local i, j
  1111.     local status, result
  1112.     local arguments
  1113.     local pos, align
  1114.  
  1115.     stdnse.print_debug(2, "MSRPC: Calling EnumDomainUsers() [%s]", smbstate['ip'])
  1116.  
  1117. --        [in,ref]      policy_handle *domain_handle,
  1118.     arguments = msrpctypes.marshall_policy_handle(domain_handle)
  1119.  
  1120. --        [in,out,ref]  uint32 *resume_handle,
  1121.     arguments = arguments .. msrpctypes.marshall_int32_ptr(nil)
  1122.  
  1123. --        [in]          samr_AcctFlags acct_flags,
  1124.     arguments = arguments .. msrpctypes.marshall_samr_AcctFlags("ACB_NONE")
  1125.  
  1126. --        [in]          uint32 max_size,
  1127.     arguments = arguments .. msrpctypes.marshall_int32(0x0400)
  1128.  
  1129. --        [out]         samr_SamArray *sam,
  1130. --        [out]         uint32 num_entries
  1131.  
  1132.  
  1133.     -- Do the call
  1134.     status, result = call_function(smbstate, 0x0d, arguments)
  1135.     if(status ~= true) then
  1136.         return false, result
  1137.     end
  1138.  
  1139.     stdnse.print_debug(3, "MSRPC: EnumDomainUsers() returned successfully")
  1140.  
  1141.     -- Make arguments easier to use
  1142.     arguments = result['arguments']
  1143.     pos = 1
  1144.  
  1145. --        [in,ref]      policy_handle *domain_handle,
  1146. --        [in,out,ref]  uint32 *resume_handle,
  1147.     pos, result['resume_handle'] = msrpctypes.unmarshall_int32(arguments, pos)
  1148.  
  1149. --        [in]          samr_AcctFlags acct_flags,
  1150. --        [in]          uint32 max_size,
  1151. --        [out]         samr_SamArray *sam,
  1152.     pos, result['sam'] = msrpctypes.unmarshall_samr_SamArray_ptr(arguments, pos)
  1153.  
  1154. --        [out]         uint32 num_entries
  1155.     pos, result['num_entries'] = msrpctypes.unmarshall_int32(arguments, pos)
  1156.  
  1157.     pos, result['return'] = msrpctypes.unmarshall_int32(arguments, pos)
  1158.     if(result['return'] == nil) then
  1159.         return false, "Read off the end of the packet (samr.enumdomainusers)"
  1160.     end
  1161.     if(result['return'] ~= 0) then
  1162.         return false, smb.get_status_name(result['return']) .. " (samr.enumdomainusers)"
  1163.     end
  1164.     
  1165.     return true, result
  1166.  
  1167. end
  1168.  
  1169. ---Call <code>QueryDisplayInfo</code>, which returns a list of users with accounts on the system, as well as extra information about
  1170. -- them (their full name and description). 
  1171. --
  1172. -- I found in testing that trying to get all the users at once is a mistake, it returns ERR_BUFFER_OVERFLOW, so instead I'm 
  1173. -- only reading one user at a time. My recommendation is to start at <code>index</code> = 0, and increment until you stop getting
  1174. -- an error indicator in <code>result['return']</code>. 
  1175. --
  1176. --@param smbstate       The SMB state table
  1177. --@param domain_handle  The domain handle, returned by <code>samr_opendomain</code>
  1178. --@param index          The index of the user to check; the first user is 0, next is 1, etc.
  1179. --@param count          [optional] The number of users to return; you may want to be careful about going too high. Default: 1. 
  1180. --@return (status, result) If status is false, result is an error message. Otherwise, result is a table of values, the most
  1181. --        useful ones being 'names', a list of all the usernames, and 'details', a further list of tables with the elements
  1182. --        'name', 'fullname', and 'description' (note that any of them can be nil if the server didn't return a value). Finally,
  1183. --        'flags' is the numeric flags for the user, while 'flags_list' is an array of strings, representing the flags.
  1184. function samr_querydisplayinfo(smbstate, domain_handle, index, count)
  1185.     local i, j
  1186.     local status, result
  1187.     local arguments
  1188.     local pos, align
  1189.  
  1190.     if(count == nil) then
  1191.         count = 1
  1192.     end
  1193.  
  1194.     -- This loop is because, in my testing, if I asked for all the results at once, it would blow up (ERR_BUFFER_OVERFLOW). So, instead,
  1195.     -- I put a little loop here and grab the names individually. 
  1196.     stdnse.print_debug(2, "MSRPC: Calling QueryDisplayInfo(%d) [%s]", index, smbstate['ip'])
  1197.  
  1198. --        [in,ref]    policy_handle *domain_handle,
  1199.     arguments = msrpctypes.marshall_policy_handle(domain_handle)
  1200.  
  1201. --        [in]        uint16 level,
  1202.     arguments = arguments .. msrpctypes.marshall_int16(1) -- Level (1 = users, 3 = groups, 4 = usernames only)
  1203.  
  1204. --        [in]        uint32 start_idx,
  1205.     arguments = arguments .. msrpctypes.marshall_int32(index)
  1206.  
  1207. --        [in]        uint32 max_entries,
  1208.     arguments = arguments .. msrpctypes.marshall_int32(count)
  1209.  
  1210. --        [in]        uint32 buf_size,
  1211.     arguments = arguments .. msrpctypes.marshall_int32(0x7FFFFFFF)
  1212.  
  1213. --        [out]       uint32 total_size,
  1214. --        [out]       uint32 returned_size,
  1215. --        [out,switch_is(level)] samr_DispInfo info
  1216.  
  1217.  
  1218.     -- Do the call
  1219.     status, result = call_function(smbstate, 0x28, arguments)
  1220.     if(status ~= true) then
  1221.         return false, result
  1222.     end
  1223.     
  1224.     stdnse.print_debug(3, "MSRPC: QueryDisplayInfo() returned successfully", i)
  1225.  
  1226.     -- Make arguments easier to use
  1227.     arguments = result['arguments']
  1228.     pos = 1
  1229.  
  1230. --        [in,ref]    policy_handle *domain_handle,
  1231. --        [in]        uint16 level,
  1232. --        [in]        uint32 start_idx,
  1233. --        [in]        uint32 max_entries,
  1234. --        [in]        uint32 buf_size,
  1235. --        [out]       uint32 total_size,
  1236.     pos, result['total_size'] = msrpctypes.unmarshall_int32(arguments, pos)
  1237.  
  1238. --        [out]       uint32 returned_size,
  1239.     pos, result['returned_size'] = msrpctypes.unmarshall_int32(arguments, pos)
  1240. --        [out,switch_is(level)] samr_DispInfo info
  1241.     pos, result['info'] = msrpctypes.unmarshall_samr_DispInfo(arguments, pos)
  1242.     if(pos == nil) then
  1243.         return false, "SMB: An error occurred while calling unmarshall_samr_DispInfo"
  1244.     end
  1245.  
  1246.     -- Get the return value
  1247.     pos, result['return'] = msrpctypes.unmarshall_int32(arguments, pos)
  1248.     if(result['return'] == nil) then
  1249.         return false, "Read off the end of the packet (samr.querydisplayall)"
  1250.     end
  1251.     if(result['return'] ~= 0 and result['return'] ~= smb.status_codes['NT_STATUS_MORE_ENTRIES']) then
  1252.         return false, smb.get_status_name(result['return']) .. " (samr.querydisplayinfo)"
  1253.     end
  1254.  
  1255.     return true, result
  1256. end
  1257.  
  1258. ---Call <code>QueryDomainInfo2</code>, which grabs various data about a domain. 
  1259. --
  1260. --@param smbstate       The SMB state table
  1261. --@param domain_handle  The domain_handle, returned by <code>samr_opendomain</code>
  1262. --@param level          The level, which determines which type of information to query for. See the @return section
  1263. --                      for details. 
  1264. --@return (status, result) If status is false, result is an error message. Otherwise, result is a table of values, 
  1265. --        and the values that are returned are dependent on the 'level' settings:
  1266. --        Level 1:
  1267. --         'min_password_length' (in characters)
  1268. --         'password_history_length' (in passwords)
  1269. --         'password_properties'
  1270. --         'password_properties_list' (array of strings)
  1271. --         'max_password_age' (in days)
  1272. --         'min_password_age' (in days)
  1273. --        Level 8
  1274. --         'create_time' (1/10ms since 1601)
  1275. --         'create_date' (string)
  1276. --        Level 12
  1277. --         'lockout_duration' (in minutes)
  1278. --         'lockout_window' (in minutes)
  1279. --         'lockout_threshold' (in attempts)
  1280. function samr_querydomaininfo2(smbstate, domain_handle, level)
  1281.     local i, j
  1282.     local status, result
  1283.     local arguments
  1284.     local pos, align
  1285.  
  1286.     stdnse.print_debug(2, "MSRPC: Calling QueryDomainInfo2(%d) [%s]", level, smbstate['ip'])
  1287.  
  1288. --        [in,ref]      policy_handle *domain_handle,
  1289.     arguments = msrpctypes.marshall_policy_handle(domain_handle)
  1290.  
  1291. --        [in]          uint16 level,
  1292.     arguments = arguments .. msrpctypes.marshall_int32(level)
  1293.  
  1294. --        [out,switch_is(level)] samr_DomainInfo *info
  1295.  
  1296.     -- Do the call
  1297.     status, result = call_function(smbstate, 0x2e, arguments)
  1298.     if(status ~= true) then
  1299.         return false, result
  1300.     end
  1301.  
  1302.     stdnse.print_debug(3, "MSRPC: QueryDomainInfo2() returned successfully")
  1303.  
  1304.     -- Make arguments easier to use
  1305.     arguments = result['arguments']
  1306.     pos = 1
  1307.  
  1308. --        [in,ref]      policy_handle *domain_handle,
  1309. --        [in]          uint16 level,
  1310. --        [out,switch_is(level)] samr_DomainInfo *info
  1311.     pos, result['info'] = msrpctypes.unmarshall_samr_DomainInfo_ptr(arguments, pos)
  1312.     if(pos == nil) then
  1313.         return false, "unmarshall_samr_DomainInfo_ptr() returned an error"
  1314.     end
  1315.  
  1316.     pos, result['return'] = msrpctypes.unmarshall_int32(arguments, pos)
  1317.     if(result['return'] == nil) then
  1318.         return false, "Read off the end of the packet (samr.querydomaininfo2)"
  1319.     end
  1320.     if(result['return'] ~= 0) then
  1321.         return false, smb.get_status_name(result['return']) .. " (samr.querydomaininfo2)"
  1322.     end
  1323.     
  1324.     return true, result
  1325. end
  1326.  
  1327. ---Call the <code>close</code> function, which closes a handle of any type (for example, domain_handle or connect_handle)
  1328. --@param smbstate The SMB state table
  1329. --@param handle   The handle to close
  1330. --@return (status, result) If status is false, result is an error message. Otherwise, result is potentially
  1331. --        a table of values, none of which are likely to be used. 
  1332. function samr_close(smbstate, handle)
  1333.     local i, j
  1334.     local status, result
  1335.     local arguments
  1336.     local pos, align
  1337.  
  1338.  
  1339.     stdnse.print_debug(2, "MSRPC: Calling Close() [%s]", smbstate['ip'])
  1340.  
  1341. --        [in,out,ref]  policy_handle *handle
  1342.     arguments = msrpctypes.marshall_policy_handle(handle)
  1343.  
  1344.     -- Do the call
  1345.     status, result = call_function(smbstate, 0x01, arguments)
  1346.     if(status ~= true) then
  1347.         return false, result
  1348.     end
  1349.  
  1350.     stdnse.print_debug(3, "MSRPC: Close() returned successfully")
  1351.  
  1352.     -- Make arguments easier to use
  1353.     arguments = result['arguments']
  1354.     pos = 1
  1355.  
  1356. --        [in,out,ref]  policy_handle *handle
  1357.     pos, result['handle'] = msrpctypes.unmarshall_policy_handle(arguments, pos)
  1358.  
  1359.     pos, result['return'] = msrpctypes.unmarshall_int32(arguments, pos)
  1360.     if(result['return'] == nil) then
  1361.         return false, "Read off the end of the packet (samr.close)"
  1362.     end
  1363.     if(result['return'] ~= 0) then
  1364.         return false, smb.get_status_name(result['return']) .. " (samr.close)"
  1365.     end
  1366.     
  1367.     return true, result
  1368. end
  1369.  
  1370. ---Call the <code>LsarOpenPolicy2</code> function, to obtain a "policy handle". This must be done before calling many 
  1371. -- of the LSA functions. 
  1372. --
  1373. --@param smbstate  The SMB state table
  1374. --@param server    The IP or Hostname of the server (seems to be ignored but it's a good idea to have it)
  1375. --@return (status, result) If status is false, result is an error message. Otherwise, result is a table of values, the most
  1376. --        useful one being 'policy_handle', which is required to call other functions. 
  1377. function lsa_openpolicy2(smbstate, server)
  1378.     local i, j
  1379.     local status, result
  1380.     local arguments
  1381.     local pos, align
  1382.  
  1383.     stdnse.print_debug(2, "MSRPC: Calling LsarOpenPolicy2() [%s]", smbstate['ip'])
  1384.  
  1385. --        [in,unique]      [string,charset(UTF16)] uint16 *system_name,
  1386.     arguments = msrpctypes.marshall_unicode_ptr(server, true)
  1387.  
  1388. --        [in]  lsa_ObjectAttribute *attr,
  1389.     arguments = arguments .. msrpctypes.marshall_lsa_ObjectAttribute()
  1390.  
  1391. --        [in]      uint32 access_mask,
  1392.     arguments = arguments .. msrpctypes.marshall_int32(0x00000800)
  1393.  
  1394. --        [out] policy_handle *handle    
  1395.  
  1396.     -- Do the call
  1397.     status, result = call_function(smbstate, 0x2C, arguments)
  1398.     if(status ~= true) then
  1399.         return false, result
  1400.     end
  1401.  
  1402.     stdnse.print_debug(3, "MSRPC: LsarOpenPolicy2() returned successfully")
  1403.  
  1404.     -- Make arguments easier to use
  1405.     arguments = result['arguments']
  1406.     pos = 1
  1407.  
  1408. --        [in,unique]      [string,charset(UTF16)] uint16 *system_name,
  1409. --        [in]  lsa_ObjectAttribute *attr,
  1410. --        [in]      uint32 access_mask,
  1411. --        [out] policy_handle *handle    
  1412.     pos, result['policy_handle'] = msrpctypes.unmarshall_policy_handle(arguments, pos)
  1413.     pos, result['return'] = msrpctypes.unmarshall_int32(arguments, pos)
  1414.  
  1415.     if(result['return'] == nil) then
  1416.         return false, "Read off the end of the packet (lsa.openpolicy2)"
  1417.     end
  1418.     if(result['return'] ~= 0) then
  1419.         return false, smb.get_status_name(result['return']) .. " (lsa.openpolicy2)"
  1420.     end
  1421.  
  1422.     return true, result
  1423. end
  1424.  
  1425. ---Call the <code>LsarLookupNames2</code> function, to convert the server's name into a sid. 
  1426. --
  1427. --@param smbstate      The SMB state table
  1428. --@param policy_handle The policy handle returned by <code>lsa_openpolicy2</code>
  1429. --@param names         An array of names to look up. To get a SID, only one of the names needs to be valid. 
  1430. --@return (status, result) If status is false, result is an error message. Otherwise, result is a table of values. 
  1431. --        The most useful result is 'domains', which is a list of domains known to the server. And, for each of the
  1432. --        domains, there is a 'name' entry, which is a string, and a 'sid' entry, which is yet another object which
  1433. --        can be passed to functions that understand SIDs. 
  1434. function lsa_lookupnames2(smbstate, policy_handle, names)
  1435.     local i, j
  1436.     local status, result
  1437.     local arguments
  1438.     local result
  1439.     local pos, align
  1440.  
  1441.     stdnse.print_debug(2, "MSRPC: Calling LsarLookupNames2(%s) [%s]", stdnse.strjoin(", ", names), smbstate['ip'])
  1442.  
  1443.  
  1444. --        [in]     policy_handle *handle,
  1445.     arguments = msrpctypes.marshall_policy_handle(policy_handle)
  1446.  
  1447. --        [in,range(0,1000)] uint32 num_names,
  1448.     arguments = arguments .. msrpctypes.marshall_int32(#names)
  1449.  
  1450. --        [in,size_is(num_names)]  lsa_String names[],
  1451.     arguments = arguments .. msrpctypes.marshall_lsa_String_array(names)
  1452.  
  1453. --        [out,unique]        lsa_RefDomainList *domains,
  1454. --        [in,out] lsa_TransSidArray2 *sids,
  1455.     arguments = arguments .. msrpctypes.marshall_lsa_TransSidArray2({nil})
  1456.  
  1457. --        [in]         lsa_LookupNamesLevel level,
  1458.     arguments = arguments .. msrpctypes.marshall_lsa_LookupNamesLevel("LOOKUP_NAMES_ALL")
  1459.  
  1460. --        [in,out] uint32 *count,
  1461.     arguments = arguments .. msrpctypes.marshall_int32(0)
  1462.     
  1463. --        [in]         uint32 unknown1,
  1464.     arguments = arguments .. msrpctypes.marshall_int32(0)
  1465.  
  1466. --        [in]         uint32 unknown2
  1467.     arguments = arguments .. msrpctypes.marshall_int32(2)
  1468.  
  1469.  
  1470.  
  1471.     -- Do the call
  1472.     status, result = call_function(smbstate, 0x3a, arguments)
  1473.     if(status ~= true) then
  1474.         return false, result
  1475.     end
  1476.  
  1477.     stdnse.print_debug(3, "MSRPC: LsarLookupNames2() returned successfully")
  1478.  
  1479.     -- Make arguments easier to use
  1480.     arguments = result['arguments']
  1481.     pos = 1
  1482.  
  1483.  
  1484. --        [in]     policy_handle *handle,
  1485. --        [in,range(0,1000)] uint32 num_names,
  1486. --        [in,size_is(num_names)]  lsa_String names[],
  1487. --        [out,unique]        lsa_RefDomainList *domains,
  1488.     pos, result['domains'] = msrpctypes.unmarshall_lsa_RefDomainList_ptr(arguments, pos)
  1489.  
  1490. --        [in,out] lsa_TransSidArray2 *rids,
  1491.     pos, result['rids'] = msrpctypes.unmarshall_lsa_TransSidArray2(arguments, pos)
  1492.     
  1493. --        [in]         lsa_LookupNamesLevel level,
  1494. --        [in,out] uint32 *count,
  1495.     pos, result['count'] = msrpctypes.unmarshall_int32(arguments, pos)
  1496.  
  1497. --        [in]         uint32 unknown1,
  1498. --        [in]         uint32 unknown2
  1499.  
  1500.  
  1501.     pos, result['return'] = msrpctypes.unmarshall_int32(arguments, pos)
  1502.     if(result['return'] == nil) then
  1503.         return false, "Read off the end of the packet (lsa.lookupnames2)"
  1504.     end
  1505.     if(result['return'] == smb.status_codes['NT_STATUS_NONE_MAPPED']) then
  1506.         return false, "Couldn't find any names the host recognized"
  1507.     end
  1508.  
  1509.     if(result['return'] ~= 0 and result['return'] ~= smb.status_codes['NT_STATUS_SOME_NOT_MAPPED']) then
  1510.         return false, smb.get_status_name(result['return']) .. " (lsa.lookupnames2)"
  1511.     end
  1512.  
  1513.     return true, result
  1514. end
  1515.  
  1516. ---Call the <code>LsarLookupSids2</code> function, to convert a list of SIDs to their names
  1517. --
  1518. --@param smbstate      The SMB state table
  1519. --@param policy_handle The policy handle returned by <code>lsa_openpolicy2</code>
  1520. --@param sids          The SIDs to look up (will probably be the server's SID with "-[rid]" appended
  1521. --@return (status, result) If status is false, result is an error message. Otherwise, result is a table of values. 
  1522. --        The element 'domains' is identical to the lookupnames2() element called 'domains'. The element 'names' is a 
  1523. --        list of strings, for the usernames (not necessary a 1:1 mapping with the RIDs), and the element 'details' is
  1524. --        a table containing more information about each name, even if the name wasn't found (this one is a 1:1 mapping
  1525. --        with the RIDs). 
  1526. function lsa_lookupsids2(smbstate, policy_handle, sids)
  1527.     local i, j
  1528.     local status, result
  1529.     local arguments
  1530.     local result
  1531.     local pos, align
  1532.  
  1533.     stdnse.print_debug(2, "MSRPC: Calling LsarLookupSids2(%s) [%s]", stdnse.strjoin(", ", sids), smbstate['ip'])
  1534.  
  1535. --        [in]     policy_handle *handle,
  1536.     arguments = msrpctypes.marshall_policy_handle(policy_handle)
  1537.     
  1538. --        [in]     lsa_SidArray *sids,
  1539.     arguments = arguments .. msrpctypes.marshall_lsa_SidArray(sids)
  1540.  
  1541. --        [out,unique]        lsa_RefDomainList *domains,
  1542. --        [in,out] lsa_TransNameArray2 *names,
  1543.     arguments = arguments .. msrpctypes.marshall_lsa_TransNameArray2(nil)
  1544.  
  1545. --        [in]         uint16 level,
  1546.     arguments = arguments .. msrpctypes.marshall_int16(1)
  1547.  
  1548. --        [in,out] uint32 *count,
  1549.     arguments = arguments .. msrpctypes.marshall_int32(0)
  1550.  
  1551. --        [in]         uint32 unknown1,
  1552.     arguments = arguments .. msrpctypes.marshall_int32(0)
  1553.  
  1554. --        [in]         uint32 unknown2
  1555.     arguments = arguments .. msrpctypes.marshall_int32(2)
  1556.  
  1557.  
  1558.     -- Do the call
  1559.     status, result = call_function(smbstate, 0x39, arguments)
  1560.     if(status ~= true) then
  1561.         return false, result
  1562.     end
  1563.  
  1564.     -- Make arguments easier to use
  1565.     arguments = result['arguments']
  1566.  
  1567. --        [in]     policy_handle *handle,
  1568. --        [in]     lsa_SidArray *sids,
  1569. --        [out,unique]        lsa_RefDomainList *domains,
  1570.     pos, result['domains'] = msrpctypes.unmarshall_lsa_RefDomainList_ptr(arguments, pos)
  1571.  
  1572. --        [in,out] lsa_TransNameArray2 *names,
  1573.     pos, result['names'] = msrpctypes.unmarshall_lsa_TransNameArray2(arguments, pos)
  1574.  
  1575. --        [in]         uint16 level,
  1576. --        [in,out] uint32 *count,
  1577.     local count
  1578.     pos, result['count'] = msrpctypes.unmarshall_int32(arguments, pos)
  1579.  
  1580. --        [in]         uint32 unknown1,
  1581. --        [in]         uint32 unknown2
  1582.  
  1583.     pos, result['return'] = msrpctypes.unmarshall_int32(arguments, pos)
  1584.     if(result['return'] == nil) then
  1585.         return false, "Read off the end of the packet (lsa.lookupnames2)"
  1586.     end
  1587.     if(result['return'] ~= 0 and result['return'] ~= smb.status_codes['NT_STATUS_SOME_NOT_MAPPED'] and result['return'] ~= smb.status_codes['NT_STATUS_NONE_MAPPED']) then
  1588.         return false, smb.get_status_name(result['return']) .. " (lsa.lookupsids2)"
  1589.     end
  1590.  
  1591.     stdnse.print_debug(3, "MSRPC: LsarLookupSids2(): Returning")
  1592.     return true, result
  1593.  
  1594. end
  1595.  
  1596. ---Call the <code>close</code> function, which closes a session created with a <code>lsa_openpolicy</code>-style function
  1597. --@param smbstate  The SMB state table
  1598. --@param handle    The handle to close
  1599. --@return (status, result) If status is false, result is an error message. Otherwise, result is potentially
  1600. --        a table of values, none of which are likely to be used. 
  1601. function lsa_close(smbstate, handle)
  1602.     local i, j
  1603.     local status, result
  1604.     local arguments
  1605.     local pos, align
  1606.  
  1607.     stdnse.print_debug(2, "MSRPC: Calling LsaClose() [%s]", smbstate['ip'])
  1608.  
  1609. --        [in,out]     policy_handle *handle
  1610.     arguments = msrpctypes.marshall_policy_handle(handle)
  1611.  
  1612.     -- Do the call
  1613.     status, result = call_function(smbstate, 0x00, arguments)
  1614.     if(status ~= true) then
  1615.         return false, result
  1616.     end
  1617.  
  1618.     -- Make arguments easier to use
  1619.     arguments = result['arguments']
  1620.     pos = 1
  1621.  
  1622. --        [in,out]     policy_handle *handle
  1623.     pos, result['handle'] = msrpctypes.unmarshall_policy_handle(arguments, pos)
  1624.  
  1625.     pos, result['return'] = msrpctypes.unmarshall_int32(arguments, pos)
  1626.     if(result['return'] == nil) then
  1627.         return false, "Read off the end of the packet (lsa.close)"
  1628.     end
  1629.     if(result['return'] ~= 0) then
  1630.         return false, smb.get_status_name(result['return']) .. " (lsa.close)"
  1631.     end
  1632.     
  1633.     stdnse.print_debug(3, "MSRPC: LsaClose() returned successfully")
  1634.     return true, result
  1635. end
  1636.  
  1637. ---A proxy to a <code>msrpctypes</code> function that converts a SidType to an english string. 
  1638. -- I implemented this as a proxy so scripts don't have to make direct calls to <code>msrpctypes</code>
  1639. -- functions.
  1640. --
  1641. --@param val The value to convert.
  1642. --@return A string that can be displayed to the user. 
  1643. function lsa_SidType_tostr(val)
  1644.     return msrpctypes.lsa_SidType_tostr(val)
  1645. end
  1646.  
  1647.  
  1648. ---Call the <code>OpenHKU</code> function, to obtain a handle to the HKEY_USERS hive
  1649. --
  1650. --@param smbstate  The SMB state table
  1651. --@return (status, result) If status is false, result is an error message. Otherwise, result is a table of values, the most
  1652. --        useful one being 'handle', which is required to call other winreg functions. 
  1653. function winreg_openhku(smbstate)
  1654.     local i, j
  1655.     local status, result
  1656.     local arguments
  1657.     local pos, align
  1658.  
  1659.     stdnse.print_debug(2, "MSRPC: Calling OpenHKU() [%s]", smbstate['ip'])
  1660.  
  1661. --        [in]      uint16 *system_name,
  1662.     arguments = msrpctypes.marshall_int16_ptr(0x1337, true)
  1663.  
  1664. --        [in]      winreg_AccessMask access_mask,
  1665.     arguments = arguments .. msrpctypes.marshall_winreg_AccessMask('MAXIMUM_ALLOWED_ACCESS')
  1666.  
  1667. --        [out,ref] policy_handle *handle
  1668.  
  1669.     -- Do the call
  1670.     status, result = call_function(smbstate, 0x04, arguments)
  1671.     if(status ~= true) then
  1672.         return false, result
  1673.     end
  1674.  
  1675.     stdnse.print_debug(3, "MSRPC: OpenHKU() returned successfully")
  1676.  
  1677.     -- Make arguments easier to use
  1678.     arguments = result['arguments']
  1679.     pos = 1
  1680.  
  1681. --        [in]      uint16 *system_name,
  1682. --        [in]      winreg_AccessMask access_mask,
  1683. --        [out,ref] policy_handle *handle
  1684.     pos, result['handle'] = msrpctypes.unmarshall_policy_handle(arguments, pos)
  1685.  
  1686.     pos, result['return'] = msrpctypes.unmarshall_int32(arguments, pos)
  1687.     if(result['return'] == nil) then
  1688.         return false, "Read off the end of the packet (winreg.openhku)"
  1689.     end
  1690.     if(result['return'] ~= 0) then
  1691.         return false, smb.get_status_name(result['return']) .. " (winreg.openhku)"
  1692.     end
  1693.  
  1694.     return true, result
  1695.  
  1696. end
  1697.  
  1698. ---Call the <code>OpenHKLM</code> function, to obtain a handle to the HKEY_LOCAL_MACHINE hive
  1699. --
  1700. --@param smbstate  The SMB state table
  1701. --@return (status, result) If status is false, result is an error message. Otherwise, result is a table of values, the most
  1702. --        useful one being 'handle', which is required to call other winreg functions. 
  1703. function winreg_openhklm(smbstate)
  1704.     local i, j
  1705.     local status, result
  1706.     local arguments
  1707.     local pos, align
  1708.  
  1709.     stdnse.print_debug(2, "MSRPC: Calling OpenHKLM() [%s]", smbstate['ip'])
  1710.  
  1711. --        [in]      uint16 *system_name,
  1712.     arguments = msrpctypes.marshall_int16_ptr(0x1337, true)
  1713.  
  1714. --        [in]      winreg_AccessMask access_mask,
  1715.     arguments = arguments .. msrpctypes.marshall_winreg_AccessMask('MAXIMUM_ALLOWED_ACCESS')
  1716.  
  1717. --        [out,ref] policy_handle *handle
  1718.  
  1719.     -- Do the call
  1720.     status, result = call_function(smbstate, 0x02, arguments)
  1721.     if(status ~= true) then
  1722.         return false, result
  1723.     end
  1724.  
  1725.     stdnse.print_debug(3, "MSRPC: OpenHKLM() returned successfully")
  1726.  
  1727.     -- Make arguments easier to use
  1728.     arguments = result['arguments']
  1729.     pos = 1
  1730.  
  1731. --        [in]      uint16 *system_name,
  1732. --        [in]      winreg_AccessMask access_mask,
  1733. --        [out,ref] policy_handle *handle
  1734.     pos, result['handle'] = msrpctypes.unmarshall_policy_handle(arguments, pos)
  1735.  
  1736.     pos, result['return'] = msrpctypes.unmarshall_int32(arguments, pos)
  1737.     if(result['return'] == nil) then
  1738.         return false, "Read off the end of the packet (winreg.openhklm)"
  1739.     end
  1740.     if(result['return'] ~= 0) then
  1741.         return false, smb.get_status_name(result['return']) .. " (winreg.openhklm)"
  1742.     end
  1743.  
  1744.     return true, result
  1745. end
  1746.  
  1747. ---Call the <code>OpenHKPD</code> function, to obtain a handle to the hidden HKEY_PERFORMANCE_DATA hive
  1748. --
  1749. --@param smbstate  The SMB state table
  1750. --@return (status, result) If status is false, result is an error message. Otherwise, result is a table of values, the most
  1751. --        useful one being 'handle', which is required to call other winreg functions. 
  1752. function winreg_openhkpd(smbstate)
  1753.     local i, j
  1754.     local status, result
  1755.     local arguments
  1756.     local pos, align
  1757.  
  1758.     stdnse.print_debug(2, "MSRPC: Calling OpenHKPD() [%s]", smbstate['ip'])
  1759.  
  1760. --        [in]      uint16 *system_name,
  1761.     arguments = msrpctypes.marshall_int16_ptr(0x1337, true)
  1762.  
  1763. --        [in]      winreg_AccessMask access_mask,
  1764.     arguments = arguments .. msrpctypes.marshall_winreg_AccessMask('MAXIMUM_ALLOWED_ACCESS')
  1765.  
  1766. --        [out,ref] policy_handle *handle
  1767.  
  1768.     -- Do the call
  1769.     status, result = call_function(smbstate, 0x03, arguments)
  1770.     if(status ~= true) then
  1771.         return false, result
  1772.     end
  1773.  
  1774.     stdnse.print_debug(3, "MSRPC: OpenHKPD() returned successfully")
  1775.  
  1776.     -- Make arguments easier to use
  1777.     arguments = result['arguments']
  1778.     pos = 1
  1779.  
  1780. --        [in]      uint16 *system_name,
  1781. --        [in]      winreg_AccessMask access_mask,
  1782. --        [out,ref] policy_handle *handle
  1783.     pos, result['handle'] = msrpctypes.unmarshall_policy_handle(arguments, pos)
  1784.  
  1785.     pos, result['return'] = msrpctypes.unmarshall_int32(arguments, pos)
  1786.     if(result['return'] == nil) then
  1787.         return false, "Read off the end of the packet (winreg.openhkpd)"
  1788.     end
  1789.     if(result['return'] ~= 0) then
  1790.         return false, smb.get_status_name(result['return']) .. " (winreg.openhkpd)"
  1791.     end
  1792.  
  1793.     return true, result
  1794. end
  1795.  
  1796. ---Call the <code>OpenHKCU</code> function, to obtain a handle to the HKEY_CURRENT_USER hive
  1797. --
  1798. --@param smbstate  The SMB state table
  1799. --@return (status, result) If status is false, result is an error message. Otherwise, result is a table of values, the most
  1800. --        useful one being 'handle', which is required to call other winreg functions. 
  1801. function winreg_openhkcu(smbstate)
  1802.     local i, j
  1803.     local status, result
  1804.     local arguments
  1805.     local pos, align
  1806.  
  1807.     stdnse.print_debug(2, "MSRPC: Calling OpenHKCU() [%s]", smbstate['ip'])
  1808.  
  1809. --        [in]      uint16 *system_name,
  1810.     arguments = msrpctypes.marshall_int16_ptr(0x1337, true)
  1811.  
  1812. --        [in]      winreg_AccessMask access_mask,
  1813.     arguments = arguments .. msrpctypes.marshall_winreg_AccessMask('MAXIMUM_ALLOWED_ACCESS')
  1814.  
  1815. --        [out,ref] policy_handle *handle
  1816.  
  1817.     -- Do the call
  1818.     status, result = call_function(smbstate, 0x01, arguments)
  1819.     if(status ~= true) then
  1820.         return false, result
  1821.     end
  1822.  
  1823.     stdnse.print_debug(3, "MSRPC: OpenHKCU() returned successfully")
  1824.  
  1825.     -- Make arguments easier to use
  1826.     arguments = result['arguments']
  1827.     pos = 1
  1828.  
  1829. --        [in]      uint16 *system_name,
  1830. --        [in]      winreg_AccessMask access_mask,
  1831. --        [out,ref] policy_handle *handle
  1832.     pos, result['handle'] = msrpctypes.unmarshall_policy_handle(arguments, pos)
  1833.  
  1834.     pos, result['return'] = msrpctypes.unmarshall_int32(arguments, pos)
  1835.     if(result['return'] == nil) then
  1836.         return false, "Read off the end of the packet (winreg.openhkcu)"
  1837.     end
  1838.     if(result['return'] ~= 0) then
  1839.         return false, smb.get_status_name(result['return']) .. " (winreg.openhkcu)"
  1840.     end
  1841.  
  1842.     return true, result
  1843.  
  1844. end
  1845.  
  1846.  
  1847.  
  1848. ---Calls the Windows registry function <code>EnumKey</code>, which returns a single key
  1849. -- under the given handle, at the index of 'index'. 
  1850. --
  1851. --@param smbstate  The SMB state table
  1852. --@param handle    A handle to hive or key. <code>winreg_openhku</code> provides a useable key, for example. 
  1853. --@param index     The index of the key to return. Generally you'll start at 0 and increment until
  1854. --                 an error is returned.
  1855. --@param name      The <code>name</code> buffer. This should be set to the empty string; however, setting to 'nil' can have
  1856. --                 interesting effects on Windows 2000 (I experienced crashes). 
  1857. --@return (status, result) If status is false, result is an error message. Otherwise, result is a table of values, the most
  1858. --        useful one being 'name', which is the name of the current key
  1859. function winreg_enumkey(smbstate, handle, index, name)
  1860.     local i, j
  1861.     local status, result
  1862.     local arguments
  1863.     local pos, align
  1864.  
  1865.     stdnse.print_debug(2, "MSRPC: Calling EnumKey(%d) [%s]", index, smbstate['ip'])
  1866.  
  1867. --        [in,ref]        policy_handle    *handle,
  1868.     arguments = msrpctypes.marshall_policy_handle(handle)
  1869.  
  1870. --        [in]            uint32           enum_index,
  1871.     arguments = arguments .. msrpctypes.marshall_int32(index)
  1872.  
  1873. --        [in,out,ref]    winreg_StringBuf *name,
  1874.     -- NOTE: if the 'name' parameter here is set to 'nil', the service on a fully patched Windows 2000 system
  1875.     -- may crash. 
  1876.     arguments = arguments .. msrpctypes.marshall_winreg_StringBuf({name=""}, 520)
  1877.  
  1878. --        [in,out,unique] winreg_StringBuf *keyclass,
  1879.     arguments = arguments .. msrpctypes.marshall_winreg_StringBuf_ptr({name=nil})
  1880.  
  1881. --        [in,out,unique] NTTIME           *last_changed_time
  1882.     arguments = arguments .. msrpctypes.marshall_NTTIME_ptr(0)
  1883.  
  1884.     -- Do the call
  1885.     status, result = call_function(smbstate, 0x09, arguments)
  1886.     if(status ~= true) then
  1887.         return false, result
  1888.     end
  1889.  
  1890.     stdnse.print_debug(3, "MSRPC: EnumKey() returned successfully")
  1891.  
  1892.     -- Make arguments easier to use
  1893.     arguments = result['arguments']
  1894.     local referent_id
  1895.  
  1896.     pos = 1
  1897.  
  1898. --        [in,ref]        policy_handle    *handle,
  1899. --        [in]            uint32           enum_index,
  1900. --        [in,out,ref]    winreg_StringBuf *name,
  1901.     pos, result['name'] = msrpctypes.unmarshall_winreg_StringBuf(arguments, pos)
  1902.  
  1903. --        [in,out,unique] winreg_StringBuf *keyclass,
  1904.     pos, result['keyclass'] = msrpctypes.unmarshall_winreg_StringBuf_ptr(arguments, pos)
  1905.  
  1906. --        [in,out,unique] NTTIME           *last_changed_time
  1907.     pos, result['changed_time'] = msrpctypes.unmarshall_NTTIME_ptr(arguments, pos)
  1908.     result['changed_date'] = os.date("%Y-%m-%d %H:%M:%S", result['changed_time'])
  1909.  
  1910.     pos, result['return'] = msrpctypes.unmarshall_int32(arguments, pos)
  1911.     if(result['return'] == nil) then
  1912.         return false, "Read off the end of the packet (winreg.enumkey)"
  1913.     end
  1914.     if(result['return'] ~= 0) then
  1915.         return false, smb.get_status_name(result['return']) .. " (winreg.enumkey)"
  1916.     end
  1917.  
  1918.     return true, result
  1919.  
  1920. end
  1921.  
  1922. --- Calls the function <code>OpenKey</code>, which obtains a handle to a named key. 
  1923. --
  1924. --@param smbstate  The SMB state table
  1925. --@param handle    A handle to hive or key. <code>winreg_openhku</code> provides a useable key, for example. 
  1926. --@param keyname   The name of the key to open. 
  1927. --@return (status, result) If status is false, result is an error message. Otherwise, result is a table of values, the most
  1928. --        useful one being 'handle', which is a handle to the newly opened key. 
  1929. function winreg_openkey(smbstate, handle, keyname)
  1930.     local i, j
  1931.     local status, result
  1932.     local arguments
  1933.     local pos, align
  1934.  
  1935.     stdnse.print_debug(2, "MSRPC: Calling OpenKey(%s) [%s]", keyname, smbstate['ip'])
  1936.  
  1937. --        [in,ref] policy_handle *parent_handle,
  1938.     arguments = msrpctypes.marshall_policy_handle(handle)
  1939.  
  1940. --        [in] winreg_String keyname,
  1941.     arguments = arguments .. msrpctypes.marshall_winreg_String({name=keyname})
  1942.  
  1943. --        [in] uint32 unknown,
  1944.     arguments = arguments .. msrpctypes.marshall_int32(0)
  1945.  
  1946. --        [in] winreg_AccessMask access_mask,
  1947.     arguments = arguments .. msrpctypes.marshall_winreg_AccessMask('MAXIMUM_ALLOWED_ACCESS')
  1948.  
  1949. --        [out,ref] policy_handle *handle
  1950.  
  1951.  
  1952.     -- Do the call
  1953.     status, result = call_function(smbstate, 0x0F, arguments)
  1954.     if(status ~= true) then
  1955.         return false, result
  1956.     end
  1957.  
  1958.     stdnse.print_debug(3, "MSRPC: OpenKey() returned successfully")
  1959.  
  1960.     -- Make arguments easier to use
  1961.     arguments = result['arguments']
  1962.     pos = 1
  1963.  
  1964. --        [in,ref] policy_handle *parent_handle,
  1965. --        [in] winreg_String keyname,
  1966. --        [in] uint32 unknown,
  1967. --        [in] winreg_AccessMask access_mask,
  1968. --        [out,ref] policy_handle *handle
  1969.     pos, result['handle'] = msrpctypes.unmarshall_policy_handle(arguments, pos)
  1970.  
  1971.     pos, result['return'] = msrpctypes.unmarshall_int32(arguments, pos)
  1972.     if(result['return'] == nil) then
  1973.         return false, "Read off the end of the packet (winreg.openkey)"
  1974.     end
  1975.     if(result['return'] ~= 0) then
  1976.         return false, smb.get_status_name(result['return']) .. " (winreg.openkey)"
  1977.     end
  1978.  
  1979.     return true, result
  1980. end
  1981.  
  1982. --- Calls the function <code>QueryInfoKey</code>, which obtains information about an opened key. 
  1983. --
  1984. --@param smbstate  The SMB state table
  1985. --@param handle    A handle to the key that's being queried. 
  1986. --@return (status, result) If status is false, result is an error message. Otherwise, result is a table of values, the most
  1987. --        useful one, at least for me, being 'last_changed_time'/'last_changed_date', which are the date and time that the
  1988. --        key was changed. 
  1989. function winreg_queryinfokey(smbstate, handle)
  1990.     local i, j
  1991.     local status, result
  1992.     local arguments
  1993.     local pos, align
  1994.  
  1995.     stdnse.print_debug(2, "MSRPC: Calling QueryInfoKey() [%s]", smbstate['ip'])
  1996.  
  1997. --        [in,ref] policy_handle *handle,
  1998.     arguments = msrpctypes.marshall_policy_handle(handle)
  1999.  
  2000. --        [in,out,ref] winreg_String *classname,
  2001.     arguments = arguments .. msrpctypes.marshall_winreg_String({name=""}, 2048)
  2002.  
  2003. --        [out,ref] uint32 *num_subkeys,
  2004. --        [out,ref] uint32 *max_subkeylen,
  2005. --        [out,ref] uint32 *max_subkeysize,
  2006. --        [out,ref] uint32 *num_values,
  2007. --        [out,ref] uint32 *max_valnamelen,
  2008. --        [out,ref] uint32 *max_valbufsize,
  2009. --        [out,ref] uint32 *secdescsize,
  2010. --        [out,ref] NTTIME *last_changed_time
  2011.  
  2012.  
  2013.     -- Do the call
  2014.     status, result = call_function(smbstate, 0x10, arguments)
  2015.     if(status ~= true) then
  2016.         return false, result
  2017.     end
  2018.  
  2019.     stdnse.print_debug(3, "MSRPC: QueryInfoKey() returned successfully")
  2020.  
  2021.     -- Make arguments easier to use
  2022.     arguments = result['arguments']
  2023.     pos = 1
  2024.  
  2025. --        [in,ref] policy_handle *handle,
  2026. --        [in,out,ref] winreg_String *classname,
  2027.     pos, result['classname'] = msrpctypes.unmarshall_winreg_String(arguments, pos)
  2028.  
  2029. --        [out,ref] uint32 *num_subkeys,
  2030.     pos, result['subkeys'] = msrpctypes.unmarshall_int32(arguments, pos)
  2031.  
  2032. --        [out,ref] uint32 *max_subkeylen,
  2033.     pos, result['subkeylen'] = msrpctypes.unmarshall_int32(arguments, pos)
  2034.  
  2035. --        [out,ref] uint32 *max_subkeysize,
  2036.     pos, result['subkeysize'] = msrpctypes.unmarshall_int32(arguments, pos)
  2037.  
  2038. --        [out,ref] uint32 *num_values,
  2039.     pos, result['num_values'] = msrpctypes.unmarshall_int32(arguments, pos)
  2040.  
  2041. --        [out,ref] uint32 *max_valnamelen,
  2042.     pos, result['max_valnamelen'] = msrpctypes.unmarshall_int32(arguments, pos)
  2043.  
  2044. --        [out,ref] uint32 *max_valbufsize,
  2045.     pos, result['max_valbufsize'] = msrpctypes.unmarshall_int32(arguments, pos)
  2046.  
  2047. --        [out,ref] uint32 *secdescsize,
  2048.     pos, result['secdescsize'] = msrpctypes.unmarshall_int32(arguments, pos)
  2049.  
  2050. --        [out,ref] NTTIME *last_changed_time
  2051.     pos, result['last_changed_time'] = msrpctypes.unmarshall_NTTIME(arguments, pos)
  2052.     result['last_changed_date'] = os.date("%Y-%m-%d %H:%M:%S", result['last_changed_time'])
  2053.  
  2054.     pos, result['return'] = msrpctypes.unmarshall_int32(arguments, pos)
  2055.     if(result['return'] == nil) then
  2056.         return false, "Read off the end of the packet (winreg.queryinfokey)"
  2057.     end
  2058.     if(result['return'] ~= 0) then
  2059.         return false, smb.get_status_name(result['return']) .. " (winreg.queryinfokey)"
  2060.     end
  2061.  
  2062.     return true, result
  2063. end
  2064.  
  2065.  
  2066. --- Calls the function <code>QueryValue</code>, which returns the value of the requested key.
  2067. --
  2068. --@param smbstate  The SMB state table
  2069. --@param handle    A handle to the key that's being queried. 
  2070. --@param value     The value we're looking for. 
  2071. --@return (status, result) If status is false, result is an error message. Otherwise, result is a table of values, the most
  2072. --        useful one, at least for me, being 'last_changed_time'/'last_changed_date', which are the date and time that the
  2073. --        key was changed. 
  2074. function winreg_queryvalue(smbstate, handle, value)
  2075.     local i, j
  2076.     local status, result
  2077.     local arguments
  2078.     local pos, align
  2079.  
  2080.     stdnse.print_debug(2, "MSRPC: Calling QueryValue(%s) [%s]", value, smbstate['ip'])
  2081.  
  2082.  
  2083. --        [in,ref] policy_handle *handle,
  2084.     arguments = msrpctypes.marshall_policy_handle(handle)
  2085.  
  2086. --        [in] winreg_String value_name,
  2087.     arguments = arguments .. msrpctypes.marshall_winreg_String({name=value})
  2088.  
  2089. --        [in,out] winreg_Type *type,
  2090.     arguments = arguments .. msrpctypes.marshall_winreg_Type_ptr("REG_NONE")
  2091.  
  2092. --        [in,out,size_is(*size),length_is(*length)] uint8 *data,
  2093.     arguments = arguments .. msrpctypes.marshall_int8_array_ptr("", 1000000)
  2094.  
  2095. --        [in,out] uint32 *size,
  2096.     arguments = arguments .. msrpctypes.marshall_int32_ptr(1000000)
  2097.  
  2098. --        [in,out] uint32 *length
  2099.     arguments = arguments .. msrpctypes.marshall_int32_ptr(0)
  2100.  
  2101.     -- Do the call
  2102.     status, result = call_function(smbstate, 0x11, arguments)
  2103.     if(status ~= true) then
  2104.         return false, result
  2105.     end
  2106.  
  2107.     stdnse.print_debug(3, "MSRPC: QueryValue() returned successfully")
  2108.     local length, referent_id
  2109.  
  2110.     -- Make arguments easier to use
  2111.     arguments = result['arguments']
  2112.     pos = 1
  2113.  
  2114.  
  2115. --        [in,ref] policy_handle *handle,
  2116. --        [in] winreg_String value_name,
  2117. --        [in,out] winreg_Type *type,
  2118.     pos, result['type'] = msrpctypes.unmarshall_winreg_Type_ptr(arguments, pos)
  2119.  
  2120. --        [in,out,size_is(*size),length_is(*length)] uint8 *data,
  2121.     pos, result['data'] = msrpctypes.unmarshall_int8_array_ptr(arguments, pos)
  2122.  
  2123.     -- Format the type properly and put it in "value"
  2124.     if(result['data'] ~= nil) then
  2125.         if(result['type'] == "REG_DWORD") then
  2126.             _, result['value'] = bin.unpack("<I", result['data'])
  2127.         elseif(result['type'] == "REG_SZ" or result['type'] == "REG_MULTI_SZ" or result['type'] == "REG_EXPAND_SZ") then
  2128.             _, result['value'] = msrpctypes.unicode_to_string(result['data'], 1, #result['data'] / 2)
  2129.         elseif(result['type'] == "REG_BINARY") then
  2130.             result['value'] = result['data']
  2131.         elseif(result['type'] == "REG_NONE") then
  2132.             result['value'] = ""
  2133.         else
  2134.             stdnse.print_debug("MSRPC ERROR: Unknown type: %s", result['type'])
  2135.             result['value'] = result['type']
  2136.         end
  2137.     else
  2138.         result['value'] = nil
  2139.     end
  2140.  
  2141. --        [in,out] uint32 *size,
  2142.     pos, result['size'] = msrpctypes.unmarshall_int32_ptr(arguments, pos)
  2143.  
  2144. --        [in,out] uint32 *length
  2145.     pos, result['length'] = msrpctypes.unmarshall_int32_ptr(arguments, pos)
  2146.  
  2147.     pos, result['return'] = msrpctypes.unmarshall_int32(arguments, pos)
  2148.  
  2149.     if(result['return'] == nil) then
  2150.         return false, "Read off the end of the packet (winreg.queryvalue)"
  2151.     end
  2152.     if(result['return'] ~= 0) then
  2153.         return false, smb.get_status_name(result['return']) .. " (winreg.queryvalue)"
  2154.     end
  2155.  
  2156.     return true, result
  2157. end
  2158.  
  2159.  
  2160.  
  2161. --- Calls the function <code>CloseKey</code>, which closes an opened handle. Strictly speaking, this doesn't have to be called (Windows
  2162. --  will close the key for you), but it's good manners to clean up after yourself. 
  2163. --
  2164. --@param smbstate  The SMB state table
  2165. --@param handle    the handle to be closed. 
  2166. --@return (status, result) If status is false, result is an error message. Otherwise, result is a table of values, none of
  2167. --                         which are especially useful. 
  2168. function winreg_closekey(smbstate, handle)
  2169.     local i, j
  2170.     local status, result
  2171.     local arguments
  2172.     local pos, align
  2173.  
  2174.     stdnse.print_debug(2, "MSRPC: Calling CloseKey() [%s]", smbstate['ip'])
  2175.  
  2176. --        [in,out,ref] policy_handle *handle
  2177.     arguments = msrpctypes.marshall_policy_handle(handle)
  2178.  
  2179.     -- Do the call
  2180.     status, result = call_function(smbstate, 0x05, arguments)
  2181.     if(status ~= true) then
  2182.         return false, result
  2183.     end
  2184.  
  2185.     stdnse.print_debug(3, "MSRPC: CloseKey() returned successfully")
  2186.  
  2187.     -- Make arguments easier to use
  2188.     arguments = result['arguments']
  2189.     pos = 1
  2190.  
  2191. --        [in,out,ref] policy_handle *handle
  2192.     pos, result['handle'] = msrpctypes.unmarshall_policy_handle(arguments, pos)
  2193.  
  2194.     pos, result['return'] = msrpctypes.unmarshall_int32(arguments, pos)
  2195.     if(result['return'] == nil) then
  2196.         return false, "Read off the end of the packet (winreg.closekey)"
  2197.     end
  2198.     if(result['return'] ~= 0) then
  2199.         return false, smb.get_status_name(result['return']) .. " (winreg.closekey)"
  2200.     end
  2201.  
  2202.     return true, result
  2203. end
  2204.  
  2205. --- Calls the function <code>OpenSCManagerA</code>, which gets a handle to the service manager. Should be closed with
  2206. -- <code>CloseServiceHandle</code> when finished. 
  2207. --
  2208. --@param smbstate    The SMB state table
  2209. --@param machinename The name or IP of the machine. 
  2210. --@return (status, result) If status is false, result is an error message. Otherwise, result is a table of values
  2211. --        representing the "out" parameters.  
  2212. function svcctl_openscmanagera(smbstate, machinename)
  2213.     local i, j
  2214.     local status, result
  2215.     local arguments
  2216.     local pos, align
  2217.  
  2218.     stdnse.print_debug(2, "MSRPC: Calling OpenSCManagerA() [%s]", smbstate['ip'])
  2219.  
  2220. --        [in] [string,charset(UTF16)] uint16 *MachineName,
  2221.     arguments = msrpctypes.marshall_ascii_ptr("\\\\" .. machinename)
  2222.  
  2223. --        [in] [string,charset(UTF16)] uint16 *DatabaseName,
  2224.     arguments = arguments .. msrpctypes.marshall_ascii_ptr(nil)
  2225.  
  2226. --        [in] uint32 access_mask,
  2227. --    arguments = arguments .. msrpctypes.marshall_int32(0x000f003f) 
  2228.     arguments = arguments .. msrpctypes.marshall_int32(0x00000002) 
  2229.  
  2230. --        [out,ref] policy_handle *handle
  2231.  
  2232.     -- Do the call
  2233.     status, result = call_function(smbstate, 0x1b, arguments)
  2234.     if(status ~= true) then
  2235.         return false, result
  2236.     end
  2237.  
  2238.     stdnse.print_debug(3, "MSRPC: OpenSCManagerA() returned successfully")
  2239.  
  2240.     -- Make arguments easier to use
  2241.     arguments = result['arguments']
  2242.     pos = 1
  2243.  
  2244. --        [in] [string,charset(UTF16)] uint16 *MachineName,
  2245. --        [in] [string,charset(UTF16)] uint16 *DatabaseName,
  2246. --        [in] uint32 access_mask,
  2247. --        [out,ref] policy_handle *handle
  2248.     pos, result['handle'] = msrpctypes.unmarshall_policy_handle(arguments, pos)
  2249.  
  2250.     pos, result['return'] = msrpctypes.unmarshall_int32(arguments, pos)
  2251.     if(result['return'] == nil) then
  2252.         return false, "Read off the end of the packet (svcctl.openscmanagera)"
  2253.     end
  2254.     if(result['return'] ~= 0) then
  2255.         return false, smb.get_status_name(result['return']) .. " (svcctl.openscmanagera)"
  2256.     end
  2257.  
  2258.     return true, result
  2259. end
  2260.  
  2261.  
  2262. --- Calls the function <code>OpenSCManagerW</code>, which gets a handle to the service manager. Should be closed with
  2263. -- <code>CloseServiceHandle</code> when finished. 
  2264. --
  2265. --@param smbstate    The SMB state table
  2266. --@param machinename The name or IP of the machine. 
  2267. --@return (status, result) If status is false, result is an error message. Otherwise, result is a table of values
  2268. --        representing the "out" parameters.  
  2269. function svcctl_openscmanagerw(smbstate, machinename)
  2270.     local i, j
  2271.     local status, result
  2272.     local arguments
  2273.     local pos, align
  2274.  
  2275. --    if(1 == 1) then
  2276. --        return svcctl_openscmanagera(smbstate, machinename)
  2277. --    end
  2278.  
  2279.     stdnse.print_debug(2, "MSRPC: Calling OpenSCManagerW() [%s]", smbstate['ip'])
  2280.  
  2281. --        [in] [string,charset(UTF16)] uint16 *MachineName,
  2282.     arguments = msrpctypes.marshall_unicode_ptr("\\\\" .. machinename, true)
  2283.  
  2284. --        [in] [string,charset(UTF16)] uint16 *DatabaseName,
  2285.     arguments = arguments .. msrpctypes.marshall_unicode_ptr(nil, true)
  2286.  
  2287. --        [in] uint32 access_mask,
  2288.     arguments = arguments .. msrpctypes.marshall_int32(0x000f003f) 
  2289. --    arguments = arguments .. msrpctypes.marshall_int32(0x00000002) 
  2290.  
  2291. --        [out,ref] policy_handle *handle
  2292.  
  2293.     -- Do the call
  2294.     status, result = call_function(smbstate, 0x0f, arguments)
  2295.     if(status ~= true) then
  2296.         return false, result
  2297.     end
  2298.  
  2299.     stdnse.print_debug(3, "MSRPC: OpenSCManagerW() returned successfully")
  2300.  
  2301.     -- Make arguments easier to use
  2302.     arguments = result['arguments']
  2303.     pos = 1
  2304.  
  2305. --        [in] [string,charset(UTF16)] uint16 *MachineName,
  2306. --        [in] [string,charset(UTF16)] uint16 *DatabaseName,
  2307. --        [in] uint32 access_mask,
  2308. --        [out,ref] policy_handle *handle
  2309.     pos, result['handle'] = msrpctypes.unmarshall_policy_handle(arguments, pos)
  2310.  
  2311.     pos, result['return'] = msrpctypes.unmarshall_int32(arguments, pos)
  2312.     if(result['return'] == nil) then
  2313.         return false, "Read off the end of the packet (svcctl.openscmanagerw)"
  2314.     end
  2315.     if(result['return'] ~= 0) then
  2316.         return false, smb.get_status_name(result['return']) .. " (svcctl.openscmanagerw)"
  2317.     end
  2318.  
  2319.     return true, result
  2320. end
  2321.  
  2322.  
  2323. --- Calls the function <code>CloseServiceHandle</code>, which releases a handle.
  2324. --
  2325. --@param smbstate  The SMB state table
  2326. --@param handle    The handle to be closed. 
  2327. --@return (status, result) If status is false, result is an error message. Otherwise, result is a table of values
  2328. --        representing the "out" parameters.  
  2329. function svcctl_closeservicehandle(smbstate, handle)
  2330.     local i, j
  2331.     local status, result
  2332.     local arguments
  2333.     local pos, align
  2334.  
  2335.     stdnse.print_debug(2, "MSRPC: Calling CloseServiceHandle() [%s]", smbstate['ip'])
  2336.  
  2337. --        [in,out,ref] policy_handle *handle
  2338.     arguments = msrpctypes.marshall_policy_handle(handle)
  2339.  
  2340.  
  2341.     -- Do the call
  2342.     status, result = call_function(smbstate, 0x00, arguments)
  2343.     if(status ~= true) then
  2344.         return false, result
  2345.     end
  2346.  
  2347.     stdnse.print_debug(3, "MSRPC: OpenSCManagerA() returned successfully")
  2348.  
  2349.     -- Make arguments easier to use
  2350.     arguments = result['arguments']
  2351.     pos = 1
  2352.  
  2353. --        [in,out,ref] policy_handle *handle
  2354.     pos, result['handle'] = msrpctypes.unmarshall_policy_handle(arguments, pos)
  2355.  
  2356.     pos, result['return'] = msrpctypes.unmarshall_int32(arguments, pos)
  2357.     if(result['return'] == nil) then
  2358.         return false, "Read off the end of the packet (svcctl.closeservicehandle)"
  2359.     end
  2360.     if(result['return'] ~= 0) then
  2361.         return false, smb.get_status_name(result['return']) .. " (svcctl.closeservicehandle)"
  2362.     end
  2363.  
  2364.     return true, result
  2365. end
  2366.  
  2367. --- Calls the function <code>CreateServiceW</code>, which creates a service on the remote machine. This should
  2368. -- be deleted with <code>DeleteService</code> when finished. 
  2369. --
  2370. --@param smbstate  The SMB state table
  2371. --@param handle    The handle created by <code>OpenSCManagerW</code>
  2372. --@return (status, result) If status is false, result is an error message. Otherwise, result is a table of values
  2373. --        representing the "out" parameters.  
  2374. function svcctl_createservicew(smbstate, handle, service_name, display_name, path)
  2375.     local i, j
  2376.     local status, result
  2377.     local arguments
  2378.     local pos, align
  2379.  
  2380.     stdnse.print_debug(2, "MSRPC: Calling CreateServiceW() [%s]", smbstate['ip'])
  2381.  
  2382. --        [in,ref] policy_handle *scmanager_handle,
  2383.     arguments = msrpctypes.marshall_policy_handle(handle)
  2384.  
  2385. --        [in] [string,charset(UTF16)] uint16 ServiceName[],
  2386.     arguments = arguments .. msrpctypes.marshall_unicode(service_name, true)
  2387.  
  2388. --        [in] [string,charset(UTF16)] uint16 *DisplayName,
  2389.     arguments = arguments .. msrpctypes.marshall_unicode_ptr(display_name, true)
  2390.  
  2391. --        [in] uint32 desired_access,
  2392.     arguments = arguments .. msrpctypes.marshall_int32(0x000f01ff) -- Access: Max
  2393.  
  2394. --        [in] uint32 type,
  2395.     arguments = arguments .. msrpctypes.marshall_int32(0x00000010) -- Type: own process
  2396.  
  2397. --        [in] uint32 start_type,
  2398.     arguments = arguments .. msrpctypes.marshall_int32(0x00000003) -- Start: Demand
  2399.  
  2400. --        [in] uint32 error_control,
  2401.     arguments = arguments .. msrpctypes.marshall_int32(0x00000000) -- Error: Ignore
  2402.  
  2403. --        [in] [string,charset(UTF16)] uint16 binary_path[],
  2404.     arguments = arguments .. msrpctypes.marshall_unicode(path, true)
  2405.  
  2406. --        [in] [string,charset(UTF16)] uint16 *LoadOrderGroupKey,
  2407.     arguments = arguments .. msrpctypes.marshall_unicode_ptr(nil)
  2408.  
  2409. --        [in,out] uint32 *TagId,
  2410.     arguments = arguments .. msrpctypes.marshall_int32_ptr(nil)
  2411.  
  2412. --        [in,size_is(dependencies_size)] uint8 *dependencies,
  2413.     arguments = arguments .. msrpctypes.marshall_int8_ptr(nil)
  2414.  
  2415. --        [in] uint32 dependencies_size,
  2416.     arguments = arguments .. msrpctypes.marshall_int32(0)
  2417.  
  2418. --        [in] [string,charset(UTF16)] uint16 *service_start_name,
  2419.     arguments = arguments .. msrpctypes.marshall_unicode_ptr(nil)
  2420.  
  2421. --        [in,size_is(password_size)] uint8 *password,
  2422.     arguments = arguments .. msrpctypes.marshall_int8_ptr(nil)
  2423.  
  2424. --        [in] uint32 password_size,
  2425.     arguments = arguments .. msrpctypes.marshall_int32(0)
  2426.  
  2427. --        [out,ref] policy_handle *handle
  2428.  
  2429.  
  2430.  
  2431.     -- Do the call
  2432.     status, result = call_function(smbstate, 0x0c, arguments)
  2433.     if(status ~= true) then
  2434.         return false, result
  2435.     end
  2436.  
  2437.     stdnse.print_debug(3, "MSRPC: CreateServiceW() returned successfully")
  2438.  
  2439.     -- Make arguments easier to use
  2440.     arguments = result['arguments']
  2441.     pos = 1
  2442.  
  2443. --        [in,ref] policy_handle *scmanager_handle,
  2444. --        [in] [string,charset(UTF16)] uint16 ServiceName[],
  2445. --        [in] [string,charset(UTF16)] uint16 *DisplayName,
  2446. --        [in] uint32 desired_access,
  2447. --        [in] uint32 type,
  2448. --        [in] uint32 start_type,
  2449. --        [in] uint32 error_control,
  2450. --        [in] [string,charset(UTF16)] uint16 binary_path[],
  2451. --        [in] [string,charset(UTF16)] uint16 *LoadOrderGroupKey,
  2452. --        [in,out] uint32 *TagId,
  2453.     pos, result['TagId'] = msrpctypes.unmarshall_int32_ptr(arguments, pos)
  2454.     
  2455. --        [in,size_is(dependencies_size)] uint8 *dependencies,
  2456. --        [in] uint32 dependencies_size,
  2457. --        [in] [string,charset(UTF16)] uint16 *service_start_name,
  2458. --        [in,size_is(password_size)] uint8 *password,
  2459. --        [in] uint32 password_size,
  2460. --        [out,ref] policy_handle *handle
  2461.     pos, result['handle'] = msrpctypes.unmarshall_policy_handle(arguments, pos)
  2462.  
  2463.     pos, result['return'] = msrpctypes.unmarshall_int32(arguments, pos)
  2464.     if(result['return'] == nil) then
  2465.         return false, "Read off the end of the packet (svcctl.createservicew)"
  2466.     end
  2467.     if(result['return'] ~= 0) then
  2468.         return false, smb.get_status_name(result['return']) .. " (svcctl.createservicew)"
  2469.     end
  2470.  
  2471.     return true, result
  2472. end
  2473.  
  2474. --- Calls the function <code>DeleteService</code>, which deletes a service on the remote machine. This service
  2475. -- has to opened with <code>OpenServiceW</code> or similar functions. 
  2476. --
  2477. --@param smbstate  The SMB state table.
  2478. --@param handle    The handle to delete, opened with <code>OpenServiceW</code> or similar. 
  2479. --@return (status, result) If status is false, result is an error message. Otherwise, result is a table of values
  2480. --        representing the "out" parameters.  
  2481. function svcctl_deleteservice(smbstate, handle)
  2482.     local i, j
  2483.     local status, result
  2484.     local arguments
  2485.     local pos, align
  2486.  
  2487.     stdnse.print_debug(2, "MSRPC: Calling DeleteService() [%s]", smbstate['ip'])
  2488.  
  2489. --        [in,ref] policy_handle *handle
  2490.     arguments = msrpctypes.marshall_policy_handle(handle)
  2491.  
  2492.  
  2493.     -- Do the call
  2494.     status, result = call_function(smbstate, 0x02, arguments)
  2495.     if(status ~= true) then
  2496.         return false, result
  2497.     end
  2498.  
  2499.     stdnse.print_debug(3, "MSRPC: DeleteService() returned successfully")
  2500.  
  2501.     -- Make arguments easier to use
  2502.     arguments = result['arguments']
  2503.     pos = 1
  2504.  
  2505.  
  2506. --        [in,ref] policy_handle *handle
  2507.  
  2508.  
  2509.     pos, result['return'] = msrpctypes.unmarshall_int32(arguments, pos)
  2510.     if(result['return'] == nil) then
  2511.         return false, "Read off the end of the packet (svcctl.deleteservice)"
  2512.     end
  2513.     if(result['return'] ~= 0) then
  2514.         return false, smb.get_status_name(result['return']) .. " (svcctl.deleteservice)"
  2515.     end
  2516.  
  2517.     return true, result
  2518. end
  2519.  
  2520. --- Calls the function <code>OpenServiceW</code>, which gets a handle to the service.  Should be closed with
  2521. -- <code>CloseServiceHandle</code> when finished. 
  2522. --
  2523. --@param smbstate The SMB state table.
  2524. --@param handle   A handle to the policy manager, opened with <code>OpenSCManagerW</code> or similar. 
  2525. --@param name     The name of the service. 
  2526. --@return (status, result) If status is false, result is an error message. Otherwise, result is a table of values
  2527. --        representing the "out" parameters.  
  2528. function svcctl_openservicew(smbstate, handle, name)
  2529.     local i, j
  2530.     local status, result
  2531.     local arguments
  2532.     local pos, align
  2533.  
  2534.     stdnse.print_debug(2, "MSRPC: Calling OpenServiceW() [%s]", smbstate['ip'])
  2535.  
  2536. --        [in,ref] policy_handle *scmanager_handle,
  2537.     arguments = msrpctypes.marshall_policy_handle(handle)
  2538.  
  2539. --        [in] [string,charset(UTF16)] uint16 ServiceName[],
  2540.     arguments = arguments .. msrpctypes.marshall_unicode(name, true)
  2541.  
  2542. --        [in] uint32 access_mask,
  2543.     arguments = arguments .. msrpctypes.marshall_int32(0x000f01ff)
  2544. --        [out,ref] policy_handle *handle
  2545.  
  2546.  
  2547.     -- Do the call
  2548.     status, result = call_function(smbstate, 0x10, arguments)
  2549.     if(status ~= true) then
  2550.         return false, result
  2551.     end
  2552.  
  2553.     stdnse.print_debug(3, "MSRPC: OpenServiceW() returned successfully")
  2554.  
  2555.     -- Make arguments easier to use
  2556.     arguments = result['arguments']
  2557.     pos = 1
  2558.  
  2559. --        [in,ref] policy_handle *scmanager_handle,
  2560. --        [in] [string,charset(UTF16)] uint16 ServiceName[],
  2561. --        [in] uint32 access_mask,
  2562. --        [out,ref] policy_handle *handle
  2563.     pos, result['handle'] = msrpctypes.unmarshall_policy_handle(arguments, pos)
  2564.  
  2565.     pos, result['return'] = msrpctypes.unmarshall_int32(arguments, pos)
  2566.     if(result['return'] == nil) then
  2567.         return false, "Read off the end of the packet (svcctl.openservicew)"
  2568.     end
  2569.     if(result['return'] ~= 0) then
  2570.         return false, smb.get_status_name(result['return']) .. " (svcctl.openservicew)"
  2571.     end
  2572.  
  2573.     return true, result
  2574. end
  2575.  
  2576. --- Calls the function <code>StartServiceW</code>, which starts a service. Requires a handle
  2577. -- created by <code>OpenServiceW</code>. 
  2578. --
  2579. --@param smbstate The SMB state table.
  2580. --@param handle   The handle, opened by <code>OpenServiceW</code>.
  2581. --@param args     An array of strings representing the arguments. 
  2582. --@return (status, result) If status is false, result is an error message. Otherwise, result is a table of values
  2583. --        representing the "out" parameters.
  2584. function svcctl_startservicew(smbstate, handle, args)
  2585.     local i, j
  2586.     local status, result
  2587.     local arguments
  2588.     local pos, align
  2589.     stdnse.print_debug(2, "MSRPC: Calling StartServiceW() [%s]", smbstate['ip'])
  2590.  
  2591. --        [in,ref] policy_handle *handle,
  2592.     arguments = msrpctypes.marshall_policy_handle(handle)
  2593.  
  2594. --        [in] uint32 NumArgs,
  2595.     if(args == nil) then
  2596.         arguments = arguments .. msrpctypes.marshall_int32(0)
  2597.     else
  2598.         arguments = arguments .. msrpctypes.marshall_int32(#args)
  2599.     end
  2600.  
  2601. --        [in/*FIXME:,length_is(NumArgs)*/] [string,charset(UTF16)] uint16 *Arguments
  2602.     arguments = arguments .. msrpctypes.marshall_unicode_array_ptr(args, true)
  2603.  
  2604.     -- Do the call
  2605.     status, result = call_function(smbstate, 0x13, arguments)
  2606.     if(status ~= true) then
  2607.         return false, result
  2608.     end
  2609.  
  2610.     stdnse.print_debug(3, "MSRPC: StartServiceW() returned successfully")
  2611.  
  2612.     -- Make arguments easier to use
  2613.     arguments = result['arguments']
  2614.     pos = 1
  2615.  
  2616. --        [in,ref] policy_handle *handle,
  2617. --        [in] uint32 NumArgs,
  2618. --        [in/*FIXME:,length_is(NumArgs)*/] [string,charset(UTF16)] uint16 *Arguments
  2619.  
  2620.     pos, result['return'] = msrpctypes.unmarshall_int32(arguments, pos)
  2621.     if(result['return'] == nil) then
  2622.         return false, "Read off the end of the packet (svcctl.startservicew)"
  2623.     end
  2624.     if(result['return'] ~= 0) then
  2625.         return false, smb.get_status_name(result['return']) .. " (svcctl.startservicew)"
  2626.     end
  2627.  
  2628.     return true, result
  2629.  
  2630. end
  2631.  
  2632. --- Calls the function <code>ControlService</code>, which can send various commands to the service. 
  2633. --
  2634. --@param smbstate The SMB state table.
  2635. --@param handle   The handle, opened by <code>OpenServiceW</code>.
  2636. --@param control  The command to send. See <code>svcctl_ControlCode</code> in <code>msrpctypes.lua</code>. 
  2637. --@return (status, result) If status is false, result is an error message. Otherwise, result is a table of values
  2638. --        representing the "out" parameters.
  2639. function svcctl_controlservice(smbstate, handle, control)
  2640.     local i, j
  2641.     local status, result
  2642.     local arguments
  2643.     local pos, align
  2644.  
  2645.     stdnse.print_debug(2, "MSRPC: Calling ControlService() [%s]", smbstate['ip'])
  2646.  
  2647. --        [in,ref] policy_handle *handle,
  2648.     arguments = msrpctypes.marshall_policy_handle(handle)
  2649.  
  2650. --        [in] uint32 control,
  2651.     arguments = arguments .. msrpctypes.marshall_svcctl_ControlCode(control)
  2652.  
  2653. --        [out,ref] SERVICE_STATUS *service_status
  2654.  
  2655.  
  2656.     -- Do the call
  2657.     status, result = call_function(smbstate, 0x01, arguments)
  2658.     if(status ~= true) then
  2659.         return false, result
  2660.     end
  2661.  
  2662.     stdnse.print_debug(3, "MSRPC: ControlService() returned successfully")
  2663.  
  2664.     -- Make arguments easier to use
  2665.     arguments = result['arguments']
  2666.     pos = 1
  2667.  
  2668. --        [in,ref] policy_handle *handle,
  2669. --        [in] uint32 control,
  2670. --        [out,ref] SERVICE_STATUS *service_status
  2671.     pos, result['service_status'] = msrpctypes.unmarshall_SERVICE_STATUS(arguments, pos)
  2672.  
  2673.     pos, result['return'] = msrpctypes.unmarshall_int32(arguments, pos)
  2674.     if(result['return'] == nil) then
  2675.         return false, "Read off the end of the packet (svcctl.controlservice)"
  2676.     end
  2677.     if(result['return'] ~= 0) then
  2678.         return false, smb.get_status_name(result['return']) .. " (svcctl.controlservice)"
  2679.     end
  2680.  
  2681.     return true, result
  2682.  
  2683. end
  2684.  
  2685.  
  2686. --- Calls the function <code>QueryServiceStatus</code>, which gets the state information about the service. 
  2687. --
  2688. --@param smbstate The SMB state table.
  2689. --@param handle   The handle, opened by <code>OpenServiceW</code>.
  2690. --@return (status, result) If status is false, result is an error message. Otherwise, result is a table of values
  2691. --        representing the "out" parameters.
  2692. function svcctl_queryservicestatus(smbstate, handle, control)
  2693.     local i, j
  2694.     local status, result
  2695.     local arguments
  2696.     local pos, align
  2697.  
  2698.     stdnse.print_debug(2, "MSRPC: Calling QueryServiceStatus() [%s]", smbstate['ip'])
  2699.  
  2700. --        [in,ref] policy_handle *handle,
  2701.     arguments = msrpctypes.marshall_policy_handle(handle)
  2702.  
  2703. --        [out,ref] SERVICE_STATUS *service_status
  2704.  
  2705.  
  2706.     -- Do the call
  2707.     status, result = call_function(smbstate, 0x06, arguments)
  2708.     if(status ~= true) then
  2709.         return false, result
  2710.     end
  2711.  
  2712.     stdnse.print_debug(3, "MSRPC: QueryServiceStatus() returned successfully")
  2713.  
  2714.     -- Make arguments easier to use
  2715.     arguments = result['arguments']
  2716.     pos = 1
  2717.  
  2718. --        [in,ref] policy_handle *handle,
  2719. --        [out,ref] SERVICE_STATUS *service_status
  2720.     pos, result['service_status'] = msrpctypes.unmarshall_SERVICE_STATUS(arguments, pos)
  2721.  
  2722.     pos, result['return'] = msrpctypes.unmarshall_int32(arguments, pos)
  2723.     if(result['return'] == nil) then
  2724.         return false, "Read off the end of the packet (svcctl.queryservicestatus)"
  2725.     end
  2726.     if(result['return'] ~= 0) then
  2727.         return false, smb.get_status_name(result['return']) .. " (svcctl.queryservicestatus)"
  2728.     end
  2729.  
  2730.     return true, result
  2731. end
  2732.  
  2733. ---Calls the function <code>JobAdd</code>, which schedules a process to be run on the remote 
  2734. -- machine. This requires administrator privileges to run, and the command itself runs as
  2735. -- SYSTEM. 
  2736. --@param smbstate The SMB state table.
  2737. --@param server   The IP or Hostname of the server (seems to be ignored but it's a good idea to have it)
  2738. --@param command  The command to run on the remote machine. The appropriate file(s) already 
  2739. --                have to be there, and this should be a full path. 
  2740. --@param time     (optional) The time at which to run the command. Default: 5 seconds from 
  2741. --                when the user logged in. 
  2742. function atsvc_jobadd(smbstate, server, command, time)
  2743.     local i, j
  2744.     local status, result
  2745.     local arguments
  2746.     local pos, align
  2747.  
  2748.     -- Set up the time
  2749.     if(time == nil) then
  2750.         -- TODO
  2751.     end
  2752.  
  2753.     stdnse.print_debug(2, "MSRPC: Calling AddJob(%s) [%s]", command, smbstate['ip'])
  2754.  
  2755. --        [in,unique,string,charset(UTF16)] uint16 *servername,
  2756.     arguments = msrpctypes.marshall_unicode_ptr(server, true)
  2757.  
  2758. --        [in] atsvc_JobInfo *job_info,
  2759.     arguments = arguments .. msrpctypes.marshall_atsvc_JobInfo(command, time)
  2760. --        [out,ref]    uint32 *job_id
  2761.  
  2762.  
  2763.     -- Do the call
  2764.     status, result = call_function(smbstate, 0x00, arguments)
  2765.     if(status ~= true) then
  2766.         return false, result
  2767.     end
  2768.  
  2769.     stdnse.print_debug(3, "MSRPC: AddJob() returned successfully")
  2770.  
  2771.     -- Make arguments easier to use
  2772.     arguments = result['arguments']
  2773.     pos = 1
  2774.  
  2775. --        [in,unique,string,charset(UTF16)] uint16 *servername,
  2776. --        [in] atsvc_JobInfo *job_info,
  2777. --        [out,ref]    uint32 *job_id
  2778.     pos, result['job_id'] = msrpctypes.unmarshall_int32(arguments, pos)
  2779.  
  2780.     pos, result['return'] = msrpctypes.unmarshall_int32(arguments, pos)
  2781.     if(result['return'] == nil) then
  2782.         return false, "Read off the end of the packet (atsvc.addjob())"
  2783.     end
  2784.     if(result['return'] ~= 0) then
  2785.         return false, smb.get_status_name(result['return']) .. " (atsvc.addjob())"
  2786.     end
  2787.  
  2788.     return true, result
  2789. end
  2790.  
  2791. ---Attempt to enumerate users using SAMR functions. 
  2792. --
  2793. --@param host The host object. 
  2794. --@return (status, result) If status is false, result is an error message. Otherwise, result
  2795. -- is an array of tables, each of which contain the following fields:
  2796. -- * name
  2797. -- * fullname
  2798. -- * description
  2799. -- * rid
  2800. -- * domain
  2801. -- * typestr
  2802. -- * source
  2803. -- * flags[]
  2804. function samr_enum_users(host)
  2805.     local i, j
  2806.  
  2807.     stdnse.print_debug(3, "Entering enum_samr()")
  2808.  
  2809.     local smbstate
  2810.     local bind_result, connect4_result, enumdomains_result
  2811.     local connect_handle
  2812.     local status, smbstate
  2813.     local response = {}
  2814.  
  2815.     -- Create the SMB session
  2816.     status, smbstate = start_smb(host, SAMR_PATH, true)
  2817.  
  2818.     if(status == false) then
  2819.         return false, smbstate
  2820.     end
  2821.  
  2822.     -- Bind to SAMR service
  2823.     status, bind_result = bind(smbstate, SAMR_UUID, SAMR_VERSION, nil)
  2824.     if(status == false) then
  2825.         stop_smb(smbstate)
  2826.         return false, bind_result
  2827.     end
  2828.  
  2829.     -- Call connect4()
  2830.     status, connect4_result = samr_connect4(smbstate, host.ip)
  2831.     if(status == false) then
  2832.         stop_smb(smbstate)
  2833.         return false, connect4_result
  2834.     end
  2835.  
  2836.     -- Save the connect_handle
  2837.     connect_handle = connect4_result['connect_handle']
  2838.  
  2839.     -- Call EnumDomains()
  2840.     status, enumdomains_result = samr_enumdomains(smbstate, connect_handle)
  2841.     if(status == false) then
  2842.         stop_smb(smbstate)
  2843.         return false, enumdomains_result
  2844.     end
  2845.  
  2846.     -- If no domains were returned, go back with an error
  2847.     if(#enumdomains_result['sam']['entries'] == 0) then
  2848.         stop_smb(smbstate)
  2849.         return false, "Couldn't find any domains"
  2850.     end
  2851.  
  2852.     -- Now, loop through the domains and find the users
  2853.     for i = 1, #enumdomains_result['sam']['entries'], 1 do
  2854.  
  2855.         local domain = enumdomains_result['sam']['entries'][i]['name']
  2856.         -- We don't care about the 'builtin' domain, in all my tests it's empty
  2857.         if(domain ~= 'Builtin') then
  2858.             local sid
  2859.             local domain_handle
  2860.             local opendomain_result, querydisplayinfo_result
  2861.  
  2862.             -- Call LookupDomain()
  2863.             status, lookupdomain_result = samr_lookupdomain(smbstate, connect_handle, domain)
  2864.             if(status == false) then
  2865.                 stop_smb(smbstate)
  2866.                 return false, lookupdomain_result
  2867.             end
  2868.  
  2869.             -- Save the sid
  2870.             sid = lookupdomain_result['sid']
  2871.     
  2872.             -- Call OpenDomain()
  2873.             status, opendomain_result = samr_opendomain(smbstate, connect_handle, sid)
  2874.             if(status == false) then
  2875.                 stop_smb(smbstate)
  2876.                 return false, opendomain_result
  2877.             end
  2878.  
  2879.             -- Save the domain handle
  2880.             domain_handle = opendomain_result['domain_handle']
  2881.  
  2882.             -- Loop as long as we're getting valid results    
  2883.             j = 0
  2884.             repeat
  2885.                 -- Call QueryDisplayInfo()
  2886.                 status, querydisplayinfo_result = samr_querydisplayinfo(smbstate, domain_handle, j, SAMR_GROUPSIZE)
  2887.                 if(status == false) then
  2888.                     stop_smb(smbstate)
  2889.                     return false, querydisplayinfo_result
  2890.                 end
  2891.  
  2892.                 -- Save the response
  2893.                 if(querydisplayinfo_result['info'] ~= nil and querydisplayinfo_result['info']['entries'] ~= nil) then
  2894.                     local k
  2895.                     for k = 1, #querydisplayinfo_result['info']['entries'], 1 do
  2896.                         local array = {}
  2897.                         local l
  2898.     
  2899.                         -- The reason these are all indexed from '1' is because we request names one at a time. 
  2900.                         array['name']        = querydisplayinfo_result['info']['entries'][k]['account_name']
  2901.                         array['fullname']    = querydisplayinfo_result['info']['entries'][k]['full_name']
  2902.                         array['description'] = querydisplayinfo_result['info']['entries'][k]['description']
  2903.                         array['rid']         = querydisplayinfo_result['info']['entries'][k]['rid']
  2904.                         array['domain']      = domain
  2905.                         array['type']        = 'SID_NAME_USER'
  2906.                         array['typestr']     = 'User'
  2907.                         array['source']      = 'SAMR Enumeration'
  2908.                         array['flags']       = querydisplayinfo_result['info']['entries'][k]['acct_flags']
  2909.  
  2910.                         -- Convert each element in the 'flags' array into the equivalent string
  2911.                         for l = 1, #array['flags'], 1 do
  2912.                             array['flags'][l] = samr_AcctFlags_tostr(array['flags'][l])
  2913.                         end
  2914.     
  2915.                         -- Add it to the array
  2916.                         response[#response + 1] = array
  2917.                     end
  2918.                 end
  2919.                 j = j + SAMR_GROUPSIZE
  2920.             until querydisplayinfo_result['return'] == 0
  2921.  
  2922.             -- Close the domain handle
  2923.             samr_close(smbstate, domain_handle)
  2924.         end -- Checking for 'builtin'
  2925.     end -- Domain loop
  2926.  
  2927.     -- Close the connect handle
  2928.     samr_close(smbstate, connect_handle)
  2929.  
  2930.     -- Stop the SAMR SMB
  2931.     stop_smb(smbstate)
  2932.  
  2933.     stdnse.print_debug(3, "Leaving enum_samr()")
  2934.  
  2935.     return true, response
  2936. end
  2937.  
  2938. ---Attempt to enumerate users using LSA functions.
  2939. --
  2940. --@param host The host object. 
  2941. --@return status, result -- if status is false, result is an error message; otherwise, result is 
  2942. --        an array of tables, each containing the following elements:
  2943. -- * name
  2944. -- * rid
  2945. -- * domain
  2946. -- * typestr
  2947. -- * source
  2948. function lsa_enum_users(host)
  2949.  
  2950.     local smbstate
  2951.     local response = {}
  2952.     local status, smbstate, bind_result, openpolicy2_result, lookupnames2_result, lookupsids2_result
  2953.  
  2954.     stdnse.print_debug(3, "Entering enum_lsa()")
  2955.  
  2956.     -- Create the SMB session
  2957.     status, smbstate = start_smb(host, LSA_PATH, true)
  2958.     if(status == false) then
  2959.         return false, smbstate
  2960.     end
  2961.  
  2962.     -- Bind to LSA service
  2963.     status, bind_result = bind(smbstate, LSA_UUID, LSA_VERSION, nil)
  2964.     if(status == false) then
  2965.         stop_smb(smbstate)
  2966.         return false, bind_result
  2967.     end
  2968.  
  2969.     -- Open the LSA policy
  2970.     status, openpolicy2_result = lsa_openpolicy2(smbstate, host.ip)
  2971.     if(status == false) then
  2972.         stop_smb(smbstate)
  2973.         return false, openpolicy2_result
  2974.     end
  2975.  
  2976.     -- Start with some common names, as well as the name returned by the negotiate call
  2977.     -- Vista doesn't like a 'null' after the server name, so fix that (TODO: the way I strip the null here feels hackish, is there a better way?)
  2978.     names = {"administrator", "guest", "test"}
  2979.     -- These aren't always sent back (especially with 'extended security')
  2980.     if(smbstate['domain'] ~= nil) then
  2981.         names[#names + 1] = smbstate['domain']
  2982.     end
  2983.     if(smbstate['server'] ~= nil) then
  2984.         names[#names + 1] = string.sub(smbstate['server'], 1, #smbstate['server'] - 1) 
  2985.     end
  2986.  
  2987.     -- Get the server's name from nbstat
  2988.     local result, server_name = netbios.get_server_name(host.ip)
  2989.     if(result == true) then
  2990.         names[#names + 1] = server_name
  2991.     end
  2992.  
  2993.     -- Get the logged in user from nbstat
  2994.     local result, user_name = netbios.get_user_name(host.ip)
  2995.     if(result == true) then
  2996.         names[#names + 1] = user_name
  2997.     end
  2998.  
  2999.     -- Look up the names, if any are valid than the server's SID will be returned
  3000.     status, lookupnames2_result = lsa_lookupnames2(smbstate, openpolicy2_result['policy_handle'], names)
  3001.     if(status == false) then
  3002.         stop_smb(smbstate)
  3003.         return false, lookupnames2_result
  3004.     end
  3005.     -- Loop through the domains returned and find the users in each
  3006.     for i = 1, #lookupnames2_result['domains']['domains'], 1 do
  3007.         local domain = lookupnames2_result['domains']['domains'][i]['name']
  3008.         local sid    = lookupnames2_result['domains']['domains'][i]['sid']
  3009.         local sids   = { }
  3010.  
  3011.         -- Start by looking up 500 and up
  3012.         for j = 500, 500 + LSA_GROUPSIZE, 1 do 
  3013.             sids[#sids + 1] = sid .. "-" .. j 
  3014.         end
  3015.  
  3016.         status, lookupsids2_result = lsa_lookupsids2(smbstate, openpolicy2_result['policy_handle'], sids)
  3017.         if(status == false) then
  3018.             stdnse.print_debug(1, string.format("Error looking up RIDs: %s", lookupsids2_result))
  3019.         else
  3020.             -- Put the details for each name into an array
  3021.             -- NOTE: Be sure to mirror any changes here in the next bit! 
  3022.             for j = 1, #lookupsids2_result['names']['names'], 1 do
  3023.                 if(lookupsids2_result['names']['names'][j]['sid_type'] ~= "SID_NAME_UNKNOWN") then
  3024.                     local result = {}
  3025.                     result['name']    = lookupsids2_result['names']['names'][j]['name']
  3026.                     result['rid']      = 500 + j - 1
  3027.                     result['domain']  = domain
  3028.                     result['type']    = lookupsids2_result['names']['names'][j]['sid_type']
  3029.                     result['typestr'] = lsa_SidType_tostr(result['type'])
  3030.                     result['source']  = "LSA Bruteforce"
  3031.                     table.insert(response, result)
  3032.                 end
  3033.             end
  3034.         end
  3035.  
  3036.         -- Start at RID 1000
  3037.         local start      = 1000
  3038.         -- Keep track of the number of consecutive empty groups
  3039.         local empty      = 0
  3040.         repeat
  3041.             -- Keep track of the number of names we found in this group
  3042.             local used_names = 0
  3043.  
  3044.             local sids = {}
  3045.             for j = start, start + LSA_GROUPSIZE, 1 do 
  3046.                 sids[#sids + 1] = sid .. "-" .. j
  3047.             end
  3048.  
  3049.             -- Try converting this group of RIDs into names
  3050.             status, lookupsids2_result = lsa_lookupsids2(smbstate, openpolicy2_result['policy_handle'], sids)
  3051.             if(status == false) then
  3052.                 stdnse.print_debug(1, string.format("Error looking up RIDs: %s", lookupsids2_result))
  3053.             else
  3054.                 -- Put the details for each name into an array
  3055.                 for j = 1, #lookupsids2_result['names']['names'], 1 do
  3056.                     -- Determine the RID
  3057.                     local name = lookupsids2_result['names']['names'][j]['name']
  3058.                     local rid = start + j - 1
  3059.                     local typenum = lookupsids2_result['names']['names'][j]['sid_type']
  3060.                     local typestr = lsa_SidType_tostr(typenum)
  3061.  
  3062.                     -- Check if the username matches the rid (one server we discovered returned every user as valid, 
  3063.                     -- this is to prevent that infinite loop)
  3064.                     if(tonumber(name) ~= rid) then
  3065.                         if(lookupsids2_result['names']['names'][j]['sid_type'] ~= "SID_NAME_UNKNOWN") then
  3066.                             local result = {}
  3067.                             result['name']    = name
  3068.                             result['rid']      = rid
  3069.                             result['domain']  = domain
  3070.                             result['type']    = typenum
  3071.                             result['typestr'] = typestr
  3072.                             result['source']  = "LSA Bruteforce"
  3073.                             table.insert(response, result)
  3074.     
  3075.                             -- Increment the number of names we've found
  3076.                             used_names = used_names + 1
  3077.                         end
  3078.                     end
  3079.                 end
  3080.             end
  3081.  
  3082.  
  3083.             -- Either increment or reset the number of empty groups
  3084.             if(used_names == 0) then
  3085.                 empty = empty + 1
  3086.             else
  3087.                 empty = 0
  3088.             end
  3089.  
  3090.             -- Go to the next set of RIDs
  3091.             start = start + LSA_GROUPSIZE
  3092.         until (status == false or (empty == LSA_MINEMPTY))
  3093.     end
  3094.  
  3095.     -- Close the handle
  3096.     lsa_close(smbstate, openpolicy2_result['policy_handle'])
  3097.  
  3098.     stop_smb(smbstate)
  3099.  
  3100.     stdnse.print_debug(3, "Leaving enum_lsa()")
  3101.  
  3102.     return true, response
  3103. end
  3104.  
  3105. ---Gets the best possible list of user accounts on the remote system using every available method. 
  3106. --
  3107. -- TODO: Caching, store this in the registry
  3108. --
  3109. --@param host The host object. 
  3110. --@return (status, result, names) If status is false, result is an error message; otherwise, result
  3111. --        is an array of users indexed by username and names is a sorted array of names. 
  3112. function get_user_list(host)
  3113.     local status_samr, result_samr
  3114.     local status_lsa,  result_lsa
  3115.     local response = {}
  3116.     local names = {}
  3117.     local i, v
  3118.  
  3119.     status_lsa,  result_lsa  = lsa_enum_users(host)
  3120.     if(status_lsa == false) then
  3121.         stdnse.print_debug("MSRPC: Failed to enumerate users through LSA: %s", result_lsa)
  3122.     else
  3123.         for i = 1, #result_lsa, 1 do
  3124.             if(result_lsa[i]['name'] ~= nil and result_lsa[i]['type'] == "SID_NAME_USER") then
  3125.                 response[result_lsa[i]['domain'] .. '\\' .. result_lsa[i]['name']] = result_lsa[i]
  3126.             end
  3127.         end
  3128.     end
  3129.  
  3130.     status_samr, result_samr = samr_enum_users(host)
  3131.     if(status_samr == false) then
  3132.         stdnse.print_debug("MSRPC: Failed to enumerate users through SAMR: %s", result_samr)
  3133.     else
  3134.         for i = 1, #result_samr, 1 do
  3135.             if(result_samr[i]['name'] ~= nil and result_samr[i]['type'] == "SID_NAME_USER") then
  3136.                 response[result_samr[i]['domain'] .. '\\' .. result_samr[i]['name']] = result_samr[i]
  3137.             end
  3138.         end
  3139.     end
  3140.  
  3141.     if(status_samr == false and status_lsa == false) then
  3142.         return false, "MSRPC: Couldn't enumerate users; see debug output for more information"
  3143.     end
  3144.  
  3145.     for i, v in pairs(response) do
  3146.         table.insert(names, i)
  3147.     end
  3148.     table.sort(names, function(a,b) return a:lower() < b:lower() end )
  3149.  
  3150.     return true, response, names
  3151. end
  3152.  
  3153. ---Create a "service" on a remote machine. This service is linked to an executable that is already
  3154. -- on the system. The name of the service can be whatever you want it to be. The service is created
  3155. -- in the "stopped" state with "manual" startup, and it ignores errors. The 'servicename' is what
  3156. -- people will see on the system while the service is running, and what'll stay there is something
  3157. -- happens that the service can't be deleted properly. 
  3158. --
  3159. -- Note that this (and the other "service" functions) are highly invasive. They make configuration
  3160. -- changes to the machine that can potentially affect stability. 
  3161. --
  3162. -- The reason that this and the other "service" functions don't require a <code>smbstate</code> 
  3163. -- object is that I wanted them to be independent. If a service fails to start, I don't want it 
  3164. -- to affect the program's ability to stop and delete the service. Every service function is
  3165. -- independent. 
  3166. --
  3167. --@param host        The host object. 
  3168. --@param servicename The name of the service to create. 
  3169. --@param path        The path and filename on the remote system. 
  3170. --@return (status, err) If status is <code>false</code>, <code>err</code> is an error message; 
  3171. --        otherwise, err is undefined. 
  3172. function service_create(host, servicename, path)
  3173.     local status, smbstate, bind_result, open_result, create_result, close_result
  3174.  
  3175.     stdnse.print_debug(1, "Creating service: %s (%s)", servicename, path)
  3176.  
  3177.     -- Create the SMB session
  3178.     status, smbstate = start_smb(host, SVCCTL_PATH)
  3179.     if(status == false) then
  3180.         return false, smbstate
  3181.     end
  3182.  
  3183.     -- Bind to SVCCTL service
  3184.     status, bind_result = bind(smbstate, SVCCTL_UUID, SVCCTL_VERSION, nil)
  3185.     if(status == false) then
  3186.         smb.stop(smbstate)
  3187.         return false, bind_result
  3188.     end
  3189.  
  3190.     -- Open the service manager
  3191.     stdnse.print_debug(2, "Opening the remote service manager")
  3192.     status, open_result = svcctl_openscmanagerw(smbstate, host.ip)
  3193.     if(status == false) then
  3194.         smb.stop(smbstate)
  3195.         return false, open_result
  3196.     end
  3197.  
  3198.     -- Create the service
  3199.     stdnse.print_debug(2, "Creating the service", servicename)
  3200.     status, create_result = svcctl_createservicew(smbstate, open_result['handle'], servicename, servicename, path)
  3201.     if(status == false) then
  3202.         smb.stop(smbstate)
  3203.         return false, create_result
  3204.     end
  3205.     -- Close the handle to the service
  3206.     status, close_result = svcctl_closeservicehandle(smbstate, create_result['handle'])
  3207.     if(status == false) then
  3208.         smb.stop(smbstate)
  3209.         return false, close_result
  3210.     end
  3211.  
  3212.     -- Close the service manager
  3213.     status, close_result = svcctl_closeservicehandle(smbstate, open_result['handle'])
  3214.     if(status == false) then
  3215.         smb.stop(smbstate)
  3216.         return false, close_result
  3217.     end
  3218.  
  3219.     smb.stop(smbstate)
  3220.  
  3221.     return true
  3222. end
  3223.  
  3224. ---Start a service on the remote machine based on its name. For example, to start the registry 
  3225. -- service, this can be called on "RemoteRegistry". 
  3226. --
  3227. -- If you start a service on a machine, you should also stop it when you're finished. Every service
  3228. -- running is extra attack surface for a potential attacker
  3229. --
  3230. --@param host        The host object. 
  3231. --@param servicename The name of the service to start. 
  3232. --@param args        [optional] The arguments to pass to the service. Most built-in services don't
  3233. --                   require arguments. 
  3234. --@return (status, err) If status is <code>false</code>, <code>err</code> is an error message; 
  3235. --        otherwise, err is undefined. 
  3236. function service_start(host, servicename, args)
  3237.     local status, smbstate, bind_result, open_result, open_service_result, start_result, close_result, query_result
  3238.  
  3239.     stdnse.print_debug(1, "Starting service: %s", servicename)
  3240.  
  3241.     -- Create the SMB session
  3242.     status, smbstate = start_smb(host, SVCCTL_PATH)
  3243.     if(status == false) then
  3244.         return false, smbstate
  3245.     end
  3246.  
  3247.     -- Bind to SVCCTL service
  3248.     status, bind_result = bind(smbstate, SVCCTL_UUID, SVCCTL_VERSION, nil)
  3249.     if(status == false) then
  3250.         smb.stop(smbstate)
  3251.         return false, bind_result
  3252.     end
  3253.  
  3254.     -- Open the service manager
  3255.     stdnse.print_debug(1, "Opening the remote service manager")
  3256.     status, open_result = svcctl_openscmanagerw(smbstate, host.ip)
  3257.     if(status == false) then
  3258.         smb.stop(smbstate)
  3259.         return false, open_result
  3260.     end
  3261.  
  3262.     -- Get a handle to the service
  3263.     stdnse.print_debug(2, "Getting a handle to the service")
  3264.     status, open_service_result = svcctl_openservicew(smbstate, open_result['handle'], servicename)
  3265.     if(status == false) then
  3266.         smb.stop(smbstate)
  3267.         return false, open_service_result
  3268.     end
  3269.  
  3270.     -- Start it
  3271.     stdnse.print_debug(2, "Starting the service")
  3272.     status, start_result = svcctl_startservicew(smbstate, open_service_result['handle'], args)
  3273.     if(status == false) then
  3274.         smb.stop(smbstate)
  3275.         return false, start_result
  3276.     end
  3277.  
  3278.     -- Wait for it to start
  3279.     stdnse.print_debug(2, "Waiting for the service to start")
  3280.     repeat
  3281.         status, query_result = svcctl_queryservicestatus(smbstate, open_service_result['handle'])
  3282.         if(status == false) then
  3283.             smb.stop(smbstate)
  3284.             return false, query_result
  3285.         end
  3286.     until query_result['service_status']['controls_accepted'][1] == "SERVICE_CONTROL_STOP"
  3287.  
  3288.     -- Close the handle to the service
  3289.     status, close_result = svcctl_closeservicehandle(smbstate, open_service_result['handle'])
  3290.     if(status == false) then
  3291.         smb.stop(smbstate)
  3292.         return false, close_result
  3293.     end
  3294.  
  3295.     -- Close the service manager
  3296.     status, close_result = svcctl_closeservicehandle(smbstate, open_result['handle'])
  3297.     if(status == false) then
  3298.         smb.stop(smbstate)
  3299.         return false, close_result
  3300.     end
  3301.  
  3302.     smb.stop(smbstate)
  3303.  
  3304.     return true
  3305. end
  3306.  
  3307. ---Stop a service on the remote machine based on its name. For example, to stop the registry 
  3308. -- service, this can be called on "RemoteRegistry". 
  3309. --
  3310. -- This can be called on a service that's already stopped without hurting anything (just keep in mind
  3311. -- that an error will be returned). 
  3312. -- 
  3313. --@param host        The host object. 
  3314. --@param servicename The name of the service to stop. 
  3315. --@return (status, err) If status is <code>false</code>, <code>err</code> is an error message; 
  3316. --        otherwise, err is undefined. 
  3317. function service_stop(host, servicename)
  3318.     local status, smbstate, bind_result, open_result, open_service_result, control_result, close_result, query_result
  3319.  
  3320.     stdnse.print_debug(1, "Stopping service: %s", servicename)
  3321.  
  3322.     -- Create the SMB session
  3323.     status, smbstate = start_smb(host, SVCCTL_PATH)
  3324.     if(status == false) then
  3325.         return false, smbstate
  3326.     end
  3327.  
  3328.     -- Bind to SVCCTL service
  3329.     status, bind_result = bind(smbstate, SVCCTL_UUID, SVCCTL_VERSION, nil)
  3330.     if(status == false) then
  3331.         smb.stop(smbstate)
  3332.         return false, bind_result
  3333.     end
  3334.  
  3335.     -- Open the service manager
  3336.     stdnse.print_debug(2, "Opening the remote service manager")
  3337.     status, open_result = svcctl_openscmanagerw(smbstate, host.ip)
  3338.     if(status == false) then
  3339.         smb.stop(smbstate)
  3340.         return false, open_result
  3341.     end
  3342.  
  3343.     -- Get a handle to the service
  3344.     stdnse.print_debug(2, "Getting a handle to the service")
  3345.     status, open_service_result = svcctl_openservicew(smbstate, open_result['handle'], servicename)
  3346.     if(status == false) then
  3347.         smb.stop(smbstate)
  3348.         return false, open_service_result
  3349.     end
  3350.  
  3351.     -- Stop it
  3352.     stdnse.print_debug(2, "Stopping the service")
  3353.     status, control_result = svcctl_controlservice(smbstate, open_service_result['handle'], "SERVICE_CONTROL_STOP")
  3354.     if(status == false) then
  3355.         smb.stop(smbstate)
  3356.         return false, control_result
  3357.     end
  3358.  
  3359.     -- Wait for it to stop (TODO: Make this better)
  3360.     stdnse.print_debug(2, "Waiting for the service to stop")
  3361.     repeat
  3362.         status, query_result = svcctl_queryservicestatus(smbstate, open_service_result['handle'])
  3363.         if(status == false) then
  3364.             smb.stop(smbstate)
  3365.             return false, query_result
  3366.         end
  3367.     until query_result['service_status']['controls_accepted'][1] == nil
  3368.  
  3369.     -- Close the handle to the service
  3370.     status, close_result = svcctl_closeservicehandle(smbstate, open_service_result['handle'])
  3371.     if(status == false) then
  3372.         smb.stop(smbstate)
  3373.         return false, close_result
  3374.     end
  3375.  
  3376.     -- Close the service manager
  3377.     status, close_result = svcctl_closeservicehandle(smbstate, open_result['handle'])
  3378.     if(status == false) then
  3379.         smb.stop(smbstate)
  3380.         return false, close_result
  3381.     end
  3382.  
  3383.     smb.stop(smbstate)
  3384.  
  3385.     return true
  3386. end 
  3387.  
  3388. ---Delete a service on the remote machine based on its name. I don't recommend deleting any services that
  3389. -- you didn't create. 
  3390. -- 
  3391. --@param host        The host object. 
  3392. --@param servicename The name of the service to delete. 
  3393. --@return (status, err) If status is <code>false</code>, <code>err</code> is an error message; 
  3394. --        otherwise, err is undefined. 
  3395. function service_delete(host, servicename)
  3396.     local status, smbstate, bind_result, open_result, open_service_result, delete_result, close_result
  3397.  
  3398.     stdnse.print_debug(1, "Deleting service: %s", servicename)
  3399.  
  3400.     -- Create the SMB session
  3401.     status, smbstate = start_smb(host, SVCCTL_PATH)
  3402.     if(status == false) then
  3403.         return false, smbstate
  3404.     end
  3405.  
  3406.     -- Bind to SVCCTL service
  3407.     status, bind_result = bind(smbstate, SVCCTL_UUID, SVCCTL_VERSION, nil)
  3408.     if(status == false) then
  3409.         smb.stop(smbstate)
  3410.         return false, bind_result
  3411.     end
  3412.  
  3413.     -- Open the service manager
  3414.     stdnse.print_debug(2, "Opening the remote service manager")
  3415.     status, open_result = svcctl_openscmanagerw(smbstate, host.ip)
  3416.     if(status == false) then
  3417.         smb.stop(smbstate)
  3418.         return false, open_result
  3419.     end
  3420.  
  3421.     -- Get a handle to the service
  3422.     stdnse.print_debug(2, "Getting a handle to the service: %s", servicename)
  3423.     status, open_service_result = svcctl_openservicew(smbstate, open_result['handle'], servicename)
  3424.     if(status == false) then
  3425.         smb.stop(smbstate)
  3426.         return false, open_service_result
  3427.     end
  3428.  
  3429.     -- Delete the service
  3430.     stdnse.print_debug(2, "Deleting the service")
  3431.     status, delete_result = svcctl_deleteservice(smbstate, open_service_result['handle'])
  3432.     if(status == false) then
  3433.         smb.stop(smbstate)
  3434.         return false, delete_result
  3435.     end
  3436.  
  3437.     -- Close the handle to the service
  3438.     status, close_result = svcctl_closeservicehandle(smbstate, open_service_result['handle'])
  3439.     if(status == false) then
  3440.         smb.stop(smbstate)
  3441.         return false, close_result
  3442.     end
  3443.  
  3444.     -- Close the service manager
  3445.     status, close_result = svcctl_closeservicehandle(smbstate, open_result['handle'])
  3446.     if(status == false) then
  3447.         smb.stop(smbstate)
  3448.         return false, close_result
  3449.     end
  3450.  
  3451.     smb.stop(smbstate)
  3452.  
  3453.     return true
  3454. end
  3455.  
  3456. ---Retrieves statistical information about the given server. This function requires administrator privileges
  3457. -- to run, and is present on all Windows versions, so it's a useful way to check whether or not an account
  3458. -- is administrative. 
  3459. --@param host       The host object
  3460. --@return (status, data) If status is false, data is an error message; otherwise, data is a table of information
  3461. --        about the server. 
  3462. function get_server_stats(host)
  3463.     local stats
  3464.     local status
  3465.     local smbstate
  3466.  
  3467.     -- Create the SMB session
  3468.     status, smbstate = start_smb(host, SRVSVC_PATH)
  3469.     if(status == false) then
  3470.         return false, smbstate
  3471.     end
  3472.    
  3473.     -- Bind to SRVSVC service
  3474.     status, bind_result = bind(smbstate, SRVSVC_UUID, SRVSVC_VERSION, nil)
  3475.     if(status == false) then
  3476.         smb.stop(smbstate)
  3477.         return false, bind_result
  3478.     end
  3479.    
  3480.     -- Call netservergetstatistics for 'server'
  3481.     status, netservergetstatistics_result = srvsvc_netservergetstatistics(smbstate, host.ip)
  3482.     if(status == false) then
  3483.         smb.stop(smbstate)
  3484.         return false, netservergetstatistics_result
  3485.     end
  3486.    
  3487.     -- Stop the session
  3488.     smb.stop(smbstate)
  3489.    
  3490.     -- Build the response   
  3491.     local stats = netservergetstatistics_result['stat']
  3492.  
  3493.     -- Convert the date to a string
  3494.     stats['start_str'] = os.date("%Y-%m-%d %H:%M:%S", stats['start'])
  3495.  
  3496.     -- Get the period and convert it to a proper time offset
  3497.     stats['period'] = os.time() - stats['start']
  3498.     if(stats['period'] > 60 * 60 * 24) then
  3499.         stats['period_str'] = string.format("%dd%dh%02dm%02ds", stats['period'] / (60*60*24), (stats['period'] % (60*60*24)) / 3600, (stats['period'] % 3600) / 60, stats['period'] % 60)
  3500.     elseif(stats['period'] > 60 * 60) then
  3501.         stats['period_str'] = string.format("%dh%02dm%02ds", stats['period'] / 3600, (stats['period'] % 3600) / 60, stats['period'] % 60)
  3502.     else
  3503.         stats['period_str'] = string.format("%02dm%02ds", stats['period'] / 60, stats['period'] % 60)
  3504.     end
  3505.    
  3506.     -- Combine the 64-bit values
  3507.     stats['bytessent'] = bit.bor(bit.lshift(stats['bytessent_high'], 32), stats['bytessent_low'])
  3508.     stats['bytesrcvd'] = bit.bor(bit.lshift(stats['bytesrcvd_high'], 32), stats['bytesrcvd_low'])
  3509.  
  3510.     -- Sidestep divide-by-zero errors (probabyl won't come up, but I'd rather be safe)
  3511.     if(stats['period'] == 0) then
  3512.         stats['period'] = 1
  3513.     end
  3514.    
  3515.       -- Get the bytes/second values
  3516.     stats['bytessentpersecond'] = stats['bytessent'] / stats['period']
  3517.     stats['bytesrcvdpersecond'] = stats['bytesrcvd'] / stats['period']
  3518.  
  3519.     return true, stats
  3520. end
  3521.  
  3522. ---Attempts to enumerate the shares on a remote system using MSRPC calls. Without a user account,
  3523. -- this will likely fail against a modern system, but will succeed against Windows 2000. 
  3524. --
  3525. --@param host The host object. 
  3526. --@return Status (true or false).
  3527. --@return List of shares (if status is true) or an an error string (if status is false).
  3528. function enum_shares(host)
  3529.  
  3530.     local status, smbstate
  3531.     local bind_result, netshareenumall_result
  3532.     local shares
  3533.     local i, v
  3534.  
  3535.     -- Create the SMB session
  3536.     status, smbstate = start_smb(host, SRVSVC_PATH)
  3537.     if(status == false) then
  3538.         return false, smbstate
  3539.     end
  3540.  
  3541.     -- Bind to SRVSVC service
  3542.     status, bind_result = bind(smbstate, SRVSVC_UUID, SRVSVC_VERSION, nil)
  3543.     if(status == false) then
  3544.         smb.stop(smbstate) 
  3545.         return false, bind_result
  3546.     end
  3547.  
  3548.     -- Call netsharenumall
  3549.     status, netshareenumall_result = srvsvc_netshareenumall(smbstate, host.ip)
  3550.     if(status == false) then
  3551.         smb.stop(smbstate) 
  3552.         return false, netshareenumall_result
  3553.     end
  3554.  
  3555.     -- Stop the SMB session
  3556.     smb.stop(smbstate)
  3557.  
  3558.     -- Convert the share list to an array
  3559.     shares = {}
  3560.     for i, v in pairs(netshareenumall_result['ctr']['array']) do
  3561.         shares[#shares + 1] = v['name']
  3562.     end
  3563.  
  3564.     return true, shares
  3565. end
  3566.  
  3567.  
  3568. ---Attempts to retrieve additional information about a share. Will fail unless we have 
  3569. -- administrative access. 
  3570. --
  3571. --@param host The host object. 
  3572. --@return Status (true or false).
  3573. --@return A table of information about the share (if status is true) or an an error string (if 
  3574. --        status is false).
  3575. function get_share_info(host, name)
  3576.     local status, smbstate
  3577.     local response = {}
  3578.  
  3579.     -- Create the SMB session
  3580.     status, smbstate = start_smb(host, SRVSVC_PATH)
  3581.     if(status == false) then
  3582.         return false, smbstate
  3583.     end
  3584.  
  3585.     -- Bind to SRVSVC service
  3586.     status, bind_result = bind(smbstate, SRVSVC_UUID, SRVSVC_VERSION, nil)
  3587.     if(status == false) then
  3588.         smb.stop(smbstate) 
  3589.         return false, bind_result
  3590.     end
  3591.  
  3592.     -- Call NetShareGetInfo
  3593.     status, netsharegetinfo_result = srvsvc_netsharegetinfo(smbstate, host.ip, name, 2)
  3594.     if(status == false) then
  3595.         smb.stop(smbstate) 
  3596.         return false, netsharegetinfo_result
  3597.     end
  3598.  
  3599.     smb.stop(smbstate)
  3600.  
  3601.     return true, netsharegetinfo_result
  3602. end
  3603.  
  3604.  
  3605.