The Railgun class to dynamically expose the Windows API.
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/'. 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'
Returns a Hash containing DLLs added to this instance with add_dll as well as references to any frozen cached dlls added directly in get_dll and copies of any frozen dlls (added directly with add_function) that the user attempted to modify with add_function.
Keys are friendly DLL names and values are the corresponding DLL instance
The windows_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.
# File lib/rex/post/meterpreter/extensions/stdapi/railgun/railgun.rb, line 211 def add_dll(dll_name, windows_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) end
Adds a function to an existing DLL definition.
If the DLL definition is frozen (ideally this should be the case for all cached dlls) an unfrozen copy is created and used henceforth for this instance.
# File lib/rex/post/meterpreter/extensions/stdapi/railgun/railgun.rb, line 181 def add_function(dll_name, function_name, return_type, params, windows_name=nil) unless known_dll_names.include?(dll_name) raise "DLL #{dll_name} not found. Known DLLs: #{PP.pp(known_dll_names, "")}" end dll = get_dll(dll_name) # For backwards compatibility, we ensure the dll is thawed if dll.frozen? # Duplicate not only the dll, but its functions as well. Frozen status will be lost dll = Marshal.load(Marshal.dump(dll)) # Update local dlls with the modifiable duplicate dlls[dll_name] = dll end dll.add_function(function_name, return_type, params, windows_name) end
Return a Windows constant matching str.
# File lib/rex/post/meterpreter/extensions/stdapi/railgun/railgun.rb, line 281 def const(str) return constant_manager.parse(str) end
Return this Railgun's WinConstManager instance, initially populated with constants defined in ApiConstants.
# File lib/rex/post/meterpreter/extensions/stdapi/railgun/railgun.rb, line 126 def constant_manager # Loads lazily return ApiConstants.manager end
Attempts to provide a DLL instance of the given name. Handles lazy loading and caching. Note that if a DLL of the given name does not exist, returns nil
# File lib/rex/post/meterpreter/extensions/stdapi/railgun/railgun.rb, line 230 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 unless dlls.has_key? dll_name # We read and write to @@cached_dlls and rely on state consistency @@cache_semaphore.synchronize do if @@cached_dlls.has_key? dll_name dlls[dll_name] = @@cached_dlls[dll_name] elsif BUILTIN_DLLS.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 @@cached_dlls[dll_name] = dll dlls[dll_name] = dll end end end return dlls[dll_name] end
# File lib/rex/post/meterpreter/extensions/stdapi/railgun/railgun.rb, line 221 def known_dll_names return BUILTIN_DLLS | dlls.keys end
Read data from a memory address on the host (useful for working with LPVOID parameters)
# File lib/rex/post/meterpreter/extensions/stdapi/railgun/railgun.rb, line 135 def memread(address, length) raise "Invalid parameters." if(not address or not length) request = Packet.create_request('stdapi_railgun_memread') request.add_tlv(TLV_TYPE_RAILGUN_MEM_ADDRESS, address) request.add_tlv(TLV_TYPE_RAILGUN_MEM_LENGTH, length) response = client.send_request(request) if(response.result == 0) return response.get_tlv_value(TLV_TYPE_RAILGUN_MEM_DATA) end return nil end
Write data to a memory address on the host (useful for working with LPVOID parameters)
# File lib/rex/post/meterpreter/extensions/stdapi/railgun/railgun.rb, line 156 def memwrite(address, data, length) 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 end
Fake having members like user32 and kernel32. reason is that
...user32.MessageBoxW()
is prettier than
...dlls["user32"].functions["MessageBoxW"]()
# File lib/rex/post/meterpreter/extensions/stdapi/railgun/railgun.rb, line 266 def method_missing(dll_symbol, *args) dll_name = dll_symbol.to_s unless known_dll_names.include? dll_name raise "DLL #{dll_name} not found. Known DLLs: #{PP.pp(known_dll_names, '')}" end dll = get_dll(dll_name) return DLLWrapper.new(dll, client) end
The multi-call shorthand (["kernel32", "ExitProcess", [0]])
# File lib/rex/post/meterpreter/extensions/stdapi/railgun/railgun.rb, line 288 def multi(functions) if @multicaller.nil? @multicaller = MultiCaller.new(client, self) end return @multicaller.call(functions) end
Return this Railgun's Util instance.
# File lib/rex/post/meterpreter/extensions/stdapi/railgun/railgun.rb, line 114 def util if @util.nil? @util = Util.new(self, client.platform) end return @util end
Generated with the Darkfish Rdoc Generator 2.