Land #4411, @bcook-r7's support for direct, atomic registry key access in meterpreter
commit
64fd818364
|
@ -1334,10 +1334,12 @@ def stdapi_net_socket_tcp_shutdown(request, response):
|
|||
channel.shutdown(how)
|
||||
return ERROR_SUCCESS, response
|
||||
|
||||
def _wreg_close_key(hkey):
|
||||
ctypes.windll.advapi32.RegCloseKey(hkey)
|
||||
|
||||
@meterpreter.register_function_windll
|
||||
def stdapi_registry_close_key(request, response):
|
||||
hkey = packet_get_tlv(request, TLV_TYPE_HKEY)['value']
|
||||
result = ctypes.windll.advapi32.RegCloseKey(hkey)
|
||||
_wreg_close_key(packet_get_tlv(request, TLV_TYPE_HKEY)['value'])
|
||||
return ERROR_SUCCESS, response
|
||||
|
||||
@meterpreter.register_function_windll
|
||||
|
@ -1372,11 +1374,9 @@ def stdapi_registry_delete_value(request, response):
|
|||
result = ctypes.windll.advapi32.RegDeleteValueA(root_key, ctypes.byref(value_name))
|
||||
return result, response
|
||||
|
||||
@meterpreter.register_function_windll
|
||||
def stdapi_registry_enum_key(request, response):
|
||||
def _wreg_enum_key(request, response, hkey):
|
||||
ERROR_MORE_DATA = 0xea
|
||||
ERROR_NO_MORE_ITEMS = 0x0103
|
||||
hkey = packet_get_tlv(request, TLV_TYPE_HKEY)['value']
|
||||
name = (ctypes.c_char * 4096)()
|
||||
index = 0
|
||||
tries = 0
|
||||
|
@ -1399,10 +1399,22 @@ def stdapi_registry_enum_key(request, response):
|
|||
return result, response
|
||||
|
||||
@meterpreter.register_function_windll
|
||||
def stdapi_registry_enum_value(request, response):
|
||||
def stdapi_registry_enum_key(request, response):
|
||||
hkey = packet_get_tlv(request, TLV_TYPE_HKEY)['value']
|
||||
return _wreg_enum_key(request, response, hkey)
|
||||
|
||||
@meterpreter.register_function_windll
|
||||
def stdapi_registry_enum_key_direct(request, response):
|
||||
err, hkey = _wreg_open_key(request)
|
||||
if err != ERROR_SUCCESS:
|
||||
return err, response
|
||||
ret = _wreg_enum_key(request, response, hkey)
|
||||
_wreg_close_key(hkey)
|
||||
return ret
|
||||
|
||||
def _wreg_enum_value(request, response, hkey):
|
||||
ERROR_MORE_DATA = 0xea
|
||||
ERROR_NO_MORE_ITEMS = 0x0103
|
||||
hkey = packet_get_tlv(request, TLV_TYPE_HKEY)['value']
|
||||
name = (ctypes.c_char * 4096)()
|
||||
name_sz = ctypes.c_uint32()
|
||||
index = 0
|
||||
|
@ -1426,6 +1438,20 @@ def stdapi_registry_enum_value(request, response):
|
|||
index += 1
|
||||
return result, response
|
||||
|
||||
@meterpreter.register_function_windll
|
||||
def stdapi_registry_enum_value(request, response):
|
||||
hkey = packet_get_tlv(request, TLV_TYPE_HKEY)['value']
|
||||
return _wreg_enum_value(request, response, hkey)
|
||||
|
||||
@meterpreter.register_function_windll
|
||||
def stdapi_registry_enum_value_direct(request, response):
|
||||
err, hkey = _wreg_open_key(request)
|
||||
if err != ERROR_SUCCESS:
|
||||
return err, response
|
||||
ret = _wreg_enum_value(request, response, hkey)
|
||||
_wreg_close_key(hkey)
|
||||
return ret
|
||||
|
||||
@meterpreter.register_function_windll
|
||||
def stdapi_registry_load_key(request, response):
|
||||
root_key = packet_get_tlv(request, TLV_TYPE_ROOT_KEY)
|
||||
|
@ -1434,16 +1460,22 @@ def stdapi_registry_load_key(request, response):
|
|||
result = ctypes.windll.advapi32.RegLoadKeyA(root_key, sub_key, file_name)
|
||||
return result, response
|
||||
|
||||
@meterpreter.register_function_windll
|
||||
def stdapi_registry_open_key(request, response):
|
||||
def _wreg_open_key(request):
|
||||
root_key = packet_get_tlv(request, TLV_TYPE_ROOT_KEY)['value']
|
||||
base_key = packet_get_tlv(request, TLV_TYPE_BASE_KEY)['value']
|
||||
base_key = ctypes.create_string_buffer(bytes(base_key, 'UTF-8'))
|
||||
permission = packet_get_tlv(request, TLV_TYPE_PERMISSION).get('value', winreg.KEY_ALL_ACCESS)
|
||||
handle_id = ctypes.c_void_p()
|
||||
if ctypes.windll.advapi32.RegOpenKeyExA(root_key, ctypes.byref(base_key), 0, permission, ctypes.byref(handle_id)) != ERROR_SUCCESS:
|
||||
return error_result_windows(), response
|
||||
response += tlv_pack(TLV_TYPE_HKEY, handle_id.value)
|
||||
return error_result_windows(), 0
|
||||
return ERROR_SUCCESS, handle_id.value
|
||||
|
||||
@meterpreter.register_function_windll
|
||||
def stdapi_registry_open_key(request, response):
|
||||
err, hkey = _wreg_open_key(request)
|
||||
if err != ERROR_SUCCESS:
|
||||
return err, response
|
||||
response += tlv_pack(TLV_TYPE_HKEY, hkey)
|
||||
return ERROR_SUCCESS, response
|
||||
|
||||
@meterpreter.register_function_windll
|
||||
|
@ -1467,9 +1499,7 @@ def stdapi_registry_query_class(request, response):
|
|||
response += tlv_pack(TLV_TYPE_VALUE_DATA, ctypes.string_at(value_data))
|
||||
return ERROR_SUCCESS, response
|
||||
|
||||
@meterpreter.register_function_windll
|
||||
def stdapi_registry_query_value(request, response):
|
||||
hkey = packet_get_tlv(request, TLV_TYPE_HKEY)['value']
|
||||
def _query_value(request, response, hkey):
|
||||
value_name = packet_get_tlv(request, TLV_TYPE_VALUE_NAME)['value']
|
||||
value_name = ctypes.create_string_buffer(bytes(value_name, 'UTF-8'))
|
||||
value_type = ctypes.c_uint32()
|
||||
|
@ -1496,8 +1526,20 @@ def stdapi_registry_query_value(request, response):
|
|||
return error_result_windows(), response
|
||||
|
||||
@meterpreter.register_function_windll
|
||||
def stdapi_registry_set_value(request, response):
|
||||
def stdapi_registry_query_value(request, response):
|
||||
hkey = packet_get_tlv(request, TLV_TYPE_HKEY)['value']
|
||||
return _query_value(request, response, hkey)
|
||||
|
||||
@meterpreter.register_function_windll
|
||||
def stdapi_registry_query_value_direct(request, response):
|
||||
err, hkey = _wreg_open_key(request)
|
||||
if err != ERROR_SUCCESS:
|
||||
return err, response
|
||||
ret = _query_value(request, response, hkey)
|
||||
_wreg_close_key(hkey)
|
||||
return ret
|
||||
|
||||
def _set_value(request, response, hkey):
|
||||
value_name = packet_get_tlv(request, TLV_TYPE_VALUE_NAME)['value']
|
||||
value_name = ctypes.create_string_buffer(bytes(value_name, 'UTF-8'))
|
||||
value_type = packet_get_tlv(request, TLV_TYPE_VALUE_TYPE)['value']
|
||||
|
@ -1505,6 +1547,20 @@ def stdapi_registry_set_value(request, response):
|
|||
result = ctypes.windll.advapi32.RegSetValueExA(hkey, ctypes.byref(value_name), 0, value_type, value_data, len(value_data))
|
||||
return result, response
|
||||
|
||||
@meterpreter.register_function_windll
|
||||
def stdapi_registry_set_value(request, response):
|
||||
hkey = packet_get_tlv(request, TLV_TYPE_HKEY)['value']
|
||||
return _set_value(request, response, hkey)
|
||||
|
||||
@meterpreter.register_function_windll
|
||||
def stdapi_registry_set_value_direct(request, response):
|
||||
err, hkey = _wreg_open_key(request)
|
||||
if err != ERROR_SUCCESS:
|
||||
return err, response
|
||||
ret = _set_value(request, response, hkey)
|
||||
_wreg_close_key(hkey)
|
||||
return ret
|
||||
|
||||
@meterpreter.register_function_windll
|
||||
def stdapi_registry_unload_key(request, response):
|
||||
root_key = packet_get_tlv(request, TLV_TYPE_ROOT_KEY)['value']
|
||||
|
|
|
@ -439,12 +439,10 @@ protected
|
|||
subkeys = []
|
||||
root_key, base_key = session.sys.registry.splitkey(key)
|
||||
perms = meterpreter_registry_perms(KEY_READ, view)
|
||||
open_key = session.sys.registry.open_key(root_key, base_key, perms)
|
||||
keys = open_key.enum_key
|
||||
keys = session.sys.registry.enum_key_direct(root_key, base_key, perms)
|
||||
keys.each { |subkey|
|
||||
subkeys << subkey
|
||||
}
|
||||
open_key.close
|
||||
return subkeys
|
||||
rescue Rex::Post::Meterpreter::RequestError => e
|
||||
return nil
|
||||
|
@ -460,12 +458,10 @@ protected
|
|||
vals = {}
|
||||
root_key, base_key = session.sys.registry.splitkey(key)
|
||||
perms = meterpreter_registry_perms(KEY_READ, view)
|
||||
open_key = session.sys.registry.open_key(root_key, base_key, perms)
|
||||
vals = open_key.enum_value
|
||||
vals = session.sys.registry.enum_value_direct(root_key, base_key, perms)
|
||||
vals.each { |val|
|
||||
values << val.name
|
||||
}
|
||||
open_key.close
|
||||
return values
|
||||
rescue Rex::Post::Meterpreter::RequestError => e
|
||||
return nil
|
||||
|
@ -480,10 +476,8 @@ protected
|
|||
value = nil
|
||||
root_key, base_key = session.sys.registry.splitkey(key)
|
||||
perms = meterpreter_registry_perms(KEY_READ, view)
|
||||
open_key = session.sys.registry.open_key(root_key, base_key, perms)
|
||||
v = open_key.query_value(valname)
|
||||
v = session.sys.registry.query_value_direct(root_key, base_key, valname, perms)
|
||||
value = v.data
|
||||
open_key.close
|
||||
rescue Rex::Post::Meterpreter::RequestError => e
|
||||
return nil
|
||||
end
|
||||
|
@ -516,9 +510,8 @@ protected
|
|||
begin
|
||||
root_key, base_key = session.sys.registry.splitkey(key)
|
||||
perms = meterpreter_registry_perms(KEY_WRITE, view)
|
||||
open_key = session.sys.registry.open_key(root_key, base_key, perms)
|
||||
open_key.set_value(valname, session.sys.registry.type2str(type), data)
|
||||
open_key.close
|
||||
session.sys.registry.set_value_direct(root_key, base_key,
|
||||
valname, session.sys.registry.type2str(type), data, perms)
|
||||
return true
|
||||
rescue Rex::Post::Meterpreter::RequestError => e
|
||||
return nil
|
||||
|
|
|
@ -89,7 +89,6 @@ class Registry
|
|||
request.add_tlv(TLV_TYPE_TARGET_HOST, target_host)
|
||||
request.add_tlv(TLV_TYPE_ROOT_KEY, root_key)
|
||||
|
||||
|
||||
response = client.send_request(request)
|
||||
|
||||
return Rex::Post::Meterpreter::Extensions::Stdapi::Sys::RegistrySubsystem::RemoteRegistryKey.new(
|
||||
|
@ -166,6 +165,24 @@ class Registry
|
|||
return keys
|
||||
end
|
||||
|
||||
def Registry.enum_key_direct(root_key, base_key, perm = KEY_READ)
|
||||
request = Packet.create_request('stdapi_registry_enum_key_direct')
|
||||
keys = []
|
||||
|
||||
request.add_tlv(TLV_TYPE_ROOT_KEY, root_key)
|
||||
request.add_tlv(TLV_TYPE_BASE_KEY, base_key)
|
||||
request.add_tlv(TLV_TYPE_PERMISSION, perm)
|
||||
|
||||
response = client.send_request(request)
|
||||
|
||||
# Enumerate through all of the registry keys
|
||||
response.each(TLV_TYPE_KEY_NAME) do |key_name|
|
||||
keys << key_name.value
|
||||
end
|
||||
|
||||
keys
|
||||
end
|
||||
|
||||
##
|
||||
#
|
||||
# Registry value interaction
|
||||
|
@ -195,10 +212,55 @@ class Registry
|
|||
return true
|
||||
end
|
||||
|
||||
def Registry.set_value_direct(root_key, base_key, name, type, data, perm = KEY_WRITE)
|
||||
request = Packet.create_request('stdapi_registry_set_value_direct')
|
||||
|
||||
request.add_tlv(TLV_TYPE_ROOT_KEY, root_key)
|
||||
request.add_tlv(TLV_TYPE_BASE_KEY, base_key)
|
||||
request.add_tlv(TLV_TYPE_PERMISSION, perm)
|
||||
request.add_tlv(TLV_TYPE_VALUE_NAME, name)
|
||||
request.add_tlv(TLV_TYPE_VALUE_TYPE, type)
|
||||
|
||||
if type == REG_SZ
|
||||
data += "\x00"
|
||||
elsif type == REG_DWORD
|
||||
data = [data.to_i].pack('V')
|
||||
end
|
||||
|
||||
request.add_tlv(TLV_TYPE_VALUE_DATA, data)
|
||||
|
||||
response = client.send_request(request)
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
#
|
||||
# Queries the registry value supplied in name and returns an
|
||||
# initialized RegistryValue instance if a match is found.
|
||||
#
|
||||
def Registry.query_value_direct(root_key, base_key, name, perm = KEY_READ)
|
||||
request = Packet.create_request('stdapi_registry_query_value_direct')
|
||||
|
||||
request.add_tlv(TLV_TYPE_ROOT_KEY, root_key)
|
||||
request.add_tlv(TLV_TYPE_BASE_KEY, base_key)
|
||||
request.add_tlv(TLV_TYPE_PERMISSION, perm)
|
||||
request.add_tlv(TLV_TYPE_VALUE_NAME, name)
|
||||
|
||||
response = client.send_request(request)
|
||||
|
||||
type = response.get_tlv(TLV_TYPE_VALUE_TYPE).value
|
||||
data = response.get_tlv(TLV_TYPE_VALUE_DATA).value
|
||||
|
||||
if type == REG_SZ
|
||||
data = data[0..-2]
|
||||
elsif type == REG_DWORD
|
||||
data = data.unpack('N')[0]
|
||||
end
|
||||
|
||||
Rex::Post::Meterpreter::Extensions::Stdapi::Sys::RegistrySubsystem::RegistryValue.new(
|
||||
client, 0, name, type, data)
|
||||
end
|
||||
|
||||
def Registry.query_value(hkey, name)
|
||||
request = Packet.create_request('stdapi_registry_query_value')
|
||||
|
||||
|
@ -207,8 +269,8 @@ class Registry
|
|||
|
||||
response = client.send_request(request)
|
||||
|
||||
data = response.get_tlv(TLV_TYPE_VALUE_DATA).value;
|
||||
type = response.get_tlv(TLV_TYPE_VALUE_TYPE).value;
|
||||
data = response.get_tlv(TLV_TYPE_VALUE_DATA).value
|
||||
type = response.get_tlv(TLV_TYPE_VALUE_TYPE).value
|
||||
|
||||
if (type == REG_SZ)
|
||||
data = data[0..-2]
|
||||
|
@ -272,6 +334,24 @@ class Registry
|
|||
return values
|
||||
end
|
||||
|
||||
def Registry.enum_value_direct(root_key, base_key, perm = KEY_READ)
|
||||
request = Packet.create_request('stdapi_registry_enum_value_direct')
|
||||
values = []
|
||||
|
||||
request.add_tlv(TLV_TYPE_ROOT_KEY, root_key)
|
||||
request.add_tlv(TLV_TYPE_BASE_KEY, base_key)
|
||||
request.add_tlv(TLV_TYPE_PERMISSION, perm)
|
||||
|
||||
response = client.send_request(request)
|
||||
|
||||
response.each(TLV_TYPE_VALUE_NAME) do |value_name|
|
||||
values << Rex::Post::Meterpreter::Extensions::Stdapi::Sys::RegistrySubsystem::RegistryValue.new(
|
||||
client, 0, value_name.value)
|
||||
end
|
||||
|
||||
values
|
||||
end
|
||||
|
||||
#
|
||||
# Return the key value associated with the supplied string. This is useful
|
||||
# for converting HKLM as a string into its actual integer representation.
|
||||
|
|
Loading…
Reference in New Issue