2005-04-10 10:31:38 +00:00
|
|
|
#!/usr/bin/ruby
|
|
|
|
|
2005-07-09 21:18:49 +00:00
|
|
|
require 'rex/post/process'
|
|
|
|
require 'rex/post/meterpreter/packet'
|
|
|
|
require 'rex/post/meterpreter/client'
|
|
|
|
require 'rex/post/meterpreter/extensions/stdapi/constants'
|
|
|
|
require 'rex/post/meterpreter/extensions/stdapi/stdapi'
|
|
|
|
require 'rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/registry_key'
|
|
|
|
require 'rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/registry_value'
|
2005-04-10 10:31:38 +00:00
|
|
|
|
|
|
|
module Rex
|
|
|
|
module Post
|
|
|
|
module Meterpreter
|
|
|
|
module Extensions
|
|
|
|
module Stdapi
|
2005-04-15 06:23:59 +00:00
|
|
|
module Sys
|
2005-04-10 10:31:38 +00:00
|
|
|
|
2005-04-12 05:53:29 +00:00
|
|
|
###
|
|
|
|
#
|
|
|
|
# This class provides access to the Windows registry on the remote
|
|
|
|
# machine.
|
|
|
|
#
|
|
|
|
###
|
2005-04-10 10:31:38 +00:00
|
|
|
class Registry
|
|
|
|
|
|
|
|
class <<self
|
|
|
|
attr_accessor :client
|
|
|
|
end
|
|
|
|
|
2005-04-10 22:30:04 +00:00
|
|
|
##
|
|
|
|
#
|
|
|
|
# Registry key interaction
|
|
|
|
#
|
|
|
|
##
|
|
|
|
|
2005-11-15 05:22:13 +00:00
|
|
|
#
|
2005-04-12 05:53:29 +00:00
|
|
|
# Opens the supplied registry key relative to the root key with
|
|
|
|
# the supplied permissions. Right now this is merely a wrapper around
|
|
|
|
# create_key.
|
2005-11-15 05:22:13 +00:00
|
|
|
#
|
2005-04-10 10:31:38 +00:00
|
|
|
def Registry.open_key(root_key, base_key, perm = KEY_READ)
|
2005-04-10 22:30:04 +00:00
|
|
|
return self.create_key(root_key, base_key, perm)
|
|
|
|
end
|
2005-04-10 10:31:38 +00:00
|
|
|
|
2005-11-15 05:22:13 +00:00
|
|
|
#
|
2005-04-12 05:53:29 +00:00
|
|
|
# Creates the supplied registry key or opens it if it already exists.
|
2005-11-15 05:22:13 +00:00
|
|
|
#
|
2005-04-10 22:30:04 +00:00
|
|
|
def Registry.create_key(root_key, base_key, perm = KEY_READ)
|
|
|
|
request = Packet.create_request('stdapi_registry_create_key')
|
|
|
|
|
2005-04-10 10:31:38 +00:00
|
|
|
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)
|
|
|
|
|
2005-04-11 01:59:45 +00:00
|
|
|
response = client.send_request(request)
|
2005-04-10 10:31:38 +00:00
|
|
|
|
2005-04-15 06:23:59 +00:00
|
|
|
return Rex::Post::Meterpreter::Extensions::Stdapi::Sys::RegistrySubsystem::RegistryKey.new(
|
|
|
|
client, root_key, base_key, perm, response.get_tlv(TLV_TYPE_HKEY).value)
|
2005-04-10 22:30:04 +00:00
|
|
|
end
|
|
|
|
|
2005-11-15 05:22:13 +00:00
|
|
|
#
|
2005-04-12 05:53:29 +00:00
|
|
|
# Deletes the supplied registry key.
|
2005-11-15 05:22:13 +00:00
|
|
|
#
|
2005-04-11 01:28:33 +00:00
|
|
|
def Registry.delete_key(root_key, base_key, recursive = true)
|
|
|
|
request = Packet.create_request('stdapi_registry_delete_key')
|
|
|
|
flags = 0
|
|
|
|
|
|
|
|
if (recursive)
|
|
|
|
flags |= DELETE_KEY_FLAG_RECURSIVE
|
|
|
|
end
|
|
|
|
|
|
|
|
request.add_tlv(TLV_TYPE_ROOT_KEY, root_key)
|
|
|
|
request.add_tlv(TLV_TYPE_BASE_KEY, base_key)
|
|
|
|
request.add_tlv(TLV_TYPE_FLAGS, flags)
|
|
|
|
|
2005-04-11 01:59:45 +00:00
|
|
|
if (client.send_request(request) != nil)
|
2005-04-11 01:28:33 +00:00
|
|
|
return true
|
|
|
|
end
|
|
|
|
|
|
|
|
return false
|
|
|
|
end
|
2005-11-15 05:22:13 +00:00
|
|
|
|
|
|
|
#
|
2005-04-12 05:53:29 +00:00
|
|
|
# Closes the supplied registry key.
|
2005-11-15 05:22:13 +00:00
|
|
|
#
|
2005-04-10 22:30:04 +00:00
|
|
|
def Registry.close_key(hkey)
|
|
|
|
request = Packet.create_request('stdapi_registry_close_key')
|
|
|
|
|
|
|
|
request.add_tlv(TLV_TYPE_HKEY, hkey)
|
|
|
|
|
2005-04-11 01:59:45 +00:00
|
|
|
client.send_packet(request)
|
2005-04-10 22:30:04 +00:00
|
|
|
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
|
2005-11-15 05:22:13 +00:00
|
|
|
#
|
|
|
|
# Enumerates the supplied registry key returning an array of key names.
|
|
|
|
#
|
2005-04-10 22:51:16 +00:00
|
|
|
def Registry.enum_key(hkey)
|
|
|
|
keys = []
|
|
|
|
request = Packet.create_request('stdapi_registry_enum_key')
|
|
|
|
|
|
|
|
request.add_tlv(TLV_TYPE_HKEY, hkey)
|
|
|
|
|
2005-04-11 01:59:45 +00:00
|
|
|
response = client.send_request(request)
|
2005-04-10 22:51:16 +00:00
|
|
|
|
|
|
|
# Enumerate through all of the registry keys
|
|
|
|
response.each(TLV_TYPE_KEY_NAME) { |key_name|
|
|
|
|
keys << key_name.value
|
|
|
|
}
|
|
|
|
|
|
|
|
return keys
|
|
|
|
end
|
|
|
|
|
2005-04-10 22:30:04 +00:00
|
|
|
##
|
|
|
|
#
|
|
|
|
# Registry value interaction
|
|
|
|
#
|
|
|
|
##
|
|
|
|
|
2005-11-15 05:22:13 +00:00
|
|
|
#
|
2005-04-12 05:53:29 +00:00
|
|
|
# Sets the registry value relative to the supplied hkey.
|
2005-11-15 05:22:13 +00:00
|
|
|
#
|
2005-04-10 22:30:04 +00:00
|
|
|
def Registry.set_value(hkey, name, type, data)
|
|
|
|
request = Packet.create_request('stdapi_registry_set_value')
|
|
|
|
|
|
|
|
request.add_tlv(TLV_TYPE_HKEY, hkey)
|
|
|
|
request.add_tlv(TLV_TYPE_VALUE_NAME, name)
|
|
|
|
request.add_tlv(TLV_TYPE_VALUE_TYPE, type)
|
|
|
|
|
|
|
|
if (type == REG_SZ)
|
2005-07-10 06:32:13 +00:00
|
|
|
data += "\x00"
|
2005-04-11 15:45:33 +00:00
|
|
|
else (type == REG_DWORD)
|
|
|
|
data = [ data.to_i ].pack("V")
|
2005-04-10 22:30:04 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
request.add_tlv(TLV_TYPE_VALUE_DATA, data)
|
|
|
|
|
2005-04-11 01:59:45 +00:00
|
|
|
response = client.send_request(request)
|
2005-04-10 22:30:04 +00:00
|
|
|
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
|
2005-11-15 05:22:13 +00:00
|
|
|
#
|
2005-04-12 05:53:29 +00:00
|
|
|
# Queries the registry value supplied in name and returns an
|
|
|
|
# initialized RegistryValue instance if a match is found.
|
2005-11-15 05:22:13 +00:00
|
|
|
#
|
2005-04-10 22:30:04 +00:00
|
|
|
def Registry.query_value(hkey, name)
|
|
|
|
request = Packet.create_request('stdapi_registry_query_value')
|
|
|
|
|
|
|
|
request.add_tlv(TLV_TYPE_HKEY, hkey)
|
|
|
|
request.add_tlv(TLV_TYPE_VALUE_NAME, name)
|
|
|
|
|
2005-04-11 01:59:45 +00:00
|
|
|
response = client.send_request(request)
|
2005-04-10 22:30:04 +00:00
|
|
|
|
|
|
|
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..-1]
|
|
|
|
elsif (type == REG_DWORD)
|
|
|
|
data = data.unpack("N")[0]
|
|
|
|
end
|
|
|
|
|
2005-04-15 06:23:59 +00:00
|
|
|
return Rex::Post::Meterpreter::Extensions::Stdapi::Sys::RegistrySubsystem::RegistryValue.new(
|
|
|
|
client, hkey, name, type, data)
|
2005-04-10 22:30:04 +00:00
|
|
|
end
|
|
|
|
|
2005-11-15 05:22:13 +00:00
|
|
|
#
|
2005-04-12 05:53:29 +00:00
|
|
|
# Deletes the registry value supplied in name from the supplied
|
|
|
|
# registry key.
|
2005-11-15 05:22:13 +00:00
|
|
|
#
|
2005-04-10 22:30:04 +00:00
|
|
|
def Registry.delete_value(hkey, name)
|
|
|
|
request = Packet.create_request('stdapi_registry_delete_value')
|
|
|
|
|
|
|
|
request.add_tlv(TLV_TYPE_HKEY, hkey)
|
|
|
|
request.add_tlv(TLV_TYPE_VALUE_NAME, name)
|
|
|
|
|
2005-04-11 01:59:45 +00:00
|
|
|
if (client.send_request(request) != nil)
|
2005-04-10 22:30:04 +00:00
|
|
|
return true
|
|
|
|
end
|
|
|
|
|
|
|
|
return false
|
2005-04-10 10:31:38 +00:00
|
|
|
end
|
|
|
|
|
2005-11-15 05:22:13 +00:00
|
|
|
#
|
2005-04-12 05:53:29 +00:00
|
|
|
# Enumerates all of the values at the supplied hkey including their
|
|
|
|
# names. An array of RegistryValue's is returned.
|
2005-11-15 05:22:13 +00:00
|
|
|
#
|
2005-04-11 01:28:33 +00:00
|
|
|
def Registry.enum_value(hkey)
|
|
|
|
request = Packet.create_request('stdapi_registry_enum_value')
|
|
|
|
values = []
|
|
|
|
|
|
|
|
request.add_tlv(TLV_TYPE_HKEY, hkey)
|
|
|
|
|
2005-04-11 01:59:45 +00:00
|
|
|
response = client.send_request(request)
|
2005-04-11 01:28:33 +00:00
|
|
|
|
|
|
|
response.each(TLV_TYPE_VALUE_NAME) { |value_name|
|
2005-04-15 06:23:59 +00:00
|
|
|
values << Rex::Post::Meterpreter::Extensions::Stdapi::Sys::RegistrySubsystem::RegistryValue.new(
|
|
|
|
client, hkey, value_name.value)
|
2005-04-11 01:28:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return values
|
|
|
|
end
|
|
|
|
|
2005-11-18 01:12:45 +00:00
|
|
|
#
|
|
|
|
# Return the key value associated with the supplied string. This is useful
|
|
|
|
# for converting HKLM as a string into its actual integer representation.
|
|
|
|
#
|
|
|
|
def self.key2str(key)
|
|
|
|
if (key == 'HKLM' or key == 'HKEY_LOCAL_MACHINE')
|
|
|
|
return HKEY_LOCAL_MACHINE
|
|
|
|
elsif (key == 'HKCU' or key == 'HKEY_CURRENT_USER')
|
|
|
|
return HKEY_CURRENT_USER
|
|
|
|
elsif (key == 'HKU' or key == 'HKEY_USERS')
|
|
|
|
return HKEY_USERS
|
|
|
|
elsif (key == 'HKCR' or key == 'HKEY_CLASSES_ROOT')
|
|
|
|
return HKEY_CLASSES_ROOT
|
|
|
|
elsif (key == 'HKEY_CURRENT_CONFIG')
|
|
|
|
return HKEY_CURRENT_CONFIG
|
|
|
|
elsif (key == 'HKEY_PERFORMANCE_DATA')
|
|
|
|
return HKEY_PERFORMANCE_DATA
|
|
|
|
elsif (key == 'HKEY_DYN_DATA')
|
|
|
|
return HKEY_DYN_DATA
|
|
|
|
else
|
|
|
|
raise ArgumentError, "Unknown key: #{key}"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Returns the integer value associated with the supplied registry value
|
|
|
|
# type (like REG_SZ).
|
|
|
|
#
|
|
|
|
def self.type2str(type)
|
|
|
|
return REG_SZ if (type == 'REG_SZ')
|
|
|
|
return REG_DWORD if (type == 'REG_DWORD')
|
|
|
|
return REG_BINARY if (type == 'REG_BINARY')
|
|
|
|
return REG_EXPAND_SZ if (type == 'REG_EXPAND_SZ')
|
|
|
|
return REG_NONE if (type == 'REG_NONE')
|
|
|
|
return nil
|
|
|
|
end
|
|
|
|
|
|
|
|
#
|
|
|
|
# Split the supplied full registry key into its root key and base key. For
|
|
|
|
# instance, passing HKLM\Software\Dog will return [ HKEY_LOCAL_MACHINE,
|
|
|
|
# 'Software\Dog' ]
|
|
|
|
#
|
|
|
|
def self.splitkey(str)
|
|
|
|
if (str =~ /^(.+?)\\(.*)$/)
|
|
|
|
[ key2str($1), $2 ]
|
|
|
|
else
|
|
|
|
raise ArgumentError, "Invalid key: #{key}"
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2005-04-10 10:31:38 +00:00
|
|
|
end
|
|
|
|
|
2005-04-15 06:23:59 +00:00
|
|
|
end; end; end; end; end; end
|