ruby_smb 1.0.3 → 2.0.1
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.
- checksums.yaml +5 -5
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/.travis.yml +3 -2
- data/Gemfile +6 -2
- data/README.md +35 -47
- data/examples/enum_registry_key.rb +28 -0
- data/examples/enum_registry_values.rb +30 -0
- data/examples/negotiate.rb +51 -8
- data/examples/pipes.rb +2 -1
- data/examples/read_file_encryption.rb +56 -0
- data/examples/read_registry_key_value.rb +32 -0
- data/lib/ruby_smb.rb +4 -1
- data/lib/ruby_smb/client.rb +233 -22
- data/lib/ruby_smb/client/authentication.rb +70 -33
- data/lib/ruby_smb/client/echo.rb +20 -2
- data/lib/ruby_smb/client/encryption.rb +62 -0
- data/lib/ruby_smb/client/negotiation.rb +172 -24
- data/lib/ruby_smb/client/signing.rb +19 -0
- data/lib/ruby_smb/client/tree_connect.rb +24 -18
- data/lib/ruby_smb/client/utils.rb +8 -7
- data/lib/ruby_smb/client/winreg.rb +46 -0
- data/lib/ruby_smb/crypto.rb +30 -0
- data/lib/ruby_smb/dcerpc.rb +38 -0
- data/lib/ruby_smb/dcerpc/bind.rb +2 -2
- data/lib/ruby_smb/dcerpc/bind_ack.rb +2 -2
- data/lib/ruby_smb/dcerpc/error.rb +3 -0
- data/lib/ruby_smb/dcerpc/ndr.rb +95 -16
- data/lib/ruby_smb/dcerpc/pdu_header.rb +1 -1
- data/lib/ruby_smb/dcerpc/request.rb +28 -9
- data/lib/ruby_smb/dcerpc/rrp_unicode_string.rb +35 -0
- data/lib/ruby_smb/dcerpc/srvsvc.rb +10 -0
- data/lib/ruby_smb/dcerpc/srvsvc/net_share_enum_all.rb +9 -0
- data/lib/ruby_smb/dcerpc/winreg.rb +340 -0
- data/lib/ruby_smb/dcerpc/winreg/close_key_request.rb +24 -0
- data/lib/ruby_smb/dcerpc/winreg/close_key_response.rb +27 -0
- data/lib/ruby_smb/dcerpc/winreg/enum_key_request.rb +45 -0
- data/lib/ruby_smb/dcerpc/winreg/enum_key_response.rb +42 -0
- data/lib/ruby_smb/dcerpc/winreg/enum_value_request.rb +39 -0
- data/lib/ruby_smb/dcerpc/winreg/enum_value_response.rb +36 -0
- data/lib/ruby_smb/dcerpc/winreg/open_key_request.rb +34 -0
- data/lib/ruby_smb/dcerpc/winreg/open_key_response.rb +25 -0
- data/lib/ruby_smb/dcerpc/winreg/open_root_key_request.rb +43 -0
- data/lib/ruby_smb/dcerpc/winreg/open_root_key_response.rb +35 -0
- data/lib/ruby_smb/dcerpc/winreg/query_info_key_request.rb +27 -0
- data/lib/ruby_smb/dcerpc/winreg/query_info_key_response.rb +40 -0
- data/lib/ruby_smb/dcerpc/winreg/query_value_request.rb +39 -0
- data/lib/ruby_smb/dcerpc/winreg/query_value_response.rb +57 -0
- data/lib/ruby_smb/dcerpc/winreg/regsam.rb +40 -0
- data/lib/ruby_smb/dispatcher/socket.rb +4 -3
- data/lib/ruby_smb/error.rb +68 -2
- data/lib/ruby_smb/generic_packet.rb +33 -4
- data/lib/ruby_smb/smb1/commands.rb +1 -1
- data/lib/ruby_smb/smb1/file.rb +66 -15
- data/lib/ruby_smb/smb1/packet/close_request.rb +2 -5
- data/lib/ruby_smb/smb1/packet/close_response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/echo_request.rb +2 -4
- data/lib/ruby_smb/smb1/packet/echo_response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/empty_packet.rb +10 -1
- data/lib/ruby_smb/smb1/packet/logoff_request.rb +2 -4
- data/lib/ruby_smb/smb1/packet/logoff_response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/negotiate_request.rb +2 -5
- data/lib/ruby_smb/smb1/packet/negotiate_response.rb +3 -7
- data/lib/ruby_smb/smb1/packet/negotiate_response_extended.rb +4 -4
- data/lib/ruby_smb/smb1/packet/nt_create_andx_request.rb +2 -4
- data/lib/ruby_smb/smb1/packet/nt_create_andx_response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/nt_trans/create_request.rb +2 -1
- data/lib/ruby_smb/smb1/packet/nt_trans/create_response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/nt_trans/request.rb +2 -4
- data/lib/ruby_smb/smb1/packet/nt_trans/response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/read_andx_request.rb +2 -5
- data/lib/ruby_smb/smb1/packet/read_andx_response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/session_setup_legacy_request.rb +2 -1
- data/lib/ruby_smb/smb1/packet/session_setup_legacy_response.rb +3 -2
- data/lib/ruby_smb/smb1/packet/session_setup_request.rb +2 -5
- data/lib/ruby_smb/smb1/packet/session_setup_response.rb +3 -2
- data/lib/ruby_smb/smb1/packet/trans/peek_nmpipe_request.rb +0 -1
- data/lib/ruby_smb/smb1/packet/trans/peek_nmpipe_response.rb +3 -2
- data/lib/ruby_smb/smb1/packet/trans/request.rb +2 -5
- data/lib/ruby_smb/smb1/packet/trans/response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/trans/transact_nmpipe_request.rb +1 -1
- data/lib/ruby_smb/smb1/packet/trans/transact_nmpipe_response.rb +1 -1
- data/lib/ruby_smb/smb1/packet/trans2/find_first2_request.rb +2 -1
- data/lib/ruby_smb/smb1/packet/trans2/find_first2_response.rb +8 -2
- data/lib/ruby_smb/smb1/packet/trans2/find_next2_request.rb +2 -1
- data/lib/ruby_smb/smb1/packet/trans2/find_next2_response.rb +8 -2
- data/lib/ruby_smb/smb1/packet/trans2/open2_request.rb +2 -1
- data/lib/ruby_smb/smb1/packet/trans2/open2_response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/trans2/request.rb +2 -4
- data/lib/ruby_smb/smb1/packet/trans2/request_secondary.rb +2 -4
- data/lib/ruby_smb/smb1/packet/trans2/response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/trans2/set_file_information_request.rb +2 -1
- data/lib/ruby_smb/smb1/packet/trans2/set_file_information_response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/tree_connect_request.rb +2 -4
- data/lib/ruby_smb/smb1/packet/tree_connect_response.rb +13 -3
- data/lib/ruby_smb/smb1/packet/tree_disconnect_request.rb +2 -4
- data/lib/ruby_smb/smb1/packet/tree_disconnect_response.rb +2 -1
- data/lib/ruby_smb/smb1/packet/write_andx_request.rb +3 -6
- data/lib/ruby_smb/smb1/packet/write_andx_response.rb +2 -1
- data/lib/ruby_smb/smb1/pipe.rb +87 -6
- data/lib/ruby_smb/smb1/tree.rb +50 -3
- data/lib/ruby_smb/smb2/bit_field/session_flags.rb +2 -1
- data/lib/ruby_smb/smb2/bit_field/share_flags.rb +6 -4
- data/lib/ruby_smb/smb2/file.rb +103 -25
- data/lib/ruby_smb/smb2/negotiate_context.rb +108 -0
- data/lib/ruby_smb/smb2/packet.rb +2 -0
- data/lib/ruby_smb/smb2/packet/close_request.rb +2 -4
- data/lib/ruby_smb/smb2/packet/close_response.rb +2 -1
- data/lib/ruby_smb/smb2/packet/compression_transform_header.rb +41 -0
- data/lib/ruby_smb/smb2/packet/create_request.rb +2 -4
- data/lib/ruby_smb/smb2/packet/create_response.rb +2 -1
- data/lib/ruby_smb/smb2/packet/echo_request.rb +2 -4
- data/lib/ruby_smb/smb2/packet/echo_response.rb +2 -1
- data/lib/ruby_smb/smb2/packet/error_packet.rb +15 -3
- data/lib/ruby_smb/smb2/packet/ioctl_request.rb +2 -5
- data/lib/ruby_smb/smb2/packet/ioctl_response.rb +2 -1
- data/lib/ruby_smb/smb2/packet/logoff_request.rb +2 -4
- data/lib/ruby_smb/smb2/packet/logoff_response.rb +2 -1
- data/lib/ruby_smb/smb2/packet/negotiate_request.rb +51 -17
- data/lib/ruby_smb/smb2/packet/negotiate_response.rb +52 -5
- data/lib/ruby_smb/smb2/packet/query_directory_request.rb +2 -4
- data/lib/ruby_smb/smb2/packet/query_directory_response.rb +8 -2
- data/lib/ruby_smb/smb2/packet/read_request.rb +2 -4
- data/lib/ruby_smb/smb2/packet/read_response.rb +2 -1
- data/lib/ruby_smb/smb2/packet/session_setup_request.rb +2 -5
- data/lib/ruby_smb/smb2/packet/session_setup_response.rb +2 -1
- data/lib/ruby_smb/smb2/packet/set_info_request.rb +2 -4
- data/lib/ruby_smb/smb2/packet/set_info_response.rb +2 -1
- data/lib/ruby_smb/smb2/packet/transform_header.rb +84 -0
- data/lib/ruby_smb/smb2/packet/tree_connect_request.rb +93 -10
- data/lib/ruby_smb/smb2/packet/tree_connect_response.rb +10 -22
- data/lib/ruby_smb/smb2/packet/tree_disconnect_request.rb +2 -4
- data/lib/ruby_smb/smb2/packet/tree_disconnect_response.rb +2 -1
- data/lib/ruby_smb/smb2/packet/write_request.rb +2 -4
- data/lib/ruby_smb/smb2/packet/write_response.rb +2 -1
- data/lib/ruby_smb/smb2/pipe.rb +86 -12
- data/lib/ruby_smb/smb2/smb2_header.rb +1 -1
- data/lib/ruby_smb/smb2/tree.rb +65 -21
- data/lib/ruby_smb/version.rb +1 -1
- data/ruby_smb.gemspec +5 -3
- data/spec/lib/ruby_smb/client_spec.rb +1612 -108
- data/spec/lib/ruby_smb/crypto_spec.rb +25 -0
- data/spec/lib/ruby_smb/dcerpc/bind_ack_spec.rb +2 -2
- data/spec/lib/ruby_smb/dcerpc/bind_spec.rb +2 -2
- data/spec/lib/ruby_smb/dcerpc/ndr_spec.rb +410 -0
- data/spec/lib/ruby_smb/dcerpc/request_spec.rb +50 -7
- data/spec/lib/ruby_smb/dcerpc/rrp_unicode_string_spec.rb +98 -0
- data/spec/lib/ruby_smb/dcerpc/srvsvc/net_share_enum_all_spec.rb +13 -0
- data/spec/lib/ruby_smb/dcerpc/srvsvc_spec.rb +60 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/close_key_request_spec.rb +28 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/close_key_response_spec.rb +36 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/enum_key_request_spec.rb +108 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/enum_key_response_spec.rb +97 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_request_spec.rb +94 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_response_spec.rb +82 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/open_key_request_spec.rb +74 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/open_key_response_spec.rb +35 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_request_spec.rb +90 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_response_spec.rb +38 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/query_info_key_request_spec.rb +39 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/query_info_key_response_spec.rb +113 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/query_value_request_spec.rb +88 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/query_value_response_spec.rb +150 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/regsam_spec.rb +32 -0
- data/spec/lib/ruby_smb/dcerpc/winreg_spec.rb +710 -0
- data/spec/lib/ruby_smb/dcerpc_spec.rb +81 -0
- data/spec/lib/ruby_smb/dispatcher/socket_spec.rb +2 -2
- data/spec/lib/ruby_smb/error_spec.rb +59 -0
- data/spec/lib/ruby_smb/generic_packet_spec.rb +52 -4
- data/spec/lib/ruby_smb/smb1/file_spec.rb +191 -2
- data/spec/lib/ruby_smb/smb1/packet/empty_packet_spec.rb +68 -0
- data/spec/lib/ruby_smb/smb1/packet/session_setup_legacy_request_spec.rb +2 -2
- data/spec/lib/ruby_smb/smb1/packet/session_setup_legacy_response_spec.rb +2 -2
- data/spec/lib/ruby_smb/smb1/packet/session_setup_request_spec.rb +2 -2
- data/spec/lib/ruby_smb/smb1/packet/session_setup_response_spec.rb +1 -1
- data/spec/lib/ruby_smb/smb1/packet/trans2/find_first2_response_spec.rb +11 -2
- data/spec/lib/ruby_smb/smb1/packet/trans2/find_next2_response_spec.rb +11 -2
- data/spec/lib/ruby_smb/smb1/packet/tree_connect_response_spec.rb +40 -0
- data/spec/lib/ruby_smb/smb1/pipe_spec.rb +272 -149
- data/spec/lib/ruby_smb/smb1/tree_spec.rb +44 -7
- data/spec/lib/ruby_smb/smb2/bit_field/session_flags_spec.rb +9 -0
- data/spec/lib/ruby_smb/smb2/bit_field/share_flags_spec.rb +27 -0
- data/spec/lib/ruby_smb/smb2/file_spec.rb +323 -6
- data/spec/lib/ruby_smb/smb2/negotiate_context_spec.rb +332 -0
- data/spec/lib/ruby_smb/smb2/packet/compression_transform_header_spec.rb +108 -0
- data/spec/lib/ruby_smb/smb2/packet/error_packet_spec.rb +78 -0
- data/spec/lib/ruby_smb/smb2/packet/negotiate_request_spec.rb +138 -3
- data/spec/lib/ruby_smb/smb2/packet/negotiate_response_spec.rb +120 -2
- data/spec/lib/ruby_smb/smb2/packet/query_directory_response_spec.rb +8 -0
- data/spec/lib/ruby_smb/smb2/packet/transform_header_spec.rb +220 -0
- data/spec/lib/ruby_smb/smb2/packet/tree_connect_request_spec.rb +339 -9
- data/spec/lib/ruby_smb/smb2/packet/tree_connect_response_spec.rb +3 -22
- data/spec/lib/ruby_smb/smb2/pipe_spec.rb +286 -149
- data/spec/lib/ruby_smb/smb2/smb2_header_spec.rb +2 -2
- data/spec/lib/ruby_smb/smb2/tree_spec.rb +261 -2
- metadata +191 -83
- metadata.gz.sig +0 -0
- data/lib/ruby_smb/smb1/dcerpc.rb +0 -67
- data/lib/ruby_smb/smb2/dcerpc.rb +0 -70
- data/spec/lib/ruby_smb/smb1/packet/error_packet_spec.rb +0 -37
@@ -5,6 +5,10 @@ module RubySMB
|
|
5
5
|
#https://msdn.microsoft.com/en-us/library/cc247293.aspx
|
6
6
|
|
7
7
|
class NetShareEnumAll < BinData::Record
|
8
|
+
attr_reader :opnum
|
9
|
+
|
10
|
+
mandatory_parameter :host
|
11
|
+
|
8
12
|
endian :little
|
9
13
|
|
10
14
|
uint32 :referent_id, initial_value: 0x00000001
|
@@ -27,6 +31,11 @@ module RubySMB
|
|
27
31
|
uint32 :resume_referent_id, initial_value: 0x00000001
|
28
32
|
uint32 :resume_handle, initial_value: 0
|
29
33
|
|
34
|
+
def initialize_instance
|
35
|
+
super
|
36
|
+
@opnum = NET_SHARE_ENUM_ALL
|
37
|
+
end
|
38
|
+
|
30
39
|
def pad_length
|
31
40
|
offset = (server_unc.abs_offset + server_unc.to_binary_s.length) % 4
|
32
41
|
(4 - offset) % 4
|
@@ -0,0 +1,340 @@
|
|
1
|
+
module RubySMB
|
2
|
+
module Dcerpc
|
3
|
+
module Winreg
|
4
|
+
|
5
|
+
UUID = '338CD001-2244-31F1-AAAA-900038001003'
|
6
|
+
VER_MAJOR = 1
|
7
|
+
VER_MINOR = 0
|
8
|
+
|
9
|
+
# Operation numbers
|
10
|
+
OPEN_HKCR = 0x00
|
11
|
+
OPEN_HKCU = 0x01
|
12
|
+
OPEN_HKLM = 0x02
|
13
|
+
OPEN_HKPD = 0x03
|
14
|
+
OPEN_HKU = 0x04
|
15
|
+
REG_CLOSE_KEY = 0x05
|
16
|
+
REG_ENUM_KEY = 0x09
|
17
|
+
REG_ENUM_VALUE = 0x0a
|
18
|
+
REG_OPEN_KEY = 0x0f
|
19
|
+
REG_QUERY_INFO_KEY = 0x10
|
20
|
+
REG_QUERY_VALUE = 0x11
|
21
|
+
OPEN_HKCC = 0x1b
|
22
|
+
OPEN_HKPT = 0x20
|
23
|
+
OPEN_HKPN = 0x21
|
24
|
+
|
25
|
+
require 'ruby_smb/dcerpc/winreg/regsam'
|
26
|
+
require 'ruby_smb/dcerpc/winreg/open_root_key_request'
|
27
|
+
require 'ruby_smb/dcerpc/winreg/open_root_key_response'
|
28
|
+
require 'ruby_smb/dcerpc/winreg/close_key_request'
|
29
|
+
require 'ruby_smb/dcerpc/winreg/close_key_response'
|
30
|
+
require 'ruby_smb/dcerpc/winreg/enum_key_request'
|
31
|
+
require 'ruby_smb/dcerpc/winreg/enum_key_response'
|
32
|
+
require 'ruby_smb/dcerpc/winreg/enum_value_request'
|
33
|
+
require 'ruby_smb/dcerpc/winreg/enum_value_response'
|
34
|
+
require 'ruby_smb/dcerpc/winreg/open_key_request'
|
35
|
+
require 'ruby_smb/dcerpc/winreg/open_key_response'
|
36
|
+
require 'ruby_smb/dcerpc/winreg/query_info_key_request'
|
37
|
+
require 'ruby_smb/dcerpc/winreg/query_info_key_response'
|
38
|
+
require 'ruby_smb/dcerpc/winreg/query_value_request'
|
39
|
+
require 'ruby_smb/dcerpc/winreg/query_value_response'
|
40
|
+
|
41
|
+
ROOT_KEY_MAP = {
|
42
|
+
"HKEY_CLASSES_ROOT" => OPEN_HKCR,
|
43
|
+
"HKCR" => OPEN_HKCR,
|
44
|
+
"HKEY_CURRENT_USER" => OPEN_HKCU,
|
45
|
+
"HKCU" => OPEN_HKCU,
|
46
|
+
"HKEY_LOCAL_MACHINE" => OPEN_HKLM,
|
47
|
+
"HKLM" => OPEN_HKLM,
|
48
|
+
"HKEY_PERFORMANCE_DATA" => OPEN_HKPD,
|
49
|
+
"HKPD" => OPEN_HKPD,
|
50
|
+
"HKEY_USERS" => OPEN_HKU,
|
51
|
+
"HKU" => OPEN_HKU,
|
52
|
+
"HKEY_CURRENT_CONFIG" => OPEN_HKCC,
|
53
|
+
"HKCC" => OPEN_HKCC,
|
54
|
+
"HKEY_PERFORMANCE_TEXT" => OPEN_HKPT,
|
55
|
+
"HKPT" => OPEN_HKPT,
|
56
|
+
"HKEY_PERFORMANCE_NLS_TEXT" => OPEN_HKPN,
|
57
|
+
"HKPN" => OPEN_HKPN
|
58
|
+
}
|
59
|
+
|
60
|
+
# Open the registry root key and return a handle for it. The key can be
|
61
|
+
# either a long format (e.g. HKEY_LOCAL_MACHINE) or a short format
|
62
|
+
# (e.g. HKLM)
|
63
|
+
#
|
64
|
+
# @param root_key [String] the root key to open
|
65
|
+
# @return [Ndr::NdrContextHandle] the RPC context handle for the root key
|
66
|
+
# @raise [RubySMB::Dcerpc::Error::InvalidPacket] if the response is not a OpenRootKeyResponse packet
|
67
|
+
# @raise [RubySMB::Dcerpc::Error::WinregError] if the response error status is not ERROR_SUCCESS
|
68
|
+
def open_root_key(root_key)
|
69
|
+
root_key_opnum = RubySMB::Dcerpc::Winreg::ROOT_KEY_MAP[root_key]
|
70
|
+
raise ArgumentError, "Unknown Root Key: #{root_key}" unless root_key_opnum
|
71
|
+
|
72
|
+
root_key_request_packet = OpenRootKeyRequest.new(opnum: root_key_opnum)
|
73
|
+
response = dcerpc_request(root_key_request_packet)
|
74
|
+
|
75
|
+
begin
|
76
|
+
root_key_response_packet = OpenRootKeyResponse.read(response)
|
77
|
+
rescue IOError
|
78
|
+
raise RubySMB::Dcerpc::Error::InvalidPacket,
|
79
|
+
"Error reading OpenRootKeyResponse (command = #{root_key_opnum})"
|
80
|
+
end
|
81
|
+
unless root_key_response_packet.error_status == WindowsError::Win32::ERROR_SUCCESS
|
82
|
+
raise RubySMB::Dcerpc::Error::WinregError,
|
83
|
+
"Error returned when opening root key #{root_key}: "\
|
84
|
+
"#{WindowsError::Win32.find_by_retval(root_key_response_packet.error_status.value).join(',')}"
|
85
|
+
end
|
86
|
+
|
87
|
+
root_key_response_packet.ph_key
|
88
|
+
end
|
89
|
+
|
90
|
+
# Open the registry key specified by a root key handle (previously open
|
91
|
+
# with #open_root_key) and a subkey. It returns a handle for the key.
|
92
|
+
#
|
93
|
+
# @param handle [Ndr::NdrContextHandle] the handle for the root key
|
94
|
+
# @param sub_key [String] the subkey to open
|
95
|
+
# @return [Ndr::NdrContextHandle] the RPC context handle for the key
|
96
|
+
# @raise [RubySMB::Dcerpc::Error::InvalidPacket] if the response is not a OpenKeyResponse packet
|
97
|
+
# @raise [RubySMB::Dcerpc::Error::WinregError] if the response error status is not ERROR_SUCCESS
|
98
|
+
def open_key(handle, sub_key)
|
99
|
+
openkey_request_packet = RubySMB::Dcerpc::Winreg::OpenKeyRequest.new(hkey: handle, lp_sub_key: sub_key)
|
100
|
+
openkey_request_packet.sam_desired.read_control = 1
|
101
|
+
openkey_request_packet.sam_desired.key_query_value = 1
|
102
|
+
openkey_request_packet.sam_desired.key_enumerate_sub_keys = 1
|
103
|
+
openkey_request_packet.sam_desired.key_notify = 1
|
104
|
+
response = dcerpc_request(openkey_request_packet)
|
105
|
+
begin
|
106
|
+
open_key_response = RubySMB::Dcerpc::Winreg::OpenKeyResponse.read(response)
|
107
|
+
rescue IOError
|
108
|
+
raise RubySMB::Dcerpc::Error::InvalidPacket, "Error reading the OpenKey response"
|
109
|
+
end
|
110
|
+
unless open_key_response.error_status == WindowsError::Win32::ERROR_SUCCESS
|
111
|
+
raise RubySMB::Dcerpc::Error::WinregError, "Error returned when opening subkey #{sub_key}: "\
|
112
|
+
"#{WindowsError::Win32.find_by_retval(open_key_response.error_status.value).join(',')}"
|
113
|
+
end
|
114
|
+
|
115
|
+
open_key_response.phk_result
|
116
|
+
end
|
117
|
+
|
118
|
+
# Retrieve the data associated with the named value of a specified
|
119
|
+
# registry open key.
|
120
|
+
#
|
121
|
+
# @param handle [Ndr::NdrContextHandle] the handle for the key
|
122
|
+
# @param value_name [String] the name of the value
|
123
|
+
# @return [String] the data of the value entry
|
124
|
+
# @raise [RubySMB::Dcerpc::Error::InvalidPacket] if the response is not a QueryValueResponse packet
|
125
|
+
# @raise [RubySMB::Dcerpc::Error::WinregError] if the response error status is not ERROR_SUCCESS
|
126
|
+
def query_value(handle, value_name)
|
127
|
+
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
|
129
|
+
response = dcerpc_request(query_value_request_packet)
|
130
|
+
begin
|
131
|
+
query_value_response = RubySMB::Dcerpc::Winreg::QueryValueResponse.read(response)
|
132
|
+
rescue IOError
|
133
|
+
raise RubySMB::Dcerpc::Error::InvalidPacket, "Error reading the QueryValue response"
|
134
|
+
end
|
135
|
+
unless query_value_response.error_status == WindowsError::Win32::ERROR_SUCCESS
|
136
|
+
raise RubySMB::Dcerpc::Error::WinregError, "Error returned when reading value #{value_name}: "\
|
137
|
+
"#{WindowsError::Win32.find_by_retval(query_value_response.error_status.value).join(',')}"
|
138
|
+
end
|
139
|
+
|
140
|
+
query_value_request_packet = RubySMB::Dcerpc::Winreg::QueryValueRequest.new(hkey: handle, lp_value_name: value_name)
|
141
|
+
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
|
143
|
+
response = dcerpc_request(query_value_request_packet)
|
144
|
+
begin
|
145
|
+
query_value_response = RubySMB::Dcerpc::Winreg::QueryValueResponse.read(response)
|
146
|
+
rescue IOError
|
147
|
+
raise RubySMB::Dcerpc::Error::InvalidPacket, "Error reading the QueryValue response"
|
148
|
+
end
|
149
|
+
unless query_value_response.error_status == WindowsError::Win32::ERROR_SUCCESS
|
150
|
+
raise RubySMB::Dcerpc::Error::WinregError, "Error returned when reading value #{value_name}: "\
|
151
|
+
"#{WindowsError::Win32.find_by_retval(query_value_response.error_status.value).join(',')}"
|
152
|
+
end
|
153
|
+
|
154
|
+
query_value_response.data
|
155
|
+
end
|
156
|
+
|
157
|
+
# Close the handle to the registry key.
|
158
|
+
#
|
159
|
+
# @param handle [Ndr::NdrContextHandle] the handle for the key
|
160
|
+
# @return [WindowsError::Win32] the response error status
|
161
|
+
# @raise [RubySMB::Dcerpc::Error::InvalidPacket] if the response is not a CloseKeyResponse packet
|
162
|
+
# @raise [RubySMB::Dcerpc::Error::WinregError] if the response error status is not ERROR_SUCCESS
|
163
|
+
def close_key(handle)
|
164
|
+
close_key_request_packet = RubySMB::Dcerpc::Winreg::CloseKeyRequest.new(hkey: handle)
|
165
|
+
response = dcerpc_request(close_key_request_packet)
|
166
|
+
begin
|
167
|
+
close_key_response = RubySMB::Dcerpc::Winreg::CloseKeyResponse.read(response)
|
168
|
+
rescue IOError
|
169
|
+
raise RubySMB::Dcerpc::Error::InvalidPacket, "Error reading the CloseKey response"
|
170
|
+
end
|
171
|
+
unless close_key_response.error_status == WindowsError::Win32::ERROR_SUCCESS
|
172
|
+
raise RubySMB::Dcerpc::Error::WinregError, "Error returned when closing the key: "\
|
173
|
+
"#{WindowsError::Win32.find_by_retval(close_key_response.error_status.value).join(',')}"
|
174
|
+
end
|
175
|
+
|
176
|
+
close_key_response.error_status
|
177
|
+
end
|
178
|
+
|
179
|
+
# Retrive relevant information on the key that corresponds to the
|
180
|
+
# specified key handle.
|
181
|
+
#
|
182
|
+
# @param handle [Ndr::NdrContextHandle] the handle for the key
|
183
|
+
# @return [RubySMB::Dcerpc::Winreg::QueryInfoKeyResponse] the QueryInfoKeyResponse packet
|
184
|
+
# @raise [RubySMB::Dcerpc::Error::InvalidPacket] if the response is not a QueryInfoKeyResponse packet
|
185
|
+
# @raise [RubySMB::Dcerpc::Error::WinregError] if the response error status is not ERROR_SUCCESS
|
186
|
+
def query_info_key(handle)
|
187
|
+
query_info_key_request_packet = RubySMB::Dcerpc::Winreg::QueryInfoKeyRequest.new(hkey: handle)
|
188
|
+
response = dcerpc_request(query_info_key_request_packet)
|
189
|
+
begin
|
190
|
+
query_info_key_response = RubySMB::Dcerpc::Winreg::QueryInfoKeyResponse.read(response)
|
191
|
+
rescue IOError
|
192
|
+
raise RubySMB::Dcerpc::Error::InvalidPacket, "Error reading the query_infoKey response"
|
193
|
+
end
|
194
|
+
unless query_info_key_response.error_status == WindowsError::Win32::ERROR_SUCCESS
|
195
|
+
raise RubySMB::Dcerpc::Error::WinregError, "Error returned when querying information: "\
|
196
|
+
"#{WindowsError::Win32.find_by_retval(query_info_key_response.error_status.value).join(',')}"
|
197
|
+
end
|
198
|
+
|
199
|
+
query_info_key_response
|
200
|
+
end
|
201
|
+
|
202
|
+
# Enumerate the subkey at the specified index.
|
203
|
+
#
|
204
|
+
# @param handle [Ndr::NdrContextHandle] the handle for the key
|
205
|
+
# @param index [Numeric] the index of the subkey
|
206
|
+
# @return [String] the subkey name
|
207
|
+
# @raise [RubySMB::Dcerpc::Error::InvalidPacket] if the response is not a EnumKeyResponse packet
|
208
|
+
# @raise [RubySMB::Dcerpc::Error::WinregError] if the response error status is not ERROR_SUCCESS
|
209
|
+
def enum_key(handle, index)
|
210
|
+
enum_key_request_packet = RubySMB::Dcerpc::Winreg::EnumKeyRequest.new(hkey: handle, dw_index: index)
|
211
|
+
enum_key_request_packet.lpft_last_write_time = 0
|
212
|
+
enum_key_request_packet.lp_class.referent.buffer = 0
|
213
|
+
enum_key_request_packet.lp_name.buffer.referent.max_count = 256
|
214
|
+
response = dcerpc_request(enum_key_request_packet)
|
215
|
+
begin
|
216
|
+
enum_key_response = RubySMB::Dcerpc::Winreg::EnumKeyResponse.read(response)
|
217
|
+
rescue IOError
|
218
|
+
raise RubySMB::Dcerpc::Error::InvalidPacket, "Error reading the EnumKey response"
|
219
|
+
end
|
220
|
+
unless enum_key_response.error_status == WindowsError::Win32::ERROR_SUCCESS
|
221
|
+
raise RubySMB::Dcerpc::Error::WinregError, "Error returned when enumerating the key: "\
|
222
|
+
"#{WindowsError::Win32.find_by_retval(enum_key_response.error_status.value).join(',')}"
|
223
|
+
end
|
224
|
+
|
225
|
+
enum_key_response.lp_name.to_s
|
226
|
+
end
|
227
|
+
|
228
|
+
# Enumerate the value at the specified index for the specified registry key.
|
229
|
+
#
|
230
|
+
# @param handle [Ndr::NdrContextHandle] the handle for the key
|
231
|
+
# @param index [Numeric] the index of the subkey
|
232
|
+
# @return [String] the data of the value entry
|
233
|
+
# @raise [RubySMB::Dcerpc::Error::InvalidPacket] if the response is not a EnumValueResponse packet
|
234
|
+
# @raise [RubySMB::Dcerpc::Error::WinregError] if the response error status is not ERROR_SUCCESS
|
235
|
+
def enum_value(handle, index)
|
236
|
+
enum_value_request_packet = RubySMB::Dcerpc::Winreg::EnumValueRequest.new(hkey: handle, dw_index: index)
|
237
|
+
enum_value_request_packet.lp_data.referent_identifier = 0
|
238
|
+
enum_value_request_packet.lp_value_name.buffer.referent.max_count = 256
|
239
|
+
response = dcerpc_request(enum_value_request_packet)
|
240
|
+
begin
|
241
|
+
enum_value_response = RubySMB::Dcerpc::Winreg::EnumValueResponse.read(response)
|
242
|
+
rescue IOError
|
243
|
+
raise RubySMB::Dcerpc::Error::InvalidPacket, "Error reading the Enumvalue response"
|
244
|
+
end
|
245
|
+
unless enum_value_response.error_status == WindowsError::Win32::ERROR_SUCCESS
|
246
|
+
raise RubySMB::Dcerpc::Error::WinregError, "Error returned when enumerating values: "\
|
247
|
+
"#{WindowsError::Win32.find_by_retval(enum_value_response.error_status.value).join(',')}"
|
248
|
+
end
|
249
|
+
|
250
|
+
enum_value_response.lp_value_name.to_s
|
251
|
+
end
|
252
|
+
|
253
|
+
# Checks if the specified registry key exists. It returns true if it
|
254
|
+
# exists, false otherwise.
|
255
|
+
#
|
256
|
+
# @param key [String] the registry key to check
|
257
|
+
# @return [Boolean]
|
258
|
+
def has_registry_key?(key)
|
259
|
+
bind(endpoint: RubySMB::Dcerpc::Winreg)
|
260
|
+
|
261
|
+
root_key, sub_key = key.gsub(/\//, '\\').split('\\', 2)
|
262
|
+
begin
|
263
|
+
root_key_handle = open_root_key(root_key)
|
264
|
+
subkey_handle = open_key(root_key_handle, sub_key)
|
265
|
+
rescue RubySMB::Dcerpc::Error::WinregError
|
266
|
+
return false
|
267
|
+
end
|
268
|
+
close_key(subkey_handle)
|
269
|
+
return true
|
270
|
+
end
|
271
|
+
|
272
|
+
# Retrieve the data associated with the named value of a specified
|
273
|
+
# registry key.
|
274
|
+
#
|
275
|
+
# @param key [String] the registry key
|
276
|
+
# @param value_name [String] the name of the value to read
|
277
|
+
# @return [String] the data of the value entry
|
278
|
+
def read_registry_key_value(key, value_name)
|
279
|
+
bind(endpoint: RubySMB::Dcerpc::Winreg)
|
280
|
+
|
281
|
+
root_key, sub_key = key.gsub(/\//, '\\').split('\\', 2)
|
282
|
+
root_key_handle = open_root_key(root_key)
|
283
|
+
subkey_handle = open_key(root_key_handle, sub_key)
|
284
|
+
value = query_value(subkey_handle, value_name)
|
285
|
+
close_key(subkey_handle)
|
286
|
+
value
|
287
|
+
end
|
288
|
+
|
289
|
+
# Enumerate the subkeys of a specified registry key. If only a root key
|
290
|
+
# is provided, it enumerates its subkeys.
|
291
|
+
#
|
292
|
+
# @param key [String] the registry key
|
293
|
+
# @return [Array<String>] the subkeys
|
294
|
+
def enum_registry_key(key)
|
295
|
+
bind(endpoint: RubySMB::Dcerpc::Winreg)
|
296
|
+
|
297
|
+
root_key, sub_key = key.gsub(/\//, '\\').split('\\', 2)
|
298
|
+
root_key_handle = open_root_key(root_key)
|
299
|
+
subkey_handle = if sub_key.nil? || sub_key.empty?
|
300
|
+
root_key_handle
|
301
|
+
else
|
302
|
+
open_key(root_key_handle, sub_key)
|
303
|
+
end
|
304
|
+
query_info_key_response = query_info_key(subkey_handle)
|
305
|
+
key_count = query_info_key_response.lpc_sub_keys.to_i
|
306
|
+
enum_result = []
|
307
|
+
key_count.times do |i|
|
308
|
+
enum_result << enum_key(subkey_handle, i)
|
309
|
+
end
|
310
|
+
close_key(subkey_handle)
|
311
|
+
enum_result
|
312
|
+
end
|
313
|
+
|
314
|
+
# Enumerate the values for the specified registry key.
|
315
|
+
#
|
316
|
+
# @param key [String] the registry key
|
317
|
+
# @return [Array<String>] the values
|
318
|
+
def enum_registry_values(key)
|
319
|
+
bind(endpoint: RubySMB::Dcerpc::Winreg)
|
320
|
+
|
321
|
+
root_key, sub_key = key.gsub(/\//, '\\').split('\\', 2)
|
322
|
+
root_key_handle = open_root_key(root_key)
|
323
|
+
subkey_handle = if sub_key.nil? || sub_key.empty?
|
324
|
+
root_key_handle
|
325
|
+
else
|
326
|
+
open_key(root_key_handle, sub_key)
|
327
|
+
end
|
328
|
+
query_info_key_response = query_info_key(subkey_handle)
|
329
|
+
value_count = query_info_key_response.lpc_values.to_i
|
330
|
+
enum_result = []
|
331
|
+
value_count.times do |i|
|
332
|
+
enum_result << enum_value(subkey_handle, i)
|
333
|
+
end
|
334
|
+
close_key(subkey_handle)
|
335
|
+
enum_result
|
336
|
+
end
|
337
|
+
|
338
|
+
end
|
339
|
+
end
|
340
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module RubySMB
|
2
|
+
module Dcerpc
|
3
|
+
module Winreg
|
4
|
+
|
5
|
+
class RpcHkey < Ndr::NdrContextHandle; end
|
6
|
+
|
7
|
+
# This class represents a BaseRegCloseKey Request Packet as defined in
|
8
|
+
# [3.1.5.6 BaseRegCloseKey (Opnum 5)](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rrp/bc7545ff-0a54-4465-a95a-396b5c2995df)
|
9
|
+
class CloseKeyRequest < BinData::Record
|
10
|
+
attr_reader :opnum
|
11
|
+
|
12
|
+
endian :little
|
13
|
+
|
14
|
+
rpc_hkey :hkey
|
15
|
+
|
16
|
+
def initialize_instance
|
17
|
+
super
|
18
|
+
@opnum = REG_CLOSE_KEY
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module RubySMB
|
2
|
+
module Dcerpc
|
3
|
+
module Winreg
|
4
|
+
|
5
|
+
class RpcHkey < Ndr::NdrContextHandle; end
|
6
|
+
|
7
|
+
# This class represents a BaseRegCloseKey Response Packet as defined in
|
8
|
+
# [3.1.5.6 BaseRegCloseKey (Opnum 5)](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rrp/bc7545ff-0a54-4465-a95a-396b5c2995df)
|
9
|
+
class CloseKeyResponse < BinData::Record
|
10
|
+
attr_reader :opnum
|
11
|
+
|
12
|
+
endian :little
|
13
|
+
|
14
|
+
rpc_hkey :hkey
|
15
|
+
uint32 :error_status
|
16
|
+
|
17
|
+
def initialize_instance
|
18
|
+
super
|
19
|
+
@opnum = REG_CLOSE_KEY
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module RubySMB
|
2
|
+
module Dcerpc
|
3
|
+
module Winreg
|
4
|
+
|
5
|
+
class RpcHkey < Ndr::NdrContextHandle; end
|
6
|
+
|
7
|
+
# This class represents a BaseRegEnumKey Request Packet as defined in
|
8
|
+
# [3.1.5.10 BaseRegEnumKey (Opnum 9)](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rrp/668627e9-e0eb-4ab1-911f-0af589beeac3)
|
9
|
+
class EnumKeyRequest < BinData::Record
|
10
|
+
attr_reader :opnum
|
11
|
+
|
12
|
+
endian :little
|
13
|
+
|
14
|
+
rpc_hkey :hkey
|
15
|
+
uint32 :dw_index
|
16
|
+
rrp_unicode_string :lp_name
|
17
|
+
string :pad1, length: -> { pad_length1 }
|
18
|
+
prrp_unicode_string :lp_class
|
19
|
+
string :pad2, length: -> { pad_length2 }
|
20
|
+
ndr_lp_file_time :lpft_last_write_time
|
21
|
+
|
22
|
+
def initialize_instance
|
23
|
+
super
|
24
|
+
@opnum = REG_ENUM_KEY
|
25
|
+
end
|
26
|
+
|
27
|
+
# Determines the correct length for the padding in front of
|
28
|
+
# #lp_class. It should always force a 4-byte alignment.
|
29
|
+
def pad_length1
|
30
|
+
offset = (lp_name.abs_offset + lp_name.to_binary_s.length) % 4
|
31
|
+
(4 - offset) % 4
|
32
|
+
end
|
33
|
+
|
34
|
+
# Determines the correct length for the padding in front of
|
35
|
+
# #lpft_last_write_time. It should always force a 4-byte alignment.
|
36
|
+
def pad_length2
|
37
|
+
offset = (lp_class.abs_offset + lp_class.to_binary_s.length) % 4
|
38
|
+
(4 - offset) % 4
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|