1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-06 12:41:29 +00:00

Replace bin.lua packing in msrpc libraries

This commit is contained in:
dmiller
2018-09-19 21:43:44 +00:00
parent 867e9b3fec
commit 00ec940ead
2 changed files with 210 additions and 196 deletions

View File

@@ -50,7 +50,6 @@
--@copyright Same as Nmap--See https://nmap.org/book/man-legal.html --@copyright Same as Nmap--See https://nmap.org/book/man-legal.html
----------------------------------------------------------------------- -----------------------------------------------------------------------
local bin = require "bin"
local datetime = require "datetime" local datetime = require "datetime"
local ipOps = require "ipOps" local ipOps = require "ipOps"
local math = require "math" local math = require "math"
@@ -245,7 +244,7 @@ function bind(smbstate, interface_uuid, interface_version, transfer_syntax)
transfer_syntax = TRANSFER_SYNTAX transfer_syntax = TRANSFER_SYNTAX
end end
data = bin.pack("<CCCC>I<SSISSICCCC", data = string.pack("<BBBB>I4<I2I2I4I2I2I4BxxxI2Bx",
0x05, -- Version (major) 0x05, -- Version (major)
0x00, -- Version (minor) 0x00, -- Version (minor)
0x0B, -- Packet type (0x0B = bind) 0x0B, -- Packet type (0x0B = bind)
@@ -258,19 +257,14 @@ function bind(smbstate, interface_uuid, interface_version, transfer_syntax)
MAX_FRAGMENT, -- Max receive frag MAX_FRAGMENT, -- Max receive frag
0x00000000, -- Assoc group 0x00000000, -- Assoc group
0x01, -- Number of items 0x01, -- Number of items
0x00, -- Padding/alignment
0x00, -- Padding/alignment
0x00 -- Padding/alignment
) .. bin.pack("<SCCASSAI",
0x0000, -- Context ID 0x0000, -- Context ID
0x01, -- Number of transaction items. */ 0x01) -- Number of transaction items. */
0x00, -- Padding/alignment .. interface_uuid -- Interface (eg. SRVSVC UUID: 4b324fc8-1670-01d3-1278-5a47bf6ee188)
interface_uuid, -- Interface (eg. SRVSVC UUID: 4b324fc8-1670-01d3-1278-5a47bf6ee188) .. string.pack("<I2I2",
interface_version, -- Interface version (major) interface_version, -- Interface version (major)
0x0000, -- Interface version (minor) 0x0000) -- Interface version (minor)
transfer_syntax, -- Transfer syntax .. transfer_syntax -- Transfer syntax
2 -- Syntax version .. string.pack("<I4", 2) -- Syntax version
)
status, result = smb.write_file(smbstate, data, 0) status, result = smb.write_file(smbstate, data, 0)
if(status ~= true) then if(status ~= true) then
@@ -289,10 +283,13 @@ function bind(smbstate, interface_uuid, interface_version, transfer_syntax)
data = result['data'] data = result['data']
-- Extract the first part from the response -- Extract the first part from the response
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) local fmt = "<BBBB>I4<I2I2I4"
if(result['call_id'] == nil) then if #data < string.packsize(fmt) then
return false, "MSRPC: ERROR: Ran off the end of SMB packet; likely due to server truncation" return false, "MSRPC: ERROR: Ran off the end of SMB packet; likely due to server truncation"
end end
result.version_major, result.version_minor, result.packet_type, result.packet_flags,
result.data_representation, result.frag_length, result.auth_length,
result.call_id, pos = string.unpack(fmt, data)
-- Check if the packet type was a fault -- Check if the packet type was a fault
if(result['packet_type'] == 0x03) then -- MSRPC_FAULT if(result['packet_type'] == 0x03) then -- MSRPC_FAULT
@@ -320,23 +317,22 @@ function bind(smbstate, interface_uuid, interface_version, transfer_syntax)
end end
-- If we made it this far, then we have a valid Bind() result. Pull out some more parameters. -- If we made it this far, then we have a valid Bind() result. Pull out some more parameters.
pos, result['max_transmit_frag'], result['max_receive_frag'], result['assoc_group'], result['secondary_address_length'] = bin.unpack("<SSIS", data, pos) local fmt = "<I2I2I4I2"
if(result['secondary_address_length'] == nil) then if #data - pos + 1 < string.packsize(fmt) then
return false, "MSRPC: ERROR: Ran off the end of SMB packet; likely due to server truncation" return false, "MSRPC: ERROR: Ran off the end of SMB packet; likely due to server truncation"
end end
result.max_transmit_frag, result.max_receive_frag, result.assoc_group,
result.secondary_address_length, pos = string.unpack(fmt, data, pos)
-- Read the secondary address -- Read the secondary address
pos, result['secondary_address'] = bin.unpack(string.format("<A%d", result['secondary_address_length']), data, pos) if #data - pos + 1 < result.secondary_address_length + 1 then -- +1 to account for num_results below
if(result['secondary_address'] == nil) then
return false, "MSRPC: ERROR: Ran off the end of SMB packet; likely due to server truncation" return false, "MSRPC: ERROR: Ran off the end of SMB packet; likely due to server truncation"
end end
result.secondary_address, pos = string.unpack(("<c%d"):format(result.secondary_address_length), data, pos)
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 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
-- Read the number of results -- Read the number of results
pos, result['num_results'] = bin.unpack("<C", data, pos) result.num_results, pos = string.unpack("<B", data, pos)
if(result['num_results'] == nil) then
return false, "MSRPC: ERROR: Ran off the end of SMB packet; likely due to server truncation"
end
pos = pos + ((4 - ((pos - 1) % 4)) % 4); -- Alignment pos = pos + ((4 - ((pos - 1) % 4)) % 4); -- Alignment
-- Verify we got back what we expected -- Verify we got back what we expected
@@ -345,10 +341,11 @@ function bind(smbstate, interface_uuid, interface_version, transfer_syntax)
end end
-- Read in the last bits -- Read in the last bits
pos, result['ack_result'], result['align'], result['transfer_syntax'], result['syntax_version'] = bin.unpack("<SSA16I", data, pos) local fmt = "<I2I2c16I4"
if(result['syntax_version'] == nil) then if #data - pos + 1 < string.packsize(fmt) then
return false, "MSRPC: ERROR: Ran off the end of SMB packet; likely due to server truncation" return false, "MSRPC: ERROR: Ran off the end of SMB packet; likely due to server truncation"
end end
result.ack_result, result.align, result.transfer_syntax, result.syntax_version, pos = string.unpack(fmt, data, pos)
return true, result return true, result
end end
@@ -388,7 +385,7 @@ function call_function(smbstate, opnum, arguments)
local first = true local first = true
local is_first, is_last local is_first, is_last
data = bin.pack("<CCCC>I<SSIISSA", data = string.pack("<BBBB>I4<I2I2I4I4I2I2",
0x05, -- Version (major) 0x05, -- Version (major)
0x00, -- Version (minor) 0x00, -- Version (minor)
0x00, -- Packet type (0x00 = request) 0x00, -- Packet type (0x00 = request)
@@ -399,9 +396,8 @@ function call_function(smbstate, opnum, arguments)
0x41414141, -- Call ID (I use 'AAAA' because it's easy to recognize) 0x41414141, -- Call ID (I use 'AAAA' because it's easy to recognize)
#arguments, -- Alloc hint #arguments, -- Alloc hint
0x0000, -- Context ID 0x0000, -- Context ID
opnum, -- Opnum opnum) -- Opnum
arguments .. arguments
)
stdnse.debug3("MSRPC: Calling function 0x%02x with %d bytes of arguments", opnum, #arguments) stdnse.debug3("MSRPC: Calling function 0x%02x with %d bytes of arguments", opnum, #arguments)
@@ -425,10 +421,13 @@ function call_function(smbstate, opnum, arguments)
data = result['data'] data = result['data']
-- Extract the first part from the response -- Extract the first part from the response
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) local fmt = "<BBBB>I4<I2I2I4"
if(result['call_id'] == nil) then if #data < string.packsize(fmt) then
return false, "MSRPC: ERROR: Ran off the end of SMB packet; likely due to server truncation" return false, "MSRPC: ERROR: Ran off the end of SMB packet; likely due to server truncation"
end end
result.version_major, result.version_minor, result.packet_type,
result.packet_flags, result.data_representation, result.frag_length,
result.auth_length, result.call_id, pos = string.unpack(fmt, data)
-- Check if we're fragmented -- Check if we're fragmented
is_first = ((result['packet_flags'] & 0x01) == 0x01) is_first = ((result['packet_flags'] & 0x01) == 0x01)
@@ -462,10 +461,11 @@ function call_function(smbstate, opnum, arguments)
end end
-- Extract some more -- Extract some more
pos, result['alloc_hint'], result['context_id'], result['cancel_count'], align = bin.unpack("<ISCC", data, pos) local fmt = "<I4I2BB"
if(align == nil) then if #data - pos + 1 < string.packsize(fmt) then
return false, "MSRPC: ERROR: Ran off the end of SMB packet; likely due to server truncation" return false, "MSRPC: ERROR: Ran off the end of SMB packet; likely due to server truncation"
end end
result.alloc_hint, result.context_id, result.cancel_count, align, pos = string.unpack(fmt, data, pos)
-- Rest is the arguments -- Rest is the arguments
arguments = arguments .. string.sub(data, pos) arguments = arguments .. string.sub(data, pos)
@@ -487,12 +487,11 @@ function call_lanmanapi(smbstate, opnum, paramdesc, datadesc, data)
local parameters = "" local parameters = ""
local pos local pos
parameters = bin.pack("<SzzA", parameters = string.pack("<I2zz",
opnum, opnum,
paramdesc, -- Parameter Descriptor paramdesc, -- Parameter Descriptor
datadesc, -- Return Descriptor datadesc) -- Return Descriptor
data .. data
)
stdnse.debug1("MSRPC: Sending Browser Service request") stdnse.debug1("MSRPC: Sending Browser Service request")
status, result = smb.send_transaction_named_pipe(smbstate, parameters, nil, "\\PIPE\\LANMAN", true) status, result = smb.send_transaction_named_pipe(smbstate, parameters, nil, "\\PIPE\\LANMAN", true)
@@ -516,11 +515,10 @@ function rap_netserverenum2(smbstate, domain, server_type, detail_level)
local paramdesc = (domain and "WrLehDz" or "WrLehDO") local paramdesc = (domain and "WrLehDz" or "WrLehDO")
assert( detail_level > 0 and detail_level < 2, "detail_level must be either 0 or 1") assert( detail_level > 0 and detail_level < 2, "detail_level must be either 0 or 1")
local datadesc = ( detail_level == 0 and "B16" or "B16BBDz") local datadesc = ( detail_level == 0 and "B16" or "B16BBDz")
local data = bin.pack("<SSIA", detail_level, local data = string.pack("<I2I2I4", detail_level,
14724, 14724,
server_type, server_type)
(domain or "") .. (domain or "")
)
local status, result = call_lanmanapi(smbstate, NETSERVERENUM2, paramdesc, datadesc, data ) local status, result = call_lanmanapi(smbstate, NETSERVERENUM2, paramdesc, datadesc, data )
@@ -532,7 +530,7 @@ function rap_netserverenum2(smbstate, domain, server_type, detail_level)
local data = result.data local data = result.data
stdnse.debug1("MSRPC: Parsing Browser Service response") stdnse.debug1("MSRPC: Parsing Browser Service response")
local pos, status, convert, entry_count, available_entries = bin.unpack("<SSSS", parameters) local status, convert, entry_count, available_entries, pos = string.unpack("<I2I2I2I2", parameters)
if(status ~= 0) then if(status ~= 0) then
return false, string.format("Call to Browser Service failed with status = %d", status) return false, string.format("Call to Browser Service failed with status = %d", status)
@@ -547,7 +545,7 @@ function rap_netserverenum2(smbstate, domain, server_type, detail_level)
for i = 1, entry_count, 1 do for i = 1, entry_count, 1 do
local server = {} local server = {}
pos, server.name = bin.unpack("<z", data, pos) server.name, pos = string.unpack("<z", data, pos)
stdnse.debug1("MSRPC: Found name: %s", server.name) stdnse.debug1("MSRPC: Found name: %s", server.name)
-- pos needs to be rounded to the next even multiple of 16 -- pos needs to be rounded to the next even multiple of 16
@@ -556,10 +554,10 @@ function rap_netserverenum2(smbstate, domain, server_type, detail_level)
if ( detail_level > 0 ) then if ( detail_level > 0 ) then
local comment_offset, _ local comment_offset, _
server.version = {} server.version = {}
pos, server.version.major, server.version.minor, server.version.major, server.version.minor,
server.type, comment_offset, _ = bin.unpack("<CCISS", data, pos) server.type, comment_offset, _, pos = string.unpack("<BBI4I2I2", data, pos)
_, server.comment = bin.unpack("<z", data, (comment_offset - convert + 1)) server.comment, pos = string.unpack("<z", data, (comment_offset - convert + 1))
end end
table.insert(entries, server) table.insert(entries, server)
end end
@@ -1157,8 +1155,9 @@ end
--@param uuid UUID byte string --@param uuid UUID byte string
--@return UUID converted to string representation --@return UUID converted to string representation
function uuid_to_string(uuid) function uuid_to_string(uuid)
local pos, i1,s1,s2,c1,c2,c3,c4,c5,c6,c7,c8 = bin.unpack("<ISSCCCCCCCC",uuid) -- Mixed-endian; first 3 parts are little-endian, next 2 are big-endian
return string.format("%02x-%02x-%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",i1,s1,s2,c1,c2,c3,c4,c5,c6,c7,c8) local A, B, C, D, E = string.unpack("<I4I2I2>c2c6", uuid)
return ("%08x-%04x-%04x-%s-%s"):format(A, B, C, stdnse.tohex(D), stdnse.tohex(E))
end end
--- Helper function that maps known UUIDs to corresponding exe/services. --- Helper function that maps known UUIDs to corresponding exe/services.
@@ -1234,7 +1233,7 @@ function epmapper_lookup(smbstate,handle)
-- stdnse.debug1("new_handle: %s", stdnse.tohex(new_handle)) -- stdnse.debug1("new_handle: %s", stdnse.tohex(new_handle))
local num_entries local num_entries
pos, num_entries = bin.unpack("<I",data,45) num_entries, pos = string.unpack("<I4", data, 45)
if num_entries == 0 then if num_entries == 0 then
return false, "finished" return false, "finished"
end end
@@ -1244,7 +1243,7 @@ function epmapper_lookup(smbstate,handle)
pos = pos + 16 pos = pos + 16
pos = pos + 8 pos = pos + 8
local annotation_length local annotation_length
pos,annotation_length = bin.unpack("<I",data,pos) annotation_length, pos = string.unpack("<I4", data, pos)
if annotation_length > 1 then if annotation_length > 1 then
lookup_response.annotation = string.sub(data,pos,pos+annotation_length-2) lookup_response.annotation = string.sub(data,pos,pos+annotation_length-2)
end end
@@ -1254,11 +1253,11 @@ function epmapper_lookup(smbstate,handle)
--skip lengths --skip lengths
pos = pos + 8 pos = pos + 8
local num_floors,floor_len,uuid, address_type,address_len,tcp_port,udp_port,ip_addr,saved_pos,ncalrpc,ncacn_np,netbios,ncacn_http local num_floors,floor_len,uuid, address_type,address_len,tcp_port,udp_port,ip_addr,saved_pos,ncalrpc,ncacn_np,netbios,ncacn_http
pos, num_floors = bin.unpack("<S",data,pos) num_floors, pos = string.unpack("<I2", data, pos)
for i = 1, num_floors do for i = 1, num_floors do
saved_pos = pos saved_pos = pos
pos, floor_len = bin.unpack("<S",data,pos) floor_len, pos = string.unpack("<I2", data, pos)
if i == 1 then if i == 1 then
uuid = string.sub(data,pos+1,pos+16) uuid = string.sub(data,pos+1,pos+16)
@@ -1266,11 +1265,11 @@ function epmapper_lookup(smbstate,handle)
lookup_response.exe = string_uuid_to_exe(lookup_response.uuid) lookup_response.exe = string_uuid_to_exe(lookup_response.uuid)
else else
if not (i == 2) and not (i == 3) then -- just skip floor 2 and 3 if not (i == 2) and not (i == 3) then -- just skip floor 2 and 3
pos,address_type,address_len = bin.unpack("<CS",data,pos) address_type, address_len, pos = string.unpack("<BI2", data, pos)
if address_type == 0x07 then if address_type == 0x07 then
pos,lookup_response.tcp_port = bin.unpack(">S",data,pos) lookup_response.tcp_port, pos = string.unpack(">I2", data, pos)
elseif address_type == 0x08 then elseif address_type == 0x08 then
pos,lookup_response.udp_port = bin.unpack(">S",data,pos) lookup_response.udp_port, pos = string.unpack(">I2", data, pos)
elseif address_type == 0x09 then elseif address_type == 0x09 then
local ip local ip
ip, pos = string.unpack("c4", data, pos) ip, pos = string.unpack("c4", data, pos)
@@ -1285,7 +1284,7 @@ function epmapper_lookup(smbstate,handle)
lookup_response.netbios = string.sub(data,pos,pos+address_len-2) lookup_response.netbios = string.sub(data,pos,pos+address_len-2)
floor_len = floor_len + address_len - 2 floor_len = floor_len + address_len - 2
elseif address_type == 0x1f then elseif address_type == 0x1f then
pos, lookup_response.ncacn_http = bin.unpack(">S",data,pos) lookup_response.ncacn_http, pos = string.unpack(">I2", data, pos)
else else
stdnse.debug1("unknown address type %x",address_type) stdnse.debug1("unknown address type %x",address_type)
end end
@@ -2844,7 +2843,7 @@ function winreg_queryvalue(smbstate, handle, value)
if(result['data'] ~= nil) then if(result['data'] ~= nil) then
local _ local _
if(result['type'] == "REG_DWORD") then if(result['type'] == "REG_DWORD") then
_, result['value'] = bin.unpack("<I", result['data']) result['value'] = string.unpack("<I4", result['data'])
elseif(result['type'] == "REG_SZ" or result['type'] == "REG_MULTI_SZ" or result['type'] == "REG_EXPAND_SZ") then elseif(result['type'] == "REG_SZ" or result['type'] == "REG_MULTI_SZ" or result['type'] == "REG_EXPAND_SZ") then
_, result['value'] = msrpctypes.unicode_to_string(result['data'], 1, #result['data'] / 2) _, result['value'] = msrpctypes.unicode_to_string(result['data'], 1, #result['data'] / 2)
elseif(result['type'] == "REG_BINARY") then elseif(result['type'] == "REG_BINARY") then
@@ -5057,13 +5056,13 @@ function RRAS_marshall_RequestBuffer(RB_PCBIndex, RB_ReqType, RB_Buffer)
RB_Dummy = 4 RB_Dummy = 4
RB_Done = 0 RB_Done = 0
Alignment = 0 Alignment = 0
rb_blob = bin.pack("<IIIILA", rb_blob = string.pack("<I4I4I4I4I8",
RB_PCBIndex, RB_PCBIndex,
RB_ReqType, RB_ReqType,
RB_Dummy, RB_Dummy,
RB_Done, RB_Done,
Alignment, Alignment)
RB_Buffer) .. RB_Buffer
return rb_blob return rb_blob
end end
@@ -5114,7 +5113,7 @@ function RRAS_SubmitRequest(smbstate, pReqBuffer, dwcbBufSize)
--pack the request --pack the request
local req_blob local req_blob
--[in, out, unique, size_is(dwcbBufSize) PBYTE pReqBuffer, --[in, out, unique, size_is(dwcbBufSize) PBYTE pReqBuffer,
req_blob = bin.pack("<IIAA", 0x20000, dwcbBufSize, pReqBuffer, get_pad(pReqBuffer,4)) --unique pointer see samba:ndr_push_unique_ptr req_blob = string.pack("<I4I4", 0x20000, dwcbBufSize) .. pReqBuffer .. get_pad(pReqBuffer,4) --unique pointer see samba:ndr_push_unique_ptr
--[in] DWORD dwcbBufSize --[in] DWORD dwcbBufSize
.. msrpctypes.marshall_int32(dwcbBufSize) .. msrpctypes.marshall_int32(dwcbBufSize)
--call the function --call the function
@@ -5226,35 +5225,35 @@ function DNSSERVER_Query(smbstate, server_name, zone, operation)
local unique_ptr local unique_ptr
unique_ptr = 0x00020000 unique_ptr = 0x00020000
srv_name_utf16 = msrpctypes.string_to_unicode(server_name, true) srv_name_utf16 = msrpctypes.string_to_unicode(server_name, true)
req_blob = bin.pack("<IIIIAA", req_blob = string.pack("<I4I4I4I4",
unique_ptr, unique_ptr,
#srv_name_utf16/2, #srv_name_utf16/2,
0, 0,
#srv_name_utf16/2, #srv_name_utf16/2)
srv_name_utf16, .. srv_name_utf16
get_pad(srv_name_utf16, 4)) .. get_pad(srv_name_utf16, 4)
--[in, unique, string] LPCSTR pszZone, --[in, unique, string] LPCSTR pszZone,
if(zone == nil) then if(zone == nil) then
req_blob = bin.pack("<I", 0x00000000) req_blob = string.pack("<I4", 0x00000000)
else else
zone_ascii = zone .. '\0' zone_ascii = zone .. '\0'
req_blob = req_blob .. bin.pack("<IIIIAA", req_blob = req_blob .. string.pack("<I4I4I4I4",
unique_ptr + 1, unique_ptr + 1,
#zone_ascii, #zone_ascii,
0, 0,
#zone_ascii, #zone_ascii)
zone_ascii, .. zone_ascii
get_pad(zone_ascii, 4)) .. get_pad(zone_ascii, 4)
end end
--[in, unique, string] LPCSTR pszOperation, --[in, unique, string] LPCSTR pszOperation,
operation_ascii = operation .. '\0' operation_ascii = operation .. '\0'
req_blob = req_blob .. bin.pack("<IIIIAA", req_blob = req_blob .. string.pack("<I4I4I4I4",
unique_ptr+2, unique_ptr+2,
#operation_ascii, #operation_ascii,
0, 0,
#operation_ascii, #operation_ascii)
operation_ascii, .. operation_ascii
get_pad(operation_ascii, 4)) .. get_pad(operation_ascii, 4)
local call_result local call_result
stdnse.debug( stdnse.debug(
@@ -5282,7 +5281,10 @@ function DNSSERVER_Query(smbstate, server_name, zone, operation)
result = {} result = {}
pos, result['type_id'] = msrpctypes.unmarshall_int32_ptr(rep_blob) pos, result['type_id'] = msrpctypes.unmarshall_int32_ptr(rep_blob)
--[out, switch_is(*pdwTypeId)] DNSSRV_RPC_UNION* ppData) -- pointer_default(unique) --[out, switch_is(*pdwTypeId)] DNSSRV_RPC_UNION* ppData) -- pointer_default(unique)
pos, ptr, result['data']= bin.unpack("<IA", rep_blob, pos) -- TODO: The original used the 'A' format to unpack a single byte, which I
-- replaced with the literal equivalent 'B'. Should it have been a substring
-- to the end of the blob instead?
ptr, result['data'], pos = string.unpack("<I4B", rep_blob, pos)
return result return result
end end

View File

@@ -103,7 +103,6 @@
-- * SIDs will be converted to user-readable strings in the standard format (S-x-y-...) -- * SIDs will be converted to user-readable strings in the standard format (S-x-y-...)
-- * GUIDs are stored as tables of values; however, I might change this to a string representation at some point -- * GUIDs are stored as tables of values; however, I might change this to a string representation at some point
local bin = require "bin"
local os = require "os" local os = require "os"
local stdnse = require "stdnse" local stdnse = require "stdnse"
local string = require "string" local string = require "string"
@@ -163,14 +162,15 @@ function string_to_unicode(string, do_null)
return result return result
end end
--- Read a unicode string from a buffer, similar to how <code>bin.unpack</code> would, optionally eat the null terminator, --- Read a unicode string from a buffer, optionally eat the null terminator,
-- and optionally align it to 4-byte boundaries. -- and optionally align it to 4-byte boundaries.
-- --
--@param buffer The buffer to read from, typically the full 'arguments' value for MSRPC --@param buffer The buffer to read from, typically the full 'arguments' value for MSRPC
--@param pos The position in the buffer to start (just like <code>bin.unpack</code>) --@param pos The position in the buffer to start
--@param length The number of ascii characters that will be read (including the null, if do_null is set). --@param length The number of ascii characters that will be read (including the null, if do_null is set).
--@param do_null [optional] Remove a null terminator from the string as the last character. Default false. --@param do_null [optional] Remove a null terminator from the string as the last character. Default false.
--@return (pos, string) The new position and the string read, again imitating <code>bin.unpack</code>. If there was an --@return pos The new position
--@return string The string read. If there was an
-- attempt to read off the end of the string, then 'nil' is returned for both parameters. -- attempt to read off the end of the string, then 'nil' is returned for both parameters.
function unicode_to_string(buffer, pos, length, do_null) function unicode_to_string(buffer, pos, length, do_null)
stdnse.debug4("MSRPC: Entering unicode_to_string(pos = %d, length = %d)", pos, length) stdnse.debug4("MSRPC: Entering unicode_to_string(pos = %d, length = %d)", pos, length)
@@ -250,9 +250,9 @@ local function marshall_ptr(location, func, args, value)
-- If we're marshalling the HEAD section, add a REFERENT_ID. -- If we're marshalling the HEAD section, add a REFERENT_ID.
if(location == HEAD or location == ALL) then if(location == HEAD or location == ALL) then
if(func == nil or args == nil or value == nil) then if(func == nil or args == nil or value == nil) then
result = result .. bin.pack("<I", 0) result = result .. string.pack("<I4", 0)
else else
result = result .. bin.pack("<I", REFERENT_ID) result = result .. string.pack("<I4", REFERENT_ID)
end end
end end
@@ -312,11 +312,12 @@ local function unmarshall_ptr(location, data, pos, func, args, result)
end end
-- If we're unmarshalling the header, then pull off a referent_id. -- If we're unmarshalling the header, then pull off a referent_id.
if(location == HEAD or location == ALL) then if(location == HEAD or location == ALL) then
local referent_id if #data - pos + 1 < 4 then
pos, referent_id = bin.unpack("<I", data, pos)
if(referent_id == nil) then
stdnse.debug1("MSRPC: ERROR: Ran off the end of a packet in unmarshall_ptr(). Please report!") stdnse.debug1("MSRPC: ERROR: Ran off the end of a packet in unmarshall_ptr(). Please report!")
return pos, nil
end end
local referent_id
referent_id, pos = string.unpack("<I4", data, pos)
if(location == HEAD) then if(location == HEAD) then
if(referent_id == 0) then if(referent_id == 0) then
@@ -404,22 +405,20 @@ end
-- marshalling function after the 'location' variable. -- marshalling function after the 'location' variable.
--@return A string representing the marshalled data. --@return A string representing the marshalled data.
function marshall_array(array) function marshall_array(array)
local i
local result = ""
stdnse.debug4("MSRPC: Entering marshall_array()") stdnse.debug4("MSRPC: Entering marshall_array()")
-- The max count is always at the front of the array (at least, in my tests). It is possible that -- The max count is always at the front of the array (at least, in my tests). It is possible that
-- this won't always hold true, so if you're having an issue that you've traced back to this function, -- this won't always hold true, so if you're having an issue that you've traced back to this function,
-- you might want to double-check my assumption. -- you might want to double-check my assumption.
result = result .. bin.pack("<I", #array) local result = {string.pack("<I4", #array)}
-- Encode the HEAD sections of all the elements in the array -- Encode the HEAD sections of all the elements in the array
for i = 1, #array, 1 do for i = 1, #array, 1 do
local func = array[i]['func'] local func = array[i]['func']
local args = array[i]['args'] local args = array[i]['args']
result = result .. func(HEAD, table.unpack(args)) result[#result+1] = func(HEAD, table.unpack(args))
end end
-- Encode the BODY sections of all the elements in the array -- Encode the BODY sections of all the elements in the array
@@ -427,11 +426,11 @@ function marshall_array(array)
local func = array[i]['func'] local func = array[i]['func']
local args = array[i]['args'] local args = array[i]['args']
result = result .. func(BODY, table.unpack(args)) result[#result+1] = func(BODY, table.unpack(args))
end end
stdnse.debug4("MSRPC: Leaving marshall_array()") stdnse.debug4("MSRPC: Leaving marshall_array()")
return result return table.concat(result)
end end
---Unmarshalls an array. ---Unmarshalls an array.
@@ -463,20 +462,19 @@ end
--@return The new position --@return The new position
--@return The result of unmarshalling this value. --@return The result of unmarshalling this value.
local function unmarshall_array(data, pos, count, func, args) local function unmarshall_array(data, pos, count, func, args)
local i
local size
local result = {}
stdnse.debug4("MSRPC: Entering unmarshall_array()") stdnse.debug4("MSRPC: Entering unmarshall_array()")
if(args == nil) then if(args == nil) then
args = {} args = {}
end end
local pos, max_count = bin.unpack("<I", data, pos) if #data - pos + 1 < 4 then
if(max_count == nil) then
stdnse.debug1("MSRPC: ERROR: Ran off the end of a packet in unmarshall_array(). Please report!") stdnse.debug1("MSRPC: ERROR: Ran off the end of a packet in unmarshall_array(). Please report!")
return pos, nil
end end
local max_count, pos = string.unpack("<I4", data, pos)
local result = {}
-- Unmarshall the header, which will be referent_ids and base types. -- Unmarshall the header, which will be referent_ids and base types.
for i = 1, count, 1 do for i = 1, count, 1 do
@@ -568,12 +566,11 @@ function marshall_unicode(str, do_null, max_length)
max_length = buffer_length max_length = buffer_length
end end
result = bin.pack("<IIIA", result = string.pack("<I4I4I4",
max_length, -- Max count max_length, -- Max count
0, -- Offset 0, -- Offset
buffer_length, -- Actual count buffer_length) -- Actual count
string_to_unicode(str, do_null, true) .. string_to_unicode(str, do_null, true)
)
stdnse.debug4("MSRPC: Leaving marshall_unicode()") stdnse.debug4("MSRPC: Leaving marshall_unicode()")
@@ -597,13 +594,12 @@ function marshall_ascii(str, max_length)
local padding = string.rep('\0', (4 - (buffer_length % 4)) % 4) local padding = string.rep('\0', (4 - (buffer_length % 4)) % 4)
result = bin.pack("<IIIzA", result = string.pack("<I4I4I4z",
max_length, max_length,
0, 0,
buffer_length, buffer_length,
str, str)
padding .. padding
)
return result return result
end end
@@ -660,10 +656,11 @@ function unmarshall_unicode(data, pos, do_null)
do_null = false do_null = false
end end
pos, max, offset, actual = bin.unpack("<III", data, pos) if #data - pos + 1 < 3*4 then
if(actual == nil) then
stdnse.debug1("MSRPC: ERROR: Ran off the end of a packet in unmarshall_unicode(). Please report!") stdnse.debug1("MSRPC: ERROR: Ran off the end of a packet in unmarshall_unicode(). Please report!")
return pos, nil
end end
max, offset, actual, pos = string.unpack("<I4I4I4", data, pos)
pos, str = unicode_to_string(data, pos, actual, do_null, true) pos, str = unicode_to_string(data, pos, actual, do_null, true)
@@ -730,7 +727,7 @@ function marshall_int64(int64)
local result local result
stdnse.debug4("MSRPC: Entering marshall_int64()") stdnse.debug4("MSRPC: Entering marshall_int64()")
result = bin.pack("<L", int64) result = string.pack("<I8", int64)
stdnse.debug4("MSRPC: Leaving marshall_int64()") stdnse.debug4("MSRPC: Leaving marshall_int64()")
return result return result
@@ -747,7 +744,7 @@ function marshall_int32(int32)
local result local result
stdnse.debug4("MSRPC: Entering marshall_int32()") stdnse.debug4("MSRPC: Entering marshall_int32()")
result = bin.pack("<I", int32) result = string.pack("<I4", int32)
stdnse.debug4("MSRPC: Leaving marshall_int32()") stdnse.debug4("MSRPC: Leaving marshall_int32()")
return result return result
@@ -758,17 +755,17 @@ end
--@param data The array --@param data The array
--@return A string representing the marshalled data --@return A string representing the marshalled data
function marshall_int32_array(data) function marshall_int32_array(data)
local result = "" local result = {
marshall_int32(0x0400), -- Max count
result = result .. marshall_int32(0x0400) -- Max count marshall_int32(0), -- Offset
result = result .. marshall_int32(0) -- Offset marshall_int32(#data), -- Actual count
result = result .. marshall_int32(#data) -- Actual count }
for _, v in ipairs(data) do for _, v in ipairs(data) do
result = result .. marshall_int32(v) result[#result+1] = marshall_int32(v)
end end
return result return table.concat(result)
end end
--- Marshall an int16 --- Marshall an int16
@@ -785,10 +782,10 @@ function marshall_int16(int16, pad)
stdnse.debug4("MSRPC: Entering marshall_int16()") stdnse.debug4("MSRPC: Entering marshall_int16()")
if(pad == false) then if(pad == false) then
return bin.pack("<S", int16) return string.pack("<I2", int16)
end end
result = bin.pack("<SS", int16, 0) result = string.pack("<I2xx", int16)
stdnse.debug4("MSRPC: Leaving marshall_int16()") stdnse.debug4("MSRPC: Leaving marshall_int16()")
@@ -810,10 +807,10 @@ function marshall_int8(int8, pad)
stdnse.debug4("MSRPC: Entering marshall_int8()") stdnse.debug4("MSRPC: Entering marshall_int8()")
if(pad == false) then if(pad == false) then
return bin.pack("<C", int8) return string.pack("<B", int8)
end end
result = bin.pack("<CCS", int8, 0, 0) result = string.pack("<Bxxx", int8)
stdnse.debug4("MSRPC: Leaving marshall_int8()") stdnse.debug4("MSRPC: Leaving marshall_int8()")
return result return result
@@ -828,10 +825,11 @@ function unmarshall_int64(data, pos)
local value local value
stdnse.debug4("MSRPC: Entering unmarshall_int64()") stdnse.debug4("MSRPC: Entering unmarshall_int64()")
pos, value = bin.unpack("<l", data, pos) if #data - pos + 1 < 8 then
if(value == nil) then
stdnse.debug1("MSRPC: ERROR: Ran off the end of a packet in unmarshall_int64(). Please report!") stdnse.debug1("MSRPC: ERROR: Ran off the end of a packet in unmarshall_int64(). Please report!")
return pos, nil
end end
value, pos = string.unpack("<i8", data, pos)
stdnse.debug4("MSRPC: Leaving unmarshall_int64()") stdnse.debug4("MSRPC: Leaving unmarshall_int64()")
return pos, value return pos, value
@@ -845,10 +843,11 @@ end
function unmarshall_int32(data, pos) function unmarshall_int32(data, pos)
local value local value
pos, value = bin.unpack("<I", data, pos) if #data - pos + 1 < 4 then
if(value == nil) then
stdnse.debug1("MSRPC: ERROR: Ran off the end of a packet in unmarshall_int32(). Please report!") stdnse.debug1("MSRPC: ERROR: Ran off the end of a packet in unmarshall_int32(). Please report!")
return pos, nil
end end
pos, value = string.unpack("<I4", data, pos)
return pos, value return pos, value
end end
@@ -864,10 +863,11 @@ function unmarshall_int16(data, pos, pad)
stdnse.debug4("MSRPC: Entering unmarshall_int16()") stdnse.debug4("MSRPC: Entering unmarshall_int16()")
pos, value = bin.unpack("<S", data, pos) if #data - pos + 1 < 2 then
if(value == nil) then
stdnse.debug1("MSRPC: ERROR: Ran off the end of a packet in unmarshall_int16(). Please report!") stdnse.debug1("MSRPC: ERROR: Ran off the end of a packet in unmarshall_int16(). Please report!")
return pos, nil
end end
value, pos = string.unpack("<I2", data, pos)
if(pad == nil or pad == true) then if(pad == nil or pad == true) then
pos = pos + 2 pos = pos + 2
@@ -889,10 +889,11 @@ function unmarshall_int8(data, pos, pad)
stdnse.debug4("MSRPC: Entering unmarshall_int8()") stdnse.debug4("MSRPC: Entering unmarshall_int8()")
pos, value = bin.unpack("<C", data, pos) if #data - pos + 1 < 1 then
if(value == nil) then
stdnse.debug1("MSRPC: ERROR: Ran off the end of a packet in unmarshall_int8(). Please report!") stdnse.debug1("MSRPC: ERROR: Ran off the end of a packet in unmarshall_int8(). Please report!")
return pos, nil
end end
value, pos = string.unpack("<B", data, pos)
if(pad == nil or pad == true) then if(pad == nil or pad == true) then
pos = pos + 3 pos = pos + 3
@@ -1039,7 +1040,7 @@ function marshall_int8_array(data, max_length)
max_length = #data max_length = #data
end end
local result = bin.pack("<IIa", max_length, 0, data) local result = string.pack("<I4I4", max_length, 0) .. data
stdnse.debug4("MSRPC: Leaving marshall_int8_array()") stdnse.debug4("MSRPC: Leaving marshall_int8_array()")
@@ -1059,15 +1060,17 @@ function unmarshall_int8_array(data, pos, pad)
stdnse.debug4("MSRPC: Entering unmarshall_int8_array()") stdnse.debug4("MSRPC: Entering unmarshall_int8_array()")
pos, max, offset, actual = bin.unpack("<III", data, pos) if #data - pos + 1 < 3*4 then
if(actual == nil) then
stdnse.debug1("MSRPC: ERROR: Ran off the end of a packet in unmarshall_int8_array(). Please report!") stdnse.debug1("MSRPC: ERROR: Ran off the end of a packet in unmarshall_int8_array(). Please report!")
return pos, nil
end end
max, offset, actual, pos = string.unpack("<I4I4I4", data, pos)
pos, str = bin.unpack("<A"..actual, data, pos) if #data - pos + 1 < actual then
if(str == nil) then
stdnse.debug1("MSRPC: ERROR: Ran off the end of a packet in unmarshall_int8_array() [2]. Please report!") stdnse.debug1("MSRPC: ERROR: Ran off the end of a packet in unmarshall_int8_array() [2]. Please report!")
return pos - 3*4, nil
end end
str, pos = string.unpack("<c"..actual, data, pos)
-- Do the alignment (note the "- 1", it's there because of 1-based arrays) -- Do the alignment (note the "- 1", it's there because of 1-based arrays)
if(pad == nil or pad == true) then if(pad == nil or pad == true) then
@@ -1161,9 +1164,9 @@ function marshall_NTTIME(time)
stdnse.debug4("MSRPC: Entering marshall_NTTIME()") stdnse.debug4("MSRPC: Entering marshall_NTTIME()")
if(time == 0) then if(time == 0) then
result = bin.pack("<L", 0) result = string.pack("<I8", 0)
else else
result = bin.pack("<L", (time + 11644473600) * 10000000) result = string.pack("<I8", (time + 11644473600) * 10000000)
end end
stdnse.debug4("MSRPC: Leaving marshall_NTTIME()") stdnse.debug4("MSRPC: Leaving marshall_NTTIME()")
@@ -1179,10 +1182,11 @@ function unmarshall_NTTIME(data, pos)
local time local time
stdnse.debug4("MSRPC: Entering unmarshall_NTTIME()") stdnse.debug4("MSRPC: Entering unmarshall_NTTIME()")
pos, time = bin.unpack("<L", data, pos) if #data - pos + 1 < 8 then
if(time == nil) then
stdnse.debug1("MSRPC: ERROR: Ran off the end of a packet in unmarshall_NTTIME(). Please report!") stdnse.debug1("MSRPC: ERROR: Ran off the end of a packet in unmarshall_NTTIME(). Please report!")
return pos, nil
end end
time, pos = string.unpack("<I8", data, pos)
if(time ~= 0) then if(time ~= 0) then
time = (time // 10000000) - 11644473600 time = (time // 10000000) - 11644473600
@@ -1242,13 +1246,15 @@ end
--@param pos The position within the data. --@param pos The position within the data.
--@return (pos, time) The new position, and the time in seconds since 1970. --@return (pos, time) The new position, and the time in seconds since 1970.
function unmarshall_SYSTEMTIME(data, pos) function unmarshall_SYSTEMTIME(data, pos)
local date = {} local fmt = "<I2I2I2I2I2I2I2I2"
local _ if #data - pos + 1 < string.packsize(fmt) then
pos, date['year'], date['month'], _, date['day'], date['hour'], date['min'], date['sec'], _ = bin.unpack("<SSSSSSSS", data, pos)
if(date['sec'] == nil) then
stdnse.debug1("MSRPC: ERROR: Ran off the end of a packet in unmarshall_SYSTEMTIME(). Please report!") stdnse.debug1("MSRPC: ERROR: Ran off the end of a packet in unmarshall_SYSTEMTIME(). Please report!")
return pos, nil
end end
local date = {}
-- TODO: consider returning the date table instead, allowing the caller to see milliseconds.
date.year, date.month, date.dow, date.day, date.hour, date.min, date.sec, date.msec, pos = string.unpack(fmt, data, pos)
return pos, os.time(date) return pos, os.time(date)
end end
@@ -1424,10 +1430,11 @@ function unmarshall_raw(data, pos, length)
local val local val
stdnse.debug4("MSRPC: Entering unmarshall_raw()") stdnse.debug4("MSRPC: Entering unmarshall_raw()")
pos, val = bin.unpack(string.format("A%d", length), data, pos) if #data - pos + 1 < length then
if(val == nil) then
stdnse.debug1("MSRPC: ERROR: Ran off the end of a packet in unmarshall_raw(). Please report!") stdnse.debug1("MSRPC: ERROR: Ran off the end of a packet in unmarshall_raw(). Please report!")
return pos, nil
end end
val, pos = string.unpack(("c%d"):format(length), data, pos)
stdnse.debug4("MSRPC: Leaving unmarshall_raw()") stdnse.debug4("MSRPC: Leaving unmarshall_raw()")
return pos, val return pos, val
@@ -1457,7 +1464,7 @@ local function marshall_guid(guid)
local result local result
stdnse.debug4("MSRPC: Entering marshall_guid()") stdnse.debug4("MSRPC: Entering marshall_guid()")
result = bin.pack("<ISSAA", guid['time_low'], guid['time_high'], guid['time_hi_and_version'], guid['clock_seq'], guid['node']) result = string.pack("<I4I2I2", guid.time_low, guid.time_high, guid.time_hi_and_version) .. guid.clock_seq .. guid.node
stdnse.debug4("MSRPC: Leaving marshall_guid()") stdnse.debug4("MSRPC: Leaving marshall_guid()")
return result return result
@@ -1469,13 +1476,15 @@ end
--@param pos The position within the data. --@param pos The position within the data.
--@return (pos, result) The new position in <code>data</code>, and a table representing the datatype. --@return (pos, result) The new position in <code>data</code>, and a table representing the datatype.
local function unmarshall_guid(data, pos) local function unmarshall_guid(data, pos)
local guid = {} local fmt = "<I4I2I2c2c6"
stdnse.debug4("MSRPC: Entering unmarshall_guid()") stdnse.debug4("MSRPC: Entering unmarshall_guid()")
pos, guid['time_low'], guid['time_high'], guid['time_hi_and_version'], guid['clock_seq'], guid['node'] = bin.unpack("<ISSA2A6", data, pos) if #data - pos + 1 < string.packsize(fmt) then
if(guid['node'] == nil) then
stdnse.debug1("MSRPC: ERROR: Ran off the end of a packet in unmarshall_guid(). Please report!") stdnse.debug1("MSRPC: ERROR: Ran off the end of a packet in unmarshall_guid(). Please report!")
return pos, nil
end end
local guid = {}
guid.time_low, guid.time_high, guid.time_hi_and_version, guid.clock_seq, guid.node, pos = string.unpack(fmt, data, pos)
stdnse.debug4("MSRPC: Leaving unmarshall_guid()") stdnse.debug4("MSRPC: Leaving unmarshall_guid()")
return pos, guid return pos, guid
@@ -1496,7 +1505,7 @@ function marshall_policy_handle(policy_handle)
local result local result
stdnse.debug4("MSRPC: Entering marshall_policy_handle()") stdnse.debug4("MSRPC: Entering marshall_policy_handle()")
result = bin.pack("<IA", policy_handle['handle_type'], marshall_guid(policy_handle['uuid'])) result = string.pack("<I4", policy_handle.handle_type) .. marshall_guid(policy_handle.uuid)
stdnse.debug4("MSRPC: Leaving marshall_policy_handle()") stdnse.debug4("MSRPC: Leaving marshall_policy_handle()")
return result return result
@@ -1547,11 +1556,11 @@ function unmarshall_dom_sid2(data, pos)
pos, sid['num_auths'] = unmarshall_int8(data, pos, false) pos, sid['num_auths'] = unmarshall_int8(data, pos, false)
-- Note that authority is big endian (I guess it's an array, not really an integer like we're handling it) -- Note that authority is big endian (I guess it's an array, not really an integer like we're handling it)
pos, sid['authority_high'], sid['authority_low'] = bin.unpack(">SI", data, pos) if #data - pos + 1 < 6 then
if(sid['authority_low'] == nil) then
stdnse.debug1("MSRPC: ERROR: Ran off the end of a packet in unmarshall_dom_sid2(). Please report!") stdnse.debug1("MSRPC: ERROR: Ran off the end of a packet in unmarshall_dom_sid2(). Please report!")
return pos, nil
end end
sid['authority'] = (sid['authority_high'] << 32) | sid['authority_low'] sid.authority, pos = string.unpack(">I6", data, pos)
sid['sub_auths'] = {} sid['sub_auths'] = {}
for i = 1, sid['num_auths'], 1 do for i = 1, sid['num_auths'], 1 do
@@ -1609,12 +1618,11 @@ function marshall_dom_sid2(sid)
local pos = 3 local pos = 3
pos_next = string.find(sid, "-", pos) pos_next = string.find(sid, "-", pos)
sid_array['sid_rev_num'] = string.sub(sid, pos, pos_next - 1) sid_array.sid_rev_num = tonumber(string.sub(sid, pos, pos_next - 1))
pos = pos_next + 1 pos = pos_next + 1
pos_next = string.find(sid, "-", pos) pos_next = string.find(sid, "-", pos)
sid_array['authority_high'] = string.sub(sid, pos, pos_next - 1) >> 32 sid_array.authority_high = tonumber(string.sub(sid, pos, pos_next - 1))
sid_array['authority_low'] = string.sub(sid, pos, pos_next - 1) & 0xFFFFFFFF
sid_array['sub_auths'] = {} sid_array['sub_auths'] = {}
i = 1 i = 1
@@ -1622,22 +1630,25 @@ function marshall_dom_sid2(sid)
pos = pos_next + 1 pos = pos_next + 1
pos_next = string.find(sid, "-", pos) pos_next = string.find(sid, "-", pos)
if(pos_next == nil) then if(pos_next == nil) then
sid_array['sub_auths'][i] = string.sub(sid, pos) sid_array['sub_auths'][i] = tonumber(string.sub(sid, pos))
else else
sid_array['sub_auths'][i] = string.sub(sid, pos, pos_next - 1) sid_array['sub_auths'][i] = tonumber(string.sub(sid, pos, pos_next - 1))
end end
i = i + 1 i = i + 1
until pos_next == nil until pos_next == nil
sid_array['num_auths'] = i - 1 sid_array['num_auths'] = i - 1
result = bin.pack("<I", sid_array['num_auths']) result = {
result = result .. bin.pack("<CC>SI", sid_array['sid_rev_num'], sid_array['num_auths'], sid_array['authority_high'], sid_array['authority_low']) -- TODO: Is the first 32-bit integer here supposed to be num_auths, or some
-- other count value?
string.pack("<I4BB>I6", sid_array.num_auths, sid_array.sid_rev_num, sid_array.num_auths, sid_array.authority),
}
for i = 1, sid_array['num_auths'], 1 do for i = 1, sid_array['num_auths'], 1 do
result = result .. bin.pack("<I", sid_array['sub_auths'][i]) result[#result+1] = string.pack("<I4", sid_array['sub_auths'][i])
end end
stdnse.debug4("MSRPC: Leaving marshall_dom_sid2()") stdnse.debug4("MSRPC: Leaving marshall_dom_sid2()")
return result return table.concat(result)
end end
@@ -1697,7 +1708,7 @@ local function marshall_lsa_String_internal(location, str, max_length, do_null)
end end
if(location == HEAD or location == ALL) then if(location == HEAD or location == ALL) then
result = result .. bin.pack("<SSA", length * 2, max_length * 2, marshall_ptr(HEAD, marshall_unicode, {str, do_null, max_length}, str)) result = result .. string.pack("<I2I2", length * 2, max_length * 2) .. marshall_ptr(HEAD, marshall_unicode, {str, do_null, max_length}, str)
end end
if(location == BODY or location == ALL) then if(location == BODY or location == ALL) then
@@ -2718,7 +2729,7 @@ function marshall_winreg_StringBuf(table, max_length)
-- For some reason, 0-length strings are handled differently (no null terminator)... -- For some reason, 0-length strings are handled differently (no null terminator)...
if(name == "") then if(name == "") then
length = 0 length = 0
result = bin.pack("<SSA", length * 2, max_length * 2, marshall_ptr(ALL, marshall_unicode, {name, false, max_length}, name)) result = string.pack("<I2I2", length * 2, max_length * 2) .. marshall_ptr(ALL, marshall_unicode, {name, false, max_length}, name)
else else
if(name == nil) then if(name == nil) then
length = 0 length = 0
@@ -2726,7 +2737,7 @@ function marshall_winreg_StringBuf(table, max_length)
length = #name + 1 length = #name + 1
end end
result = bin.pack("<SSA", length * 2, max_length * 2, marshall_ptr(ALL, marshall_unicode, {name, true, max_length}, name)) result = string.pack("<I2I2", length * 2, max_length * 2) .. marshall_ptr(ALL, marshall_unicode, {name, true, max_length}, name)
end end
stdnse.debug4("MSRPC: Leaving marshall_winreg_StringBuf()") stdnse.debug4("MSRPC: Leaving marshall_winreg_StringBuf()")
@@ -2978,7 +2989,7 @@ local function marshall_srvsvc_NetShareInfo1(location, name, sharetype, comment)
local sharetype = marshall_basetype(location, marshall_srvsvc_ShareType, {sharetype}) local sharetype = marshall_basetype(location, marshall_srvsvc_ShareType, {sharetype})
local comment = marshall_ptr(location, marshall_unicode, {comment, true}, comment) local comment = marshall_ptr(location, marshall_unicode, {comment, true}, comment)
result = bin.pack("<AAA", name, sharetype, comment) result = name .. sharetype .. comment
stdnse.debug4("MSRPC: Leaving marshall_srvsvc_NetShareInfo1()") stdnse.debug4("MSRPC: Leaving marshall_srvsvc_NetShareInfo1()")
return result return result
@@ -3123,19 +3134,19 @@ end
--@return A string representing the marshalled data. --@return A string representing the marshalled data.
function marshall_srvsvc_NetShareCtr0(NetShareCtr0) function marshall_srvsvc_NetShareCtr0(NetShareCtr0)
local i local i
local result = "" local result = {}
stdnse.debug4("MSRPC: Entering marshall_srvsvc_NetShareCtr0()") stdnse.debug4("MSRPC: Entering marshall_srvsvc_NetShareCtr0()")
if(NetShareCtr0 == nil) then if(NetShareCtr0 == nil) then
result = result .. bin.pack("<I", 0) result[#result+1] = string.pack("<I4", 0)
else else
local array = NetShareCtr0['array'] local array = NetShareCtr0['array']
local marshall = nil local marshall = nil
if(array == nil) then if(array == nil) then
result = result .. bin.pack("<I", 0) result[#result+1] = string.pack("<I4", 0)
else else
result = result .. bin.pack("<I", #array) -- count result[#result+1] = string.pack("<I4", #array) -- count
-- Build the array that we can marshall -- Build the array that we can marshall
marshall = {} marshall = {}
@@ -3146,11 +3157,11 @@ function marshall_srvsvc_NetShareCtr0(NetShareCtr0)
end end
end end
result = result .. marshall_ptr(ALL, marshall_array, {marshall}, marshall) -- array result[#result+1] = marshall_ptr(ALL, marshall_array, {marshall}, marshall) -- array
end end
stdnse.debug4("MSRPC: Leaving marshall_srvsvc_NetShareCtr0()") stdnse.debug4("MSRPC: Leaving marshall_srvsvc_NetShareCtr0()")
return result return table.concat(result)
end end
---Unmarshall a NetShareCtr (container) type 0. See the marshall function for the definition. ---Unmarshall a NetShareCtr (container) type 0. See the marshall function for the definition.
@@ -3186,19 +3197,19 @@ end
--@return A string representing the marshalled data. --@return A string representing the marshalled data.
function marshall_srvsvc_NetShareCtr1(NetShareCtr1) function marshall_srvsvc_NetShareCtr1(NetShareCtr1)
local i local i
local result = "" local result = {}
stdnse.debug4("MSRPC: Entering marshall_srvsvc_NetShareCtr1()") stdnse.debug4("MSRPC: Entering marshall_srvsvc_NetShareCtr1()")
if(NetShareCtr1 == nil) then if(NetShareCtr1 == nil) then
result = result .. bin.pack("<I", 0) result[#result+1] = string.pack("<I4", 0)
else else
local array = NetShareCtr1['array'] local array = NetShareCtr1['array']
local marshall = nil local marshall = nil
if(array == nil) then if(array == nil) then
result = result .. bin.pack("<I", 0) result[#result+1] = string.pack("<I4", 0)
else else
result = result .. bin.pack("<I", #array) -- count result[#result+1] = string.pack("<I4", #array) -- count
-- Build the array that we can marshall -- Build the array that we can marshall
marshall = {} marshall = {}
@@ -3209,11 +3220,11 @@ function marshall_srvsvc_NetShareCtr1(NetShareCtr1)
end end
end end
result = result .. marshall_ptr(ALL, marshall_array, {marshall}, marshall) -- array result[#result+1] = marshall_ptr(ALL, marshall_array, {marshall}, marshall) -- array
end end
stdnse.debug4("MSRPC: Leaving marshall_srvsvc_NetShareCtr1()") stdnse.debug4("MSRPC: Leaving marshall_srvsvc_NetShareCtr1()")
return result return table.concat(result)
end end
@@ -3232,19 +3243,19 @@ end
--@return A string representing the marshalled data. --@return A string representing the marshalled data.
function marshall_srvsvc_NetShareCtr2(NetShareCtr2) function marshall_srvsvc_NetShareCtr2(NetShareCtr2)
local i local i
local result = "" local result = {}
stdnse.debug4("MSRPC: Entering marshall_srvsvc_NetShareCtr2()") stdnse.debug4("MSRPC: Entering marshall_srvsvc_NetShareCtr2()")
if(NetShareCtr2 == nil) then if(NetShareCtr2 == nil) then
result = result .. bin.pack("<I", 0) result[#result+1] = string.pack("<I4", 0)
else else
local array = NetShareCtr2['array'] local array = NetShareCtr2['array']
local marshall = nil local marshall = nil
if(array == nil) then if(array == nil) then
result = result .. bin.pack("<I", 0) result[#result+1] = string.pack("<I4", 0)
else else
result = result .. bin.pack("<I", #array) -- count result[#result+1] = string.pack("<I4", #array) -- count
-- Build the array that we can marshall -- Build the array that we can marshall
marshall = {} marshall = {}
@@ -3256,11 +3267,11 @@ function marshall_srvsvc_NetShareCtr2(NetShareCtr2)
end end
end end
result = result .. marshall_ptr(ALL, marshall_array, {marshall}, marshall) -- array result[#result+1] = marshall_ptr(ALL, marshall_array, {marshall}, marshall) -- array
end end
stdnse.debug4("MSRPC: Leaving marshall_srvsvc_NetShareCtr2()") stdnse.debug4("MSRPC: Leaving marshall_srvsvc_NetShareCtr2()")
return result return table.concat(result)
end end
---Marshall the top-level NetShareCtr. This is a union of a bunch of different containers: ---Marshall the top-level NetShareCtr. This is a union of a bunch of different containers:
@@ -3290,19 +3301,20 @@ end
-- For level 0, you'll probably want a table containing array=nil. -- For level 0, you'll probably want a table containing array=nil.
--@return A string representing the marshalled data, or 'nil' if it couldn't be marshalled. --@return A string representing the marshalled data, or 'nil' if it couldn't be marshalled.
function marshall_srvsvc_NetShareCtr(level, data) function marshall_srvsvc_NetShareCtr(level, data)
local result
stdnse.debug4("MSRPC: Entering marshall_srvsvc_NetShareCtr()") stdnse.debug4("MSRPC: Entering marshall_srvsvc_NetShareCtr()")
local marshaller
if(level == 0) then if(level == 0) then
result = bin.pack("<IA", level, marshall_ptr(ALL, marshall_srvsvc_NetShareCtr0, {data}, data)) marshaller = marshall_srvsvc_NetShareCtr0
elseif(level == 1) then elseif(level == 1) then
result = bin.pack("<IA", level, marshall_ptr(ALL, marshall_srvsvc_NetShareCtr1, {data}, data)) marshaller = marshall_srvsvc_NetShareCtr1
elseif(level == 2) then elseif(level == 2) then
result = bin.pack("<IA", level, marshall_ptr(ALL, marshall_srvsvc_NetShareCtr2, {data}, data)) marshaller = marshall_srvsvc_NetShareCtr2
else else
stdnse.debug1("MSRPC: ERROR: Script requested an unknown level for srvsvc_NetShareCtr: %d", level) stdnse.debug1("MSRPC: ERROR: Script requested an unknown level for srvsvc_NetShareCtr: %d", level)
result = nil return nil
end end
local result = string.pack("<I4", level) .. marshall_ptr(ALL, marshaller, {data}, data)
stdnse.debug4("MSRPC: Leaving marshall_srvsvc_NetShareCtr()") stdnse.debug4("MSRPC: Leaving marshall_srvsvc_NetShareCtr()")
return result return result
@@ -3407,7 +3419,7 @@ local function marshall_srvsvc_NetSessInfo10(location, client, user, time, idle_
local time = marshall_basetype(location, marshall_int32, {time}) local time = marshall_basetype(location, marshall_int32, {time})
local idle_time = marshall_basetype(location, marshall_int32, {idle_time}) local idle_time = marshall_basetype(location, marshall_int32, {idle_time})
result = bin.pack("<AAAA", client, user, time, idle_time) result = client .. user .. time .. idle_time
stdnse.debug4("MSRPC: Leaving marshall_srvsvc_NetShareInfo10()") stdnse.debug4("MSRPC: Leaving marshall_srvsvc_NetShareInfo10()")
return result return result
@@ -3463,19 +3475,19 @@ end
--@return A string representing the marshalled data. --@return A string representing the marshalled data.
function marshall_srvsvc_NetSessCtr10(NetSessCtr10) function marshall_srvsvc_NetSessCtr10(NetSessCtr10)
local i local i
local result = "" local result = {}
stdnse.debug4("MSRPC: Entering marshall_srvsvc_NetSessCtr10()") stdnse.debug4("MSRPC: Entering marshall_srvsvc_NetSessCtr10()")
if(NetSessCtr10 == nil) then if(NetSessCtr10 == nil) then
result = result .. bin.pack("<I", 0) result[#result+1] = string.pack("<I4", 0)
else else
local array = NetSessCtr10['array'] local array = NetSessCtr10['array']
local marshall = nil local marshall = nil
if(array == nil) then if(array == nil) then
result = result .. bin.pack("<I", 0) result[#result+1] = string.pack("<I4", 0)
else else
result = result .. bin.pack("<I", #array) -- count result[#result+1] = string.pack("<I4", #array) -- count
-- Build the array that we can marshall -- Build the array that we can marshall
marshall = {} marshall = {}
@@ -3486,11 +3498,11 @@ function marshall_srvsvc_NetSessCtr10(NetSessCtr10)
end end
end end
result = result .. marshall_ptr(ALL, marshall_array, {marshall}, marshall) -- array result[#result+1] = marshall_ptr(ALL, marshall_array, {marshall}, marshall) -- array
end end
stdnse.debug4("MSRPC: Leaving marshall_srvsvc_NetSessCtr10()") stdnse.debug4("MSRPC: Leaving marshall_srvsvc_NetSessCtr10()")
return result return table.concat(result)
end end
---Unmarshall a NetSessCtr (session container) type 10. See the marshall function for the definition. ---Unmarshall a NetSessCtr (session container) type 10. See the marshall function for the definition.
@@ -3536,7 +3548,7 @@ function marshall_srvsvc_NetSessCtr(level, data)
stdnse.debug4("MSRPC: Entering marshall_srvsvc_NetShareCtr()") stdnse.debug4("MSRPC: Entering marshall_srvsvc_NetShareCtr()")
if(level == 10) then if(level == 10) then
result = bin.pack("<IA", level, marshall_ptr(ALL, marshall_srvsvc_NetSessCtr10, {data}, data)) result = string.pack("<I4", level) .. marshall_ptr(ALL, marshall_srvsvc_NetSessCtr10, {data}, data)
else else
stdnse.debug1("MSRPC: ERROR: Script requested an unknown level for srvsvc_NetSessCtr") stdnse.debug1("MSRPC: ERROR: Script requested an unknown level for srvsvc_NetSessCtr")
result = nil result = nil
@@ -3557,7 +3569,7 @@ function unmarshall_srvsvc_NetSessCtr(data, pos)
local result local result
stdnse.debug4("MSRPC: Entering unmarshall_srvsvc_NetSessCtr()") stdnse.debug4("MSRPC: Entering unmarshall_srvsvc_NetSessCtr()")
pos, level = bin.unpack("<I", data, pos) level, pos = string.unpack("<I4", data, pos)
if(level == 10) then if(level == 10) then
pos, result = unmarshall_ptr(ALL, data, pos, unmarshall_srvsvc_NetSessCtr10, {}) pos, result = unmarshall_ptr(ALL, data, pos, unmarshall_srvsvc_NetSessCtr10, {})