ruby_smb 1.0.0 → 1.1.0
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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data/.travis.yml +4 -1
- data/README.md +35 -47
- data/examples/enum_registry_key.rb +28 -0
- data/examples/enum_registry_values.rb +30 -0
- data/examples/pipes.rb +2 -1
- data/examples/read_registry_key_value.rb +32 -0
- data/lib/ruby_smb/client/authentication.rb +43 -25
- data/lib/ruby_smb/client/echo.rb +20 -2
- data/lib/ruby_smb/client/negotiation.rb +27 -12
- data/lib/ruby_smb/client/tree_connect.rb +20 -14
- data/lib/ruby_smb/client/utils.rb +2 -2
- data/lib/ruby_smb/client/winreg.rb +46 -0
- data/lib/ruby_smb/client.rb +28 -4
- 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/net_share_enum_all.rb +9 -0
- data/lib/ruby_smb/dcerpc/srvsvc.rb +10 -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/dcerpc/winreg.rb +340 -0
- data/lib/ruby_smb/dcerpc.rb +38 -0
- data/lib/ruby_smb/dispatcher/socket.rb +3 -1
- data/lib/ruby_smb/error.rb +40 -1
- data/lib/ruby_smb/generic_packet.rb +33 -4
- data/lib/ruby_smb/smb1/file.rb +67 -11
- 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 +2 -1
- data/lib/ruby_smb/smb1/packet/session_setup_request.rb +2 -5
- data/lib/ruby_smb/smb1/packet/session_setup_response.rb +2 -1
- 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 +2 -5
- data/lib/ruby_smb/smb1/packet/write_andx_response.rb +2 -1
- data/lib/ruby_smb/smb1/pipe.rb +86 -5
- data/lib/ruby_smb/smb1/tree.rb +40 -2
- data/lib/ruby_smb/smb2/file.rb +97 -1
- 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/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 +2 -5
- data/lib/ruby_smb/smb2/packet/negotiate_response.rb +2 -1
- 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/tree_connect_request.rb +2 -5
- data/lib/ruby_smb/smb2/packet/tree_connect_response.rb +8 -2
- 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 +98 -11
- data/lib/ruby_smb/smb2/tree.rb +44 -6
- data/lib/ruby_smb/version.rb +1 -1
- data/lib/ruby_smb.rb +0 -1
- data/ruby_smb.gemspec +3 -3
- data/spec/lib/ruby_smb/client_spec.rb +271 -11
- 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 +3 -1
- 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/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/file_spec.rb +295 -2
- data/spec/lib/ruby_smb/smb2/packet/error_packet_spec.rb +78 -0
- data/spec/lib/ruby_smb/smb2/packet/query_directory_response_spec.rb +8 -0
- data/spec/lib/ruby_smb/smb2/packet/tree_connect_response_spec.rb +8 -0
- data/spec/lib/ruby_smb/smb2/pipe_spec.rb +322 -145
- data/spec/lib/ruby_smb/smb2/tree_spec.rb +214 -0
- data.tar.gz.sig +0 -0
- metadata +70 -11
- 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
|
@@ -0,0 +1,710 @@
|
|
|
1
|
+
RSpec.describe RubySMB::Dcerpc::Winreg do
|
|
2
|
+
let(:winreg) do
|
|
3
|
+
RubySMB::SMB1::Pipe.new(
|
|
4
|
+
tree: double('Tree'),
|
|
5
|
+
response: RubySMB::SMB1::Packet::NtCreateAndxResponse.new,
|
|
6
|
+
name: 'winreg'
|
|
7
|
+
)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
describe '#open_root_key' do
|
|
11
|
+
let(:root_key_request_packet) { double('Root Key Request Packet') }
|
|
12
|
+
let(:response) { double('Response') }
|
|
13
|
+
let(:root_key_response_packet) { double('Root Key Response Packet') }
|
|
14
|
+
let(:ph_key) { double('PHKEY') }
|
|
15
|
+
before :example do
|
|
16
|
+
allow(described_class::OpenRootKeyRequest).to receive(:new).and_return(root_key_request_packet)
|
|
17
|
+
allow(winreg).to receive(:dcerpc_request).and_return(response)
|
|
18
|
+
allow(described_class::OpenRootKeyResponse).to receive(:read).and_return(root_key_response_packet)
|
|
19
|
+
allow(root_key_response_packet).to receive_messages(
|
|
20
|
+
:error_status => WindowsError::Win32::ERROR_SUCCESS,
|
|
21
|
+
:ph_key => ph_key
|
|
22
|
+
)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
context 'when the root key is unknown' do
|
|
26
|
+
it 'raises an ArgumentError exception' do
|
|
27
|
+
expect { winreg.open_root_key('UNKNOWN') }.to raise_error(ArgumentError)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it 'create the expected OpenRootKeyRequest packet' do
|
|
32
|
+
winreg.open_root_key('HKLM')
|
|
33
|
+
expect(described_class::OpenRootKeyRequest).to have_received(:new).with(opnum: described_class::OPEN_HKLM)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it 'sends the expected dcerpc request' do
|
|
37
|
+
winreg.open_root_key('HKLM')
|
|
38
|
+
expect(winreg).to have_received(:dcerpc_request).with(root_key_request_packet)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it 'creates a OpenRootKeyResponse structure from the expected dcerpc response' do
|
|
42
|
+
winreg.open_root_key('HKLM')
|
|
43
|
+
expect(described_class::OpenRootKeyResponse).to have_received(:read).with(response)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
context 'when an IOError occurs while parsing the response' do
|
|
47
|
+
it 'raises a RubySMB::Dcerpc::Error::InvalidPacket' do
|
|
48
|
+
allow(described_class::OpenRootKeyResponse).to receive(:read).and_raise(IOError)
|
|
49
|
+
expect { winreg.open_root_key('HKLM') }.to raise_error(RubySMB::Dcerpc::Error::InvalidPacket)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
context 'when the response error status is not WindowsError::Win32::ERROR_SUCCESS' do
|
|
54
|
+
it 'raises a RubySMB::Dcerpc::Error::WinregError' do
|
|
55
|
+
allow(root_key_response_packet).to receive(:error_status).and_return(WindowsError::Win32::ERROR_INVALID_DATA)
|
|
56
|
+
expect { winreg.open_root_key('HKLM') }.to raise_error(RubySMB::Dcerpc::Error::WinregError)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it 'returns the expected handler' do
|
|
61
|
+
expect(winreg.open_root_key('HKLM')).to eq(ph_key)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
describe '#open_key' do
|
|
66
|
+
let(:handle) { double('Handle') }
|
|
67
|
+
let(:sub_key) { double('Sub-key') }
|
|
68
|
+
let(:openkey_request_packet) { double('OpenKey Request Packet') }
|
|
69
|
+
let(:regsam) { double('Regsam') }
|
|
70
|
+
let(:response) { double('Response') }
|
|
71
|
+
let(:open_key_response) { double('OpenKey Response') }
|
|
72
|
+
let(:phk_result) { double('Phk Result') }
|
|
73
|
+
before :example do
|
|
74
|
+
allow(described_class::OpenKeyRequest).to receive(:new).and_return(openkey_request_packet)
|
|
75
|
+
allow(openkey_request_packet).to receive(:sam_desired).and_return(regsam)
|
|
76
|
+
allow(regsam).to receive_messages(
|
|
77
|
+
:read_control= => nil,
|
|
78
|
+
:key_query_value= => nil,
|
|
79
|
+
:key_enumerate_sub_keys= => nil,
|
|
80
|
+
:key_notify= => nil,
|
|
81
|
+
)
|
|
82
|
+
allow(winreg).to receive(:dcerpc_request).and_return(response)
|
|
83
|
+
allow(described_class::OpenKeyResponse).to receive(:read).and_return(open_key_response)
|
|
84
|
+
allow(open_key_response).to receive_messages(
|
|
85
|
+
:error_status => WindowsError::Win32::ERROR_SUCCESS,
|
|
86
|
+
:phk_result => phk_result
|
|
87
|
+
)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
it 'create the expected OpenKeyRequest packet' do
|
|
91
|
+
winreg.open_key(handle, sub_key)
|
|
92
|
+
expect(described_class::OpenKeyRequest).to have_received(:new).with(hkey: handle, lp_sub_key: sub_key)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
it 'sets the expected user rights on the request packet' do
|
|
96
|
+
winreg.open_key(handle, sub_key)
|
|
97
|
+
expect(regsam).to have_received(:read_control=).with(1)
|
|
98
|
+
expect(regsam).to have_received(:key_query_value=).with(1)
|
|
99
|
+
expect(regsam).to have_received(:key_enumerate_sub_keys=).with(1)
|
|
100
|
+
expect(regsam).to have_received(:key_notify=).with(1)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
it 'sends the expected dcerpc request' do
|
|
104
|
+
winreg.open_key(handle, sub_key)
|
|
105
|
+
expect(winreg).to have_received(:dcerpc_request).with(openkey_request_packet)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
it 'creates a OpenKeyResponse structure from the expected dcerpc response' do
|
|
109
|
+
winreg.open_key(handle, sub_key)
|
|
110
|
+
expect(described_class::OpenKeyResponse).to have_received(:read).with(response)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
context 'when an IOError occurs while parsing the response' do
|
|
114
|
+
it 'raises a RubySMB::Dcerpc::Error::InvalidPacket' do
|
|
115
|
+
allow(described_class::OpenKeyResponse).to receive(:read).and_raise(IOError)
|
|
116
|
+
expect { winreg.open_key(handle, sub_key) }.to raise_error(RubySMB::Dcerpc::Error::InvalidPacket)
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
context 'when the response error status is not WindowsError::Win32::ERROR_SUCCESS' do
|
|
121
|
+
it 'raises a RubySMB::Dcerpc::Error::WinregError' do
|
|
122
|
+
allow(open_key_response).to receive(:error_status).and_return(WindowsError::Win32::ERROR_INVALID_DATA)
|
|
123
|
+
expect { winreg.open_key(handle, sub_key) }.to raise_error(RubySMB::Dcerpc::Error::WinregError)
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
it 'returns the expected handler' do
|
|
128
|
+
expect(winreg.open_key(handle, sub_key)).to eq(phk_result)
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
describe '#query_value' do
|
|
133
|
+
let(:handle) { double('Handle') }
|
|
134
|
+
let(:value_name) { double('Value Name') }
|
|
135
|
+
let(:query_value_request_packet1) { double('Query Value Request Packet #1') }
|
|
136
|
+
let(:query_value_request_packet2) { double('Query Value Request Packet #2') }
|
|
137
|
+
let(:lp_data1) { double('LpData #1') }
|
|
138
|
+
let(:lp_data2) { double('LpData #2') }
|
|
139
|
+
let(:response1) { double('Response #1') }
|
|
140
|
+
let(:response2) { double('Response #2') }
|
|
141
|
+
let(:query_value_response1) { double('Query Value Response #1') }
|
|
142
|
+
let(:query_value_response2) { double('Query Value Response #2') }
|
|
143
|
+
let(:data) { double('Data') }
|
|
144
|
+
let(:lpcb_data) { double('LpcbData') }
|
|
145
|
+
let(:lpcb_data_referent) { double('Lpcb Data Referent') }
|
|
146
|
+
before :example do
|
|
147
|
+
first_request = true
|
|
148
|
+
allow(described_class::QueryValueRequest).to receive(:new) do
|
|
149
|
+
if first_request
|
|
150
|
+
first_request = false
|
|
151
|
+
query_value_request_packet1
|
|
152
|
+
else
|
|
153
|
+
query_value_request_packet2
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
allow(query_value_request_packet1).to receive(:lp_data).and_return(lp_data1)
|
|
157
|
+
allow(query_value_request_packet2).to receive_messages(
|
|
158
|
+
:lp_data => lp_data2,
|
|
159
|
+
:lpcb_data= => nil
|
|
160
|
+
)
|
|
161
|
+
allow(lp_data1).to receive(:referent_identifier=)
|
|
162
|
+
allow(lp_data2).to receive(:max_count=)
|
|
163
|
+
allow(winreg).to receive(:dcerpc_request).with(query_value_request_packet1).and_return(response1)
|
|
164
|
+
allow(winreg).to receive(:dcerpc_request).with(query_value_request_packet2).and_return(response2)
|
|
165
|
+
allow(described_class::QueryValueResponse).to receive(:read).with(response1).and_return(query_value_response1)
|
|
166
|
+
allow(described_class::QueryValueResponse).to receive(:read).with(response2).and_return(query_value_response2)
|
|
167
|
+
allow(query_value_response1).to receive(:error_status).and_return(WindowsError::Win32::ERROR_SUCCESS)
|
|
168
|
+
allow(query_value_response2).to receive_messages(
|
|
169
|
+
:error_status => WindowsError::Win32::ERROR_SUCCESS,
|
|
170
|
+
:data => data
|
|
171
|
+
)
|
|
172
|
+
allow(query_value_response1).to receive(:lpcb_data).and_return(lpcb_data)
|
|
173
|
+
allow(lpcb_data).to receive(:referent).and_return(lpcb_data_referent)
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
it 'create the expected QueryValueRequest packets' do
|
|
177
|
+
winreg.query_value(handle, value_name)
|
|
178
|
+
expect(described_class::QueryValueRequest).to have_received(:new).with(hkey: handle, lp_value_name: value_name).twice
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
it 'sets the expected user rights on the first request packet' do
|
|
182
|
+
winreg.query_value(handle, value_name)
|
|
183
|
+
expect(lp_data1).to have_received(:referent_identifier=).with(0)
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
it 'sets the expected user rights on the second request packet' do
|
|
187
|
+
winreg.query_value(handle, value_name)
|
|
188
|
+
expect(lp_data2).to have_received(:max_count=).with(lpcb_data_referent)
|
|
189
|
+
expect(query_value_request_packet2).to have_received(:lpcb_data=).with(lpcb_data)
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
it 'sends the expected dcerpc requests' do
|
|
193
|
+
winreg.query_value(handle, value_name)
|
|
194
|
+
expect(winreg).to have_received(:dcerpc_request).with(query_value_request_packet1).once.ordered
|
|
195
|
+
expect(winreg).to have_received(:dcerpc_request).with(query_value_request_packet2).once.ordered
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
context 'when receiving the first response' do
|
|
199
|
+
it 'creates a QueryValueResponse structure from the expected dcerpc response' do
|
|
200
|
+
winreg.query_value(handle, value_name)
|
|
201
|
+
expect(described_class::QueryValueResponse).to have_received(:read).with(response1)
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
context 'when an IOError occurs while parsing the response' do
|
|
205
|
+
it 'raises a RubySMB::Dcerpc::Error::InvalidPacket' do
|
|
206
|
+
allow(described_class::QueryValueResponse).to receive(:read).with(response1).and_raise(IOError)
|
|
207
|
+
expect { winreg.query_value(handle, value_name) }.to raise_error(RubySMB::Dcerpc::Error::InvalidPacket)
|
|
208
|
+
end
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
context 'when the first response error status is not WindowsError::Win32::ERROR_SUCCESS' do
|
|
212
|
+
it 'raises a RubySMB::Dcerpc::Error::WinregError' do
|
|
213
|
+
allow(query_value_response1).to receive(:error_status).and_return(WindowsError::Win32::ERROR_INVALID_DATA)
|
|
214
|
+
expect { winreg.query_value(handle, value_name) }.to raise_error(RubySMB::Dcerpc::Error::WinregError)
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
context 'when receiving the second response' do
|
|
220
|
+
it 'creates a QueryValueResponse structure from the expected dcerpc response' do
|
|
221
|
+
winreg.query_value(handle, value_name)
|
|
222
|
+
expect(described_class::QueryValueResponse).to have_received(:read).with(response2)
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
context 'when an IOError occurs while parsing the response' do
|
|
226
|
+
it 'raises a RubySMB::Dcerpc::Error::InvalidPacket' do
|
|
227
|
+
allow(described_class::QueryValueResponse).to receive(:read).with(response2).and_raise(IOError)
|
|
228
|
+
expect { winreg.query_value(handle, value_name) }.to raise_error(RubySMB::Dcerpc::Error::InvalidPacket)
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
context 'when the first response error status is not WindowsError::Win32::ERROR_SUCCESS' do
|
|
233
|
+
it 'raises a RubySMB::Dcerpc::Error::WinregError' do
|
|
234
|
+
allow(query_value_response2).to receive(:error_status).and_return(WindowsError::Win32::ERROR_INVALID_DATA)
|
|
235
|
+
expect { winreg.query_value(handle, value_name) }.to raise_error(RubySMB::Dcerpc::Error::WinregError)
|
|
236
|
+
end
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
it 'returns the expected response data' do
|
|
241
|
+
expect(winreg.query_value(handle, value_name)).to eq(data)
|
|
242
|
+
end
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
describe '#close_key' do
|
|
246
|
+
let(:handle) { double('Handle') }
|
|
247
|
+
let(:close_key_request_packet) { double('CloseKey Request Packet') }
|
|
248
|
+
let(:response) { double('Response') }
|
|
249
|
+
let(:close_key_response) { double('CloseKey Response') }
|
|
250
|
+
before :example do
|
|
251
|
+
allow(described_class::CloseKeyRequest).to receive(:new).and_return(close_key_request_packet)
|
|
252
|
+
allow(winreg).to receive(:dcerpc_request).and_return(response)
|
|
253
|
+
allow(described_class::CloseKeyResponse).to receive(:read).and_return(close_key_response)
|
|
254
|
+
allow(close_key_response).to receive(:error_status).and_return(WindowsError::Win32::ERROR_SUCCESS)
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
it 'create the expected CloseKeyRequest packet' do
|
|
258
|
+
winreg.close_key(handle)
|
|
259
|
+
expect(described_class::CloseKeyRequest).to have_received(:new).with(hkey: handle)
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
it 'sends the expected dcerpc request' do
|
|
263
|
+
winreg.close_key(handle)
|
|
264
|
+
expect(winreg).to have_received(:dcerpc_request).with(close_key_request_packet)
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
it 'creates a CloseKeyResponse structure from the expected dcerpc response' do
|
|
268
|
+
winreg.close_key(handle)
|
|
269
|
+
expect(described_class::CloseKeyResponse).to have_received(:read).with(response)
|
|
270
|
+
end
|
|
271
|
+
|
|
272
|
+
context 'when an IOError occurs while parsing the response' do
|
|
273
|
+
it 'raises a RubySMB::Dcerpc::Error::InvalidPacket' do
|
|
274
|
+
allow(described_class::CloseKeyResponse).to receive(:read).and_raise(IOError)
|
|
275
|
+
expect { winreg.close_key(handle) }.to raise_error(RubySMB::Dcerpc::Error::InvalidPacket)
|
|
276
|
+
end
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
context 'when the response error status is not WindowsError::Win32::ERROR_SUCCESS' do
|
|
280
|
+
it 'raises a RubySMB::Dcerpc::Error::WinregError' do
|
|
281
|
+
allow(close_key_response).to receive(:error_status).and_return(WindowsError::Win32::ERROR_INVALID_DATA)
|
|
282
|
+
expect { winreg.close_key(handle) }.to raise_error(RubySMB::Dcerpc::Error::WinregError)
|
|
283
|
+
end
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
it 'returns the expected error status' do
|
|
287
|
+
expect(winreg.close_key(handle)).to eq(WindowsError::Win32::ERROR_SUCCESS)
|
|
288
|
+
end
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
describe '#query_info_key' do
|
|
292
|
+
let(:handle) { double('Handle') }
|
|
293
|
+
let(:query_info_key_request_packet) { double('CloseKey Request Packet') }
|
|
294
|
+
let(:response) { double('Response') }
|
|
295
|
+
let(:query_info_key_response) { double('CloseKey Response') }
|
|
296
|
+
before :example do
|
|
297
|
+
allow(described_class::QueryInfoKeyRequest).to receive(:new).and_return(query_info_key_request_packet)
|
|
298
|
+
allow(winreg).to receive(:dcerpc_request).and_return(response)
|
|
299
|
+
allow(described_class::QueryInfoKeyResponse).to receive(:read).and_return(query_info_key_response)
|
|
300
|
+
allow(query_info_key_response).to receive(:error_status).and_return(WindowsError::Win32::ERROR_SUCCESS)
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
it 'create the expected QueryInfoKeyRequest packet' do
|
|
304
|
+
winreg.query_info_key(handle)
|
|
305
|
+
expect(described_class::QueryInfoKeyRequest).to have_received(:new).with(hkey: handle)
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
it 'sends the expected dcerpc request' do
|
|
309
|
+
winreg.query_info_key(handle)
|
|
310
|
+
expect(winreg).to have_received(:dcerpc_request).with(query_info_key_request_packet)
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
it 'creates a QueryInfoKeyResponse structure from the expected dcerpc response' do
|
|
314
|
+
winreg.query_info_key(handle)
|
|
315
|
+
expect(described_class::QueryInfoKeyResponse).to have_received(:read).with(response)
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
context 'when an IOError occurs while parsing the response' do
|
|
319
|
+
it 'raises a RubySMB::Dcerpc::Error::InvalidPacket' do
|
|
320
|
+
allow(described_class::QueryInfoKeyResponse).to receive(:read).and_raise(IOError)
|
|
321
|
+
expect { winreg.query_info_key(handle) }.to raise_error(RubySMB::Dcerpc::Error::InvalidPacket)
|
|
322
|
+
end
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
context 'when the response error status is not WindowsError::Win32::ERROR_SUCCESS' do
|
|
326
|
+
it 'raises a RubySMB::Dcerpc::Error::WinregError' do
|
|
327
|
+
allow(query_info_key_response).to receive(:error_status).and_return(WindowsError::Win32::ERROR_INVALID_DATA)
|
|
328
|
+
expect { winreg.query_info_key(handle) }.to raise_error(RubySMB::Dcerpc::Error::WinregError)
|
|
329
|
+
end
|
|
330
|
+
end
|
|
331
|
+
|
|
332
|
+
it 'returns the expected response' do
|
|
333
|
+
expect(winreg.query_info_key(handle)).to eq(query_info_key_response)
|
|
334
|
+
end
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
describe '#enum_key' do
|
|
338
|
+
let(:handle) { double('Handle') }
|
|
339
|
+
let(:index) { double('Index') }
|
|
340
|
+
let(:enum_key_request_packet) { double('enum_key Request Packet') }
|
|
341
|
+
let(:lp_class) { double('Lp Class') }
|
|
342
|
+
let(:lp_name) { double('Lp Name') }
|
|
343
|
+
let(:buffer) { double('Buffer') }
|
|
344
|
+
let(:lp_class_buffer_referent) { double('Lp Class buffer referent') }
|
|
345
|
+
let(:lp_name_buffer_referent) { double('Lp Name buffer referent') }
|
|
346
|
+
let(:response) { double('Response') }
|
|
347
|
+
let(:enum_key_response) { double('enum_key Response') }
|
|
348
|
+
let(:result_str) { double('Result String') }
|
|
349
|
+
before :example do
|
|
350
|
+
allow(described_class::EnumKeyRequest).to receive(:new).and_return(enum_key_request_packet)
|
|
351
|
+
allow(enum_key_request_packet).to receive_messages(
|
|
352
|
+
:lpft_last_write_time= => nil,
|
|
353
|
+
:lp_class => lp_class,
|
|
354
|
+
:lp_name => lp_name
|
|
355
|
+
)
|
|
356
|
+
allow(lp_class).to receive(:referent).and_return(lp_class_buffer_referent)
|
|
357
|
+
allow(lp_name).to receive(:buffer).and_return(buffer)
|
|
358
|
+
allow(buffer).to receive(:referent).and_return(lp_name_buffer_referent)
|
|
359
|
+
allow(lp_class_buffer_referent).to receive(:buffer=)
|
|
360
|
+
allow(lp_name_buffer_referent).to receive(:max_count=)
|
|
361
|
+
allow(winreg).to receive(:dcerpc_request).and_return(response)
|
|
362
|
+
allow(described_class::EnumKeyResponse).to receive(:read).and_return(enum_key_response)
|
|
363
|
+
allow(enum_key_response).to receive(:error_status).and_return(WindowsError::Win32::ERROR_SUCCESS)
|
|
364
|
+
allow(enum_key_response).to receive_message_chain(:lp_name, :to_s => result_str)
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
it 'create the expected EnumKeyRequest packet' do
|
|
368
|
+
winreg.enum_key(handle, index)
|
|
369
|
+
expect(described_class::EnumKeyRequest).to have_received(:new).with(hkey: handle, dw_index: index)
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
it 'sets the expected user rights on the request packet' do
|
|
373
|
+
winreg.enum_key(handle, index)
|
|
374
|
+
expect(enum_key_request_packet).to have_received(:lpft_last_write_time=).with(0)
|
|
375
|
+
expect(lp_class_buffer_referent).to have_received(:buffer=).with(0)
|
|
376
|
+
expect(lp_name_buffer_referent).to have_received(:max_count=).with(256)
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
it 'sends the expected dcerpc request' do
|
|
380
|
+
winreg.enum_key(handle, index)
|
|
381
|
+
expect(winreg).to have_received(:dcerpc_request).with(enum_key_request_packet)
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
it 'creates a EnumKeyResponse structure from the expected dcerpc response' do
|
|
385
|
+
winreg.enum_key(handle, index)
|
|
386
|
+
expect(described_class::EnumKeyResponse).to have_received(:read).with(response)
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
context 'when an IOError occurs while parsing the response' do
|
|
390
|
+
it 'raises a RubySMB::Dcerpc::Error::InvalidPacket' do
|
|
391
|
+
allow(described_class::EnumKeyResponse).to receive(:read).and_raise(IOError)
|
|
392
|
+
expect { winreg.enum_key(handle, index) }.to raise_error(RubySMB::Dcerpc::Error::InvalidPacket)
|
|
393
|
+
end
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
context 'when the response error status is not WindowsError::Win32::ERROR_SUCCESS' do
|
|
397
|
+
it 'raises a RubySMB::Dcerpc::Error::WinregError' do
|
|
398
|
+
allow(enum_key_response).to receive(:error_status).and_return(WindowsError::Win32::ERROR_INVALID_DATA)
|
|
399
|
+
expect { winreg.enum_key(handle, index) }.to raise_error(RubySMB::Dcerpc::Error::WinregError)
|
|
400
|
+
end
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
it 'returns the expected key name' do
|
|
404
|
+
expect(winreg.enum_key(handle, index)).to eq(result_str)
|
|
405
|
+
end
|
|
406
|
+
end
|
|
407
|
+
|
|
408
|
+
describe '#enum_value' do
|
|
409
|
+
let(:handle) { double('Handle') }
|
|
410
|
+
let(:index) { double('Index') }
|
|
411
|
+
let(:enum_value_request_packet) { double('EnumValue Request Packet') }
|
|
412
|
+
let(:lp_value_name) { double('Lp Value Name') }
|
|
413
|
+
let(:lp_data) { double('Lp Data') }
|
|
414
|
+
let(:buffer) { double('Buffer') }
|
|
415
|
+
let(:referent) { double('Referent') }
|
|
416
|
+
let(:response) { double('Response') }
|
|
417
|
+
let(:enum_value_response) { double('EnumValue Response') }
|
|
418
|
+
let(:result_str) { double('Result String') }
|
|
419
|
+
before :example do
|
|
420
|
+
allow(described_class::EnumValueRequest).to receive(:new).and_return(enum_value_request_packet)
|
|
421
|
+
allow(enum_value_request_packet).to receive_messages(
|
|
422
|
+
:lp_value_name => lp_value_name,
|
|
423
|
+
:lp_data => lp_data
|
|
424
|
+
)
|
|
425
|
+
allow(lp_value_name).to receive(:buffer).and_return(buffer)
|
|
426
|
+
allow(buffer).to receive(:referent).and_return(referent)
|
|
427
|
+
allow(referent).to receive(:max_count=)
|
|
428
|
+
allow(lp_data).to receive(:referent_identifier=)
|
|
429
|
+
allow(winreg).to receive(:dcerpc_request).and_return(response)
|
|
430
|
+
allow(described_class::EnumValueResponse).to receive(:read).and_return(enum_value_response)
|
|
431
|
+
allow(enum_value_response).to receive(:error_status).and_return(WindowsError::Win32::ERROR_SUCCESS)
|
|
432
|
+
allow(enum_value_response).to receive_message_chain(:lp_value_name, :to_s => result_str)
|
|
433
|
+
end
|
|
434
|
+
|
|
435
|
+
it 'create the expected EnumValueRequest packet' do
|
|
436
|
+
winreg.enum_value(handle, index)
|
|
437
|
+
expect(described_class::EnumValueRequest).to have_received(:new).with(hkey: handle, dw_index: index)
|
|
438
|
+
end
|
|
439
|
+
|
|
440
|
+
it 'sets the expected user rights on the request packet' do
|
|
441
|
+
winreg.enum_value(handle, index)
|
|
442
|
+
expect(referent).to have_received(:max_count=).with(256)
|
|
443
|
+
expect(lp_data).to have_received(:referent_identifier=).with(0)
|
|
444
|
+
end
|
|
445
|
+
|
|
446
|
+
it 'sends the expected dcerpc request' do
|
|
447
|
+
winreg.enum_value(handle, index)
|
|
448
|
+
expect(winreg).to have_received(:dcerpc_request).with(enum_value_request_packet)
|
|
449
|
+
end
|
|
450
|
+
|
|
451
|
+
it 'creates a EnumValueResponse structure from the expected dcerpc response' do
|
|
452
|
+
winreg.enum_value(handle, index)
|
|
453
|
+
expect(described_class::EnumValueResponse).to have_received(:read).with(response)
|
|
454
|
+
end
|
|
455
|
+
|
|
456
|
+
context 'when an IOError occurs while parsing the response' do
|
|
457
|
+
it 'raises a RubySMB::Dcerpc::Error::InvalidPacket' do
|
|
458
|
+
allow(described_class::EnumValueResponse).to receive(:read).and_raise(IOError)
|
|
459
|
+
expect { winreg.enum_value(handle, index) }.to raise_error(RubySMB::Dcerpc::Error::InvalidPacket)
|
|
460
|
+
end
|
|
461
|
+
end
|
|
462
|
+
|
|
463
|
+
context 'when the response error status is not WindowsError::Win32::ERROR_SUCCESS' do
|
|
464
|
+
it 'raises a RubySMB::Dcerpc::Error::WinregError' do
|
|
465
|
+
allow(enum_value_response).to receive(:error_status).and_return(WindowsError::Win32::ERROR_INVALID_DATA)
|
|
466
|
+
expect { winreg.enum_value(handle, index) }.to raise_error(RubySMB::Dcerpc::Error::WinregError)
|
|
467
|
+
end
|
|
468
|
+
end
|
|
469
|
+
|
|
470
|
+
it 'returns the expected key name' do
|
|
471
|
+
expect(winreg.enum_value(handle, index)).to eq(result_str)
|
|
472
|
+
end
|
|
473
|
+
end
|
|
474
|
+
|
|
475
|
+
describe '#has_registry_key?' do
|
|
476
|
+
let(:root_key) { 'HKLM' }
|
|
477
|
+
let(:sub_key) { 'my\\sub\\key\\path' }
|
|
478
|
+
let(:key) { "#{root_key}\\#{sub_key}" }
|
|
479
|
+
let(:root_key_handle) { double('Root Key Handle') }
|
|
480
|
+
let(:subkey_handle) { double('Subkey Handle') }
|
|
481
|
+
before :example do
|
|
482
|
+
allow(winreg).to receive_messages(
|
|
483
|
+
:bind => nil,
|
|
484
|
+
:open_root_key => root_key_handle,
|
|
485
|
+
:open_key => subkey_handle,
|
|
486
|
+
:close_key => nil
|
|
487
|
+
)
|
|
488
|
+
end
|
|
489
|
+
|
|
490
|
+
it 'binds a DCERPC connection to the expected remote endpoint' do
|
|
491
|
+
winreg.has_registry_key?(key)
|
|
492
|
+
expect(winreg).to have_received(:bind).with(endpoint: RubySMB::Dcerpc::Winreg)
|
|
493
|
+
end
|
|
494
|
+
|
|
495
|
+
it 'opens the expected root key' do
|
|
496
|
+
winreg.has_registry_key?(key)
|
|
497
|
+
expect(winreg).to have_received(:open_root_key).with(root_key)
|
|
498
|
+
end
|
|
499
|
+
|
|
500
|
+
it 'opens the expected registry key' do
|
|
501
|
+
winreg.has_registry_key?(key)
|
|
502
|
+
expect(winreg).to have_received(:open_key).with(root_key_handle, sub_key)
|
|
503
|
+
end
|
|
504
|
+
|
|
505
|
+
context 'when a WinregError occurs while opening the root key' do
|
|
506
|
+
it 'returns false' do
|
|
507
|
+
allow(winreg).to receive(:open_root_key).and_raise(RubySMB::Dcerpc::Error::WinregError)
|
|
508
|
+
expect(winreg.has_registry_key?(key)).to be false
|
|
509
|
+
end
|
|
510
|
+
end
|
|
511
|
+
|
|
512
|
+
context 'when a WinregError occurs while opening the registry key' do
|
|
513
|
+
it 'returns false' do
|
|
514
|
+
allow(winreg).to receive(:open_key).and_raise(RubySMB::Dcerpc::Error::WinregError)
|
|
515
|
+
expect(winreg.has_registry_key?(key)).to be false
|
|
516
|
+
end
|
|
517
|
+
end
|
|
518
|
+
|
|
519
|
+
it 'closes the key' do
|
|
520
|
+
winreg.has_registry_key?(key)
|
|
521
|
+
expect(winreg).to have_received(:close_key).with(subkey_handle)
|
|
522
|
+
end
|
|
523
|
+
|
|
524
|
+
it 'returns true when no error occurs' do
|
|
525
|
+
expect(winreg.has_registry_key?(key)).to be true
|
|
526
|
+
end
|
|
527
|
+
end
|
|
528
|
+
|
|
529
|
+
describe '#read_registry_key_value' do
|
|
530
|
+
let(:root_key) { 'HKLM' }
|
|
531
|
+
let(:sub_key) { 'my\\sub\\key\\path' }
|
|
532
|
+
let(:key) { "#{root_key}\\#{sub_key}" }
|
|
533
|
+
let(:value_name) { 'registry_value_name' }
|
|
534
|
+
let(:root_key_handle) { double('Root Key Handle') }
|
|
535
|
+
let(:subkey_handle) { double('Subkey Handle') }
|
|
536
|
+
let(:value) { double('Value') }
|
|
537
|
+
before :example do
|
|
538
|
+
allow(winreg).to receive_messages(
|
|
539
|
+
:bind => nil,
|
|
540
|
+
:open_root_key => root_key_handle,
|
|
541
|
+
:open_key => subkey_handle,
|
|
542
|
+
:query_value => value,
|
|
543
|
+
:close_key => nil
|
|
544
|
+
)
|
|
545
|
+
end
|
|
546
|
+
|
|
547
|
+
it 'binds a DCERPC connection to the expected remote endpoint' do
|
|
548
|
+
winreg.read_registry_key_value(key, value_name)
|
|
549
|
+
expect(winreg).to have_received(:bind).with(endpoint: RubySMB::Dcerpc::Winreg)
|
|
550
|
+
end
|
|
551
|
+
|
|
552
|
+
it 'opens the expected root key' do
|
|
553
|
+
winreg.read_registry_key_value(key, value_name)
|
|
554
|
+
expect(winreg).to have_received(:open_root_key).with(root_key)
|
|
555
|
+
end
|
|
556
|
+
|
|
557
|
+
it 'opens the expected registry key' do
|
|
558
|
+
winreg.read_registry_key_value(key, value_name)
|
|
559
|
+
expect(winreg).to have_received(:open_key).with(root_key_handle, sub_key)
|
|
560
|
+
end
|
|
561
|
+
|
|
562
|
+
it 'queries the expected registry key value' do
|
|
563
|
+
winreg.read_registry_key_value(key, value_name)
|
|
564
|
+
expect(winreg).to have_received(:query_value).with(subkey_handle, value_name)
|
|
565
|
+
end
|
|
566
|
+
|
|
567
|
+
it 'closes the key' do
|
|
568
|
+
winreg.read_registry_key_value(key, value_name)
|
|
569
|
+
expect(winreg).to have_received(:close_key).with(subkey_handle)
|
|
570
|
+
end
|
|
571
|
+
|
|
572
|
+
it 'returns expect registry key value' do
|
|
573
|
+
expect(winreg.read_registry_key_value(key, value_name)).to eq(value)
|
|
574
|
+
end
|
|
575
|
+
end
|
|
576
|
+
|
|
577
|
+
describe '#enum_registry_key' do
|
|
578
|
+
let(:root_key) { 'HKLM' }
|
|
579
|
+
let(:sub_key) { 'my\\sub\\key\\path' }
|
|
580
|
+
let(:key) { "#{root_key}\\#{sub_key}" }
|
|
581
|
+
let(:value_name) { 'registry_value_name' }
|
|
582
|
+
let(:root_key_handle) { double('Root Key Handle') }
|
|
583
|
+
let(:subkey_handle) { double('Subkey Handle') }
|
|
584
|
+
let(:query_info_key_response) { double('Query Info Key Response') }
|
|
585
|
+
let(:subkey_nb) { 2 }
|
|
586
|
+
before :example do
|
|
587
|
+
allow(winreg).to receive_messages(
|
|
588
|
+
:bind => nil,
|
|
589
|
+
:open_root_key => root_key_handle,
|
|
590
|
+
:open_key => subkey_handle,
|
|
591
|
+
:query_info_key => query_info_key_response,
|
|
592
|
+
:enum_key => nil,
|
|
593
|
+
:close_key => nil
|
|
594
|
+
)
|
|
595
|
+
allow(query_info_key_response).to receive(:lpc_sub_keys).and_return(subkey_nb)
|
|
596
|
+
end
|
|
597
|
+
|
|
598
|
+
it 'binds a DCERPC connection to the expected remote endpoint' do
|
|
599
|
+
winreg.enum_registry_key(key)
|
|
600
|
+
expect(winreg).to have_received(:bind).with(endpoint: RubySMB::Dcerpc::Winreg)
|
|
601
|
+
end
|
|
602
|
+
|
|
603
|
+
it 'opens the expected root key' do
|
|
604
|
+
winreg.enum_registry_key(key)
|
|
605
|
+
expect(winreg).to have_received(:open_root_key).with(root_key)
|
|
606
|
+
end
|
|
607
|
+
|
|
608
|
+
context 'when the registry key only contains the root key' do
|
|
609
|
+
it 'queries information for the root key' do
|
|
610
|
+
winreg.enum_registry_key(root_key)
|
|
611
|
+
expect(winreg).to have_received(:query_info_key).with(root_key_handle)
|
|
612
|
+
end
|
|
613
|
+
end
|
|
614
|
+
|
|
615
|
+
it 'opens the expected registry key' do
|
|
616
|
+
winreg.enum_registry_key(key)
|
|
617
|
+
expect(winreg).to have_received(:open_key).with(root_key_handle, sub_key)
|
|
618
|
+
end
|
|
619
|
+
|
|
620
|
+
it 'queries information for the expected registry key' do
|
|
621
|
+
winreg.enum_registry_key(key)
|
|
622
|
+
expect(winreg).to have_received(:query_info_key).with(subkey_handle)
|
|
623
|
+
end
|
|
624
|
+
|
|
625
|
+
it 'calls #enum_key the expected number of times' do
|
|
626
|
+
winreg.enum_registry_key(key)
|
|
627
|
+
expect(winreg).to have_received(:enum_key).with(subkey_handle, instance_of(Fixnum)).twice
|
|
628
|
+
end
|
|
629
|
+
|
|
630
|
+
it 'closes the key' do
|
|
631
|
+
winreg.enum_registry_key(key)
|
|
632
|
+
expect(winreg).to have_received(:close_key).with(subkey_handle)
|
|
633
|
+
end
|
|
634
|
+
|
|
635
|
+
it 'returns the expected array of enumerated keys' do
|
|
636
|
+
key1 = 'key1'
|
|
637
|
+
key2 = 'key2'
|
|
638
|
+
allow(winreg).to receive(:enum_key).with(subkey_handle, 0).and_return(key1)
|
|
639
|
+
allow(winreg).to receive(:enum_key).with(subkey_handle, 1).and_return(key2)
|
|
640
|
+
expect(winreg.enum_registry_key(key)).to eq([key1, key2])
|
|
641
|
+
end
|
|
642
|
+
end
|
|
643
|
+
|
|
644
|
+
describe '#enum_registry_values' do
|
|
645
|
+
let(:root_key) { 'HKLM' }
|
|
646
|
+
let(:sub_key) { 'my\\sub\\key\\path' }
|
|
647
|
+
let(:key) { "#{root_key}\\#{sub_key}" }
|
|
648
|
+
let(:value_name) { 'registry_value_name' }
|
|
649
|
+
let(:root_key_handle) { double('Root Key Handle') }
|
|
650
|
+
let(:subkey_handle) { double('Subkey Handle') }
|
|
651
|
+
let(:query_info_key_response) { double('Query Info Key Response') }
|
|
652
|
+
let(:subkey_nb) { 2 }
|
|
653
|
+
before :example do
|
|
654
|
+
allow(winreg).to receive_messages(
|
|
655
|
+
:bind => nil,
|
|
656
|
+
:open_root_key => root_key_handle,
|
|
657
|
+
:open_key => subkey_handle,
|
|
658
|
+
:query_info_key => query_info_key_response,
|
|
659
|
+
:enum_value => nil,
|
|
660
|
+
:close_key => nil
|
|
661
|
+
)
|
|
662
|
+
allow(query_info_key_response).to receive(:lpc_values).and_return(subkey_nb)
|
|
663
|
+
end
|
|
664
|
+
|
|
665
|
+
it 'binds a DCERPC connection to the expected remote endpoint' do
|
|
666
|
+
winreg.enum_registry_values(key)
|
|
667
|
+
expect(winreg).to have_received(:bind).with(endpoint: RubySMB::Dcerpc::Winreg)
|
|
668
|
+
end
|
|
669
|
+
|
|
670
|
+
it 'opens the expected root key' do
|
|
671
|
+
winreg.enum_registry_values(key)
|
|
672
|
+
expect(winreg).to have_received(:open_root_key).with(root_key)
|
|
673
|
+
end
|
|
674
|
+
|
|
675
|
+
context 'when the registry key only contains the root key' do
|
|
676
|
+
it 'queries information for the root key' do
|
|
677
|
+
winreg.enum_registry_values(root_key)
|
|
678
|
+
expect(winreg).to have_received(:query_info_key).with(root_key_handle)
|
|
679
|
+
end
|
|
680
|
+
end
|
|
681
|
+
|
|
682
|
+
it 'opens the expected registry key' do
|
|
683
|
+
winreg.enum_registry_values(key)
|
|
684
|
+
expect(winreg).to have_received(:open_key).with(root_key_handle, sub_key)
|
|
685
|
+
end
|
|
686
|
+
|
|
687
|
+
it 'queries information for the expected registry key' do
|
|
688
|
+
winreg.enum_registry_values(key)
|
|
689
|
+
expect(winreg).to have_received(:query_info_key).with(subkey_handle)
|
|
690
|
+
end
|
|
691
|
+
|
|
692
|
+
it 'calls #enum_key the expected number of times' do
|
|
693
|
+
winreg.enum_registry_values(key)
|
|
694
|
+
expect(winreg).to have_received(:enum_value).with(subkey_handle, instance_of(Fixnum)).twice
|
|
695
|
+
end
|
|
696
|
+
|
|
697
|
+
it 'closes the key' do
|
|
698
|
+
winreg.enum_registry_values(key)
|
|
699
|
+
expect(winreg).to have_received(:close_key).with(subkey_handle)
|
|
700
|
+
end
|
|
701
|
+
|
|
702
|
+
it 'returns the expected array of enumerated keys' do
|
|
703
|
+
value1 = 'value1'
|
|
704
|
+
value2 = 'value2'
|
|
705
|
+
allow(winreg).to receive(:enum_value).with(subkey_handle, 0).and_return(value1)
|
|
706
|
+
allow(winreg).to receive(:enum_value).with(subkey_handle, 1).and_return(value2)
|
|
707
|
+
expect(winreg.enum_registry_values(key)).to eq([value1, value2])
|
|
708
|
+
end
|
|
709
|
+
end
|
|
710
|
+
end
|