ruby_smb 1.0.5 → 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.tar.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.rb +0 -1
- data/lib/ruby_smb/client.rb +2 -0
- data/lib/ruby_smb/client/winreg.rb +46 -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/smb1/file.rb +2 -0
- data/lib/ruby_smb/smb1/pipe.rb +78 -2
- data/lib/ruby_smb/smb2/packet/error_packet.rb +2 -4
- data/lib/ruby_smb/smb2/pipe.rb +89 -2
- data/lib/ruby_smb/version.rb +1 -1
- data/ruby_smb.gemspec +3 -3
- data/spec/lib/ruby_smb/client_spec.rb +148 -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/smb1/file_spec.rb +9 -1
- data/spec/lib/ruby_smb/smb1/pipe_spec.rb +210 -148
- data/spec/lib/ruby_smb/smb2/packet/error_packet_spec.rb +3 -24
- data/spec/lib/ruby_smb/smb2/pipe_spec.rb +256 -145
- metadata +66 -9
- metadata.gz.sig +0 -0
- data/lib/ruby_smb/smb1/dcerpc.rb +0 -72
- data/lib/ruby_smb/smb2/dcerpc.rb +0 -75
@@ -0,0 +1,81 @@
|
|
1
|
+
RSpec.describe RubySMB::Dcerpc do
|
2
|
+
let(:tree) { double('Tree') }
|
3
|
+
let(:pipe) do
|
4
|
+
RubySMB::SMB1::Pipe.new(
|
5
|
+
tree: tree,
|
6
|
+
response: RubySMB::SMB1::Packet::NtCreateAndxResponse.new,
|
7
|
+
name: 'winreg'
|
8
|
+
)
|
9
|
+
end
|
10
|
+
|
11
|
+
describe '#bind' do
|
12
|
+
let(:options) { { endpoint: RubySMB::Dcerpc::Winreg } }
|
13
|
+
let(:bind_packet) { RubySMB::Dcerpc::Bind.new(options) }
|
14
|
+
let(:bind_ack_packet) { RubySMB::Dcerpc::BindAck.new }
|
15
|
+
let(:client) { double('Client') }
|
16
|
+
|
17
|
+
before :example do
|
18
|
+
allow(RubySMB::Dcerpc::Bind).to receive(:new).and_return(bind_packet)
|
19
|
+
allow(pipe).to receive(:write)
|
20
|
+
allow(pipe).to receive(:read)
|
21
|
+
bind_ack_packet.p_result_list.n_results = 1
|
22
|
+
bind_ack_packet.p_result_list.p_results[0].result = RubySMB::Dcerpc::BindAck::ACCEPTANCE
|
23
|
+
allow(RubySMB::Dcerpc::BindAck).to receive(:read).and_return(bind_ack_packet)
|
24
|
+
allow(tree).to receive(:client).and_return(client)
|
25
|
+
allow(client).to receive(:max_buffer_size=)
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'creates a Bind packet' do
|
29
|
+
pipe.bind(options)
|
30
|
+
expect(RubySMB::Dcerpc::Bind).to have_received(:new).with(options)
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'writes to the named pipe' do
|
34
|
+
pipe.bind(options)
|
35
|
+
expect(pipe).to have_received(:write).with(data: bind_packet.to_binary_s)
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'reads the socket' do
|
39
|
+
pipe.bind(options)
|
40
|
+
expect(pipe).to have_received(:read)
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'creates a BindAck packet from the response' do
|
44
|
+
raw_response = RubySMB::Dcerpc::BindAck.new.to_binary_s
|
45
|
+
allow(pipe).to receive(:read).and_return(raw_response)
|
46
|
+
pipe.bind(options)
|
47
|
+
expect(RubySMB::Dcerpc::BindAck).to have_received(:read).with(raw_response)
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'raises the expected exception when an invalid packet is received' do
|
51
|
+
allow(RubySMB::Dcerpc::BindAck).to receive(:read).and_raise(IOError)
|
52
|
+
expect { pipe.bind(options) }.to raise_error(RubySMB::Dcerpc::Error::InvalidPacket)
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'raises the expected exception when it is not a BindAck packet' do
|
56
|
+
response = RubySMB::Dcerpc::Bind.new
|
57
|
+
allow(RubySMB::Dcerpc::BindAck).to receive(:read).and_return(response)
|
58
|
+
expect { pipe.bind(options) }.to raise_error(RubySMB::Dcerpc::Error::BindError)
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'raises an exception when no result is returned' do
|
62
|
+
bind_ack_packet.p_result_list.n_results = 0
|
63
|
+
expect { pipe.bind(options) }.to raise_error(RubySMB::Dcerpc::Error::BindError)
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'raises an exception when result is not ACCEPTANCE' do
|
67
|
+
bind_ack_packet.p_result_list.p_results[0].result = RubySMB::Dcerpc::BindAck::USER_REJECTION
|
68
|
+
expect { pipe.bind(options) }.to raise_error(RubySMB::Dcerpc::Error::BindError)
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'sets the Tree #client.max_buffer_size property to the DCERPC response #max_xmit_frag property value' do
|
72
|
+
bind_ack_packet.max_xmit_frag = 64
|
73
|
+
pipe.bind(options)
|
74
|
+
expect(client).to have_received(:max_buffer_size=).with(64)
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'returns the expected BindAck packet' do
|
78
|
+
expect(pipe.bind(options)).to eq(bind_ack_packet)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -110,10 +110,18 @@ RSpec.describe RubySMB::SMB1::File do
|
|
110
110
|
file.read_packet
|
111
111
|
end
|
112
112
|
|
113
|
-
it 'sets the
|
113
|
+
it 'sets the #max_count_of_bytes_to_return of the packet' do
|
114
114
|
expect(file.read_packet(read_length: 55).parameter_block.max_count_of_bytes_to_return).to eq 55
|
115
115
|
end
|
116
116
|
|
117
|
+
it 'sets the #min_count_of_bytes_to_return of the packet' do
|
118
|
+
expect(file.read_packet(read_length: 55).parameter_block.min_count_of_bytes_to_return).to eq 55
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'sets the #remaining of the packet' do
|
122
|
+
expect(file.read_packet(read_length: 55).parameter_block.remaining).to eq 55
|
123
|
+
end
|
124
|
+
|
117
125
|
it 'sets the offset of the packet' do
|
118
126
|
expect(file.read_packet(offset: 55).parameter_block.offset).to eq 55
|
119
127
|
end
|
@@ -1,15 +1,12 @@
|
|
1
1
|
RSpec.describe RubySMB::SMB1::Pipe do
|
2
2
|
|
3
|
+
it { expect(described_class).to be < RubySMB::SMB1::File }
|
4
|
+
|
3
5
|
let(:peek_nmpipe_response) {
|
4
6
|
packet = RubySMB::SMB1::Packet::Trans::PeekNmpipeResponse.new
|
5
7
|
packet.data_block.trans_parameters.read("\x10\x20\x00\x00\x03\x00")
|
6
8
|
packet
|
7
9
|
}
|
8
|
-
|
9
|
-
describe RubySMB::SMB1::Pipe do
|
10
|
-
it { expect(described_class).to be < RubySMB::SMB1::File }
|
11
|
-
end
|
12
|
-
|
13
10
|
let(:dispatcher) { RubySMB::Dispatcher::Socket.new(double('socket')) }
|
14
11
|
let(:client) { RubySMB::Client.new(dispatcher, username: 'msfadmin', password: 'msfadmin') }
|
15
12
|
let(:connect_response) {
|
@@ -124,201 +121,266 @@ RSpec.describe RubySMB::SMB1::Pipe do
|
|
124
121
|
end
|
125
122
|
end
|
126
123
|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
allow(pipe).to receive(:bind)
|
134
|
-
allow(pipe).to receive(:request).and_return(dcerpc_response)
|
135
|
-
allow(RubySMB::Dcerpc::Srvsvc::NetShareEnumAll).to receive(:parse_response).and_return([])
|
124
|
+
describe '#initialize' do
|
125
|
+
context 'when name is not provided' do
|
126
|
+
it 'raises an ArgumentError' do
|
127
|
+
expect {
|
128
|
+
described_class.new(tree: tree, response: nt_create_andx_response, name: nil)
|
129
|
+
}.to raise_error(ArgumentError)
|
136
130
|
end
|
131
|
+
end
|
137
132
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
133
|
+
it 'calls the superclass with the expected arguments' do
|
134
|
+
expect(pipe.tree).to eq(tree)
|
135
|
+
expect(pipe.name).to eq(filename)
|
136
|
+
expect(pipe.attributes).to eq(nt_create_andx_response.parameter_block.ext_file_attributes)
|
137
|
+
expect(pipe.fid).to eq(nt_create_andx_response.parameter_block.fid)
|
138
|
+
expect(pipe.last_access).to eq(nt_create_andx_response.parameter_block.last_access_time.to_datetime)
|
139
|
+
expect(pipe.last_change).to eq(nt_create_andx_response.parameter_block.last_change_time.to_datetime)
|
140
|
+
expect(pipe.last_write).to eq(nt_create_andx_response.parameter_block.last_write_time.to_datetime)
|
141
|
+
expect(pipe.size).to eq(nt_create_andx_response.parameter_block.end_of_file)
|
142
|
+
expect(pipe.size_on_disk).to eq(nt_create_andx_response.parameter_block.allocation_size)
|
143
|
+
end
|
142
144
|
|
143
|
-
|
144
|
-
|
145
|
-
pipe.
|
145
|
+
context 'with \'srvsvc\' filename' do
|
146
|
+
it 'extends Srvsvc class' do
|
147
|
+
pipe = described_class.new(tree: tree, response: nt_create_andx_response, name: 'srvsvc')
|
148
|
+
expect(pipe.respond_to?(:net_share_enum_all)).to be true
|
146
149
|
end
|
150
|
+
end
|
147
151
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
expect(RubySMB::Dcerpc::Srvsvc::NetShareEnumAll).to receive(:parse_response).with(stub)
|
153
|
-
pipe.net_share_enum_all(host)
|
152
|
+
context 'with \'winreg\' filename' do
|
153
|
+
it 'extends Winreg class' do
|
154
|
+
pipe = described_class.new(tree: tree, response: nt_create_andx_response, name: 'winreg')
|
155
|
+
expect(pipe.respond_to?(:has_registry_key?)).to be true
|
154
156
|
end
|
157
|
+
end
|
158
|
+
end
|
155
159
|
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
160
|
+
describe '#dcerpc_request' do
|
161
|
+
let(:options) { { host: '1.2.3.4' } }
|
162
|
+
let(:stub_packet ) { RubySMB::Dcerpc::Winreg::OpenKeyRequest.new }
|
163
|
+
let(:dcerpc_request) { double('DCERPC Request') }
|
164
|
+
let(:request_stub) { double('Request stub') }
|
165
|
+
let(:binary_dcerpc_request) { double('Binary DCERPC Request') }
|
166
|
+
let(:trans_nmpipe_request) { double('TransactNmpipeRequest') }
|
167
|
+
let(:trans_data) { double('Trans data') }
|
168
|
+
let(:trans_nmpipe_raw_response) { double('Trans nmpipe raw response') }
|
169
|
+
let(:trans_nmpipe_response) { double('TransactNmpipeResponse') }
|
170
|
+
let(:raw_data) { double('Raw data') }
|
171
|
+
let(:dcerpc_response) { double('DCERPC Response') }
|
172
|
+
let(:result) { 'Result' }
|
173
|
+
|
174
|
+
before :example do
|
175
|
+
allow(RubySMB::Dcerpc::Request).to receive(:new).and_return(dcerpc_request)
|
176
|
+
allow(dcerpc_request).to receive_messages(
|
177
|
+
:stub => request_stub,
|
178
|
+
:to_binary_s => binary_dcerpc_request
|
179
|
+
)
|
180
|
+
allow(request_stub).to receive(:read)
|
181
|
+
allow(RubySMB::SMB1::Packet::Trans::TransactNmpipeRequest).to receive(:new).and_return(trans_nmpipe_request)
|
182
|
+
allow(tree).to receive(:set_header_fields)
|
183
|
+
allow(trans_nmpipe_request).to receive_message_chain(:data_block, :trans_data => trans_data)
|
184
|
+
allow(trans_nmpipe_request).to receive(:set_fid)
|
185
|
+
allow(trans_data).to receive(:write_data=)
|
186
|
+
allow(client).to receive(:send_recv).and_return(trans_nmpipe_raw_response)
|
187
|
+
allow(RubySMB::SMB1::Packet::Trans::TransactNmpipeResponse).to receive(:read).and_return(trans_nmpipe_response)
|
188
|
+
allow(trans_nmpipe_response).to receive_messages(
|
189
|
+
:valid? => true,
|
190
|
+
:status_code => WindowsError::NTStatus::STATUS_SUCCESS
|
191
|
+
)
|
192
|
+
allow(trans_nmpipe_response).to receive_message_chain(:data_block, :trans_data, :read_data, :to_binary_s => raw_data)
|
193
|
+
allow(RubySMB::Dcerpc::Response).to receive(:read).and_return(dcerpc_response)
|
194
|
+
allow(dcerpc_response).to receive_message_chain(:pdu_header, :ptype => RubySMB::Dcerpc::PTypes::RESPONSE)
|
195
|
+
allow(dcerpc_response).to receive(:stub).and_return(result)
|
172
196
|
end
|
173
197
|
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
198
|
+
it 'creates a Request packet with the expected arguments' do
|
199
|
+
pipe.dcerpc_request(stub_packet, options)
|
200
|
+
expect(options).to eq( { host: '1.2.3.4', endpoint: 'Winreg' })
|
201
|
+
expect(RubySMB::Dcerpc::Request).to have_received(:new).with({ opnum: stub_packet.opnum }, options)
|
202
|
+
end
|
178
203
|
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
bind_ack_packet.p_result_list.n_results = 1
|
184
|
-
bind_ack_packet.p_result_list.p_results[0].result = RubySMB::Dcerpc::BindAck::ACCEPTANCE
|
185
|
-
allow(RubySMB::Dcerpc::BindAck).to receive(:read).and_return(bind_ack_packet)
|
186
|
-
end
|
204
|
+
it 'sets DCERPC request stub to the stub packet passed as argument' do
|
205
|
+
pipe.dcerpc_request(stub_packet, options)
|
206
|
+
expect(request_stub).to have_received(:read).with(stub_packet.to_binary_s)
|
207
|
+
end
|
187
208
|
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
209
|
+
it 'creates a Trans TransactNmpipeRequest packet' do
|
210
|
+
pipe.dcerpc_request(stub_packet, options)
|
211
|
+
expect(RubySMB::SMB1::Packet::Trans::TransactNmpipeRequest).to have_received(:new).with(options)
|
212
|
+
end
|
192
213
|
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
214
|
+
it 'calls Tree #set_header_fields' do
|
215
|
+
pipe.dcerpc_request(stub_packet, options)
|
216
|
+
expect(tree).to have_received(:set_header_fields).with(trans_nmpipe_request)
|
217
|
+
end
|
218
|
+
|
219
|
+
it 'calls TransactNmpipeRequest #set_fid' do
|
220
|
+
pipe.dcerpc_request(stub_packet, options)
|
221
|
+
expect(trans_nmpipe_request).to have_received(:set_fid).with(pipe.fid)
|
222
|
+
end
|
223
|
+
|
224
|
+
it 'sets the expected #write_data request property' do
|
225
|
+
pipe.dcerpc_request(stub_packet, options)
|
226
|
+
expect(trans_data).to have_received(:write_data=).with(binary_dcerpc_request)
|
227
|
+
end
|
197
228
|
|
198
|
-
|
199
|
-
|
200
|
-
|
229
|
+
it 'sends the expected request' do
|
230
|
+
pipe.dcerpc_request(stub_packet, options)
|
231
|
+
expect(client).to have_received(:send_recv).with(trans_nmpipe_request)
|
232
|
+
end
|
233
|
+
|
234
|
+
it 'creates a Trans TransactNmpipeResponse packet from the response' do
|
235
|
+
pipe.dcerpc_request(stub_packet, options)
|
236
|
+
expect(RubySMB::SMB1::Packet::Trans::TransactNmpipeResponse).to have_received(:read).with(trans_nmpipe_raw_response)
|
237
|
+
end
|
238
|
+
|
239
|
+
context 'when the response is not a Trans packet' do
|
240
|
+
it 'raises an InvalidPacket exception' do
|
241
|
+
allow(trans_nmpipe_response).to receive_message_chain(:smb_header, :protocol)
|
242
|
+
allow(trans_nmpipe_response).to receive_message_chain(:smb_header, :command)
|
243
|
+
allow(trans_nmpipe_response).to receive(:valid?).and_return(false)
|
244
|
+
expect { pipe.dcerpc_request(stub_packet, options) }.to raise_error(RubySMB::Error::InvalidPacket)
|
201
245
|
end
|
246
|
+
end
|
202
247
|
|
203
|
-
|
204
|
-
|
205
|
-
allow(
|
206
|
-
expect(
|
207
|
-
pipe.bind(options)
|
248
|
+
context 'when the response status code is not STATUS_SUCCESS or STATUS_BUFFER_OVERFLOW' do
|
249
|
+
it 'raises an UnexpectedStatusCode exception' do
|
250
|
+
allow(trans_nmpipe_response).to receive(:status_code).and_return(WindowsError::NTStatus::STATUS_INVALID_HANDLE)
|
251
|
+
expect { pipe.dcerpc_request(stub_packet, options) }.to raise_error(RubySMB::Error::UnexpectedStatusCode)
|
208
252
|
end
|
253
|
+
end
|
209
254
|
|
210
|
-
|
211
|
-
|
212
|
-
expect { pipe.
|
255
|
+
context 'when the response status code is STATUS_SUCCESS' do
|
256
|
+
it 'does not raise any exception' do
|
257
|
+
expect { pipe.dcerpc_request(stub_packet, options) }.not_to raise_error
|
213
258
|
end
|
214
259
|
|
215
|
-
it '
|
216
|
-
|
217
|
-
|
218
|
-
expect { pipe.bind(options) }.to raise_error(RubySMB::Dcerpc::Error::BindError)
|
260
|
+
it 'creates a DCERPC Response packet from the response' do
|
261
|
+
pipe.dcerpc_request(stub_packet, options)
|
262
|
+
expect(RubySMB::Dcerpc::Response).to have_received(:read).with(raw_data)
|
219
263
|
end
|
220
264
|
|
221
|
-
|
222
|
-
|
223
|
-
|
265
|
+
context 'when an IOError occurs while parsing the DCERPC response' do
|
266
|
+
it 'raises an InvalidPacket exception' do
|
267
|
+
allow(RubySMB::Dcerpc::Response).to receive(:read).and_raise(IOError)
|
268
|
+
expect { pipe.dcerpc_request(stub_packet, options) }.to raise_error(RubySMB::Dcerpc::Error::InvalidPacket)
|
269
|
+
end
|
224
270
|
end
|
225
271
|
|
226
|
-
|
227
|
-
|
228
|
-
|
272
|
+
context 'when the response is not a DCERPC Response packet' do
|
273
|
+
it 'raises an InvalidPacket exception' do
|
274
|
+
allow(dcerpc_response).to receive_message_chain(:pdu_header, :ptype => RubySMB::Dcerpc::PTypes::FAULT)
|
275
|
+
expect { pipe.dcerpc_request(stub_packet, options) }.to raise_error(RubySMB::Dcerpc::Error::InvalidPacket)
|
276
|
+
end
|
229
277
|
end
|
230
278
|
|
231
|
-
it 'returns the expected
|
232
|
-
expect(pipe.
|
279
|
+
it 'returns the expected stub data' do
|
280
|
+
expect(pipe.dcerpc_request(stub_packet, options)).to eq(result)
|
233
281
|
end
|
234
282
|
end
|
235
283
|
|
236
|
-
|
237
|
-
let(:
|
238
|
-
let(:
|
239
|
-
let(:req_packet) { RubySMB::Dcerpc::Request.new({ :opnum => opnum }, options) }
|
240
|
-
let(:nmpipe_packet) { RubySMB::SMB1::Packet::Trans::TransactNmpipeRequest.new(options) }
|
241
|
-
let(:nmpipe_response) { RubySMB::SMB1::Packet::Trans::TransactNmpipeResponse.new }
|
242
|
-
let(:res_packet) { RubySMB::Dcerpc::Response.new }
|
243
|
-
|
284
|
+
context 'when the response status code is STATUS_BUFFER_OVERFLOW' do
|
285
|
+
let(:data_count) { 100 }
|
286
|
+
let(:added_raw_data) { double('Added raw data') }
|
244
287
|
before :example do
|
245
|
-
allow(
|
246
|
-
allow(
|
247
|
-
allow(
|
248
|
-
allow(
|
249
|
-
allow(
|
288
|
+
allow(trans_nmpipe_response).to receive(:status_code).and_return(WindowsError::NTStatus::STATUS_BUFFER_OVERFLOW)
|
289
|
+
allow(trans_nmpipe_response).to receive_message_chain(:parameter_block, :data_count => data_count)
|
290
|
+
allow(pipe).to receive(:read).and_return(added_raw_data)
|
291
|
+
allow(raw_data).to receive(:<<)
|
292
|
+
allow(dcerpc_response).to receive_message_chain(:pdu_header, :pfc_flags, :first_frag => 1)
|
293
|
+
allow(dcerpc_response).to receive_message_chain(:pdu_header, :pfc_flags, :last_frag => 1)
|
250
294
|
end
|
251
295
|
|
252
|
-
it '
|
253
|
-
expect(
|
254
|
-
pipe.request(opnum, options)
|
296
|
+
it 'does not raise any exception' do
|
297
|
+
expect { pipe.dcerpc_request(stub_packet, options) }.not_to raise_error
|
255
298
|
end
|
256
299
|
|
257
|
-
it '
|
258
|
-
|
259
|
-
pipe.
|
300
|
+
it 'reads the expected number of bytes and concatenate it the first response raw data' do
|
301
|
+
pipe.dcerpc_request(stub_packet, options)
|
302
|
+
expect(pipe).to have_received(:read).with(bytes: tree.client.max_buffer_size - data_count)
|
303
|
+
expect(raw_data).to have_received(:<<).with(added_raw_data)
|
260
304
|
end
|
261
305
|
|
262
|
-
it '
|
263
|
-
|
264
|
-
|
306
|
+
it 'creates a DCERPC Response packet from the updated raw data' do
|
307
|
+
pipe.dcerpc_request(stub_packet, options)
|
308
|
+
expect(RubySMB::Dcerpc::Response).to have_received(:read).with(raw_data)
|
265
309
|
end
|
266
310
|
|
267
|
-
|
268
|
-
|
269
|
-
|
311
|
+
context 'when an IOError occurs while parsing the DCERPC response' do
|
312
|
+
it 'raises an InvalidPacket exception' do
|
313
|
+
allow(RubySMB::Dcerpc::Response).to receive(:read).and_raise(IOError)
|
314
|
+
expect { pipe.dcerpc_request(stub_packet, options) }.to raise_error(RubySMB::Dcerpc::Error::InvalidPacket)
|
315
|
+
end
|
270
316
|
end
|
271
317
|
|
272
|
-
|
273
|
-
|
274
|
-
|
318
|
+
context 'when the response is not a DCERPC Response packet' do
|
319
|
+
it 'raises an InvalidPacket exception' do
|
320
|
+
allow(dcerpc_response).to receive_message_chain(:pdu_header, :ptype => RubySMB::Dcerpc::PTypes::FAULT)
|
321
|
+
expect { pipe.dcerpc_request(stub_packet, options) }.to raise_error(RubySMB::Dcerpc::Error::InvalidPacket)
|
275
322
|
end
|
276
|
-
pipe.request(opnum, options)
|
277
323
|
end
|
278
324
|
|
279
|
-
|
280
|
-
|
281
|
-
|
325
|
+
context 'when the response is not the first fragment' do
|
326
|
+
it 'raises an InvalidPacket exception' do
|
327
|
+
allow(dcerpc_response).to receive_message_chain(:pdu_header, :pfc_flags, :first_frag => 0)
|
328
|
+
expect { pipe.dcerpc_request(stub_packet, options) }.to raise_error(RubySMB::Dcerpc::Error::InvalidPacket)
|
329
|
+
end
|
282
330
|
end
|
283
331
|
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
end
|
332
|
+
context 'when the response is the last fragment' do
|
333
|
+
it 'only reads the pipe once' do
|
334
|
+
pipe.dcerpc_request(stub_packet, options)
|
335
|
+
expect(RubySMB::Dcerpc::Response).to have_received(:read).once
|
336
|
+
end
|
290
337
|
|
291
|
-
|
292
|
-
|
293
|
-
|
338
|
+
it 'returns the expected stub data' do
|
339
|
+
expect(pipe.dcerpc_request(stub_packet, options)).to eq(result)
|
340
|
+
end
|
294
341
|
end
|
295
342
|
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
343
|
+
context 'when the response is not the last fragment' do
|
344
|
+
let(:raw_data2) { double('Raw data #2') }
|
345
|
+
let(:dcerpc_response2) { double('DCERPC Response #2') }
|
346
|
+
let(:result2) { 'Result #2' }
|
347
|
+
before :example do
|
348
|
+
allow(dcerpc_response).to receive_message_chain(:pdu_header, :pfc_flags, :last_frag => 0)
|
349
|
+
allow(pipe).to receive(:read).with(bytes: tree.client.max_buffer_size).and_return(raw_data2)
|
350
|
+
allow(RubySMB::Dcerpc::Response).to receive(:read).with(raw_data2).and_return(dcerpc_response2)
|
351
|
+
allow(dcerpc_response2).to receive_message_chain(:pdu_header, :ptype => RubySMB::Dcerpc::PTypes::RESPONSE)
|
352
|
+
allow(dcerpc_response2).to receive_message_chain(:pdu_header, :pfc_flags, :last_frag => 1)
|
353
|
+
allow(dcerpc_response2).to receive(:stub).and_return(result2)
|
354
|
+
end
|
300
355
|
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
end
|
356
|
+
it 'reads the expected number of bytes' do
|
357
|
+
pipe.dcerpc_request(stub_packet, options)
|
358
|
+
expect(pipe).to have_received(:read).with(bytes: tree.client.max_buffer_size)
|
359
|
+
end
|
306
360
|
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
361
|
+
it 'creates a DCERPC Response packet from the new raw data' do
|
362
|
+
pipe.dcerpc_request(stub_packet, options)
|
363
|
+
expect(RubySMB::Dcerpc::Response).to have_received(:read).with(raw_data2)
|
364
|
+
end
|
311
365
|
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
366
|
+
context 'when an IOError occurs while parsing the new DCERPC response' do
|
367
|
+
it 'raises an InvalidPacket exception' do
|
368
|
+
allow(RubySMB::Dcerpc::Response).to receive(:read).with(raw_data2).and_raise(IOError)
|
369
|
+
expect { pipe.dcerpc_request(stub_packet, options) }.to raise_error(RubySMB::Dcerpc::Error::InvalidPacket)
|
370
|
+
end
|
371
|
+
end
|
317
372
|
|
318
|
-
|
319
|
-
|
373
|
+
context 'when the new response is not a DCERPC Response packet' do
|
374
|
+
it 'raises an InvalidPacket exception' do
|
375
|
+
allow(dcerpc_response2).to receive_message_chain(:pdu_header, :ptype => RubySMB::Dcerpc::PTypes::FAULT)
|
376
|
+
expect { pipe.dcerpc_request(stub_packet, options) }.to raise_error(RubySMB::Dcerpc::Error::InvalidPacket)
|
377
|
+
end
|
378
|
+
end
|
379
|
+
|
380
|
+
it 'returns the expected stub data' do
|
381
|
+
expect(pipe.dcerpc_request(stub_packet, options)).to eq(result)
|
382
|
+
end
|
320
383
|
end
|
321
384
|
end
|
322
385
|
end
|
323
|
-
|
324
386
|
end
|