ruby_smb 2.0.2 → 2.0.7
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/examples/anonymous_auth.rb +3 -3
- data/examples/append_file.rb +10 -8
- data/examples/authenticate.rb +9 -5
- data/examples/delete_file.rb +8 -6
- data/examples/enum_registry_key.rb +5 -4
- data/examples/enum_registry_values.rb +5 -4
- data/examples/list_directory.rb +8 -6
- data/examples/negotiate_with_netbios_service.rb +9 -5
- data/examples/net_share_enum_all.rb +6 -4
- data/examples/pipes.rb +11 -12
- data/examples/query_service_status.rb +64 -0
- data/examples/read_file.rb +8 -6
- data/examples/read_registry_key_value.rb +6 -5
- data/examples/rename_file.rb +9 -7
- data/examples/tree_connect.rb +7 -5
- data/examples/write_file.rb +9 -7
- data/lib/ruby_smb/client.rb +81 -48
- data/lib/ruby_smb/client/authentication.rb +5 -10
- data/lib/ruby_smb/client/echo.rb +2 -4
- data/lib/ruby_smb/client/negotiation.rb +3 -4
- data/lib/ruby_smb/client/tree_connect.rb +2 -4
- data/lib/ruby_smb/client/utils.rb +16 -10
- data/lib/ruby_smb/client/winreg.rb +1 -1
- data/lib/ruby_smb/dcerpc.rb +4 -0
- data/lib/ruby_smb/dcerpc/error.rb +3 -0
- data/lib/ruby_smb/dcerpc/ndr.rb +306 -44
- data/lib/ruby_smb/dcerpc/netlogon.rb +101 -0
- data/lib/ruby_smb/dcerpc/netlogon/netr_server_authenticate3_request.rb +37 -0
- data/lib/ruby_smb/dcerpc/netlogon/netr_server_authenticate3_response.rb +26 -0
- data/lib/ruby_smb/dcerpc/netlogon/netr_server_password_set2_request.rb +37 -0
- data/lib/ruby_smb/dcerpc/netlogon/netr_server_password_set2_response.rb +23 -0
- data/lib/ruby_smb/dcerpc/netlogon/netr_server_req_challenge_request.rb +32 -0
- data/lib/ruby_smb/dcerpc/netlogon/netr_server_req_challenge_response.rb +24 -0
- data/lib/ruby_smb/dcerpc/request.rb +19 -0
- data/lib/ruby_smb/dcerpc/rpc_security_attributes.rb +34 -0
- data/lib/ruby_smb/dcerpc/rrp_unicode_string.rb +9 -6
- data/lib/ruby_smb/dcerpc/svcctl.rb +479 -0
- data/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_request.rb +48 -0
- data/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_response.rb +26 -0
- data/lib/ruby_smb/dcerpc/svcctl/close_service_handle_request.rb +25 -0
- data/lib/ruby_smb/dcerpc/svcctl/close_service_handle_response.rb +26 -0
- data/lib/ruby_smb/dcerpc/svcctl/control_service_request.rb +26 -0
- data/lib/ruby_smb/dcerpc/svcctl/control_service_response.rb +26 -0
- data/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_request.rb +35 -0
- data/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_response.rb +23 -0
- data/lib/ruby_smb/dcerpc/svcctl/open_service_w_request.rb +31 -0
- data/lib/ruby_smb/dcerpc/svcctl/open_service_w_response.rb +23 -0
- data/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_request.rb +25 -0
- data/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_response.rb +44 -0
- data/lib/ruby_smb/dcerpc/svcctl/query_service_status_request.rb +23 -0
- data/lib/ruby_smb/dcerpc/svcctl/query_service_status_response.rb +27 -0
- data/lib/ruby_smb/dcerpc/svcctl/service_status.rb +25 -0
- data/lib/ruby_smb/dcerpc/svcctl/start_service_w_request.rb +27 -0
- data/lib/ruby_smb/dcerpc/svcctl/start_service_w_response.rb +25 -0
- data/lib/ruby_smb/dcerpc/winreg.rb +98 -17
- data/lib/ruby_smb/dcerpc/winreg/create_key_request.rb +73 -0
- data/lib/ruby_smb/dcerpc/winreg/create_key_response.rb +36 -0
- data/lib/ruby_smb/dcerpc/winreg/enum_key_request.rb +1 -1
- data/lib/ruby_smb/dcerpc/winreg/enum_value_request.rb +1 -1
- data/lib/ruby_smb/dcerpc/winreg/enum_value_response.rb +1 -1
- data/lib/ruby_smb/dcerpc/winreg/open_root_key_request.rb +4 -4
- data/lib/ruby_smb/dcerpc/winreg/query_info_key_request.rb +1 -1
- data/lib/ruby_smb/dcerpc/winreg/query_value_request.rb +7 -6
- data/lib/ruby_smb/dcerpc/winreg/query_value_response.rb +10 -10
- data/lib/ruby_smb/dcerpc/winreg/save_key_request.rb +37 -0
- data/lib/ruby_smb/dcerpc/winreg/save_key_response.rb +23 -0
- data/lib/ruby_smb/dispatcher/base.rb +1 -1
- data/lib/ruby_smb/dispatcher/socket.rb +1 -1
- data/lib/ruby_smb/error.rb +21 -5
- data/lib/ruby_smb/field/stringz16.rb +17 -1
- data/lib/ruby_smb/generic_packet.rb +11 -1
- data/lib/ruby_smb/nbss/session_header.rb +4 -4
- data/lib/ruby_smb/smb1/file.rb +10 -25
- data/lib/ruby_smb/smb1/packet/trans2/find_first2_response.rb +0 -1
- data/lib/ruby_smb/smb1/packet/trans2/find_next2_response.rb +0 -1
- data/lib/ruby_smb/smb1/packet/trans2/open2_response.rb +1 -2
- data/lib/ruby_smb/smb1/packet/trans2/set_file_information_response.rb +1 -13
- data/lib/ruby_smb/smb1/pipe.rb +8 -6
- data/lib/ruby_smb/smb1/tree.rb +13 -9
- data/lib/ruby_smb/smb2/file.rb +33 -33
- data/lib/ruby_smb/smb2/pipe.rb +9 -6
- data/lib/ruby_smb/smb2/tree.rb +21 -11
- data/lib/ruby_smb/version.rb +1 -1
- data/spec/lib/ruby_smb/client_spec.rb +174 -68
- data/spec/lib/ruby_smb/dcerpc/ndr_spec.rb +1396 -77
- data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_authenticate3_request_spec.rb +69 -0
- data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_authenticate3_response_spec.rb +53 -0
- data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_password_set2_request_spec.rb +69 -0
- data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_password_set2_response_spec.rb +37 -0
- data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_req_challenge_request_spec.rb +45 -0
- data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_req_challenge_response_spec.rb +37 -0
- data/spec/lib/ruby_smb/dcerpc/rpc_security_attributes_spec.rb +161 -0
- data/spec/lib/ruby_smb/dcerpc/rrp_unicode_string_spec.rb +49 -12
- data/spec/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_request_spec.rb +191 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_response_spec.rb +38 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/close_service_handle_request_spec.rb +30 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/close_service_handle_response_spec.rb +38 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/control_service_request_spec.rb +39 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/control_service_response_spec.rb +38 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_request_spec.rb +78 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_response_spec.rb +38 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/open_service_w_request_spec.rb +59 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/open_service_w_response_spec.rb +38 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_request_spec.rb +38 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_response_spec.rb +152 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_status_request_spec.rb +30 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_status_response_spec.rb +38 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/service_status_spec.rb +72 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/start_service_w_request_spec.rb +46 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/start_service_w_response_spec.rb +30 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl_spec.rb +512 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/create_key_request_spec.rb +110 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/create_key_response_spec.rb +44 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/enum_key_request_spec.rb +0 -4
- data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_request_spec.rb +2 -2
- data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_response_spec.rb +2 -2
- data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_request_spec.rb +9 -4
- data/spec/lib/ruby_smb/dcerpc/winreg/query_info_key_request_spec.rb +0 -4
- data/spec/lib/ruby_smb/dcerpc/winreg/query_value_request_spec.rb +17 -17
- data/spec/lib/ruby_smb/dcerpc/winreg/query_value_response_spec.rb +11 -23
- data/spec/lib/ruby_smb/dcerpc/winreg/save_key_request_spec.rb +57 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/save_key_response_spec.rb +22 -0
- data/spec/lib/ruby_smb/dcerpc/winreg_spec.rb +227 -41
- data/spec/lib/ruby_smb/dispatcher/socket_spec.rb +10 -10
- data/spec/lib/ruby_smb/error_spec.rb +34 -5
- data/spec/lib/ruby_smb/field/stringz16_spec.rb +12 -0
- data/spec/lib/ruby_smb/generic_packet_spec.rb +7 -0
- data/spec/lib/ruby_smb/nbss/session_header_spec.rb +4 -11
- data/spec/lib/ruby_smb/smb1/file_spec.rb +2 -4
- data/spec/lib/ruby_smb/smb1/packet/trans2/find_first2_response_spec.rb +0 -1
- data/spec/lib/ruby_smb/smb1/packet/trans2/find_next2_response_spec.rb +0 -1
- data/spec/lib/ruby_smb/smb1/packet/trans2/open2_response_spec.rb +0 -5
- data/spec/lib/ruby_smb/smb1/packet/trans2/set_file_information_response_spec.rb +0 -6
- data/spec/lib/ruby_smb/smb1/pipe_spec.rb +30 -5
- data/spec/lib/ruby_smb/smb1/tree_spec.rb +22 -0
- data/spec/lib/ruby_smb/smb2/file_spec.rb +61 -9
- data/spec/lib/ruby_smb/smb2/pipe_spec.rb +9 -5
- data/spec/lib/ruby_smb/smb2/tree_spec.rb +58 -1
- metadata +107 -18
- metadata.gz.sig +0 -0
data/examples/write_file.rb
CHANGED
@@ -9,18 +9,20 @@
|
|
9
9
|
require 'bundler/setup'
|
10
10
|
require 'ruby_smb'
|
11
11
|
|
12
|
-
address
|
13
|
-
username
|
14
|
-
password
|
15
|
-
share
|
16
|
-
file
|
17
|
-
data
|
12
|
+
address = ARGV[0]
|
13
|
+
username = ARGV[1]
|
14
|
+
password = ARGV[2]
|
15
|
+
share = ARGV[3]
|
16
|
+
file = ARGV[4]
|
17
|
+
data = ARGV[5]
|
18
|
+
smb_versions = ARGV[6]&.split(',') || ['1','2','3']
|
19
|
+
|
18
20
|
path = "\\\\#{address}\\#{share}"
|
19
21
|
|
20
22
|
sock = TCPSocket.new address, 445
|
21
23
|
dispatcher = RubySMB::Dispatcher::Socket.new(sock)
|
22
24
|
|
23
|
-
client = RubySMB::Client.new(dispatcher, smb1:
|
25
|
+
client = RubySMB::Client.new(dispatcher, smb1: smb_versions.include?('1'), smb2: smb_versions.include?('2'), smb3: smb_versions.include?('3'), username: username, password: password)
|
24
26
|
protocol = client.negotiate
|
25
27
|
status = client.authenticate
|
26
28
|
|
data/lib/ruby_smb/client.rb
CHANGED
@@ -160,9 +160,16 @@ module RubySMB
|
|
160
160
|
|
161
161
|
# The UID set in SMB1
|
162
162
|
# @!attribute [rw] user_id
|
163
|
-
# @return [
|
163
|
+
# @return [Integer]
|
164
164
|
attr_accessor :user_id
|
165
165
|
|
166
|
+
# The Process ID set in SMB1
|
167
|
+
# It is randomly generated during the client initialization, but can
|
168
|
+
# be modified using the accessor.
|
169
|
+
# @!attribute [rw] pid
|
170
|
+
# @return [Integer]
|
171
|
+
attr_accessor :pid
|
172
|
+
|
166
173
|
# The maximum size SMB message that the Client accepts (in bytes)
|
167
174
|
# The default value is equal to {MAX_BUFFER_SIZE}.
|
168
175
|
# @!attribute [rw] max_buffer_size
|
@@ -258,6 +265,14 @@ module RubySMB
|
|
258
265
|
# @return [Integer] the negotiated SMB version
|
259
266
|
attr_accessor :negotiated_smb_version
|
260
267
|
|
268
|
+
# Whether or not the server supports multi-credit operations. It is
|
269
|
+
# reported by the LARGE_MTU capabiliy as part of the negotiation process
|
270
|
+
# (SMB 2.x and 3.x).
|
271
|
+
# @!attribute [rw] server_supports_multi_credit
|
272
|
+
# @return [Boolean] true if the server supports multi-credit operations,
|
273
|
+
# false otherwise
|
274
|
+
attr_accessor :server_supports_multi_credit
|
275
|
+
|
261
276
|
# @param dispatcher [RubySMB::Dispatcher::Socket] the packet dispatcher to use
|
262
277
|
# @param smb1 [Boolean] whether or not to enable SMB1 support
|
263
278
|
# @param smb2 [Boolean] whether or not to enable SMB2 support
|
@@ -268,6 +283,7 @@ module RubySMB
|
|
268
283
|
raise ArgumentError, 'You must enable at least one Protocol'
|
269
284
|
end
|
270
285
|
@dispatcher = dispatcher
|
286
|
+
@pid = rand(0xFFFF)
|
271
287
|
@domain = domain
|
272
288
|
@local_workstation = local_workstation
|
273
289
|
@password = password.encode('utf-8') || ''.encode('utf-8')
|
@@ -285,6 +301,7 @@ module RubySMB
|
|
285
301
|
@server_max_read_size = RubySMB::SMB2::File::MAX_PACKET_SIZE
|
286
302
|
@server_max_write_size = RubySMB::SMB2::File::MAX_PACKET_SIZE
|
287
303
|
@server_max_transact_size = RubySMB::SMB2::File::MAX_PACKET_SIZE
|
304
|
+
@server_supports_multi_credit = false
|
288
305
|
|
289
306
|
# SMB 3.x options
|
290
307
|
@session_encrypt_data = always_encrypt
|
@@ -344,7 +361,7 @@ module RubySMB
|
|
344
361
|
# @param packet [RubySMB::GenericPacket] the packet to set the message id for
|
345
362
|
# @return [RubySMB::GenericPacket] the modified packet
|
346
363
|
def increment_smb_message_id(packet)
|
347
|
-
packet.smb2_header.message_id = smb2_message_id
|
364
|
+
packet.smb2_header.message_id = self.smb2_message_id
|
348
365
|
self.smb2_message_id += 1
|
349
366
|
packet
|
350
367
|
end
|
@@ -394,8 +411,7 @@ module RubySMB
|
|
394
411
|
raise RubySMB::Error::InvalidPacket.new(
|
395
412
|
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
396
413
|
expected_cmd: RubySMB::SMB2::Packet::LogoffResponse::COMMAND,
|
397
|
-
|
398
|
-
received_cmd: response.smb2_header.command
|
414
|
+
packet: response
|
399
415
|
)
|
400
416
|
end
|
401
417
|
else
|
@@ -406,8 +422,7 @@ module RubySMB
|
|
406
422
|
raise RubySMB::Error::InvalidPacket.new(
|
407
423
|
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
408
424
|
expected_cmd: RubySMB::SMB1::Packet::LogoffResponse::COMMAND,
|
409
|
-
|
410
|
-
received_cmd: response.smb_header.command
|
425
|
+
packet: response
|
411
426
|
)
|
412
427
|
end
|
413
428
|
end
|
@@ -427,7 +442,8 @@ module RubySMB
|
|
427
442
|
version = packet.packet_smb_version
|
428
443
|
case version
|
429
444
|
when 'SMB1'
|
430
|
-
packet.smb_header.uid = user_id if user_id
|
445
|
+
packet.smb_header.uid = self.user_id if self.user_id
|
446
|
+
packet.smb_header.pid_low = self.pid if self.pid
|
431
447
|
packet = smb1_sign(packet)
|
432
448
|
when 'SMB2'
|
433
449
|
packet = increment_smb_message_id(packet)
|
@@ -443,35 +459,38 @@ module RubySMB
|
|
443
459
|
packet = packet
|
444
460
|
end
|
445
461
|
|
462
|
+
encrypt_data = false
|
446
463
|
if can_be_encrypted?(packet) && encryption_supported? && (@session_encrypt_data || encrypt)
|
447
|
-
|
448
|
-
raw_response = recv_encrypt
|
449
|
-
loop do
|
450
|
-
break unless is_status_pending?(raw_response)
|
451
|
-
sleep 1
|
452
|
-
raw_response = recv_encrypt
|
453
|
-
end
|
454
|
-
else
|
455
|
-
dispatcher.send_packet(packet)
|
456
|
-
raw_response = dispatcher.recv_packet
|
457
|
-
loop do
|
458
|
-
break unless is_status_pending?(raw_response)
|
459
|
-
sleep 1
|
460
|
-
raw_response = dispatcher.recv_packet
|
461
|
-
end unless version == 'SMB1'
|
464
|
+
encrypt_data = true
|
462
465
|
end
|
466
|
+
send_packet(packet, encrypt: encrypt_data)
|
467
|
+
raw_response = recv_packet(encrypt: encrypt_data)
|
468
|
+
smb2_header = nil
|
469
|
+
loop do
|
470
|
+
smb2_header = RubySMB::SMB2::SMB2Header.read(raw_response)
|
471
|
+
break unless is_status_pending?(smb2_header)
|
472
|
+
sleep 1
|
473
|
+
raw_response = recv_packet(encrypt: encrypt_data)
|
474
|
+
rescue IOError
|
475
|
+
# We're expecting an SMB2 packet, but the server sent an SMB1 packet
|
476
|
+
# instead. This behavior has been observed with older versions of Samba
|
477
|
+
# when something goes wrong on the server side. So, we just ignore it
|
478
|
+
# and expect the caller to handle this wrong response packet.
|
479
|
+
break
|
480
|
+
end unless version == 'SMB1'
|
463
481
|
|
464
482
|
self.sequence_counter += 1 if signing_required && !session_key.empty?
|
483
|
+
# update the SMB2 message ID according to the received Credit Charged
|
484
|
+
self.smb2_message_id += smb2_header.credit_charge - 1 if smb2_header && self.server_supports_multi_credit
|
465
485
|
raw_response
|
466
486
|
end
|
467
487
|
|
468
488
|
# Check if the response is an asynchronous operation with STATUS_PENDING
|
469
489
|
# status code.
|
470
490
|
#
|
471
|
-
# @param
|
491
|
+
# @param smb2_header [String] the response packet SMB2 header
|
472
492
|
# @return [Boolean] true if it is a status pending operation, false otherwise
|
473
|
-
def is_status_pending?(
|
474
|
-
smb2_header = RubySMB::SMB2::SMB2Header.read(raw_response)
|
493
|
+
def is_status_pending?(smb2_header)
|
475
494
|
value = smb2_header.nt_status.value
|
476
495
|
status_code = WindowsError::NTStatus.find_by_retval(value).first
|
477
496
|
status_code == WindowsError::NTStatus::STATUS_PENDING &&
|
@@ -497,37 +516,50 @@ module RubySMB
|
|
497
516
|
['0x0300', '0x0302', '0x0311'].include?(@dialect)
|
498
517
|
end
|
499
518
|
|
500
|
-
# Encrypt and send a packet
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
519
|
+
# Encrypt (if required) and send a packet.
|
520
|
+
#
|
521
|
+
# @param encrypt [Boolean] true if the packet should be encrypted, false
|
522
|
+
# otherwise
|
523
|
+
def send_packet(packet, encrypt: false)
|
524
|
+
if encrypt
|
525
|
+
begin
|
526
|
+
packet = smb3_encrypt(packet.to_binary_s)
|
527
|
+
rescue RubySMB::Error::RubySMBError => e
|
528
|
+
raise RubySMB::Error::EncryptionError, "Error while encrypting #{packet.class.name} packet (SMB #{@dialect}): #{e}"
|
529
|
+
end
|
506
530
|
end
|
507
|
-
dispatcher.send_packet(
|
531
|
+
dispatcher.send_packet(packet)
|
508
532
|
end
|
509
533
|
|
510
|
-
# Receives the raw response through the Dispatcher and decrypt the packet.
|
534
|
+
# Receives the raw response through the Dispatcher and decrypt the packet (if required).
|
511
535
|
#
|
536
|
+
# @param encrypt [Boolean] true if the packet is encrypted, false otherwise
|
512
537
|
# @return [String] the raw unencrypted packet
|
513
|
-
def
|
538
|
+
def recv_packet(encrypt: false)
|
514
539
|
begin
|
515
540
|
raw_response = dispatcher.recv_packet
|
516
541
|
rescue RubySMB::Error::CommunicationError => e
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
raise RubySMB::Error::InvalidPacket, 'Not a SMB2 TransformHeader packet'
|
542
|
+
if encrypt
|
543
|
+
raise RubySMB::Error::EncryptionError, "Communication error with the "\
|
544
|
+
"remote host: #{e.message}. The server supports encryption but was "\
|
545
|
+
"not able to handle the encrypted request."
|
546
|
+
else
|
547
|
+
raise e
|
548
|
+
end
|
525
549
|
end
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
550
|
+
if encrypt
|
551
|
+
begin
|
552
|
+
transform_response = RubySMB::SMB2::Packet::TransformHeader.read(raw_response)
|
553
|
+
rescue IOError
|
554
|
+
raise RubySMB::Error::InvalidPacket, 'Not a SMB2 TransformHeader packet'
|
555
|
+
end
|
556
|
+
begin
|
557
|
+
raw_response = smb3_decrypt(transform_response)
|
558
|
+
rescue RubySMB::Error::RubySMBError => e
|
559
|
+
raise RubySMB::Error::EncryptionError, "Error while decrypting #{transform_response.class.name} packet (SMB #@dialect}): #{e}"
|
560
|
+
end
|
530
561
|
end
|
562
|
+
raw_response
|
531
563
|
end
|
532
564
|
|
533
565
|
# Connects to the supplied share
|
@@ -551,7 +583,7 @@ module RubySMB
|
|
551
583
|
# @param [String] host
|
552
584
|
def net_share_enum_all(host)
|
553
585
|
tree = tree_connect("\\\\#{host}\\IPC$")
|
554
|
-
named_pipe = tree.
|
586
|
+
named_pipe = tree.open_pipe(filename: "srvsvc", write: true, read: true)
|
555
587
|
named_pipe.net_share_enum_all(host)
|
556
588
|
end
|
557
589
|
|
@@ -568,6 +600,7 @@ module RubySMB
|
|
568
600
|
self.smb2_message_id = 0
|
569
601
|
self.client_encryption_key = nil
|
570
602
|
self.server_encryption_key = nil
|
603
|
+
self.server_supports_multi_credit = false
|
571
604
|
end
|
572
605
|
|
573
606
|
# Requests a NetBIOS Session Service using the provided name.
|
@@ -605,7 +638,7 @@ module RubySMB
|
|
605
638
|
session_request.session_header.session_packet_type = RubySMB::Nbss::SESSION_REQUEST
|
606
639
|
session_request.called_name = called_name
|
607
640
|
session_request.calling_name = calling_name
|
608
|
-
session_request.session_header.
|
641
|
+
session_request.session_header.stream_protocol_length =
|
609
642
|
session_request.num_bytes - session_request.session_header.num_bytes
|
610
643
|
session_request
|
611
644
|
end
|
@@ -60,8 +60,7 @@ module RubySMB
|
|
60
60
|
raise RubySMB::Error::InvalidPacket.new(
|
61
61
|
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
62
62
|
expected_cmd: RubySMB::SMB1::Packet::SessionSetupLegacyResponse::COMMAND,
|
63
|
-
|
64
|
-
received_cmd: packet.smb_header.command
|
63
|
+
packet: packet
|
65
64
|
)
|
66
65
|
end
|
67
66
|
packet
|
@@ -154,8 +153,7 @@ module RubySMB
|
|
154
153
|
raise RubySMB::Error::InvalidPacket.new(
|
155
154
|
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
156
155
|
expected_cmd: RubySMB::SMB1::Packet::SessionSetupResponse::COMMAND,
|
157
|
-
|
158
|
-
received_cmd: packet.smb_header.command
|
156
|
+
packet: packet
|
159
157
|
)
|
160
158
|
end
|
161
159
|
packet
|
@@ -168,8 +166,7 @@ module RubySMB
|
|
168
166
|
raise RubySMB::Error::InvalidPacket.new(
|
169
167
|
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
170
168
|
expected_cmd: RubySMB::SMB1::Packet::SessionSetupResponse::COMMAND,
|
171
|
-
|
172
|
-
received_cmd: packet.smb_header.command
|
169
|
+
packet: packet
|
173
170
|
)
|
174
171
|
end
|
175
172
|
|
@@ -236,8 +233,7 @@ module RubySMB
|
|
236
233
|
raise RubySMB::Error::InvalidPacket.new(
|
237
234
|
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
238
235
|
expected_cmd: RubySMB::SMB2::Packet::SessionSetupResponse::COMMAND,
|
239
|
-
|
240
|
-
received_cmd: packet.smb2_header.command
|
236
|
+
packet: packet
|
241
237
|
)
|
242
238
|
end
|
243
239
|
|
@@ -251,8 +247,7 @@ module RubySMB
|
|
251
247
|
raise RubySMB::Error::InvalidPacket.new(
|
252
248
|
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
253
249
|
expected_cmd: RubySMB::SMB2::Packet::SessionSetupResponse::COMMAND,
|
254
|
-
|
255
|
-
received_cmd: packet.smb2_header.command
|
250
|
+
packet: packet
|
256
251
|
)
|
257
252
|
end
|
258
253
|
|
data/lib/ruby_smb/client/echo.rb
CHANGED
@@ -21,8 +21,7 @@ module RubySMB
|
|
21
21
|
raise RubySMB::Error::InvalidPacket.new(
|
22
22
|
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
23
23
|
expected_cmd: RubySMB::SMB1::Packet::EchoResponse::COMMAND,
|
24
|
-
|
25
|
-
received_cmd: response.smb_header.command
|
24
|
+
packet: response
|
26
25
|
)
|
27
26
|
end
|
28
27
|
response
|
@@ -40,8 +39,7 @@ module RubySMB
|
|
40
39
|
raise RubySMB::Error::InvalidPacket.new(
|
41
40
|
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
42
41
|
expected_cmd: RubySMB::SMB2::Packet::EchoResponse::COMMAND,
|
43
|
-
|
44
|
-
received_cmd: response.smb2_header.command
|
42
|
+
packet: response
|
45
43
|
)
|
46
44
|
end
|
47
45
|
response
|
@@ -83,16 +83,14 @@ module RubySMB
|
|
83
83
|
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
84
84
|
expected_cmd: RubySMB::SMB1::Packet::NegotiateResponseExtended::COMMAND,
|
85
85
|
expected_custom: "extended_security=1",
|
86
|
-
|
87
|
-
received_cmd: packet.smb_header.command,
|
86
|
+
packet: packet,
|
88
87
|
received_custom: "extended_security=#{extended_security}"
|
89
88
|
)
|
90
89
|
elsif packet.packet_smb_version == 'SMB2'
|
91
90
|
raise RubySMB::Error::InvalidPacket.new(
|
92
91
|
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
93
92
|
expected_cmd: RubySMB::SMB2::Packet::NegotiateResponse::COMMAND,
|
94
|
-
|
95
|
-
received_cmd: packet.smb2_header.command
|
93
|
+
packet: packet
|
96
94
|
)
|
97
95
|
else
|
98
96
|
raise RubySMB::Error::InvalidPacket, 'Unknown SMB protocol version'
|
@@ -140,6 +138,7 @@ module RubySMB
|
|
140
138
|
self.server_guid = packet.server_guid
|
141
139
|
self.server_start_time = packet.server_start_time.to_time if packet.server_start_time != 0
|
142
140
|
self.server_system_time = packet.system_time.to_time if packet.system_time != 0
|
141
|
+
self.server_supports_multi_credit = self.dialect != '0x0202' && packet&.capabilities&.large_mtu == 1
|
143
142
|
case self.dialect
|
144
143
|
when '0x02ff'
|
145
144
|
when '0x0300', '0x0302'
|
@@ -33,8 +33,7 @@ module RubySMB
|
|
33
33
|
raise RubySMB::Error::InvalidPacket.new(
|
34
34
|
expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
|
35
35
|
expected_cmd: RubySMB::SMB1::Packet::TreeConnectResponse::COMMAND,
|
36
|
-
|
37
|
-
received_cmd: response.smb_header.command
|
36
|
+
packet: response
|
38
37
|
)
|
39
38
|
end
|
40
39
|
unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
|
@@ -73,8 +72,7 @@ module RubySMB
|
|
73
72
|
raise RubySMB::Error::InvalidPacket.new(
|
74
73
|
expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
|
75
74
|
expected_cmd: RubySMB::SMB2::Packet::TreeConnectResponse::COMMAND,
|
76
|
-
|
77
|
-
received_cmd: response.smb2_header.command
|
75
|
+
packet: response
|
78
76
|
)
|
79
77
|
end
|
80
78
|
unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
|
@@ -24,19 +24,25 @@ module RubySMB
|
|
24
24
|
last_tree.id
|
25
25
|
end
|
26
26
|
|
27
|
-
def open(path, disposition=RubySMB::Dispositions::FILE_OPEN, write: false, read: true)
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
27
|
+
def open(path, disposition=RubySMB::Dispositions::FILE_OPEN, write: false, read: true, pipe: false)
|
28
|
+
if pipe
|
29
|
+
file = last_tree.open_pipe(filename: path, write: write, read: read, disposition: disposition)
|
30
|
+
else
|
31
|
+
file = last_tree.open_file(filename: path, write: write, read: read, disposition: disposition)
|
32
|
+
end
|
33
|
+
@last_file_id = if file.respond_to?(:guid)
|
34
|
+
# SMB2 uses guid
|
35
|
+
file.guid.to_binary_s
|
36
|
+
elsif file.respond_to?(:fid)
|
37
|
+
# SMB1 uses fid
|
38
|
+
file.fid.to_binary_s
|
39
|
+
end
|
40
|
+
@open_files[@last_file_id] = file
|
41
|
+
@last_file_id
|
36
42
|
end
|
37
43
|
|
38
44
|
def create_pipe(path, disposition=RubySMB::Dispositions::FILE_OPEN_IF)
|
39
|
-
open(path
|
45
|
+
open(path, disposition, write: true, read: true, pipe: true)
|
40
46
|
end
|
41
47
|
|
42
48
|
#Writes data to an open file handle
|
@@ -6,7 +6,7 @@ module RubySMB
|
|
6
6
|
share = "\\\\#{host}\\IPC$"
|
7
7
|
tree = @tree_connects.find {|tree| tree.share == share}
|
8
8
|
tree = tree_connect(share) unless tree
|
9
|
-
named_pipe = tree.
|
9
|
+
named_pipe = tree.open_pipe(filename: "winreg", write: true, read: true)
|
10
10
|
if block_given?
|
11
11
|
res = yield named_pipe
|
12
12
|
named_pipe.close
|
data/lib/ruby_smb/dcerpc.rb
CHANGED
@@ -10,15 +10,19 @@ module RubySMB
|
|
10
10
|
require 'ruby_smb/dcerpc/ptypes'
|
11
11
|
require 'ruby_smb/dcerpc/p_syntax_id_t'
|
12
12
|
require 'ruby_smb/dcerpc/rrp_unicode_string'
|
13
|
+
require 'ruby_smb/dcerpc/rpc_security_attributes'
|
13
14
|
require 'ruby_smb/dcerpc/pdu_header'
|
14
15
|
require 'ruby_smb/dcerpc/srvsvc'
|
16
|
+
require 'ruby_smb/dcerpc/svcctl'
|
15
17
|
require 'ruby_smb/dcerpc/winreg'
|
18
|
+
require 'ruby_smb/dcerpc/netlogon'
|
16
19
|
require 'ruby_smb/dcerpc/request'
|
17
20
|
require 'ruby_smb/dcerpc/response'
|
18
21
|
require 'ruby_smb/dcerpc/bind'
|
19
22
|
require 'ruby_smb/dcerpc/bind_ack'
|
20
23
|
|
21
24
|
|
25
|
+
|
22
26
|
# Bind to the remote server interface endpoint.
|
23
27
|
#
|
24
28
|
# @param options [Hash] the options to pass to the Bind request packet. At least, :endpoint must but provided with an existing Dcerpc class
|