Land #4411, @bcook-r7's support for direct, atomic registry key access in meterpreter

bug/bundler_fix
jvazquez-r7 2015-03-04 10:01:33 -06:00
commit 64fd818364
No known key found for this signature in database
GPG Key ID: 38D99152B9352D83
3 changed files with 159 additions and 30 deletions

View File

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

View File

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

View File

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