mirror of
https://github.com/nmap/nmap.git
synced 2026-01-03 05:09:14 +00:00
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.
This commit is contained in:
@@ -395,6 +395,65 @@ local function call_function(smbstate, opnum, arguments)
|
||||
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.
|
||||
|
||||
104
nselib/smb.lua
104
nselib/smb.lua
@@ -1972,18 +1972,23 @@ end
|
||||
-- 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 @@ function send_transaction_named_pipe(smb, function_parameters, function_data, pi
|
||||
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.
|
||||
)
|
||||
|
||||
-- \PIPE\ is 0x07 bytes long.
|
||||
data = bin.pack("<z", pipe);
|
||||
data = data .. function_parameters;
|
||||
data = data .. function_data
|
||||
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
|
||||
|
||||
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 @@ end
|
||||
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 @@ function share_get_details(host, share)
|
||||
-- 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 @@ function share_get_details(host, share)
|
||||
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 @@ end
|
||||
-- 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 @@ function share_get_list(host)
|
||||
-- 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
|
||||
|
||||
Reference in New Issue
Block a user