Skip to content

Commit

Permalink
Update how railgun handles pointer return types
Browse files Browse the repository at this point in the history
Update railgun to handle pointer return types. If the type that is
pointed to is known (i.e. PCHAR, PULONG_PTR) and not LPVOID, the
contents returned to the caller. The raw address is also returned in the
&return key to enable the caller to free the buffer if necessary which
is determined by the function that was called.
  • Loading branch information
zeroSteiner authored and gwillcox-r7 committed Feb 23, 2023
1 parent 4c25530 commit 42bd87e
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 8 deletions.
24 changes: 17 additions & 7 deletions lib/rex/post/meterpreter/extensions/stdapi/railgun/library.rb
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ def build_packet_and_layouts(packet, function, args, arch)
# it's not a pointer (LPVOID is a pointer but is not backed by railgun memory, ala PBLOB)
buffer = [0].pack(native)
case param_desc[0]
when 'LPVOID', 'PULONG_PTR', 'ULONG_PTR'
when 'LPVOID', 'ULONG_PTR'
num = param_to_number(args[param_idx])
buffer += [num].pack(native)
when 'DWORD'
Expand Down Expand Up @@ -273,8 +273,8 @@ def build_packet_and_layouts(packet, function, args, arch)
[packet, layouts]
end

def build_response(packet, function, layouts, arch)
case arch
def build_response(packet, function, layouts, client)
case client.native_arch
when ARCH_X64
native = 'Q<'
when ARCH_X86
Expand All @@ -301,7 +301,7 @@ def build_response(packet, function, layouts, arch)
# process return value
case function.return_type
when 'LPVOID', 'ULONG_PTR'
if arch == ARCH_X64
if client.native_arch == ARCH_X64
return_hash['return'] = rec_return_value
else
return_hash['return'] = rec_return_value & 0xffffffff
Expand All @@ -317,9 +317,19 @@ def build_response(packet, function, layouts, arch)
when 'VOID'
return_hash['return'] = nil
when 'PCHAR'
return_hash['return'] = rec_return_value == 0 ? nil : read_string(rec_return_value)
return_hash['return'] = rec_return_value == 0 ? nil : client.railgun.util.read_string(rec_return_value)
return_hash['&return'] = rec_return_value
when 'PWCHAR'
return_hash['return'] = rec_return_value == 0 ? nil : read_wstring(rec_return_value)
return_hash['return'] = rec_return_value == 0 ? nil : client.railgun.util.read_wstring(rec_return_value)
return_hash['&return'] = rec_return_value
when 'PULONG_PTR'
if client.native_arch == ARCH_X64
return_hash['return'] = rec_return_value == 0 ? nil : client.railgun.util.memread(rec_return_value, 8)&.unpack1('Q<')
return_hash['&return'] = rec_return_value
else
return_hash['return'] = rec_return_value == 0 ? nil : client.railgun.util.memread(rec_return_value, 4)&.unpack1('V')
return_hash['&return'] = rec_return_value
end
else
raise "unexpected return type: #{function.return_type}"
end
Expand Down Expand Up @@ -379,7 +389,7 @@ def process_function_call(function, args, client)

response = client.send_request(request)

build_response(response, function, layouts, client.native_arch)
build_response(response, function, layouts, client)
end

# perform type conversions as necessary to reduce the datatypes to their primitives
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ def call(functions)
lib_name, function, args = f
library = @parent.get_library(lib_name)
function = library.functions[function] unless function.instance_of? LibraryFunction
function_results << library.build_response(call_results.shift, function, call_layouts.shift, @client.native_arch)
function_results << library.build_response(call_results.shift, function, call_layouts.shift, @client)
end

function_results
Expand Down

0 comments on commit 42bd87e

Please sign in to comment.