ruby_smb 0.0.8 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/examples/tree_connect.rb +27 -0
  5. data/lib/ruby_smb/client.rb +25 -2
  6. data/lib/ruby_smb/client/authentication.rb +5 -6
  7. data/lib/ruby_smb/client/negotiation.rb +2 -3
  8. data/lib/ruby_smb/client/signing.rb +6 -2
  9. data/lib/ruby_smb/client/tree_connect.rb +86 -0
  10. data/lib/ruby_smb/generic_packet.rb +1 -1
  11. data/lib/ruby_smb/smb1.rb +1 -1
  12. data/lib/ruby_smb/smb1/bit_field.rb +4 -0
  13. data/lib/ruby_smb/smb1/bit_field/directory_access_mask.rb +38 -0
  14. data/lib/ruby_smb/smb1/bit_field/file_access_mask.rb +38 -0
  15. data/lib/ruby_smb/smb1/bit_field/optional_support.rb +19 -0
  16. data/lib/ruby_smb/smb1/bit_field/tree_connect_flags.rb +18 -0
  17. data/lib/ruby_smb/smb1/commands.rb +2 -0
  18. data/lib/ruby_smb/smb1/packet.rb +4 -0
  19. data/lib/ruby_smb/smb1/packet/tree_connect_request.rb +34 -0
  20. data/lib/ruby_smb/smb1/packet/tree_connect_response.rb +74 -0
  21. data/lib/ruby_smb/smb1/packet/tree_disconnect_request.rb +29 -0
  22. data/lib/ruby_smb/smb1/packet/tree_disconnect_response.rb +30 -0
  23. data/lib/ruby_smb/smb1/tree.rb +55 -0
  24. data/lib/ruby_smb/smb2.rb +1 -0
  25. data/lib/ruby_smb/smb2/bit_field.rb +4 -0
  26. data/lib/ruby_smb/smb2/bit_field/directory_access_mask.rb +38 -0
  27. data/lib/ruby_smb/smb2/bit_field/file_access_mask.rb +38 -0
  28. data/lib/ruby_smb/smb2/bit_field/share_capabailities.rb +21 -0
  29. data/lib/ruby_smb/smb2/bit_field/share_flags.rb +75 -0
  30. data/lib/ruby_smb/smb2/packet.rb +5 -0
  31. data/lib/ruby_smb/smb2/packet/error_packet.rb +15 -0
  32. data/lib/ruby_smb/smb2/packet/tree_connect_request.rb +27 -0
  33. data/lib/ruby_smb/smb2/packet/tree_connect_response.rb +50 -0
  34. data/lib/ruby_smb/smb2/packet/tree_disconnect_request.rb +21 -0
  35. data/lib/ruby_smb/smb2/packet/tree_disconnect_response.rb +22 -0
  36. data/lib/ruby_smb/smb2/smb2_header.rb +3 -3
  37. data/lib/ruby_smb/smb2/tree.rb +51 -0
  38. data/lib/ruby_smb/version.rb +1 -1
  39. data/ruby_smb.gemspec +1 -1
  40. data/spec/lib/ruby_smb/client_spec.rb +114 -4
  41. data/spec/lib/ruby_smb/smb1/bit_field/directory_access_mask_spec.rb +190 -0
  42. data/spec/lib/ruby_smb/smb1/bit_field/file_access_mask_spec.rb +190 -0
  43. data/spec/lib/ruby_smb/smb1/bit_field/optional_support_spec.rb +52 -0
  44. data/spec/lib/ruby_smb/smb1/bit_field/tree_connect_flags_spec.rb +37 -0
  45. data/spec/lib/ruby_smb/smb1/packet/tree_connect_request_spec.rb +53 -0
  46. data/spec/lib/ruby_smb/smb1/packet/tree_connect_response_spec.rb +86 -0
  47. data/spec/lib/ruby_smb/smb1/packet/tree_disconnect_request_spec.rb +40 -0
  48. data/spec/lib/ruby_smb/smb1/packet/tree_disconnect_response_spec.rb +40 -0
  49. data/spec/lib/ruby_smb/smb1/tree_spec.rb +55 -0
  50. data/spec/lib/ruby_smb/smb2/bit_field/directory_access_mask_spec.rb +190 -0
  51. data/spec/lib/ruby_smb/smb2/bit_field/file_access_mask_spec.rb +190 -0
  52. data/spec/lib/ruby_smb/smb2/bit_field/share_capabilities_spec.rb +54 -0
  53. data/spec/lib/ruby_smb/smb2/bit_field/share_flags_spec.rb +184 -0
  54. data/spec/lib/ruby_smb/smb2/packet/tree_connect_request_spec.rb +49 -0
  55. data/spec/lib/ruby_smb/smb2/packet/tree_connect_response_spec.rb +57 -0
  56. data/spec/lib/ruby_smb/smb2/packet/tree_disconnect_request_spec.rb +30 -0
  57. data/spec/lib/ruby_smb/smb2/packet/tree_disconnect_response_spec.rb +30 -0
  58. data/spec/lib/ruby_smb/smb2/tree_spec.rb +54 -0
  59. metadata +63 -6
  60. metadata.gz.sig +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 203527ee7c807b85b3af96aea81bdc9f543b5f16
4
- data.tar.gz: f80aa766405b6b813a5ac9a65aca3778d24f20a0
3
+ metadata.gz: 4447c748fa5ae3b4bade1f7da2f90b05e98f90e3
4
+ data.tar.gz: 0a077bd853a42f08210f527475965459347570a0
5
5
  SHA512:
6
- metadata.gz: 79add85ae366057d7c77cafa684c6c3d6e842777bbf161d768dd8e206a344f712fc3cf5684a0d625c77162e1a07f8dcb7e43bf92292b9fedd0bfd8169a873375
7
- data.tar.gz: 5866aa5f7aed28b0dfa8b3c147434ebefe6a6e4964618ba7d4762349f5090e826c1461950ec79a53fc52074f75eb99abc8b6a488d9901f2701b537c28aec5601
6
+ metadata.gz: 0284a70fde3ac94578b232fb30cfd0a2a579947104a700371cd04f78b9b29ff295ac4f90423fbb280848fc35f1095b42c9f3caa0c229dbee02a1f8480466b28e
7
+ data.tar.gz: 94ba89646185e15f2c2a945849948287fb01734523c092fbe410f0e8d42d31b518c53eb2689192d64358fda5493fbf791d12e3cd0e3ce2102828f0345910ad13
checksums.yaml.gz.sig CHANGED
Binary file
data.tar.gz.sig CHANGED
Binary file
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/ruby
2
+
3
+ # This example script is used for testing TreeConnect functionality
4
+ # It will attempt to connect to a specific share and then disconnect.
5
+ # Example usage: ruby tree_connect.rb 192.168.172.138 msfadmin msfadmin TEST_SHARE
6
+ # This will try to connect to \\192.168.172.138\TEST_SHARE with the msfadmin:msfadmin credentials
7
+
8
+ require 'bundler/setup'
9
+ require 'ruby_smb'
10
+
11
+ address = ARGV[0]
12
+ username = ARGV[1]
13
+ password = ARGV[2]
14
+ share = ARGV[3]
15
+ path = "\\\\#{address}\\#{share}"
16
+
17
+ sock = TCPSocket.new address, 445
18
+ dispatcher = RubySMB::Dispatcher::Socket.new(sock)
19
+
20
+ client = RubySMB::Client.new(dispatcher, smb1: true, smb2: true, username: username, password: password)
21
+ protocol = client.negotiate
22
+ status = client.authenticate
23
+
24
+ puts "#{protocol} : #{status}"
25
+
26
+ tree = client.smb2_tree_connect(path)
27
+ tree.disconnect!
@@ -6,10 +6,12 @@ module RubySMB
6
6
  require 'ruby_smb/client/negotiation'
7
7
  require 'ruby_smb/client/authentication'
8
8
  require 'ruby_smb/client/signing'
9
+ require 'ruby_smb/client/tree_connect'
9
10
 
10
11
  include RubySMB::Client::Negotiation
11
12
  include RubySMB::Client::Authentication
12
13
  include RubySMB::Client::Signing
14
+ include RubySMB::Client::TreeConnect
13
15
 
14
16
  # The Default SMB1 Dialect string used in an SMB1 Negotiate Request
15
17
  SMB1_DIALECT_SMB1_DEFAULT = "NT LM 0.12"
@@ -116,6 +118,20 @@ module RubySMB
116
118
  @smb2_message_id = 0
117
119
  end
118
120
 
121
+ # Sets the message id field in an SMB2 packet's
122
+ # header to the one tracked by the client. It then increments
123
+ # the counter on the client.
124
+ #
125
+ # @param packet [RubySMB::GenericPacket] the packet to set the message id for
126
+ # @return [RubySMB::GenericPacket] the modified packet
127
+ def increment_smb_message_id(packet)
128
+ if packet.smb2_header.message_id == 0 && self.smb2_message_id != 0
129
+ packet.smb2_header.message_id = self.smb2_message_id
130
+ self.smb2_message_id += 1
131
+ end
132
+ packet
133
+ end
134
+
119
135
  def login(username: self.username, password: self.password, domain: self.domain, local_workstation: self.local_workstation )
120
136
  @domain = domain
121
137
  @local_workstation = local_workstation
@@ -141,15 +157,22 @@ module RubySMB
141
157
  def send_recv(packet)
142
158
  case packet.packet_smb_version
143
159
  when 'SMB1'
160
+ if self.user_id
161
+ packet.smb_header.uid = self.user_id
162
+ end
144
163
  packet = smb1_sign(packet)
145
164
  when 'SMB2'
146
- packet = smb2_sign(packet)
165
+ packet = increment_smb_message_id(packet)
166
+ packet.smb2_header.session_id = self.session_id
167
+ unless packet.is_a?(RubySMB::SMB2::Packet::SessionSetupRequest)
168
+ packet = smb2_sign(packet)
169
+ end
147
170
  else
148
171
  packet = packet
149
172
  end
150
173
  dispatcher.send_packet(packet)
151
174
  raw_response = dispatcher.recv_packet
152
- if self.sequence_counter > 0
175
+ if self.signing_required && !self.session_key.empty?
153
176
  self.sequence_counter += 1
154
177
  end
155
178
  raw_response
@@ -136,12 +136,11 @@ module RubySMB
136
136
  response = smb2_ntlmssp_negotiate
137
137
  challenge_packet = smb2_ntlmssp_challenge_packet(response)
138
138
  session_id = challenge_packet.smb2_header.session_id
139
+ self.session_id = session_id
139
140
  challenge_message = smb2_type2_message(challenge_packet)
140
141
  raw = smb2_ntlmssp_authenticate(challenge_message, session_id)
141
142
  response = smb2_ntlmssp_final_packet(raw)
142
- response_code = response.status_code
143
- self.session_id = response.smb2_header.session_id if response_code.name == "STATUS_SUCCESS"
144
- response_code
143
+ response.status_code
145
144
  end
146
145
 
147
146
  # Takes the raw binary string and returns a {RubySMB::SMB2::Packet::SessionSetupResponse}
@@ -185,7 +184,9 @@ module RubySMB
185
184
  type1_message = ntlm_client.init_context
186
185
  packet = RubySMB::SMB2::Packet::SessionSetupRequest.new
187
186
  packet.set_type1_blob(type1_message.serialize)
188
- packet.smb2_header.message_id = 1 #self.smb2_message_id
187
+ # This Message ID should always be 1, but thanks to Multi-Protocol Negotiation
188
+ # the Message ID can be out of sync at this point so we re-synch it here.
189
+ packet.smb2_header.message_id = 1
189
190
  self.smb2_message_id = 2
190
191
  packet
191
192
  end
@@ -225,8 +226,6 @@ module RubySMB
225
226
  packet = RubySMB::SMB2::Packet::SessionSetupRequest.new
226
227
  packet.smb2_header.session_id = session_id
227
228
  packet.set_type3_blob(type3_message.serialize)
228
- packet.smb2_header.message_id = self.smb2_message_id
229
- self.smb2_message_id += 1
230
229
  packet
231
230
  end
232
231
 
@@ -1,3 +1,4 @@
1
+ require 'securerandom'
1
2
  module RubySMB
2
3
  class Client
3
4
  # This module holds all of the methods backing the {RubySMB::Client#negotiate} method
@@ -114,11 +115,9 @@ module RubySMB
114
115
  # @ return [RubySMB::SMB2::Packet::NegotiateRequest] a completed SMB2 Negotiate Request packet
115
116
  def smb2_negotiate_request
116
117
  packet = RubySMB::SMB2::Packet::NegotiateRequest.new
117
- packet.smb2_header.message_id = self.smb2_message_id
118
- # Increment the message id when doing SMB2
119
- self.smb2_message_id += 1
120
118
  packet.security_mode.signing_enabled = 1
121
119
  packet.add_dialect(SMB2_DIALECT_DEFAULT)
120
+ packet.client_guid = SecureRandom.random_bytes(16)
122
121
  packet
123
122
  end
124
123
  end
@@ -17,7 +17,9 @@ module RubySMB
17
17
  # @return [RubySMB::GenericPacket] the packet, signed if needed
18
18
  def smb1_sign(packet)
19
19
  if self.signing_required && !self.session_key.empty?
20
- packet.smb_header.security_features = self.sequence_counter
20
+ # Pack the Sequence counter into a int64le
21
+ packed_sequence_counter = [self.sequence_counter].pack('Q<')
22
+ packet.smb_header.security_features = packed_sequence_counter
21
23
  signature = OpenSSL::Digest::MD5.digest(self.session_key + packet.to_binary_s)[0,8]
22
24
  packet.smb_header.security_features = signature
23
25
  self.sequence_counter += 1
@@ -35,8 +37,10 @@ module RubySMB
35
37
  # @return [RubySMB::GenericPacket] the packet, signed if needed
36
38
  def smb2_sign(packet)
37
39
  if self.signing_required && !self.session_key.empty?
40
+ packet.smb2_header.flags.signed = 1
41
+ packet.smb2_header.signature = "\x00" * 16
38
42
  hmac = OpenSSL::HMAC.digest(OpenSSL::Digest::SHA256.new, self.session_key, packet.to_binary_s)
39
- packet.smb2_header.signature = hmac
43
+ packet.smb2_header.signature = hmac[0,16]
40
44
  packet
41
45
  else
42
46
  packet
@@ -0,0 +1,86 @@
1
+ module RubySMB
2
+ class Client
3
+
4
+ # This module contains all of the methods for a client to connect to a
5
+ # remote share or named pipe.
6
+ module TreeConnect
7
+
8
+ #
9
+ # SMB 1 Methods
10
+ #
11
+
12
+ # Sends a request to connect to a remote Tree and returns the
13
+ # {RubySMB::SMB1::Tree}
14
+ #
15
+ # @param share [String] the share path to connect to
16
+ # @return [RubySMB::SMB1::Tree] the connected Tree
17
+ def smb1_tree_connect(share)
18
+ request = RubySMB::SMB1::Packet::TreeConnectRequest.new
19
+ request.smb_header.tid = 65535
20
+ request.data_block.path = share
21
+ raw_response = send_recv(request)
22
+ begin
23
+ response = RubySMB::SMB1::Packet::TreeConnectResponse.read(raw_response)
24
+ rescue EOFError
25
+ response = RubySMB::SMB1::Packet::ErrorPacket.read(raw_response)
26
+ end
27
+ smb1_tree_from_response(share, response)
28
+ end
29
+
30
+ # Parses a Tree structure from a Tree Connect Response
31
+ #
32
+ # @param share [String] the share path to connect to
33
+ # @param response [RubySMB::SMB1::Packet::TreeConnectResponse] the response packet to parse into our Tree
34
+ # @return [RubySMB::SMB1::Tree]
35
+ def smb1_tree_from_response(share,response)
36
+ unless response.smb_header.command == RubySMB::SMB1::Commands::SMB_COM_TREE_CONNECT
37
+ raise RubySMB::Error::InvalidPacket, "Not a TreeConnectResponse"
38
+ end
39
+ unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
40
+ raise RubySMB::Error::UnexpectedStatusCode, response.status_code.name
41
+ end
42
+ RubySMB::SMB1::Tree.new(client: self, share: share, response: response)
43
+ end
44
+
45
+ #
46
+ # SMB2 Methods
47
+ #
48
+
49
+ # Sends a request to connect to a remote Tree and returns the
50
+ # {RubySMB::SMB2::Tree}
51
+ #
52
+ # @param share [String] the share path to connect to
53
+ # @return [RubySMB::SMB2::Tree] the connected Tree
54
+ def smb2_tree_connect(share)
55
+ request = RubySMB::SMB2::Packet::TreeConnectRequest.new
56
+ request.smb2_header.tree_id = 65535
57
+ request.encode_path(share)
58
+ raw_response = send_recv(request)
59
+ begin
60
+ response = RubySMB::SMB2::Packet::TreeConnectResponse.read(raw_response)
61
+ rescue EOFError
62
+ response = RubySMB::SMB2::Packet::ErrorPacket.read(raw_response)
63
+ end
64
+ smb2_tree_from_response(share, response)
65
+ end
66
+
67
+ # Parses a Tree structure from a Tree Connect Response
68
+ #
69
+ # @param share [String] the share path to connect to
70
+ # @param response [RubySMB::SMB2::Packet::TreeConnectResponse] the response packet to parse into our Tree
71
+ # @return [RubySMB::SMB2::Tree]
72
+ def smb2_tree_from_response(share,response)
73
+ unless response.smb2_header.command == RubySMB::SMB2::Commands::TREE_CONNECT
74
+ raise RubySMB::Error::InvalidPacket, "Not a TreeConnectResponse"
75
+ end
76
+ unless response.status_code == WindowsError::NTStatus::STATUS_SUCCESS
77
+ raise RubySMB::Error::UnexpectedStatusCode, response.status_code.name
78
+ end
79
+ RubySMB::SMB2::Tree.new(client: self, share: share, response: response)
80
+ end
81
+
82
+ end
83
+
84
+
85
+ end
86
+ end
@@ -161,7 +161,7 @@ module RubySMB
161
161
  def process_array_field(array_field, depth)
162
162
  array_field_str = ''
163
163
  array_field.each do |sub_field|
164
- fields = sub_field.class.fields.fields
164
+ fields = sub_field.class.fields.raw_fields
165
165
  sub_field_hashes = self.class.walk_fields(fields)
166
166
  sub_field_hashes.each do |sub_field_hash|
167
167
  name = sub_field_hash[:name]
data/lib/ruby_smb/smb1.rb CHANGED
@@ -12,5 +12,5 @@ module RubySMB::SMB1
12
12
  require 'ruby_smb/smb1/data_block'
13
13
  require 'ruby_smb/smb1/dialect'
14
14
  require 'ruby_smb/smb1/packet'
15
-
15
+ require 'ruby_smb/smb1/tree'
16
16
  end
@@ -5,6 +5,10 @@ module RubySMB
5
5
  require 'ruby_smb/smb1/bit_field/header_flags2'
6
6
  require 'ruby_smb/smb1/bit_field/security_mode'
7
7
  require 'ruby_smb/smb1/bit_field/capabilities'
8
+ require 'ruby_smb/smb1/bit_field/tree_connect_flags'
9
+ require 'ruby_smb/smb1/bit_field/optional_support'
10
+ require 'ruby_smb/smb1/bit_field/directory_access_mask'
11
+ require 'ruby_smb/smb1/bit_field/file_access_mask'
8
12
  end
9
13
  end
10
14
  end
@@ -0,0 +1,38 @@
1
+ module RubySMB
2
+ module SMB1
3
+ module BitField
4
+ # An Access Mask bit field used to describe the permissions on a Directory, as defined in
5
+ # [2.2.1.4.2 Directory_Access_Mask](https://msdn.microsoft.com/en-us/library/ff470234.aspx)
6
+ class DirectoryAccessMask < BinData::Record
7
+ endian :little
8
+ bit1 :read_attr, label: 'Read Attributes'
9
+ bit1 :delete_child, label: 'Delete Child'
10
+ bit1 :traverse, label: 'Traverse'
11
+ bit1 :write_ea, label: 'Write Extended Attributes'
12
+ bit1 :read_ea, label: 'Read Extended Attributes'
13
+ bit1 :add_subdir, label: 'Add Subdirectory'
14
+ bit1 :add_file, label: 'Add File'
15
+ bit1 :list, label: 'List Directory'
16
+ # byte boundary
17
+ bit7 :reserved, label: 'Reserved Space'
18
+ bit1 :write_attr, label: 'Write Attributes'
19
+
20
+ # byte boundary
21
+ bit3 :reserved2, label: 'Reserved Space'
22
+ bit1 :synchronize, label: 'Synchronize'
23
+ bit1 :write_owner, label: 'Write Owner'
24
+ bit1 :write_dac, label: 'Write DAC'
25
+ bit1 :read_control, label: 'Read Control'
26
+ bit1 :delete_access, label: 'Delete'
27
+ # byte boundary
28
+ bit1 :generic_read, label: 'Generic Read'
29
+ bit1 :generic_write, label: 'Generic Write'
30
+ bit1 :generic_execute, label: 'Generic Execute'
31
+ bit1 :generic_all, label: 'Generic All'
32
+ bit2 :reserved3
33
+ bit1 :maximum, label: 'Maximum Allowed'
34
+ bit1 :system_security, label: 'System Security'
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,38 @@
1
+ module RubySMB
2
+ module SMB1
3
+ module BitField
4
+ # An Access Mask bit field used to describe the permissions on a File, Printer, or named Pipe. As defined in
5
+ # [2.2.1.4.1 File_Pipe_Printer_Access_Mask](https://msdn.microsoft.com/en-us/library/ff469915.aspx)
6
+ class FileAccessMask < BinData::Record
7
+ endian :little
8
+ bit1 :read_attr, label: 'Read Attributes'
9
+ bit1 :delete_child, label: 'Delete Child'
10
+ bit1 :execute, label: 'Traverse'
11
+ bit1 :write_ea, label: 'Write Extended Attributes'
12
+ bit1 :read_ea, label: 'Read Extended Attributes'
13
+ bit1 :append_data, label: 'Append Data'
14
+ bit1 :write_data, label: 'Write Data'
15
+ bit1 :read_data, label: 'Read Data'
16
+ # byte boundary
17
+ bit7 :reserved, label: 'Reserved Space'
18
+ bit1 :write_attr, label: 'Write Attributes'
19
+
20
+ # byte boundary
21
+ bit3 :reserved2, label: 'Reserved Space'
22
+ bit1 :synchronize, label: 'Synchronize'
23
+ bit1 :write_owner, label: 'Write Owner'
24
+ bit1 :write_dac, label: 'Write DAC'
25
+ bit1 :read_control, label: 'Read Control'
26
+ bit1 :delete_access, label: 'Delete'
27
+ # byte boundary
28
+ bit1 :generic_read, label: 'Generic Read'
29
+ bit1 :generic_write, label: 'Generic Write'
30
+ bit1 :generic_execute, label: 'Generic Execute'
31
+ bit1 :generic_all, label: 'Generic All'
32
+ bit2 :reserved3
33
+ bit1 :maximum, label: 'Maximum Allowed'
34
+ bit1 :system_security, label: 'System Security'
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,19 @@
1
+ module RubySMB
2
+ module SMB1
3
+ module BitField
4
+ # The OptionalSupport bit-field for an SMB1 TreeConnect Response Packet
5
+ # [2.2.4.7.2 Server Response Extensions](https://msdn.microsoft.com/en-us/library/cc246331.aspx)
6
+ class OptionalSupport < BinData::Record
7
+ endian :little
8
+ bit2 :reserved, label: 'Reserved Space', initial_value: 0
9
+ bit1 :extended_signature, label: 'Extended Signature', initial_value: 0
10
+ bit1 :unique_filename, label: 'Unique Filename', initial_value: 0
11
+ bit2 :csc_mask, label: 'CSC Mask', initial_value: 0
12
+ bit1 :dfs, label: 'DFS Share', initial_value: 0
13
+ bit1 :search, label: 'Exclusive Search Bits', initial_value: 1
14
+ bit8 :reserved2, label: 'Reserved Space', initial_value: 0
15
+
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,18 @@
1
+ module RubySMB
2
+ module SMB1
3
+ module BitField
4
+ # The Flags bit-field for an SMB1 TreeConnect Request Packet
5
+ # [2.2.4.7.1 Client Request Extensions](https://msdn.microsoft.com/en-us/library/cc246330.aspx)
6
+ class TreeConnectFlags < BinData::Record
7
+ endian :little
8
+ bit4 :reserved, label: 'Reserved Space', initial_value: 0
9
+ bit1 :extended_response, label: 'Extended Response', initial_value: 1
10
+ bit1 :extended_signature, label: 'Extended Signature', initial_value: 0
11
+ bit1 :reserved2, label: 'Reserved Space', initial_value: 0
12
+ bit1 :disconnect, label: 'Disconnect Tree', initial_value: 0
13
+ bit4 :reserved3, label: 'Reserved Space', initial_value: 0
14
+ bit4 :reserved4, label: 'Reserved Space', initial_value: 0
15
+ end
16
+ end
17
+ end
18
+ end
@@ -1,8 +1,10 @@
1
1
  module RubySMB
2
2
  module SMB1
3
3
  module Commands
4
+ SMB_COM_TREE_DISCONNECT = 0x71
4
5
  SMB_COM_NEGOTIATE = 0x72
5
6
  SMB_COM_SESSION_SETUP = 0x73
7
+ SMB_COM_TREE_CONNECT = 0x75
6
8
  SMB_COM_NO_ANDX_COMMAND = 0xFF
7
9
  end
8
10
  end
@@ -7,6 +7,10 @@ module RubySMB
7
7
  require 'ruby_smb/smb1/packet/negotiate_response_extended'
8
8
  require 'ruby_smb/smb1/packet/session_setup_request'
9
9
  require 'ruby_smb/smb1/packet/session_setup_response'
10
+ require 'ruby_smb/smb1/packet/tree_connect_request'
11
+ require 'ruby_smb/smb1/packet/tree_connect_response'
12
+ require 'ruby_smb/smb1/packet/tree_disconnect_request'
13
+ require 'ruby_smb/smb1/packet/tree_disconnect_response'
10
14
  end
11
15
  end
12
16
  end
@@ -0,0 +1,34 @@
1
+ module RubySMB
2
+ module SMB1
3
+ module Packet
4
+
5
+ # This class represents an SMB1 TreeConnect Request Packet as defined in
6
+ # [2.2.4.7.1 Client Request Extensions](https://msdn.microsoft.com/en-us/library/cc246330.aspx)
7
+ class TreeConnectRequest < RubySMB::GenericPacket
8
+
9
+ # A SMB1 Parameter Block as defined by the {TreeConnectRequest}
10
+ class ParameterBlock < RubySMB::SMB1::ParameterBlock
11
+ and_x_block :andx_block
12
+ tree_connect_flags :flags
13
+ uint16 :password_length, label: 'Password Length', initial_value: 0x01
14
+ end
15
+
16
+ class DataBlock < RubySMB::SMB1::DataBlock
17
+ stringz :password, label: 'Password Field', initial_value: '', length: lambda { self.parent.parameter_block.password_length }
18
+ stringz :path, label: 'Resource Path'
19
+ stringz :service, label: 'Resource Type', initial_value: '?????'
20
+ end
21
+
22
+ smb_header :smb_header
23
+ parameter_block :parameter_block
24
+ data_block :data_block
25
+
26
+ def initialize_instance
27
+ super
28
+ smb_header.command = RubySMB::SMB1::Commands::SMB_COM_TREE_CONNECT
29
+ end
30
+
31
+ end
32
+ end
33
+ end
34
+ end