ruby_smb 2.0.2 → 2.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/examples/anonymous_auth.rb +3 -3
  5. data/examples/append_file.rb +10 -8
  6. data/examples/authenticate.rb +9 -5
  7. data/examples/delete_file.rb +8 -6
  8. data/examples/enum_registry_key.rb +5 -4
  9. data/examples/enum_registry_values.rb +5 -4
  10. data/examples/list_directory.rb +8 -6
  11. data/examples/negotiate_with_netbios_service.rb +9 -5
  12. data/examples/net_share_enum_all.rb +6 -4
  13. data/examples/pipes.rb +11 -12
  14. data/examples/query_service_status.rb +64 -0
  15. data/examples/read_file.rb +8 -6
  16. data/examples/read_registry_key_value.rb +6 -5
  17. data/examples/rename_file.rb +9 -7
  18. data/examples/tree_connect.rb +7 -5
  19. data/examples/write_file.rb +9 -7
  20. data/lib/ruby_smb/client.rb +72 -43
  21. data/lib/ruby_smb/client/negotiation.rb +1 -0
  22. data/lib/ruby_smb/dcerpc.rb +2 -0
  23. data/lib/ruby_smb/dcerpc/error.rb +3 -0
  24. data/lib/ruby_smb/dcerpc/ndr.rb +209 -44
  25. data/lib/ruby_smb/dcerpc/request.rb +13 -0
  26. data/lib/ruby_smb/dcerpc/rpc_security_attributes.rb +34 -0
  27. data/lib/ruby_smb/dcerpc/rrp_unicode_string.rb +9 -6
  28. data/lib/ruby_smb/dcerpc/svcctl.rb +479 -0
  29. data/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_request.rb +48 -0
  30. data/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_response.rb +26 -0
  31. data/lib/ruby_smb/dcerpc/svcctl/close_service_handle_request.rb +25 -0
  32. data/lib/ruby_smb/dcerpc/svcctl/close_service_handle_response.rb +26 -0
  33. data/lib/ruby_smb/dcerpc/svcctl/control_service_request.rb +26 -0
  34. data/lib/ruby_smb/dcerpc/svcctl/control_service_response.rb +26 -0
  35. data/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_request.rb +35 -0
  36. data/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_response.rb +23 -0
  37. data/lib/ruby_smb/dcerpc/svcctl/open_service_w_request.rb +31 -0
  38. data/lib/ruby_smb/dcerpc/svcctl/open_service_w_response.rb +23 -0
  39. data/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_request.rb +25 -0
  40. data/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_response.rb +44 -0
  41. data/lib/ruby_smb/dcerpc/svcctl/query_service_status_request.rb +23 -0
  42. data/lib/ruby_smb/dcerpc/svcctl/query_service_status_response.rb +27 -0
  43. data/lib/ruby_smb/dcerpc/svcctl/service_status.rb +25 -0
  44. data/lib/ruby_smb/dcerpc/svcctl/start_service_w_request.rb +27 -0
  45. data/lib/ruby_smb/dcerpc/svcctl/start_service_w_response.rb +25 -0
  46. data/lib/ruby_smb/dcerpc/winreg.rb +98 -17
  47. data/lib/ruby_smb/dcerpc/winreg/create_key_request.rb +73 -0
  48. data/lib/ruby_smb/dcerpc/winreg/create_key_response.rb +36 -0
  49. data/lib/ruby_smb/dcerpc/winreg/enum_key_request.rb +1 -1
  50. data/lib/ruby_smb/dcerpc/winreg/enum_value_request.rb +1 -1
  51. data/lib/ruby_smb/dcerpc/winreg/enum_value_response.rb +1 -1
  52. data/lib/ruby_smb/dcerpc/winreg/open_root_key_request.rb +4 -4
  53. data/lib/ruby_smb/dcerpc/winreg/query_info_key_request.rb +1 -1
  54. data/lib/ruby_smb/dcerpc/winreg/query_value_request.rb +7 -6
  55. data/lib/ruby_smb/dcerpc/winreg/query_value_response.rb +10 -10
  56. data/lib/ruby_smb/dcerpc/winreg/save_key_request.rb +37 -0
  57. data/lib/ruby_smb/dcerpc/winreg/save_key_response.rb +23 -0
  58. data/lib/ruby_smb/dispatcher/base.rb +1 -1
  59. data/lib/ruby_smb/dispatcher/socket.rb +1 -1
  60. data/lib/ruby_smb/field/stringz16.rb +17 -1
  61. data/lib/ruby_smb/nbss/session_header.rb +4 -4
  62. data/lib/ruby_smb/smb1/file.rb +2 -10
  63. data/lib/ruby_smb/smb1/pipe.rb +2 -0
  64. data/lib/ruby_smb/smb2/file.rb +25 -17
  65. data/lib/ruby_smb/smb2/pipe.rb +3 -0
  66. data/lib/ruby_smb/smb2/tree.rb +9 -3
  67. data/lib/ruby_smb/version.rb +1 -1
  68. data/spec/lib/ruby_smb/client_spec.rb +161 -60
  69. data/spec/lib/ruby_smb/dcerpc/ndr_spec.rb +1396 -77
  70. data/spec/lib/ruby_smb/dcerpc/rpc_security_attributes_spec.rb +161 -0
  71. data/spec/lib/ruby_smb/dcerpc/rrp_unicode_string_spec.rb +49 -12
  72. data/spec/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_request_spec.rb +191 -0
  73. data/spec/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_response_spec.rb +38 -0
  74. data/spec/lib/ruby_smb/dcerpc/svcctl/close_service_handle_request_spec.rb +30 -0
  75. data/spec/lib/ruby_smb/dcerpc/svcctl/close_service_handle_response_spec.rb +38 -0
  76. data/spec/lib/ruby_smb/dcerpc/svcctl/control_service_request_spec.rb +39 -0
  77. data/spec/lib/ruby_smb/dcerpc/svcctl/control_service_response_spec.rb +38 -0
  78. data/spec/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_request_spec.rb +78 -0
  79. data/spec/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_response_spec.rb +38 -0
  80. data/spec/lib/ruby_smb/dcerpc/svcctl/open_service_w_request_spec.rb +59 -0
  81. data/spec/lib/ruby_smb/dcerpc/svcctl/open_service_w_response_spec.rb +38 -0
  82. data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_request_spec.rb +38 -0
  83. data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_response_spec.rb +152 -0
  84. data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_status_request_spec.rb +30 -0
  85. data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_status_response_spec.rb +38 -0
  86. data/spec/lib/ruby_smb/dcerpc/svcctl/service_status_spec.rb +72 -0
  87. data/spec/lib/ruby_smb/dcerpc/svcctl/start_service_w_request_spec.rb +46 -0
  88. data/spec/lib/ruby_smb/dcerpc/svcctl/start_service_w_response_spec.rb +30 -0
  89. data/spec/lib/ruby_smb/dcerpc/svcctl_spec.rb +512 -0
  90. data/spec/lib/ruby_smb/dcerpc/winreg/create_key_request_spec.rb +110 -0
  91. data/spec/lib/ruby_smb/dcerpc/winreg/create_key_response_spec.rb +44 -0
  92. data/spec/lib/ruby_smb/dcerpc/winreg/enum_key_request_spec.rb +0 -4
  93. data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_request_spec.rb +2 -2
  94. data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_response_spec.rb +2 -2
  95. data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_request_spec.rb +9 -4
  96. data/spec/lib/ruby_smb/dcerpc/winreg/query_info_key_request_spec.rb +0 -4
  97. data/spec/lib/ruby_smb/dcerpc/winreg/query_value_request_spec.rb +17 -17
  98. data/spec/lib/ruby_smb/dcerpc/winreg/query_value_response_spec.rb +11 -23
  99. data/spec/lib/ruby_smb/dcerpc/winreg/save_key_request_spec.rb +57 -0
  100. data/spec/lib/ruby_smb/dcerpc/winreg/save_key_response_spec.rb +22 -0
  101. data/spec/lib/ruby_smb/dcerpc/winreg_spec.rb +215 -41
  102. data/spec/lib/ruby_smb/dispatcher/socket_spec.rb +10 -10
  103. data/spec/lib/ruby_smb/field/stringz16_spec.rb +12 -0
  104. data/spec/lib/ruby_smb/nbss/session_header_spec.rb +4 -11
  105. data/spec/lib/ruby_smb/smb1/pipe_spec.rb +7 -0
  106. data/spec/lib/ruby_smb/smb2/file_spec.rb +60 -6
  107. data/spec/lib/ruby_smb/smb2/pipe_spec.rb +7 -0
  108. data/spec/lib/ruby_smb/smb2/tree_spec.rb +35 -1
  109. metadata +72 -2
  110. metadata.gz.sig +0 -0
@@ -0,0 +1,27 @@
1
+ require 'ruby_smb/dcerpc/ndr'
2
+
3
+ module RubySMB
4
+ module Dcerpc
5
+ module Svcctl
6
+
7
+ # [3.1.4.19 RStartServiceW (Opnum 19)](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-scmr/d9be95a2-cf01-4bdc-b30f-6fe4b37ada16)
8
+ class StartServiceWRequest < BinData::Record
9
+ attr_reader :opnum
10
+
11
+ endian :little
12
+
13
+ sc_rpc_handle :h_service
14
+ uint32 :argc
15
+ ndr_lp_string_ptrsw :argv
16
+
17
+ def initialize_instance
18
+ super
19
+ @opnum = START_SERVICE_W
20
+ end
21
+ end
22
+
23
+ end
24
+ end
25
+ end
26
+
27
+
@@ -0,0 +1,25 @@
1
+ require 'ruby_smb/dcerpc/ndr'
2
+
3
+ module RubySMB
4
+ module Dcerpc
5
+ module Svcctl
6
+
7
+ # [3.1.4.19 RStartServiceW (Opnum 19)](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-scmr/d9be95a2-cf01-4bdc-b30f-6fe4b37ada16)
8
+ class StartServiceWResponse < BinData::Record
9
+ attr_reader :opnum
10
+
11
+ endian :little
12
+
13
+ uint32 :error_status
14
+
15
+ def initialize_instance
16
+ super
17
+ @opnum = START_SERVICE_W
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+
25
+
@@ -13,11 +13,13 @@ module RubySMB
13
13
  OPEN_HKPD = 0x03
14
14
  OPEN_HKU = 0x04
15
15
  REG_CLOSE_KEY = 0x05
16
+ REG_CREATE_KEY = 0x06
16
17
  REG_ENUM_KEY = 0x09
17
18
  REG_ENUM_VALUE = 0x0a
18
19
  REG_OPEN_KEY = 0x0f
19
20
  REG_QUERY_INFO_KEY = 0x10
20
21
  REG_QUERY_VALUE = 0x11
22
+ REG_SAVE_KEY = 0x14
21
23
  OPEN_HKCC = 0x1b
22
24
  OPEN_HKPT = 0x20
23
25
  OPEN_HKPN = 0x21
@@ -37,6 +39,10 @@ module RubySMB
37
39
  require 'ruby_smb/dcerpc/winreg/query_info_key_response'
38
40
  require 'ruby_smb/dcerpc/winreg/query_value_request'
39
41
  require 'ruby_smb/dcerpc/winreg/query_value_response'
42
+ require 'ruby_smb/dcerpc/winreg/create_key_request'
43
+ require 'ruby_smb/dcerpc/winreg/create_key_response'
44
+ require 'ruby_smb/dcerpc/winreg/save_key_request'
45
+ require 'ruby_smb/dcerpc/winreg/save_key_response'
40
46
 
41
47
  ROOT_KEY_MAP = {
42
48
  "HKEY_CLASSES_ROOT" => OPEN_HKCR,
@@ -125,7 +131,9 @@ module RubySMB
125
131
  # @raise [RubySMB::Dcerpc::Error::WinregError] if the response error status is not ERROR_SUCCESS
126
132
  def query_value(handle, value_name)
127
133
  query_value_request_packet = RubySMB::Dcerpc::Winreg::QueryValueRequest.new(hkey: handle, lp_value_name: value_name)
128
- query_value_request_packet.lp_data.referent_identifier = 0
134
+ query_value_request_packet.lp_type = 0
135
+ query_value_request_packet.lpcb_data = 0
136
+ query_value_request_packet.lpcb_len = 0
129
137
  response = dcerpc_request(query_value_request_packet)
130
138
  begin
131
139
  query_value_response = RubySMB::Dcerpc::Winreg::QueryValueResponse.read(response)
@@ -137,9 +145,9 @@ module RubySMB
137
145
  "#{WindowsError::Win32.find_by_retval(query_value_response.error_status.value).join(',')}"
138
146
  end
139
147
 
140
- query_value_request_packet = RubySMB::Dcerpc::Winreg::QueryValueRequest.new(hkey: handle, lp_value_name: value_name)
141
148
  query_value_request_packet.lpcb_data = query_value_response.lpcb_data
142
- query_value_request_packet.lp_data.max_count = query_value_response.lpcb_data.referent
149
+ query_value_request_packet.lp_data = []
150
+ query_value_request_packet.lp_data.referent.max_count = query_value_response.lpcb_data.referent
143
151
  response = dcerpc_request(query_value_request_packet)
144
152
  begin
145
153
  query_value_response = RubySMB::Dcerpc::Winreg::QueryValueResponse.read(response)
@@ -185,6 +193,10 @@ module RubySMB
185
193
  # @raise [RubySMB::Dcerpc::Error::WinregError] if the response error status is not ERROR_SUCCESS
186
194
  def query_info_key(handle)
187
195
  query_info_key_request_packet = RubySMB::Dcerpc::Winreg::QueryInfoKeyRequest.new(hkey: handle)
196
+ query_info_key_request_packet.lp_class = ''
197
+ query_info_key_request_packet.lp_class.referent.actual_count = 0
198
+ query_info_key_request_packet.lp_class.maximum_length = 1024
199
+ query_info_key_request_packet.lp_class.buffer.referent.max_count = 1024 / 2
188
200
  response = dcerpc_request(query_info_key_request_packet)
189
201
  begin
190
202
  query_info_key_response = RubySMB::Dcerpc::Winreg::QueryInfoKeyResponse.read(response)
@@ -209,7 +221,9 @@ module RubySMB
209
221
  def enum_key(handle, index)
210
222
  enum_key_request_packet = RubySMB::Dcerpc::Winreg::EnumKeyRequest.new(hkey: handle, dw_index: index)
211
223
  enum_key_request_packet.lpft_last_write_time = 0
212
- enum_key_request_packet.lp_class.referent.buffer = 0
224
+ enum_key_request_packet.lp_class = ''
225
+ enum_key_request_packet.lp_class.referent.buffer = :null
226
+ enum_key_request_packet.lp_name.buffer = ''
213
227
  enum_key_request_packet.lp_name.buffer.referent.max_count = 256
214
228
  response = dcerpc_request(enum_key_request_packet)
215
229
  begin
@@ -234,7 +248,7 @@ module RubySMB
234
248
  # @raise [RubySMB::Dcerpc::Error::WinregError] if the response error status is not ERROR_SUCCESS
235
249
  def enum_value(handle, index)
236
250
  enum_value_request_packet = RubySMB::Dcerpc::Winreg::EnumValueRequest.new(hkey: handle, dw_index: index)
237
- enum_value_request_packet.lp_data.referent_identifier = 0
251
+ enum_value_request_packet.lp_value_name.buffer = ''
238
252
  enum_value_request_packet.lp_value_name.buffer.referent.max_count = 256
239
253
  response = dcerpc_request(enum_value_request_packet)
240
254
  begin
@@ -250,13 +264,72 @@ module RubySMB
250
264
  enum_value_response.lp_value_name.to_s
251
265
  end
252
266
 
267
+ # Creates the specified registry key and returns a handle to the newly created key
268
+ #
269
+ # @param handle [Ndr::NdrContextHandle] the handle for the key
270
+ # @param sub_key [String] the name of the key
271
+ # @param opts [Hash] options for the CreateKeyRequest
272
+ # @return [RubySMB::Dcerpc::Winreg::PrpcHkey] the handle to the opened or created key
273
+ # @raise [RubySMB::Dcerpc::Error::InvalidPacket] if the response is not a CreateKeyResponse packet
274
+ # @raise [RubySMB::Dcerpc::Error::WinregError] if the response error status is not ERROR_SUCCESS
275
+ def create_key(handle, sub_key, opts = {})
276
+ opts = {
277
+ hkey: handle,
278
+ lp_sub_key: sub_key,
279
+ lp_class: opts[:lp_class] || :null,
280
+ dw_options: opts[:dw_options] || RubySMB::Dcerpc::Winreg::CreateKeyRequest::REG_KEY_TYPE_VOLATILE,
281
+ sam_desired: opts[:sam_desired] || RubySMB::Dcerpc::Winreg::Regsam.new(maximum: 1),
282
+ lp_security_attributes: opts[:lp_security_attributes] || RubySMB::Dcerpc::RpcSecurityAttributes.new,
283
+ lpdw_disposition: opts[:lpdw_disposition] || RubySMB::Dcerpc::Winreg::CreateKeyRequest::REG_CREATED_NEW_KEY,
284
+ }
285
+ create_key_request_packet = RubySMB::Dcerpc::Winreg::CreateKeyRequest.new(opts)
286
+ response = dcerpc_request(create_key_request_packet)
287
+ begin
288
+ create_key_response = RubySMB::Dcerpc::Winreg::CreateKeyResponse.read(response)
289
+ rescue IOError
290
+ raise RubySMB::Dcerpc::Error::InvalidPacket, "Error reading the CreateKey response"
291
+ end
292
+ unless create_key_response.error_status == WindowsError::Win32::ERROR_SUCCESS
293
+ raise RubySMB::Dcerpc::Error::WinregError, "Error returned when creating key #{sub_key}: "\
294
+ "#{WindowsError::Win32.find_by_retval(create_key_response.error_status.value).join(',')}"
295
+ end
296
+
297
+ create_key_response.hkey
298
+ end
299
+
300
+ # Saves the specified key, subkeys, and values to a new file
301
+ #
302
+ # @param handle [Ndr::NdrContextHandle] the handle for the key
303
+ # @param file_name [String] the name of the registry file in which the specified key and subkeys are to be saved
304
+ # @param opts [Hash] options for the SaveKeyRequest
305
+ # @raise [RubySMB::Dcerpc::Error::InvalidPacket] if the response is not a SaveKeyResponse packet
306
+ # @raise [RubySMB::Dcerpc::Error::WinregError] if the response error status is not ERROR_SUCCESS
307
+ def save_key(handle, file_name, opts = {})
308
+ opts = {
309
+ hkey: handle,
310
+ lp_file: file_name,
311
+ lp_security_attributes: opts[:lp_security_attributes] || :null,
312
+ }
313
+ save_key_request_packet = RubySMB::Dcerpc::Winreg::SaveKeyRequest.new(opts)
314
+ response = dcerpc_request(save_key_request_packet)
315
+ begin
316
+ save_key_response = RubySMB::Dcerpc::Winreg::SaveKeyResponse.read(response)
317
+ rescue IOError
318
+ raise RubySMB::Dcerpc::Error::InvalidPacket, "Error reading the SaveKeyResponse response"
319
+ end
320
+ unless save_key_response.error_status == WindowsError::Win32::ERROR_SUCCESS
321
+ raise RubySMB::Dcerpc::Error::WinregError, "Error returned when saving key to #{file_name}: "\
322
+ "#{WindowsError::Win32.find_by_retval(save_key_response.error_status.value).join(',')}"
323
+ end
324
+ end
325
+
253
326
  # Checks if the specified registry key exists. It returns true if it
254
327
  # exists, false otherwise.
255
328
  #
256
329
  # @param key [String] the registry key to check
257
330
  # @return [Boolean]
258
- def has_registry_key?(key)
259
- bind(endpoint: RubySMB::Dcerpc::Winreg)
331
+ def has_registry_key?(key, bind: true)
332
+ bind(endpoint: RubySMB::Dcerpc::Winreg) if bind
260
333
 
261
334
  root_key, sub_key = key.gsub(/\//, '\\').split('\\', 2)
262
335
  begin
@@ -265,8 +338,10 @@ module RubySMB
265
338
  rescue RubySMB::Dcerpc::Error::WinregError
266
339
  return false
267
340
  end
268
- close_key(subkey_handle)
269
341
  return true
342
+ ensure
343
+ close_key(subkey_handle) if subkey_handle
344
+ close_key(root_key_handle) if root_key_handle
270
345
  end
271
346
 
272
347
  # Retrieve the data associated with the named value of a specified
@@ -275,15 +350,17 @@ module RubySMB
275
350
  # @param key [String] the registry key
276
351
  # @param value_name [String] the name of the value to read
277
352
  # @return [String] the data of the value entry
278
- def read_registry_key_value(key, value_name)
279
- bind(endpoint: RubySMB::Dcerpc::Winreg)
353
+ def read_registry_key_value(key, value_name, bind: true)
354
+ bind(endpoint: RubySMB::Dcerpc::Winreg) if bind
280
355
 
281
356
  root_key, sub_key = key.gsub(/\//, '\\').split('\\', 2)
282
357
  root_key_handle = open_root_key(root_key)
283
358
  subkey_handle = open_key(root_key_handle, sub_key)
284
359
  value = query_value(subkey_handle, value_name)
285
- close_key(subkey_handle)
286
360
  value
361
+ ensure
362
+ close_key(subkey_handle) if subkey_handle
363
+ close_key(root_key_handle) if root_key_handle
287
364
  end
288
365
 
289
366
  # Enumerate the subkeys of a specified registry key. If only a root key
@@ -291,8 +368,8 @@ module RubySMB
291
368
  #
292
369
  # @param key [String] the registry key
293
370
  # @return [Array<String>] the subkeys
294
- def enum_registry_key(key)
295
- bind(endpoint: RubySMB::Dcerpc::Winreg)
371
+ def enum_registry_key(key, bind: true)
372
+ bind(endpoint: RubySMB::Dcerpc::Winreg) if bind
296
373
 
297
374
  root_key, sub_key = key.gsub(/\//, '\\').split('\\', 2)
298
375
  root_key_handle = open_root_key(root_key)
@@ -307,16 +384,18 @@ module RubySMB
307
384
  key_count.times do |i|
308
385
  enum_result << enum_key(subkey_handle, i)
309
386
  end
310
- close_key(subkey_handle)
311
387
  enum_result
388
+ ensure
389
+ close_key(subkey_handle) if subkey_handle
390
+ close_key(root_key_handle) if root_key_handle
312
391
  end
313
392
 
314
393
  # Enumerate the values for the specified registry key.
315
394
  #
316
395
  # @param key [String] the registry key
317
396
  # @return [Array<String>] the values
318
- def enum_registry_values(key)
319
- bind(endpoint: RubySMB::Dcerpc::Winreg)
397
+ def enum_registry_values(key, bind: true)
398
+ bind(endpoint: RubySMB::Dcerpc::Winreg) if bind
320
399
 
321
400
  root_key, sub_key = key.gsub(/\//, '\\').split('\\', 2)
322
401
  root_key_handle = open_root_key(root_key)
@@ -331,8 +410,10 @@ module RubySMB
331
410
  value_count.times do |i|
332
411
  enum_result << enum_value(subkey_handle, i)
333
412
  end
334
- close_key(subkey_handle)
335
413
  enum_result
414
+ ensure
415
+ close_key(subkey_handle) if subkey_handle
416
+ close_key(root_key_handle) if root_key_handle
336
417
  end
337
418
 
338
419
  end
@@ -0,0 +1,73 @@
1
+ module RubySMB
2
+ module Dcerpc
3
+ module Winreg
4
+
5
+ class RpcHkey < Ndr::NdrContextHandle; end
6
+
7
+ # This class represents a BaseRegCreateKey Request Packet as defined in
8
+ # [3.1.5.7 BaseRegCreateKey (Opnum 6)](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rrp/c7186ae2-1c82-45e9-933b-97d9873657e8)
9
+ class CreateKeyRequest < BinData::Record
10
+ # Options:
11
+ # bitwise OR of one of the key types (REG_KEY_TYPE_*), and any or none
12
+ # of the other options:
13
+ #
14
+ # This key is not volatile. The key and all its values MUST be
15
+ # persisted to the backing store and is preserved when the registry
16
+ # server loses context due to a computer restart, reboot, or shut down
17
+ # process.
18
+ REG_KEY_TYPE_NON_VOLATILE = 0x00000000
19
+ # This key is volatile. The key with all its subkeys and values MUST
20
+ # NOT be preserved when the registry server loses context due to a
21
+ # computer restart, reboot, or shut down process.
22
+ REG_KEY_TYPE_VOLATILE = 0x00000001
23
+ # This key is a symbolic link to another key.
24
+ REG_KEY_TYPE_SYMLINK = 0x00000002
25
+ # Indicates that the caller wishes to assert its backup and/or restore
26
+ # privileges.
27
+ REG_OPTION_BACKUP_RESTORE = 0x00000004
28
+ # Indicates that the caller wishes to open the targeted symlink source
29
+ # rather than the symlink target.
30
+ REG_OPTION_OPEN_LINK = 0x00000008
31
+ # Indicates that the caller wishes to disable limited user access
32
+ # virtualization for this operation.
33
+ REG_OPTION_DONT_VIRTUALIZE = 0x00000010
34
+
35
+
36
+ # Create disposition:
37
+ # The key did not exist and was created.
38
+ REG_CREATED_NEW_KEY = 0x00000001
39
+ # The key already existed and was opened without being changed.
40
+ REG_OPENED_EXISTING_KEY = 0x00000002
41
+
42
+ attr_reader :opnum
43
+
44
+ endian :little
45
+
46
+ rpc_hkey :hkey
47
+ rrp_unicode_string :lp_sub_key
48
+ string :pad1, length: -> { pad_length(self.lp_sub_key) }
49
+ rrp_unicode_string :lp_class
50
+ string :pad2, length: -> { pad_length(self.lp_class) }
51
+ uint32 :dw_options
52
+ regsam :sam_desired
53
+ prpc_security_attributes :lp_security_attributes
54
+ string :pad3, length: -> { pad_length(self.lp_security_attributes) }
55
+ ndr_lp_dword :lpdw_disposition
56
+
57
+ def initialize_instance
58
+ super
59
+ @opnum = REG_CREATE_KEY
60
+ end
61
+
62
+ # Determines the correct length for the padding, so that the next
63
+ # field is 4-byte aligned.
64
+ def pad_length(prev_element)
65
+ offset = (prev_element.abs_offset + prev_element.to_binary_s.length) % 4
66
+ (4 - offset) % 4
67
+ end
68
+ end
69
+
70
+ end
71
+ end
72
+ end
73
+
@@ -0,0 +1,36 @@
1
+ module RubySMB
2
+ module Dcerpc
3
+ module Winreg
4
+
5
+ class PrpcHkey < Ndr::NdrContextHandle; end
6
+
7
+ # This class represents a BaseRegCreateKey Response Packet as defined in
8
+ # [3.1.5.7 BaseRegCreateKey (Opnum 6)](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rrp/c7186ae2-1c82-45e9-933b-97d9873657e8)
9
+ class CreateKeyResponse < BinData::Record
10
+ # Create disposition
11
+ # The key did not exist and was created.
12
+ REG_CREATED_NEW_KEY = 0x00000001
13
+ # The key already existed and was opened without being changed.
14
+ REG_OPENED_EXISTING_KEY = 0x00000002
15
+
16
+ attr_reader :opnum
17
+
18
+ endian :little
19
+
20
+ prpc_hkey :hkey
21
+ ndr_lp_dword :lpdw_disposition
22
+ uint32 :error_status
23
+
24
+ def initialize_instance
25
+ super
26
+ @opnum = REG_CREATE_KEY
27
+ end
28
+ end
29
+
30
+ end
31
+ end
32
+ end
33
+
34
+
35
+
36
+
@@ -13,7 +13,7 @@ module RubySMB
13
13
 
14
14
  rpc_hkey :hkey
15
15
  uint32 :dw_index
16
- rrp_unicode_string :lp_name
16
+ rrp_unicode_string :lp_name
17
17
  string :pad1, length: -> { pad_length1 }
18
18
  prrp_unicode_string :lp_class
19
19
  string :pad2, length: -> { pad_length2 }
@@ -16,7 +16,7 @@ module RubySMB
16
16
  rrp_unicode_string :lp_value_name
17
17
  string :pad, length: -> { pad_length }
18
18
  ndr_lp_dword :lp_type
19
- ndr_lp_byte :lp_data
19
+ ndr_lp_byte_array :lp_data
20
20
  ndr_lp_dword :lpcb_data
21
21
  ndr_lp_dword :lpcb_len
22
22
 
@@ -12,7 +12,7 @@ module RubySMB
12
12
  rrp_unicode_string :lp_value_name
13
13
  string :pad, length: -> { pad_length }
14
14
  ndr_lp_dword :lp_type
15
- ndr_lp_byte :lp_data
15
+ ndr_lp_byte_array :lp_data
16
16
  ndr_lp_dword :lpcb_data
17
17
  ndr_lp_dword :lpcb_len
18
18
  uint32 :error_status
@@ -4,10 +4,10 @@ module RubySMB
4
4
 
5
5
  # This class represents a PREGISTRY_SERVER_NAME structure as defined in
6
6
  # [2.2.2 PREGISTRY_SERVER_NAME](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rrp/8bcd15fd-1aa5-44e2-8662-112ec3e9817b)
7
- class PRegistryServerName < Ndr::NdrTopLevelFullPointer
7
+ class PRegistryServerName < Ndr::NdrPointer
8
8
  endian :little
9
9
 
10
- string16 :referent, read_length: -> { 4 }
10
+ string16 :referent, onlyif: -> { self.referent_id != 0 }, read_length: -> { 4 }
11
11
  end
12
12
 
13
13
  # This class is a generic class that represents OpenXXX Request packet,
@@ -33,8 +33,8 @@ module RubySMB
33
33
  def initialize_instance
34
34
  super
35
35
  @opnum = get_parameter(:opnum) if has_parameter?(:opnum)
36
- p_registry_server_name.referent = "\0\0"
37
- sam_desired.maximum = 1 unless [OPEN_HKPD, OPEN_HKPT, OPEN_HKPN].include?(@opnum)
36
+ self.p_registry_server_name = :null
37
+ self.sam_desired.maximum = 1 unless [OPEN_HKPD, OPEN_HKPT, OPEN_HKPN].include?(@opnum)
38
38
  end
39
39
  end
40
40
 
@@ -12,7 +12,7 @@ module RubySMB
12
12
  endian :little
13
13
 
14
14
  rpc_hkey :hkey
15
- rrp_unicode_string :lp_class, initial_value: 0
15
+ rrp_unicode_string :lp_class
16
16
 
17
17
  def initialize_instance
18
18
  super