ruby_smb 1.0.3 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (200) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/.travis.yml +3 -2
  5. data/Gemfile +6 -2
  6. data/README.md +35 -47
  7. data/examples/enum_registry_key.rb +28 -0
  8. data/examples/enum_registry_values.rb +30 -0
  9. data/examples/negotiate.rb +51 -8
  10. data/examples/pipes.rb +2 -1
  11. data/examples/read_file_encryption.rb +56 -0
  12. data/examples/read_registry_key_value.rb +32 -0
  13. data/lib/ruby_smb.rb +4 -1
  14. data/lib/ruby_smb/client.rb +233 -22
  15. data/lib/ruby_smb/client/authentication.rb +70 -33
  16. data/lib/ruby_smb/client/echo.rb +20 -2
  17. data/lib/ruby_smb/client/encryption.rb +62 -0
  18. data/lib/ruby_smb/client/negotiation.rb +172 -24
  19. data/lib/ruby_smb/client/signing.rb +19 -0
  20. data/lib/ruby_smb/client/tree_connect.rb +24 -18
  21. data/lib/ruby_smb/client/utils.rb +8 -7
  22. data/lib/ruby_smb/client/winreg.rb +46 -0
  23. data/lib/ruby_smb/crypto.rb +30 -0
  24. data/lib/ruby_smb/dcerpc.rb +38 -0
  25. data/lib/ruby_smb/dcerpc/bind.rb +2 -2
  26. data/lib/ruby_smb/dcerpc/bind_ack.rb +2 -2
  27. data/lib/ruby_smb/dcerpc/error.rb +3 -0
  28. data/lib/ruby_smb/dcerpc/ndr.rb +95 -16
  29. data/lib/ruby_smb/dcerpc/pdu_header.rb +1 -1
  30. data/lib/ruby_smb/dcerpc/request.rb +28 -9
  31. data/lib/ruby_smb/dcerpc/rrp_unicode_string.rb +35 -0
  32. data/lib/ruby_smb/dcerpc/srvsvc.rb +10 -0
  33. data/lib/ruby_smb/dcerpc/srvsvc/net_share_enum_all.rb +9 -0
  34. data/lib/ruby_smb/dcerpc/winreg.rb +340 -0
  35. data/lib/ruby_smb/dcerpc/winreg/close_key_request.rb +24 -0
  36. data/lib/ruby_smb/dcerpc/winreg/close_key_response.rb +27 -0
  37. data/lib/ruby_smb/dcerpc/winreg/enum_key_request.rb +45 -0
  38. data/lib/ruby_smb/dcerpc/winreg/enum_key_response.rb +42 -0
  39. data/lib/ruby_smb/dcerpc/winreg/enum_value_request.rb +39 -0
  40. data/lib/ruby_smb/dcerpc/winreg/enum_value_response.rb +36 -0
  41. data/lib/ruby_smb/dcerpc/winreg/open_key_request.rb +34 -0
  42. data/lib/ruby_smb/dcerpc/winreg/open_key_response.rb +25 -0
  43. data/lib/ruby_smb/dcerpc/winreg/open_root_key_request.rb +43 -0
  44. data/lib/ruby_smb/dcerpc/winreg/open_root_key_response.rb +35 -0
  45. data/lib/ruby_smb/dcerpc/winreg/query_info_key_request.rb +27 -0
  46. data/lib/ruby_smb/dcerpc/winreg/query_info_key_response.rb +40 -0
  47. data/lib/ruby_smb/dcerpc/winreg/query_value_request.rb +39 -0
  48. data/lib/ruby_smb/dcerpc/winreg/query_value_response.rb +57 -0
  49. data/lib/ruby_smb/dcerpc/winreg/regsam.rb +40 -0
  50. data/lib/ruby_smb/dispatcher/socket.rb +4 -3
  51. data/lib/ruby_smb/error.rb +68 -2
  52. data/lib/ruby_smb/generic_packet.rb +33 -4
  53. data/lib/ruby_smb/smb1/commands.rb +1 -1
  54. data/lib/ruby_smb/smb1/file.rb +66 -15
  55. data/lib/ruby_smb/smb1/packet/close_request.rb +2 -5
  56. data/lib/ruby_smb/smb1/packet/close_response.rb +2 -1
  57. data/lib/ruby_smb/smb1/packet/echo_request.rb +2 -4
  58. data/lib/ruby_smb/smb1/packet/echo_response.rb +2 -1
  59. data/lib/ruby_smb/smb1/packet/empty_packet.rb +10 -1
  60. data/lib/ruby_smb/smb1/packet/logoff_request.rb +2 -4
  61. data/lib/ruby_smb/smb1/packet/logoff_response.rb +2 -1
  62. data/lib/ruby_smb/smb1/packet/negotiate_request.rb +2 -5
  63. data/lib/ruby_smb/smb1/packet/negotiate_response.rb +3 -7
  64. data/lib/ruby_smb/smb1/packet/negotiate_response_extended.rb +4 -4
  65. data/lib/ruby_smb/smb1/packet/nt_create_andx_request.rb +2 -4
  66. data/lib/ruby_smb/smb1/packet/nt_create_andx_response.rb +2 -1
  67. data/lib/ruby_smb/smb1/packet/nt_trans/create_request.rb +2 -1
  68. data/lib/ruby_smb/smb1/packet/nt_trans/create_response.rb +2 -1
  69. data/lib/ruby_smb/smb1/packet/nt_trans/request.rb +2 -4
  70. data/lib/ruby_smb/smb1/packet/nt_trans/response.rb +2 -1
  71. data/lib/ruby_smb/smb1/packet/read_andx_request.rb +2 -5
  72. data/lib/ruby_smb/smb1/packet/read_andx_response.rb +2 -1
  73. data/lib/ruby_smb/smb1/packet/session_setup_legacy_request.rb +2 -1
  74. data/lib/ruby_smb/smb1/packet/session_setup_legacy_response.rb +3 -2
  75. data/lib/ruby_smb/smb1/packet/session_setup_request.rb +2 -5
  76. data/lib/ruby_smb/smb1/packet/session_setup_response.rb +3 -2
  77. data/lib/ruby_smb/smb1/packet/trans/peek_nmpipe_request.rb +0 -1
  78. data/lib/ruby_smb/smb1/packet/trans/peek_nmpipe_response.rb +3 -2
  79. data/lib/ruby_smb/smb1/packet/trans/request.rb +2 -5
  80. data/lib/ruby_smb/smb1/packet/trans/response.rb +2 -1
  81. data/lib/ruby_smb/smb1/packet/trans/transact_nmpipe_request.rb +1 -1
  82. data/lib/ruby_smb/smb1/packet/trans/transact_nmpipe_response.rb +1 -1
  83. data/lib/ruby_smb/smb1/packet/trans2/find_first2_request.rb +2 -1
  84. data/lib/ruby_smb/smb1/packet/trans2/find_first2_response.rb +8 -2
  85. data/lib/ruby_smb/smb1/packet/trans2/find_next2_request.rb +2 -1
  86. data/lib/ruby_smb/smb1/packet/trans2/find_next2_response.rb +8 -2
  87. data/lib/ruby_smb/smb1/packet/trans2/open2_request.rb +2 -1
  88. data/lib/ruby_smb/smb1/packet/trans2/open2_response.rb +2 -1
  89. data/lib/ruby_smb/smb1/packet/trans2/request.rb +2 -4
  90. data/lib/ruby_smb/smb1/packet/trans2/request_secondary.rb +2 -4
  91. data/lib/ruby_smb/smb1/packet/trans2/response.rb +2 -1
  92. data/lib/ruby_smb/smb1/packet/trans2/set_file_information_request.rb +2 -1
  93. data/lib/ruby_smb/smb1/packet/trans2/set_file_information_response.rb +2 -1
  94. data/lib/ruby_smb/smb1/packet/tree_connect_request.rb +2 -4
  95. data/lib/ruby_smb/smb1/packet/tree_connect_response.rb +13 -3
  96. data/lib/ruby_smb/smb1/packet/tree_disconnect_request.rb +2 -4
  97. data/lib/ruby_smb/smb1/packet/tree_disconnect_response.rb +2 -1
  98. data/lib/ruby_smb/smb1/packet/write_andx_request.rb +3 -6
  99. data/lib/ruby_smb/smb1/packet/write_andx_response.rb +2 -1
  100. data/lib/ruby_smb/smb1/pipe.rb +87 -6
  101. data/lib/ruby_smb/smb1/tree.rb +50 -3
  102. data/lib/ruby_smb/smb2/bit_field/session_flags.rb +2 -1
  103. data/lib/ruby_smb/smb2/bit_field/share_flags.rb +6 -4
  104. data/lib/ruby_smb/smb2/file.rb +103 -25
  105. data/lib/ruby_smb/smb2/negotiate_context.rb +108 -0
  106. data/lib/ruby_smb/smb2/packet.rb +2 -0
  107. data/lib/ruby_smb/smb2/packet/close_request.rb +2 -4
  108. data/lib/ruby_smb/smb2/packet/close_response.rb +2 -1
  109. data/lib/ruby_smb/smb2/packet/compression_transform_header.rb +41 -0
  110. data/lib/ruby_smb/smb2/packet/create_request.rb +2 -4
  111. data/lib/ruby_smb/smb2/packet/create_response.rb +2 -1
  112. data/lib/ruby_smb/smb2/packet/echo_request.rb +2 -4
  113. data/lib/ruby_smb/smb2/packet/echo_response.rb +2 -1
  114. data/lib/ruby_smb/smb2/packet/error_packet.rb +15 -3
  115. data/lib/ruby_smb/smb2/packet/ioctl_request.rb +2 -5
  116. data/lib/ruby_smb/smb2/packet/ioctl_response.rb +2 -1
  117. data/lib/ruby_smb/smb2/packet/logoff_request.rb +2 -4
  118. data/lib/ruby_smb/smb2/packet/logoff_response.rb +2 -1
  119. data/lib/ruby_smb/smb2/packet/negotiate_request.rb +51 -17
  120. data/lib/ruby_smb/smb2/packet/negotiate_response.rb +52 -5
  121. data/lib/ruby_smb/smb2/packet/query_directory_request.rb +2 -4
  122. data/lib/ruby_smb/smb2/packet/query_directory_response.rb +8 -2
  123. data/lib/ruby_smb/smb2/packet/read_request.rb +2 -4
  124. data/lib/ruby_smb/smb2/packet/read_response.rb +2 -1
  125. data/lib/ruby_smb/smb2/packet/session_setup_request.rb +2 -5
  126. data/lib/ruby_smb/smb2/packet/session_setup_response.rb +2 -1
  127. data/lib/ruby_smb/smb2/packet/set_info_request.rb +2 -4
  128. data/lib/ruby_smb/smb2/packet/set_info_response.rb +2 -1
  129. data/lib/ruby_smb/smb2/packet/transform_header.rb +84 -0
  130. data/lib/ruby_smb/smb2/packet/tree_connect_request.rb +93 -10
  131. data/lib/ruby_smb/smb2/packet/tree_connect_response.rb +10 -22
  132. data/lib/ruby_smb/smb2/packet/tree_disconnect_request.rb +2 -4
  133. data/lib/ruby_smb/smb2/packet/tree_disconnect_response.rb +2 -1
  134. data/lib/ruby_smb/smb2/packet/write_request.rb +2 -4
  135. data/lib/ruby_smb/smb2/packet/write_response.rb +2 -1
  136. data/lib/ruby_smb/smb2/pipe.rb +86 -12
  137. data/lib/ruby_smb/smb2/smb2_header.rb +1 -1
  138. data/lib/ruby_smb/smb2/tree.rb +65 -21
  139. data/lib/ruby_smb/version.rb +1 -1
  140. data/ruby_smb.gemspec +5 -3
  141. data/spec/lib/ruby_smb/client_spec.rb +1612 -108
  142. data/spec/lib/ruby_smb/crypto_spec.rb +25 -0
  143. data/spec/lib/ruby_smb/dcerpc/bind_ack_spec.rb +2 -2
  144. data/spec/lib/ruby_smb/dcerpc/bind_spec.rb +2 -2
  145. data/spec/lib/ruby_smb/dcerpc/ndr_spec.rb +410 -0
  146. data/spec/lib/ruby_smb/dcerpc/request_spec.rb +50 -7
  147. data/spec/lib/ruby_smb/dcerpc/rrp_unicode_string_spec.rb +98 -0
  148. data/spec/lib/ruby_smb/dcerpc/srvsvc/net_share_enum_all_spec.rb +13 -0
  149. data/spec/lib/ruby_smb/dcerpc/srvsvc_spec.rb +60 -0
  150. data/spec/lib/ruby_smb/dcerpc/winreg/close_key_request_spec.rb +28 -0
  151. data/spec/lib/ruby_smb/dcerpc/winreg/close_key_response_spec.rb +36 -0
  152. data/spec/lib/ruby_smb/dcerpc/winreg/enum_key_request_spec.rb +108 -0
  153. data/spec/lib/ruby_smb/dcerpc/winreg/enum_key_response_spec.rb +97 -0
  154. data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_request_spec.rb +94 -0
  155. data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_response_spec.rb +82 -0
  156. data/spec/lib/ruby_smb/dcerpc/winreg/open_key_request_spec.rb +74 -0
  157. data/spec/lib/ruby_smb/dcerpc/winreg/open_key_response_spec.rb +35 -0
  158. data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_request_spec.rb +90 -0
  159. data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_response_spec.rb +38 -0
  160. data/spec/lib/ruby_smb/dcerpc/winreg/query_info_key_request_spec.rb +39 -0
  161. data/spec/lib/ruby_smb/dcerpc/winreg/query_info_key_response_spec.rb +113 -0
  162. data/spec/lib/ruby_smb/dcerpc/winreg/query_value_request_spec.rb +88 -0
  163. data/spec/lib/ruby_smb/dcerpc/winreg/query_value_response_spec.rb +150 -0
  164. data/spec/lib/ruby_smb/dcerpc/winreg/regsam_spec.rb +32 -0
  165. data/spec/lib/ruby_smb/dcerpc/winreg_spec.rb +710 -0
  166. data/spec/lib/ruby_smb/dcerpc_spec.rb +81 -0
  167. data/spec/lib/ruby_smb/dispatcher/socket_spec.rb +2 -2
  168. data/spec/lib/ruby_smb/error_spec.rb +59 -0
  169. data/spec/lib/ruby_smb/generic_packet_spec.rb +52 -4
  170. data/spec/lib/ruby_smb/smb1/file_spec.rb +191 -2
  171. data/spec/lib/ruby_smb/smb1/packet/empty_packet_spec.rb +68 -0
  172. data/spec/lib/ruby_smb/smb1/packet/session_setup_legacy_request_spec.rb +2 -2
  173. data/spec/lib/ruby_smb/smb1/packet/session_setup_legacy_response_spec.rb +2 -2
  174. data/spec/lib/ruby_smb/smb1/packet/session_setup_request_spec.rb +2 -2
  175. data/spec/lib/ruby_smb/smb1/packet/session_setup_response_spec.rb +1 -1
  176. data/spec/lib/ruby_smb/smb1/packet/trans2/find_first2_response_spec.rb +11 -2
  177. data/spec/lib/ruby_smb/smb1/packet/trans2/find_next2_response_spec.rb +11 -2
  178. data/spec/lib/ruby_smb/smb1/packet/tree_connect_response_spec.rb +40 -0
  179. data/spec/lib/ruby_smb/smb1/pipe_spec.rb +272 -149
  180. data/spec/lib/ruby_smb/smb1/tree_spec.rb +44 -7
  181. data/spec/lib/ruby_smb/smb2/bit_field/session_flags_spec.rb +9 -0
  182. data/spec/lib/ruby_smb/smb2/bit_field/share_flags_spec.rb +27 -0
  183. data/spec/lib/ruby_smb/smb2/file_spec.rb +323 -6
  184. data/spec/lib/ruby_smb/smb2/negotiate_context_spec.rb +332 -0
  185. data/spec/lib/ruby_smb/smb2/packet/compression_transform_header_spec.rb +108 -0
  186. data/spec/lib/ruby_smb/smb2/packet/error_packet_spec.rb +78 -0
  187. data/spec/lib/ruby_smb/smb2/packet/negotiate_request_spec.rb +138 -3
  188. data/spec/lib/ruby_smb/smb2/packet/negotiate_response_spec.rb +120 -2
  189. data/spec/lib/ruby_smb/smb2/packet/query_directory_response_spec.rb +8 -0
  190. data/spec/lib/ruby_smb/smb2/packet/transform_header_spec.rb +220 -0
  191. data/spec/lib/ruby_smb/smb2/packet/tree_connect_request_spec.rb +339 -9
  192. data/spec/lib/ruby_smb/smb2/packet/tree_connect_response_spec.rb +3 -22
  193. data/spec/lib/ruby_smb/smb2/pipe_spec.rb +286 -149
  194. data/spec/lib/ruby_smb/smb2/smb2_header_spec.rb +2 -2
  195. data/spec/lib/ruby_smb/smb2/tree_spec.rb +261 -2
  196. metadata +191 -83
  197. metadata.gz.sig +0 -0
  198. data/lib/ruby_smb/smb1/dcerpc.rb +0 -67
  199. data/lib/ruby_smb/smb2/dcerpc.rb +0 -70
  200. data/spec/lib/ruby_smb/smb1/packet/error_packet_spec.rb +0 -37
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/ruby
2
+
3
+ # This example script is used for testing the Winreg registry key value read functionality.
4
+ # It will attempt to connect to a host and reads the value of a specified registry key.
5
+ # Example usage: ruby enum_registry_key.rb 192.168.172.138 msfadmin msfadmin HKLM\\My\\Key ValueName
6
+ # This will try to connect to \\192.168.172.138 with the msfadmin:msfadmin credentialas and reads the ValueName data corresponding to the HKLM\\My\\Key registry key.
7
+
8
+ require 'bundler/setup'
9
+ require 'ruby_smb'
10
+
11
+ address = ARGV[0]
12
+ username = ARGV[1]
13
+ password = ARGV[2]
14
+ registry_key = ARGV[3]
15
+ value_name = ARGV[4]
16
+
17
+ sock = TCPSocket.new address, 445
18
+ dispatcher = RubySMB::Dispatcher::Socket.new(sock, read_timeout: 60)
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
+ puts "Key: #{registry_key}"
26
+ puts "Value: #{value_name}"
27
+
28
+ key_value = client.read_registry_key_value(address, registry_key, value_name)
29
+ puts key_value
30
+
31
+ client.disconnect!
32
+
@@ -1,6 +1,9 @@
1
1
  require 'bindata'
2
2
  require 'net/ntlm'
3
3
  require 'net/ntlm/client'
4
+ require 'openssl'
5
+ require 'openssl/ccm'
6
+ require 'openssl/cmac'
4
7
  require 'windows_error'
5
8
  require 'windows_error/nt_status'
6
9
  # A packet parsing and manipulation library for the SMB1 and SMB2 protocols
@@ -15,7 +18,6 @@ module RubySMB
15
18
  require 'ruby_smb/field'
16
19
  require 'ruby_smb/nbss'
17
20
  require 'ruby_smb/fscc'
18
- require 'ruby_smb/dcerpc'
19
21
  require 'ruby_smb/generic_packet'
20
22
  require 'ruby_smb/dispatcher'
21
23
  require 'ruby_smb/version'
@@ -23,4 +25,5 @@ module RubySMB
23
25
  require 'ruby_smb/smb2'
24
26
  require 'ruby_smb/smb1'
25
27
  require 'ruby_smb/client'
28
+ require 'ruby_smb/crypto'
26
29
  end
@@ -8,6 +8,8 @@ module RubySMB
8
8
  require 'ruby_smb/client/tree_connect'
9
9
  require 'ruby_smb/client/echo'
10
10
  require 'ruby_smb/client/utils'
11
+ require 'ruby_smb/client/winreg'
12
+ require 'ruby_smb/client/encryption'
11
13
 
12
14
  include RubySMB::Client::Negotiation
13
15
  include RubySMB::Client::Authentication
@@ -15,13 +17,21 @@ module RubySMB
15
17
  include RubySMB::Client::TreeConnect
16
18
  include RubySMB::Client::Echo
17
19
  include RubySMB::Client::Utils
20
+ include RubySMB::Client::Winreg
21
+ include RubySMB::Client::Encryption
18
22
 
19
23
  # The Default SMB1 Dialect string used in an SMB1 Negotiate Request
20
24
  SMB1_DIALECT_SMB1_DEFAULT = 'NT LM 0.12'.freeze
21
25
  # The Default SMB2 Dialect string used in an SMB1 Negotiate Request
22
26
  SMB1_DIALECT_SMB2_DEFAULT = 'SMB 2.002'.freeze
23
- # Dialect value for SMB2 Default (Version 2.02)
24
- SMB2_DIALECT_DEFAULT = 0x0202
27
+ # The SMB2 wildcard revision number Dialect string used in an SMB1 Negotiate Request
28
+ # It indicates that the server implements SMB 2.1 or future dialect revisions
29
+ # Note that this must be used for SMB3
30
+ SMB1_DIALECT_SMB2_WILDCARD = 'SMB 2.???'.freeze
31
+ # Dialect values for SMB2
32
+ SMB2_DIALECT_DEFAULT = ['0x0202', '0x0210']
33
+ # Dialect values for SMB3
34
+ SMB3_DIALECT_DEFAULT = ['0x0300', '0x0302', '0x0311']
25
35
  # The default maximum size of a SMB message that the Client accepts (in bytes)
26
36
  MAX_BUFFER_SIZE = 64512
27
37
  # The default maximum size of a SMB message that the Server accepts (in bytes)
@@ -133,6 +143,11 @@ module RubySMB
133
143
  # @return [Boolean]
134
144
  attr_accessor :smb2
135
145
 
146
+ # Whether or not the Client should support SMB3
147
+ # @!attribute [rw] smb3
148
+ # @return [Boolean]
149
+ attr_accessor :smb3
150
+
136
151
  # Tracks the current SMB2 Message ID that keeps communication in sync
137
152
  # @!attribute [rw] smb2_message_id
138
153
  # @return [Integer]
@@ -176,12 +191,80 @@ module RubySMB
176
191
  # @return [Integer]
177
192
  attr_accessor :server_max_transact_size
178
193
 
194
+ # The algorithm to compute the preauthentication integrity hash (SMB 3.1.1).
195
+ # @!attribute [rw] preauth_integrity_hash_algorithm
196
+ # @return [String]
197
+ attr_accessor :preauth_integrity_hash_algorithm
198
+
199
+ # The preauthentication integrity hash value (SMB 3.1.1).
200
+ # @!attribute [rw] preauth_integrity_hash_value
201
+ # @return [String]
202
+ attr_accessor :preauth_integrity_hash_value
203
+
204
+ # The algorithm for encryption (SMB 3.x).
205
+ # @!attribute [rw] encryption_algorithm
206
+ # @return [String]
207
+ attr_accessor :encryption_algorithm
208
+
209
+ # The client encryption key (SMB 3.x).
210
+ # @!attribute [rw] client_encryption_key
211
+ # @return [String]
212
+ attr_accessor :client_encryption_key
213
+
214
+ # The server encryption key (SMB 3.x).
215
+ # @!attribute [rw] server_encryption_key
216
+ # @return [String]
217
+ attr_accessor :server_encryption_key
218
+
219
+ # Whether or not the whole session needs to be encrypted (SMB 3.x)
220
+ # @!attribute [rw] session_encrypt_data
221
+ # @return [Boolean]
222
+ attr_accessor :session_encrypt_data
223
+
224
+ # The encryption algorithms supported by the server (SMB 3.x).
225
+ # @!attribute [rw] server_encryption_algorithms
226
+ # @return [Array<Integer>] list of supported encryption algorithms
227
+ # (constants defined in RubySMB::SMB2::EncryptionCapabilities)
228
+ attr_accessor :server_encryption_algorithms
229
+
230
+ # The compression algorithms supported by the server (SMB 3.x).
231
+ # @!attribute [rw] server_compression_algorithms
232
+ # @return [Array<Integer>] list of supported compression algorithms
233
+ # (constants defined in RubySMB::SMB2::CompressionCapabilities)
234
+ attr_accessor :server_compression_algorithms
235
+
236
+ # The GUID of the server (SMB 2.x and 3.x).
237
+ # @!attribute [rw] server_guid
238
+ # @return [String]
239
+ attr_accessor :server_guid
240
+
241
+ # The server's start time if it is reported as part of the negotiation
242
+ # process (SMB 2.x and 3.x). This value is nil if the server does not report
243
+ # it (reports a value of 0).
244
+ # @!attribute [rw] server_start_time
245
+ # @return [Time] the time that the server reports that it was started at
246
+ attr_accessor :server_start_time
247
+
248
+ # The server's current time if it is reported as part of the negotiation
249
+ # process (SMB 2.x and 3.x). This value is nil if the server does not report
250
+ # it (reports a value of 0).
251
+ # @!attribute [rw] server_system_time
252
+ # @return [Time] the time that the server reports as current
253
+ attr_accessor :server_system_time
254
+
255
+ # The SMB version that has been successfully negotiated. This value is only
256
+ # set after the NEGOTIATE handshake has been performed.
257
+ # @!attribute [rw] negotiated_smb_version
258
+ # @return [Integer] the negotiated SMB version
259
+ attr_accessor :negotiated_smb_version
260
+
179
261
  # @param dispatcher [RubySMB::Dispatcher::Socket] the packet dispatcher to use
180
262
  # @param smb1 [Boolean] whether or not to enable SMB1 support
181
263
  # @param smb2 [Boolean] whether or not to enable SMB2 support
182
- def initialize(dispatcher, smb1: true, smb2: true, username:, password:, domain: '.', local_workstation: 'WORKSTATION')
264
+ # @param smb3 [Boolean] whether or not to enable SMB3 support
265
+ def initialize(dispatcher, smb1: true, smb2: true, smb3: true, username:, password:, domain: '.', local_workstation: 'WORKSTATION', always_encrypt: true)
183
266
  raise ArgumentError, 'No Dispatcher provided' unless dispatcher.is_a? RubySMB::Dispatcher::Base
184
- if smb1 == false && smb2 == false
267
+ if smb1 == false && smb2 == false && smb3 == false
185
268
  raise ArgumentError, 'You must enable at least one Protocol'
186
269
  end
187
270
  @dispatcher = dispatcher
@@ -194,6 +277,7 @@ module RubySMB
194
277
  @signing_required = false
195
278
  @smb1 = smb1
196
279
  @smb2 = smb2
280
+ @smb3 = smb3
197
281
  @username = username.encode('utf-8') || ''.encode('utf-8')
198
282
  @max_buffer_size = MAX_BUFFER_SIZE
199
283
  # These sizes will be modifed during negotiation
@@ -202,10 +286,14 @@ module RubySMB
202
286
  @server_max_write_size = RubySMB::SMB2::File::MAX_PACKET_SIZE
203
287
  @server_max_transact_size = RubySMB::SMB2::File::MAX_PACKET_SIZE
204
288
 
289
+ # SMB 3.x options
290
+ @session_encrypt_data = always_encrypt
291
+
205
292
  negotiate_version_flag = 0x02000000
206
293
  flags = Net::NTLM::Client::DEFAULT_FLAGS |
207
294
  Net::NTLM::FLAGS[:TARGET_INFO] |
208
- negotiate_version_flag
295
+ negotiate_version_flag ^
296
+ Net::NTLM::FLAGS[:OEM]
209
297
 
210
298
  @ntlm_client = Net::NTLM::Client.new(
211
299
  @username,
@@ -241,7 +329,7 @@ module RubySMB
241
329
  # @param data [String] the data the server should echo back (ignored in SMB2)
242
330
  # @return [WindowsError::ErrorCode] the NTStatus of the last response received
243
331
  def echo(count: 1, data: '')
244
- response = if smb2
332
+ response = if smb2 || smb3
245
333
  smb2_echo
246
334
  else
247
335
  smb1_echo(count: count, data: data)
@@ -256,10 +344,8 @@ module RubySMB
256
344
  # @param packet [RubySMB::GenericPacket] the packet to set the message id for
257
345
  # @return [RubySMB::GenericPacket] the modified packet
258
346
  def increment_smb_message_id(packet)
259
- if packet.smb2_header.message_id.zero? && smb2_message_id != 0
260
- packet.smb2_header.message_id = smb2_message_id
261
- self.smb2_message_id += 1
262
- end
347
+ packet.smb2_header.message_id = smb2_message_id
348
+ self.smb2_message_id += 1
263
349
  packet
264
350
  end
265
351
 
@@ -281,7 +367,8 @@ module RubySMB
281
367
  negotiate_version_flag = 0x02000000
282
368
  flags = Net::NTLM::Client::DEFAULT_FLAGS |
283
369
  Net::NTLM::FLAGS[:TARGET_INFO] |
284
- negotiate_version_flag
370
+ negotiate_version_flag ^
371
+ Net::NTLM::FLAGS[:OEM]
285
372
 
286
373
  @ntlm_client = Net::NTLM::Client.new(
287
374
  @username,
@@ -297,15 +384,32 @@ module RubySMB
297
384
  # Sends a LOGOFF command to the remote server to terminate the session
298
385
  #
299
386
  # @return [WindowsError::ErrorCode] the NTStatus of the response
387
+ # @raise [RubySMB::Error::InvalidPacket] if the response packet is not a LogoffResponse packet
300
388
  def logoff!
301
- if smb2
389
+ if smb2 || smb3
302
390
  request = RubySMB::SMB2::Packet::LogoffRequest.new
303
391
  raw_response = send_recv(request)
304
392
  response = RubySMB::SMB2::Packet::LogoffResponse.read(raw_response)
393
+ unless response.valid?
394
+ raise RubySMB::Error::InvalidPacket.new(
395
+ expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
396
+ expected_cmd: RubySMB::SMB2::Packet::LogoffResponse::COMMAND,
397
+ received_proto: response.smb2_header.protocol,
398
+ received_cmd: response.smb2_header.command
399
+ )
400
+ end
305
401
  else
306
402
  request = RubySMB::SMB1::Packet::LogoffRequest.new
307
403
  raw_response = send_recv(request)
308
404
  response = RubySMB::SMB1::Packet::LogoffResponse.read(raw_response)
405
+ unless response.valid?
406
+ raise RubySMB::Error::InvalidPacket.new(
407
+ expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
408
+ expected_cmd: RubySMB::SMB1::Packet::LogoffResponse::COMMAND,
409
+ received_proto: response.smb_header.protocol,
410
+ received_cmd: response.smb_header.command
411
+ )
412
+ end
309
413
  end
310
414
  wipe_state!
311
415
  response.status_code
@@ -315,9 +419,13 @@ module RubySMB
315
419
  # It will also sign the packet if neccessary.
316
420
  #
317
421
  # @param packet [RubySMB::GenericPacket] the request to be sent
422
+ # @param encrypt [Boolean] true if encryption has to be enabled for this transaction
423
+ # (note that if @session_encrypt_data is set, encryption will be enabled
424
+ # regardless of this parameter value)
318
425
  # @return [String] the raw response data received
319
- def send_recv(packet)
320
- case packet.packet_smb_version
426
+ def send_recv(packet, encrypt: false)
427
+ version = packet.packet_smb_version
428
+ case version
321
429
  when 'SMB1'
322
430
  packet.smb_header.uid = user_id if user_id
323
431
  packet = smb1_sign(packet)
@@ -325,25 +433,110 @@ module RubySMB
325
433
  packet = increment_smb_message_id(packet)
326
434
  packet.smb2_header.session_id = session_id
327
435
  unless packet.is_a?(RubySMB::SMB2::Packet::SessionSetupRequest)
328
- packet = smb2_sign(packet)
436
+ if self.smb2
437
+ packet = smb2_sign(packet)
438
+ elsif self.smb3
439
+ packet = smb3_sign(packet)
440
+ end
329
441
  end
330
442
  else
331
443
  packet = packet
332
444
  end
333
- dispatcher.send_packet(packet)
334
- raw_response = dispatcher.recv_packet
445
+
446
+ if can_be_encrypted?(packet) && encryption_supported? && (@session_encrypt_data || encrypt)
447
+ send_encrypt(packet)
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'
462
+ end
335
463
 
336
464
  self.sequence_counter += 1 if signing_required && !session_key.empty?
337
465
  raw_response
338
466
  end
339
467
 
468
+ # Check if the response is an asynchronous operation with STATUS_PENDING
469
+ # status code.
470
+ #
471
+ # @param raw_response [String] the raw response packet
472
+ # @return [Boolean] true if it is a status pending operation, false otherwise
473
+ def is_status_pending?(raw_response)
474
+ smb2_header = RubySMB::SMB2::SMB2Header.read(raw_response)
475
+ value = smb2_header.nt_status.value
476
+ status_code = WindowsError::NTStatus.find_by_retval(value).first
477
+ status_code == WindowsError::NTStatus::STATUS_PENDING &&
478
+ smb2_header.flags.async_command == 1
479
+ end
480
+
481
+ # Check if the request packet can be encrypted. Per the SMB2 spec,
482
+ # SessionSetupRequest and NegotiateRequest must not be encrypted.
483
+ #
484
+ # @param packet [RubySMB::GenericPacket] the request packet
485
+ # @return [Boolean] true if the packet can be encrypted
486
+ def can_be_encrypted?(packet)
487
+ return false if packet.packet_smb_version == 'SMB1'
488
+ [RubySMB::SMB2::Packet::SessionSetupRequest, RubySMB::SMB2::Packet::NegotiateRequest].none? do |klass|
489
+ packet.is_a?(klass)
490
+ end
491
+ end
492
+
493
+ # Check if the current dialect supports encryption.
494
+ #
495
+ # @return [Boolean] true if encryption is supported
496
+ def encryption_supported?
497
+ ['0x0300', '0x0302', '0x0311'].include?(@dialect)
498
+ end
499
+
500
+ # Encrypt and send a packet
501
+ def send_encrypt(packet)
502
+ begin
503
+ transform_request = smb3_encrypt(packet.to_binary_s)
504
+ rescue RubySMB::Error::RubySMBError => e
505
+ raise RubySMB::Error::EncryptionError, "Error while encrypting #{packet.class.name} packet (SMB #{@dialect}): #{e}"
506
+ end
507
+ dispatcher.send_packet(transform_request)
508
+ end
509
+
510
+ # Receives the raw response through the Dispatcher and decrypt the packet.
511
+ #
512
+ # @return [String] the raw unencrypted packet
513
+ def recv_encrypt
514
+ begin
515
+ raw_response = dispatcher.recv_packet
516
+ rescue RubySMB::Error::CommunicationError => e
517
+ raise RubySMB::Error::EncryptionError, "Communication error with the "\
518
+ "remote host: #{e.message}. The server supports encryption but was "\
519
+ "not able to handle the encrypted request."
520
+ end
521
+ begin
522
+ transform_response = RubySMB::SMB2::Packet::TransformHeader.read(raw_response)
523
+ rescue IOError
524
+ raise RubySMB::Error::InvalidPacket, 'Not a SMB2 TransformHeader packet'
525
+ end
526
+ begin
527
+ smb3_decrypt(transform_response)
528
+ rescue RubySMB::Error::RubySMBError => e
529
+ raise RubySMB::Error::EncryptionError, "Error while decrypting #{transform_response.class.name} packet (SMB #@dialect}): #{e}"
530
+ end
531
+ end
532
+
340
533
  # Connects to the supplied share
341
534
  #
342
535
  # @param share [String] the path to the share in `\\server\share_name` format
343
536
  # @return [RubySMB::SMB1::Tree] if talking over SMB1
344
537
  # @return [RubySMB::SMB2::Tree] if talking over SMB2
345
538
  def tree_connect(share)
346
- connected_tree = if smb2
539
+ connected_tree = if smb2 || smb3
347
540
  smb2_tree_connect(share)
348
541
  else
349
542
  smb1_tree_connect(share)
@@ -373,6 +566,8 @@ module RubySMB
373
566
  self.session_key = ''
374
567
  self.sequence_counter = 0
375
568
  self.smb2_message_id = 0
569
+ self.client_encryption_key = nil
570
+ self.server_encryption_key = nil
376
571
  end
377
572
 
378
573
  # Requests a NetBIOS Session Service using the provided name.
@@ -380,14 +575,19 @@ module RubySMB
380
575
  # @param name [String] the NetBIOS name to request
381
576
  # @return [TrueClass] if session request is granted
382
577
  # @raise [RubySMB::Error::NetBiosSessionService] if session request is refused
578
+ # @raise [RubySMB::Error::InvalidPacket] if the response packet is not a NBSS packet
383
579
  def session_request(name = '*SMBSERVER')
384
580
  session_request = session_request_packet(name)
385
581
  dispatcher.send_packet(session_request, nbss_header: false)
386
582
  raw_response = dispatcher.recv_packet(full_response: true)
387
- session_header = RubySMB::Nbss::SessionHeader.read(raw_response)
388
- if session_header.session_packet_type == RubySMB::Nbss::NEGATIVE_SESSION_RESPONSE
389
- negative_session_response = RubySMB::Nbss::NegativeSessionResponse.read(raw_response)
390
- raise RubySMB::Error::NetBiosSessionService, "Session Request failed: #{negative_session_response.error_msg}"
583
+ begin
584
+ session_header = RubySMB::Nbss::SessionHeader.read(raw_response)
585
+ if session_header.session_packet_type == RubySMB::Nbss::NEGATIVE_SESSION_RESPONSE
586
+ negative_session_response = RubySMB::Nbss::NegativeSessionResponse.read(raw_response)
587
+ raise RubySMB::Error::NetBiosSessionService, "Session Request failed: #{negative_session_response.error_msg}"
588
+ end
589
+ rescue IOError
590
+ raise RubySMB::Error::InvalidPacket, 'Not a NBSS packet'
391
591
  end
392
592
 
393
593
  return true
@@ -410,5 +610,16 @@ module RubySMB
410
610
  session_request
411
611
  end
412
612
 
613
+ def update_preauth_hash(data)
614
+ unless @preauth_integrity_hash_algorithm
615
+ raise RubySMB::Error::EncryptionError.new(
616
+ 'Cannot compute the Preauth Integrity Hash value: Preauth Integrity Hash Algorithm is nil'
617
+ )
618
+ end
619
+ @preauth_integrity_hash_value = OpenSSL::Digest.digest(
620
+ @preauth_integrity_hash_algorithm,
621
+ @preauth_integrity_hash_value + data.to_binary_s
622
+ )
623
+ end
413
624
  end
414
625
  end
@@ -54,14 +54,15 @@ module RubySMB
54
54
  end
55
55
 
56
56
  def smb1_anonymous_auth_response(raw_response)
57
- begin
58
- packet = RubySMB::SMB1::Packet::SessionSetupLegacyResponse.read(raw_response)
59
- rescue
60
- packet = RubySMB::SMB1::Packet::EmptyPacket.read(raw_response)
61
- end
62
-
63
- unless packet.smb_header.command == RubySMB::SMB1::Commands::SMB_COM_SESSION_SETUP
64
- raise RubySMB::Error::InvalidPacket, "Command was #{packet.smb_header.command} and not #{RubySMB::SMB1::Commands::SMB_COM_SESSION_SETUP}"
57
+ packet = RubySMB::SMB1::Packet::SessionSetupLegacyResponse.read(raw_response)
58
+
59
+ unless packet.valid?
60
+ raise RubySMB::Error::InvalidPacket.new(
61
+ expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
62
+ expected_cmd: RubySMB::SMB1::Packet::SessionSetupLegacyResponse::COMMAND,
63
+ received_proto: packet.smb_header.protocol,
64
+ received_cmd: packet.smb_header.command
65
+ )
65
66
  end
66
67
  packet
67
68
  end
@@ -147,14 +148,15 @@ module RubySMB
147
148
 
148
149
  # Takes the raw binary string and returns a {RubySMB::SMB1::Packet::SessionSetupResponse}
149
150
  def smb1_ntlmssp_final_packet(raw_response)
150
- begin
151
- packet = RubySMB::SMB1::Packet::SessionSetupResponse.read(raw_response)
152
- rescue
153
- packet = RubySMB::SMB1::Packet::EmptyPacket.read(raw_response)
154
- end
151
+ packet = RubySMB::SMB1::Packet::SessionSetupResponse.read(raw_response)
155
152
 
156
- unless packet.smb_header.command == RubySMB::SMB1::Commands::SMB_COM_SESSION_SETUP
157
- raise RubySMB::Error::InvalidPacket, "Command was #{packet.smb_header.command} and not #{RubySMB::SMB1::Commands::SMB_COM_SESSION_SETUP}"
153
+ unless packet.valid?
154
+ raise RubySMB::Error::InvalidPacket.new(
155
+ expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
156
+ expected_cmd: RubySMB::SMB1::Packet::SessionSetupResponse::COMMAND,
157
+ received_proto: packet.smb_header.protocol,
158
+ received_cmd: packet.smb_header.command
159
+ )
158
160
  end
159
161
  packet
160
162
  end
@@ -162,15 +164,20 @@ module RubySMB
162
164
  # Takes the raw binary string and returns a {RubySMB::SMB1::Packet::SessionSetupResponse}
163
165
  def smb1_ntlmssp_challenge_packet(raw_response)
164
166
  packet = RubySMB::SMB1::Packet::SessionSetupResponse.read(raw_response)
165
- status_code = packet.status_code
167
+ unless packet.valid?
168
+ raise RubySMB::Error::InvalidPacket.new(
169
+ expected_proto: RubySMB::SMB1::SMB_PROTOCOL_ID,
170
+ expected_cmd: RubySMB::SMB1::Packet::SessionSetupResponse::COMMAND,
171
+ received_proto: packet.smb_header.protocol,
172
+ received_cmd: packet.smb_header.command
173
+ )
174
+ end
166
175
 
176
+ status_code = packet.status_code
167
177
  unless status_code.name == 'STATUS_MORE_PROCESSING_REQUIRED'
168
- raise RubySMB::Error::UnexpectedStatusCode, status_code.to_s
178
+ raise RubySMB::Error::UnexpectedStatusCode, status_code
169
179
  end
170
180
 
171
- unless packet.smb_header.command == RubySMB::SMB1::Commands::SMB_COM_SESSION_SETUP
172
- raise RubySMB::Error::InvalidPacket, "Command was #{packet.smb_header.command} and not #{RubySMB::SMB1::Commands::SMB_COM_SESSION_SETUP}"
173
- end
174
181
  packet
175
182
  end
176
183
 
@@ -194,6 +201,9 @@ module RubySMB
194
201
  def smb2_authenticate
195
202
  response = smb2_ntlmssp_negotiate
196
203
  challenge_packet = smb2_ntlmssp_challenge_packet(response)
204
+ if @dialect == '0x0311'
205
+ update_preauth_hash(challenge_packet)
206
+ end
197
207
  @session_id = challenge_packet.smb2_header.session_id
198
208
  type2_b64_message = smb2_type2_message(challenge_packet)
199
209
  type3_message = @ntlm_client.init_context(type2_b64_message)
@@ -206,28 +216,49 @@ module RubySMB
206
216
  raw = smb2_ntlmssp_authenticate(type3_message, @session_id)
207
217
  response = smb2_ntlmssp_final_packet(raw)
208
218
 
219
+ if @smb3 && !@session_encrypt_data && response.session_flags.encrypt_data == 1
220
+ @session_encrypt_data = true
221
+ end
222
+ ######
223
+ # DEBUG
224
+ #puts "Session ID = #{@session_id.to_binary_s.each_byte.map {|e| '%02x' % e}.join}"
225
+ #puts "Session key = #{@session_key.each_byte.map {|e| '%02x' % e}.join}"
226
+ #puts "PreAuthHash = #{@preauth_integrity_hash_value.each_byte.map {|e| '%02x' % e}.join}" if @preauth_integrity_hash_value
227
+ ######
228
+
209
229
  response.status_code
210
230
  end
211
231
 
212
232
  # Takes the raw binary string and returns a {RubySMB::SMB2::Packet::SessionSetupResponse}
213
233
  def smb2_ntlmssp_final_packet(raw_response)
214
234
  packet = RubySMB::SMB2::Packet::SessionSetupResponse.read(raw_response)
215
- unless packet.smb2_header.command == RubySMB::SMB2::Commands::SESSION_SETUP
216
- raise RubySMB::Error::InvalidPacket, "Command was #{packet.smb2_header.command} and not #{RubySMB::SMB2::Commands::SESSION_SETUP}"
235
+ unless packet.valid?
236
+ raise RubySMB::Error::InvalidPacket.new(
237
+ expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
238
+ expected_cmd: RubySMB::SMB2::Packet::SessionSetupResponse::COMMAND,
239
+ received_proto: packet.smb2_header.protocol,
240
+ received_cmd: packet.smb2_header.command
241
+ )
217
242
  end
243
+
218
244
  packet
219
245
  end
220
246
 
221
247
  # Takes the raw binary string and returns a {RubySMB::SMB2::Packet::SessionSetupResponse}
222
248
  def smb2_ntlmssp_challenge_packet(raw_response)
223
249
  packet = RubySMB::SMB2::Packet::SessionSetupResponse.read(raw_response)
224
- status_code = packet.status_code
225
- unless status_code.name == 'STATUS_MORE_PROCESSING_REQUIRED'
226
- raise RubySMB::Error::UnexpectedStatusCode, status_code.to_s
250
+ unless packet.valid?
251
+ raise RubySMB::Error::InvalidPacket.new(
252
+ expected_proto: RubySMB::SMB2::SMB2_PROTOCOL_ID,
253
+ expected_cmd: RubySMB::SMB2::Packet::SessionSetupResponse::COMMAND,
254
+ received_proto: packet.smb2_header.protocol,
255
+ received_cmd: packet.smb2_header.command
256
+ )
227
257
  end
228
258
 
229
- unless packet.smb2_header.command == RubySMB::SMB2::Commands::SESSION_SETUP
230
- raise RubySMB::Error::InvalidPacket, "Command was #{packet.smb2_header.command} and not #{RubySMB::SMB2::Commands::SESSION_SETUP}"
259
+ status_code = packet.status_code
260
+ unless status_code.name == 'STATUS_MORE_PROCESSING_REQUIRED'
261
+ raise RubySMB::Error::UnexpectedStatusCode, status_code
231
262
  end
232
263
  packet
233
264
  end
@@ -238,7 +269,11 @@ module RubySMB
238
269
  # @return [String] the binary string response from the server
239
270
  def smb2_ntlmssp_negotiate
240
271
  packet = smb2_ntlmssp_negotiate_packet
241
- send_recv(packet)
272
+ response = send_recv(packet)
273
+ if @dialect == '0x0311'
274
+ update_preauth_hash(packet)
275
+ end
276
+ response
242
277
  end
243
278
 
244
279
  # Creates the {RubySMB::SMB2::Packet::SessionSetupRequest} packet
@@ -250,10 +285,7 @@ module RubySMB
250
285
  type1_message = ntlm_client.init_context
251
286
  packet = RubySMB::SMB2::Packet::SessionSetupRequest.new
252
287
  packet.set_type1_blob(type1_message.serialize)
253
- # This Message ID should always be 1, but thanks to Multi-Protocol Negotiation
254
- # the Message ID can be out of sync at this point so we re-synch it here.
255
- packet.smb2_header.message_id = 1
256
- self.smb2_message_id = 2
288
+ packet.security_mode.signing_enabled = 1
257
289
  packet
258
290
  end
259
291
 
@@ -276,7 +308,11 @@ module RubySMB
276
308
  # @return [String] the raw binary response from the server
277
309
  def smb2_ntlmssp_authenticate(type3_message, user_id)
278
310
  packet = smb2_ntlmssp_auth_packet(type3_message, user_id)
279
- send_recv(packet)
311
+ response = send_recv(packet)
312
+ if @dialect == '0x0311'
313
+ update_preauth_hash(packet)
314
+ end
315
+ response
280
316
  end
281
317
 
282
318
  # Generates the {RubySMB::SMB2::Packet::SessionSetupRequest} packet
@@ -289,6 +325,7 @@ module RubySMB
289
325
  packet = RubySMB::SMB2::Packet::SessionSetupRequest.new
290
326
  packet.smb2_header.session_id = session_id
291
327
  packet.set_type3_blob(type3_message.serialize)
328
+ packet.security_mode.signing_enabled = 1
292
329
  packet
293
330
  end
294
331