mirror of
https://github.com/nmap/nmap.git
synced 2025-12-06 04:31:29 +00:00
Mostly splitting function summaries (the first paragraph of NSEdoc) from the body of the description to make the summary indexes shorter and easier to scan. Also fixed some unbalanced code tags like <code>foo</table>
4675 lines
168 KiB
Lua
4675 lines
168 KiB
Lua
---
|
|
-- This module was written to marshall parameters for Microsoft RPC (MSRPC) calls. The values passed in and out are based
|
|
-- on structs defined by the protocol, and documented by Samba developers. For detailed breakdowns of the types, take a
|
|
-- look at Samba 4.0's <code>.idl</code> files.
|
|
--
|
|
-- There is nothing simple about how this all comes together, so I'll take some time to explain how it's done. This
|
|
-- is fairly technical and, when it comes right down to it, unnecessary for how to use these functions (although if you
|
|
-- want to write one of these, you best understand it).
|
|
--
|
|
-- There are base types, like int32 and int16. These are marshalled the way you'd expect (converted to a 4- or
|
|
-- 2-byte little endian string). The only trick with these is that they have to end up aligned on 4-byte boundaries.
|
|
-- So, a 2-byte integer requires 2 bytes of padding, and a 1-byte integer requires 3 bytes of padding. The functions
|
|
-- <code>marshall_int32</code>, <code>marshall_int16</code>, etc. will marshall the base types, and <code>unmarshall_int32</code>,
|
|
-- <code>unmarshall_int16</code>, etc. will unmarshall them.
|
|
--
|
|
-- Strings are a little bit trickier. A string is preceded by three 32-bit values: the max length, the offset, and
|
|
-- the length. Additionally, strings may or may not be null terminated, depending on where they're being used. For
|
|
-- more information on strings, see the comments on <code>marshall_unicode</code>. The functions <code>marshall_unicode</code>
|
|
-- and <code>unmarshall_unicode</code> can be used to marshall/unmarshall strings.
|
|
--
|
|
-- Pointers also have interesting properties. A pointer is preceded by a 4-byte value called (at least by Wireshark)
|
|
-- the "referent id". For a valid pointer, this can be anything except 0 (I use 'NMAP' for it). If it's '0', then
|
|
-- it's a null pointer and the data doesn't actually follow. To help clarify, a pointer to the integer '4' could be
|
|
-- marshalled as the hex string <code>78 56 34 12 04 00 00 00</code> (the referent_id is 0x12345678 and the integer
|
|
-- itself is 0x00000004). If the integer is nil, then it's marshalled as <code>00 00 00 00</code>, which is simply
|
|
-- a referent_id of 0.
|
|
--
|
|
-- From the perspective of the program, pointers can be marshalled by using the "<code>_ptr</code>" versions of normal functions
|
|
-- (for example, <code>marshall_int32_ptr</code> and <code>unmarshall_unicode_ptr</code>. From the perspective
|
|
-- of functions within this module, especially functions for marshalling structs and arrays, the <code>marshall_ptr</code>
|
|
-- and <code>unmarshall_ptr</code> functions should be used. These can marshall any data type; the marshalling function
|
|
-- is passed as a parameter.
|
|
--
|
|
-- So far, this is fairly straight forward. Arrays are where everything falls apart.
|
|
--
|
|
-- An array of basic types is simply the types themselves, preceded by the "max length" of the array (which can be
|
|
-- longer than the actual length). When pointers are used in an array, however, things get hairy. The 'referent_id's
|
|
-- of the pointers are all put at the start of the array, along with the base types. Then, the data is put at the
|
|
-- end of the array, for all the referent_ids that aren't null. Let's say you have four strings, "abc", "def", null, and
|
|
-- "jkl", in an array. The array would look like this:
|
|
-- <code>
|
|
-- 0x00200000 (referent_id for "abc")
|
|
-- 0x00400000 (referent_id for "def")
|
|
-- 0x00000000 (null referent_id)
|
|
-- 0x00800000 (referent_id for "jkl")
|
|
-- "abc" (note that this also has the standard string stuff, the max_length, offset, and actual_length)
|
|
-- "def"
|
|
-- "ghi"
|
|
-- </code>
|
|
--
|
|
-- If you mix in a base type, it goes at the front along with the referent_ids. So, let's say you have a structure
|
|
-- that contains two integers and a string. You have an array of these. It would encode like this:
|
|
-- <code>
|
|
-- 0x00200000 (referent_id for the string in the first struct)
|
|
-- 0x00000001 (first integer in the first struct)
|
|
-- 0x00000002 (second integer in the first struct)
|
|
-- 0x00400000 (referent_id for the string in the second struct)
|
|
-- 0x00000003 (first integer in the second struct)
|
|
-- 0x00000004 (second integer in the second struct)
|
|
-- "string1" (contains max_length, offset, and actual_length)
|
|
-- "string2"
|
|
-- </code>
|
|
--
|
|
-- From the perspective of the program, arrays shouldn't need to be marshalled/unmarshalled, this is tricky and should be
|
|
-- left up to functions within this module. Functions within this module should use <code>marshall_array</code> and
|
|
-- <code>unmarshall_array</code> to interact with arrays. These take callback functions for the datatype being stored
|
|
-- in the array; these callback functions have to be in a particular format, so care should be taken when writing them.
|
|
-- In particular, the first parameter has to be <code>location</code>, which is used to separate the header (the part with the
|
|
-- referent_ids) and the body (the part with the pointer data). These are explained more thoroughly in the function headers.
|
|
--
|
|
-- Structs are handled the same as arrays. The referent_ids and base types go at the top, and the values being pointed to
|
|
-- go at the bottom. An array of struct, as has already been shown, will have all the base types and referent_ids for all the
|
|
-- members at the top, and all the values for all the pointers at the bottom.
|
|
--
|
|
-- Structs tend to be custom functions. Sometimes, these functions are passed as the callback to <code>marshall_ptr</code> or
|
|
-- <code>marshall_array</code> (and the equivalent <code>unmarshall_</code> functions). This means that the custom struct
|
|
-- functions have to be able to split themselves into the base types and the pointer data automatically. For an example, see
|
|
-- the functions that have already been written.
|
|
--
|
|
-- In the case where you need to unmarshall the same struct from both an array and a pointer, there's an issue; they require
|
|
-- different prototypes. There's really no way to directly fix this, at least, none that I could come up with, so I write
|
|
-- a function called <code>unmarshall_struct</code>. <code>unmarshall_struct</code> basically calls a struct unmarshalling
|
|
-- function the same way <code>unmarshall_array</code> would. This is a bit of a kludge, but it's the best I could come up
|
|
-- with.
|
|
--
|
|
-- There are different sections in here, which correspond to "families" of types. I modeled these after Samba's <code>.idl</code> files.
|
|
-- MISC corresponds to <code>misc.idl</code>, LSA to <code>lsa.idl</code>, etc. Each of these sections has possible dependencies; for example, SAMR
|
|
-- functions use LSA strings, and everything uses SECURITY and MISC. So the order is important -- dependencies have to go
|
|
-- above the module.
|
|
--
|
|
-- The datatypes used here are modeled after the datatypes used by Microsoft's functions. Each function that represents
|
|
-- a struct will have the struct definition in its comment; and that struct (or the closest representation to it) will be
|
|
-- returned. Often, this requires scripts to access something like <code>result['names']['names'][0]['name']</code>, which is
|
|
-- rather unwieldy, but I decided that following Microsoft's definitions was the most usable way for many reasons. I find
|
|
-- the best way to figure out how to work a function is to call a print_table()-style function on the result and look at
|
|
-- how the response is laid out.
|
|
--
|
|
-- Many datatypes are automatically encoded when sent and decoded when received to make life easier for developers. Some
|
|
-- examples are:
|
|
-- * All absolute time values will be seconds from 1970
|
|
-- * All relative time values will be in seconds (this includes the <code>hyper</code> datatype); when possible, the milliseconds/microseconds (as far down as we have access to) will be preserved as a decimal
|
|
-- * All enumerations will be a string representing the constant (which can be converted to a user-readable string using one of the <code>_tostr</code> functions); what that means is, enumeration values are never used, only the names
|
|
-- * 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
|
|
|
|
local bin = require "bin"
|
|
local bit = require "bit"
|
|
local os = require "os"
|
|
local stdnse = require "stdnse"
|
|
local string = require "string"
|
|
local table = require "table"
|
|
local unicode = require "unicode"
|
|
_ENV = stdnse.module("msrpctypes", stdnse.seeall)
|
|
|
|
local REFERENT_ID = 0x50414d4e
|
|
local HEAD = 'HEAD'
|
|
local BODY = 'BODY'
|
|
local ALL = 'ALL'
|
|
|
|
--- Convert a string to Unicode (UTF-16 LE), optionally add a null terminator,
|
|
-- and align it to 4-byte boundaries.
|
|
--
|
|
-- This is frequently used in MSRPC calls, so I put it here, but it might be a
|
|
-- good idea to move this function (and the converse one below) into a separate
|
|
-- library.
|
|
--
|
|
--@param string The string to convert.
|
|
--@param do_null [optional] Add a null-terminator to the unicode string.
|
|
-- Default false.
|
|
--@return The unicode version of the string.
|
|
function string_to_unicode(string, do_null)
|
|
local i
|
|
|
|
stdnse.debug4("MSRPC: Entering string_to_unicode(string = %s)", string)
|
|
|
|
if(do_null == nil) then
|
|
do_null = false
|
|
end
|
|
|
|
-- Try converting the value to a string
|
|
if(type(string) ~= 'string') then
|
|
string = tostring(string)
|
|
end
|
|
|
|
if(string == nil) then
|
|
stdnse.debug1("MSRPC: WARNING: couldn't convert value to string in string_to_unicode()")
|
|
end
|
|
|
|
|
|
local result = unicode.utf8to16(string)
|
|
|
|
-- Add a null, if the caller requested it
|
|
if(do_null == true) then
|
|
result = result .. "\0\0"
|
|
end
|
|
|
|
-- Align it to a multiple of 4, if necessary
|
|
if(#result % 4 ~= 0) then
|
|
result = result .. "\0\0"
|
|
end
|
|
|
|
stdnse.debug4("MSRPC: Leaving string_to_unicode()")
|
|
|
|
return result
|
|
end
|
|
|
|
--- Read a unicode string from a buffer, similar to how <code>bin.unpack</code> would, optionally eat the null terminator,
|
|
-- and optionally align it to 4-byte boundaries.
|
|
--
|
|
--@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 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.
|
|
--@return (pos, string) The new position and the string read, again imitating <code>bin.unpack</code>. If there was an
|
|
-- 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)
|
|
stdnse.debug4("MSRPC: Entering unicode_to_string(pos = %d, length = %d)", pos, length)
|
|
|
|
local endpos = pos + length * 2 - 1
|
|
|
|
if endpos > #buffer then
|
|
stdnse.debug1("MSRPC: ERROR: Ran off the end of a string in unicode_to_string(), this likely means we are reading a packet incorrectly. Please report! (pos = %d, #buffer = %d, endpos = %d)", pos, #buffer, endpos)
|
|
|
|
return nil, nil
|
|
end
|
|
|
|
local str = unicode.utf16to8(string.sub(buffer, pos, endpos))
|
|
|
|
if do_null then
|
|
str = string.sub(str, 1, -2) -- Eat the null terminator
|
|
end
|
|
|
|
-- Align to 4-byte boundary
|
|
endpos = endpos + (endpos + 1 - pos) % 4
|
|
|
|
stdnse.debug4("MSRPC: Leaving unicode_to_string()")
|
|
|
|
return endpos + 1, str
|
|
end
|
|
|
|
-------------------------------------
|
|
-- SPECIAL
|
|
-- (dependencies: n/a)
|
|
-------------------------------------
|
|
|
|
---Marshalls a pointer to another datatype.
|
|
--
|
|
-- This function will optionally separate the REFERENT_ID of the pointer (which
|
|
-- goes at location = HEAD) from the data part of the pointer (which goes at
|
|
-- location = BODY). If the entire pointer is needed, then location should be
|
|
-- set to ALL.
|
|
--
|
|
-- When marshalling the body, the function <code>func</code> is called, which
|
|
-- is passed as a parameter, with the arguments <code>args</code>. This
|
|
-- function has to return a marshalled parameter, but other than that it can be
|
|
-- any marshalling function. The 'value' parameter simply determined whether or
|
|
-- not it's a null pointer, and will probably be a repeat of one of the
|
|
-- arguments.
|
|
--
|
|
-- Note that the function <code>func</code> doesn't have to conform to any
|
|
-- special prototype, as long as the <code>args</code> array matches what the
|
|
-- function wants.
|
|
--
|
|
-- This can be used to marshall an int16 value of 0x1234 with padding like this:
|
|
-- <code>
|
|
-- marshall_ptr(ALL, marshall_int16, {0x1234, true}, 0x1234)
|
|
-- </code>
|
|
--
|
|
-- And here's how a 'nil' string might be marshalled:
|
|
-- <code>
|
|
-- local str = nil
|
|
-- marshall_ptr(ALL, marshall_unicode, {str, true}, str)
|
|
-- </code>
|
|
--
|
|
--@param location The part of the pointer wanted, either HEAD (for the
|
|
-- referent_id), BODY (for the pointer data), or ALL (for both
|
|
-- together). Generally, unless the referent_id is split from
|
|
-- the data (for example, in an array), you will want ALL.
|
|
--@param func The function to call when encoding the body. Should convert the
|
|
-- arguments passed in the <code>args</code> parameter to a string.
|
|
--@param args An array of arguments that will be directly passed to the
|
|
-- function <code>func</code>
|
|
--@param value The value that's actually being encoded. This is simply used to
|
|
-- determine whether or not the pointer is null.
|
|
--@return A string representing the marshalled data.
|
|
local function marshall_ptr(location, func, args, value)
|
|
local result = ""
|
|
|
|
stdnse.debug4("MSRPC: Entering marshall_ptr(location = %s)", location)
|
|
|
|
-- If we're marshalling the HEAD section, add a REFERENT_ID.
|
|
if(location == HEAD or location == ALL) then
|
|
if(func == nil or args == nil or value == nil) then
|
|
result = result .. bin.pack("<I", 0)
|
|
else
|
|
result = result .. bin.pack("<I", REFERENT_ID)
|
|
end
|
|
end
|
|
|
|
-- If we're marshalling the BODY section, and the value isn't null, call the function to marshall
|
|
-- the data.
|
|
if(location == BODY or location == ALL) then
|
|
if(func == nil or args == nil or value == nil) then
|
|
else
|
|
result = result .. func(table.unpack(args))
|
|
end
|
|
end
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_ptr()")
|
|
|
|
return result
|
|
end
|
|
|
|
---Unmarshalls a pointer by removing the referent_id in the HEAD section and
|
|
--the data in the BODY section (or both in the ALL section).
|
|
--
|
|
-- Because the unmarshall function for the body is called if and only if the
|
|
-- referent_id is non-zero, if the head and the body are split apart, the
|
|
-- second call to this function has to know the context. This is the purpose
|
|
-- for the <code>result</code> parameter, it is the result from the first time
|
|
-- this is called.
|
|
--
|
|
-- The function <code>func</code> has to conform to this format:
|
|
--<code>
|
|
-- func(data, pos, <args>)
|
|
--</code>
|
|
--
|
|
--@param location The part of the pointer being processed, either HEAD (for the
|
|
-- referent_id), BODY (for the pointer data), or ALL (for both
|
|
-- together). Generally, unless the referent_id is split from
|
|
-- the data (for example, in an array), you will want ALL.
|
|
--@param data The data being processed.
|
|
--@param pos The position within <code>data</code>
|
|
--@param func The function that's used to process the body data (only
|
|
-- called if it isn't a null pointer). This function has to conform
|
|
-- to a specific prototype, see above.
|
|
--@param args The arguments that'll be passed to the function
|
|
-- <code>func</code>, after the data array and the position.
|
|
--@param result This is required when unmarshalling the BODY section, which
|
|
-- always comes after unmarshalling the HEAD. It is the result
|
|
-- returned for this parameter during the HEAD unmarshall. If the
|
|
-- referent_id was '0', then this function doesn't unmarshall
|
|
-- anything.
|
|
--@return The new position
|
|
--@reutrn The result. For HEAD the result is either <code>true</code> for valid
|
|
-- pointers or <code>false</code> for null pointers. For BODY or ALL,
|
|
-- the result is <code>nil</code> for null pointers, or the data for
|
|
-- valid pointers.
|
|
local function unmarshall_ptr(location, data, pos, func, args, result)
|
|
stdnse.debug4("MSRPC: Entering unmarshall_ptr()")
|
|
if(args == nil) then
|
|
args = {}
|
|
end
|
|
-- If we're unmarshalling the header, then pull off a referent_id.
|
|
if(location == HEAD or location == ALL) then
|
|
local referent_id
|
|
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!")
|
|
end
|
|
|
|
if(location == HEAD) then
|
|
if(referent_id == 0) then
|
|
result = false
|
|
else
|
|
result = true
|
|
end
|
|
else
|
|
if(referent_id == 0) then
|
|
result = nil
|
|
else
|
|
result = true
|
|
end
|
|
end
|
|
end
|
|
|
|
if(location == BODY or location == ALL) then
|
|
if(result == true) then
|
|
pos, result = func(data, pos, table.unpack(args))
|
|
else
|
|
result = nil
|
|
end
|
|
end
|
|
|
|
return pos, result
|
|
end
|
|
|
|
---Similar to <code>marshall_ptr</code>, except that this marshalls a type that isn't a pointer.
|
|
--
|
|
-- It also understands pointers, in the sense that it'll only return data in
|
|
-- the HEAD section, since basetypes are printed in the HEAD and not the BODY.
|
|
--
|
|
-- Using this isn't strictly necessary, but it cleans up functions for
|
|
-- generating structs containing both pointers and basetypes (see
|
|
-- <code>marshall_srvsvc_NetShareInfo2</code>).
|
|
--
|
|
-- Like <code>marshall_ptr</code>, the function doesn't have to match any
|
|
-- prototype, as long as the proper arguments are passed to it.
|
|
--
|
|
--@param location The part of the pointer wanted, either HEAD (for the data
|
|
-- itself), BODY (for nothing, since this isn't a pointer), or
|
|
-- ALL (for the data). Generally, unless the referent_id is
|
|
-- split from the data (for example, in an array), you will want
|
|
-- ALL.
|
|
--@param func The function to call when encoding the body. Should convert the
|
|
-- arguments passed in the <code>args</code> parameter to a string.
|
|
--@param args An array of arguments that will be directly passed to the
|
|
-- function <code>func</code>
|
|
--@return A string representing the marshalled data.
|
|
local function marshall_basetype(location, func, args)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering marshall_basetype()")
|
|
|
|
if(location == HEAD or location == ALL) then
|
|
result = bin.pack("<A", func(table.unpack(args)))
|
|
else
|
|
result = ""
|
|
end
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_basetype()")
|
|
|
|
return result
|
|
end
|
|
|
|
---Marshalls an array.
|
|
--
|
|
-- Recall (from the module comment) that the data in an array is split into the
|
|
-- referent_ids and base types at the top and the data at the bottom. This
|
|
-- function will call any number of location-aware functions twice (once for
|
|
-- the top and once for the bottom).
|
|
--
|
|
-- Each element in the array can technically have a different function. I don't
|
|
-- know why I allowed that, and may refactor it out in the future. For now, I
|
|
-- strongly recommend setting the function to the same for every element.
|
|
--
|
|
-- The function that's called has to have the prototype:
|
|
--<code>
|
|
-- func(location, <args>)
|
|
--</code>
|
|
-- where "location" is the standard HEAD/BODY/ALL location used throughout the
|
|
-- functions.
|
|
--
|
|
--@param array An array of tables. Each table contains 'func', a pointer to the
|
|
-- marshalling function and 'args', the arguments to pass to the
|
|
-- marshalling function after the 'location' variable.
|
|
--@return A string representing the marshalled data.
|
|
function marshall_array(array)
|
|
local i
|
|
local result = ""
|
|
|
|
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
|
|
-- 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.
|
|
result = result .. bin.pack("<I", #array)
|
|
|
|
-- Encode the HEAD sections of all the elements in the array
|
|
for i = 1, #array, 1 do
|
|
local func = array[i]['func']
|
|
local args = array[i]['args']
|
|
|
|
result = result .. func(HEAD, table.unpack(args))
|
|
end
|
|
|
|
-- Encode the BODY sections of all the elements in the array
|
|
for i = 1, #array, 1 do
|
|
local func = array[i]['func']
|
|
local args = array[i]['args']
|
|
|
|
result = result .. func(BODY, table.unpack(args))
|
|
end
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_array()")
|
|
return result
|
|
end
|
|
|
|
---Unmarshalls an array.
|
|
--
|
|
-- This function starts to get a little hairy, due to the number of parameters
|
|
-- that need to be propagated, but it isn't too bad. Basically, this
|
|
-- unmarshalls an array by calling the given function for each element.
|
|
--
|
|
-- The function <code>func</code> has to conform to a very specific prototype:
|
|
--<code>
|
|
-- func(location, data, pos, result, <args>)
|
|
--</code>
|
|
-- Where <code>location<code> is the standard HEAD/BODY location,
|
|
-- <code>data<code> and <code>pos<code> are the packet and position within it,
|
|
-- <code>result<code> is the result from the HEAD section (if it's nil, it
|
|
-- isn't used), and <code>args<code> are arbitrary arguments passed to it.
|
|
--
|
|
-- I made the call to pass the same arguments to each function when it's
|
|
-- called. This is, for example, whether or not to null-terminate a string, or
|
|
-- whether or not to pad an int16. If different types are required, you're
|
|
-- probably out of luck.
|
|
--
|
|
--@param data The data being processed.
|
|
--@param pos The position within <code>data</code>.
|
|
--@param count The number of elements in the array.
|
|
--@param func The function to call to unmarshall each parameter. Has to match a
|
|
-- specific prototype; see the function comment.
|
|
--@param args Arbitrary arguments to pass to the function.
|
|
--@return The new position
|
|
--@return The result of unmarshalling this value.
|
|
local function unmarshall_array(data, pos, count, func, args)
|
|
local i
|
|
local size
|
|
local result = {}
|
|
|
|
stdnse.debug4("MSRPC: Entering unmarshall_array()")
|
|
|
|
if(args == nil) then
|
|
args = {}
|
|
end
|
|
|
|
local pos, max_count = bin.unpack("<I", data, pos)
|
|
if(max_count == nil) then
|
|
stdnse.debug1("MSRPC: ERROR: Ran off the end of a packet in unmarshall_array(). Please report!")
|
|
end
|
|
|
|
-- Unmarshall the header, which will be referent_ids and base types.
|
|
for i = 1, count, 1 do
|
|
pos, result[i] = func(HEAD, data, pos, nil, table.unpack(args))
|
|
end
|
|
|
|
-- Unmarshall the body. Note that the original result (result[i]) is passed back
|
|
-- into this function. This is required for pointers because, to unmarshall a pointer,
|
|
-- we have to remember whether or not it's null.
|
|
for i = 1, count, 1 do
|
|
pos, result[i] = func(BODY, data, pos, result[i], table.unpack(args))
|
|
end
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_array()")
|
|
|
|
return pos, result
|
|
end
|
|
|
|
---Call a function that matches the prototype for <code>unmarshall_array</code>.
|
|
--
|
|
-- This allows the same struct to be used in <code>unmarshall_array</code> and
|
|
-- in <code>unmarshall_ptr</code>. It is kind of a kludge, but it makes sense,
|
|
-- and was the cleanest solution I could come up with to this problem (although
|
|
-- I'm sure that there's a better one staring me in the face).
|
|
--
|
|
-- The <code>func</code> parameter, obviously, has to match the same prototype
|
|
-- as strings being passed to <code>unmarshall_array</code>, which is:
|
|
--<code>
|
|
-- func(location, data, pos, result, <args>)
|
|
--</code>
|
|
--
|
|
--@param data The data being processed.
|
|
--@param pos The position within <code>data</code>.
|
|
--@param func The function to call to unmarshall each parameter. Has to match a
|
|
-- specific prototype; see the function comment.
|
|
--@param args Arbitrary arguments to pass to the function.
|
|
--@return The new position
|
|
--@return The result of unmarshalling this value.
|
|
local function unmarshall_struct(data, pos, func, args)
|
|
local result
|
|
|
|
stdnse.debug4("MSRPC: Entering unmarshall_struct()")
|
|
|
|
if(args == nil) then
|
|
args = {}
|
|
end
|
|
|
|
pos, result = func(ALL, data, pos, nil, args)
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_struct()")
|
|
|
|
return pos, result
|
|
end
|
|
|
|
-------------------------------------
|
|
-- BASE TYPES
|
|
-- (dependencies: n/a)
|
|
-------------------------------------
|
|
|
|
--- Marshall a string that is in the format:
|
|
-- <code>[string,charset(UTF16)] uint16 *str</code>
|
|
--
|
|
-- This has the max size of the buffer, the offset (I'm not sure what the offset does, I've
|
|
-- never seen it used), the actual size, and the string itself. This will always align to
|
|
-- the 4-byte boundary.
|
|
--
|
|
--@param str The string to insert. Cannot be nil.
|
|
--@param do_null [optional] Appends a null to the end of the string. Default false.
|
|
--@param max_length [optional] Sets a max length that's different than the string's length. Length
|
|
-- is in characters, not bytes.
|
|
--@return A string representing the marshalled data.
|
|
function marshall_unicode(str, do_null, max_length)
|
|
local buffer_length
|
|
local result
|
|
|
|
stdnse.debug4("MSRPC: Entering marshall_unicode()")
|
|
|
|
if(do_null == nil) then
|
|
do_null = false
|
|
end
|
|
|
|
if(do_null) then
|
|
buffer_length = #str + 1
|
|
else
|
|
buffer_length = #str
|
|
end
|
|
|
|
if(max_length == nil) then
|
|
max_length = buffer_length
|
|
end
|
|
|
|
result = bin.pack("<IIIA",
|
|
max_length, -- Max count
|
|
0, -- Offset
|
|
buffer_length, -- Actual count
|
|
string_to_unicode(str, do_null, true)
|
|
)
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_unicode()")
|
|
|
|
return result
|
|
end
|
|
|
|
--- Marshall a null-terminated ascii string, with the length/maxlength prepended. Very similar
|
|
-- to <code>marshall_unicode</code>, except it's ascii and the null terminator is always used.
|
|
--
|
|
--@param str The string to marshall.
|
|
--@param max_length [optional] The maximum length; default: actual length.
|
|
function marshall_ascii(str, max_length)
|
|
local buffer_length
|
|
local result
|
|
local padding = ""
|
|
|
|
buffer_length = #str + 1
|
|
|
|
if(max_length == nil) then
|
|
max_length = buffer_length
|
|
end
|
|
|
|
while((#(str .. string.char(0 .. padding)) % 4) ~= 0) do
|
|
padding = padding .. string.char(0)
|
|
end
|
|
|
|
result = bin.pack("<IIIzA",
|
|
max_length,
|
|
0,
|
|
buffer_length,
|
|
str,
|
|
padding
|
|
)
|
|
|
|
return result
|
|
end
|
|
|
|
--- Marshall a pointer to a unicode string.
|
|
--
|
|
--@param str The string to insert. Can be nil.
|
|
--@param do_null [optional] Appends a null to the end of the string. Default false.
|
|
--@param max_length [optional] Sets a max length that's different than the string's length. Length
|
|
-- is in characters, not bytes.
|
|
--@return A string representing the marshalled data.
|
|
function marshall_unicode_ptr(str, do_null, max_length)
|
|
local result
|
|
|
|
stdnse.debug4("MSRPC: Entering marshall_unicode()")
|
|
|
|
result = marshall_ptr(ALL, marshall_unicode, {str, do_null, max_length}, str)
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_unicode()")
|
|
|
|
return result
|
|
end
|
|
|
|
--- Marshall a pointer to an ascii string.
|
|
--
|
|
--@param str The string to insert. Can be nil.
|
|
--@param max_length [optional] Sets a max length that's different than the string's length.
|
|
--@return A string representing the marshalled data.
|
|
function marshall_ascii_ptr(str, max_length)
|
|
local result
|
|
|
|
result = marshall_ptr(ALL, marshall_ascii, {str, max_length}, str)
|
|
|
|
return result
|
|
end
|
|
|
|
--- Unmarshall a string that is in the format:
|
|
-- <code>[string,charset(UTF16)] uint16 *str</code>
|
|
--
|
|
-- See <code>marshall_unicode</code> for more information.
|
|
--
|
|
--@param data The data buffer.
|
|
--@param pos The position in the data buffer.
|
|
--@param do_null [optional] Discards the final character, the string terminator. Default false.
|
|
--
|
|
--@return (pos, str) The new position, and the string. The string may be nil.
|
|
function unmarshall_unicode(data, pos, do_null)
|
|
local ptr, str
|
|
local max, offset, actual
|
|
|
|
stdnse.debug4("MSRPC: Entering unmarshall_unicode()")
|
|
|
|
if(do_null == nil) then
|
|
do_null = false
|
|
end
|
|
|
|
pos, max, offset, actual = bin.unpack("<III", data, pos)
|
|
if(actual == nil) then
|
|
stdnse.debug1("MSRPC: ERROR: Ran off the end of a packet in unmarshall_unicode(). Please report!")
|
|
end
|
|
|
|
pos, str = unicode_to_string(data, pos, actual, do_null, true)
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_unicode()")
|
|
|
|
return pos, str
|
|
end
|
|
|
|
---Unmarshall a pointer to a unicode string.
|
|
--
|
|
--@param data The data being processed.
|
|
--@param pos The position within <code>data</code>.
|
|
--@param do_null [optional] Assumes a null is at the end of the string. Default false.
|
|
--@return (pos, result) The new position and the string.
|
|
function unmarshall_unicode_ptr(data, pos, do_null)
|
|
local result
|
|
|
|
stdnse.debug4("MSRPC: Entering unmarshall_unicode_ptr()")
|
|
pos, result = unmarshall_ptr(ALL, data, pos, unmarshall_unicode, {do_null})
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_unicode_ptr()")
|
|
|
|
return pos, result
|
|
end
|
|
|
|
---Marshall an array of unicode strings. This is a perfect demonstration of how to use
|
|
-- <code>marshall_array</code>.
|
|
--
|
|
--@param strings The array of strings to marshall
|
|
--@param do_null [optional] Appends a null to the end of the string. Default false.
|
|
--@return A string representing the marshalled data.
|
|
function marshall_unicode_array(strings, do_null)
|
|
local array = {}
|
|
local result
|
|
|
|
for i = 1, #strings, 1 do
|
|
array[i] = {}
|
|
array[i]['func'] = marshall_ptr
|
|
array[i]['args'] = {marshall_unicode, {strings[i], do_null}, strings[i]}
|
|
end
|
|
|
|
result = marshall_array(array)
|
|
|
|
return result
|
|
end
|
|
|
|
---Marshall a pointer to an array of unicode strings. See <code>marshall_unicode_array</code>
|
|
-- for more information.
|
|
--
|
|
--@param strings The array of strings to marshall
|
|
--@param do_null [optional] Appends a null to the end of the string. Default false.
|
|
--@return A string representing the marshalled data.
|
|
function marshall_unicode_array_ptr(strings, do_null)
|
|
local result
|
|
|
|
result = marshall_ptr(ALL, marshall_unicode_array, {strings, do_null}, strings)
|
|
|
|
return result
|
|
end
|
|
|
|
--- Marshall an int64. This is simply an 8-byte integer inserted into the buffer, nothing fancy.
|
|
--@param int64 The integer to insert
|
|
--@return A string representing the marshalled data.
|
|
function marshall_int64(int64)
|
|
local result
|
|
|
|
stdnse.debug4("MSRPC: Entering marshall_int64()")
|
|
result = bin.pack("<L", int64)
|
|
stdnse.debug4("MSRPC: Leaving marshall_int64()")
|
|
|
|
return result
|
|
end
|
|
|
|
--- Marshall an int32
|
|
--
|
|
-- <code> [in] uint32 var</code>
|
|
--
|
|
-- This is simply an integer inserted into the buffer, nothing fancy.
|
|
--@param int32 The integer to insert
|
|
--@return A string representing the marshalled data.
|
|
function marshall_int32(int32)
|
|
local result
|
|
|
|
stdnse.debug4("MSRPC: Entering marshall_int32()")
|
|
result = bin.pack("<I", int32)
|
|
stdnse.debug4("MSRPC: Leaving marshall_int32()")
|
|
|
|
return result
|
|
end
|
|
|
|
---Marshall an array of int32 values.
|
|
--
|
|
--@param data The array
|
|
--@return A string representing the marshalled data
|
|
function marshall_int32_array(data)
|
|
local result = ""
|
|
|
|
result = result .. marshall_int32(0x0400) -- Max count
|
|
result = result .. marshall_int32(0) -- Offset
|
|
result = result .. marshall_int32(#data) -- Actual count
|
|
|
|
for _, v in ipairs(data) do
|
|
result = result .. marshall_int32(v)
|
|
end
|
|
|
|
return result
|
|
end
|
|
|
|
--- Marshall an int16
|
|
--
|
|
-- <code> [in] uint16 var</code>
|
|
--
|
|
-- This is simply an integer inserted into the buffer, nothing fancy.
|
|
--@param int16 The integer to insert
|
|
--@param pad [optional] If set, will align the insert on 4-byte boundaries. Default: true.
|
|
--@return A string representing the marshalled data.
|
|
function marshall_int16(int16, pad)
|
|
local result
|
|
|
|
stdnse.debug4("MSRPC: Entering marshall_int16()")
|
|
|
|
if(pad == false) then
|
|
return bin.pack("<S", int16)
|
|
end
|
|
|
|
result = bin.pack("<SS", int16, 0)
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_int16()")
|
|
|
|
return result
|
|
end
|
|
|
|
--- Marshall an int8
|
|
--
|
|
-- <code> [in] uint8 var</code>
|
|
--
|
|
-- This is simply an integer inserted into the buffer, nothing fancy.
|
|
--
|
|
--@param int8 The integer to insert
|
|
--@param pad [optional] If set, will align the insert on 4-byte boundaries. Default: true.
|
|
--@return A string representing the marshalled data.
|
|
function marshall_int8(int8, pad)
|
|
local result
|
|
|
|
stdnse.debug4("MSRPC: Entering marshall_int8()")
|
|
|
|
if(pad == false) then
|
|
return bin.pack("<C", int8)
|
|
end
|
|
|
|
result = bin.pack("<CCS", int8, 0, 0)
|
|
stdnse.debug4("MSRPC: Leaving marshall_int8()")
|
|
|
|
return result
|
|
end
|
|
|
|
--- Unmarshall an int64. See <code>marshall_int64</code> for more information.
|
|
--
|
|
--@param data The data being processed.
|
|
--@param pos The position within <code>data</code>.
|
|
--@return (pos, int64) The new position, and the value.
|
|
function unmarshall_int64(data, pos)
|
|
local value
|
|
|
|
stdnse.debug4("MSRPC: Entering unmarshall_int64()")
|
|
pos, value = bin.unpack("<l", data, pos)
|
|
if(value == nil) then
|
|
stdnse.debug1("MSRPC: ERROR: Ran off the end of a packet in unmarshall_int64(). Please report!")
|
|
end
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_int64()")
|
|
|
|
return pos, value
|
|
end
|
|
|
|
--- Unmarshall an int32. See <code>marshall_int32</code> for more information.
|
|
--
|
|
--@param data The data being processed.
|
|
--@param pos The position within <code>data</code>.
|
|
--@return (pos, int32) The new position, and the value.
|
|
function unmarshall_int32(data, pos)
|
|
local value
|
|
|
|
pos, value = bin.unpack("<I", data, pos)
|
|
if(value == nil) then
|
|
stdnse.debug1("MSRPC: ERROR: Ran off the end of a packet in unmarshall_int32(). Please report!")
|
|
end
|
|
|
|
return pos, value
|
|
end
|
|
|
|
--- Unmarshall an int16. See <code>marshall_int16</code> for more information.
|
|
--
|
|
--@param data The data packet.
|
|
--@param pos The position within the data.
|
|
--@param pad [optional] If set, will remove extra bytes to align the packet, Default: true
|
|
--@return (pos, int16) The new position, and the value.
|
|
function unmarshall_int16(data, pos, pad)
|
|
local value
|
|
|
|
stdnse.debug4("MSRPC: Entering unmarshall_int16()")
|
|
|
|
pos, value = bin.unpack("<S", data, pos)
|
|
if(value == nil) then
|
|
stdnse.debug1("MSRPC: ERROR: Ran off the end of a packet in unmarshall_int16(). Please report!")
|
|
end
|
|
|
|
if(pad == nil or pad == true) then
|
|
pos = pos + 2
|
|
end
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_int16()")
|
|
|
|
return pos, value
|
|
end
|
|
|
|
--- Unmarshall an int8. See <code>marshall_int8</code> for more information.
|
|
--
|
|
--@param data The data packet.
|
|
--@param pos The position within the data.
|
|
--@param pad [optional] If set, will remove extra bytes to align the packet, Default: true
|
|
--@return (pos, int8) The new position, and the value.
|
|
function unmarshall_int8(data, pos, pad)
|
|
local value
|
|
|
|
stdnse.debug4("MSRPC: Entering unmarshall_int8()")
|
|
|
|
pos, value = bin.unpack("<C", data, pos)
|
|
if(value == nil) then
|
|
stdnse.debug1("MSRPC: ERROR: Ran off the end of a packet in unmarshall_int8(). Please report!")
|
|
end
|
|
|
|
if(pad == nil or pad == true) then
|
|
pos = pos + 3
|
|
end
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_int8()")
|
|
|
|
return pos, value
|
|
end
|
|
|
|
--- Marshall a pointer to an int64.
|
|
--
|
|
-- If the pointer is null, it simply marshalls the
|
|
-- integer '0'. Otherwise, it uses a referent id followed by the integer.
|
|
--
|
|
--@param int64 The value of the integer pointer
|
|
--@return A string representing the marshalled data.
|
|
function marshall_int64_ptr(int64)
|
|
local result
|
|
|
|
stdnse.debug4("MSRPC: Entering marshall_int64_ptr()")
|
|
result = marshall_ptr(ALL, marshall_int64, {int64}, int64)
|
|
stdnse.debug4("MSRPC: Leaving marshall_int64_ptr()")
|
|
|
|
return result
|
|
end
|
|
|
|
--- Marshall a pointer to an int32
|
|
--
|
|
-- <code> [in,out] uint32 *ptr</code>
|
|
--
|
|
-- If the pointer is null, it simply marshalls the integer '0'. Otherwise,
|
|
-- it uses a referent id followed by the integer.
|
|
--
|
|
--@param int32 The value of the integer pointer
|
|
--@return A string representing the marshalled data.
|
|
function marshall_int32_ptr(int32)
|
|
local result
|
|
|
|
stdnse.debug4("MSRPC: Entering marshall_int32_ptr()")
|
|
result = marshall_ptr(ALL, marshall_int32, {int32}, int32)
|
|
stdnse.debug4("MSRPC: Leaving marshall_int32_ptr()")
|
|
|
|
return result
|
|
end
|
|
|
|
--- Marshall a pointer to an int16
|
|
--
|
|
-- <code> [in,out] uint16 *ptr</code>
|
|
--
|
|
-- If the pointer is null, it simply marshalls the integer '0'. Otherwise,
|
|
-- it uses a referent id followed by the integer.
|
|
--
|
|
--@param int16 The value of the integer pointer
|
|
--@param pad [optional] If set, will align the insert on 4-byte boundaries. Default: true.
|
|
--@return A string representing the marshalled data.
|
|
function marshall_int16_ptr(int16, pad)
|
|
local result
|
|
|
|
stdnse.debug4("MSRPC: Entering marshall_int16_ptr()")
|
|
result = marshall_ptr(ALL, marshall_int16, {int16, pad}, int16)
|
|
stdnse.debug4("MSRPC: Leaving marshall_int16_ptr()")
|
|
|
|
return result
|
|
end
|
|
|
|
--- Marshall a pointer to an int8
|
|
--
|
|
-- <code> [in,out] uint8 *ptr</code>
|
|
--
|
|
-- If the pointer is null, it simply marshalls the integer '0'. Otherwise,
|
|
-- it uses a referent id followed by the integer.
|
|
--
|
|
--@param int8 The value of the integer pointer
|
|
--@param pad [optional] If set, will align the insert on 4-byte boundaries. Default: true.
|
|
--@return A string representing the marshalled data.
|
|
function marshall_int8_ptr(int8, pad)
|
|
local result
|
|
|
|
stdnse.debug4("MSRPC: Entering marshall_int8_ptr()")
|
|
result = marshall_ptr(ALL, marshall_int8, {int8, pad}, int8)
|
|
stdnse.debug4("MSRPC: Leaving marshall_int8_ptr()")
|
|
|
|
return result
|
|
end
|
|
|
|
--- Unmarshall a pointer to an int32. See <code>marshall_int32_ptr</code> for more information.
|
|
--
|
|
--@param data The data packet.
|
|
--@param pos The position within the data.
|
|
--@return (pos, int32) The new position, and the value.
|
|
function unmarshall_int32_ptr(data, pos)
|
|
local result
|
|
|
|
stdnse.debug4("MSRPC: Entering unmarshall_int32_ptr()")
|
|
pos, result = unmarshall_ptr(ALL, data, pos, unmarshall_int32, {})
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_int32_ptr()")
|
|
|
|
return pos, result
|
|
end
|
|
|
|
--- Unmarshall a pointer to an int16. See <code>marshall_int16_ptr</code> for more information.
|
|
--
|
|
--@param data The data packet.
|
|
--@param pos The position within the data.
|
|
--@param pad [optional] If set, will remove extra bytes to align the packet, Default: true
|
|
--@return (pos, int16) The new position, and the value.
|
|
function unmarshall_int16_ptr(data, pos, pad)
|
|
local result
|
|
|
|
stdnse.debug4("MSRPC: Entering unmarshall_int16_ptr()")
|
|
pos, result = unmarshall_ptr(ALL, data, pos, unmarshall_int16, {pad})
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_int16_ptr()")
|
|
|
|
return pos, result
|
|
end
|
|
|
|
--- Unmarshall a pointer to an int8. See <code>marshall_int8_ptr</code> for more information.
|
|
--
|
|
--@param data The data packet.
|
|
--@param pos The position within the data.
|
|
--@param pad [optional] If set, will remove extra bytes to align the packet, Default: true
|
|
--@return (pos, int8) The new position, and the value.
|
|
function unmarshall_int8_ptr(data, pos, pad)
|
|
local result
|
|
|
|
stdnse.debug4("MSRPC: Entering unmarshall_int8_ptr()")
|
|
pos, result = unmarshall_ptr(ALL, data, pos, unmarshall_int8, {pad})
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_int8_ptr()")
|
|
|
|
return pos, result
|
|
end
|
|
|
|
--- Marshall an array of int8s, with an optional max_length set.
|
|
--
|
|
--@param data The array to marshall, as a string. Cannot be nil.
|
|
--@param max_length [optional] The maximum length of the buffer. Default: the length of
|
|
-- <code>data</code>.
|
|
--@return A string representing the marshalled data.
|
|
function marshall_int8_array(data, max_length)
|
|
local result = ""
|
|
|
|
stdnse.debug4("MSRPC: Entering marshall_int8_array()")
|
|
|
|
if(max_length == nil) then
|
|
max_length = #data
|
|
end
|
|
|
|
result = result .. bin.pack("<IIIA", max_length, 0, #data, data)
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_int8_array()")
|
|
|
|
return result
|
|
end
|
|
|
|
--- Unmarshall an array of int8s.
|
|
--
|
|
--@param data The data packet.
|
|
--@param pos The position within the data.
|
|
--@param pad [optional] If set to true, will align data on 4-byte boundaries. Default:
|
|
-- true.
|
|
--@return (pos, str) The position, and the resulting string, which cannot be nil.
|
|
function unmarshall_int8_array(data, pos, pad)
|
|
local max, offset, actual
|
|
local str
|
|
|
|
stdnse.debug4("MSRPC: Entering unmarshall_int8_array()")
|
|
|
|
pos, max, offset, actual = bin.unpack("<III", data, pos)
|
|
if(actual == nil) then
|
|
stdnse.debug1("MSRPC: ERROR: Ran off the end of a packet in unmarshall_int8_array(). Please report!")
|
|
end
|
|
|
|
pos, str = bin.unpack("<A"..actual, data, pos)
|
|
if(str == nil) then
|
|
stdnse.debug1("MSRPC: ERROR: Ran off the end of a packet in unmarshall_int8_array() [2]. Please report!")
|
|
end
|
|
|
|
-- Do the alignment (note the "- 1", it's there because of 1-based arrays)
|
|
if(pad == nil or pad == true) then
|
|
while(((pos - 1) % 4) ~= 0) do
|
|
pos = pos + 1
|
|
end
|
|
end
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_int8_array()")
|
|
|
|
return pos, str
|
|
end
|
|
|
|
--- Marshall a pointer to an array of int8s.
|
|
--
|
|
--@param data The array to marshall, as a string. Can be nil.
|
|
--@param max_length [optional] The maximum length of the buffer. Default: the length of
|
|
-- <code>data</code>.
|
|
--@return A string representing the marshalled data.
|
|
function marshall_int8_array_ptr(data, max_length)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering marshall_int8_array_ptr()")
|
|
|
|
result = marshall_ptr(ALL, marshall_int8_array, {data, max_length}, data)
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_int8_array_ptr()")
|
|
return result
|
|
end
|
|
|
|
--- Unmarshall a pointer to an array of int8s. By default, aligns the result to 4-byte
|
|
-- boundaries.
|
|
--
|
|
--@param data The data packet.
|
|
--@param pos The position within the data.
|
|
--@param pad [optional] If set to true, will align data on 4-byte boundaries. Default:
|
|
-- true.
|
|
--@return (pos, str) The position, and the resulting string, which cannot be nil.
|
|
function unmarshall_int8_array_ptr(data, pos, pad)
|
|
local str
|
|
stdnse.debug4("MSRPC: Entering unmarshall_int8_array_ptr()")
|
|
|
|
pos, str = unmarshall_ptr(ALL, data, pos, unmarshall_int8_array, {pad})
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_int8_array_ptr()")
|
|
return pos, str
|
|
end
|
|
|
|
--- Unmarshall an array of int32s.
|
|
--
|
|
--@param data The data packet.
|
|
--@param pos The position within the data.
|
|
--@return (pos, str) The position, and the resulting string, which cannot be nil.
|
|
function unmarshall_int32_array(data, pos, count)
|
|
local maxcount
|
|
local result = {}
|
|
|
|
pos, maxcount = unmarshall_int32(data, pos)
|
|
|
|
for i = 1, count, 1 do
|
|
pos, result[i] = unmarshall_int32(data, pos)
|
|
end
|
|
|
|
return pos, result
|
|
end
|
|
|
|
--- Unmarshall a pointer to an array of int32s.
|
|
--
|
|
--@param data The data packet.
|
|
--@param pos The position within the data.
|
|
--@return (pos, str) The position, and the resulting string, which cannot be nil.
|
|
function unmarshall_int32_array_ptr(data, pos)
|
|
local count, array
|
|
|
|
pos, count = unmarshall_int32(data, pos)
|
|
pos, array = unmarshall_ptr(ALL, data, pos, unmarshall_int32_array, {count})
|
|
|
|
return pos, array
|
|
end
|
|
|
|
---Marshalls an NTTIME.
|
|
--
|
|
-- This is sent as the number of 1/10 microseconds since 1601; however the
|
|
-- internal representation is the number of seconds since 1970. Because doing
|
|
-- conversions in code is annoying, the user will never have to understand
|
|
-- anything besides seconds since 1970.
|
|
--
|
|
--@param time The time, in seconds since 1970.
|
|
--@return A string representing the marshalled data.
|
|
function marshall_NTTIME(time)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering marshall_NTTIME()")
|
|
|
|
if(time == 0) then
|
|
result = bin.pack("<L", 0)
|
|
else
|
|
result = bin.pack("<L", (time + 11644473600) * 10000000)
|
|
end
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_NTTIME()")
|
|
return result
|
|
end
|
|
|
|
---Unmarshalls an NTTIME. See <code>marshall_NTTIME</code> for more information.
|
|
--
|
|
--@param data The data packet.
|
|
--@param pos The position within the data.
|
|
--@return (pos, time) The new position, and the time in seconds since 1970.
|
|
function unmarshall_NTTIME(data, pos)
|
|
local time
|
|
stdnse.debug4("MSRPC: Entering unmarshall_NTTIME()")
|
|
|
|
pos, time = bin.unpack("<L", data, pos)
|
|
if(time == nil) then
|
|
stdnse.debug1("MSRPC: ERROR: Ran off the end of a packet in unmarshall_NTTIME(). Please report!")
|
|
end
|
|
|
|
if(time ~= 0) then
|
|
time = (time / 10000000) - 11644473600
|
|
end
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_NTTIME()")
|
|
return pos, time
|
|
end
|
|
|
|
---Marshalls an NTTIME*.
|
|
--
|
|
--@param time The time, in seconds since 1970.
|
|
--@return A string representing the marshalled data.
|
|
function marshall_NTTIME_ptr(time)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering marshall_NTTIME_ptr()")
|
|
|
|
result = marshall_ptr(ALL, marshall_NTTIME, {time}, time)
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_NTTIME_ptr()")
|
|
return result
|
|
end
|
|
|
|
---Unmarshalls an <code>NTTIME*</code>.
|
|
--
|
|
--@param data The data packet.
|
|
--@param pos The position within the data.
|
|
--@return (pos, time) The new position, and the time in seconds since 1970.
|
|
function unmarshall_NTTIME_ptr(data, pos)
|
|
local time
|
|
stdnse.debug4("MSRPC: Entering unmarshall_NTTIME_ptr()")
|
|
|
|
pos, time = unmarshall_ptr(ALL, data, pos, unmarshall_NTTIME, {})
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_NTTIME_ptr()")
|
|
return pos, time
|
|
end
|
|
|
|
---Unmarshall a SYSTEMTIME structure, converting it to a standard representation.
|
|
--
|
|
--The structure is as follows:
|
|
--
|
|
-- <code>
|
|
-- typedef struct _SYSTEMTIME {
|
|
-- WORD wYear;
|
|
-- WORD wMonth;
|
|
-- WORD wDayOfWeek;
|
|
-- WORD wDay;
|
|
-- WORD wHour;
|
|
-- WORD wMinute;
|
|
-- WORD wSecond;
|
|
-- WORD wMilliseconds;
|
|
-- } SYSTEMTIME
|
|
-- </code>
|
|
--
|
|
--@param data The data packet.
|
|
--@param pos The position within the data.
|
|
--@return (pos, time) The new position, and the time in seconds since 1970.
|
|
function unmarshall_SYSTEMTIME(data, pos)
|
|
local date = {}
|
|
local _
|
|
|
|
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!")
|
|
end
|
|
|
|
return pos, os.time(date)
|
|
end
|
|
|
|
---Unmarshalls a <code>hyper</code>.
|
|
--
|
|
-- I have no idea what a <code>hyper</code> is, just that it seems to be a
|
|
-- 64-bit data type used for measuring time, and that the units happen to be
|
|
-- negative microseconds. This function converts the value to seconds and
|
|
-- returns it.
|
|
--
|
|
--@param data The data packet.
|
|
--@param pos The position within the data.
|
|
--@return (pos, val) The new position, and the result in seconds.
|
|
function unmarshall_hyper(data, pos)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering unmarshall_hyper()")
|
|
|
|
pos, result = unmarshall_int64(data, pos)
|
|
result = result / -10000000
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_hyper()")
|
|
return pos, result
|
|
end
|
|
|
|
---Marshall an entry in a table.
|
|
--
|
|
-- Basically, converts the string to a number based on the entries in
|
|
-- <code>table</code> before sending. Multiple values can be ORed together
|
|
-- (like flags) by separating them with pipes ("|").
|
|
--
|
|
--@param val The value to look up. Can be multiple values with pipes between,
|
|
-- e.g. "A|B|C".
|
|
--@param table The table to use for lookups. The keys should be the names, and
|
|
-- the values should be the numbers.
|
|
--@return A string representing the marshalled data.
|
|
local function marshall_Enum32(val, table)
|
|
local result = 0
|
|
stdnse.debug4("MSRPC: Entering marshall_Enum32()")
|
|
|
|
local vals = stdnse.strsplit("|", val)
|
|
local i
|
|
|
|
for i = 1, #vals, 1 do
|
|
result = bit.bor(result, table[vals[i]])
|
|
end
|
|
|
|
result = marshall_int32(result)
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_Enum32()")
|
|
return result
|
|
end
|
|
|
|
---Unmarshall an entry in a table. Basically, converts the next int32 in the buffer to a string
|
|
-- based on the entries in <code>table</code> before returning.
|
|
--
|
|
--@param data The data packet.
|
|
--@param pos The position within the data.
|
|
--@param table The table to use for lookups. The keys should be the names, and the values should be
|
|
-- the numbers.
|
|
--@param default The default value to return if the lookup was unsuccessful.
|
|
--@return (pos, policy_handle) The new position, and a table representing the policy_handle.
|
|
local function unmarshall_Enum32(data, pos, table, default)
|
|
stdnse.debug4("MSRPC: Entering unmarshall_Enum32()")
|
|
|
|
if(default == nil) then
|
|
default = "<unknown>"
|
|
end
|
|
|
|
local pos, val = unmarshall_int32(data, pos)
|
|
|
|
for i, v in pairs(table) do
|
|
if(v == val) then
|
|
return pos, i
|
|
end
|
|
end
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_Enum32()")
|
|
return pos, default
|
|
end
|
|
|
|
---Unmarshall an entry in a table. Basically, converts the next int16 in the buffer to a string
|
|
-- based on the entries in <code>table</code> before returning.
|
|
--
|
|
--@param data The data packet.
|
|
--@param pos The position within the data.
|
|
--@param table The table to use for lookups. The keys should be the names, and the values should be
|
|
-- the numbers.
|
|
--@param default The default value to return if the lookup was unsuccessful.
|
|
--@param pad [optional] If set, will ensure that we end up on an even multiple of 4. Default: true.
|
|
--@return (pos, policy_handle) The new position, and a table representing the policy_handle.
|
|
local function unmarshall_Enum16(data, pos, table, default, pad)
|
|
stdnse.debug4("MSRPC: Entering unmarshall_Enum16()")
|
|
|
|
if(default == nil) then
|
|
default = "<unknown>"
|
|
end
|
|
|
|
local pos, val = unmarshall_int16(data, pos, pad)
|
|
|
|
for i, v in pairs(table) do
|
|
if(v == val) then
|
|
return pos, i
|
|
end
|
|
end
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_Enum16()")
|
|
return pos, default
|
|
end
|
|
|
|
---Marshall an entry in a table.
|
|
--
|
|
-- Basically, converts the string to a number based on the entries in
|
|
-- <code>table</code> before sending. Multiple values can be ORed together
|
|
-- (like flags) by separating them with pipes ("|").
|
|
--
|
|
--@param val The value to look up. Can be multiple values with pipes between,
|
|
-- e.g. "A|B|C".
|
|
--@param table The table to use for lookups. The keys should be the names, and
|
|
-- the values should be the numbers.
|
|
--@param pad [optional] If set, will ensure that we end up on an even multiple of 4. Default: true.
|
|
--@return A string representing the marshalled data.
|
|
local function marshall_Enum8(val, table, pad)
|
|
local result = 0
|
|
stdnse.debug4("MSRPC: Entering marshall_Enum8()")
|
|
|
|
local vals = stdnse.strsplit("|", val)
|
|
local i
|
|
|
|
for i = 1, #vals, 1 do
|
|
result = bit.bor(result, table[vals[i]])
|
|
end
|
|
|
|
result = marshall_int8(result, pad)
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_Enum8()")
|
|
return result
|
|
end
|
|
|
|
|
|
|
|
---Similar to <code>unmarshall_Enum32</code>, except it'll return every value that could be ANDed together to
|
|
-- create the resulting value (except a 0 value). This is effective for parsing flag data types.
|
|
--@param data The data packet.
|
|
--@param pos The position within the data.
|
|
--@param table The table to use for lookups. The keys should be the names, and the values should be
|
|
-- the numbers.
|
|
--@return (pos, array) The new position, and a table representing the enumeration values.
|
|
local function unmarshall_Enum32_array(data, pos, table)
|
|
local array = {}
|
|
local i, v
|
|
local val
|
|
stdnse.debug4("MSRPC: Entering unmarshall_Enum32_array()")
|
|
|
|
pos, val = unmarshall_int32(data, pos)
|
|
|
|
for i, v in pairs(table) do
|
|
if(bit.band(v, val) ~= 0) then
|
|
array[#array + 1] = i
|
|
end
|
|
end
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_Enum32_array()")
|
|
return pos, array
|
|
end
|
|
|
|
---Unmarshall raw data.
|
|
--@param data The data packet.
|
|
--@param pos The position within the data.
|
|
--@param length The number of bytes to unmarshall.
|
|
--@return (pos, data) The new position in the packet, and a string representing the raw data.
|
|
function unmarshall_raw(data, pos, length)
|
|
local val
|
|
stdnse.debug4("MSRPC: Entering unmarshall_raw()")
|
|
|
|
pos, val = bin.unpack(string.format("A%d", length), data, pos)
|
|
if(val == nil) then
|
|
stdnse.debug1("MSRPC: ERROR: Ran off the end of a packet in unmarshall_raw(). Please report!")
|
|
end
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_raw()")
|
|
return pos, val
|
|
end
|
|
|
|
|
|
-------------------------------------
|
|
-- MISC
|
|
-- (dependencies: n/a)
|
|
-------------------------------------
|
|
|
|
---Marshalls a GUID, which looks like this:
|
|
--
|
|
--<code>
|
|
-- typedef [public,noprint,gensize,noejs] struct {
|
|
-- uint32 time_low;
|
|
-- uint16 time_mid;
|
|
-- uint16 time_hi_and_version;
|
|
-- uint8 clock_seq[2];
|
|
-- uint8 node[6];
|
|
-- } GUID;
|
|
--</code>
|
|
--
|
|
--@param guid A table representing the GUID.
|
|
--@return A string representing the marshalled data.
|
|
local function marshall_guid(guid)
|
|
local result
|
|
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'])
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_guid()")
|
|
return result
|
|
end
|
|
|
|
---Unmarshalls a GUID. See <code>marshall_guid</code> for the structure.
|
|
--
|
|
--@param data The data packet.
|
|
--@param pos The position within the data.
|
|
--@return (pos, result) The new position in <code>data</code>, and a table representing the datatype.
|
|
local function unmarshall_guid(data, pos)
|
|
local 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(guid['node'] == nil) then
|
|
stdnse.debug1("MSRPC: ERROR: Ran off the end of a packet in unmarshall_guid(). Please report!")
|
|
end
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_guid()")
|
|
return pos, guid
|
|
end
|
|
|
|
---Marshalls a policy_handle, which looks like this:
|
|
--
|
|
--<code>
|
|
-- typedef struct {
|
|
-- uint32 handle_type;
|
|
-- GUID uuid;
|
|
-- } policy_handle;
|
|
--</code>
|
|
--
|
|
--@param policy_handle The policy_handle to marshall.
|
|
--@return A string representing the marshalled data.
|
|
function marshall_policy_handle(policy_handle)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering marshall_policy_handle()")
|
|
|
|
result = bin.pack("<IA", policy_handle['handle_type'], marshall_guid(policy_handle['uuid']))
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_policy_handle()")
|
|
return result
|
|
end
|
|
|
|
---Unmarshalls a policy_handle. See <code>marshall_policy_handle</code> for the structure.
|
|
--
|
|
--@param data The data packet.
|
|
--@param pos The position within the data.
|
|
--@return (pos, result) The new position in <code>data</code>, and a table representing the datatype.
|
|
function unmarshall_policy_handle(data, pos)
|
|
local policy_handle = {}
|
|
stdnse.debug4("MSRPC: Entering unmarshall_policy_handle()")
|
|
|
|
pos, policy_handle['handle_type'] = unmarshall_int32(data, pos)
|
|
pos, policy_handle['uuid'] = unmarshall_guid(data, pos)
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_policy_handle()")
|
|
return pos, policy_handle
|
|
end
|
|
|
|
----------------------------------
|
|
-- SECURITY
|
|
-- (dependencies: MISC)
|
|
----------------------------------
|
|
|
|
---Unmarshall a dom_sid struct
|
|
--
|
|
--<code>
|
|
-- typedef [public,gensize,noprint,noejs,nosize] struct {
|
|
-- uint8 sid_rev_num; /**< SID revision number */
|
|
-- [range(0,15)] int8 num_auths; /**< Number of sub-authorities */
|
|
-- uint8 id_auth[6]; /**< Identifier Authority */
|
|
-- uint32 sub_auths[num_auths];
|
|
-- } dom_sid;
|
|
--</code>
|
|
--
|
|
--@param data The data being processed.
|
|
--@param pos The position within <code>data</code>.
|
|
--@return (pos, result) The new position in <code>data</code>, and a table representing the datatype.
|
|
function unmarshall_dom_sid2(data, pos)
|
|
local i
|
|
|
|
-- Read the SID from the packet
|
|
local sid = {}
|
|
pos, sid['count'] = unmarshall_int32(data, pos)
|
|
pos, sid['sid_rev_num'] = 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)
|
|
pos, sid['authority_high'], sid['authority_low'] = bin.unpack(">SI", data, pos)
|
|
if(sid['authority_low'] == nil) then
|
|
stdnse.debug1("MSRPC: ERROR: Ran off the end of a packet in unmarshall_dom_sid2(). Please report!")
|
|
end
|
|
sid['authority'] = bit.bor(bit.lshift(sid['authority_high'], 32), sid['authority_low'])
|
|
|
|
sid['sub_auths'] = {}
|
|
for i = 1, sid['num_auths'], 1 do
|
|
pos, sid['sub_auths'][i] = unmarshall_int32(data, pos)
|
|
end
|
|
|
|
-- Convert the SID to a string
|
|
local result = string.format("S-%u-%u", sid['sid_rev_num'], sid['authority'])
|
|
for i = 1, sid['num_auths'], 1 do
|
|
result = result .. string.format("-%u", sid['sub_auths'][i])
|
|
end
|
|
|
|
return pos, result
|
|
end
|
|
|
|
---Unmarshall a pointer to a <code>dom_sid2</code> struct. See the <code>unmarshall_dom_sid2</code> function
|
|
-- for more information.
|
|
--
|
|
--@param data The data being processed.
|
|
--@param pos The position within <code>data</code>.
|
|
--@return (pos, result) The new position in <code>data</code>, and a table representing the datatype.
|
|
function unmarshall_dom_sid2_ptr(data, pos)
|
|
return unmarshall_ptr(ALL, data, pos, unmarshall_dom_sid2, {})
|
|
end
|
|
|
|
---Marshall a dom_sid struct
|
|
--
|
|
--<code>
|
|
-- typedef [public,gensize,noprint,noejs,nosize] struct {
|
|
-- uint8 sid_rev_num; /**< SID revision number */
|
|
-- [range(0,15)] int8 num_auths; /**< Number of sub-authorities */
|
|
-- uint8 id_auth[6]; /**< Identifier Authority */
|
|
-- uint32 sub_auths[num_auths];
|
|
-- } dom_sid;
|
|
--</code>
|
|
--
|
|
--@return A string representing the marshalled data.
|
|
function marshall_dom_sid2(sid)
|
|
local i
|
|
local pos_next
|
|
local sid_array = {}
|
|
local result = ""
|
|
stdnse.debug4("MSRPC: Entering marshall_dom_sid2()")
|
|
|
|
|
|
if(string.find(sid, "^S%-") == nil) then
|
|
stdnse.debug1("MSRPC: ERROR: Invalid SID encountered: %s\n", sid)
|
|
return nil
|
|
end
|
|
if(string.find(sid, "%-%d+$") == nil) then
|
|
stdnse.debug1("MSRPC: ERROR: Invalid SID encountered: %s\n", sid)
|
|
return nil
|
|
end
|
|
|
|
local pos = 3
|
|
|
|
pos_next = string.find(sid, "-", pos)
|
|
sid_array['sid_rev_num'] = string.sub(sid, pos, pos_next - 1)
|
|
|
|
pos = pos_next + 1
|
|
pos_next = string.find(sid, "-", pos)
|
|
sid_array['authority_high'] = bit.rshift(string.sub(sid, pos, pos_next - 1), 32)
|
|
sid_array['authority_low'] = bit.band(string.sub(sid, pos, pos_next - 1), 0xFFFFFFFF)
|
|
|
|
sid_array['sub_auths'] = {}
|
|
i = 1
|
|
repeat
|
|
pos = pos_next + 1
|
|
pos_next = string.find(sid, "-", pos)
|
|
if(pos_next == nil) then
|
|
sid_array['sub_auths'][i] = string.sub(sid, pos)
|
|
else
|
|
sid_array['sub_auths'][i] = string.sub(sid, pos, pos_next - 1)
|
|
end
|
|
i = i + 1
|
|
until pos_next == nil
|
|
sid_array['num_auths'] = i - 1
|
|
|
|
result = bin.pack("<I", sid_array['num_auths'])
|
|
result = result .. bin.pack("<CC>SI", sid_array['sid_rev_num'], sid_array['num_auths'], sid_array['authority_high'], sid_array['authority_low'])
|
|
for i = 1, sid_array['num_auths'], 1 do
|
|
result = result .. bin.pack("<I", sid_array['sub_auths'][i])
|
|
end
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_dom_sid2()")
|
|
return result
|
|
end
|
|
|
|
|
|
|
|
|
|
----------------------------------
|
|
-- LSA
|
|
-- (dependencies: SECURITY)
|
|
----------------------------------
|
|
|
|
|
|
---A <code>lsa_String</code> is a buffer that holds a non-null-terminated string. It can have a max size that's different
|
|
-- from its actual size. I tagged this one as "internal" because I don't want the user to have to provide
|
|
-- a "location".
|
|
--
|
|
-- This is the format:
|
|
--
|
|
--<code>
|
|
-- typedef [public,noejs] struct {
|
|
-- [value(2*strlen_m(string))] uint16 length;
|
|
-- [value(2*strlen_m(string))] uint16 size;
|
|
-- [charset(UTF16),size_is(size/2),length_is(length/2)] uint16 *string;
|
|
-- } lsa_String;
|
|
--</code>
|
|
--
|
|
--@param location The part of the pointer wanted, either HEAD (for the referent_id), BODY
|
|
-- (for the pointer data), or ALL (for both together). Generally, unless the
|
|
-- referent_id is split from the data (for example, in an array), you will want
|
|
-- ALL.
|
|
--@param str The string to marshall
|
|
--@param max_length [optional] The maximum size of the buffer, in characters, including the null terminator.
|
|
-- Defaults to the length of the string, including the null.
|
|
--@param do_null [optional] Appends a null to the end of the string. Default false.
|
|
--@return A string representing the marshalled data.
|
|
local function marshall_lsa_String_internal(location, str, max_length, do_null)
|
|
local length
|
|
local result = ""
|
|
stdnse.debug4("MSRPC: Entering marshall_lsa_String_internal()")
|
|
|
|
-- Handle default max lengths
|
|
if(max_length == nil) then
|
|
if(str == nil) then
|
|
max_length = 0
|
|
else
|
|
max_length = #str
|
|
end
|
|
end
|
|
|
|
if(str == nil) then
|
|
length = 0
|
|
else
|
|
length = #str
|
|
end
|
|
|
|
if(do_null == nil) then
|
|
do_null = false
|
|
end
|
|
|
|
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))
|
|
end
|
|
|
|
if(location == BODY or location == ALL) then
|
|
result = result .. bin.pack("<A", marshall_ptr(BODY, marshall_unicode, {str, do_null, max_length}, str))
|
|
end
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_lsa_String_internal()")
|
|
return result
|
|
end
|
|
|
|
---Unmarshall a <code>lsa_String</code> value. See <code>marshall_lsa_String_internal</code> for more information.
|
|
--
|
|
--@param location The part of the pointer wanted, either HEAD (for the data itself), BODY
|
|
-- (for nothing, since this isn't a pointer), or ALL (for the data). Generally, unless the
|
|
-- referent_id is split from the data (for example, in an array), you will want
|
|
-- ALL.
|
|
--@param data The data packet.
|
|
--@param pos The position within the data.
|
|
--@param result This is required when unmarshalling the BODY section, which always comes after
|
|
-- unmarshalling the HEAD. It is the result returned for this parameter during the
|
|
-- HEAD unmarshall. If the referent_id was '0', then this function doesn't unmarshall
|
|
-- anything.
|
|
--@return (pos, str) The new position, and the unmarshalled string.
|
|
local function unmarshall_lsa_String_internal(location, data, pos, result)
|
|
local length, size
|
|
local str
|
|
stdnse.debug4("MSRPC: Entering unmarshall_lsa_String_internal()")
|
|
|
|
if(location == HEAD or location == ALL) then
|
|
pos, length = unmarshall_int16(data, pos, false)
|
|
pos, size = unmarshall_int16(data, pos, false)
|
|
|
|
pos, str = unmarshall_ptr(HEAD, data, pos, unmarshall_unicode, {false})
|
|
end
|
|
|
|
if(location == BODY or location == ALL) then
|
|
pos, str = unmarshall_ptr(BODY, data, pos, unmarshall_unicode, {false}, result)
|
|
end
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_lsa_String_internal()")
|
|
return pos, str
|
|
end
|
|
|
|
---Public version of <code>marshall_lsa_String_internal</code> -- see that function on that for more information.
|
|
-- This version doesn't require a <code>location</code>, so it's suitable to be a public function.
|
|
--
|
|
--@param str The string to marshall
|
|
--@param max_length [optional] The maximum size of the buffer, in characters, including the null terminator.
|
|
-- Defaults to the length of the string, including the null.
|
|
--@return A string representing the marshalled data.
|
|
function marshall_lsa_String(str, max_length)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering marshall_lsa_String()")
|
|
|
|
result = marshall_lsa_String_internal(ALL, str, max_length)
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_lsa_String()")
|
|
return result
|
|
end
|
|
|
|
---Marshall an array of lsa_String objects. This is a perfect demonstration of how to use
|
|
-- <code>marshall_array</code>.
|
|
--
|
|
--@param strings The array of strings to marshall
|
|
--@return A string representing the marshalled data.
|
|
function marshall_lsa_String_array(strings)
|
|
local array = {}
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering marshall_lsa_String_array()")
|
|
|
|
for i = 1, #strings, 1 do
|
|
array[i] = {}
|
|
array[i]['func'] = marshall_lsa_String_internal
|
|
array[i]['args'] = {strings[i]}
|
|
end
|
|
|
|
result = marshall_array(array)
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_lsa_String_array()")
|
|
return result
|
|
end
|
|
|
|
---Basically the same as <code>marshall_lsa_String_array</code>, except it has a different structure
|
|
--
|
|
--@param strings The array of strings to marshall
|
|
function marshall_lsa_String_array2(strings)
|
|
local array = {}
|
|
local result
|
|
|
|
for i = 1, #strings, 1 do
|
|
array[i] = {}
|
|
array[i]['func'] = marshall_lsa_String_internal
|
|
array[i]['args'] = {strings[i], nil, nil, false}
|
|
end
|
|
|
|
result = marshall_int32(1000) -- Max length
|
|
result = result .. marshall_int32(0) -- Offset
|
|
result = result .. marshall_array(array)
|
|
|
|
--require 'nsedebug'
|
|
--nsedebug.print_hex(result)
|
|
--os.exit()
|
|
return result
|
|
end
|
|
|
|
---Table of SID types.
|
|
local lsa_SidType =
|
|
{
|
|
SID_NAME_USE_NONE = 0, -- NOTUSED
|
|
SID_NAME_USER = 1, -- user
|
|
SID_NAME_DOM_GRP = 2, -- domain group
|
|
SID_NAME_DOMAIN = 3, -- domain: don't know what this is
|
|
SID_NAME_ALIAS = 4, -- local group
|
|
SID_NAME_WKN_GRP = 5, -- well-known group
|
|
SID_NAME_DELETED = 6, -- deleted account: needed for c2 rating
|
|
SID_NAME_INVALID = 7, -- invalid account
|
|
SID_NAME_UNKNOWN = 8, -- oops.
|
|
SID_NAME_COMPUTER = 9 -- machine
|
|
}
|
|
---String versions of SID types
|
|
local lsa_SidType_str =
|
|
{
|
|
SID_NAME_USE_NONE = "n/a",
|
|
SID_NAME_USER = "User",
|
|
SID_NAME_DOM_GRP = "Domain group",
|
|
SID_NAME_DOMAIN = "Domain",
|
|
SID_NAME_ALIAS = "Local group",
|
|
SID_NAME_WKN_GRP = "Well known group",
|
|
SID_NAME_DELETED = "Deleted account",
|
|
SID_NAME_INVALID = "Invalid account",
|
|
SID_NAME_UNKNOWN = "Unknown account",
|
|
SID_NAME_COMPUTER = "Machine"
|
|
}
|
|
---Marshall a <code>lsa_SidType</code>. This datatype is tied to the table above with that
|
|
-- name.
|
|
--
|
|
--@param sid_type The value to marshall, as a string
|
|
--@return The marshalled integer representing the given value, or <code>nil</code> if it wasn't
|
|
-- found.
|
|
function marshall_lsa_SidType(sid_type)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering marshall_lsa_SidType()")
|
|
|
|
result = marshall_Enum32(sid_type, lsa_SidType)
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_lsa_SidType()")
|
|
return result
|
|
end
|
|
|
|
---Unmarshall a <code>lsa_SidType</code>. This datatype is tied to the table with that name.
|
|
--
|
|
--@param data The data packet.
|
|
--@param pos The position within the data.
|
|
--@return (pos, str) The new position, and the string representing the datatype.
|
|
function unmarshall_lsa_SidType(data, pos)
|
|
local str
|
|
stdnse.debug4("MSRPC: Entering unmarshall_lsa_SidType()")
|
|
|
|
pos, str = unmarshall_Enum16(data, pos, lsa_SidType)
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_lsa_SidType()")
|
|
return pos, str
|
|
end
|
|
|
|
---Convert a <code>lsa_SidType</code> value to a string that can be shown to the user. This is
|
|
-- based on the <code>_str</code> table.
|
|
--
|
|
--@param val The string value (returned by the <code>unmarshall_</code> function) to convert.
|
|
--@return A string suitable for displaying to the user, or <code>nil</code> if it wasn't found.
|
|
function lsa_SidType_tostr(val)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering lsa_SidType_tostr()")
|
|
|
|
result = lsa_SidType_str[val]
|
|
|
|
stdnse.debug4("MSRPC: Leaving lsa_SidType_tostr()")
|
|
return result
|
|
end
|
|
|
|
---LSA name levels.
|
|
local lsa_LookupNamesLevel =
|
|
{
|
|
LOOKUP_NAMES_ALL = 1,
|
|
LOOKUP_NAMES_DOMAINS_ONLY = 2,
|
|
LOOKUP_NAMES_PRIMARY_DOMAIN_ONLY = 3,
|
|
LOOKUP_NAMES_UPLEVEL_TRUSTS_ONLY = 4,
|
|
LOOKUP_NAMES_FOREST_TRUSTS_ONLY = 5,
|
|
LOOKUP_NAMES_UPLEVEL_TRUSTS_ONLY2 = 6
|
|
}
|
|
---LSA name level strings.
|
|
local lsa_LookupNamesLevel_str =
|
|
{
|
|
LOOKUP_NAMES_ALL = "All",
|
|
LOOKUP_NAMES_DOMAINS_ONLY = "Domains only",
|
|
LOOKUP_NAMES_PRIMARY_DOMAIN_ONLY = "Primary domains only",
|
|
LOOKUP_NAMES_UPLEVEL_TRUSTS_ONLY = "Uplevel trusted domains only",
|
|
LOOKUP_NAMES_FOREST_TRUSTS_ONLY = "Forest trusted domains only",
|
|
LOOKUP_NAMES_UPLEVEL_TRUSTS_ONLY2 = "Uplevel trusted domains only (2)"
|
|
}
|
|
---Marshall a <code>lsa_LookupNamesLevel</code>. This datatype is tied to the table above with that
|
|
-- name.
|
|
--
|
|
--@param names_level The value to marshall, as a string
|
|
--@return The marshalled integer representing the given value, or <code>nil</code> if it wasn't
|
|
-- found.
|
|
function marshall_lsa_LookupNamesLevel(names_level)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering marshall_lsa_LookupNamesLevel()")
|
|
|
|
result = marshall_Enum32(names_level, lsa_LookupNamesLevel)
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_lsa_LookupNamesLevel()")
|
|
return result
|
|
end
|
|
|
|
---Unmarshall a <code>lsa_LookupNamesLevel</code>. This datatype is tied to the table with that name.
|
|
--
|
|
--@param data The data packet.
|
|
--@param pos The position within the data.
|
|
--@return (pos, str) The new position, and the string representing the datatype.
|
|
function unmarshall_lsa_LookupNamesLevel(data, pos)
|
|
local str
|
|
stdnse.debug4("MSRPC: Entering unmarshall_lsa_LookupNamesLevel()")
|
|
|
|
pos, str = unmarshall_Enum32(data, pos, lsa_LookupNamesLevel)
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_lsa_LookupNamesLevel()")
|
|
return pos, str
|
|
end
|
|
|
|
---Convert a <code>lsa_LookupNamesLevel</code> value to a string that can be shown to the user. This is
|
|
-- based on the <code>_str</code> table.
|
|
--
|
|
--@param val The string value (returned by the <code>unmarshall_</code> function) to convert.
|
|
--@return A string suitable for displaying to the user, or <code>nil</code> if it wasn't found.
|
|
function lsa_LookupNamesLevel_tostr(val)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering lsa_LookupNamesLevel_tostr()")
|
|
|
|
result = lsa_LookupNamesLevel_str[val]
|
|
|
|
stdnse.debug4("MSRPC: Leaving lsa_LookupNamesLevel_tostr()")
|
|
return result
|
|
end
|
|
|
|
---Marshall a lsa_TranslatedSid2 struct
|
|
--
|
|
--<code>
|
|
-- typedef struct {
|
|
-- lsa_SidType sid_type;
|
|
-- uint32 rid;
|
|
-- uint32 sid_index;
|
|
-- uint32 unknown;
|
|
-- } lsa_TranslatedSid2;
|
|
--</code>
|
|
--
|
|
--@param location The part of the pointer wanted, either HEAD (for the data itself), BODY
|
|
-- (for nothing, since this isn't a pointer), or ALL (for the data). Generally, unless the
|
|
-- referent_id is split from the data (for example, in an array), you will want
|
|
-- ALL.
|
|
--@param sid_type The <code>sid_type</code> value (I don't know what this means)
|
|
--@param rid The <code>rid</code> (a number representing the user)
|
|
--@param sid_index The <code>sid_index</code> value (I don't know what this means, either)
|
|
--@param unknown An unknown value (is normally 0).
|
|
--@return A string representing the marshalled data.
|
|
local function marshall_lsa_TranslatedSid2(location, sid_type, rid, sid_index, unknown)
|
|
local result = ""
|
|
stdnse.debug4("MSRPC: Entering marshall_lsa_TranslatedSid2()")
|
|
|
|
-- Set some default values
|
|
if(sid_type == nil) then sid_type = "SID_NAME_USE_NONE" end
|
|
if(rid == nil) then rid = 0 end
|
|
if(sid_index == nil) then sid_index = 0 end
|
|
if(unknown == nil) then unknown = 0 end
|
|
|
|
if(location == HEAD or location == ALL) then
|
|
result = result .. marshall_lsa_SidType(sid_type)
|
|
result = result .. marshall_int32(rid)
|
|
result = result .. marshall_int32(sid_index)
|
|
result = result .. marshall_int32(unknown)
|
|
end
|
|
|
|
if(location == BODY or location == ALL) then
|
|
end
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_lsa_TranslatedSid2()")
|
|
return result
|
|
end
|
|
|
|
---Unmarshall a lsa_TranslatedSid2 struct
|
|
--
|
|
--<code>
|
|
-- typedef struct {
|
|
-- lsa_SidType sid_type;
|
|
-- uint32 rid;
|
|
-- uint32 sid_index;
|
|
-- uint32 unknown;
|
|
-- } lsa_TranslatedSid2;
|
|
--</code>
|
|
--
|
|
--@param location The part of the pointer wanted, either HEAD (for the data itself), BODY
|
|
-- (for nothing, since this isn't a pointer), or ALL (for the data). Generally, unless the
|
|
-- referent_id is split from the data (for example, in an array), you will want
|
|
-- ALL.
|
|
--@param data The data being processed.
|
|
--@param pos The position within <code>data</code>.
|
|
--@param result This is required when unmarshalling the BODY section, which always comes after
|
|
-- unmarshalling the HEAD. It is the result returned for this parameter during the
|
|
-- HEAD unmarshall. If the referent_id was '0', then this function doesn't unmarshall
|
|
-- anything.
|
|
--@return (pos, result) The new position in <code>data</code>, and a table representing the datatype.
|
|
local function unmarshall_lsa_TranslatedSid2(location, data, pos, result)
|
|
if(result == nil) then
|
|
result = {}
|
|
end
|
|
|
|
if(location == HEAD or location == ALL) then
|
|
pos, result['sid_type'] = unmarshall_lsa_SidType(data, pos)
|
|
pos, result['rid'] = unmarshall_int32(data, pos)
|
|
pos, result['sid_index'] = unmarshall_int32(data, pos)
|
|
pos, result['unknown'] = unmarshall_int32(data, pos)
|
|
end
|
|
|
|
|
|
if(location == BODY or location == ALL) then
|
|
end
|
|
|
|
return pos, result
|
|
end
|
|
|
|
---Marshall a lsa_TranslatedName2 struct
|
|
--
|
|
--<code>
|
|
-- typedef struct {
|
|
-- lsa_SidType sid_type;
|
|
-- lsa_String name;
|
|
-- uint32 sid_index;
|
|
-- uint32 unknown;
|
|
-- } lsa_TranslatedName2;
|
|
--</code>
|
|
--
|
|
--@param location The part of the pointer wanted, either HEAD (for the data itself), BODY
|
|
-- (for nothing, since this isn't a pointer), or ALL (for the data). Generally, unless the
|
|
-- referent_id is split from the data (for example, in an array), you will want
|
|
-- ALL.
|
|
--@param sid_type The <code>sid_type</code> value, as a string
|
|
--@param name The name of the user
|
|
--@param sid_index The sid_index (I don't know what this is)
|
|
--@param unknown An unknown value, normally 0
|
|
--@return A string representing the marshalled data.
|
|
local function marshall_lsa_TranslatedName2(location, sid_type, name, sid_index, unknown)
|
|
local result = ""
|
|
stdnse.debug4("MSRPC: Entering marshall_lsa_TranslatedName2()")
|
|
|
|
-- Set some default values
|
|
if(sid_type == nil) then sid_type = "SID_NAME_USE_NONE" end
|
|
if(name == nil) then name = "" end
|
|
if(sid_index == nil) then sid_index = 0 end
|
|
if(unknown == nil) then unknown = 0 end
|
|
|
|
if(location == HEAD or location == ALL) then
|
|
result = result .. marshall_lsa_SidType(sid_type)
|
|
result = result .. marshall_lsa_String_internal(HEAD, name)
|
|
result = result .. marshall_int32(sid_index)
|
|
result = result .. marshall_int32(unknown)
|
|
end
|
|
|
|
if(location == BODY or location == ALL) then
|
|
result = result .. marshall_lsa_String_internal(BODY, name)
|
|
end
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_lsa_TranslatedName2()")
|
|
return result
|
|
end
|
|
|
|
--@param location The part of the pointer wanted, either HEAD (for the data itself), BODY
|
|
-- (for nothing, since this isn't a pointer), or ALL (for the data). Generally, unless the
|
|
-- referent_id is split from the data (for example, in an array), you will want
|
|
-- ALL.
|
|
--@param data The data being processed.
|
|
--@param pos The position within <code>data</code>.
|
|
--@param result This is required when unmarshalling the BODY section, which always comes after
|
|
-- unmarshalling the HEAD. It is the result returned for this parameter during the
|
|
-- HEAD unmarshall. If the referent_id was '0', then this function doesn't unmarshall
|
|
-- anything.
|
|
--@return (pos, result) The new position in <code>data</code>, and a table representing the datatype.
|
|
local function unmarshall_lsa_TranslatedName2(location, data, pos, result)
|
|
stdnse.debug4("MSRPC: Entering unmarshall_lsa_TranslatedName2()")
|
|
if(result == nil) then
|
|
result = {}
|
|
end
|
|
|
|
if(location == HEAD or location == ALL) then
|
|
pos, result['sid_type'] = unmarshall_lsa_SidType(data, pos)
|
|
pos, result['name'] = unmarshall_lsa_String_internal(HEAD, data, pos)
|
|
pos, result['sid_index'] = unmarshall_int32(data, pos)
|
|
pos, result['unknown'] = unmarshall_int32(data, pos)
|
|
end
|
|
|
|
|
|
if(location == BODY or location == ALL) then
|
|
pos, result['name'] = unmarshall_lsa_String_internal(BODY, data, pos, result['name'])
|
|
end
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_lsa_TranslatedName2()")
|
|
return pos, result
|
|
end
|
|
|
|
|
|
---Marshall a lsa_TransSidArray2 struct
|
|
--
|
|
--<code>
|
|
-- typedef struct {
|
|
-- [range(0,1000)] uint32 count;
|
|
-- [size_is(count)] lsa_TranslatedSid2 *sids;
|
|
-- } lsa_TransSidArray2;
|
|
--</code>
|
|
--
|
|
--@param sids An array of SIDs to translate (as strings)
|
|
--@return A string representing the marshalled data.
|
|
function marshall_lsa_TransSidArray2(sids)
|
|
local result = ""
|
|
local array = {}
|
|
stdnse.debug4("MSRPC: Entering marshall_lsa_TransSidArray2()")
|
|
|
|
result = result .. marshall_int32(#sids)
|
|
|
|
for i = 1, #sids, 1 do
|
|
array[i] = {}
|
|
array[i]['func'] = marshall_lsa_TranslatedSid2
|
|
array[i]['args'] = {sids[i]['sid_type'], sids[i]['rid'], sids[i]['sid_index'], sids[i]['unknown']}
|
|
end
|
|
|
|
result = result .. marshall_ptr(ALL, marshall_array, {array}, array)
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_lsa_TransSidArray2()")
|
|
return result
|
|
end
|
|
|
|
---Marshall a lsa_StringLarge struct
|
|
--
|
|
--<code>
|
|
-- typedef [public] struct {
|
|
-- [value(2*strlen_m(string))] uint16 length;
|
|
-- [value(2*(strlen_m(string)+1))] uint16 size;
|
|
-- [charset(UTF16),size_is(size/2),length_is(length/2)] uint16 *string;
|
|
-- } lsa_StringLarge;
|
|
--</code>
|
|
--
|
|
--@param location The part of the pointer wanted, either HEAD (for the data itself), BODY
|
|
-- (for nothing, since this isn't a pointer), or ALL (for the data). Generally, unless the
|
|
-- referent_id is split from the data (for example, in an array), you will want
|
|
-- ALL.
|
|
--@param data The data being processed.
|
|
--@param pos The position within <code>data</code>.
|
|
--@param result This is required when unmarshalling the BODY section, which always comes after
|
|
-- unmarshalling the HEAD. It is the result returned for this parameter during the
|
|
-- HEAD unmarshall. If the referent_id was '0', then this function doesn't unmarshall
|
|
-- anything.
|
|
--@return (pos, result) The new position in <code>data</code>, and the string value.
|
|
local function unmarshall_lsa_StringLarge(location, data, pos, result)
|
|
local length, size
|
|
local str
|
|
stdnse.debug4("MSRPC: Entering unmarshall_lsa_StringLarge()")
|
|
|
|
if(location == HEAD or location == ALL) then
|
|
pos, length = unmarshall_int16(data, pos, false)
|
|
pos, size = unmarshall_int16(data, pos, false)
|
|
|
|
pos, str = unmarshall_ptr(HEAD, data, pos, unmarshall_unicode, {false})
|
|
end
|
|
|
|
if(location == BODY or location == ALL) then
|
|
pos, str = unmarshall_ptr(BODY, data, pos, unmarshall_unicode, {false}, result)
|
|
end
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_lsa_StringLarge()")
|
|
return pos, str
|
|
end
|
|
|
|
---Unmarshall a lsa_DomainInfo struct
|
|
--
|
|
--<code>
|
|
-- typedef struct {
|
|
-- lsa_StringLarge name;
|
|
-- dom_sid2 *sid;
|
|
-- } lsa_DomainInfo;
|
|
--</code>
|
|
--
|
|
--@param location The part of the pointer wanted, either HEAD (for the data itself), BODY
|
|
-- (for nothing, since this isn't a pointer), or ALL (for the data). Generally, unless the
|
|
-- referent_id is split from the data (for example, in an array), you will want
|
|
-- ALL.
|
|
--@param data The data being processed.
|
|
--@param pos The position within <code>data</code>.
|
|
--@param result This is required when unmarshalling the BODY section, which always comes after
|
|
-- unmarshalling the HEAD. It is the result returned for this parameter during the
|
|
-- HEAD unmarshall. If the referent_id was '0', then this function doesn't unmarshall
|
|
-- anything.
|
|
--@return (pos, result) The new position in <code>data</code>, and a table representing the datatype.
|
|
local function unmarshall_lsa_DomainInfo(location, data, pos, result)
|
|
stdnse.debug4("MSRPC: Entering unmarshall_lsa_DomainInfo()")
|
|
if(result == nil) then
|
|
result = {}
|
|
end
|
|
|
|
if(location == HEAD or location == ALL) then
|
|
pos, result['name'] = unmarshall_lsa_StringLarge(HEAD, data, pos)
|
|
pos, result['sid'] = unmarshall_ptr(HEAD, data, pos, unmarshall_dom_sid2)
|
|
end
|
|
|
|
if(location == BODY or location == ALL) then
|
|
pos, result['name'] = unmarshall_lsa_StringLarge(BODY, data, pos, result['name'])
|
|
pos, result['sid'] = unmarshall_ptr(BODY, data, pos, unmarshall_dom_sid2, {}, result['sid'])
|
|
end
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_lsa_DomainInfo()")
|
|
return pos, result
|
|
end
|
|
|
|
---Unmarshall a lsa_RefDomainList struct
|
|
--
|
|
--<code>
|
|
-- typedef struct {
|
|
-- [range(0,1000)] uint32 count;
|
|
-- [size_is(count)] lsa_DomainInfo *domains;
|
|
-- uint32 max_size;
|
|
-- } lsa_RefDomainList;
|
|
--</code>
|
|
--
|
|
--@param data The data being processed.
|
|
--@param pos The position within <code>data</code>.
|
|
--@return (pos, result) The new position in <code>data</code>, and a table representing the datatype.
|
|
function unmarshall_lsa_RefDomainList(data, pos)
|
|
local result = {}
|
|
stdnse.debug4("MSRPC: Entering unmarshall_lsa_RefDomainList()")
|
|
|
|
-- Head
|
|
pos, result['count'] = unmarshall_int32(data, pos)
|
|
pos, result['domains'] = unmarshall_ptr(HEAD, data, pos, unmarshall_array, {result['count'], unmarshall_lsa_DomainInfo, {}})
|
|
pos, result['max_size'] = unmarshall_int32(data, pos)
|
|
|
|
-- Body
|
|
pos, result['domains'] = unmarshall_ptr(BODY, data, pos, unmarshall_array, {result['count'], unmarshall_lsa_DomainInfo, {}}, result['domains'])
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_lsa_RefDomainList()")
|
|
return pos, result
|
|
end
|
|
|
|
---Unmarshall a pointer to a <code>lsa_RefDomainList</code>. See the <code>unmarshall_lsa_RefDomainList</code> function
|
|
-- for more information.
|
|
--
|
|
--@param data The data being processed.
|
|
--@param pos The position within <code>data</code>.
|
|
--@return (pos, result) The new position in <code>data</code>, and a table representing the datatype.
|
|
function unmarshall_lsa_RefDomainList_ptr(data, pos)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering unmarshall_lsa_RefDomainList_ptr()")
|
|
|
|
pos, result = unmarshall_ptr(ALL, data, pos, unmarshall_lsa_RefDomainList, nil)
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_lsa_RefDomainList_ptr()")
|
|
return pos, result
|
|
end
|
|
|
|
---Unmarshall a lsa_TransSidArray2 struct
|
|
--
|
|
--<code>
|
|
-- typedef struct {
|
|
-- [range(0,1000)] uint32 count;
|
|
-- [size_is(count)] lsa_TranslatedSid2 *sids;
|
|
-- } lsa_TransSidArray2;
|
|
--</code>
|
|
--
|
|
--@param data The data being processed.
|
|
--@param pos The position within <code>data</code>.
|
|
--@return (pos, result) The new position in <code>data</code>, and a table representing the datatype.
|
|
function unmarshall_lsa_TransSidArray2(data, pos)
|
|
local result = {}
|
|
stdnse.debug4("MSRPC: Entering unmarshall_lsa_TransSidArray2()")
|
|
|
|
pos, result['count'] = unmarshall_int32(data, pos)
|
|
pos, result['sid'] = unmarshall_ptr(ALL, data, pos, unmarshall_array, {result['count'], unmarshall_lsa_TranslatedSid2, {}})
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_lsa_TransSidArray2()")
|
|
return pos, result
|
|
end
|
|
|
|
---Marshall a lsa_QosInfo struct
|
|
--
|
|
--<code>
|
|
-- typedef struct {
|
|
-- uint32 len; /* ignored */
|
|
-- uint16 impersonation_level;
|
|
-- uint8 context_mode;
|
|
-- uint8 effective_only;
|
|
-- } lsa_QosInfo;
|
|
--</code>
|
|
--
|
|
-- I didn't bother letting the user specify values, since I don't know what any of them do. The
|
|
-- defaults seem to work really well.
|
|
--
|
|
--@return A string representing the marshalled data.
|
|
function marshall_lsa_QosInfo()
|
|
local result = ""
|
|
stdnse.debug4("MSRPC: Entering marshall_lsa_QosInfo()")
|
|
|
|
result = result .. marshall_int32(12)
|
|
result = result .. marshall_int16(2, false)
|
|
result = result .. marshall_int8(1, false)
|
|
result = result .. marshall_int8(0, false)
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_lsa_QosInfo()")
|
|
return result
|
|
end
|
|
|
|
---Marshall a lsa_ObjectAttribute struct
|
|
--
|
|
--<code>
|
|
-- typedef struct {
|
|
-- uint32 len; /* ignored */
|
|
-- uint8 *root_dir;
|
|
-- [string,charset(UTF16)] uint16 *object_name;
|
|
-- uint32 attributes;
|
|
-- security_descriptor *sec_desc;
|
|
-- lsa_QosInfo *sec_qos;
|
|
-- } lsa_ObjectAttribute;
|
|
--</code>
|
|
--
|
|
-- I didn't bother letting the user specify values, since I don't know what any of them do. The
|
|
-- defaults seem to work really well.
|
|
--
|
|
--@return A string representing the marshalled data.
|
|
function marshall_lsa_ObjectAttribute()
|
|
local result = ""
|
|
stdnse.debug4("MSRPC: Entering marshall_lsa_ObjectAttribute()")
|
|
|
|
result = result .. marshall_int32(24)
|
|
result = result .. marshall_int32(0) -- Null'ing out these pointers for now. Maybe we'll need them in the future...
|
|
result = result .. marshall_int32(0)
|
|
result = result .. marshall_int32(0)
|
|
result = result .. marshall_int32(0)
|
|
result = result .. marshall_ptr(ALL, marshall_lsa_QosInfo, {})
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_lsa_ObjectAttribute()")
|
|
return result
|
|
end
|
|
|
|
---Marshall a lsa_SidPtr struct
|
|
--
|
|
--<code>
|
|
-- typedef struct {
|
|
-- dom_sid2 *sid;
|
|
-- } lsa_SidPtr;
|
|
--</code>
|
|
--
|
|
--@param location The part of the pointer wanted, either HEAD (for the data itself), BODY
|
|
-- (for nothing, since this isn't a pointer), or ALL (for the data). Generally, unless the
|
|
-- referent_id is split from the data (for example, in an array), you will want
|
|
-- ALL.
|
|
--@param sid The SID to marshall (as a string).
|
|
--@return A string representing the marshalled data.
|
|
local function marshall_lsa_SidPtr(location, sid)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering marshall_lsa_SidPtr()")
|
|
|
|
result = marshall_ptr(location, marshall_dom_sid2, {sid}, sid)
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_lsa_SidPtr()")
|
|
return result
|
|
end
|
|
|
|
---Marshall a lsa_SidArray struct
|
|
--
|
|
--<code>
|
|
-- typedef [public] struct {
|
|
-- [range(0,1000)] uint32 num_sids;
|
|
-- [size_is(num_sids)] lsa_SidPtr *sids;
|
|
-- } lsa_SidArray;
|
|
--</code>
|
|
--
|
|
--@param sids The array of SIDs to marshall (as strings).
|
|
--@return A string representing the marshalled data.
|
|
function marshall_lsa_SidArray(sids)
|
|
local result = ""
|
|
local array = {}
|
|
|
|
result = result .. marshall_int32(#sids)
|
|
|
|
for i = 1, #sids, 1 do
|
|
array[i] = {}
|
|
array[i]['func'] = marshall_lsa_SidPtr
|
|
array[i]['args'] = {sids[i]}
|
|
end
|
|
|
|
result = result .. marshall_ptr(ALL, marshall_array, {array}, array)
|
|
|
|
return result
|
|
end
|
|
|
|
---Unmarshall a lsa_SidPtr struct
|
|
--
|
|
--<code>
|
|
-- typedef struct {
|
|
-- dom_sid2 *sid;
|
|
-- } lsa_SidPtr;
|
|
--</code>
|
|
--
|
|
--@param location The part of the pointer wanted, either HEAD (for the data itself), BODY
|
|
-- (for nothing, since this isn't a pointer), or ALL (for the data). Generally, unless the
|
|
-- referent_id is split from the data (for example, in an array), you will want
|
|
-- ALL.
|
|
--@param data The data being processed.
|
|
--@param pos The position within <code>data</code>.
|
|
--@param result This is required when unmarshalling the BODY section, which always comes after
|
|
-- unmarshalling the HEAD. It is the result returned for this parameter during the
|
|
-- HEAD unmarshall. If the referent_id was '0', then this function doesn't unmarshall
|
|
-- anything.
|
|
--@return (pos, result) The new position in <code>data</code>, and a table representing the datatype.
|
|
function unmarshall_lsa_SidPtr(location, data, pos, result)
|
|
return unmarshall_ptr(location, data, pos, unmarshall_dom_sid2, {}, result)
|
|
end
|
|
|
|
---Unmarshall a lsa_SidArray struct
|
|
--
|
|
-- typedef [public] struct {
|
|
-- [range(0,1000)] uint32 num_sids;
|
|
-- [size_is(num_sids)] lsa_SidPtr *sids;
|
|
-- } lsa_SidArray;
|
|
--
|
|
--@param data The data being processed.
|
|
--@param pos The position within <code>data</code>.
|
|
--@return (pos, result) The new position in <code>data</code>, and a table representing the datatype.
|
|
function unmarshall_lsa_SidArray(data, pos)
|
|
local sidarray = {}
|
|
|
|
pos, sidarray['count'] = unmarshall_int32(data, pos)
|
|
pos, sidarray['sids'] = unmarshall_ptr(ALL, data, pos, unmarshall_array, {sidarray['count'], unmarshall_lsa_SidPtr, {}})
|
|
|
|
return pos, sidarray
|
|
end
|
|
|
|
---Marshall a lsa_TransNameArray2 struct
|
|
--
|
|
--<code>
|
|
-- typedef struct {
|
|
-- [range(0,1000)] uint32 count;
|
|
-- [size_is(count)] lsa_TranslatedName2 *names;
|
|
-- } lsa_TransNameArray2;
|
|
--</code>
|
|
--
|
|
--@param names An array of names to translate.
|
|
--@return A string representing the marshalled data.
|
|
function marshall_lsa_TransNameArray2(names)
|
|
local result = ""
|
|
local array = {}
|
|
stdnse.debug4("MSRPC: Entering marshall_lsa_TransNameArray2()")
|
|
|
|
if(names == nil) then
|
|
result = result .. marshall_int32(0)
|
|
array = nil
|
|
else
|
|
result = result .. marshall_int32(#names)
|
|
|
|
for i = 1, #names, 1 do
|
|
array[i] = {}
|
|
array[i]['func'] = marshall_lsa_TranslatedName2
|
|
array[i]['args'] = {names[i]['sid_type'], names[i]['name'], names[i]['sid_index'], names[i]['unknown']}
|
|
end
|
|
end
|
|
|
|
result = result .. marshall_ptr(ALL, marshall_array, {array}, array)
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_lsa_TransNameArray2()")
|
|
return result
|
|
end
|
|
|
|
---Unmarshall a <code>lsa_TransNameArray2</code> structure. See the <code>marshall_lsa_TransNameArray2</code> for more
|
|
-- information.
|
|
--
|
|
--@param data The data being processed.
|
|
--@param pos The position within <code>data</code>.
|
|
--@return (pos, result) The new position in <code>data</code>, and a table representing the datatype.
|
|
function unmarshall_lsa_TransNameArray2(data, pos)
|
|
local result = {}
|
|
stdnse.debug4("MSRPC: Entering unmarshall_lsa_TransNameArray2()")
|
|
|
|
pos, result['count'] = unmarshall_int32(data, pos)
|
|
pos, result['names'] = unmarshall_ptr(ALL, data, pos, unmarshall_array, {result['count'], unmarshall_lsa_TranslatedName2, {}})
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_lsa_TransNameArray2()")
|
|
return pos, result
|
|
end
|
|
|
|
|
|
|
|
-------------------------------------
|
|
-- WINREG
|
|
-- (dependencies: LSA, INITSHUTDOWN, SECURITY)
|
|
-------------------------------------
|
|
--- Access masks for Windows registry calls
|
|
local winreg_AccessMask =
|
|
{
|
|
DELETE_ACCESS = 0x00010000,
|
|
READ_CONTROL_ACCESS = 0x00020000,
|
|
WRITE_DAC_ACCESS = 0x00040000,
|
|
WRITE_OWNER_ACCESS = 0x00080000,
|
|
SYNCHRONIZE_ACCESS = 0x00100000,
|
|
ACCESS_SACL_ACCESS = 0x00800000,
|
|
SYSTEM_SECURITY_ACCESS = 0x01000000,
|
|
MAXIMUM_ALLOWED_ACCESS = 0x02000000,
|
|
GENERIC_ALL_ACCESS = 0x10000000,
|
|
GENERIC_EXECUTE_ACCESS = 0x20000000,
|
|
GENERIC_WRITE_ACCESS = 0x40000000,
|
|
GENERIC_READ_ACCESS = 0x80000000
|
|
}
|
|
--- String versions of access masks for Windows registry calls
|
|
local winreg_AccessMask_str =
|
|
{
|
|
DELETE_ACCESS = "Delete",
|
|
READ_CONTROL_ACCESS = "Read",
|
|
WRITE_DAC_ACCESS = "Write",
|
|
WRITE_OWNER_ACCESS = "Write (owner)",
|
|
SYNCHRONIZE_ACCESS = "Synchronize",
|
|
ACCESS_SACL_ACCESS = "Access SACL",
|
|
SYSTEM_SECURITY_ACCESS = "System security",
|
|
MAXIMUM_ALLOWED_ACCESS = "Maximum allowed access",
|
|
GENERIC_ALL_ACCESS = "All access",
|
|
GENERIC_EXECUTE_ACCESS = "Execute access",
|
|
GENERIC_WRITE_ACCESS = "Write access",
|
|
GENERIC_READ_ACCESS = "Read access"
|
|
}
|
|
|
|
---Marshall a <code>winreg_AccessMask</code>.
|
|
--
|
|
--@param accessmask The access mask as a string (see the <code>winreg_AccessMask</code>
|
|
-- table)
|
|
--@return A string representing the marshalled data.
|
|
function marshall_winreg_AccessMask(accessmask)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering marshall_winreg_AccessMask()")
|
|
|
|
result = marshall_Enum32(accessmask, winreg_AccessMask)
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_winreg_AccessMask()")
|
|
return result
|
|
end
|
|
|
|
---Unmarshall a <code>winreg_AccessMask</code>. This datatype is tied to the table with that name.
|
|
--
|
|
--@param data The data packet.
|
|
--@param pos The position within the data.
|
|
--@return (pos, str) The new position, and the string representing the datatype.
|
|
function unmarshall_winreg_AccessMask(data, pos)
|
|
local str
|
|
stdnse.debug4("MSRPC: Entering unmarshall_winreg_AccessMask()")
|
|
|
|
pos, str = unmarshall_Enum32(data, pos, winreg_AccessMask)
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_winreg_AccessMask()")
|
|
return pos, str
|
|
end
|
|
|
|
---Convert a <code>winreg_AccessMask</code> value to a string that can be shown to the user. This is
|
|
-- based on the <code>_str</code> table.
|
|
--
|
|
--@param val The string value (returned by the <code>unmarshall_</code> function) to convert.
|
|
--@return A string suitable for displaying to the user, or <code>nil</code> if it wasn't found.
|
|
function winreg_AccessMask_tostr(val)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering winreg_AccessMask_tostr()")
|
|
|
|
result = winreg_AccessMask_str[val]
|
|
|
|
stdnse.debug4("MSRPC: Leaving winreg_AccessMask_tostr()")
|
|
return result
|
|
end
|
|
|
|
---Registry types
|
|
winreg_Type =
|
|
{
|
|
REG_NONE = 0,
|
|
REG_SZ = 1,
|
|
REG_EXPAND_SZ = 2,
|
|
REG_BINARY = 3,
|
|
REG_DWORD = 4,
|
|
REG_DWORD_BIG_ENDIAN = 5,
|
|
REG_LINK = 6,
|
|
REG_MULTI_SZ = 7,
|
|
REG_RESOURCE_LIST = 8,
|
|
REG_FULL_RESOURCE_DESCRIPTOR = 9,
|
|
REG_RESOURCE_REQUIREMENTS_LIST = 10,
|
|
REG_QWORD = 11
|
|
}
|
|
|
|
---Registry type strings
|
|
winreg_Type_str =
|
|
{
|
|
REG_NONE = "None",
|
|
REG_SZ = "String",
|
|
REG_EXPAND_SZ = "String (expanded)",
|
|
REG_BINARY = "Binary",
|
|
REG_DWORD = "Dword",
|
|
REG_DWORD_BIG_ENDIAN = "Dword (big endian)",
|
|
REG_LINK = "Link",
|
|
REG_MULTI_SZ = "String (multi)",
|
|
REG_RESOURCE_LIST = "Resource list",
|
|
REG_FULL_RESOURCE_DESCRIPTOR = "Full resource descriptor",
|
|
REG_RESOURCE_REQUIREMENTS_LIST = "Resource requirements list",
|
|
REG_QWORD = "Qword"
|
|
}
|
|
|
|
---Marshall a <code>winreg_Type</code>. This datatype is tied to the table above with that
|
|
-- name.
|
|
--
|
|
--@param winregtype The value to marshall, as a string
|
|
--@return The marshalled integer representing the given value, or <code>nil</code> if it wasn't
|
|
-- found.
|
|
function marshall_winreg_Type(winregtype)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering marshall_winreg_Type()")
|
|
|
|
result = marshall_Enum32(winregtype, winreg_Type)
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_winreg_Type()")
|
|
return result
|
|
end
|
|
|
|
---Unmarshall a <code>winreg_Type</code>. This datatype is tied to the table with that name.
|
|
--
|
|
--@param data The data packet.
|
|
--@param pos The position within the data.
|
|
--@return (pos, str) The new position, and the string representing the datatype.
|
|
function unmarshall_winreg_Type(data, pos)
|
|
local str
|
|
stdnse.debug4("MSRPC: Entering unmarshall_winreg_Type()")
|
|
|
|
pos, str = unmarshall_Enum32(data, pos, winreg_Type)
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_winreg_Type()")
|
|
return pos, str
|
|
end
|
|
|
|
---Marshall a pointer to a <code>winreg_Type</code>. This datatype is tied to the table above with that
|
|
-- name.
|
|
--
|
|
--@param winreg_type The value to marshall, as a string
|
|
--@return The marshalled integer representing the given value, or <code>nil</code> if it wasn't
|
|
-- found.
|
|
function marshall_winreg_Type_ptr(winreg_type)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering marshall_winreg_Type_ptr()")
|
|
|
|
result = marshall_ptr(ALL, marshall_winreg_Type, {winreg_type}, winreg_type)
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_winreg_Type_ptr()")
|
|
return result
|
|
end
|
|
|
|
---Unmarshall a pointer to a <code>winreg_Type</code>. This datatype is tied to the table with that name.
|
|
--
|
|
--@param data The data packet.
|
|
--@param pos The position within the data.
|
|
--@return (pos, str) The new position, and the string representing the datatype.
|
|
function unmarshall_winreg_Type_ptr(data, pos)
|
|
local str
|
|
stdnse.debug4("MSRPC: Entering unmarshall_winreg_Type_ptr()")
|
|
|
|
pos, str = unmarshall_ptr(ALL, data, pos, unmarshall_winreg_Type, {})
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_winreg_Type_ptr()")
|
|
return pos, str
|
|
end
|
|
|
|
---Convert a <code>winreg_Type</code> value to a string that can be shown to the user. This is
|
|
-- based on the <code>_str</code> table.
|
|
--
|
|
--@param val The string value (returned by the <code>unmarshall_</code> function) to convert.
|
|
--@return A string suitable for displaying to the user, or <code>nil</code> if it wasn't found.
|
|
function winreg_Type_tostr(val)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering winreg_Type_tostr()")
|
|
|
|
result = winreg_Type_str[val]
|
|
|
|
stdnse.debug4("MSRPC: Leaving winreg_Type_tostr()")
|
|
return result
|
|
end
|
|
|
|
--- A winreg_stringbuf is a buffer that holds a null-terminated string. It can have a max size that's different
|
|
-- from its actual size.
|
|
--
|
|
-- This is the format:
|
|
--
|
|
--<code>
|
|
-- typedef struct {
|
|
-- [value(strlen_m_term(name)*2)] uint16 length;
|
|
-- uint16 size;
|
|
-- [size_is(size/2),length_is(length/2),charset(UTF16)] uint16 *name;
|
|
-- } winreg_StringBuf;
|
|
--</code>
|
|
--
|
|
--@param table The table to marshall. Will probably contain just the 'name' entry.
|
|
--@param max_length [optional] The maximum size of the buffer, in characters, including the null terminator.
|
|
-- Defaults to the length of the string, including the null.
|
|
--@return A string representing the marshalled data.
|
|
function marshall_winreg_StringBuf(table, max_length)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering marshall_winreg_StringBuf()")
|
|
|
|
local name = table['name']
|
|
local length
|
|
|
|
-- Handle default max lengths
|
|
if(max_length == nil) then
|
|
if(name == nil) then
|
|
max_length = 0
|
|
else
|
|
max_length = #name + 1
|
|
end
|
|
end
|
|
|
|
-- For some reason, 0-length strings are handled differently (no null terminator)...
|
|
if(name == "") then
|
|
length = 0
|
|
result = bin.pack("<SSA", length * 2, max_length * 2, marshall_ptr(ALL, marshall_unicode, {name, false, max_length}, name))
|
|
else
|
|
if(name == nil) then
|
|
length = 0
|
|
else
|
|
length = #name + 1
|
|
end
|
|
|
|
result = bin.pack("<SSA", length * 2, max_length * 2, marshall_ptr(ALL, marshall_unicode, {name, true, max_length}, name))
|
|
end
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_winreg_StringBuf()")
|
|
return result
|
|
end
|
|
|
|
---Unmarshall a winreg_StringBuf buffer.
|
|
--
|
|
--@param data The data buffer.
|
|
--@param pos The position in the data buffer.
|
|
--@return (pos, str) The new position and the string.
|
|
function unmarshall_winreg_StringBuf(data, pos)
|
|
local length, size
|
|
local str
|
|
stdnse.debug4("MSRPC: Entering unmarshall_winreg_StringBuf()")
|
|
|
|
pos, length = unmarshall_int16(data, pos, false)
|
|
pos, size = unmarshall_int16(data, pos, false)
|
|
|
|
pos, str = unmarshall_ptr(ALL, data, pos, unmarshall_unicode, {true})
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_winreg_StringBuf()")
|
|
return pos, str
|
|
end
|
|
|
|
---Marshall a winreg_StringBuffer pointer. Same as <code>marshall_winreg_StringBuf</code>, except
|
|
-- the string can be <code>nil</code>.
|
|
--
|
|
--@param table The table representing the String.
|
|
--@param max_length [optional] The maximum size of the buffer, in characters. Defaults to the length of the string, including the null.
|
|
--@return A string representing the marshalled data.
|
|
function marshall_winreg_StringBuf_ptr(table, max_length)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering marshall_winreg_StringBuf_ptr()")
|
|
|
|
result = marshall_ptr(ALL, marshall_winreg_StringBuf, {table, max_length}, table)
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_winreg_StringBuf_ptr()")
|
|
return result
|
|
end
|
|
|
|
---Unmarshall a winreg_StringBuffer pointer
|
|
--
|
|
--@param data The data buffer.
|
|
--@param pos The position in the data buffer.
|
|
--@return (pos, str) The new position and the string.
|
|
function unmarshall_winreg_StringBuf_ptr(data, pos)
|
|
local str
|
|
stdnse.debug4("MSRPC: Entering unmarshall_winreg_StringBuf_ptr()")
|
|
|
|
pos, str = unmarshall_ptr(ALL, data, pos, unmarshall_winreg_StringBuf, {})
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_winreg_StringBuf_ptr()")
|
|
return pos, str
|
|
end
|
|
|
|
|
|
--- A winreg_String has the same makeup as a winreg_StringBuf, as far as I can tell, so delegate to that function.
|
|
--
|
|
--@param table The table representing the String.
|
|
--@param max_length [optional] The maximum size of the buffer, in characters. Defaults to the length of the string, including the null.
|
|
--@return A string representing the marshalled data.
|
|
function marshall_winreg_String(table, max_length)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering marshall_winreg_String()")
|
|
|
|
result = marshall_winreg_StringBuf(table, max_length)
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_winreg_String()")
|
|
return result
|
|
end
|
|
|
|
---Unmarshall a winreg_String. Since it has the same makeup as winreg_StringBuf, delegate to that.
|
|
--
|
|
--@param data The data buffer.
|
|
--@param pos The position in the data buffer.
|
|
--@return (pos, str) The new position and the string.
|
|
function unmarshall_winreg_String(data, pos)
|
|
local str
|
|
stdnse.debug4("MSRPC: Entering unmarshall_winreg_String()")
|
|
|
|
pos, str = unmarshall_winreg_StringBuf(data, pos)
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_winreg_String()")
|
|
return pos, str
|
|
end
|
|
|
|
|
|
-------------------------------------
|
|
-- SRVSVC
|
|
-- (dependencies: SECURITY, SVCCTL)
|
|
-------------------------------------
|
|
---Share types
|
|
local srvsvc_ShareType =
|
|
{
|
|
STYPE_DISKTREE = 0x00000000,
|
|
STYPE_DISKTREE_TEMPORARY = 0x40000000,
|
|
STYPE_DISKTREE_HIDDEN = 0x80000000,
|
|
STYPE_PRINTQ = 0x00000001,
|
|
STYPE_PRINTQ_TEMPORARY = 0x40000001,
|
|
STYPE_PRINTQ_HIDDEN = 0x80000001,
|
|
STYPE_DEVICE = 0x00000002, -- Serial device
|
|
STYPE_DEVICE_TEMPORARY = 0x40000002,
|
|
STYPE_DEVICE_HIDDEN = 0x80000002,
|
|
STYPE_IPC = 0x00000003, -- Interprocess communication (IPC)
|
|
STYPE_IPC_TEMPORARY = 0x40000003,
|
|
STYPE_IPC_HIDDEN = 0x80000003
|
|
}
|
|
---Share type strings
|
|
local srvsvc_ShareType_str =
|
|
{
|
|
STYPE_DISKTREE = "Disk",
|
|
STYPE_DISKTREE_TEMPORARY = "Disk (temporary)",
|
|
STYPE_DISKTREE_HIDDEN = "Disk (hidden)",
|
|
STYPE_PRINTQ = "Print queue",
|
|
STYPE_PRINTQ_TEMPORARY = "Print queue (temporary)",
|
|
STYPE_PRINTQ_HIDDEN = "Print queue (hidden)",
|
|
STYPE_DEVICE = "Serial device",
|
|
STYPE_DEVICE_TEMPORARY = "Serial device (temporary)",
|
|
STYPE_DEVICE_HIDDEN = "Serial device (hidden)",
|
|
STYPE_IPC = "Interprocess Communication",
|
|
STYPE_IPC_TEMPORARY = "Interprocess Communication (temporary)",
|
|
STYPE_IPC_HIDDEN = "Interprocess Communication (hidden)"
|
|
}
|
|
|
|
---Marshall a <code>srvsvc_ShareType</code>. This datatype is tied to the table above with that
|
|
-- name.
|
|
--
|
|
--@param sharetype The value to marshall, as a string
|
|
--@return The marshalled integer representing the given value, or <code>nil</code> if it wasn't
|
|
-- found.
|
|
function marshall_srvsvc_ShareType(sharetype)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering marshall_srvsvc_ShareType()")
|
|
|
|
result = marshall_Enum32(sharetype, srvsvc_ShareType)
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_srvsvc_ShareType()")
|
|
return result
|
|
end
|
|
|
|
---Unmarshall a <code>srvsvc_ShareType</code>. This datatype is tied to the table with that name.
|
|
--
|
|
--@param data The data packet.
|
|
--@param pos The position within the data.
|
|
--@return (pos, str) The new position, and the string representing the datatype.
|
|
function unmarshall_srvsvc_ShareType(data, pos)
|
|
local str
|
|
stdnse.debug4("MSRPC: Entering unmarshall_srvsvc_ShareType()")
|
|
|
|
pos, str = unmarshall_Enum32(data, pos, srvsvc_ShareType)
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_srvsvc_ShareType()")
|
|
return pos, str
|
|
end
|
|
|
|
---Convert a <code>srvsvc_ShareType</code> value to a string that can be shown to the user. This is
|
|
-- based on the <code>_str</code> table.
|
|
--
|
|
--@param val The string value (returned by the <code>unmarshall_</code> function) to convert.
|
|
--@return A string suitable for displaying to the user, or <code>nil</code> if it wasn't found.
|
|
function srvsvc_ShareType_tostr(val)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering srvsvc_ShareType_tostr()")
|
|
|
|
result = srvsvc_ShareType_str[val]
|
|
|
|
stdnse.debug4("MSRPC: Leaving srvsvc_ShareType_tostr()")
|
|
return result
|
|
end
|
|
|
|
---Marshall a NetShareInfo type 0, which is just a name.
|
|
--
|
|
--<code>
|
|
-- typedef struct {
|
|
-- [string,charset(UTF16)] uint16 *name;
|
|
-- } srvsvc_NetShareInfo0;
|
|
--</code>
|
|
--
|
|
--@param location The part of the pointer wanted, either HEAD (for the data itself), BODY
|
|
-- (for nothing, since this isn't a pointer), or ALL (for the data). Generally, unless the
|
|
-- referent_id is split from the data (for example, in an array), you will want
|
|
-- ALL.
|
|
--@param name The name to marshall.
|
|
--@return A string representing the marshalled data.
|
|
local function marshall_srvsvc_NetShareInfo0(location, name)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering marshall_srvsvc_NetShareInfo0()")
|
|
|
|
result = marshall_ptr(location, marshall_unicode, {name, true}, name)
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_srvsvc_NetShareInfo0()")
|
|
return result
|
|
end
|
|
|
|
---Unmarshall a NetShareInfo type 0, which is just a name. See the marshall function for more information.
|
|
--
|
|
--@param location The part of the pointer wanted, either HEAD (for the data itself), BODY
|
|
-- (for nothing, since this isn't a pointer), or ALL (for the data). Generally, unless the
|
|
-- referent_id is split from the data (for example, in an array), you will want
|
|
-- ALL.
|
|
--@param data The data packet.
|
|
--@param pos The position within the data.
|
|
--@param result This is required when unmarshalling the BODY section, which always comes after
|
|
-- unmarshalling the HEAD. It is the result returned for this parameter during the
|
|
-- HEAD unmarshall. If the referent_id was '0', then this function doesn't unmarshall
|
|
-- anything.
|
|
--@return (pos, result) The new position in <code>data</code>, and a table representing the datatype.
|
|
local function unmarshall_srvsvc_NetShareInfo0(location, data, pos, result)
|
|
stdnse.debug4("MSRPC: Entering unmarshall_srvsvc_NetShareInfo0()")
|
|
if(result == nil) then
|
|
result = {}
|
|
end
|
|
|
|
if(location == HEAD or location == ALL) then
|
|
pos, result['name'] = unmarshall_ptr(HEAD, data, pos, unmarshall_unicode, {true})
|
|
end
|
|
|
|
if(location == BODY or location == ALL) then
|
|
pos, result['name'] = unmarshall_ptr(BODY, data, pos, unmarshall_unicode, {true}, result['name'])
|
|
end
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_srvsvc_NetShareInfo0()")
|
|
return pos, result
|
|
end
|
|
|
|
---Marshall a NetShareInfo type 1, which is the name and a few other things.
|
|
--
|
|
--<code>
|
|
-- typedef struct {
|
|
-- [string,charset(UTF16)] uint16 *name;
|
|
-- srvsvc_ShareType type;
|
|
-- [string,charset(UTF16)] uint16 *comment;
|
|
-- } srvsvc_NetShareInfo1;
|
|
--</code>
|
|
--
|
|
--@param location The part of the pointer wanted, either HEAD (for the data itself), BODY
|
|
-- (for nothing, since this isn't a pointer), or ALL (for the data). Generally, unless the
|
|
-- referent_id is split from the data (for example, in an array), you will want
|
|
-- ALL.
|
|
--@param name The name to marshall.
|
|
--@param sharetype The sharetype to marshall (as a string).
|
|
--@param comment The comment to marshall.
|
|
--@return A string representing the marshalled data.
|
|
local function marshall_srvsvc_NetShareInfo1(location, name, sharetype, comment)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering marshall_srvsvc_NetShareInfo1()")
|
|
local name = marshall_ptr(location, marshall_unicode, {name, true}, name)
|
|
local sharetype = marshall_basetype(location, marshall_srvsvc_ShareType, {sharetype})
|
|
local comment = marshall_ptr(location, marshall_unicode, {comment, true}, comment)
|
|
|
|
result = bin.pack("<AAA", name, sharetype, comment)
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_srvsvc_NetShareInfo1()")
|
|
return result
|
|
end
|
|
|
|
---Unmarshall a NetShareInfo type 1, which is a name and a couple other things. See the marshall
|
|
-- function for more information.
|
|
--
|
|
--@param location The part of the pointer wanted, either HEAD (for the data itself), BODY
|
|
-- (for nothing, since this isn't a pointer), or ALL (for the data). Generally, unless the
|
|
-- referent_id is split from the data (for example, in an array), you will want
|
|
-- ALL.
|
|
--@param data The data packet.
|
|
--@param pos The position within the data.
|
|
--@param result This is required when unmarshalling the BODY section, which always comes after
|
|
-- unmarshalling the HEAD. It is the result returned for this parameter during the
|
|
-- HEAD unmarshall. If the referent_id was '0', then this function doesn't unmarshall
|
|
-- anything.
|
|
--@return (pos, result) The new position in <code>data</code>, and a table representing the datatype.
|
|
local function unmarshall_srvsvc_NetShareInfo1(location, data, pos, result)
|
|
stdnse.debug4("MSRPC: Entering unmarshall_srvsvc_NetShareInfo1()")
|
|
if(result == nil) then
|
|
result = {}
|
|
end
|
|
|
|
if(location == HEAD or location == ALL) then
|
|
pos, result['name'] = unmarshall_ptr(HEAD, data, pos, unmarshall_unicode, {true})
|
|
pos, result['sharetype'] = unmarshall_srvsvc_ShareType(data, pos)
|
|
pos, result['comment'] = unmarshall_ptr(HEAD, data, pos, unmarshall_unicode, {true})
|
|
end
|
|
|
|
if(location == BODY or location == ALL) then
|
|
pos, result['name'] = unmarshall_ptr(BODY, data, pos, unmarshall_unicode, {true}, result['name'])
|
|
pos, result['comment'] = unmarshall_ptr(BODY, data, pos, unmarshall_unicode, {true}, result['comment'])
|
|
end
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_srvsvc_NetShareInfo1()")
|
|
return pos, result
|
|
end
|
|
|
|
|
|
---Marshall a NetShareInfo type 2, which is the name and a few other things.
|
|
--
|
|
--<code>
|
|
-- typedef struct {
|
|
-- [string,charset(UTF16)] uint16 *name;
|
|
-- srvsvc_ShareType type;
|
|
-- [string,charset(UTF16)] uint16 *comment;
|
|
-- uint32 permissions;
|
|
-- uint32 max_users;
|
|
-- uint32 current_users;
|
|
-- [string,charset(UTF16)] uint16 *path;
|
|
-- [string,charset(UTF16)] uint16 *password;
|
|
-- } srvsvc_NetShareInfo2;
|
|
--</code>
|
|
--
|
|
--@param location The part of the pointer wanted, either HEAD (for the data itself), BODY
|
|
-- (for nothing, since this isn't a pointer), or ALL (for the data). Generally, unless the
|
|
-- referent_id is split from the data (for example, in an array), you will want
|
|
-- ALL.
|
|
--@param name The name to marshall.
|
|
--@param sharetype The sharetype to marshall (as a string).
|
|
--@param comment The comment to marshall.
|
|
--@param permissions The permissions, an integer.
|
|
--@param max_users The max users, an integer.
|
|
--@param current_users The current users, an integer.
|
|
--@param path The path, a string.
|
|
--@param password The share-level password, a string (never used on Windows).
|
|
--@return A string representing the marshalled data.
|
|
local function marshall_srvsvc_NetShareInfo2(location, name, sharetype, comment, permissions, max_users, current_users, path, password)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering marshall_srvsvc_NetShareInfo2()")
|
|
local name = marshall_ptr(location, marshall_unicode, {name, true}, name)
|
|
local sharetype = marshall_basetype(location, marshall_srvsvc_ShareType, {sharetype})
|
|
local comment = marshall_ptr(location, marshall_unicode, {comment, true}, comment)
|
|
local permissions = marshall_basetype(location, marshall_int32, {permissions})
|
|
local max_users = marshall_basetype(location, marshall_int32, {max_users})
|
|
local current_users = marshall_basetype(location, marshall_int32, {current_users})
|
|
local path = marshall_ptr(location, marshall_unicode, {path, true}, path)
|
|
local password = marshall_ptr(location, marshall_unicode, {password, true}, password)
|
|
|
|
result = name .. sharetype .. comment .. permissions .. max_users .. current_users .. path .. password
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_srvsvc_NetShareInfo2()")
|
|
return result
|
|
end
|
|
|
|
---Unmarshall a NetShareInfo type 2, which is a name and a few other things. See the marshall
|
|
-- function for more information.
|
|
--
|
|
--@param location The part of the pointer wanted, either HEAD (for the data itself), BODY
|
|
-- (for nothing, since this isn't a pointer), or ALL (for the data). Generally, unless the
|
|
-- referent_id is split from the data (for example, in an array), you will want
|
|
-- ALL.
|
|
--@param data The data packet.
|
|
--@param pos The position within the data.
|
|
--@param result This is required when unmarshalling the BODY section, which always comes after
|
|
-- unmarshalling the HEAD. It is the result returned for this parameter during the
|
|
-- HEAD unmarshall. If the referent_id was '0', then this function doesn't unmarshall
|
|
-- anything.
|
|
--@return (pos, result) The new position in <code>data</code>, and a table representing the datatype.
|
|
local function unmarshall_srvsvc_NetShareInfo2(location, data, pos, result)
|
|
stdnse.debug4("MSRPC: Entering unmarshall_srvsvc_NetShareInfo2()")
|
|
if(result == nil) then
|
|
result = {}
|
|
end
|
|
|
|
if(location == HEAD or location == ALL) then
|
|
pos, result['name'] = unmarshall_ptr(HEAD, data, pos, unmarshall_unicode, {true})
|
|
pos, result['sharetype'] = unmarshall_srvsvc_ShareType(data, pos)
|
|
pos, result['comment'] = unmarshall_ptr(HEAD, data, pos, unmarshall_unicode, {true})
|
|
pos, result['permissions'] = unmarshall_int32(data, pos)
|
|
pos, result['max_users'] = unmarshall_int32(data, pos)
|
|
pos, result['current_users'] = unmarshall_int32(data, pos)
|
|
pos, result['path'] = unmarshall_ptr(HEAD, data, pos, unmarshall_unicode, {true})
|
|
pos, result['password'] = unmarshall_ptr(HEAD, data, pos, unmarshall_unicode, {true})
|
|
end
|
|
|
|
if(location == BODY or location == ALL) then
|
|
pos, result['name'] = unmarshall_ptr(BODY, data, pos, unmarshall_unicode, {true}, result['name'])
|
|
pos, result['comment'] = unmarshall_ptr(BODY, data, pos, unmarshall_unicode, {true}, result['comment'])
|
|
pos, result['path'] = unmarshall_ptr(BODY, data, pos, unmarshall_unicode, {true}, result['path'])
|
|
pos, result['password'] = unmarshall_ptr(BODY, data, pos, unmarshall_unicode, {true}, result['password'])
|
|
end
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_srvsvc_NetShareInfo2()")
|
|
return pos, result
|
|
end
|
|
|
|
---Marshall a NetShareCtr (container) type 0.
|
|
--
|
|
--It is a simple array with the following definition:
|
|
--
|
|
--<code>
|
|
-- typedef struct {
|
|
-- uint32 count;
|
|
-- [size_is(count)] srvsvc_NetShareInfo0 *array;
|
|
-- } srvsvc_NetShareCtr0;
|
|
--</code>
|
|
--
|
|
--@param NetShareCtr0 A table representing the structure.
|
|
--@return A string representing the marshalled data.
|
|
function marshall_srvsvc_NetShareCtr0(NetShareCtr0)
|
|
local i
|
|
local result = ""
|
|
stdnse.debug4("MSRPC: Entering marshall_srvsvc_NetShareCtr0()")
|
|
|
|
if(NetShareCtr0 == nil) then
|
|
result = result .. bin.pack("<I", 0)
|
|
else
|
|
local array = NetShareCtr0['array']
|
|
local marshall = nil
|
|
|
|
if(array == nil) then
|
|
result = result .. bin.pack("<I", 0)
|
|
else
|
|
result = result .. bin.pack("<I", #array) -- count
|
|
|
|
-- Build the array that we can marshall
|
|
marshall = {}
|
|
for i = 1, #array, 1 do
|
|
marshall[i] = {}
|
|
marshall[i]['func'] = marshall_srvsvc_NetShareInfo0
|
|
marshall[i]['args'] = {array[i]['name']}
|
|
end
|
|
end
|
|
|
|
result = result .. marshall_ptr(ALL, marshall_array, {marshall}, marshall) -- array
|
|
end
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_srvsvc_NetShareCtr0()")
|
|
return result
|
|
end
|
|
|
|
---Unmarshall a NetShareCtr (container) type 0. See the marshall function for the definition.
|
|
--
|
|
--@param data The data packet.
|
|
--@param pos The position within the data.
|
|
--@return (pos, result) The new position in <code>data</code>, and a table representing the datatype.
|
|
function unmarshall_srvsvc_NetShareCtr0(data, pos)
|
|
local count
|
|
local result = {}
|
|
stdnse.debug4("MSRPC: Entering unmarshall_srvsvc_NetShareCtr0()")
|
|
|
|
pos, count = unmarshall_int32(data, pos)
|
|
|
|
pos, result['array'] = unmarshall_ptr(ALL, data, pos, unmarshall_array, {count, unmarshall_srvsvc_NetShareInfo0, {}})
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_srvsvc_NetShareCtr0()")
|
|
return pos, result
|
|
end
|
|
|
|
---Marshall a NetShareCtr (container) type 1.
|
|
--
|
|
--It is a simple array with the following definition:
|
|
--
|
|
--<code>
|
|
-- typedef struct {
|
|
-- uint32 count;
|
|
-- [size_is(count)] srvsvc_NetShareInfo1 *array;
|
|
-- } srvsvc_NetShareCtr1;
|
|
--</code>
|
|
--
|
|
--@param NetShareCtr1 A table representing the structure.
|
|
--@return A string representing the marshalled data.
|
|
function marshall_srvsvc_NetShareCtr1(NetShareCtr1)
|
|
local i
|
|
local result = ""
|
|
stdnse.debug4("MSRPC: Entering marshall_srvsvc_NetShareCtr1()")
|
|
|
|
if(NetShareCtr1 == nil) then
|
|
result = result .. bin.pack("<I", 0)
|
|
else
|
|
local array = NetShareCtr1['array']
|
|
local marshall = nil
|
|
|
|
if(array == nil) then
|
|
result = result .. bin.pack("<I", 0)
|
|
else
|
|
result = result .. bin.pack("<I", #array) -- count
|
|
|
|
-- Build the array that we can marshall
|
|
marshall = {}
|
|
for i = 1, #array, 1 do
|
|
marshall[i] = {}
|
|
marshall[i]['func'] = marshall_srvsvc_NetShareInfo1
|
|
marshall[i]['args'] = {array[i]['name'], array[i]['sharetype'], array[i]['comment']}
|
|
end
|
|
end
|
|
|
|
result = result .. marshall_ptr(ALL, marshall_array, {marshall}, marshall) -- array
|
|
end
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_srvsvc_NetShareCtr1()")
|
|
return result
|
|
end
|
|
|
|
|
|
---Marshall a NetShareCtr (container) type 2.
|
|
--
|
|
--It is a simple array with the following definition:
|
|
--
|
|
--<code>
|
|
-- typedef struct {
|
|
-- uint32 count;
|
|
-- [size_is(count)] srvsvc_NetShareInfo2 *array;
|
|
-- } srvsvc_NetShareCtr2;
|
|
--</code>
|
|
--
|
|
--@param NetShareCtr2 A pointer to the structure.
|
|
--@return A string representing the marshalled data.
|
|
function marshall_srvsvc_NetShareCtr2(NetShareCtr2)
|
|
local i
|
|
local result = ""
|
|
stdnse.debug4("MSRPC: Entering marshall_srvsvc_NetShareCtr2()")
|
|
|
|
if(NetShareCtr2 == nil) then
|
|
result = result .. bin.pack("<I", 0)
|
|
else
|
|
local array = NetShareCtr2['array']
|
|
local marshall = nil
|
|
|
|
if(array == nil) then
|
|
result = result .. bin.pack("<I", 0)
|
|
else
|
|
result = result .. bin.pack("<I", #array) -- count
|
|
|
|
-- Build the array that we can marshall
|
|
marshall = {}
|
|
for i = 1, #array, 1 do
|
|
marshall[i] = {}
|
|
marshall[i]['func'] = marshall_srvsvc_NetShareInfo2
|
|
marshall[i]['args'] = {array[i]['name'], array[i]['sharetype'], array[i]['comment'], array[i]['permissions'], array[i]['max_users'], array[i]['current_users'], array[i]['path'], array[i]['password']}
|
|
marshall[i]['args'] = {array[i]['name']}
|
|
end
|
|
end
|
|
|
|
result = result .. marshall_ptr(ALL, marshall_array, {marshall}, marshall) -- array
|
|
end
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_srvsvc_NetShareCtr2()")
|
|
return result
|
|
end
|
|
|
|
---Marshall the top-level NetShareCtr. This is a union of a bunch of different containers:
|
|
--
|
|
--<code>
|
|
-- typedef union {
|
|
-- [case(0)] srvsvc_NetShareCtr0 *ctr0;
|
|
-- [case(1)] srvsvc_NetShareCtr1 *ctr1;
|
|
-- [case(2)] srvsvc_NetShareCtr2 *ctr2;
|
|
-- [case(501)] srvsvc_NetShareCtr501 *ctr501;
|
|
-- [case(502)] srvsvc_NetShareCtr502 *ctr502;
|
|
-- [case(1004)] srvsvc_NetShareCtr1004 *ctr1004;
|
|
-- [case(1005)] srvsvc_NetShareCtr1005 *ctr1005;
|
|
-- [case(1006)] srvsvc_NetShareCtr1006 *ctr1006;
|
|
-- [case(1007)] srvsvc_NetShareCtr1007 *ctr1007;
|
|
-- [case(1501)] srvsvc_NetShareCtr1501 *ctr1501;
|
|
-- [default] ;
|
|
-- } srvsvc_NetShareCtr;
|
|
--</code>
|
|
--
|
|
-- Not all of them are implemented, however; look at the code to see which are implemented (at the
|
|
-- time of this writing, it's 0, 1, and 2).
|
|
--
|
|
--@param level The level to request. Different levels will return different results, but also require
|
|
-- different access levels to call.
|
|
--@param data The data to populate the array with. Depending on the level, this data will be different.
|
|
-- 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.
|
|
function marshall_srvsvc_NetShareCtr(level, data)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering marshall_srvsvc_NetShareCtr()")
|
|
|
|
if(level == 0) then
|
|
result = bin.pack("<IA", level, marshall_ptr(ALL, marshall_srvsvc_NetShareCtr0, {data}, data))
|
|
elseif(level == 1) then
|
|
result = bin.pack("<IA", level, marshall_ptr(ALL, marshall_srvsvc_NetShareCtr1, {data}, data))
|
|
elseif(level == 2) then
|
|
result = bin.pack("<IA", level, marshall_ptr(ALL, marshall_srvsvc_NetShareCtr2, {data}, data))
|
|
else
|
|
stdnse.debug1("MSRPC: ERROR: Script requested an unknown level for srvsvc_NetShareCtr: %d", level)
|
|
result = nil
|
|
end
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_srvsvc_NetShareCtr()")
|
|
return result
|
|
end
|
|
|
|
---Unmarshall the top-level NetShareCtr. This is a union of a bunch of containers, see the equivalent
|
|
-- marshall function for more information; at the time of this writing I've only implemented level = 0.
|
|
--
|
|
--@param data The data packet.
|
|
--@param pos The position within the data.
|
|
--@return (pos, result) The new position in <code>data</code>, and a table representing the datatype.
|
|
-- The result may be <code>nil</code> if there's an error.
|
|
function unmarshall_srvsvc_NetShareCtr(data, pos)
|
|
local level
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering unmarshall_srv_NetShareCtr()")
|
|
|
|
pos, level = unmarshall_int32(data, pos)
|
|
|
|
if(level == 0) then
|
|
pos, result = unmarshall_ptr(ALL, data, pos, unmarshall_srvsvc_NetShareCtr0, {})
|
|
else
|
|
stdnse.debug1("MSRPC: ERROR: Server returned an unknown level for srvsvc_NetShareCtr: %d", level)
|
|
pos, result = nil, nil
|
|
end
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_srv_NetShareCtr()")
|
|
return pos, result
|
|
end
|
|
|
|
---Unmarshall the top-level NetShareInfo. This is a union of a bunch of different structs:
|
|
--
|
|
--<code>
|
|
-- typedef union {
|
|
-- [case(0)] srvsvc_NetShareInfo0 *info0;
|
|
-- [case(1)] srvsvc_NetShareInfo1 *info1;
|
|
-- [case(2)] srvsvc_NetShareInfo2 *info2;
|
|
-- [case(501)] srvsvc_NetShareInfo501 *info501;
|
|
-- [case(502)] srvsvc_NetShareInfo502 *info502;
|
|
-- [case(1004)] srvsvc_NetShareInfo1004 *info1004;
|
|
-- [case(1005)] srvsvc_NetShareInfo1005 *info1005;
|
|
-- [case(1006)] srvsvc_NetShareInfo1006 *info1006;
|
|
-- [case(1007)] srvsvc_NetShareInfo1007 *info1007;
|
|
-- [case(1501)] sec_desc_buf *info1501;
|
|
-- [default] ;
|
|
-- } srvsvc_NetShareInfo;
|
|
--</code>
|
|
--
|
|
-- Not all of them are implemented, however; look at the code to see which are implemented (at the
|
|
-- time of this writing, it's 0, 1, and 2).
|
|
--
|
|
--@param data The data being processed.
|
|
--@param pos The position within <code>data</code>.
|
|
--@return (pos, result) The new position in <code>data</code>, and a table representing the datatype. This may be
|
|
-- <code>nil</code> if there was an error.
|
|
function unmarshall_srvsvc_NetShareInfo(data, pos)
|
|
local level
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering unmarshall_srvsvc_NetShareInfo()")
|
|
pos, level = unmarshall_int32(data, pos)
|
|
|
|
if(level == 0) then
|
|
pos, result = unmarshall_ptr(ALL, data, pos, unmarshall_struct, {unmarshall_srvsvc_NetShareInfo0, {}})
|
|
elseif(level == 1) then
|
|
pos, result = unmarshall_ptr(ALL, data, pos, unmarshall_struct, {unmarshall_srvsvc_NetShareInfo1, {}})
|
|
elseif(level == 2) then
|
|
pos, result = unmarshall_ptr(ALL, data, pos, unmarshall_struct, {unmarshall_srvsvc_NetShareInfo2, {}})
|
|
else
|
|
stdnse.debug1("MSRPC: ERROR: Invalid level returned by NetShareInfo: %d\n", level)
|
|
pos, result = nil, nil
|
|
end
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_srvsvc_NetShareInfo()")
|
|
return pos, result
|
|
end
|
|
|
|
---Marshall a NetSessInfo type 10.
|
|
--
|
|
--<code>
|
|
-- typedef struct {
|
|
-- [string,charset(UTF16)] uint16 *client;
|
|
-- [string,charset(UTF16)] uint16 *user;
|
|
-- uint32 time;
|
|
-- uint32 idle_time;
|
|
-- } srvsvc_NetSessInfo10;
|
|
--</code>
|
|
--
|
|
--@param location The part of the pointer wanted, either HEAD (for the data itself), BODY
|
|
-- (for nothing, since this isn't a pointer), or ALL (for the data). Generally, unless the
|
|
-- referent_id is split from the data (for example, in an array), you will want
|
|
-- ALL.
|
|
--@param client The client string.
|
|
--@param user The user string.
|
|
--@param time The number of seconds that the user has been logged on.
|
|
--@param idle_time The number of seconds that the user's been idle.
|
|
--@return A string representing the marshalled data.
|
|
local function marshall_srvsvc_NetSessInfo10(location, client, user, time, idle_time)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering marshall_srvsvc_NetShareInfo10()")
|
|
local client = marshall_ptr(location, marshall_unicode, {client, true}, client)
|
|
local user = marshall_ptr(location, marshall_unicode, {user, true}, user)
|
|
local time = marshall_basetype(location, marshall_int32, {time})
|
|
local idle_time = marshall_basetype(location, marshall_int32, {idle_time})
|
|
|
|
result = bin.pack("<AAAA", client, user, time, idle_time)
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_srvsvc_NetShareInfo10()")
|
|
return result
|
|
end
|
|
|
|
---Unmarshall a NetSessInfo type 10. For more information, see the marshall function.
|
|
--
|
|
--@param location The part of the pointer wanted, either HEAD (for the data itself), BODY
|
|
-- (for nothing, since this isn't a pointer), or ALL (for the data). Generally, unless the
|
|
-- referent_id is split from the data (for example, in an array), you will want
|
|
-- ALL.
|
|
--@param data The data packet.
|
|
--@param pos The position within the data.
|
|
--@param result This is required when unmarshalling the BODY section, which always comes after
|
|
-- unmarshalling the HEAD. It is the result returned for this parameter during the
|
|
-- HEAD unmarshall. If the referent_id was '0', then this function doesn't unmarshall
|
|
-- anything.
|
|
--@return (pos, result) The new position in <code>data</code>, and a table representing the datatype.
|
|
local function unmarshall_srvsvc_NetSessInfo10(location, data, pos, result)
|
|
stdnse.debug4("MSRPC: Entering unmarshall_srvsvc_NetSessInfo10()")
|
|
if(result == nil) then
|
|
result = {}
|
|
end
|
|
|
|
if(location == HEAD or location == ALL) then
|
|
pos, result['client'] = unmarshall_ptr(HEAD, data, pos, unmarshall_unicode, {true})
|
|
pos, result['user'] = unmarshall_ptr(HEAD, data, pos, unmarshall_unicode, {true})
|
|
pos, result['time'] = unmarshall_int32(data, pos)
|
|
pos, result['idle_time'] = unmarshall_int32(data, pos)
|
|
end
|
|
|
|
if(location == BODY or location == ALL) then
|
|
pos, result['client'] = unmarshall_ptr(BODY, data, pos, unmarshall_unicode, {true}, result['client'])
|
|
pos, result['user'] = unmarshall_ptr(BODY, data, pos, unmarshall_unicode, {true}, result['user'])
|
|
end
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_srvsvc_NetSessInfo10()")
|
|
return pos, result
|
|
end
|
|
|
|
---Marshall a NetSessCtr (session container) type 10.
|
|
--
|
|
--It is a simple array with the following definition:
|
|
--
|
|
--<code>
|
|
-- typedef struct {
|
|
-- uint32 count;
|
|
-- [size_is(count)] srvsvc_NetSessInfo10 *array;
|
|
-- } srvsvc_NetSessCtr10;
|
|
--</code>
|
|
--
|
|
--@param NetSessCtr10 A table representing the structure.
|
|
--@return A string representing the marshalled data.
|
|
function marshall_srvsvc_NetSessCtr10(NetSessCtr10)
|
|
local i
|
|
local result = ""
|
|
stdnse.debug4("MSRPC: Entering marshall_srvsvc_NetSessCtr10()")
|
|
|
|
if(NetSessCtr10 == nil) then
|
|
result = result .. bin.pack("<I", 0)
|
|
else
|
|
local array = NetSessCtr10['array']
|
|
local marshall = nil
|
|
|
|
if(array == nil) then
|
|
result = result .. bin.pack("<I", 0)
|
|
else
|
|
result = result .. bin.pack("<I", #array) -- count
|
|
|
|
-- Build the array that we can marshall
|
|
marshall = {}
|
|
for i = 1, #array, 1 do
|
|
marshall[i] = {}
|
|
marshall[i]['func'] = marshall_srvsvc_NetSessInfo10
|
|
marshall[i]['args'] = {array[i]['client'], array[i]['user'], array[i]['time'], array[i]['idle_time']}
|
|
end
|
|
end
|
|
|
|
result = result .. marshall_ptr(ALL, marshall_array, {marshall}, marshall) -- array
|
|
end
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_srvsvc_NetSessCtr10()")
|
|
return result
|
|
end
|
|
|
|
---Unmarshall a NetSessCtr (session container) type 10. See the marshall function for the definition.
|
|
--
|
|
--@param data The data packet.
|
|
--@param pos The position within the data.
|
|
--@return (pos, result) The new position in <code>data</code>, and a table representing the datatype.
|
|
function unmarshall_srvsvc_NetSessCtr10(data, pos)
|
|
local count
|
|
local result = {}
|
|
stdnse.debug4("MSRPC: Entering unmarshall_srvsvc_NetSessCtr10()")
|
|
|
|
pos, count = unmarshall_int32(data, pos)
|
|
|
|
pos, result['array'] = unmarshall_ptr(ALL, data, pos, unmarshall_array, {count, unmarshall_srvsvc_NetSessInfo10, {}})
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_srvsvc_NetSessCtr10()")
|
|
return pos, result
|
|
end
|
|
|
|
---Marshall the top-level NetShareCtr. This is a union of a bunch of different containers:
|
|
--
|
|
--<code>
|
|
-- typedef union {
|
|
-- [case(0)] srvsvc_NetSessCtr0 *ctr0;
|
|
-- [case(1)] srvsvc_NetSessCtr1 *ctr1;
|
|
-- [case(2)] srvsvc_NetSessCtr2 *ctr2;
|
|
-- [case(10)] srvsvc_NetSessCtr10 *ctr10;
|
|
-- [case(502)] srvsvc_NetSessCtr502 *ctr502;
|
|
-- [default] ;
|
|
-- } srvsvc_NetSessCtr;
|
|
--</code>
|
|
--
|
|
-- Not all of them are implemented, however; look at the code to see which are implemented (at the
|
|
-- time of this writing, it's just 10).
|
|
--
|
|
--@param level The level to request. Different levels will return different results, but also require
|
|
-- different access levels to call.
|
|
--@param data The data to populate the array with. Depending on the level, this data will be different.
|
|
--@return A string representing the marshalled data.
|
|
function marshall_srvsvc_NetSessCtr(level, data)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering marshall_srvsvc_NetShareCtr()")
|
|
|
|
if(level == 10) then
|
|
result = bin.pack("<IA", level, marshall_ptr(ALL, marshall_srvsvc_NetSessCtr10, {data}, data))
|
|
else
|
|
stdnse.debug1("MSRPC: ERROR: Script requested an unknown level for srvsvc_NetSessCtr")
|
|
result = nil
|
|
end
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_srvsvc_NetShareCtr()")
|
|
return result
|
|
end
|
|
|
|
---Unmarshall the top-level NetShareCtr. This is a union; see the marshall function for more information.
|
|
--
|
|
--@param data The data being processed.
|
|
--@param pos The position within <code>data</code>
|
|
--@return (pos, result) The new position in <code>data</code>, and a table representing the datatype. Can be
|
|
-- <code>nil</code> if there's an error.
|
|
function unmarshall_srvsvc_NetSessCtr(data, pos)
|
|
local level
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering unmarshall_srvsvc_NetSessCtr()")
|
|
|
|
pos, level = bin.unpack("<I", data, pos)
|
|
|
|
if(level == 10) then
|
|
pos, result = unmarshall_ptr(ALL, data, pos, unmarshall_srvsvc_NetSessCtr10, {})
|
|
else
|
|
stdnse.debug1("MSRPC: ERROR: Invalid level returned by NetSessCtr: %d\n", level)
|
|
pos, result = nil, nil
|
|
end
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_srvsvc_NetSessCtr()")
|
|
return pos, result
|
|
end
|
|
|
|
|
|
---Unmarshall a <code>srvsvc_Statistics</code> packet. This is basically a great big struct:
|
|
--
|
|
--<code>
|
|
-- typedef struct {
|
|
-- uint32 start;
|
|
-- uint32 fopens;
|
|
-- uint32 devopens;
|
|
-- uint32 jobsqueued;
|
|
-- uint32 sopens;
|
|
-- uint32 stimeouts;
|
|
-- uint32 serrorout;
|
|
-- uint32 pwerrors;
|
|
-- uint32 permerrors;
|
|
-- uint32 syserrors;
|
|
-- uint32 bytessent_low;
|
|
-- uint32 bytessent_high;
|
|
-- uint32 bytesrcvd_low;
|
|
-- uint32 bytesrcvd_high;
|
|
-- uint32 avresponse;
|
|
-- uint32 reqbufneed;
|
|
-- uint32 bigbufneed;
|
|
-- } srvsvc_Statistics;
|
|
--</code>
|
|
--
|
|
-- Note that Wireshark (at least, the version I'm using, 1.0.3) gets this wrong, so be careful.
|
|
--
|
|
--@param data The data being processed.
|
|
--@param pos The position within <code>data</code>
|
|
--@return (pos, result) The new position in <code>data</code>, and a table representing the datatype.
|
|
function unmarshall_srvsvc_Statistics(data, pos)
|
|
local response = {}
|
|
stdnse.debug4("MSRPC: Entering unmarshall_srvsvc_Statistics()")
|
|
|
|
pos, response['start'] = unmarshall_int32(data, pos)
|
|
pos, response['fopens'] = unmarshall_int32(data, pos)
|
|
pos, response['devopens'] = unmarshall_int32(data, pos)
|
|
pos, response['jobsqueued'] = unmarshall_int32(data, pos)
|
|
pos, response['sopens'] = unmarshall_int32(data, pos)
|
|
pos, response['stimeouts'] = unmarshall_int32(data, pos)
|
|
pos, response['serrorout'] = unmarshall_int32(data, pos)
|
|
pos, response['pwerrors'] = unmarshall_int32(data, pos)
|
|
pos, response['permerrors'] = unmarshall_int32(data, pos)
|
|
pos, response['syserrors'] = unmarshall_int32(data, pos)
|
|
pos, response['bytessent_low'] = unmarshall_int32(data, pos)
|
|
pos, response['bytessent_high'] = unmarshall_int32(data, pos)
|
|
pos, response['bytesrcvd_low'] = unmarshall_int32(data, pos)
|
|
pos, response['bytesrcvd_high'] = unmarshall_int32(data, pos)
|
|
pos, response['avresponse'] = unmarshall_int32(data, pos)
|
|
pos, response['reqbufneed'] = unmarshall_int32(data, pos)
|
|
pos, response['bigbufneed'] = unmarshall_int32(data, pos)
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_srvsvc_Statistics()")
|
|
return pos, response
|
|
end
|
|
|
|
---Unmarshalls a <code>srvsvc_Statistics</code> as a pointer. Wireshark fails to do this, and ends
|
|
-- up parsing the packet wrong, so take care when packetlogging.
|
|
--
|
|
-- See <code>unmarshall_srvsvc_Statistics</code> for more information.
|
|
--
|
|
--@param data The data being processed.
|
|
--@param pos The position within <code>data</code>
|
|
--@return (pos, result) The new position in <code>data</code>, and a table representing the datatype.
|
|
function unmarshall_srvsvc_Statistics_ptr(data, pos)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering unmarshall_srvsvc_Statistics_ptr()")
|
|
|
|
pos, result = unmarshall_ptr(ALL, data, pos, unmarshall_srvsvc_Statistics, {})
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_srvsvc_Statistics_ptr()")
|
|
return pos, result
|
|
end
|
|
|
|
|
|
|
|
----------------------------------
|
|
-- SAMR
|
|
-- (dependencies: MISC, LSA, SECURITY)
|
|
----------------------------------
|
|
|
|
local samr_ConnectAccessMask =
|
|
{
|
|
SAMR_ACCESS_CONNECT_TO_SERVER = 0x00000001,
|
|
SAMR_ACCESS_SHUTDOWN_SERVER = 0x00000002,
|
|
SAMR_ACCESS_INITIALIZE_SERVER = 0x00000004,
|
|
SAMR_ACCESS_CREATE_DOMAIN = 0x00000008,
|
|
SAMR_ACCESS_ENUM_DOMAINS = 0x00000010,
|
|
SAMR_ACCESS_OPEN_DOMAIN = 0x00000020
|
|
}
|
|
local samr_ConnectAccessMask_str =
|
|
{
|
|
SAMR_ACCESS_CONNECT_TO_SERVER = "Connect to server",
|
|
SAMR_ACCESS_SHUTDOWN_SERVER = "Shutdown server",
|
|
SAMR_ACCESS_INITIALIZE_SERVER = "Initialize server",
|
|
SAMR_ACCESS_CREATE_DOMAIN = "Create domain",
|
|
SAMR_ACCESS_ENUM_DOMAINS = "Enum domains",
|
|
SAMR_ACCESS_OPEN_DOMAIN = "Open domain"
|
|
}
|
|
|
|
---Marshall a <code>samr_ConnectAccessMask</code>. This datatype is tied to the table above with that
|
|
-- name.
|
|
--
|
|
--@param accessmask The value to marshall, as a string
|
|
--@return The marshalled integer representing the given value, or <code>nil</code> if it wasn't
|
|
-- found.
|
|
function marshall_samr_ConnectAccessMask(accessmask)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering marshall_samr_ConnectAccessMask()")
|
|
|
|
result = marshall_Enum32(accessmask, samr_ConnectAccessMask)
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_samr_ConnectAccessMask()")
|
|
return result
|
|
end
|
|
|
|
---Unmarshall a <code>samr_ConnectAccessMask</code>. This datatype is tied to the table with that name.
|
|
--
|
|
--@param data The data packet.
|
|
--@param pos The position within the data.
|
|
--@return (pos, result) The new position in <code>data</code>, and a table representing the datatype.
|
|
function unmarshall_samr_ConnectAccessMask(data, pos)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering unmarshall_samr_ConnectAccessMask()")
|
|
|
|
pos, result = unmarshall_Enum32(data, pos, samr_ConnectAccessMask)
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_samr_ConnectAccessMask()")
|
|
return pos, result
|
|
end
|
|
|
|
---Convert a <code>samr_ConnectAccessMask</code> value to a string that can be shown to the user. This is
|
|
-- based on the <code>_str</code> table.
|
|
--
|
|
--@param val The string value (returned by the <code>unmarshall_</code> function) to convert.
|
|
--@return A string suitable for displaying to the user, or <code>nil</code> if it wasn't found.
|
|
function samr_ConnectAccessMask_tostr(val)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering samr_ConnectAccessMask_tostr()")
|
|
|
|
result = samr_ConnectAccessMask_str[val]
|
|
|
|
stdnse.debug4("MSRPC: Leaving samr_ConnectAccessMask_tostr()")
|
|
return result
|
|
end
|
|
|
|
local samr_DomainAccessMask =
|
|
{
|
|
DOMAIN_ACCESS_LOOKUP_INFO_1 = 0x00000001,
|
|
DOMAIN_ACCESS_SET_INFO_1 = 0x00000002,
|
|
DOMAIN_ACCESS_LOOKUP_INFO_2 = 0x00000004,
|
|
DOMAIN_ACCESS_SET_INFO_2 = 0x00000008,
|
|
DOMAIN_ACCESS_CREATE_USER = 0x00000010,
|
|
DOMAIN_ACCESS_CREATE_GROUP = 0x00000020,
|
|
DOMAIN_ACCESS_CREATE_ALIAS = 0x00000040,
|
|
DOMAIN_ACCESS_LOOKUP_ALIAS = 0x00000080,
|
|
DOMAIN_ACCESS_ENUM_ACCOUNTS = 0x00000100,
|
|
DOMAIN_ACCESS_OPEN_ACCOUNT = 0x00000200,
|
|
DOMAIN_ACCESS_SET_INFO_3 = 0x00000400
|
|
}
|
|
local samr_DomainAccessMask_str =
|
|
{
|
|
DOMAIN_ACCESS_LOOKUP_INFO_1 = "Lookup info (1)",
|
|
DOMAIN_ACCESS_SET_INFO_1 = "Set info (1)",
|
|
DOMAIN_ACCESS_LOOKUP_INFO_2 = "Lookup info (2)",
|
|
DOMAIN_ACCESS_SET_INFO_2 = "Set info (2)",
|
|
DOMAIN_ACCESS_CREATE_USER = "Create user",
|
|
DOMAIN_ACCESS_CREATE_GROUP = "Create group",
|
|
DOMAIN_ACCESS_CREATE_ALIAS = "Create alias",
|
|
DOMAIN_ACCESS_LOOKUP_ALIAS = "Lookup alias",
|
|
DOMAIN_ACCESS_ENUM_ACCOUNTS = "Enum accounts",
|
|
DOMAIN_ACCESS_OPEN_ACCOUNT = "Open account",
|
|
DOMAIN_ACCESS_SET_INFO_3 = "Set info (3)"
|
|
}
|
|
|
|
---Marshall a <code>samr_DomainAccessMask</code>. This datatype is tied to the table above with that
|
|
-- name.
|
|
--
|
|
--@param accessmask The value to marshall, as a string
|
|
--@return The marshalled integer representing the given value, or <code>nil</code> if it wasn't
|
|
-- found.
|
|
function marshall_samr_DomainAccessMask(accessmask)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering marshall_samr_DomainAccessMask()")
|
|
|
|
result = marshall_Enum32(accessmask, samr_DomainAccessMask)
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_samr_DomainAccessMask()")
|
|
return result
|
|
end
|
|
|
|
---Unmarshall a <code>samr_DomainAccessMask</code>. This datatype is tied to the table with that name.
|
|
--
|
|
--@param data The data packet.
|
|
--@param pos The position within the data.
|
|
--@return (pos, result) The new position in <code>data</code>, and a table representing the datatype.
|
|
function unmarshall_samr_DomainAccessMask(data, pos)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering unmarshall_samr_DomainAccessMask()")
|
|
|
|
pos, result = unmarshall_Enum32(data, pos, samr_DomainAccessMask)
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_samr_DomainAccessMask()")
|
|
return pos, result
|
|
end
|
|
|
|
---Convert a <code>samr_DomainAccessMask</code> value to a string that can be shown to the user. This is
|
|
-- based on the <code>_str</code> table.
|
|
--
|
|
--@param val The string value (returned by the <code>unmarshall_</code> function) to convert.
|
|
--@return A string suitable for displaying to the user, or <code>nil</code> if it wasn't found.
|
|
function samr_DomainAccessMask_tostr(val)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering samr_DomainAccessMask_tostr()")
|
|
|
|
result = samr_DomainAccessMask_str[val]
|
|
|
|
stdnse.debug4("MSRPC: Leaving samr_DomainAccessMask_tostr()")
|
|
return result
|
|
end
|
|
|
|
local samr_AcctFlags =
|
|
{
|
|
ACB_NONE = 0x0000000,
|
|
ACB_DISABLED = 0x00000001, -- User account disabled
|
|
ACB_HOMDIRREQ = 0x00000002, -- Home directory required
|
|
ACB_PWNOTREQ = 0x00000004, -- User password not required
|
|
ACB_TEMPDUP = 0x00000008, -- Temporary duplicate account
|
|
ACB_NORMAL = 0x00000010, -- Normal user account
|
|
ACB_MNS = 0x00000020, -- MNS logon user account
|
|
ACB_DOMTRUST = 0x00000040, -- Interdomain trust account
|
|
ACB_WSTRUST = 0x00000080, -- Workstation trust account
|
|
ACB_SVRTRUST = 0x00000100, -- Server trust account
|
|
ACB_PWNOEXP = 0x00000200, -- User password does not expire
|
|
ACB_AUTOLOCK = 0x00000400, -- Account auto locked
|
|
ACB_ENC_TXT_PWD_ALLOWED = 0x00000800, -- Encryped text password is allowed
|
|
ACB_SMARTCARD_REQUIRED = 0x00001000, -- Smart Card required
|
|
ACB_TRUSTED_FOR_DELEGATION = 0x00002000, -- Trusted for Delegation
|
|
ACB_NOT_DELEGATED = 0x00004000, -- Not delegated
|
|
ACB_USE_DES_KEY_ONLY = 0x00008000, -- Use DES key only
|
|
ACB_DONT_REQUIRE_PREAUTH = 0x00010000, -- Preauth not required
|
|
ACB_PW_EXPIRED = 0x00020000, -- Password Expired
|
|
ACB_NO_AUTH_DATA_REQD = 0x00080000 -- No authorization data required
|
|
}
|
|
local samr_AcctFlags_str =
|
|
{
|
|
ACB_NONE = "n/a",
|
|
ACB_DISABLED = "Account disabled",
|
|
ACB_HOMDIRREQ = "Home directory required",
|
|
ACB_PWNOTREQ = "Password not required",
|
|
ACB_TEMPDUP = "Temporary duplicate account",
|
|
ACB_NORMAL = "Normal user account",
|
|
ACB_MNS = "MNS logon user account",
|
|
ACB_DOMTRUST = "Interdomain trust account",
|
|
ACB_WSTRUST = "Workstation trust account",
|
|
ACB_SVRTRUST = "Server trust account",
|
|
ACB_PWNOEXP = "Password does not expire",
|
|
ACB_AUTOLOCK = "Auto locked",
|
|
ACB_ENC_TXT_PWD_ALLOWED = "Encryped text password is allowed",
|
|
ACB_SMARTCARD_REQUIRED = "Smart Card required",
|
|
ACB_TRUSTED_FOR_DELEGATION = "Trusted for Delegation",
|
|
ACB_NOT_DELEGATED = "Not delegated",
|
|
ACB_USE_DES_KEY_ONLY = "Use DES key only",
|
|
ACB_DONT_REQUIRE_PREAUTH = "Preauth not required",
|
|
ACB_PW_EXPIRED = "Password Expired",
|
|
ACB_NO_AUTH_DATA_REQD = "No authorization data required"
|
|
}
|
|
|
|
---Marshall a <code>samr_AcctFlags</code>. This datatype is tied to the table above with that
|
|
-- name.
|
|
--
|
|
--@param flags The value to marshall, as a string
|
|
--@return The marshalled integer representing the given value, or <code>nil</code> if it wasn't
|
|
-- found.
|
|
function marshall_samr_AcctFlags(flags)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering marshall_samr_AcctFlags()")
|
|
|
|
result = marshall_Enum32(flags, samr_AcctFlags)
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_samr_AcctFlags()")
|
|
return result
|
|
end
|
|
|
|
---Unmarshall a <code>samr_AcctFlags</code>. This datatype is tied to the table with that name.
|
|
--
|
|
--@param data The data packet.
|
|
--@param pos The position within the data.
|
|
--@return (pos, str) The new position, and the string representing the datatype.
|
|
function unmarshall_samr_AcctFlags(data, pos)
|
|
local str
|
|
stdnse.debug4("MSRPC: Entering unmarshall_samr_AcctFlags()")
|
|
|
|
pos, str = unmarshall_Enum32_array(data, pos, samr_AcctFlags)
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_samr_AcctFlags()")
|
|
return pos, str
|
|
end
|
|
|
|
---Convert a <code>samr_AcctFlags</code> value to a string that can be shown to the user. This is
|
|
-- based on the <code>_str</code> table.
|
|
--
|
|
--@param val The string value (returned by the <code>unmarshall_</code> function) to convert.
|
|
--@return A string suitable for displaying to the user, or <code>nil</code> if it wasn't found.
|
|
function samr_AcctFlags_tostr(val)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering samr_AcctFlags_tostr()")
|
|
|
|
result = samr_AcctFlags_str[val]
|
|
|
|
stdnse.debug4("MSRPC: Leaving samr_AcctFlags_tostr()")
|
|
return result
|
|
end
|
|
|
|
local samr_PasswordProperties =
|
|
{
|
|
DOMAIN_PASSWORD_COMPLEX = 0x00000001,
|
|
DOMAIN_PASSWORD_NO_ANON_CHANGE = 0x00000002,
|
|
DOMAIN_PASSWORD_NO_CLEAR_CHANGE = 0x00000004,
|
|
DOMAIN_PASSWORD_LOCKOUT_ADMINS = 0x00000008,
|
|
DOMAIN_PASSWORD_STORE_CLEARTEXT = 0x00000010,
|
|
DOMAIN_REFUSE_PASSWORD_CHANGE = 0x00000020
|
|
}
|
|
local samr_PasswordProperties_str =
|
|
{
|
|
DOMAIN_PASSWORD_COMPLEX = "Complexity requirements exist",
|
|
DOMAIN_PASSWORD_NO_ANON_CHANGE = "Must be logged in to change password",
|
|
DOMAIN_PASSWORD_NO_CLEAR_CHANGE = "Cannot change passwords in cleartext",
|
|
DOMAIN_PASSWORD_LOCKOUT_ADMINS = "Admin account can be locked out",
|
|
DOMAIN_PASSWORD_STORE_CLEARTEXT = "Cleartext passwords can be stored",
|
|
DOMAIN_REFUSE_PASSWORD_CHANGE = "Passwords cannot be changed"
|
|
}
|
|
|
|
---Marshall a <code>samr_PasswordProperties</code>. This datatype is tied to the table above with that
|
|
-- name.
|
|
--
|
|
--@param properties The value to marshall, as a string
|
|
--@return The marshalled integer representing the given value, or <code>nil</code> if it wasn't
|
|
-- found.
|
|
function marshall_samr_PasswordProperties(properties)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering marshall_samr_PasswordProperties()")
|
|
|
|
result = marshall_Enum32(properties, samr_PasswordProperties)
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_samr_PasswordProperties()")
|
|
return result
|
|
end
|
|
|
|
---Unmarshall a <code>samr_PasswordProperties</code>. This datatype is tied to the table with that name.
|
|
--
|
|
--@param data The data packet.
|
|
--@param pos The position within the data.
|
|
--@return (pos, str) The new position, and the string representing the datatype.
|
|
function unmarshall_samr_PasswordProperties(data, pos)
|
|
local str
|
|
stdnse.debug4("MSRPC: Entering unmarshall_samr_PasswordProperties()")
|
|
|
|
pos, str = unmarshall_Enum32_array(data, pos, samr_PasswordProperties)
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_samr_PasswordProperties()")
|
|
return pos, str
|
|
end
|
|
|
|
---Convert a <code>samr_PasswordProperties</code> value to a string that can be shown to the user. This is
|
|
-- based on the <code>_str</code> table.
|
|
--
|
|
--@param val The string value (returned by the <code>unmarshall_</code> function) to convert.
|
|
--@return A string suitable for displaying to the user, or <code>nil</code> if it wasn't found.
|
|
function samr_PasswordProperties_tostr(val)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering samr_PasswordProperties_tostr()")
|
|
|
|
result = samr_PasswordProperties_str[val]
|
|
|
|
stdnse.debug4("MSRPC: Leaving samr_PasswordProperties_tostr()")
|
|
return result
|
|
end
|
|
|
|
|
|
---Unmarshall a samr_SamEntry struct
|
|
--
|
|
--<code>
|
|
-- typedef struct {
|
|
-- uint32 idx;
|
|
-- lsa_String name;
|
|
-- } samr_SamEntry;
|
|
--</code>
|
|
--
|
|
--@param location The part of the pointer wanted, either HEAD (for the data itself), BODY
|
|
-- (for nothing, since this isn't a pointer), or ALL (for the data). Generally, unless the
|
|
-- referent_id is split from the data (for example, in an array), you will want
|
|
-- ALL.
|
|
--@param data The data being processed.
|
|
--@param pos The position within <code>data</code>.
|
|
--@param result This is required when unmarshalling the BODY section, which always comes after
|
|
-- unmarshalling the HEAD. It is the result returned for this parameter during the
|
|
-- HEAD unmarshall. If the referent_id was '0', then this function doesn't unmarshall
|
|
-- anything.
|
|
--@return (pos, result) The new position in <code>data</code>, and a table representing the datatype.
|
|
local function unmarshall_samr_SamEntry(location, data, pos, result)
|
|
stdnse.debug4("MSRPC: Entering unmarshall_samr_SamEntry()")
|
|
if(result == nil) then
|
|
result = {}
|
|
end
|
|
|
|
if(location == HEAD or location == ALL) then
|
|
pos, result['idx'] = unmarshall_int32(data, pos)
|
|
pos, result['name'] = unmarshall_lsa_String_internal(HEAD, data, pos)
|
|
end
|
|
|
|
|
|
if(location == BODY or location == ALL) then
|
|
pos, result['name'] = unmarshall_lsa_String_internal(BODY, data, pos, result['name'])
|
|
end
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_samr_SamEntry()")
|
|
return pos, result
|
|
end
|
|
|
|
---Unmarshall a samr_SamArray struct
|
|
--
|
|
--<code>
|
|
-- typedef struct {
|
|
-- uint32 count;
|
|
-- [size_is(count)] samr_SamEntry *entries;
|
|
-- } samr_SamArray;
|
|
--</code>
|
|
--
|
|
--@param data The data being processed.
|
|
--@param pos The position within <code>data</code>.
|
|
--@return (pos, result) The new position in <code>data</code>, and a table representing the datatype.
|
|
function unmarshall_samr_SamArray(data, pos)
|
|
local result = {}
|
|
stdnse.debug4("MSRPC: Entering unmarshall_samr_SamArray()")
|
|
|
|
pos, result['count'] = unmarshall_int32(data, pos)
|
|
pos, result['entries'] = unmarshall_ptr(ALL, data, pos, unmarshall_array, {result['count'], unmarshall_samr_SamEntry, {}})
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_samr_SamArray()")
|
|
return pos, result
|
|
end
|
|
|
|
---Unmarshall a pointer to a <code>samr_SamArray</code> type. See <code>unmarshall_samr_SamArray</code> for
|
|
-- more information.
|
|
--
|
|
--@param data The data being processed.
|
|
--@param pos The position within <code>data</code>.
|
|
--@return (pos, result) The new position in <code>data</code>, and a table representing the datatype.
|
|
function unmarshall_samr_SamArray_ptr(data, pos)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering unmarshall_samr_SamArray_ptr()")
|
|
|
|
pos, result = unmarshall_ptr(ALL, data, pos, unmarshall_samr_SamArray, {})
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_samr_SamArray_ptr()")
|
|
return pos, result
|
|
end
|
|
|
|
---Unmarshall a samr_DispEntryGeneral struct
|
|
--
|
|
--<code>
|
|
-- typedef struct {
|
|
-- uint32 idx;
|
|
-- uint32 rid;
|
|
-- samr_AcctFlags acct_flags;
|
|
-- lsa_String account_name;
|
|
-- lsa_String description;
|
|
-- lsa_String full_name;
|
|
-- } samr_DispEntryGeneral;
|
|
--</code>
|
|
--
|
|
--@param location The part of the pointer wanted, either HEAD (for the data itself), BODY
|
|
-- (for nothing, since this isn't a pointer), or ALL (for the data). Generally, unless the
|
|
-- referent_id is split from the data (for example, in an array), you will want
|
|
-- ALL.
|
|
--@param data The data being processed.
|
|
--@param pos The position within <code>data</code>.
|
|
--@param result This is required when unmarshalling the BODY section, which always comes after
|
|
-- unmarshalling the HEAD. It is the result returned for this parameter during the
|
|
-- HEAD unmarshall. If the referent_id was '0', then this function doesn't unmarshall
|
|
-- anything.
|
|
--@return (pos, result) The new position in <code>data</code>, and a table representing the datatype.
|
|
local function unmarshall_samr_DispEntryGeneral(location, data, pos, result)
|
|
stdnse.debug4("MSRPC: Entering unmarshall_samr_DispEntryGeneral()")
|
|
if(result == nil) then
|
|
result = {}
|
|
end
|
|
|
|
if(location == HEAD or location == ALL) then
|
|
pos, result['idx'] = unmarshall_int32(data, pos)
|
|
pos, result['rid'] = unmarshall_int32(data, pos)
|
|
pos, result['acct_flags'] = unmarshall_samr_AcctFlags(data, pos)
|
|
pos, result['account_name'] = unmarshall_lsa_String_internal(HEAD, data, pos)
|
|
pos, result['description'] = unmarshall_lsa_String_internal(HEAD, data, pos)
|
|
pos, result['full_name'] = unmarshall_lsa_String_internal(HEAD, data, pos)
|
|
end
|
|
|
|
|
|
if(location == BODY or location == ALL) then
|
|
pos, result['account_name'] = unmarshall_lsa_String_internal(BODY, data, pos, result['account_name'])
|
|
pos, result['description'] = unmarshall_lsa_String_internal(BODY, data, pos, result['description'])
|
|
pos, result['full_name'] = unmarshall_lsa_String_internal(BODY, data, pos, result['full_name'])
|
|
end
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_samr_DispEntryGeneral()")
|
|
return pos, result
|
|
end
|
|
|
|
---Unmarshall a samr_DispInfoGeneral struct
|
|
--
|
|
--<code>
|
|
-- typedef struct {
|
|
-- uint32 count;
|
|
-- [size_is(count)] samr_DispEntryGeneral *entries;
|
|
-- } samr_DispInfoGeneral;
|
|
--</code>
|
|
--
|
|
--@param data The data being processed.
|
|
--@param pos The position within <code>data</code>.
|
|
--@return (pos, result) The new position in <code>data</code>, and a table representing the datatype.
|
|
function unmarshall_samr_DispInfoGeneral(data, pos)
|
|
local result = {}
|
|
stdnse.debug4("MSRPC: Entering unmarshall_samr_DispInfoGeneral()")
|
|
|
|
pos, result['count'] = unmarshall_int32(data, pos)
|
|
pos, result['entries'] = unmarshall_ptr(ALL, data, pos, unmarshall_array, {result['count'], unmarshall_samr_DispEntryGeneral, {}})
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_samr_DispInfoGeneral()")
|
|
return pos, result
|
|
end
|
|
|
|
|
|
---Unmarshall a samr_DispInfo struct
|
|
--
|
|
--<code>
|
|
-- typedef [switch_type(uint16)] union {
|
|
-- [case(1)] samr_DispInfoGeneral info1;/* users */
|
|
-- [case(2)] samr_DispInfoFull info2; /* trust accounts? */
|
|
-- [case(3)] samr_DispInfoFullGroups info3; /* groups */
|
|
-- [case(4)] samr_DispInfoAscii info4; /* users */
|
|
-- [case(5)] samr_DispInfoAscii info5; /* groups */
|
|
-- } samr_DispInfo;
|
|
--</code>
|
|
--
|
|
--@param data The data being processed.
|
|
--@param pos The position within <code>data</code>.
|
|
--@return (pos, result) The new position in <code>data</code>, and a table representing the datatype. It may also return
|
|
-- <code>nil</code>, if there was an error.
|
|
function unmarshall_samr_DispInfo(data, pos)
|
|
local level
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering unmarshall_samr_DispInfo()")
|
|
|
|
pos, level = unmarshall_int16(data, pos)
|
|
|
|
if(level == 1) then
|
|
pos, result = unmarshall_samr_DispInfoGeneral(data, pos)
|
|
else
|
|
stdnse.debug1("MSRPC: ERROR: Server returned an unknown level for samr_DispInfo: %d", level)
|
|
pos, result = nil, nil
|
|
end
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_samr_DispInfo()")
|
|
return pos, result
|
|
end
|
|
|
|
---Unmarshall a samr_DomInfo1 struct
|
|
--
|
|
--<code>
|
|
-- typedef struct {
|
|
-- uint16 min_password_length;
|
|
-- uint16 password_history_length;
|
|
-- samr_PasswordProperties password_properties;
|
|
-- /* yes, these are signed. They are in negative 100ns */
|
|
-- dlong max_password_age;
|
|
-- dlong min_password_age;
|
|
-- } samr_DomInfo1;
|
|
--</code>
|
|
--
|
|
--@param data The data being processed.
|
|
--@param pos The position within <code>data</code>.
|
|
--@return (pos, result) The new position in <code>data</code>, and a table representing the datatype.
|
|
function unmarshall_samr_DomInfo1(data, pos)
|
|
local result = {}
|
|
stdnse.debug4("MSRPC: Entering unmarshall_samr_DomInfo1()")
|
|
|
|
pos, result['min_password_length'] = unmarshall_int16(data, pos, false)
|
|
pos, result['password_history_length'] = unmarshall_int16(data, pos, false)
|
|
pos, result['password_properties'] = unmarshall_samr_PasswordProperties(data, pos)
|
|
pos, result['max_password_age'] = unmarshall_hyper(data, pos)
|
|
pos, result['min_password_age'] = unmarshall_hyper(data, pos)
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_samr_DomInfo1()")
|
|
return pos, result
|
|
end
|
|
|
|
---Unmarshall a samr_DomInfo8 struct
|
|
--
|
|
--<code>
|
|
-- typedef struct {
|
|
-- hyper sequence_num;
|
|
-- NTTIME domain_create_time;
|
|
-- } samr_DomInfo8;
|
|
--</code>
|
|
--
|
|
--@param data The data being processed.
|
|
--@param pos The position within <code>data</code>.
|
|
--@return (pos, result) The new position in <code>data</code>, and a table representing the datatype.
|
|
function unmarshall_samr_DomInfo8(data, pos)
|
|
local result = {}
|
|
stdnse.debug4("MSRPC: Entering unmarshall_samr_DomInfo8()")
|
|
|
|
pos, result['sequence_num'] = unmarshall_hyper(data, pos)
|
|
pos, result['domain_create_time'] = unmarshall_NTTIME(data, pos)
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_samr_DomInfo8()")
|
|
return pos, result
|
|
end
|
|
|
|
---Unmarshall a samr_DomInfo12 struct
|
|
--
|
|
--<code>
|
|
-- typedef struct {
|
|
-- hyper lockout_duration;
|
|
-- hyper lockout_window;
|
|
-- uint16 lockout_threshold;
|
|
-- } samr_DomInfo12;
|
|
--</code>
|
|
--
|
|
--@param data The data being processed.
|
|
--@param pos The position within <code>data</code>.
|
|
--@return (pos, result) The new position in <code>data</code>, and a table representing the datatype.
|
|
function unmarshall_samr_DomInfo12(data, pos)
|
|
local result = {}
|
|
stdnse.debug4("MSRPC: Entering unmarshall_samr_DomInfo12()")
|
|
|
|
pos, result['lockout_duration'] = unmarshall_hyper(data, pos)
|
|
pos, result['lockout_window'] = unmarshall_hyper(data, pos)
|
|
pos, result['lockout_threshold'] = unmarshall_int16(data, pos)
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_samr_DomInfo12()")
|
|
return pos, result
|
|
end
|
|
|
|
---Unmarshall a samr_DomainInfo union
|
|
--
|
|
--<code>
|
|
-- typedef [switch_type(uint16)] union {
|
|
-- [case(1)] samr_DomInfo1 info1;
|
|
-- [case(2)] samr_DomInfo2 info2;
|
|
-- [case(3)] samr_DomInfo3 info3;
|
|
-- [case(4)] samr_DomInfo4 info4;
|
|
-- [case(5)] samr_DomInfo5 info5;
|
|
-- [case(6)] samr_DomInfo6 info6;
|
|
-- [case(7)] samr_DomInfo7 info7;
|
|
-- [case(8)] samr_DomInfo8 info8;
|
|
-- [case(9)] samr_DomInfo9 info9;
|
|
-- [case(11)] samr_DomInfo11 info11;
|
|
-- [case(12)] samr_DomInfo12 info12;
|
|
-- [case(13)] samr_DomInfo13 info13;
|
|
-- } samr_DomainInfo;
|
|
--</code>
|
|
--
|
|
--@param data The data being processed.
|
|
--@param pos The position within <code>data</code>.
|
|
--@return (pos, result) The new position in <code>data</code>, and a table representing the datatype. May return
|
|
-- <code>nil</code> if there was an error.
|
|
function unmarshall_samr_DomainInfo(data, pos)
|
|
local level
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering unmarshall_samr_DomainInfo()")
|
|
|
|
pos, level = unmarshall_int16(data, pos)
|
|
|
|
if(level == 1) then
|
|
pos, result = unmarshall_samr_DomInfo1(data, pos)
|
|
elseif(level == 8) then
|
|
pos, result = unmarshall_samr_DomInfo8(data, pos)
|
|
elseif(level == 12) then
|
|
pos, result = unmarshall_samr_DomInfo12(data, pos)
|
|
else
|
|
stdnse.debug1("MSRPC: ERROR: Server returned an unknown level for samr_DomainInfo: %d", level)
|
|
pos, result = nil, nil
|
|
end
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_samr_DomainInfo()")
|
|
return pos, result
|
|
end
|
|
|
|
---Unmarshall a pointer to a <code>samr_DomainInfo</code>. See <code>unmarshall_samr_DomainInfo</code> for
|
|
-- more information.
|
|
--
|
|
--@param data The data being processed.
|
|
--@param pos The position within <code>data</code>.
|
|
--@return (pos, result) The new position in <code>data</code>, and a table representing the datatype. May return
|
|
-- <code>nil</code> if there was an error.
|
|
function unmarshall_samr_DomainInfo_ptr(data, pos)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering unmarshall_samr_DomainInfo_ptr()")
|
|
|
|
pos, result = unmarshall_ptr(ALL, data, pos, unmarshall_samr_DomainInfo, {})
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_samr_DomainInfo_ptr()")
|
|
return pos, result
|
|
end
|
|
|
|
---Unmarshall a samr_Ids struct
|
|
--
|
|
--<code>
|
|
-- typedef struct {
|
|
-- [range(0,1024)] uint32 count;
|
|
-- [size_is(count)] uint32 *ids;
|
|
-- } samr_Ids;
|
|
--</code>
|
|
--
|
|
--@param data The data being processed.
|
|
--@param pos The position within <code>data</code>.
|
|
--@return (pos, result) The new position in <code>data</code>, and a table representing the datatype. May return
|
|
-- <code>nil</code> if there was an error.
|
|
function unmarshall_samr_Ids(data, pos)
|
|
local array
|
|
|
|
pos, array = unmarshall_int32_array_ptr(data, pos)
|
|
|
|
return pos, array
|
|
end
|
|
|
|
----------------------------------
|
|
-- SVCCTL
|
|
-- (dependencies: MISC)
|
|
----------------------------------
|
|
|
|
local svcctl_ControlCode =
|
|
{
|
|
SERVICE_CONTROL_CONTINUE = 0x00000003,
|
|
SERVICE_CONTROL_INTERROGATE = 0x00000004,
|
|
SERVICE_CONTROL_NETBINDADD = 0x00000007,
|
|
SERVICE_CONTROL_NETBINDDISABLE = 0x0000000A,
|
|
SERVICE_CONTROL_NETBINDENABLE = 0x00000009,
|
|
SERVICE_CONTROL_NETBINDREMOVE = 0x00000008,
|
|
SERVICE_CONTROL_PARAMCHANGE = 0x00000006,
|
|
SERVICE_CONTROL_PAUSE = 0x00000002,
|
|
SERVICE_CONTROL_STOP = 0x00000001,
|
|
}
|
|
local svcctl_ControlCode_str =
|
|
{
|
|
SERVICE_CONTROL_CONTINUE = "Notifies a paused service that it should resume.",
|
|
SERVICE_CONTROL_INTERROGATE = "Notifies a service that it should report its current status information to the service control manager.",
|
|
SERVICE_CONTROL_NETBINDADD = "Notifies a network service that there is a new component for binding. Deprecated.",
|
|
SERVICE_CONTROL_NETBINDDISABLE = "Notifies a network service that one of its bindings has been disabled. Deprecated.",
|
|
SERVICE_CONTROL_NETBINDENABLE = "Notifies a network service that a disabled binding has been enabled. Deprecated",
|
|
SERVICE_CONTROL_NETBINDREMOVE = "Notifies a network service that a component for binding has been removed. Deprecated",
|
|
SERVICE_CONTROL_PARAMCHANGE = "Notifies a service that its startup parameters have changed.",
|
|
SERVICE_CONTROL_PAUSE = "Notifies a service that it should pause.",
|
|
SERVICE_CONTROL_STOP = "Notifies a service that it should stop."
|
|
}
|
|
|
|
|
|
---Marshall a <code>svcctl_ControlCode</code>. This datatype is tied to the table above with that
|
|
-- name.
|
|
--
|
|
--@param flags The value to marshall, as a string
|
|
--@return The marshalled integer representing the given value, or <code>nil</code> if it wasn't
|
|
-- found.
|
|
function marshall_svcctl_ControlCode(flags)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering marshall_svcctl_ControlCode()")
|
|
|
|
result = marshall_Enum32(flags, svcctl_ControlCode)
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_svcctl_ControlCode()")
|
|
return result
|
|
end
|
|
|
|
---Unmarshall a <code>svcctl_ControlCode</code>. This datatype is tied to the table with that name.
|
|
--
|
|
--@param data The data packet.
|
|
--@param pos The position within the data.
|
|
--@return (pos, str) The new position, and the string representing the datatype.
|
|
function unmarshall_svcctl_ControlCode(data, pos)
|
|
local str
|
|
stdnse.debug4("MSRPC: Entering unmarshall_svcctl_ControlCode()")
|
|
|
|
pos, str = unmarshall_Enum32_array(data, pos, svcctl_ControlCode)
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_svcctl_ControlCode()")
|
|
return pos, str
|
|
end
|
|
|
|
---Convert a <code>svcctl_ControlCode</code> value to a string that can be shown to the user. This is
|
|
-- based on the <code>_str</code> table.
|
|
--
|
|
--@param val The string value (returned by the <code>unmarshall_</code> function) to convert.
|
|
--@return A string suitable for displaying to the user, or <code>nil</code> if it wasn't found.
|
|
function svcctl_ControlCode_tostr(val)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering svcctl_ControlCode_tostr()")
|
|
|
|
result = svcctl_ControlCode_str[val]
|
|
|
|
stdnse.debug4("MSRPC: Leaving svcctl_ControlCode_tostr()")
|
|
return result
|
|
end
|
|
|
|
local svcctl_Type =
|
|
{
|
|
SERVICE_TYPE_KERNEL_DRIVER = 0x01,
|
|
SERVICE_TYPE_FS_DRIVER = 0x02,
|
|
SERVICE_TYPE_ADAPTER = 0x04,
|
|
SERVICE_TYPE_RECOGNIZER_DRIVER = 0x08,
|
|
SERVICE_TYPE_DRIVER = 0x0B,
|
|
SERVICE_TYPE_WIN32_OWN_PROCESS = 0x10,
|
|
SERVICE_TYPE_WIN32_SHARE_PROCESS = 0x20,
|
|
SERVICE_TYPE_WIN32 = 0x30
|
|
}
|
|
|
|
---Marshall a <code>svcctl_Type</code>. This datatype is tied to the table above with that
|
|
-- name.
|
|
--
|
|
--@param flags The value to marshall, as a string
|
|
--@return The marshalled integer representing the given value, or <code>nil</code> if it wasn't
|
|
-- found.
|
|
function marshall_svcctl_Type(flags)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering marshall_svcctl_Type()")
|
|
|
|
result = marshall_Enum32(flags, svcctl_Type)
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_svcctl_Type()")
|
|
return result
|
|
end
|
|
|
|
---Unmarshall a <code>svcctl_Type</code>. This datatype is tied to the table with that name.
|
|
--
|
|
--@param data The data packet.
|
|
--@param pos The position within the data.
|
|
--@return (pos, str) The new position, and the string representing the datatype.
|
|
function unmarshall_svcctl_Type(data, pos)
|
|
local str
|
|
stdnse.debug4("MSRPC: Entering unmarshall_svcctl_Type()")
|
|
|
|
pos, str = unmarshall_Enum32_array(data, pos, svcctl_Type)
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_svcctl_Type()")
|
|
return pos, str
|
|
end
|
|
|
|
--[[Convert a <code>svcctl_Type</code> value to a string that can be shown to the user. This is
|
|
-- based on the <code>_str</code> table.
|
|
--
|
|
--@param val The string value (returned by the <code>unmarshall_</code> function) to convert.
|
|
--@return A string suitable for displaying to the user, or <code>nil</code> if it wasn't found.
|
|
function svcctl_Type_tostr(val)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering svcctl_Type_tostr()")
|
|
|
|
result = svcctl_Type_str[val]
|
|
|
|
stdnse.debug4("MSRPC: Leaving svcctl_Type_tostr()")
|
|
return result
|
|
end]]--
|
|
|
|
|
|
|
|
local svcctl_State =
|
|
{
|
|
SERVICE_STATE_ACTIVE = 0x01,
|
|
SERVICE_STATE_INACTIVE = 0x02,
|
|
SERVICE_STATE_ALL = 0x03
|
|
}
|
|
---Marshall a <code>svcctl_State</code>. This datatype is tied to the table above with that
|
|
-- name.
|
|
--
|
|
--@param flags The value to marshall, as a string
|
|
--@return The marshalled integer representing the given value, or <code>nil</code> if it wasn't
|
|
-- found.
|
|
function marshall_svcctl_State(flags)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering marshall_svcctl_State()")
|
|
|
|
result = marshall_Enum32(flags, svcctl_State)
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_svcctl_State()")
|
|
return result
|
|
end
|
|
|
|
---Unmarshall a <code>svcctl_State</code>. This datatype is tied to the table with that name.
|
|
--
|
|
--@param data The data packet.
|
|
--@param pos The position within the data.
|
|
--@return (pos, str) The new position, and the string representing the datatype.
|
|
function unmarshall_svcctl_State(data, pos)
|
|
local str
|
|
stdnse.debug4("MSRPC: Entering unmarshall_svcctl_State()")
|
|
|
|
pos, str = unmarshall_Enum32_array(data, pos, svcctl_State)
|
|
|
|
stdnse.debug4("MSRPC: Leaving unmarshall_svcctl_State()")
|
|
return pos, str
|
|
end
|
|
|
|
--[[Convert a <code>svcctl_State</code> value to a string that can be shown to the user. This is
|
|
-- based on the <code>_str</code> table.
|
|
--
|
|
--@param val The string value (returned by the <code>unmarshall_</code> function) to convert.
|
|
--@return A string suitable for displaying to the user, or <code>nil</code> if it wasn't found.
|
|
function svcctl_State_tostr(val)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering svcctl_State_tostr()")
|
|
|
|
result = svcctl_State_str[val]
|
|
|
|
stdnse.debug4("MSRPC: Leaving svcctl_State_tostr()")
|
|
return result
|
|
end]]--
|
|
|
|
|
|
---Unmarshall a SERVICE_STATUS struct, converting it to a table.
|
|
--
|
|
-- The structure is as follows:
|
|
--
|
|
-- <code>
|
|
-- typedef struct {
|
|
-- uint32 type;
|
|
-- uint32 state;
|
|
-- uint32 controls_accepted;
|
|
-- WERROR win32_exit_code;
|
|
-- uint32 service_exit_code;
|
|
-- uint32 check_point;
|
|
-- uint32 wait_hint;
|
|
-- } SERVICE_STATUS;
|
|
-- </code>
|
|
--
|
|
--@param data The data packet.
|
|
--@param pos The position within the data.
|
|
--@return (pos, table) The new position, and the table of values.
|
|
function unmarshall_SERVICE_STATUS(data, pos)
|
|
local result = {}
|
|
|
|
pos, result['type'] = unmarshall_svcctl_Type(data, pos)
|
|
pos, result['state'] = unmarshall_svcctl_State(data, pos)
|
|
pos, result['controls_accepted'] = unmarshall_svcctl_ControlCode(data, pos)
|
|
pos, result['win32_exit_code'] = unmarshall_int32(data, pos)
|
|
pos, result['service_exit_code'] = unmarshall_int32(data, pos)
|
|
pos, result['check_point'] = unmarshall_int32(data, pos)
|
|
pos, result['wait_hint'] = unmarshall_int32(data, pos)
|
|
|
|
return pos, result
|
|
end
|
|
|
|
|
|
|
|
local atsvc_DaysOfMonth =
|
|
{
|
|
First = 0x00000001,
|
|
Second = 0x00000002,
|
|
Third = 0x00000004,
|
|
Fourth = 0x00000008,
|
|
Fifth = 0x00000010,
|
|
Sixth = 0x00000020,
|
|
Seventh = 0x00000040,
|
|
Eighth = 0x00000080,
|
|
Ninth = 0x00000100,
|
|
Tenth = 0x00000200,
|
|
Eleventh = 0x00000400,
|
|
Twelfth = 0x00000800,
|
|
Thirteenth = 0x00001000,
|
|
Fourteenth = 0x00002000,
|
|
Fifteenth = 0x00004000,
|
|
Sixteenth = 0x00008000,
|
|
Seventeenth = 0x00010000,
|
|
Eighteenth = 0x00020000,
|
|
Ninteenth = 0x00040000,
|
|
Twentieth = 0x00080000,
|
|
Twentyfirst = 0x00100000,
|
|
Twentysecond = 0x00200000,
|
|
Twentythird = 0x00400000,
|
|
Twentyfourth = 0x00800000,
|
|
Twentyfifth = 0x01000000,
|
|
Twentysixth = 0x02000000,
|
|
Twentyseventh = 0x04000000,
|
|
Twentyeighth = 0x08000000,
|
|
Twentyninth = 0x10000000,
|
|
Thirtieth = 0x20000000,
|
|
Thirtyfirst = 0x40000000
|
|
}
|
|
|
|
---Marshall a <code>atsvc_DaysOfMonth</code>. This datatype is tied to the table above with that
|
|
-- name.
|
|
--
|
|
--@param flags The value to marshall, as a string
|
|
--@return The marshalled integer representing the given value, or <code>nil</code> if it wasn't
|
|
-- found.
|
|
function marshall_atsvc_DaysOfMonth(flags)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering marshall_atsvc_DaysOfMonth()")
|
|
|
|
result = marshall_Enum32(flags, atsvc_DaysOfMonth)
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_atsvc_DaysOfMonth()")
|
|
return result
|
|
end
|
|
|
|
|
|
local atsvc_Flags =
|
|
{
|
|
JOB_RUN_PERIODICALLY = 0x01,
|
|
JOB_EXEC_ERROR = 0x02,
|
|
JOB_RUNS_TODAY = 0x04,
|
|
JOB_ADD_CURRENT_DATE = 0x08,
|
|
JOB_NONINTERACTIVE = 0x10
|
|
}
|
|
---Marshall a <code>atsvc_Flags</code>. This datatype is tied to the table above with that
|
|
-- name.
|
|
--
|
|
--@param flags The value to marshall, as a string
|
|
--@return The marshalled integer representing the given value, or <code>nil</code> if it wasn't
|
|
-- found.
|
|
function marshall_atsvc_Flags(flags)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering marshall_atsvc_Flags()")
|
|
|
|
result = marshall_Enum8(flags, atsvc_Flags, false)
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_atsvc_Flags()")
|
|
return result
|
|
end
|
|
|
|
|
|
local atsvc_DaysOfWeek =
|
|
{
|
|
DAYSOFWEEK_MONDAY = 0x01,
|
|
DAYSOFWEEK_TUESDAY = 0x02,
|
|
DAYSOFWEEK_WEDNESDAY = 0x04,
|
|
DAYSOFWEEK_THURSDAY = 0x08,
|
|
DAYSOFWEEK_FRIDAY = 0x10,
|
|
DAYSOFWEEK_SATURDAY = 0x20,
|
|
DAYSOFWEEK_SUNDAY = 0x40
|
|
}
|
|
---Marshall a <code>atsvc_DaysOfWeek</code>. This datatype is tied to the table above with that
|
|
-- name.
|
|
--
|
|
--@param flags The value to marshall, as a string
|
|
--@return The marshalled integer representing the given value, or <code>nil</code> if it wasn't
|
|
-- found.
|
|
function marshall_atsvc_DaysOfWeek(flags)
|
|
local result
|
|
stdnse.debug4("MSRPC: Entering marshall_atsvc_DaysOfWeek()")
|
|
|
|
result = marshall_Enum8(flags, atsvc_DaysOfWeek, false)
|
|
|
|
stdnse.debug4("MSRPC: Leaving marshall_atsvc_DaysOfWeek()")
|
|
return result
|
|
end
|
|
|
|
---Marshall a JobInfo struct.
|
|
--
|
|
--The structure is as follows:
|
|
--
|
|
--<code>
|
|
-- typedef struct {
|
|
-- uint32 job_time;
|
|
-- atsvc_DaysOfMonth days_of_month;
|
|
-- atsvc_DaysOfWeek days_of_week;
|
|
-- atsvc_Flags flags;
|
|
-- [string,charset(UTF16)] uint16 *command;
|
|
-- } atsvc_JobInfo;
|
|
--</code>
|
|
--
|
|
--@param command The command to run. This has to be just the command, no parameters; if a
|
|
-- program requires parameters, then the best way to run it is through a batch
|
|
-- file.
|
|
--@param time The time at which to run the job, in milliseconds from midnight.
|
|
function marshall_atsvc_JobInfo(command, time)
|
|
local result = ""
|
|
|
|
result = result .. marshall_int32(time) -- Job time
|
|
result = result .. marshall_int32(0) -- Day of month
|
|
result = result .. marshall_int8(0, false) -- Day of week
|
|
result = result .. marshall_atsvc_Flags("JOB_NONINTERACTIVE") -- Flags
|
|
result = result .. marshall_int16(0, false) -- Padding
|
|
result = result .. marshall_unicode_ptr(command, true) -- Command
|
|
|
|
return result
|
|
end
|
|
|
|
|
|
|
|
|
|
return _ENV;
|