Module: RubySMB::Dcerpc::Winreg

Defined in:
lib/ruby_smb/dcerpc/winreg.rb,
lib/ruby_smb/dcerpc/winreg/regsam.rb,
lib/ruby_smb/dcerpc/winreg/enum_key_request.rb,
lib/ruby_smb/dcerpc/winreg/open_key_request.rb,
lib/ruby_smb/dcerpc/winreg/close_key_request.rb,
lib/ruby_smb/dcerpc/winreg/enum_key_response.rb,
lib/ruby_smb/dcerpc/winreg/open_key_response.rb,
lib/ruby_smb/dcerpc/winreg/close_key_response.rb,
lib/ruby_smb/dcerpc/winreg/enum_value_request.rb,
lib/ruby_smb/dcerpc/winreg/enum_value_response.rb,
lib/ruby_smb/dcerpc/winreg/query_value_request.rb,
lib/ruby_smb/dcerpc/winreg/query_value_response.rb,
lib/ruby_smb/dcerpc/winreg/open_root_key_request.rb,
lib/ruby_smb/dcerpc/winreg/open_root_key_response.rb,
lib/ruby_smb/dcerpc/winreg/query_info_key_request.rb,
lib/ruby_smb/dcerpc/winreg/query_info_key_response.rb

Defined Under Namespace

Classes: CloseKeyRequest, CloseKeyResponse, EnumKeyRequest, EnumKeyResponse, EnumValueRequest, EnumValueResponse, OpenKeyRequest, OpenKeyResponse, OpenRootKeyRequest, OpenRootKeyResponse, PRegistryServerName, PrpcHkey, QueryInfoKeyRequest, QueryInfoKeyResponse, QueryValueRequest, QueryValueResponse, Regsam, RpcHkey

Constant Summary collapse

UUID =
'338CD001-2244-31F1-AAAA-900038001003'
VER_MAJOR =
1
VER_MINOR =
0
OPEN_HKCR =

Operation numbers

0x00
OPEN_HKCU =
0x01
OPEN_HKLM =
0x02
OPEN_HKPD =
0x03
OPEN_HKU =
0x04
REG_CLOSE_KEY =
0x05
REG_ENUM_KEY =
0x09
REG_ENUM_VALUE =
0x0a
REG_OPEN_KEY =
0x0f
REG_QUERY_INFO_KEY =
0x10
REG_QUERY_VALUE =
0x11
OPEN_HKCC =
0x1b
OPEN_HKPT =
0x20
OPEN_HKPN =
0x21
ROOT_KEY_MAP =
{
  "HKEY_CLASSES_ROOT"         => OPEN_HKCR,
  "HKCR"                      => OPEN_HKCR,
  "HKEY_CURRENT_USER"         => OPEN_HKCU,
  "HKCU"                      => OPEN_HKCU,
  "HKEY_LOCAL_MACHINE"        => OPEN_HKLM,
  "HKLM"                      => OPEN_HKLM,
  "HKEY_PERFORMANCE_DATA"     => OPEN_HKPD,
  "HKPD"                      => OPEN_HKPD,
  "HKEY_USERS"                => OPEN_HKU,
  "HKU"                       => OPEN_HKU,
  "HKEY_CURRENT_CONFIG"       => OPEN_HKCC,
  "HKCC"                      => OPEN_HKCC,
  "HKEY_PERFORMANCE_TEXT"     => OPEN_HKPT,
  "HKPT"                      => OPEN_HKPT,
  "HKEY_PERFORMANCE_NLS_TEXT" => OPEN_HKPN,
  "HKPN"                      => OPEN_HKPN
}

Instance Method Summary collapse

Instance Method Details

#close_key(handle) ⇒ WindowsError::Win32

Close the handle to the registry key.

Parameters:

Returns:

  • (WindowsError::Win32) —

    the response error status

Raises:



163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/ruby_smb/dcerpc/winreg.rb', line 163

def close_key(handle)
  close_key_request_packet = RubySMB::Dcerpc::Winreg::CloseKeyRequest.new(hkey: handle)
  response = dcerpc_request(close_key_request_packet)
  begin
    close_key_response = RubySMB::Dcerpc::Winreg::CloseKeyResponse.read(response)
  rescue IOError
    raise RubySMB::Dcerpc::Error::InvalidPacket, "Error reading the CloseKey response"
  end
  unless close_key_response.error_status == WindowsError::Win32::ERROR_SUCCESS
    raise RubySMB::Dcerpc::Error::WinregError, "Error returned when closing the key: "\
      "#{WindowsError::Win32.find_by_retval(close_key_response.error_status.value).join(',')}"
  end

  close_key_response.error_status
end

#enum_key(handle, index) ⇒ String

Enumerate the subkey at the specified index.

Parameters:

Returns:

  • (String) —

    the subkey name

Raises:



209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
# File 'lib/ruby_smb/dcerpc/winreg.rb', line 209

def enum_key(handle, index)
  enum_key_request_packet = RubySMB::Dcerpc::Winreg::EnumKeyRequest.new(hkey: handle, dw_index: index)
  enum_key_request_packet.lpft_last_write_time = 0
  enum_key_request_packet.lp_class.referent.buffer = 0
  enum_key_request_packet.lp_name.buffer.referent.max_count = 256
  response = dcerpc_request(enum_key_request_packet)
  begin
    enum_key_response = RubySMB::Dcerpc::Winreg::EnumKeyResponse.read(response)
  rescue IOError
    raise RubySMB::Dcerpc::Error::InvalidPacket, "Error reading the EnumKey response"
  end
  unless enum_key_response.error_status == WindowsError::Win32::ERROR_SUCCESS
    raise RubySMB::Dcerpc::Error::WinregError, "Error returned when enumerating the key: "\
      "#{WindowsError::Win32.find_by_retval(enum_key_response.error_status.value).join(',')}"
  end

  enum_key_response.lp_name.to_s
end

#enum_registry_key(key) ⇒ Array<String>

Enumerate the subkeys of a specified registry key. If only a root key is provided, it enumerates its subkeys.

Parameters:

  • key (String) —

    the registry key

Returns:

  • (Array<String>) —

    the subkeys



294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
# File 'lib/ruby_smb/dcerpc/winreg.rb', line 294

def enum_registry_key(key)
  bind(endpoint: RubySMB::Dcerpc::Winreg)

  root_key, sub_key = key.gsub(/\//, '\\').split('\\', 2)
  root_key_handle = open_root_key(root_key)
  subkey_handle = if sub_key.nil? || sub_key.empty?
                    root_key_handle
                  else
                    open_key(root_key_handle, sub_key)
                  end
  query_info_key_response = query_info_key(subkey_handle)
  key_count = query_info_key_response.lpc_sub_keys.to_i
  enum_result = []
  key_count.times do |i|
    enum_result << enum_key(subkey_handle, i)
  end
  close_key(subkey_handle)
  enum_result
end

#enum_registry_values(key) ⇒ Array<String>

Enumerate the values for the specified registry key.

Parameters:

  • key (String) —

    the registry key

Returns:

  • (Array<String>) —

    the values



318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
# File 'lib/ruby_smb/dcerpc/winreg.rb', line 318

def enum_registry_values(key)
  bind(endpoint: RubySMB::Dcerpc::Winreg)

  root_key, sub_key = key.gsub(/\//, '\\').split('\\', 2)
  root_key_handle = open_root_key(root_key)
  subkey_handle = if sub_key.nil? || sub_key.empty?
                    root_key_handle
                  else
                    open_key(root_key_handle, sub_key)
                  end
  query_info_key_response = query_info_key(subkey_handle)
  value_count = query_info_key_response.lpc_values.to_i
  enum_result = []
  value_count.times do |i|
    enum_result << enum_value(subkey_handle, i)
  end
  close_key(subkey_handle)
  enum_result
end

#enum_value(handle, index) ⇒ String

Enumerate the value at the specified index for the specified registry key.

Parameters:

Returns:

  • (String) —

    the data of the value entry

Raises:



235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
# File 'lib/ruby_smb/dcerpc/winreg.rb', line 235

def enum_value(handle, index)
  enum_value_request_packet = RubySMB::Dcerpc::Winreg::EnumValueRequest.new(hkey: handle, dw_index: index)
  enum_value_request_packet.lp_data.referent_identifier = 0
  enum_value_request_packet.lp_value_name.buffer.referent.max_count = 256
  response = dcerpc_request(enum_value_request_packet)
  begin
    enum_value_response = RubySMB::Dcerpc::Winreg::EnumValueResponse.read(response)
  rescue IOError
    raise RubySMB::Dcerpc::Error::InvalidPacket, "Error reading the Enumvalue response"
  end
  unless enum_value_response.error_status == WindowsError::Win32::ERROR_SUCCESS
    raise RubySMB::Dcerpc::Error::WinregError, "Error returned when enumerating values: "\
      "#{WindowsError::Win32.find_by_retval(enum_value_response.error_status.value).join(',')}"
  end

  enum_value_response.lp_value_name.to_s
end

#has_registry_key?(key) ⇒ Boolean

Checks if the specified registry key exists. It returns true if it exists, false otherwise.

Parameters:

  • key (String) —

    the registry key to check

Returns:

  • (Boolean)


258
259
260
261
262
263
264
265
266
267
268
269
270
# File 'lib/ruby_smb/dcerpc/winreg.rb', line 258

def has_registry_key?(key)
  bind(endpoint: RubySMB::Dcerpc::Winreg)

  root_key, sub_key = key.gsub(/\//, '\\').split('\\', 2)
  begin
    root_key_handle = open_root_key(root_key)
    subkey_handle = open_key(root_key_handle, sub_key)
  rescue RubySMB::Dcerpc::Error::WinregError
    return false
  end
  close_key(subkey_handle)
  return true
end

#open_key(handle, sub_key) ⇒ Ndr::NdrContextHandle

Open the registry key specified by a root key handle (previously open with #open_root_key) and a subkey. It returns a handle for the key.

Parameters:

Returns:

Raises:



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/ruby_smb/dcerpc/winreg.rb', line 98

def open_key(handle, sub_key)
  openkey_request_packet = RubySMB::Dcerpc::Winreg::OpenKeyRequest.new(hkey: handle, lp_sub_key: sub_key)
  openkey_request_packet.sam_desired.read_control = 1
  openkey_request_packet.sam_desired.key_query_value = 1
  openkey_request_packet.sam_desired.key_enumerate_sub_keys = 1
  openkey_request_packet.sam_desired.key_notify = 1
  response = dcerpc_request(openkey_request_packet)
  begin
    open_key_response = RubySMB::Dcerpc::Winreg::OpenKeyResponse.read(response)
  rescue IOError
    raise RubySMB::Dcerpc::Error::InvalidPacket, "Error reading the OpenKey response"
  end
  unless open_key_response.error_status == WindowsError::Win32::ERROR_SUCCESS
    raise RubySMB::Dcerpc::Error::WinregError, "Error returned when opening subkey #{sub_key}: "\
      "#{WindowsError::Win32.find_by_retval(open_key_response.error_status.value).join(',')}"
  end

  open_key_response.phk_result
end

#open_root_key(root_key) ⇒ Ndr::NdrContextHandle

Open the registry root key and return a handle for it. The key can be either a long format (e.g. HKEY_LOCAL_MACHINE) or a short format (e.g. HKLM)

Parameters:

  • root_key (String) —

    the root key to open

Returns:

Raises:



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/ruby_smb/dcerpc/winreg.rb', line 68

def open_root_key(root_key)
  root_key_opnum = RubySMB::Dcerpc::Winreg::ROOT_KEY_MAP[root_key]
  raise ArgumentError, "Unknown Root Key: #{root_key}" unless root_key_opnum

  root_key_request_packet = OpenRootKeyRequest.new(opnum: root_key_opnum)
  response = dcerpc_request(root_key_request_packet)

  begin
    root_key_response_packet = OpenRootKeyResponse.read(response)
  rescue IOError
    raise RubySMB::Dcerpc::Error::InvalidPacket,
      "Error reading OpenRootKeyResponse (command = #{root_key_opnum})"
  end
  unless root_key_response_packet.error_status == WindowsError::Win32::ERROR_SUCCESS
    raise RubySMB::Dcerpc::Error::WinregError,
      "Error returned when opening root key #{root_key}: "\
      "#{WindowsError::Win32.find_by_retval(root_key_response_packet.error_status.value).join(',')}"
  end

  root_key_response_packet.ph_key
end

#query_info_key(handle) ⇒ RubySMB::Dcerpc::Winreg::QueryInfoKeyResponse

Retrive relevant information on the key that corresponds to the specified key handle.

Parameters:

Returns:

Raises:



186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
# File 'lib/ruby_smb/dcerpc/winreg.rb', line 186

def query_info_key(handle)
  query_info_key_request_packet = RubySMB::Dcerpc::Winreg::QueryInfoKeyRequest.new(hkey: handle)
  response = dcerpc_request(query_info_key_request_packet)
  begin
    query_info_key_response = RubySMB::Dcerpc::Winreg::QueryInfoKeyResponse.read(response)
  rescue IOError
    raise RubySMB::Dcerpc::Error::InvalidPacket, "Error reading the query_infoKey response"
  end
  unless query_info_key_response.error_status == WindowsError::Win32::ERROR_SUCCESS
    raise RubySMB::Dcerpc::Error::WinregError, "Error returned when querying information: "\
      "#{WindowsError::Win32.find_by_retval(query_info_key_response.error_status.value).join(',')}"
  end

  query_info_key_response
end

#query_value(handle, value_name) ⇒ String

Retrieve the data associated with the named value of a specified registry open key.

Parameters:

  • handle (Ndr::NdrContextHandle) —

    the handle for the key

  • value_name (String) —

    the name of the value

Returns:

  • (String) —

    the data of the value entry

Raises:



126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/ruby_smb/dcerpc/winreg.rb', line 126

def query_value(handle, value_name)
  query_value_request_packet = RubySMB::Dcerpc::Winreg::QueryValueRequest.new(hkey: handle, lp_value_name: value_name)
  query_value_request_packet.lp_data.referent_identifier = 0
  response = dcerpc_request(query_value_request_packet)
  begin
    query_value_response = RubySMB::Dcerpc::Winreg::QueryValueResponse.read(response)
  rescue IOError
    raise RubySMB::Dcerpc::Error::InvalidPacket, "Error reading the QueryValue response"
  end
  unless query_value_response.error_status == WindowsError::Win32::ERROR_SUCCESS
    raise RubySMB::Dcerpc::Error::WinregError, "Error returned when reading value #{value_name}: "\
      "#{WindowsError::Win32.find_by_retval(query_value_response.error_status.value).join(',')}"
  end

  query_value_request_packet = RubySMB::Dcerpc::Winreg::QueryValueRequest.new(hkey: handle, lp_value_name: value_name)
  query_value_request_packet.lpcb_data = query_value_response.lpcb_data
  query_value_request_packet.lp_data.max_count = query_value_response.lpcb_data.referent
  response = dcerpc_request(query_value_request_packet)
  begin
    query_value_response = RubySMB::Dcerpc::Winreg::QueryValueResponse.read(response)
  rescue IOError
    raise RubySMB::Dcerpc::Error::InvalidPacket, "Error reading the QueryValue response"
  end
  unless query_value_response.error_status == WindowsError::Win32::ERROR_SUCCESS
    raise RubySMB::Dcerpc::Error::WinregError, "Error returned when reading value #{value_name}: "\
      "#{WindowsError::Win32.find_by_retval(query_value_response.error_status.value).join(',')}"
  end

  query_value_response.data
end

#read_registry_key_value(key, value_name) ⇒ String

Retrieve the data associated with the named value of a specified registry key.

Parameters:

  • key (String) —

    the registry key

  • value_name (String) —

    the name of the value to read

Returns:

  • (String) —

    the data of the value entry



278
279
280
281
282
283
284
285
286
287
# File 'lib/ruby_smb/dcerpc/winreg.rb', line 278

def read_registry_key_value(key, value_name)
  bind(endpoint: RubySMB::Dcerpc::Winreg)

  root_key, sub_key = key.gsub(/\//, '\\').split('\\', 2)
  root_key_handle = open_root_key(root_key)
  subkey_handle = open_key(root_key_handle, sub_key)
  value = query_value(subkey_handle, value_name)
  close_key(subkey_handle)
  value
end