Support platform specific railgun constants

bug/bundler_fix
Spencer McIntyre 2017-04-25 12:24:49 -04:00
parent daf8833174
commit 9c60c3ee46
19 changed files with 125 additions and 99 deletions

View File

@ -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

View File

@ -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

View File

@ -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'],

View File

@ -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'],

View File

@ -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"],

View File

@ -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',[])

View File

@ -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"]

View File

@ -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"],

View File

@ -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),

View File

@ -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', [
])

View File

@ -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"],

View File

@ -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"],

View File

@ -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',[

View File

@ -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'],

View File

@ -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"],

View File

@ -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

View File

@ -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

View File

@ -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<'

View File

@ -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,7 +62,7 @@ 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
@ -129,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
#
@ -162,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
#
@ -252,7 +263,7 @@ class Railgun
end
require "rex/post/meterpreter/extensions/stdapi/railgun/def/#{client.platform}/def_#{dll_name}"
dll = Def.const_get('Def_' << dll_name).create_dll.freeze
dll = Def.const_get('Def_' << dll_name).create_dll(constant_manager).freeze
@@cached_dlls[dll_name] = dll
dlls[dll_name] = dll
@ -284,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)
@ -295,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)