Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/lib/rex/post/meterpreter/extensions/stdapi/sys/registry.rb
Views: 11793
# -*- coding: binary -*-12require 'rex/post/process'3require 'rex/post/meterpreter/packet'4require 'rex/post/meterpreter/client'5require 'rex/post/meterpreter/extensions/stdapi/constants'6require 'rex/post/meterpreter/extensions/stdapi/stdapi'7require 'rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/registry_key'8require 'rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/registry_value'9require 'rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/remote_registry_key'1011module Rex12module Post13module Meterpreter14module Extensions15module Stdapi16module Sys1718###19#20# This class provides access to the Windows registry on the remote21# machine.22#23###24class Registry2526class << self27attr_accessor :client28end2930##31#32# Registry key interaction33#34##3536#37# Opens the supplied registry key relative to the root key with38# the supplied permissions. Right now this is merely a wrapper around39# create_key.40#4142def Registry.load_key(root_key,base_key,hive_file)43request = Packet.create_request(COMMAND_ID_STDAPI_REGISTRY_LOAD_KEY)44request.add_tlv(TLV_TYPE_ROOT_KEY, root_key)45request.add_tlv(TLV_TYPE_BASE_KEY, base_key)46request.add_tlv(TLV_TYPE_FILE_PATH, client.unicode_filter_decode( hive_file ))4748response = client.send_request(request)49return response.get_tlv(TLV_TYPE_RESULT).value50end5152def Registry.unload_key(root_key,base_key)53request = Packet.create_request(COMMAND_ID_STDAPI_REGISTRY_UNLOAD_KEY)54request.add_tlv(TLV_TYPE_ROOT_KEY, root_key)55request.add_tlv(TLV_TYPE_BASE_KEY, base_key)56response = client.send_request(request)57return response.get_tlv(TLV_TYPE_RESULT).value58end596061def Registry.open_key(root_key, base_key, perm = KEY_READ)62# If no base key was provided, just return the root_key.63if (base_key == nil or base_key.length == 0)64return RegistrySubsystem::RegistryKey.new(client, root_key, base_key, perm, root_key)65end6667request = Packet.create_request(COMMAND_ID_STDAPI_REGISTRY_OPEN_KEY)6869request.add_tlv(TLV_TYPE_ROOT_KEY, root_key)70request.add_tlv(TLV_TYPE_BASE_KEY, base_key)71request.add_tlv(TLV_TYPE_PERMISSION, perm)7273response = client.send_request(request)7475return Rex::Post::Meterpreter::Extensions::Stdapi::Sys::RegistrySubsystem::RegistryKey.new(76client, root_key, base_key, perm, response.get_tlv(TLV_TYPE_HKEY).value)77end7879# Checks if a key exists on the target registry80#81# @param root_key [String] the root part of the key path. Ex: HKEY_LOCAL_MACHINE82# @param base_key [String] the base part of the key path83# @return [Boolean] true if the key exists on the target registry, false otherwise, even84# it the session hasn't permissions to access the target key.85# @raise [TimeoutError] if the timeout expires when waiting the answer86# @raise [Rex::Post::Meterpreter::RequestError] if the parameters are not valid87def Registry.check_key_exists(root_key, base_key)88request = Packet.create_request(COMMAND_ID_STDAPI_REGISTRY_CHECK_KEY_EXISTS)89request.add_tlv(TLV_TYPE_ROOT_KEY, root_key)90request.add_tlv(TLV_TYPE_BASE_KEY, base_key)91response = client.send_request(request)92return response.get_tlv(TLV_TYPE_BOOL).value93end9495#96# Opens the supplied registry key on the specified remote host. Requires that the97# current process has credentials to access the target and that the target has the98# remote registry service running.99#100def Registry.open_remote_key(target_host, root_key)101102request = Packet.create_request(COMMAND_ID_STDAPI_REGISTRY_OPEN_REMOTE_KEY)103104request.add_tlv(TLV_TYPE_TARGET_HOST, target_host)105request.add_tlv(TLV_TYPE_ROOT_KEY, root_key)106107response = client.send_request(request)108109return Rex::Post::Meterpreter::Extensions::Stdapi::Sys::RegistrySubsystem::RemoteRegistryKey.new(110client, target_host, root_key, response.get_tlv(TLV_TYPE_HKEY).value)111end112113#114# Creates the supplied registry key or opens it if it already exists.115#116def Registry.create_key(root_key, base_key, perm = KEY_READ)117request = Packet.create_request(COMMAND_ID_STDAPI_REGISTRY_CREATE_KEY)118119request.add_tlv(TLV_TYPE_ROOT_KEY, root_key)120request.add_tlv(TLV_TYPE_BASE_KEY, base_key)121request.add_tlv(TLV_TYPE_PERMISSION, perm)122123response = client.send_request(request)124125return Rex::Post::Meterpreter::Extensions::Stdapi::Sys::RegistrySubsystem::RegistryKey.new(126client, root_key, base_key, perm, response.get_tlv(TLV_TYPE_HKEY).value)127end128129#130# Deletes the supplied registry key.131#132def Registry.delete_key(root_key, base_key, recursive = true)133request = Packet.create_request(COMMAND_ID_STDAPI_REGISTRY_DELETE_KEY)134flags = 0135136if (recursive)137flags |= DELETE_KEY_FLAG_RECURSIVE138end139140request.add_tlv(TLV_TYPE_ROOT_KEY, root_key)141request.add_tlv(TLV_TYPE_BASE_KEY, base_key)142request.add_tlv(TLV_TYPE_FLAGS, flags)143144if (client.send_request(request) != nil)145return true146end147148return false149end150151#152# Closes the supplied registry key.153#154def Registry.close_key(hkey)155request = Packet.create_request(COMMAND_ID_STDAPI_REGISTRY_CLOSE_KEY)156157request.add_tlv(TLV_TYPE_HKEY, hkey)158159client.send_packet(request)160161return true162end163164#165# Enumerates the supplied registry key returning an array of key names.166#167def Registry.enum_key(hkey)168keys = []169request = Packet.create_request(COMMAND_ID_STDAPI_REGISTRY_ENUM_KEY)170171request.add_tlv(TLV_TYPE_HKEY, hkey)172173response = client.send_request(request)174175# Enumerate through all of the registry keys176response.each(TLV_TYPE_KEY_NAME) { |key_name|177keys << key_name.value178}179180return keys181end182183def Registry.enum_key_direct(root_key, base_key, perm = KEY_READ)184request = Packet.create_request(COMMAND_ID_STDAPI_REGISTRY_ENUM_KEY_DIRECT)185keys = []186187request.add_tlv(TLV_TYPE_ROOT_KEY, root_key)188request.add_tlv(TLV_TYPE_BASE_KEY, base_key)189request.add_tlv(TLV_TYPE_PERMISSION, perm)190191response = client.send_request(request)192193# Enumerate through all of the registry keys194response.each(TLV_TYPE_KEY_NAME) do |key_name|195keys << key_name.value196end197198keys199end200201##202#203# Registry value interaction204#205##206207#208# Sets the registry value relative to the supplied hkey.209#210def Registry.set_value(hkey, name, type, data)211request = Packet.create_request(COMMAND_ID_STDAPI_REGISTRY_SET_VALUE)212213request.add_tlv(TLV_TYPE_HKEY, hkey)214request.add_tlv(TLV_TYPE_VALUE_NAME, name)215request.add_tlv(TLV_TYPE_VALUE_TYPE, type)216request.add_tlv(TLV_TYPE_VALUE_DATA, self.ruby2reg_value(type, data))217218client.send_request(request)219220return true221end222223def Registry.set_value_direct(root_key, base_key, name, type, data, perm = KEY_WRITE)224request = Packet.create_request(COMMAND_ID_STDAPI_REGISTRY_SET_VALUE_DIRECT)225226request.add_tlv(TLV_TYPE_ROOT_KEY, root_key)227request.add_tlv(TLV_TYPE_BASE_KEY, base_key)228request.add_tlv(TLV_TYPE_PERMISSION, perm)229request.add_tlv(TLV_TYPE_VALUE_NAME, name)230request.add_tlv(TLV_TYPE_VALUE_TYPE, type)231request.add_tlv(TLV_TYPE_VALUE_DATA, self.ruby2reg_value(type, data))232233client.send_request(request)234235true236end237238#239# Queries the registry value supplied in name and returns an240# initialized RegistryValue instance if a match is found.241#242def Registry.query_value_direct(root_key, base_key, name, perm = KEY_READ)243request = Packet.create_request(COMMAND_ID_STDAPI_REGISTRY_QUERY_VALUE_DIRECT)244245request.add_tlv(TLV_TYPE_ROOT_KEY, root_key)246request.add_tlv(TLV_TYPE_BASE_KEY, base_key)247request.add_tlv(TLV_TYPE_PERMISSION, perm)248request.add_tlv(TLV_TYPE_VALUE_NAME, name)249250response = client.send_request(request)251252type = response.get_tlv(TLV_TYPE_VALUE_TYPE).value253data = self.reg2ruby_value(type, response.get_tlv(TLV_TYPE_VALUE_DATA).value)254255Rex::Post::Meterpreter::Extensions::Stdapi::Sys::RegistrySubsystem::RegistryValue.new(256client, 0, name, type, data)257end258259def Registry.query_value(hkey, name)260request = Packet.create_request(COMMAND_ID_STDAPI_REGISTRY_QUERY_VALUE)261262request.add_tlv(TLV_TYPE_HKEY, hkey)263request.add_tlv(TLV_TYPE_VALUE_NAME, name)264265response = client.send_request(request)266267type = response.get_tlv(TLV_TYPE_VALUE_TYPE).value268data = self.reg2ruby_value(type, response.get_tlv(TLV_TYPE_VALUE_DATA).value)269270271return Rex::Post::Meterpreter::Extensions::Stdapi::Sys::RegistrySubsystem::RegistryValue.new(272client, hkey, name, type, data)273end274275#276# Deletes the registry value supplied in name from the supplied277# registry key.278#279def Registry.delete_value(hkey, name)280request = Packet.create_request(COMMAND_ID_STDAPI_REGISTRY_DELETE_VALUE)281282request.add_tlv(TLV_TYPE_HKEY, hkey)283request.add_tlv(TLV_TYPE_VALUE_NAME, name)284285if (client.send_request(request) != nil)286return true287end288289return false290end291292#293# Queries the registry class name and returns a string294#295def Registry.query_class(hkey)296request = Packet.create_request(COMMAND_ID_STDAPI_REGISTRY_QUERY_CLASS)297298request.add_tlv(TLV_TYPE_HKEY, hkey)299300response = client.send_request(request)301cls = response.get_tlv(TLV_TYPE_VALUE_DATA)302return nil if not cls303data = cls.value.gsub(/\x00.*/n, '')304return data305end306307#308# Enumerates all of the values at the supplied hkey including their309# names. An array of RegistryValue's is returned.310#311def Registry.enum_value(hkey)312request = Packet.create_request(COMMAND_ID_STDAPI_REGISTRY_ENUM_VALUE)313values = []314315request.add_tlv(TLV_TYPE_HKEY, hkey)316317response = client.send_request(request)318319response.each(TLV_TYPE_VALUE_NAME) { |value_name|320values << Rex::Post::Meterpreter::Extensions::Stdapi::Sys::RegistrySubsystem::RegistryValue.new(321client, hkey, value_name.value)322}323324return values325end326327def Registry.enum_value_direct(root_key, base_key, perm = KEY_READ)328request = Packet.create_request(COMMAND_ID_STDAPI_REGISTRY_ENUM_VALUE_DIRECT)329values = []330331request.add_tlv(TLV_TYPE_ROOT_KEY, root_key)332request.add_tlv(TLV_TYPE_BASE_KEY, base_key)333request.add_tlv(TLV_TYPE_PERMISSION, perm)334335response = client.send_request(request)336337response.each(TLV_TYPE_VALUE_NAME) do |value_name|338values << Rex::Post::Meterpreter::Extensions::Stdapi::Sys::RegistrySubsystem::RegistryValue.new(339client, 0, value_name.value)340end341342values343end344345#346# Return the key value associated with the supplied string. This is useful347# for converting HKLM as a string into its actual integer representation.348#349def self.key2str(key)350if (key == 'HKLM' or key == 'HKEY_LOCAL_MACHINE')351return HKEY_LOCAL_MACHINE352elsif (key == 'HKCU' or key == 'HKEY_CURRENT_USER')353return HKEY_CURRENT_USER354elsif (key == 'HKU' or key == 'HKEY_USERS')355return HKEY_USERS356elsif (key == 'HKCR' or key == 'HKEY_CLASSES_ROOT')357return HKEY_CLASSES_ROOT358elsif (key == 'HKEY_CURRENT_CONFIG')359return HKEY_CURRENT_CONFIG360elsif (key == 'HKEY_PERFORMANCE_DATA')361return HKEY_PERFORMANCE_DATA362elsif (key == 'HKEY_DYN_DATA')363return HKEY_DYN_DATA364else365raise ArgumentError, "Unknown key: #{key}"366end367end368369#370# Returns the integer value associated with the supplied registry value371# type (like REG_SZ).372#373# @see https://msdn.microsoft.com/en-us/library/windows/desktop/ms724884(v=vs.85).aspx374# @param type [String] A Windows registry type constant name, e.g. 'REG_SZ'375# @return [Integer] one of the `REG_*` constants376def self.type2str(type)377case type378when 'REG_BINARY' then REG_BINARY379when 'REG_DWORD' then REG_DWORD380when 'REG_EXPAND_SZ' then REG_EXPAND_SZ381when 'REG_MULTI_SZ' then REG_MULTI_SZ382when 'REG_NONE' then REG_NONE383when 'REG_QWORD' then REG_QWORD384when 'REG_SZ' then REG_SZ385else386nil387end388end389390#391# Split the supplied full registry key into its root key and base key. For392# instance, passing HKLM\Software\Dog will return [ HKEY_LOCAL_MACHINE,393# 'Software\Dog' ]394#395def self.splitkey(str)396if (str =~ /^(.+?)[\\]{1,}(.*)$/)397[ key2str($1), $2 ]398else399[ key2str(str), nil ]400end401end402403class << self404private405406def ruby2reg_value(type, value)407case type408when REG_DWORD409value = [value.to_i].pack('L<')410when REG_EXPAND_SZ411value += "\x00".b412when REG_MULTI_SZ413value = value.join("\x00".b) + "\x00\x00".b414when REG_QWORD415value = [value.to_i].pack('Q<')416when REG_SZ417value += "\x00".b418end419420value421end422423def reg2ruby_value(type, value)424case type425when REG_DWORD426value = value.unpack1('L>')427when REG_EXPAND_SZ428value = value[0..-2]429when REG_MULTI_SZ430value = value[0..-3].split("\x00".b)431when REG_QWORD432value = value.unpack1('Q<')433when REG_SZ434value = value[0..-2]435end436437value438end439end440441end442443end; end; end; end; end; end444445446447