Land #8293, add initial multi-platform railgun support
commit
123462bdca
|
@ -7,7 +7,7 @@ module Windows
|
|||
module Railgun
|
||||
|
||||
# Go through each dll and add a corresponding convenience method of the same name
|
||||
Rex::Post::Meterpreter::Extensions::Stdapi::Railgun::Railgun::BUILTIN_DLLS.each do |api|
|
||||
Rex::Post::Meterpreter::Extensions::Stdapi::Railgun::Railgun::BUILTIN_DLLS['windows'].each do |api|
|
||||
# We will be interpolating within an eval. We exercise due paranoia.
|
||||
unless api.to_s =~ /^\w+$/
|
||||
print_error 'Something is seriously wrong with Railgun.BUILTIN_DLLS list'
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
require 'thread'
|
||||
|
||||
module Rex
|
||||
module Post
|
||||
module Meterpreter
|
||||
|
@ -31,9 +33,53 @@ module Stdapi
|
|||
module Railgun
|
||||
|
||||
#
|
||||
# Manages our library of windows constants
|
||||
# A container holding useful API Constants.
|
||||
#
|
||||
class WinConstManager
|
||||
class ApiConstants
|
||||
|
||||
# This will be lazily loaded in self.manager
|
||||
@manager = nil
|
||||
|
||||
# Mutex to ensure we don't add constants more than once via thread races.
|
||||
@manager_semaphore = Mutex.new
|
||||
|
||||
class << self
|
||||
attr_accessor :manager_semaphore
|
||||
end
|
||||
|
||||
def self.inherited(child_class)
|
||||
child_class.manager_semaphore = Mutex.new
|
||||
end
|
||||
|
||||
#
|
||||
# Provides a frozen constant manager for the constants defined in
|
||||
# self.add_constants
|
||||
#
|
||||
def self.manager
|
||||
|
||||
# The first check for nil is to potentially skip the need to synchronize
|
||||
if @manager.nil?
|
||||
# Looks like we MAY need to load manager
|
||||
@manager_semaphore.synchronize do
|
||||
# We check once more. Now our options are synchronized
|
||||
if @manager.nil?
|
||||
@manager = ConstManager.new
|
||||
|
||||
self.add_constants(@manager)
|
||||
|
||||
@manager.freeze
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return @manager
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Manages our library of constants
|
||||
#
|
||||
class ConstManager
|
||||
attr_reader :consts
|
||||
|
||||
def initialize(initial_consts = {})
|
||||
|
@ -72,14 +118,14 @@ class WinConstManager
|
|||
end
|
||||
|
||||
#
|
||||
# Returns an array of constant names that have a value matching "winconst"
|
||||
# Returns an array of constant names that have a value matching "const"
|
||||
# and (optionally) a name that matches "filter_regex"
|
||||
#
|
||||
def select_const_names(winconst, filter_regex=nil)
|
||||
def select_const_names(const, filter_regex=nil)
|
||||
matches = []
|
||||
|
||||
consts.each_pair do |name, value|
|
||||
matches << name if value == winconst
|
||||
matches << name if value == const
|
||||
end
|
||||
|
||||
# Filter matches by name if a filter has been provided
|
|
@ -0,0 +1,153 @@
|
|||
# -*- coding: binary -*-
|
||||
require 'rex/post/meterpreter/extensions/stdapi/railgun/const_manager'
|
||||
|
||||
module Rex
|
||||
module Post
|
||||
module Meterpreter
|
||||
module Extensions
|
||||
module Stdapi
|
||||
module Railgun
|
||||
module Def
|
||||
|
||||
#
|
||||
# A container holding useful Linux API Constants.
|
||||
#
|
||||
class DefApiConstants_linux < ApiConstants
|
||||
|
||||
#
|
||||
# Slurp in a giant list of known constants.
|
||||
#
|
||||
def self.add_constants(const_mgr)
|
||||
const_mgr.add_const('MAP_FILE', 0x00)
|
||||
const_mgr.add_const('MAP_SHARED', 0x01)
|
||||
const_mgr.add_const('MAP_PRIVATE', 0x02)
|
||||
const_mgr.add_const('MAP_FIXED', 0x10)
|
||||
const_mgr.add_const('MAP_ANON', 0x20)
|
||||
const_mgr.add_const('MAP_ANONYMOUS', 0x20)
|
||||
const_mgr.add_const('PROT_NONE', 0x00)
|
||||
const_mgr.add_const('PROT_READ', 0x01)
|
||||
const_mgr.add_const('PROT_WRITE', 0x02)
|
||||
const_mgr.add_const('PROT_EXEC', 0x04)
|
||||
const_mgr.add_const('PROT_GROWSDOWN', 0x01000000)
|
||||
const_mgr.add_const('PROT_GROWSUP', 0x02000000)
|
||||
|
||||
const_mgr.add_const("PF_UNSPEC", 0x00000000)
|
||||
const_mgr.add_const("PF_LOCAL", 0x00000001)
|
||||
const_mgr.add_const("PF_UNIX", 0x00000000)
|
||||
const_mgr.add_const("PF_FILE", 0x00000000)
|
||||
const_mgr.add_const("PF_INET", 0x00000002)
|
||||
const_mgr.add_const("PF_AX25", 0x00000003)
|
||||
const_mgr.add_const("PF_IPX", 0x00000004)
|
||||
const_mgr.add_const("PF_APPLETALK", 0x00000005)
|
||||
const_mgr.add_const("PF_NETROM", 0x00000006)
|
||||
const_mgr.add_const("PF_BRIDGE", 0x00000007)
|
||||
const_mgr.add_const("PF_ATMPVC", 0x00000008)
|
||||
const_mgr.add_const("PF_X25", 0x00000009)
|
||||
const_mgr.add_const("PF_INET6", 0x0000000a)
|
||||
const_mgr.add_const("PF_ROSE", 0x0000000b)
|
||||
const_mgr.add_const("PF_DECnet", 0x0000000c)
|
||||
const_mgr.add_const("PF_NETBEUI", 0x0000000d)
|
||||
const_mgr.add_const("PF_SECURITY", 0x0000000e)
|
||||
const_mgr.add_const("PF_KEY", 0x0000000f)
|
||||
const_mgr.add_const("PF_NETLINK", 0x00000010)
|
||||
const_mgr.add_const("PF_ROUTE", 0x00000000)
|
||||
const_mgr.add_const("PF_PACKET", 0x00000011)
|
||||
const_mgr.add_const("PF_ASH", 0x00000012)
|
||||
const_mgr.add_const("PF_ECONET", 0x00000013)
|
||||
const_mgr.add_const("PF_ATMSVC", 0x00000014)
|
||||
const_mgr.add_const("PF_RDS", 0x00000015)
|
||||
const_mgr.add_const("PF_SNA", 0x00000016)
|
||||
const_mgr.add_const("PF_IRDA", 0x00000017)
|
||||
const_mgr.add_const("PF_PPPOX", 0x00000018)
|
||||
const_mgr.add_const("PF_WANPIPE", 0x00000019)
|
||||
const_mgr.add_const("PF_LLC", 0x0000001a)
|
||||
const_mgr.add_const("PF_IB", 0x0000001b)
|
||||
const_mgr.add_const("PF_MPLS", 0x0000001c)
|
||||
const_mgr.add_const("PF_CAN", 0x0000001d)
|
||||
const_mgr.add_const("PF_TIPC", 0x0000001e)
|
||||
const_mgr.add_const("PF_BLUETOOTH", 0x0000001f)
|
||||
const_mgr.add_const("PF_IUCV", 0x00000020)
|
||||
const_mgr.add_const("PF_RXRPC", 0x00000021)
|
||||
const_mgr.add_const("PF_ISDN", 0x00000022)
|
||||
const_mgr.add_const("PF_PHONET", 0x00000023)
|
||||
const_mgr.add_const("PF_IEEE802154", 0x00000024)
|
||||
const_mgr.add_const("PF_CAIF", 0x00000025)
|
||||
const_mgr.add_const("PF_ALG", 0x00000026)
|
||||
const_mgr.add_const("PF_NFC", 0x00000027)
|
||||
const_mgr.add_const("PF_VSOCK", 0x00000028)
|
||||
const_mgr.add_const("PF_KCM", 0x00000029)
|
||||
const_mgr.add_const("PF_MAX", 0x0000002a)
|
||||
|
||||
const_mgr.add_const("AF_UNSPEC", 0x00000000)
|
||||
const_mgr.add_const("AF_LOCAL", 0x00000001)
|
||||
const_mgr.add_const("AF_UNIX", 0x00000000)
|
||||
const_mgr.add_const("AF_FILE", 0x00000000)
|
||||
const_mgr.add_const("AF_INET", 0x00000002)
|
||||
const_mgr.add_const("AF_AX25", 0x00000003)
|
||||
const_mgr.add_const("AF_IPX", 0x00000004)
|
||||
const_mgr.add_const("AF_APPLETALK", 0x00000005)
|
||||
const_mgr.add_const("AF_NETROM", 0x00000006)
|
||||
const_mgr.add_const("AF_BRIDGE", 0x00000007)
|
||||
const_mgr.add_const("AF_ATMPVC", 0x00000008)
|
||||
const_mgr.add_const("AF_X25", 0x00000009)
|
||||
const_mgr.add_const("AF_INET6", 0x0000000a)
|
||||
const_mgr.add_const("AF_ROSE", 0x0000000b)
|
||||
const_mgr.add_const("AF_DECnet", 0x0000000c)
|
||||
const_mgr.add_const("AF_NETBEUI", 0x0000000d)
|
||||
const_mgr.add_const("AF_SECURITY", 0x0000000e)
|
||||
const_mgr.add_const("AF_KEY", 0x0000000f)
|
||||
const_mgr.add_const("AF_NETLINK", 0x00000010)
|
||||
const_mgr.add_const("AF_ROUTE", 0x00000000)
|
||||
const_mgr.add_const("AF_PACKET", 0x00000011)
|
||||
const_mgr.add_const("AF_ASH", 0x00000012)
|
||||
const_mgr.add_const("AF_ECONET", 0x00000013)
|
||||
const_mgr.add_const("AF_ATMSVC", 0x00000014)
|
||||
const_mgr.add_const("AF_RDS", 0x00000015)
|
||||
const_mgr.add_const("AF_SNA", 0x00000016)
|
||||
const_mgr.add_const("AF_IRDA", 0x00000017)
|
||||
const_mgr.add_const("AF_PPPOX", 0x00000018)
|
||||
const_mgr.add_const("AF_WANPIPE", 0x00000019)
|
||||
const_mgr.add_const("AF_LLC", 0x0000001a)
|
||||
const_mgr.add_const("AF_IB", 0x0000001b)
|
||||
const_mgr.add_const("AF_MPLS", 0x0000001c)
|
||||
const_mgr.add_const("AF_CAN", 0x0000001d)
|
||||
const_mgr.add_const("AF_TIPC", 0x0000001e)
|
||||
const_mgr.add_const("AF_BLUETOOTH", 0x0000001f)
|
||||
const_mgr.add_const("AF_IUCV", 0x00000020)
|
||||
const_mgr.add_const("AF_RXRPC", 0x00000021)
|
||||
const_mgr.add_const("AF_ISDN", 0x00000022)
|
||||
const_mgr.add_const("AF_PHONET", 0x00000023)
|
||||
const_mgr.add_const("AF_IEEE802154", 0x00000024)
|
||||
const_mgr.add_const("AF_CAIF", 0x00000025)
|
||||
const_mgr.add_const("AF_ALG", 0x00000026)
|
||||
const_mgr.add_const("AF_NFC", 0x00000027)
|
||||
const_mgr.add_const("AF_VSOCK", 0x00000028)
|
||||
const_mgr.add_const("AF_KCM", 0x00000029)
|
||||
const_mgr.add_const("AF_MAX", 0x0000002a)
|
||||
|
||||
const_mgr.add_const("SOL_RAW", 0x000000ff)
|
||||
const_mgr.add_const("SOL_DECNET", 0x00000105)
|
||||
const_mgr.add_const("SOL_X25", 0x00000106)
|
||||
const_mgr.add_const("SOL_PACKET", 0x00000107)
|
||||
const_mgr.add_const("SOL_ATM", 0x00000108)
|
||||
const_mgr.add_const("SOL_AAL", 0x00000109)
|
||||
const_mgr.add_const("SOL_IRDA", 0x0000010a)
|
||||
const_mgr.add_const("SOL_NETBEUI", 0x0000010b)
|
||||
const_mgr.add_const("SOL_LLC", 0x0000010c)
|
||||
const_mgr.add_const("SOL_DCCP", 0x0000010d)
|
||||
const_mgr.add_const("SOL_NETLINK", 0x0000010e)
|
||||
const_mgr.add_const("SOL_TIPC", 0x0000010f)
|
||||
const_mgr.add_const("SOL_RXRPC", 0x00000110)
|
||||
const_mgr.add_const("SOL_PPPOL2TP", 0x00000111)
|
||||
const_mgr.add_const("SOL_BLUETOOTH", 0x00000112)
|
||||
const_mgr.add_const("SOL_PNPIPE", 0x00000113)
|
||||
const_mgr.add_const("SOL_RDS", 0x00000114)
|
||||
const_mgr.add_const("SOL_IUCV", 0x00000115)
|
||||
const_mgr.add_const("SOL_CAIF", 0x00000116)
|
||||
const_mgr.add_const("SOL_ALG", 0x00000117)
|
||||
const_mgr.add_const("SOL_NFC", 0x00000118)
|
||||
const_mgr.add_const("SOL_KCM", 0x00000119)
|
||||
end
|
||||
end
|
||||
|
||||
end; end; end; end; end; end; end
|
|
@ -0,0 +1,121 @@
|
|||
# -*- coding: binary -*-
|
||||
module Rex
|
||||
module Post
|
||||
module Meterpreter
|
||||
module Extensions
|
||||
module Stdapi
|
||||
module Railgun
|
||||
module Def
|
||||
|
||||
class Def_libc
|
||||
|
||||
def self.create_dll(constant_manager, dll_path = 'libc.so.6')
|
||||
dll = DLL.new(dll_path, constant_manager)
|
||||
|
||||
dll.add_function(
|
||||
'calloc',
|
||||
'LPVOID',
|
||||
[
|
||||
['SIZE_T', 'nmemb', 'in'],
|
||||
['SIZE_T', 'size', 'in']
|
||||
],
|
||||
nil,
|
||||
'cdecl'
|
||||
)
|
||||
dll.add_function(
|
||||
'free',
|
||||
'VOID',
|
||||
[
|
||||
['LPVOID', 'ptr', 'in']
|
||||
],
|
||||
nil,
|
||||
'cdecl',
|
||||
)
|
||||
dll.add_function(
|
||||
'getpid',
|
||||
'DWORD',
|
||||
[],
|
||||
nil,
|
||||
'cdecl'
|
||||
)
|
||||
dll.add_function(
|
||||
'inet_ntop',
|
||||
'LPVOID',
|
||||
[
|
||||
['DWORD', 'af', 'in'],
|
||||
['PBLOB', 'src', 'in'],
|
||||
['PBLOB', 'dst', 'out'],
|
||||
['DWORD', 'size', 'in']
|
||||
],
|
||||
nil,
|
||||
'cdecl'
|
||||
)
|
||||
dll.add_function(
|
||||
'inet_pton',
|
||||
'DWORD',
|
||||
[
|
||||
['DWORD', 'af', 'in'],
|
||||
['PBLOB', 'src', 'in'],
|
||||
['PBLOB', 'dst', 'out']
|
||||
],
|
||||
nil,
|
||||
'cdecl'
|
||||
)
|
||||
dll.add_function(
|
||||
'malloc',
|
||||
'LPVOID',
|
||||
[['SIZE_T', 'size', 'in']],
|
||||
nil,
|
||||
'cdecl'
|
||||
)
|
||||
dll.add_function(
|
||||
'memfrob',
|
||||
'LPVOID',
|
||||
[
|
||||
['PBLOB', 'mem', 'inout'],
|
||||
['SIZE_T', 'length', 'in']
|
||||
],
|
||||
nil,
|
||||
'cdecl'
|
||||
)
|
||||
dll.add_function(
|
||||
'mmap',
|
||||
'LPVOID',
|
||||
[
|
||||
['LPVOID', 'addr', 'in'],
|
||||
['SIZE_T', 'length', 'in'],
|
||||
['DWORD', 'prot', 'in'],
|
||||
['DWORD', 'flags', 'in'],
|
||||
['DWORD', 'fd', 'in'],
|
||||
['SIZE_T', 'offset', 'in']
|
||||
],
|
||||
nil,
|
||||
'cdecl'
|
||||
)
|
||||
dll.add_function(
|
||||
'mprotect',
|
||||
'DWORD',
|
||||
[
|
||||
['LPVOID', 'addr', 'in'],
|
||||
['SIZE_T', 'length', 'in'],
|
||||
['DWORD', 'prot', 'in']
|
||||
],
|
||||
nil,
|
||||
'cdecl'
|
||||
)
|
||||
dll.add_function(
|
||||
'munmap',
|
||||
'DWORD',
|
||||
[
|
||||
['LPVOID', 'addr', 'in'],
|
||||
['SIZE_T', 'length', 'in']
|
||||
],
|
||||
nil,
|
||||
'cdecl'
|
||||
)
|
||||
return dll
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end; end; end; end; end; end; end
|
|
@ -1,6 +1,5 @@
|
|||
# -*- coding: binary -*-
|
||||
require 'rex/post/meterpreter/extensions/stdapi/railgun/win_const_manager'
|
||||
require 'thread'
|
||||
require 'rex/post/meterpreter/extensions/stdapi/railgun/const_manager'
|
||||
|
||||
module Rex
|
||||
module Post
|
||||
|
@ -8,41 +7,12 @@ module Meterpreter
|
|||
module Extensions
|
||||
module Stdapi
|
||||
module Railgun
|
||||
module Def
|
||||
|
||||
#
|
||||
# A container holding useful Windows API Constants.
|
||||
#
|
||||
class ApiConstants
|
||||
|
||||
# This will be lazily loaded in self.manager
|
||||
@@manager = nil
|
||||
|
||||
# Mutex to ensure we don't add constants more than once via thread races.
|
||||
@@manager_semaphore = Mutex.new
|
||||
|
||||
#
|
||||
# Provides a frozen constant manager for the constants defined in
|
||||
# self.add_constants
|
||||
#
|
||||
def self.manager
|
||||
|
||||
# The first check for nil is to potentially skip the need to synchronize
|
||||
if @@manager.nil?
|
||||
# Looks like we MAY need to load manager
|
||||
@@manager_semaphore.synchronize do
|
||||
# We check once more. Now our options are synchronized
|
||||
if @@manager.nil?
|
||||
@@manager = WinConstManager.new
|
||||
|
||||
self.add_constants(@@manager)
|
||||
|
||||
@@manager.freeze
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return @@manager
|
||||
end
|
||||
class DefApiConstants_windows < ApiConstants
|
||||
|
||||
#
|
||||
# Slurp in a giant list of known constants.
|
||||
|
@ -2356,31 +2326,31 @@ class ApiConstants
|
|||
win_const_mgr.add_const('RTM_VIEW_MASK_UCAST',0x00000001)
|
||||
win_const_mgr.add_const('CERT_ALT_NAME_VALUE_ERR_INDEX_MASK',0x0000FFFF)
|
||||
win_const_mgr.add_const('ERROR_NO_SUCH_GROUP',0x00000527)
|
||||
|
||||
|
||||
# Generic Access Rights
|
||||
win_const_mgr.add_const('GENERIC_ALL',0x10000000)
|
||||
win_const_mgr.add_const('GENERIC_EXECUTE',0x20000000)
|
||||
win_const_mgr.add_const('GENERIC_WRITE',0x40000000)
|
||||
win_const_mgr.add_const('GENERIC_READ',0x80000000)
|
||||
|
||||
|
||||
|
||||
|
||||
# Standard Access Rights
|
||||
win_const_mgr.add_const('DELETE',0x00010000)
|
||||
win_const_mgr.add_const('READ_CONTROL',0x00020000)
|
||||
win_const_mgr.add_const('WRITE_DAC',0x00040000)
|
||||
win_const_mgr.add_const('WRITE_OWNER',0x00080000)
|
||||
win_const_mgr.add_const('ACCESS_SYSTEM_SECURITY',0x01000000)
|
||||
|
||||
|
||||
# Services
|
||||
win_const_mgr.add_const('SERVICE_NO_CHANGE',0xFFFFFFFF)
|
||||
|
||||
|
||||
# Service Start Types
|
||||
win_const_mgr.add_const('START_TYPE_BOOT',0x00000000)
|
||||
win_const_mgr.add_const('START_TYPE_SYSTEM',0x00000001)
|
||||
win_const_mgr.add_const('START_TYPE_AUTO',0x00000002)
|
||||
win_const_mgr.add_const('START_TYPE_MANUAL',0x00000003)
|
||||
win_const_mgr.add_const('START_TYPE_DISABLED',0x00000004)
|
||||
|
||||
|
||||
# Service States
|
||||
win_const_mgr.add_const('SERVICE_STOPPED',0x00000001)
|
||||
win_const_mgr.add_const('SERVICE_START_PENDING',0x00000002)
|
||||
|
@ -2389,7 +2359,7 @@ class ApiConstants
|
|||
win_const_mgr.add_const('SERVICE_CONTINUE_PENDING',0x00000005)
|
||||
win_const_mgr.add_const('SERVICE_PAUSE_PENDING',0x00000006)
|
||||
win_const_mgr.add_const('SERVICE_PAUSED',0x00000007)
|
||||
|
||||
|
||||
# Service Types
|
||||
win_const_mgr.add_const('SERVICE_KERNEL_DRIVER',0x00000001)
|
||||
win_const_mgr.add_const('SERVICE_FILE_SYSTEM_DRIVER',0x00000002)
|
||||
|
@ -2397,7 +2367,7 @@ class ApiConstants
|
|||
win_const_mgr.add_const('SERVICE_RECOGNIZER_DRIVER',0x00000008)
|
||||
win_const_mgr.add_const('SERVICE_WIN32_OWN_PROCESS',0x00000010)
|
||||
win_const_mgr.add_const('SERVICE_WIN32_SHARE_PROCESS',0x00000020)
|
||||
|
||||
|
||||
# Service Manager Permissions
|
||||
win_const_mgr.add_const('SC_MANAGER_CONNECT',0x00000001)
|
||||
win_const_mgr.add_const('SC_MANAGER_CREATE_SERVICE',0x00000002)
|
||||
|
@ -2407,7 +2377,7 @@ class ApiConstants
|
|||
win_const_mgr.add_const('SC_MANAGER_MODIFY_BOOT_CONFIG',0x00000020)
|
||||
win_const_mgr.add_const('SC_MANAGER_USER_DEFINED_CONTROL',0x00000100)
|
||||
win_const_mgr.add_const('SC_MANAGER_ALL_ACCESS',0x000F003F)
|
||||
|
||||
|
||||
# Service Permissions
|
||||
win_const_mgr.add_const('SERVICE_QUERY_CONFIG',0x00000001)
|
||||
win_const_mgr.add_const('SERVICE_CHANGE_CONFIG',0x00000002)
|
||||
|
@ -2419,7 +2389,7 @@ class ApiConstants
|
|||
win_const_mgr.add_const('SERVICE_INTERROGATE',0x00000080)
|
||||
win_const_mgr.add_const('SERVICE_USER_DEFINED_CONTROL',0x00000100)
|
||||
win_const_mgr.add_const('SERVICE_ALL_ACCESS',0x000F01FF)
|
||||
|
||||
|
||||
win_const_mgr.add_const('LINEINITIALIZEEXOPTION_USECOMPLETIONPORT',0x00000003)
|
||||
win_const_mgr.add_const('AVIIF_TWOCC',0x00000002)
|
||||
win_const_mgr.add_const('TBTS_LEFT',0x00000001)
|
||||
|
@ -38170,4 +38140,4 @@ class ApiConstants
|
|||
|
||||
end
|
||||
|
||||
end; end; end; end; end; end
|
||||
end; end; end; end; end; end; end
|
|
@ -24,8 +24,8 @@ class Def_advapi32
|
|||
[:UserName, :LPTSTR]
|
||||
]
|
||||
|
||||
def self.create_dll(dll_path = 'advapi32')
|
||||
dll = DLL.new(dll_path, ApiConstants.manager)
|
||||
def self.create_dll(constant_manager, dll_path = 'advapi32')
|
||||
dll = DLL.new(dll_path, constant_manager)
|
||||
|
||||
dll.add_function('QueryServiceStatus', 'DWORD', [
|
||||
['LPVOID', 'hService', 'in'],
|
|
@ -9,8 +9,8 @@ module Def
|
|||
|
||||
class Def_crypt32
|
||||
|
||||
def self.create_dll(dll_path = 'crypt32')
|
||||
dll = DLL.new(dll_path, ApiConstants.manager)
|
||||
def self.create_dll(constant_manager, dll_path = 'crypt32')
|
||||
dll = DLL.new(dll_path, constant_manager)
|
||||
|
||||
dll.add_function('CryptUnprotectData', 'BOOL', [
|
||||
['PBLOB','pDataIn', 'in'],
|
|
@ -9,8 +9,8 @@ module Def
|
|||
|
||||
class Def_iphlpapi
|
||||
|
||||
def self.create_dll(dll_path = 'iphlpapi')
|
||||
dll = DLL.new(dll_path, ApiConstants.manager)
|
||||
def self.create_dll(constant_manager, dll_path = 'iphlpapi')
|
||||
dll = DLL.new(dll_path, constant_manager)
|
||||
|
||||
dll.add_function('CancelIPChangeNotify', 'BOOL',[
|
||||
["PBLOB","notifyOverlapped","in"],
|
|
@ -9,8 +9,8 @@ module Def
|
|||
|
||||
class Def_kernel32
|
||||
|
||||
def self.create_dll(dll_path = 'kernel32')
|
||||
dll = DLL.new(dll_path, ApiConstants.manager)
|
||||
def self.create_dll(constant_manager, dll_path = 'kernel32')
|
||||
dll = DLL.new(dll_path, constant_manager)
|
||||
|
||||
dll.add_function( 'GetConsoleWindow', 'LPVOID',[])
|
||||
|
|
@ -9,8 +9,8 @@ module Def
|
|||
|
||||
class Def_netapi32
|
||||
|
||||
def self.create_dll(dll_path = 'netapi32')
|
||||
dll = DLL.new(dll_path, ApiConstants.manager)
|
||||
def self.create_dll(constant_manager, dll_path = 'netapi32')
|
||||
dll = DLL.new(dll_path, constant_manager)
|
||||
|
||||
dll.add_function('NetApiBufferFree','DWORD',[
|
||||
["LPVOID","Buffer","in"]
|
|
@ -9,8 +9,8 @@ module Def
|
|||
|
||||
class Def_ntdll
|
||||
|
||||
def self.create_dll(dll_path = 'ntdll')
|
||||
dll = DLL.new(dll_path, ApiConstants.manager)
|
||||
def self.create_dll(constant_manager, dll_path = 'ntdll')
|
||||
dll = DLL.new(dll_path, constant_manager)
|
||||
|
||||
dll.add_function('NtAllocateVirtualMemory', 'DWORD',[
|
||||
["DWORD","ProcessHandle","in"],
|
|
@ -9,8 +9,8 @@ module Def
|
|||
|
||||
class Def_psapi
|
||||
|
||||
def self.create_dll(dll_path = 'psapi')
|
||||
dll = DLL.new(dll_path, ApiConstants.manager)
|
||||
def self.create_dll(constant_manager, dll_path = 'psapi')
|
||||
dll = DLL.new(dll_path, constant_manager)
|
||||
|
||||
dll.add_function('EnumDeviceDrivers', 'BOOL',[
|
||||
%w(PBLOB lpImageBase out),
|
|
@ -9,8 +9,8 @@ module Def
|
|||
|
||||
class Def_shell32
|
||||
|
||||
def self.create_dll(dll_path = 'shell32')
|
||||
dll = DLL.new(dll_path, ApiConstants.manager)
|
||||
def self.create_dll(constant_manager, dll_path = 'shell32')
|
||||
dll = DLL.new(dll_path, constant_manager)
|
||||
|
||||
dll.add_function('IsUserAnAdmin', 'BOOL', [
|
||||
])
|
|
@ -9,8 +9,8 @@ module Def
|
|||
|
||||
class Def_user32
|
||||
|
||||
def self.create_dll(dll_path = 'user32')
|
||||
dll = DLL.new(dll_path, ApiConstants.manager)
|
||||
def self.create_dll(constant_manager, dll_path = 'user32')
|
||||
dll = DLL.new(dll_path, constant_manager)
|
||||
|
||||
dll.add_function('ActivateKeyboardLayout', 'DWORD',[
|
||||
["DWORD","hkl","in"],
|
|
@ -9,8 +9,8 @@ module Def
|
|||
|
||||
class Def_version
|
||||
|
||||
def self.create_dll(dll_path = 'version')
|
||||
dll = DLL.new(dll_path, ApiConstants.manager)
|
||||
def self.create_dll(constant_manager, dll_path = 'version')
|
||||
dll = DLL.new(dll_path, constant_manager)
|
||||
|
||||
dll.add_function('GetFileVersionInfoA', 'BOOL',[
|
||||
["PCHAR","lptstrFilename","in"],
|
|
@ -9,8 +9,8 @@ module Def
|
|||
|
||||
class Def_wlanapi
|
||||
|
||||
def self.create_dll(dll_path = 'wlanapi')
|
||||
dll = DLL.new(dll_path, ApiConstants.manager)
|
||||
def self.create_dll(constant_manager, dll_path = 'wlanapi')
|
||||
dll = DLL.new(dll_path, constant_manager)
|
||||
|
||||
|
||||
dll.add_function( 'WlanOpenHandle', 'DWORD',[
|
|
@ -9,8 +9,8 @@ module Def
|
|||
|
||||
class Def_wldap32
|
||||
|
||||
def self.create_dll(dll_path = 'wldap32')
|
||||
dll = DLL.new(dll_path, ApiConstants.manager)
|
||||
def self.create_dll(constant_manager, dll_path = 'wldap32')
|
||||
dll = DLL.new(dll_path, constant_manager)
|
||||
|
||||
dll.add_function('ldap_sslinitA', 'DWORD',[
|
||||
['PCHAR', 'HostName', 'in'],
|
|
@ -9,8 +9,8 @@ module Def
|
|||
|
||||
class Def_ws2_32
|
||||
|
||||
def self.create_dll(dll_path = 'ws2_32')
|
||||
dll = DLL.new(dll_path, ApiConstants.manager)
|
||||
def self.create_dll(constant_manager, dll_path = 'ws2_32')
|
||||
dll = DLL.new(dll_path, constant_manager)
|
||||
|
||||
dll.add_function('getaddrinfo', 'DWORD',[
|
||||
["PCHAR","pNodeName","in"],
|
|
@ -46,11 +46,11 @@ class DLL
|
|||
attr_accessor :functions
|
||||
attr_reader :dll_path
|
||||
|
||||
def initialize(dll_path, win_consts)
|
||||
def initialize(dll_path, consts_mgr)
|
||||
@dll_path = dll_path
|
||||
|
||||
# needed by DLLHelper
|
||||
@win_consts = win_consts
|
||||
@consts_mgr = consts_mgr
|
||||
|
||||
self.functions = {}
|
||||
end
|
||||
|
@ -99,7 +99,7 @@ class DLL
|
|||
# ["DWORD","uType","in"],
|
||||
# ])
|
||||
#
|
||||
# Use +windows_name+ when the actual windows name is different from the
|
||||
# Use +remote_name+ when the actual library name is different from the
|
||||
# ruby variable. You might need to do this for example when the actual
|
||||
# func name is myFunc@4 or when you want to create an alternative version
|
||||
# of an existing function.
|
||||
|
@ -107,11 +107,11 @@ class DLL
|
|||
# When the new function is called it will return a list containing the
|
||||
# return value and all inout params. See #call_function.
|
||||
#
|
||||
def add_function(name, return_type, params, windows_name=nil, calling_conv="stdcall")
|
||||
if windows_name == nil
|
||||
windows_name = name
|
||||
def add_function(name, return_type, params, remote_name=nil, calling_conv="stdcall")
|
||||
if remote_name == nil
|
||||
remote_name = name
|
||||
end
|
||||
@functions[name] = DLLFunction.new(return_type, params, windows_name, calling_conv)
|
||||
@functions[name] = DLLFunction.new(return_type, params, remote_name, calling_conv)
|
||||
end
|
||||
|
||||
private
|
||||
|
@ -125,8 +125,6 @@ class DLL
|
|||
native = 'V'
|
||||
end
|
||||
|
||||
#puts "process_function_call(function.windows_name,#{PP.pp(args, "")})"
|
||||
|
||||
# We transmit the immediate stack and three heap-buffers:
|
||||
# in, inout and out. The reason behind the separation is bandwidth.
|
||||
# We don't want to transmit uninitialized data in or no-longer-needed data out.
|
||||
|
@ -221,7 +219,7 @@ class DLL
|
|||
# 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", "HANDLE"
|
||||
when "LPVOID", "HANDLE", "SIZE_T"
|
||||
num = param_to_number(args[param_idx])
|
||||
buffer += [num].pack(native)
|
||||
when "DWORD"
|
||||
|
@ -261,8 +259,8 @@ class DLL
|
|||
request.add_tlv(TLV_TYPE_RAILGUN_BUFFERBLOB_IN, in_only_buffer)
|
||||
request.add_tlv(TLV_TYPE_RAILGUN_BUFFERBLOB_INOUT, inout_buffer)
|
||||
|
||||
request.add_tlv(TLV_TYPE_RAILGUN_DLLNAME, @dll_path )
|
||||
request.add_tlv(TLV_TYPE_RAILGUN_FUNCNAME, function.windows_name)
|
||||
request.add_tlv(TLV_TYPE_RAILGUN_DLLNAME, @dll_path)
|
||||
request.add_tlv(TLV_TYPE_RAILGUN_FUNCNAME, function.remote_name)
|
||||
request.add_tlv(TLV_TYPE_RAILGUN_CALLCONV, function.calling_conv)
|
||||
|
||||
response = client.send_request(request)
|
||||
|
@ -368,7 +366,7 @@ class DLL
|
|||
#=== START of proccess_function_call snapshot ===
|
||||
# {
|
||||
# :platform => '#{native == 'Q' ? 'x64/windows' : 'x86/windows'}',
|
||||
# :name => '#{function.windows_name}',
|
||||
# :name => '#{function.remote_name}',
|
||||
# :params => #{function.params},
|
||||
# :return_type => '#{function.return_type}',
|
||||
# :dll_name => '#{@dll_path}',
|
||||
|
@ -379,7 +377,7 @@ class DLL
|
|||
# TLV_TYPE_RAILGUN_BUFFERBLOB_IN => #{in_only_buffer.inspect},
|
||||
# TLV_TYPE_RAILGUN_BUFFERBLOB_INOUT => #{inout_buffer.inspect},
|
||||
# TLV_TYPE_RAILGUN_DLLNAME => '#{@dll_path}',
|
||||
# TLV_TYPE_RAILGUN_FUNCNAME => '#{function.windows_name}',
|
||||
# TLV_TYPE_RAILGUN_FUNCNAME => '#{function.remote_name}',
|
||||
# },
|
||||
# :response_from_client => {
|
||||
# TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_INOUT => #{rec_inout_buffers.inspect},
|
||||
|
|
|
@ -40,8 +40,9 @@ class DLLFunction
|
|||
"DWORD" => ["in", "return"],
|
||||
"WORD" => ["in", "return"],
|
||||
"BYTE" => ["in", "return"],
|
||||
"LPVOID" => ["in", "return"], # sf: for specifying a memory address (e.g. VirtualAlloc/HeapAlloc/...) where we dont want ot back it up with actuall mem ala PBLOB
|
||||
"LPVOID" => ["in", "return"], # sf: for specifying a memory address (e.g. VirtualAlloc/HeapAlloc/...) where we don't want to back it up with actual mem ala PBLOB
|
||||
"HANDLE" => ["in", "return"],
|
||||
"SIZE_T" => ["in", "return"],
|
||||
"PDWORD" => ["in", "out", "inout"], # todo: support for functions that return pointers to strings
|
||||
"PWCHAR" => ["in", "out", "inout"],
|
||||
"PCHAR" => ["in", "out", "inout"],
|
||||
|
@ -52,15 +53,15 @@ class DLLFunction
|
|||
|
||||
@@directions = ["in", "out", "inout", "return"].freeze
|
||||
|
||||
attr_reader :return_type, :params, :windows_name, :calling_conv
|
||||
attr_reader :return_type, :params, :remote_name, :calling_conv
|
||||
|
||||
def initialize(return_type, params, windows_name, calling_conv="stdcall")
|
||||
def initialize(return_type, params, remote_name, calling_conv="stdcall")
|
||||
check_return_type(return_type) # we do error checking as early as possible so the library is easier to use
|
||||
check_params(params)
|
||||
check_calling_conv(calling_conv)
|
||||
@return_type = return_type
|
||||
@params = params
|
||||
@windows_name = windows_name
|
||||
@remote_name = remote_name
|
||||
@calling_conv = calling_conv
|
||||
end
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ module DLLHelper
|
|||
|
||||
# converts ruby string to zero-terminated ASCII string
|
||||
def str_to_ascii_z(str)
|
||||
return str+"\x00"
|
||||
return str + "\x00"
|
||||
end
|
||||
|
||||
# converts 0-terminated ASCII string to ruby string
|
||||
|
@ -72,14 +72,14 @@ module DLLHelper
|
|||
# "SOME_CONSTANT | OTHER_CONSTANT" => 17
|
||||
# "tuna" => !!!!!!!!!!Exception
|
||||
#
|
||||
# Parameter "win_consts" is a WinConstantManager
|
||||
def param_to_number(v, win_consts = @win_consts)
|
||||
# Parameter "consts_mgr" is a ConstantManager
|
||||
def param_to_number(v, consts_mgr = @consts_mgr)
|
||||
if v.class == NilClass then
|
||||
return 0
|
||||
elsif v.kind_of? Integer then
|
||||
return v # ok, it's already a number
|
||||
elsif v.kind_of? String then
|
||||
dw = win_consts.parse(v) # might raise an exception
|
||||
dw = consts_mgr.parse(v) # might raise an exception
|
||||
if dw != nil
|
||||
return dw
|
||||
else
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
|
||||
require 'pp'
|
||||
require 'enumerator'
|
||||
require 'rex/post/meterpreter/extensions/stdapi/railgun/api_constants'
|
||||
require 'rex/post/meterpreter/extensions/stdapi/railgun/tlv'
|
||||
require 'rex/post/meterpreter/extensions/stdapi/railgun/dll_helper'
|
||||
require 'rex/post/meterpreter/extensions/stdapi/railgun/buffer_item'
|
||||
|
@ -42,12 +41,12 @@ class MultiCaller
|
|||
|
||||
include DLLHelper
|
||||
|
||||
def initialize( client, parent, win_consts )
|
||||
def initialize(client, parent, consts_mgr)
|
||||
@parent = parent
|
||||
@client = client
|
||||
|
||||
# needed by DLL helper
|
||||
@win_consts = win_consts
|
||||
@consts_mgr = consts_mgr
|
||||
|
||||
if @client.native_arch == ARCH_X64
|
||||
@native = 'Q<'
|
||||
|
@ -75,7 +74,6 @@ class MultiCaller
|
|||
end
|
||||
|
||||
raise "#{function.params.length} arguments expected. #{args.length} arguments provided." unless args.length == function.params.length
|
||||
#puts "process_function_call(function.windows_name,#{PP.pp(args, "")})"
|
||||
|
||||
# We transmit the immediate stack and three heap-buffers:
|
||||
# in, inout and out. The reason behind the separation is bandwidth.
|
||||
|
@ -170,7 +168,7 @@ class MultiCaller
|
|||
# it's not a pointer
|
||||
buffer = [0].pack(@native)
|
||||
case param_desc[0]
|
||||
when "LPVOID", "HANDLE"
|
||||
when "LPVOID", "HANDLE", "SIZE_T"
|
||||
num = param_to_number(args[param_idx])
|
||||
buffer += [num].pack(@native)
|
||||
when "DWORD"
|
||||
|
@ -209,8 +207,8 @@ class MultiCaller
|
|||
group.add_tlv(TLV_TYPE_RAILGUN_STACKBLOB, literal_pairs_blob)
|
||||
group.add_tlv(TLV_TYPE_RAILGUN_BUFFERBLOB_IN, in_only_buffer)
|
||||
group.add_tlv(TLV_TYPE_RAILGUN_BUFFERBLOB_INOUT, inout_buffer)
|
||||
group.add_tlv(TLV_TYPE_RAILGUN_DLLNAME, dll_name )
|
||||
group.add_tlv(TLV_TYPE_RAILGUN_FUNCNAME, function.windows_name)
|
||||
group.add_tlv(TLV_TYPE_RAILGUN_DLLNAME, dll_host.dll_path)
|
||||
group.add_tlv(TLV_TYPE_RAILGUN_FUNCNAME, function.remote_name)
|
||||
request.tlvs << group
|
||||
|
||||
layouts << [inout_layout, out_only_layout]
|
||||
|
|
|
@ -31,13 +31,16 @@
|
|||
# chao - June 2011 - major overhaul of dll lazy loading, caching, and bit of everything
|
||||
#
|
||||
|
||||
#
|
||||
# zeroSteiner - April 2017 - added support for non-windows platforms
|
||||
#
|
||||
|
||||
require 'pp'
|
||||
require 'enumerator'
|
||||
|
||||
require 'rex/post/meterpreter/extensions/stdapi/railgun/api_constants'
|
||||
require 'rex/post/meterpreter/extensions/stdapi/railgun/tlv'
|
||||
require 'rex/post/meterpreter/extensions/stdapi/railgun/util'
|
||||
require 'rex/post/meterpreter/extensions/stdapi/railgun/win_const_manager'
|
||||
require 'rex/post/meterpreter/extensions/stdapi/railgun/const_manager'
|
||||
require 'rex/post/meterpreter/extensions/stdapi/railgun/multicall'
|
||||
require 'rex/post/meterpreter/extensions/stdapi/railgun/dll'
|
||||
require 'rex/post/meterpreter/extensions/stdapi/railgun/dll_wrapper'
|
||||
|
@ -59,28 +62,33 @@ class Railgun
|
|||
# Railgun::DLL's that have builtin definitions.
|
||||
#
|
||||
# If you want to add additional DLL definitions to be preloaded create a
|
||||
# definition class 'rex/post/meterpreter/extensions/stdapi/railgun/def/'.
|
||||
# definition class 'rex/post/meterpreter/extensions/stdapi/railgun/def/$platform/'.
|
||||
# Naming is important and should follow convention. For example, if your
|
||||
# dll's name was "my_dll"
|
||||
# file name: def_my_dll.rb
|
||||
# class name: Def_my_dll
|
||||
# entry below: 'my_dll'
|
||||
#
|
||||
BUILTIN_DLLS = [
|
||||
'kernel32',
|
||||
'ntdll',
|
||||
'user32',
|
||||
'ws2_32',
|
||||
'iphlpapi',
|
||||
'advapi32',
|
||||
'shell32',
|
||||
'netapi32',
|
||||
'crypt32',
|
||||
'wlanapi',
|
||||
'wldap32',
|
||||
'version',
|
||||
'psapi'
|
||||
].freeze
|
||||
BUILTIN_DLLS = {
|
||||
'linux' => [
|
||||
'libc'
|
||||
].freeze,
|
||||
'windows' => [
|
||||
'kernel32',
|
||||
'ntdll',
|
||||
'user32',
|
||||
'ws2_32',
|
||||
'iphlpapi',
|
||||
'advapi32',
|
||||
'shell32',
|
||||
'netapi32',
|
||||
'crypt32',
|
||||
'wlanapi',
|
||||
'wldap32',
|
||||
'version',
|
||||
'psapi'
|
||||
].freeze
|
||||
}.freeze
|
||||
|
||||
##
|
||||
# Returns a Hash containing DLLs added to this instance with #add_dll
|
||||
|
@ -109,7 +117,7 @@ class Railgun
|
|||
end
|
||||
|
||||
def self.builtin_dlls
|
||||
BUILTIN_DLLS
|
||||
BUILTIN_DLLS[client.platform]
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -124,12 +132,24 @@ class Railgun
|
|||
end
|
||||
|
||||
#
|
||||
# Return this Railgun's WinConstManager instance, initially populated with
|
||||
# Return this Railgun's platform specific ApiConstants class.
|
||||
#
|
||||
def api_constants
|
||||
if @api_constants.nil?
|
||||
require "rex/post/meterpreter/extensions/stdapi/railgun/def/#{client.platform}/api_constants"
|
||||
@api_constants = Def.const_get('DefApiConstants_' << client.platform)
|
||||
end
|
||||
|
||||
return @api_constants
|
||||
end
|
||||
|
||||
#
|
||||
# Return this Railgun's ConstManager instance, initially populated with
|
||||
# constants defined in ApiConstants.
|
||||
#
|
||||
def constant_manager
|
||||
# Loads lazily
|
||||
return ApiConstants.manager
|
||||
return api_constants.manager
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -157,22 +177,18 @@ class Railgun
|
|||
# Write data to a memory address on the host (useful for working with
|
||||
# LPVOID parameters)
|
||||
#
|
||||
def memwrite(address, data, length)
|
||||
def memwrite(address, data, length=nil)
|
||||
|
||||
length = data.length if length.nil?
|
||||
raise "Invalid parameters." if(not address or not data or not length)
|
||||
|
||||
request = Packet.create_request('stdapi_railgun_memwrite')
|
||||
|
||||
request.add_tlv(TLV_TYPE_RAILGUN_MEM_ADDRESS, address)
|
||||
request.add_tlv(TLV_TYPE_RAILGUN_MEM_DATA, data)
|
||||
request.add_tlv(TLV_TYPE_RAILGUN_MEM_LENGTH, length)
|
||||
|
||||
response = client.send_request(request)
|
||||
if(response.result == 0)
|
||||
return true
|
||||
end
|
||||
|
||||
return false
|
||||
return response.result == 0
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -182,7 +198,7 @@ class Railgun
|
|||
# cached dlls) an unfrozen copy is created and used henceforth for this
|
||||
# instance.
|
||||
#
|
||||
def add_function(dll_name, function_name, return_type, params, windows_name=nil, calling_conv="stdcall")
|
||||
def add_function(dll_name, function_name, return_type, params, remote_name=nil, calling_conv="stdcall")
|
||||
|
||||
unless known_dll_names.include?(dll_name)
|
||||
raise "DLL #{dll_name} not found. Known DLLs: #{PP.pp(known_dll_names, "")}"
|
||||
|
@ -199,31 +215,31 @@ class Railgun
|
|||
dlls[dll_name] = dll
|
||||
end
|
||||
|
||||
dll.add_function(function_name, return_type, params, windows_name, calling_conv)
|
||||
dll.add_function(function_name, return_type, params, remote_name, calling_conv)
|
||||
end
|
||||
|
||||
#
|
||||
# Adds a DLL to this Railgun.
|
||||
#
|
||||
# The +windows_name+ is the name used on the remote system and should be
|
||||
# The +remote_name+ is the name used on the remote system and should be
|
||||
# set appropriately if you want to include a path or the DLL name contains
|
||||
# non-ruby-approved characters.
|
||||
#
|
||||
# Raises an exception if a dll with the given name has already been
|
||||
# defined.
|
||||
#
|
||||
def add_dll(dll_name, windows_name=dll_name)
|
||||
def add_dll(dll_name, remote_name=dll_name)
|
||||
|
||||
if dlls.has_key? dll_name
|
||||
raise "A DLL of name #{dll_name} has already been loaded."
|
||||
end
|
||||
|
||||
dlls[dll_name] = DLL.new(windows_name, constant_manager)
|
||||
dlls[dll_name] = DLL.new(remote_name, constant_manager)
|
||||
end
|
||||
|
||||
|
||||
def known_dll_names
|
||||
return BUILTIN_DLLS | dlls.keys
|
||||
return BUILTIN_DLLS[client.platform] | dlls.keys
|
||||
end
|
||||
|
||||
#
|
||||
|
@ -232,7 +248,6 @@ class Railgun
|
|||
# exist, returns nil
|
||||
#
|
||||
def get_dll(dll_name)
|
||||
|
||||
# If the DLL is not local, we now either load it from cache or load it lazily.
|
||||
# In either case, a reference to the dll is stored in the collection "dlls"
|
||||
# If the DLL can not be found/created, no actions are taken
|
||||
|
@ -241,14 +256,14 @@ class Railgun
|
|||
@@cache_semaphore.synchronize do
|
||||
if @@cached_dlls.has_key? dll_name
|
||||
dlls[dll_name] = @@cached_dlls[dll_name]
|
||||
elsif BUILTIN_DLLS.include? dll_name
|
||||
elsif BUILTIN_DLLS[client.platform].include? dll_name
|
||||
# I highly doubt this case will ever occur, but I am paranoid
|
||||
if dll_name !~ /^\w+$/
|
||||
raise "DLL name #{dll_name} is bad. Correct Railgun::BUILTIN_DLLS"
|
||||
end
|
||||
|
||||
require 'rex/post/meterpreter/extensions/stdapi/railgun/def/def_' << dll_name
|
||||
dll = Def.const_get('Def_' << dll_name).create_dll.freeze
|
||||
require "rex/post/meterpreter/extensions/stdapi/railgun/def/#{client.platform}/def_#{dll_name}"
|
||||
dll = Def.const_get('Def_' << dll_name).create_dll(constant_manager).freeze
|
||||
|
||||
@@cached_dlls[dll_name] = dll
|
||||
dlls[dll_name] = dll
|
||||
|
@ -280,7 +295,7 @@ class Railgun
|
|||
end
|
||||
|
||||
#
|
||||
# Return a Windows constant matching +str+.
|
||||
# Return a constant matching +str+.
|
||||
#
|
||||
def const(str)
|
||||
return constant_manager.parse(str)
|
||||
|
@ -291,7 +306,7 @@ class Railgun
|
|||
#
|
||||
def multi(functions)
|
||||
if @multicaller.nil?
|
||||
@multicaller = MultiCaller.new(client, self, ApiConstants.manager)
|
||||
@multicaller = MultiCaller.new(client, self, constant_manager)
|
||||
end
|
||||
|
||||
return @multicaller.call(functions)
|
||||
|
|
|
@ -16,7 +16,7 @@ module MetasploitModule
|
|||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Python Meterpreter',
|
||||
'Description' => 'Run a meterpreter server in Python (2.5-2.7 & 3.1-3.5)',
|
||||
'Description' => 'Run a meterpreter server in Python (2.5-2.7 & 3.1-3.6)',
|
||||
'Author' => 'Spencer McIntyre',
|
||||
'Platform' => 'python',
|
||||
'Arch' => ARCH_PYTHON,
|
||||
|
|
|
@ -11,16 +11,84 @@ class MetasploitModule < Msf::Post
|
|||
|
||||
def initialize(info={})
|
||||
super( update_info( info,
|
||||
'Name' => 'Railgun API Tests',
|
||||
'Description' => %q{ This module will test railgun api functions},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [ 'Spencer McIntyre'],
|
||||
'Platform' => [ 'windows' ]
|
||||
))
|
||||
'Name' => 'Railgun API Tests',
|
||||
'Description' => %q{ This module will test railgun api functions },
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' => [ 'Spencer McIntyre' ],
|
||||
'Platform' => [ 'linux', 'windows' ]
|
||||
))
|
||||
end
|
||||
|
||||
def test_api_function_calls
|
||||
def test_api_function_calls_linux
|
||||
return unless session.platform == 'linux'
|
||||
|
||||
buffer = nil
|
||||
buffer_size = 128
|
||||
buffer_value = nil
|
||||
it "Should include error information in the results" do
|
||||
ret = true
|
||||
result = session.railgun.libc.malloc(128)
|
||||
ret &&= result['GetLastError'] == 0
|
||||
ret &&= result['ErrorMessage'].is_a? String
|
||||
end
|
||||
|
||||
it "Should support functions with no parameters" do
|
||||
ret = true
|
||||
result = session.railgun.libc.getpid()
|
||||
ret &&= result['GetLastError'] == 0
|
||||
ret &&= result['return'] == session.sys.process.getpid
|
||||
end
|
||||
|
||||
it "Should support functions with literal parameters" do
|
||||
ret = true
|
||||
result = session.railgun.libc.calloc(buffer_size, 1)
|
||||
ret &&= result['GetLastError'] == 0
|
||||
buffer = result['return']
|
||||
ret &&= buffer != 0
|
||||
end
|
||||
|
||||
it "Should support functions with in/out/inout parameter types" do
|
||||
ret = true
|
||||
# first test in/out parameter types
|
||||
result = session.railgun.libc.inet_ntop('AF_INET', "\x0a\x00\x00\x01", 128, 128)
|
||||
ret &&= result['GetLastError'] == 0
|
||||
ret &&= result['return'] != 0
|
||||
ret &&= result['dst'][0...8] == '10.0.0.1'
|
||||
# then test the inout parameter type
|
||||
result = session.railgun.libc.memfrob('metasploit', 10)
|
||||
ret &&= result['GetLastError'] == 0
|
||||
ret &&= result['return'] != 0
|
||||
ret &&= result['mem'] == 'GO^KYZFEC^'
|
||||
end
|
||||
|
||||
it "Should support calling multiple functions at once" do
|
||||
ret = true
|
||||
multi_rail = [
|
||||
['libc', 'getpid', []],
|
||||
['libc', 'memfrob', ['metasploit', 10]]
|
||||
]
|
||||
results = session.railgun.multi(multi_rail)
|
||||
ret &&= results.length == multi_rail.length
|
||||
ret &&= results[0]['return'] == session.sys.process.getpid
|
||||
ret &&= results[1]['mem'] == 'GO^KYZFEC^'
|
||||
end
|
||||
|
||||
it "Should support writing memory" do
|
||||
ret = true
|
||||
buffer_value = Rex::Text.rand_text_alphanumeric(buffer_size)
|
||||
ret &&= session.railgun.memwrite(buffer, buffer_value)
|
||||
end
|
||||
|
||||
it "Should support reading memory" do
|
||||
ret = true
|
||||
ret &&= session.railgun.memread(buffer, buffer_size) == buffer_value
|
||||
end
|
||||
|
||||
session.railgun.libc.free(buffer)
|
||||
end
|
||||
|
||||
def test_api_function_calls_windows
|
||||
return unless session.platform == 'windows'
|
||||
it "Should include error information in the results" do
|
||||
ret = true
|
||||
result = session.railgun.kernel32.GetCurrentProcess()
|
||||
|
@ -70,43 +138,39 @@ class MetasploitModule < Msf::Post
|
|||
ret &&= results[2]['return'] == session.sys.process.getpid
|
||||
end
|
||||
|
||||
it "Should support reading memory" do
|
||||
ret = true
|
||||
result = client.railgun.kernel32.GetModuleHandleA('kernel32')
|
||||
ret &&= result['GetLastError'] == 0
|
||||
ret &&= result['return'] != 0
|
||||
return false unless ret
|
||||
|
||||
handle = result['return']
|
||||
mz_header = client.railgun.memread(handle, 4)
|
||||
ret &&= mz_header == "MZ\x90\x00"
|
||||
end
|
||||
|
||||
it "Should support writing memory" do
|
||||
ret = true
|
||||
result = client.railgun.kernel32.GetProcessHeap()
|
||||
result = session.railgun.kernel32.GetProcessHeap()
|
||||
ret &&= result['GetLastError'] == 0
|
||||
ret &&= result['return'] != 0
|
||||
return false unless ret
|
||||
|
||||
buffer_size = 32
|
||||
handle = result['return']
|
||||
result = client.railgun.kernel32.HeapAlloc(handle, 0, buffer_size)
|
||||
result = session.railgun.kernel32.HeapAlloc(handle, 0, buffer_size)
|
||||
ret &&= result['GetLastError'] == 0
|
||||
ret &&= result['return'] != 0
|
||||
return false unless ret
|
||||
|
||||
buffer_value = Rex::Text.rand_text_alphanumeric(buffer_size)
|
||||
buffer = result['return']
|
||||
ret &&= client.railgun.memwrite(buffer, buffer_value, buffer_size)
|
||||
ret &&= client.railgun.memread(buffer, buffer_size) == buffer_value
|
||||
ret &&= session.railgun.memwrite(buffer, buffer_value)
|
||||
ret &&= session.railgun.memread(buffer, buffer_size) == buffer_value
|
||||
|
||||
client.railgun.kernel32.HeapFree(handle, 0, buffer)
|
||||
session.railgun.kernel32.HeapFree(handle, 0, buffer)
|
||||
ret
|
||||
end
|
||||
|
||||
it "Should support reading memory" do
|
||||
ret = true
|
||||
result = session.railgun.kernel32.GetModuleHandleA('kernel32')
|
||||
ret &&= result['GetLastError'] == 0
|
||||
ret &&= result['return'] != 0
|
||||
return false unless ret
|
||||
|
||||
handle = result['return']
|
||||
mz_header = session.railgun.memread(handle, 4)
|
||||
ret &&= mz_header == "MZ\x90\x00"
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue