Add more OSX Railgun defs and better CDECL support
parent
f7c133cdf7
commit
717f9aad12
|
@ -18,6 +18,13 @@ class DefApiConstants_osx < ApiConstants
|
|||
# Slurp in a giant list of known constants.
|
||||
#
|
||||
def self.add_constants(const_mgr)
|
||||
# https://opensource.apple.com/source/xnu/xnu-2050.18.24/bsd/sys/socket.h
|
||||
const_mgr.add_const('AF_UNSPEC', 0x00000000)
|
||||
const_mgr.add_const('AF_LOCAL', 0x00000001)
|
||||
const_mgr.add_const('AF_UNIX', 0x00000001)
|
||||
const_mgr.add_const('AF_INET', 0x00000002)
|
||||
const_mgr.add_const('AF_INET6', 0x0000001e)
|
||||
|
||||
# https://opensource.apple.com/source/xnu/xnu-2050.18.24/bsd/sys/mman.h
|
||||
const_mgr.add_const('MAP_FILE', 0x0000)
|
||||
const_mgr.add_const('MAP_SHARED', 0x0001)
|
||||
|
@ -30,12 +37,15 @@ class DefApiConstants_osx < ApiConstants
|
|||
const_mgr.add_const('PROT_WRITE', 0x0002)
|
||||
const_mgr.add_const('PROT_EXEC', 0x0004)
|
||||
|
||||
# https://opensource.apple.com/source/xnu/xnu-2050.18.24/bsd/sys/socket.h
|
||||
const_mgr.add_const('AF_UNSPEC', 0x00000000)
|
||||
const_mgr.add_const('AF_LOCAL', 0x00000001)
|
||||
const_mgr.add_const('AF_UNIX', 0x00000001)
|
||||
const_mgr.add_const('AF_INET', 0x00000002)
|
||||
const_mgr.add_const('AF_INET6', 0x0000001e)
|
||||
# https://opensource.apple.com/source/dyld/dyld-95.3/include/dlfcn.h
|
||||
const_mgr.add_const('RTLD_LAZY', 0x0001)
|
||||
const_mgr.add_const('RTLD_NOW', 0x0002)
|
||||
const_mgr.add_const('RTLD_LOCAL', 0x0004)
|
||||
const_mgr.add_const('RTLD_GLOBAL', 0x0008)
|
||||
const_mgr.add_const('RTLD_NOLOAD', 0x0010)
|
||||
const_mgr.add_const('RTLD_NODELETE', 0x0080)
|
||||
const_mgr.add_const('RTLD_FIRST', 0x0100) # Mac OS X 10.5 and later
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -22,6 +22,25 @@ class Def_libc
|
|||
nil,
|
||||
'cdecl'
|
||||
)
|
||||
lib.add_function(
|
||||
'dlclose',
|
||||
'DWORD',
|
||||
[
|
||||
['LPVOID', 'handle', 'in']
|
||||
],
|
||||
nil,
|
||||
'cdecl'
|
||||
)
|
||||
lib.add_function(
|
||||
'dlopen',
|
||||
'LPVOID',
|
||||
[
|
||||
['PCHAR', 'filename', 'in'],
|
||||
['DWORD', 'flags', 'in']
|
||||
],
|
||||
nil,
|
||||
'cdecl'
|
||||
)
|
||||
lib.add_function(
|
||||
'free',
|
||||
'VOID',
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
# -*- coding: binary -*-
|
||||
module Rex
|
||||
module Post
|
||||
module Meterpreter
|
||||
module Extensions
|
||||
module Stdapi
|
||||
module Railgun
|
||||
module Def
|
||||
|
||||
class Def_libobjc
|
||||
|
||||
def self.create_dll(constant_manager, dll_path = 'libobjc.dylib')
|
||||
lib = DLL.new(dll_path, constant_manager)
|
||||
|
||||
# https://developer.apple.com/documentation/objectivec/1418952-objc_getclass?language=objc
|
||||
lib.add_function(
|
||||
'objc_getClass',
|
||||
'LPVOID',
|
||||
[
|
||||
['PCHAR', 'name', 'in']
|
||||
],
|
||||
nil,
|
||||
'cdecl'
|
||||
)
|
||||
|
||||
# https://developer.apple.com/documentation/objectivec/1456712-objc_msgsend?language=objc
|
||||
lib.add_function(
|
||||
'objc_msgSend',
|
||||
'LPVOID',
|
||||
[
|
||||
['LPVOID', 'self', 'in'],
|
||||
['LPVOID', 'op', 'in']
|
||||
],
|
||||
nil,
|
||||
'cdecl'
|
||||
)
|
||||
|
||||
# https://developer.apple.com/documentation/objectivec/1418557-sel_registername?language=objc
|
||||
lib.add_function(
|
||||
'sel_registerName',
|
||||
'LPVOID',
|
||||
[
|
||||
['PCHAR', 'str', 'in']
|
||||
],
|
||||
nil,
|
||||
'cdecl'
|
||||
)
|
||||
|
||||
return lib
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end; end; end; end; end; end; end
|
|
@ -69,18 +69,20 @@ class DLL
|
|||
# Returns a Hash containing the return value, the result of GetLastError(),
|
||||
# and any +inout+ parameters.
|
||||
#
|
||||
# Raises an exception if +func_symbol+ is not a known function in this DLL,
|
||||
# Raises an exception if +function+ is not a known function in this DLL,
|
||||
# i.e., it hasn't been defined in a Def.
|
||||
#
|
||||
def call_function(func_symbol, args, client)
|
||||
func_name = func_symbol.to_s
|
||||
def call_function(function, args, client)
|
||||
unless function.instance_of? DLLFunction
|
||||
func_name = function.to_s
|
||||
|
||||
unless known_function_names.include? func_name
|
||||
raise "DLL-function #{func_name} not found. Known functions: #{PP.pp(known_function_names, '')}"
|
||||
unless known_function_names.include? func_name
|
||||
raise "DLL-function #{func_name} not found. Known functions: #{PP.pp(known_function_names, '')}"
|
||||
end
|
||||
|
||||
function = get_function(func_name)
|
||||
end
|
||||
|
||||
function = get_function(func_name)
|
||||
|
||||
return process_function_call(function, args, client)
|
||||
end
|
||||
|
||||
|
|
|
@ -56,21 +56,22 @@ class MultiCaller
|
|||
end
|
||||
|
||||
def call(functions)
|
||||
|
||||
request = Packet.create_request('stdapi_railgun_api_multi')
|
||||
function_results = []
|
||||
layouts = []
|
||||
functions.each do |f|
|
||||
dll_name,funcname,args = f
|
||||
dll_name, function, args = f
|
||||
dll_host = @parent.get_dll( dll_name )
|
||||
|
||||
if not dll_host
|
||||
raise "DLL #{dll_name} has not been loaded"
|
||||
end
|
||||
|
||||
function = dll_host.functions[funcname]
|
||||
if not function
|
||||
raise "DLL #{dll_name} function #{funcname} has not been defined"
|
||||
unless function.instance_of? DLLFunction
|
||||
function = dll_host.functions[function]
|
||||
if not function
|
||||
raise "DLL #{dll_name} function #{function} has not been defined"
|
||||
end
|
||||
end
|
||||
|
||||
raise "#{function.params.length} arguments expected. #{args.length} arguments provided." unless args.length == function.params.length
|
||||
|
@ -96,7 +97,7 @@ class MultiCaller
|
|||
end
|
||||
|
||||
# we care only about out-only buffers
|
||||
if param_desc[2] == "out"
|
||||
if param_desc[2] == 'out'
|
||||
if !args[param_idx].class.kind_of? Integer
|
||||
raise "error in param #{param_desc[1]}: Out-only buffers must be described by a number indicating their size in bytes "
|
||||
end
|
||||
|
@ -122,11 +123,11 @@ class MultiCaller
|
|||
end
|
||||
end
|
||||
|
||||
tmp = assemble_buffer("in", function, args)
|
||||
tmp = assemble_buffer('in', function, args)
|
||||
in_only_layout = tmp[0]
|
||||
in_only_buffer = tmp[1]
|
||||
|
||||
tmp = assemble_buffer("inout", function, args)
|
||||
tmp = assemble_buffer('inout', function, args)
|
||||
inout_layout = tmp[0]
|
||||
inout_buffer = tmp[1]
|
||||
|
||||
|
@ -146,41 +147,41 @@ class MultiCaller
|
|||
#puts " processing (#{param_desc[0]}, #{param_desc[1]}, #{param_desc[2]})"
|
||||
buffer = nil
|
||||
# is it a pointer to a buffer on our stack
|
||||
if ["PDWORD", "PWCHAR", "PCHAR", "PBLOB"].include? param_desc[0]
|
||||
#puts " pointer"
|
||||
if ['PDWORD', 'PWCHAR', 'PCHAR', 'PBLOB'].include? param_desc[0]
|
||||
#puts ' pointer'
|
||||
if args[param_idx] == nil # null pointer?
|
||||
buffer = [0].pack(@native) # type: DWORD (so the dll does not rebase it)
|
||||
buffer += [0].pack(@native) # value: 0
|
||||
elsif param_desc[2] == "in"
|
||||
elsif param_desc[2] == 'in'
|
||||
buffer = [1].pack(@native)
|
||||
buffer += [in_only_layout[param_desc[1]].addr].pack(@native)
|
||||
elsif param_desc[2] == "out"
|
||||
elsif param_desc[2] == 'out'
|
||||
buffer = [2].pack(@native)
|
||||
buffer += [out_only_layout[param_desc[1]].addr].pack(@native)
|
||||
elsif param_desc[2] == "inout"
|
||||
elsif param_desc[2] == 'inout'
|
||||
buffer = [3].pack(@native)
|
||||
buffer += [inout_layout[param_desc[1]].addr].pack(@native)
|
||||
else
|
||||
raise "unexpected direction"
|
||||
raise 'unexpected direction'
|
||||
end
|
||||
else
|
||||
#puts " not a pointer"
|
||||
#puts ' not a pointer'
|
||||
# it's not a pointer
|
||||
buffer = [0].pack(@native)
|
||||
case param_desc[0]
|
||||
when "LPVOID", "HANDLE", "SIZE_T"
|
||||
when 'LPVOID', 'HANDLE', 'SIZE_T'
|
||||
num = param_to_number(args[param_idx])
|
||||
buffer += [num].pack(@native)
|
||||
when "DWORD"
|
||||
when 'DWORD'
|
||||
num = param_to_number(args[param_idx])
|
||||
buffer += [num % 4294967296].pack(@native)
|
||||
when "WORD"
|
||||
when 'WORD'
|
||||
num = param_to_number(args[param_idx])
|
||||
buffer += [num % 65536].pack(@native)
|
||||
when "BYTE"
|
||||
when 'BYTE'
|
||||
num = param_to_number(args[param_idx])
|
||||
buffer += [num % 256].pack(@native)
|
||||
when "BOOL"
|
||||
when 'BOOL'
|
||||
case args[param_idx]
|
||||
when true
|
||||
buffer += [1].pack('V')
|
||||
|
@ -221,9 +222,9 @@ class MultiCaller
|
|||
end
|
||||
|
||||
functions.each do |f|
|
||||
dll_name,funcname,args = f
|
||||
dll_host = @parent.get_dll( dll_name )
|
||||
function = dll_host.functions[funcname]
|
||||
dll_name, function, args = f
|
||||
dll_host = @parent.get_dll(dll_name)
|
||||
function = dll_host.functions[function] unless function.instance_of? DLLFunction
|
||||
response = call_results.shift
|
||||
inout_layout, out_only_layout = layouts.shift
|
||||
|
||||
|
@ -239,28 +240,28 @@ class MultiCaller
|
|||
|
||||
# The hash the function returns
|
||||
return_hash = {
|
||||
"GetLastError" => rec_last_error,
|
||||
"ErrorMessage" => rec_err_msg
|
||||
'GetLastError' => rec_last_error,
|
||||
'ErrorMessage' => rec_err_msg
|
||||
}
|
||||
|
||||
#process return value
|
||||
case function.return_type
|
||||
when "LPVOID", "HANDLE"
|
||||
when 'LPVOID', 'HANDLE'
|
||||
if( @native == 'Q<' )
|
||||
return_hash["return"] = rec_return_value
|
||||
return_hash['return'] = rec_return_value
|
||||
else
|
||||
return_hash["return"] = rec_return_value % 4294967296
|
||||
return_hash['return'] = rec_return_value % 4294967296
|
||||
end
|
||||
when "DWORD"
|
||||
return_hash["return"] = rec_return_value % 4294967296
|
||||
when "WORD"
|
||||
return_hash["return"] = rec_return_value % 65536
|
||||
when "BYTE"
|
||||
return_hash["return"] = rec_return_value % 256
|
||||
when "BOOL"
|
||||
return_hash["return"] = (rec_return_value != 0)
|
||||
when "VOID"
|
||||
return_hash["return"] = nil
|
||||
when 'DWORD'
|
||||
return_hash['return'] = rec_return_value % 4294967296
|
||||
when 'WORD'
|
||||
return_hash['return'] = rec_return_value % 65536
|
||||
when 'BYTE'
|
||||
return_hash['return'] = rec_return_value % 256
|
||||
when 'BOOL'
|
||||
return_hash['return'] = (rec_return_value != 0)
|
||||
when 'VOID'
|
||||
return_hash['return'] = nil
|
||||
else
|
||||
raise "unexpected return type: #{function.return_type}"
|
||||
end
|
||||
|
@ -275,13 +276,13 @@ class MultiCaller
|
|||
#puts " #{param_name}"
|
||||
buffer = rec_out_only_buffers[buffer_item.addr, buffer_item.length_in_bytes]
|
||||
case buffer_item.datatype
|
||||
when "PDWORD"
|
||||
when 'PDWORD'
|
||||
return_hash[param_name] = buffer.unpack('V')[0]
|
||||
when "PCHAR"
|
||||
when 'PCHAR'
|
||||
return_hash[param_name] = asciiz_to_str(buffer)
|
||||
when "PWCHAR"
|
||||
when 'PWCHAR'
|
||||
return_hash[param_name] = uniz_to_str(buffer)
|
||||
when "PBLOB"
|
||||
when 'PBLOB'
|
||||
return_hash[param_name] = buffer
|
||||
else
|
||||
raise "unexpected type in out-only buffer of #{param_name}: #{buffer_item.datatype}"
|
||||
|
@ -292,16 +293,16 @@ class MultiCaller
|
|||
# process in-out buffers
|
||||
#puts "processing in-out buffers:"
|
||||
inout_layout.each_pair do |param_name, buffer_item|
|
||||
#puts " #{param_name}"
|
||||
#puts ' #{param_name}'
|
||||
buffer = rec_inout_buffers[buffer_item.addr, buffer_item.length_in_bytes]
|
||||
case buffer_item.datatype
|
||||
when "PDWORD"
|
||||
when 'PDWORD'
|
||||
return_hash[param_name] = buffer.unpack('V')[0]
|
||||
when "PCHAR"
|
||||
when 'PCHAR'
|
||||
return_hash[param_name] = asciiz_to_str(buffer)
|
||||
when "PWCHAR"
|
||||
when 'PWCHAR'
|
||||
return_hash[param_name] = uniz_to_str(buffer)
|
||||
when "PBLOB"
|
||||
when 'PBLOB'
|
||||
return_hash[param_name] = buffer
|
||||
else
|
||||
raise "unexpected type in in-out-buffer of #{param_name}: #{buffer_item.datatype}"
|
||||
|
|
|
@ -74,7 +74,8 @@ class Railgun
|
|||
'libc'
|
||||
].freeze,
|
||||
'osx' => [
|
||||
'libc'
|
||||
'libc',
|
||||
'libobjc'
|
||||
].freeze,
|
||||
'windows' => [
|
||||
'kernel32',
|
||||
|
|
Loading…
Reference in New Issue