9391e11202
`str_to_uniz_a` does not exist, updated to `str_to_uni_z`. Looking at cross-references, only two modules use this method to convert from ruby strings to null-terminated WCHARs. Updated the comments to clarify usage of this method and fixed the typo.
730 lines
18 KiB
Ruby
730 lines
18 KiB
Ruby
# -*- coding: binary -*-
|
|
require 'rex/post/meterpreter/extensions/stdapi/railgun/library_helper'
|
|
|
|
module Rex
|
|
module Post
|
|
module Meterpreter
|
|
module Extensions
|
|
module Stdapi
|
|
module Railgun
|
|
|
|
#
|
|
# Utility methods and constants for dealing with most types of variables.
|
|
#
|
|
class Util
|
|
|
|
# Bring in some useful string manipulation utility functions
|
|
include LibraryHelper
|
|
|
|
# Data type size info: http://msdn.microsoft.com/en-us/library/s3f49ktz(v=vs.80).aspx
|
|
PRIMITIVE_TYPE_SIZES = {
|
|
:int => 4,
|
|
:__int8 => 1,
|
|
:__int16 => 2,
|
|
:__int32 => 4,
|
|
:__int64 => 8,
|
|
:bool => 1,
|
|
:char => 1,
|
|
:short => 2,
|
|
:long => 4,
|
|
:long_long => 8,
|
|
:float => 4,
|
|
:double => 8,
|
|
:long_double => 8,
|
|
:wchar_t => 2,
|
|
}
|
|
|
|
#
|
|
# Maps a data type to its corresponding primitive or special type
|
|
# +:pointer+. Note, primitive types are mapped to themselves.
|
|
#
|
|
# typedef info: http://msdn.microsoft.com/en-us/library/aa383751(v=vs.85).aspx
|
|
TYPE_DEFINITIONS = {
|
|
##
|
|
# Primitives
|
|
##
|
|
:int => :int,
|
|
:__int8 => :__int8,
|
|
:__int16 => :__int16,
|
|
:__int32 => :__int32,
|
|
:__int64 => :__int64,
|
|
:bool => :bool,
|
|
:char => :char,
|
|
:short => :short,
|
|
:long => :long,
|
|
:long_long => :long_long,
|
|
:float => :float,
|
|
:double => :double,
|
|
:long_double => :long_double,
|
|
:wchar_t => :wchar_t,
|
|
##
|
|
# Non-pointers
|
|
##
|
|
#typedef WORD ATOM;
|
|
:ATOM => :short,
|
|
#typedef int BOOL;
|
|
:BOOL => :int,
|
|
#typedef BYTE BOOLEAN;
|
|
:BOOLEAN => :char,
|
|
#typedef unsigned char BYTE;
|
|
:BYTE => :char,
|
|
#typedef char CHAR;
|
|
:CHAR => :char,
|
|
#typedef DWORD COLORREF;
|
|
:COLORREF => :long,
|
|
#typedef unsigned long DWORD;
|
|
:DWORD => :long,
|
|
#typedef unsigned int DWORD32;
|
|
:DWORD32 => :int,
|
|
#typedef unsigned __int64 DWORD64;
|
|
:DWORD64 => :__int64,
|
|
#typedef float FLOAT;
|
|
:FLOAT => :float,
|
|
#typedef int HFILE;
|
|
:HFILE => :int,
|
|
#typedef LONG HRESULT;
|
|
:HRESULT => :long,
|
|
#typedef int INT;
|
|
:INT => :int,
|
|
#typedef signed int INT32;
|
|
:INT32 => :int,
|
|
#typedef signed __int64 INT64;
|
|
:INT64 => :__int64,
|
|
#typedef WORD LANGID;
|
|
:LANGID => :short,
|
|
#typedef DWORD LCID;
|
|
:LCID => :long,
|
|
#typedef DWORD LCTYPE;
|
|
:LCTYPE => :long,
|
|
#typedef DWORD LGRPID;
|
|
:LGRPID => :long,
|
|
#typedef long LONG;
|
|
:LONG => :long,
|
|
#typedef signed int LONG32;
|
|
:LONG32 => :int,
|
|
#typedef __int64 LONG64;
|
|
:LONG64 => :__int64,
|
|
#typedef PDWORD PLCID;
|
|
:PLCID => :pointer,
|
|
#typedef LPVOID SC_LOCK;
|
|
:SC_LOCK => :pointer,
|
|
#typedef short SHORT;
|
|
:SHORT => :short,
|
|
#typedef unsigned char UCHAR;
|
|
:UCHAR => :char,
|
|
#typedef unsigned int UINT;
|
|
:UINT => :int,
|
|
#typedef unsigned int UINT32;
|
|
:UINT32 => :int,
|
|
#typedef unsigned long ULONG;
|
|
:ULONG => :long,
|
|
#typedef unsigned int ULONG32;
|
|
:ULONG32 => :int,
|
|
#typedef unsigned __int64 ULONG64;
|
|
:ULONG64 => :__int64,
|
|
#typedef unsigned short USHORT;
|
|
:USHORT => :short,
|
|
#typedef wchar_t WCHAR;
|
|
:WCHAR => :wchar_t,
|
|
#typedef unsigned short WORD;
|
|
:WORD => :short,
|
|
##
|
|
# Pointers declared with *
|
|
##
|
|
#typedef DWORD* LPCOLORREF;
|
|
:LPCOLORREF => :pointer,
|
|
#typedef void* LPCVOID;
|
|
:LPCVOID => :pointer,
|
|
#typedef WCHAR* LPCWSTR;
|
|
:LPCWSTR => :pointer,
|
|
#typedef DWORD* LPDWORD;
|
|
:LPDWORD => :pointer,
|
|
#typedef HANDLE* LPHANDLE;
|
|
:LPHANDLE => :pointer,
|
|
#typedef int* LPINT;
|
|
:LPINT => :pointer,
|
|
#typedef long* LPLONG;
|
|
:LPLONG => :pointer,
|
|
#typedef CHAR* LPSTR;
|
|
:LPSTR => :pointer,
|
|
#typedef void* LPVOID;
|
|
:LPVOID => :pointer,
|
|
#typedef WORD* LPWORD;
|
|
:LPWORD => :pointer,
|
|
#typedef WCHAR* LPWSTR;
|
|
:LPWSTR => :pointer,
|
|
#typedef BOOL* PBOOL;
|
|
:PBOOL => :pointer,
|
|
#typedef BOOLEAN* PBOOLEAN;
|
|
:PBOOLEAN => :pointer,
|
|
#typedef BYTE* PBYTE;
|
|
:PBYTE => :pointer,
|
|
#typedef CHAR* PCHAR;
|
|
:PCHAR => :pointer,
|
|
#typedef CHAR* PCSTR;
|
|
:PCSTR => :pointer,
|
|
#typedef WCHAR* PCWSTR;
|
|
:PCWSTR => :pointer,
|
|
#typedef DWORD* PDWORD;
|
|
:PDWORD => :pointer,
|
|
#typedef DWORDLONG* PDWORDLONG;
|
|
:PDWORDLONG => :pointer,
|
|
#typedef DWORD_PTR* PDWORD_PTR;
|
|
:PDWORD_PTR => :pointer,
|
|
#typedef DWORD32* PDWORD32;
|
|
:PDWORD32 => :pointer,
|
|
#typedef DWORD64* PDWORD64;
|
|
:PDWORD64 => :pointer,
|
|
#typedef FLOAT* PFLOAT;
|
|
:PFLOAT => :pointer,
|
|
#typedef HANDLE* PHANDLE;
|
|
:PHANDLE => :pointer,
|
|
#typedef HKEY* PHKEY;
|
|
:PHKEY => :pointer,
|
|
#typedef int* PINT;
|
|
:PINT => :pointer,
|
|
#typedef INT_PTR* PINT_PTR;
|
|
:PINT_PTR => :pointer,
|
|
#typedef INT32* PINT32;
|
|
:PINT32 => :pointer,
|
|
#typedef INT64* PINT64;
|
|
:PINT64 => :pointer,
|
|
#typedef LONG* PLONG;
|
|
:PLONG => :pointer,
|
|
#typedef LONGLONG* PLONGLONG;
|
|
:PLONGLONG => :pointer,
|
|
#typedef LONG_PTR* PLONG_PTR;
|
|
:PLONG_PTR => :pointer,
|
|
#typedef LONG32* PLONG32;
|
|
:PLONG32 => :pointer,
|
|
#typedef LONG64* PLONG64;
|
|
:PLONG64 => :pointer,
|
|
#typedef SHORT* PSHORT;
|
|
:PSHORT => :pointer,
|
|
#typedef SIZE_T* PSIZE_T;
|
|
:PSIZE_T => :pointer,
|
|
#typedef SSIZE_T* PSSIZE_T;
|
|
:PSSIZE_T => :pointer,
|
|
#typedef CHAR* PSTR;
|
|
:PSTR => :pointer,
|
|
#typedef TBYTE* PTBYTE;
|
|
:PTBYTE => :pointer,
|
|
#typedef TCHAR* PTCHAR;
|
|
:PTCHAR => :pointer,
|
|
#typedef UCHAR* PUCHAR;
|
|
:PUCHAR => :pointer,
|
|
#typedef UINT* PUINT;
|
|
:PUINT => :pointer,
|
|
#typedef UINT_PTR* PUINT_PTR;
|
|
:PUINT_PTR => :pointer,
|
|
#typedef UINT32* PUINT32;
|
|
:PUINT32 => :pointer,
|
|
#typedef UINT64* PUINT64;
|
|
:PUINT64 => :pointer,
|
|
#typedef ULONG* PULONG;
|
|
:PULONG => :pointer,
|
|
#typedef ULONGLONG* PULONGLONG;
|
|
:PULONGLONG => :pointer,
|
|
#typedef ULONG_PTR* PULONG_PTR;
|
|
:PULONG_PTR => :pointer,
|
|
#typedef ULONG32* PULONG32;
|
|
:PULONG32 => :pointer,
|
|
#typedef ULONG64* PULONG64;
|
|
:PULONG64 => :pointer,
|
|
#typedef USHORT* PUSHORT;
|
|
:PUSHORT => :pointer,
|
|
#typedef void* PVOID;
|
|
:PVOID => :pointer,
|
|
#typedef WCHAR* PWCHAR;
|
|
:PWCHAR => :pointer,
|
|
#typedef WORD* PWORD;
|
|
:PWORD => :pointer,
|
|
#typedef WCHAR* PWSTR;
|
|
:PWSTR => :pointer,
|
|
#typedef HANDLE HACCEL;
|
|
:HACCEL => :pointer,
|
|
##
|
|
# Handles
|
|
##
|
|
#typedef PVOID HANDLE;
|
|
:HANDLE => :pointer,
|
|
#typedef HANDLE HBITMAP;
|
|
:HBITMAP => :pointer,
|
|
#typedef HANDLE HBRUSH;
|
|
:HBRUSH => :pointer,
|
|
#typedef HANDLE HCOLORSPACE;
|
|
:HCOLORSPACE => :pointer,
|
|
#typedef HANDLE HCONV;
|
|
:HCONV => :pointer,
|
|
#typedef HANDLE HCONVLIST;
|
|
:HCONVLIST => :pointer,
|
|
#typedef HANDLE HDC;
|
|
:HDC => :pointer,
|
|
#typedef HANDLE HDDEDATA;
|
|
:HDDEDATA => :pointer,
|
|
#typedef HANDLE HDESK;
|
|
:HDESK => :pointer,
|
|
#typedef HANDLE HDROP;
|
|
:HDROP => :pointer,
|
|
#typedef HANDLE HDWP;
|
|
:HDWP => :pointer,
|
|
#typedef HANDLE HENHMETAFILE;
|
|
:HENHMETAFILE => :pointer,
|
|
#typedef HANDLE HFONT;
|
|
:HFONT => :pointer,
|
|
#typedef HANDLE HGDIOBJ;
|
|
:HGDIOBJ => :pointer,
|
|
#typedef HANDLE HGLOBAL;
|
|
:HGLOBAL => :pointer,
|
|
#typedef HANDLE HHOOK;
|
|
:HHOOK => :pointer,
|
|
#typedef HANDLE HICON;
|
|
:HICON => :pointer,
|
|
#typedef HANDLE HINSTANCE;
|
|
:HINSTANCE => :pointer,
|
|
#typedef HANDLE HKEY;
|
|
:HKEY => :pointer,
|
|
#typedef HANDLE HKL;
|
|
:HKL => :pointer,
|
|
#typedef HANDLE HLOCAL;
|
|
:HLOCAL => :pointer,
|
|
#typedef HANDLE HMENU;
|
|
:HMENU => :pointer,
|
|
#typedef HANDLE HMETAFILE;
|
|
:HMETAFILE => :pointer,
|
|
#typedef HANDLE HPALETTE;
|
|
:HPALETTE => :pointer,
|
|
#typedef HANDLE HPEN;
|
|
:HPEN => :pointer,
|
|
#typedef HANDLE HRGN;
|
|
:HRGN => :pointer,
|
|
#typedef HANDLE HRSRC;
|
|
:HRSRC => :pointer,
|
|
#typedef HANDLE HSZ;
|
|
:HSZ => :pointer,
|
|
#typedef HANDLE WINSTA;
|
|
:WINSTA => :pointer,
|
|
#typedef HANDLE HWND;
|
|
:HWND => :pointer,
|
|
#typedef HANDLE SC_HANDLE;
|
|
:SC_HANDLE => :pointer,
|
|
#typedef HANDLE SERVICE_STATUS_HANDLE;
|
|
:SERVICE_STATUS_HANDLE => :pointer,
|
|
}
|
|
|
|
# param 'railgun' is a Railgun instance.
|
|
# param 'arch' is the client.arch
|
|
def initialize(railgun, arch)
|
|
@railgun = railgun
|
|
@is_64bit = arch == ARCH_X64
|
|
@process_heap = nil
|
|
end
|
|
|
|
#
|
|
# Given a packed pointer, unpacks it according to architecture
|
|
#
|
|
def unpack_pointer(packed_pointer)
|
|
if is_64bit
|
|
# Assume little endian
|
|
packed_pointer.unpack('Q<')[0]
|
|
else
|
|
packed_pointer.unpack('V')[0]
|
|
end
|
|
end
|
|
|
|
#
|
|
# Returns true if +pointer+ will be considered a 'null' pointer.
|
|
#
|
|
# If +pointer+ is nil or 0, returns true
|
|
# If +pointer+ is a String, if 0 after unpacking, returns true
|
|
# false otherwise
|
|
#
|
|
# See #unpack_pointer
|
|
#
|
|
def is_null_pointer(pointer)
|
|
if pointer.kind_of? String
|
|
pointer = unpack_pointer(pointer)
|
|
end
|
|
|
|
return pointer.nil? || pointer == 0
|
|
end
|
|
|
|
def alloc_and_write_data(data)
|
|
return nil if data.nil? || process_heap.nil?
|
|
|
|
result = railgun.kernel32.HeapAlloc(process_heap, railgun.const('HEAP_ZERO'), data.length)
|
|
return nil if result['return'].nil?
|
|
|
|
addr = result['return']
|
|
return nil unless railgun.memwrite(addr, data, data.length)
|
|
|
|
addr
|
|
end
|
|
|
|
def free_data(*ptrs)
|
|
return false if ptrs.empty?
|
|
return false if process_heap.nil?
|
|
|
|
results = railgun.multi(
|
|
ptrs.map { |ptr| ['kernel32', 'HeapFree', [process_heap, 0, ptr.to_i]] }
|
|
)
|
|
results.map { |res| res['return'] }.all?
|
|
end
|
|
|
|
#
|
|
# Reads null-terminated unicode strings from memory.
|
|
#
|
|
# Given a pointer to a null terminated array of WCHARs, return a ruby
|
|
# String. If +pointer+ is NULL (see #is_null_pointer) returns an empty
|
|
# string.
|
|
#
|
|
def read_wstring(pointer, length = nil)
|
|
# Return an empty string for null pointers
|
|
if is_null_pointer(pointer)
|
|
return ''
|
|
end
|
|
|
|
# If length not provided, use lstrlenW
|
|
if length.nil?
|
|
length = railgun.kernel32.lstrlenW(pointer)['return']
|
|
end
|
|
|
|
# Retrieve the array of characters
|
|
chars = read_array(:WCHAR, length, pointer)
|
|
|
|
# Concatenate the characters and convert to a ruby string
|
|
str = uniz_to_str(chars.join(''))
|
|
|
|
return str
|
|
end
|
|
|
|
#
|
|
# Write Unicode strings to memory.
|
|
#
|
|
# Given a string, returns a pointer to a null terminated WCHARs array.
|
|
#
|
|
def alloc_and_write_wstring(value)
|
|
return nil if value.nil?
|
|
|
|
alloc_and_write_data(str_to_uni_z(value))
|
|
end
|
|
|
|
alias free_wstring free_data
|
|
|
|
#
|
|
# Write ASCII strings to memory.
|
|
#
|
|
# Given a string, returns a pointer to a null terminated CHARs array.
|
|
# InitializeStr(&Str,"string");
|
|
#
|
|
def alloc_and_write_string(value)
|
|
return nil if value.nil?
|
|
|
|
alloc_and_write_data(str_to_ascii_z(value))
|
|
end
|
|
|
|
alias free_string free_data
|
|
|
|
#
|
|
# Reads null-terminated ASCII strings from memory.
|
|
#
|
|
# Given a pointer to a null terminated array of CHARs, return a ruby
|
|
# String. If +pointer+ is NULL (see #is_null_pointer) returns an empty
|
|
# string.
|
|
#
|
|
def read_string(pointer, length=nil)
|
|
if is_null_pointer(pointer)
|
|
return ''
|
|
end
|
|
|
|
unless length
|
|
length = railgun.kernel32.lstrlenA(pointer)['return']
|
|
end
|
|
|
|
chars = read_array(:CHAR, length, pointer)
|
|
return chars.join('')
|
|
end
|
|
|
|
#
|
|
# Read a given number of bytes from memory or from a provided buffer.
|
|
#
|
|
# If +buffer+ is not provided, read +size+ bytes from the client's memory.
|
|
# If +buffer+ is provided, reads +size+ characters from the index of +address+.
|
|
#
|
|
def memread(address, size, buffer = nil)
|
|
if buffer.nil?
|
|
return railgun.memread(address, size)
|
|
else
|
|
return buffer[address .. (address + size - 1)]
|
|
end
|
|
end
|
|
|
|
#
|
|
# Read and unpack a pointer from the given buffer at a given offset
|
|
#
|
|
def read_pointer(buffer, offset = 0)
|
|
unpack_pointer(buffer[offset, (offset + pointer_size)])
|
|
end
|
|
|
|
#
|
|
# Reads data structures and several windows data types
|
|
#
|
|
def read_data(type, position, buffer = nil)
|
|
if buffer.nil?
|
|
buffer = memread(position, sizeof_type(type))
|
|
position = 0
|
|
end
|
|
|
|
# If we're asked to read a data structure, deligate to read_struct
|
|
if is_struct_type?(type)
|
|
return read_struct(type, buffer, position)
|
|
end
|
|
|
|
# If the type is an array with a given size...
|
|
# BYTE[3] for example or BYTE[ENCRYPTED_PWLEN] or even PDWORD[23]
|
|
if is_array_type?(type)
|
|
# Separate the element type from the size of the array
|
|
element_type, length = split_array_type(type)
|
|
|
|
# Have read_array take care of the rest
|
|
return read_array(element_type, length, position, buffer)
|
|
end
|
|
|
|
size = sizeof_type(type)
|
|
raw = memread(position, size, buffer)
|
|
|
|
# read/unpack data for the types we have hard-coded support for
|
|
case type
|
|
when :LPWSTR
|
|
# null-terminated string of 16-bit Unicode characters
|
|
return read_wstring(read_pointer(raw))
|
|
when :DWORD
|
|
# Both on x86 and x64, DWORD is 32 bits
|
|
return raw.unpack('V').first
|
|
when :BOOL
|
|
return raw.unpack('V').first == 1
|
|
when :LONG
|
|
return raw.unpack('V').first
|
|
end
|
|
|
|
#If nothing worked thus far, return it raw
|
|
return raw
|
|
end
|
|
|
|
#
|
|
# Read +length+ number of instances of +type+ from +bufptr+ .
|
|
#
|
|
# +bufptr+ is an index in +buffer+ or, if +buffer+ is nil, a memory address
|
|
#
|
|
def read_array(type, length, bufptr, buffer = nil)
|
|
if length <= 0
|
|
return []
|
|
end
|
|
|
|
size = sizeof_type(type)
|
|
# Grab the bytes that the array consists of
|
|
buffer = memread(bufptr, size * length, buffer)
|
|
|
|
offset = 0
|
|
|
|
1.upto(length).map do |n|
|
|
data = read_data(type, offset, buffer)
|
|
|
|
offset = offset + size
|
|
|
|
data
|
|
end
|
|
end
|
|
|
|
#
|
|
# Construct the data structure described in +definition+ from +buffer+
|
|
# starting from the index +offset+
|
|
#
|
|
def read_struct(definition, buffer, offset = 0)
|
|
data = {}
|
|
|
|
offsets = struct_offsets(definition, offset)
|
|
|
|
definition.each do |mapping|
|
|
key, data_type = mapping
|
|
|
|
data[key] = read_data(data_type, offsets.shift, buffer)
|
|
end
|
|
|
|
data
|
|
end
|
|
|
|
|
|
# Returns true if the data type is a pointer, false otherwise
|
|
def is_pointer_type?(type)
|
|
return TYPE_DEFINITIONS[type] == :pointer
|
|
end
|
|
|
|
# Returns whether the given type represents an array of another type
|
|
# For example BYTE[3], BYTE[ENCRYPTED_PWLEN], or even PDWORD[23]
|
|
def is_array_type?(type)
|
|
return type =~ /^\w+\[\w+\]$/ ? true : false
|
|
end
|
|
|
|
# Returns true if the type passed describes a data structure, false otherwise
|
|
def is_struct_type?(type)
|
|
return type.kind_of? Array
|
|
end
|
|
|
|
|
|
# Returns the pointer size for this architecture
|
|
def pointer_size
|
|
is_64bit ? 8 : 4
|
|
end
|
|
|
|
# Return the size, in bytes, of the given type
|
|
def sizeof_type(type)
|
|
if is_pointer_type?(type)
|
|
return pointer_size
|
|
end
|
|
|
|
if type.kind_of? String
|
|
if is_array_type?(type)
|
|
element_type, length = split_array_type(type)
|
|
return length * sizeof_type(element_type)
|
|
else
|
|
return sizeof_type(type.to_sym)
|
|
end
|
|
end
|
|
|
|
if is_struct_type?(type)
|
|
return sizeof_struct(type)
|
|
end
|
|
|
|
if TYPE_DEFINITIONS.has_key?(type)
|
|
primitive = TYPE_DEFINITIONS[type]
|
|
|
|
if primitive == :pointer
|
|
return pointer_size
|
|
end
|
|
|
|
if PRIMITIVE_TYPE_SIZES.has_key?(primitive)
|
|
return PRIMITIVE_TYPE_SIZES[primitive]
|
|
else
|
|
raise "Type #{type} was mapped to non-existent primitive #{primitive}"
|
|
end
|
|
end
|
|
|
|
raise "Unable to determine size for type #{type}."
|
|
end
|
|
|
|
#
|
|
# Calculates the size of +struct+ after alignment.
|
|
#
|
|
def sizeof_struct(struct)
|
|
offsets = struct_offsets(struct, 0)
|
|
last_data_size = sizeof_type(struct.last[1])
|
|
size_no_padding = offsets.last + last_data_size
|
|
|
|
return size_no_padding + calc_padding(size_no_padding)
|
|
end
|
|
|
|
#
|
|
# Given a description of a data structure, returns an Array containing
|
|
# the offset from the beginning for each subsequent element, taking into
|
|
# consideration alignment and padding.
|
|
#
|
|
def struct_offsets(definition, offset)
|
|
padding = 0
|
|
offsets = []
|
|
definition.each do |mapping|
|
|
key, data_type = mapping
|
|
if sizeof_type(data_type) > padding
|
|
offset = offset + padding
|
|
end
|
|
|
|
offsets.push(offset)
|
|
|
|
offset = offset + sizeof_type(data_type)
|
|
padding = calc_padding(offset)
|
|
end
|
|
|
|
offsets
|
|
end
|
|
|
|
# http://en.wikipedia.org/wiki/Data_structure_alignment
|
|
def required_alignment
|
|
is_64bit ? 8 : 4
|
|
end
|
|
|
|
#
|
|
# Number of bytes that needed to be added to be aligned.
|
|
#
|
|
def calc_padding(offset)
|
|
align = required_alignment
|
|
|
|
# If offset is not aligned...
|
|
if (offset % align) != 0
|
|
# Calculate padding needed to be aligned
|
|
align - (offset & (align - 1))
|
|
else
|
|
0
|
|
end
|
|
end
|
|
|
|
#
|
|
# Given an explicit array definition (e.g. BYTE[23]) return size (e.g. 23) and
|
|
# and +type+ (e.g. BYTE). If a constant is given, attempt to resolve it
|
|
# that constant.
|
|
#
|
|
def split_array_type(type)
|
|
if type =~ /^(\w+)\[(\w+)\]$/
|
|
element_type = $1
|
|
length = $2
|
|
unless length =~ /^\d+$/
|
|
length = railgun.const(length)
|
|
end
|
|
|
|
return element_type.to_sym, length.to_i
|
|
else
|
|
raise "Can not split non-array type #{type}"
|
|
end
|
|
end
|
|
|
|
#
|
|
# Evaluates a bit field, returning a hash representing the meaning and
|
|
# state of each bit.
|
|
#
|
|
# Parameters:
|
|
# +value+:: a bit field represented by a Integer
|
|
# +mappings+:: { 'WINAPI_CONSTANT_NAME' => :descriptive_symbol, ... }
|
|
#
|
|
# Returns:
|
|
# { :descriptive_symbol => true/false, ... }
|
|
#
|
|
def judge_bit_field(value, mappings)
|
|
flags = {}
|
|
|
|
mappings.each do |constant_name, key|
|
|
flags[key] = (value & railgun.const(constant_name)) != 0
|
|
end
|
|
|
|
flags
|
|
end
|
|
|
|
protected
|
|
|
|
attr_accessor :railgun, :is_64bit
|
|
|
|
private
|
|
|
|
def process_heap
|
|
return @process_heap unless @process_heap.nil?
|
|
|
|
handle = railgun.kernel32.GetProcessHeap()['return']
|
|
return nil if handle == 0
|
|
@process_heap = handle
|
|
end
|
|
end # Util
|
|
end # Railgun
|
|
end # Stdapi
|
|
end # Extensions
|
|
end # Meterpreter
|
|
end # Post
|
|
end # Rex
|