Nmap Development mailing list archives

Re: [nmap-svn] r16159 - nmap/nselib


From: Ron <ron () skullsecurity net>
Date: Fri, 20 Nov 2009 11:06:55 -0600

Sorry, I committed some extra code in this one that I didn't mean to (should have 'svn diff'ed.. oops).

The code is simply functions that aren't called from anywhere (yet), so, unless somebody minds, I'm just going to leave it.

commit-mailer () insecure org wrote:
Author: ron
Date: Fri Nov 20 09:00:55 2009
New Revision: 16159

Log:
Reduced the number of connections/traffic used by smb-enum-shares.nse by half. I was checking a random share to see if 
the right error is returned for every share, when it only actually had to be done once.

Modified:
   nmap/nselib/msrpc.lua
   nmap/nselib/smb.lua

Modified: nmap/nselib/msrpc.lua
==============================================================================
--- nmap/nselib/msrpc.lua       (original)
+++ nmap/nselib/msrpc.lua       Fri Nov 20 09:00:55 2009
@@ -395,6 +395,65 @@
        return true, result
 end
+---LANMAN API calls use different conventions than everything else, so make a separate function for them. +function call_lanmanapi(smbstate, opnum, server_type)
+       local status, result
+       local parameters = ""
+       local data
+       local convert, entry_count, available_entries
+       local entries = {}
+       local pos
+
+ parameters = bin.pack("<SzzSSI", + opnum, + "WrLehDO", -- Parameter Descriptor
+                                                       "B16",      -- Return Descriptor
+                                                       0,          -- Detail level
+                                                       14724,      -- Return buffer size
+                                                       server_type -- Server type
+                                               )
+
+       stdnse.print_debug(1, "MSRPC: Sending Browser Service request")
+       status, result = smb.send_transaction_named_pipe(smbstate, parameters, nil, "\\PIPE\\LANMAN", true)
+       if(not(status)) then
+               return false, "Couldn't call LANMAN API: " .. result
+       end
+
+       parameters = result.parameters
+       data       = result.data
+
+       stdnse.print_debug(1, "MSRPC: Parsing Browser Service response")
+       pos, status, convert, entry_count, available_entries = bin.unpack("<SSSS", parameters)
+       if(status ~= 0) then
+               return false, string.format("Call to Browser Service failed with status = %d", status)
+       end
+
+       stdnse.print_debug(1, "MSRPC: Browser service returned %d entries", entry_count)
+
+       local pos = 1
+       local entry
+       for i = 1, entry_count, 1 do
+               -- Read the string
+               pos, entry = bin.unpack("<z", data, pos)
+               stdnse.print_debug(1, "MSRPC: Found name: %s", entry)
+
+               -- pos needs to be rounded to the next even multiple of 16
+               while(((pos - 1) % 16) ~= 0) do
+                       pos = pos + 1
+               end
+
+               -- Make sure we didn't hit the end of the packet
+               if(not(entry)) then
+                       return false, "Call to browser service didn't receive enough data"
+               end
+
+               -- Insert the result
+               table.insert(entries, entry)
+       end
+
+       return true, entries
+end
+
---A proxy to a <code>msrpctypes</code> function that converts a ShareType to an english string. -- I implemented this as a proxy so scripts don't have to make direct calls to <code>msrpctypes</code>
 -- functions.

Modified: nmap/nselib/smb.lua
==============================================================================
--- nmap/nselib/smb.lua (original)
+++ nmap/nselib/smb.lua Fri Nov 20 09:00:55 2009
@@ -1972,18 +1972,23 @@
-- It is probably best to think of this as another protocol layer. This function will wrap SMB stuff around a -- MSRPC call, make the call, then unwrap the SMB stuff from it before returning. --
---@param smb    The SMB object associated with the connection
---@param function_parameters The parameter data to pass to the function. This is untested, since none of the
--- transactions I've done have required parameters. ---@param function_data The data to send with the packet. This is basically the next protocol layer ---@param pipe [optional] The pipe to transact on. Default: "\PIPE\". +--@param smb The SMB object associated with the connection
+--@param function_parameters  The parameter data to pass to the function. This is untested, since none of the
+-- transactions I've done have required parameters. +--@param function_data The data to send with the packet. This is basically the next protocol layer +--@param pipe [optional] The pipe to transact on. Default: "\PIPE\". +--@param no_setup [optional] If set, the 'setup' is set to 0 and some parameters are left off. This occurs while +-- using the LANMAN Remote API. Default: false. --@return (status, result) If status is false, result is an error message. Otherwise, result is a table -- containing 'parameters' and 'data', representing the parameters and data returned by the server. -function send_transaction_named_pipe(smb, function_parameters, function_data, pipe)
+function send_transaction_named_pipe(smb, function_parameters, function_data, pipe, no_setup)
local header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, pid, mid local header, parameters, data
-       local parameters_offset, data_offset
-       local total_word_count, total_data_count, reserved1, parameter_count, parameter_offset, parameter_displacement, 
data_count, data_offset, data_displacement, setup_count, reserved2
+       local parameter_offset = 0
+       local parameter_size   = 0
+       local data_offset      = 0
+       local data_size        = 0
+       local total_word_count, total_data_count, reserved1, parameter_count, parameter_displacement, data_count, 
data_displacement, setup_count, reserved2
        local response = {}
if(pipe == nil) then
@@ -1994,34 +1999,52 @@
        header = smb_encode_header(smb, command_codes['SMB_COM_TRANSACTION']) -- 0x25 = SMB_COM_TRANSACTION
-- 0x20 for SMB header, 0x01 for parameters header, 0x20 for parameters length, 0x02 for data header, 0x07 for "\PIPE\"
-       parameters_offset = 0x20 + 0x01 + 0x20 + 0x02 + (#pipe + 1)
-       data_offset       = 0x20 + 0x01 + 0x20 + 0x02 + (#pipe + 1) + string.len(function_parameters)
+       if(function_parameters) then
+               parameter_offset = 0x20 + 0x01 + 0x20 + 0x02 + (#pipe + 1)
+               parameter_size = #function_parameters
+       end
+
+       if(function_data) then
+               data_offset       = 0x20 + 0x01 + 0x20 + 0x02 + (#pipe + 1) + parameter_size
+               data_size         = #function_data
+       end
-- Parameters are 0x20 bytes long. - parameters = bin.pack("<SSSSCCSISSSSSCCSS", - string.len(function_parameters), -- Total parameter count. - string.len(function_data), -- Total data count. - 0x000, -- Max parameter count.
-                                       0x400,                           -- Max data count.
+       parameters = bin.pack("<SSSSCCSISSSSS",
+ parameter_size, -- Total parameter count. + data_size, -- Total data count. + 0x0008, -- Max parameter count.
+                                       0x3984,                          -- Max data count.
                                        0x00,                            -- Max setup count.
                                        0x00,                            -- Reserved.
                                        0x0000,                          -- Flags (0x0000 = 2-way transaction, don't 
disconnect TIDs).
-                                       0x00000000,                      -- Timeout (0x00000000 = return immediately).
+                                       0x00001388,                      -- Timeout (0x00000000 = return immediately).
                                        0x0000,                          -- Reserved.
-                                       string.len(function_parameters), -- Parameter bytes.
-                                       parameters_offset,               -- Parameter offset.
-                                       string.len(function_data),       -- Data bytes.
-                                       data_offset,                     -- Data offset.
-                                       0x02,                            -- Number of 'setup' words (only ever seen 
'2').
-                                       0x00,                            -- Reserved.
-                                       0x0026,                          -- Function to call.
-                                       smb['fid']                       -- Handle to open file
-                               )
+                                       parameter_size,                  -- Parameter bytes.
+                                       parameter_offset,                -- Parameter offset.
+                                       data_size,                       -- Data bytes.
+                                       data_offset                      -- Data offset.
+       )
+
+       if(no_setup) then
+ parameters = parameters .. bin.pack("<CC", + 0x00, -- Number of 'setup' words (none)
+                                               0x00                             -- Reserved.
+                                       )
+       else
+               parameters = parameters .. bin.pack("<CCSS",
+                                               0x02,                            -- Number of 'setup' words
+                                               0x00,                            -- Reserved.
+                                               0x0026,                          -- Function to call.
+                                               smb['fid']                       -- Handle to open file
+                                       )
+       end
- -- \PIPE\ is 0x07 bytes long. - data = bin.pack("<z", pipe);
-       data = data .. function_parameters;
-       data = data .. function_data
+       data = bin.pack("<z", pipe)
+       data = data .. bin.pack("<I", 0) -- Padding
+
+       data = data .. (function_parameters or '')
+       data = data .. (function_data or '')
-- Send the transaction request
        stdnse.print_debug(2, "SMB: Sending SMB_COM_TRANSACTION")
@@ -2075,7 +2098,7 @@
 function send_transaction_waitnamedpipe(smb, priority, pipe)
local header1, header2, header3, header4, command, status, flags, flags2, pid_high, signature, unused, pid, mid local header, parameters, data
-       local parameters_offset, data_offset
+       local parameter_offset, data_offset
        local total_word_count, total_data_count, reserved1, parameter_count, parameter_offset, parameter_displacement, 
data_count, data_offset, data_displacement, setup_count, reserved2
        local response = {}
        local padding = ""
@@ -2643,15 +2666,6 @@
        -- Save the name
        details['name'] = share
- -- Ensure that the server returns the proper error message
-       status, result = share_host_returns_proper_error(host)
-       if(status == false) then
-               return false, result
-       end
-       if(status == true and result == false) then
-               return false, "Server doesn't return proper value for non-existent shares"
-       end
-
        -- Check if the current user can read the share
        stdnse.print_debug(1, "SMB: Checking if share %s can be read by the current user", share)
        status, result = share_user_can_read(host, share)
@@ -2702,7 +2716,7 @@
        else
                -- Process the result a bit
                result = result['info']
-               if(result['max_users'] == 4294967295) then
+               if(result['max_users'] == 0xFFFFFFFF) then
                        result['max_users'] = "<unlimited>"
                end
                details['details'] = result
@@ -2723,6 +2737,7 @@
-- detail as we could get. If extra isn't nil, it is set to extra information that should be displayed (such as a warning). function share_get_list(host) + local status, result
        local enum_status
        local extra = ""
        local shares = {}
@@ -2753,6 +2768,15 @@
        -- Sort the shares
        table.sort(shares)
+ -- Ensure that the server returns the proper error message
+       status, result = share_host_returns_proper_error(host)
+       if(status == false) then
+               return false, result
+       end
+       if(status == true and result == false) then
+               return false, "Server doesn't return proper value for non-existent shares; can't enumerate shares"
+       end
+
        -- Get more information on each share
        for i = 1, #shares, 1 do
                local status, result

_______________________________________________
Sent through the nmap-svn mailing list
http://cgi.insecure.org/mailman/listinfo/nmap-svn
_______________________________________________
Sent through the nmap-dev mailing list
http://cgi.insecure.org/mailman/listinfo/nmap-dev
Archived at http://seclists.org/nmap-dev/


Current thread: