ruby_smb 3.0.0 → 3.0.4

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 (102) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/examples/anonymous_auth.rb +29 -6
  4. data/examples/auth_capture.rb +28 -0
  5. data/examples/file_server.rb +76 -0
  6. data/examples/read_file.rb +51 -10
  7. data/examples/tree_connect.rb +49 -8
  8. data/lib/ruby_smb/client/authentication.rb +11 -3
  9. data/lib/ruby_smb/client.rb +16 -2
  10. data/lib/ruby_smb/create_actions.rb +21 -0
  11. data/lib/ruby_smb/dcerpc/encrypting_file_system/efs_rpc_encrypt_file_srv_request.rb +20 -0
  12. data/lib/ruby_smb/dcerpc/encrypting_file_system/efs_rpc_encrypt_file_srv_response.rb +20 -0
  13. data/lib/ruby_smb/dcerpc/encrypting_file_system/efs_rpc_open_file_raw_request.rb +21 -0
  14. data/lib/ruby_smb/dcerpc/encrypting_file_system/efs_rpc_open_file_raw_response.rb +21 -0
  15. data/lib/ruby_smb/dcerpc/encrypting_file_system.rb +44 -0
  16. data/lib/ruby_smb/dcerpc/print_system/rpc_add_printer_driver_ex_request.rb +22 -0
  17. data/lib/ruby_smb/dcerpc/print_system/rpc_add_printer_driver_ex_response.rb +20 -0
  18. data/lib/ruby_smb/dcerpc/print_system/rpc_enum_printer_drivers_request.rb +24 -0
  19. data/lib/ruby_smb/dcerpc/print_system/rpc_enum_printer_drivers_response.rb +23 -0
  20. data/lib/ruby_smb/dcerpc/print_system/rpc_get_printer_driver_directory_request.rb +24 -0
  21. data/lib/ruby_smb/dcerpc/print_system/rpc_get_printer_driver_directory_response.rb +22 -0
  22. data/lib/ruby_smb/dcerpc/print_system.rb +69 -0
  23. data/lib/ruby_smb/dcerpc.rb +2 -2
  24. data/lib/ruby_smb/field/nt_status.rb +20 -1
  25. data/lib/ruby_smb/fscc/file_information/file_ea_information.rb +14 -0
  26. data/lib/ruby_smb/fscc/file_information/file_network_open_information.rb +22 -0
  27. data/lib/ruby_smb/fscc/file_information/file_stream_information.rb +16 -0
  28. data/lib/ruby_smb/fscc/file_information.rb +29 -0
  29. data/lib/ruby_smb/fscc/file_system_information/file_fs_attribute_information.rb +46 -0
  30. data/lib/ruby_smb/fscc/file_system_information/file_fs_volume_information.rb +19 -0
  31. data/lib/ruby_smb/fscc/file_system_information.rb +22 -0
  32. data/lib/ruby_smb/fscc.rb +1 -0
  33. data/lib/ruby_smb/generic_packet.rb +6 -0
  34. data/lib/ruby_smb/gss/provider/authenticator.rb +4 -0
  35. data/lib/ruby_smb/gss/provider/ntlm.rb +13 -3
  36. data/lib/ruby_smb/server/server_client/negotiation.rb +0 -2
  37. data/lib/ruby_smb/server/server_client/session_setup.rb +43 -32
  38. data/lib/ruby_smb/server/server_client/share_io.rb +28 -0
  39. data/lib/ruby_smb/server/server_client/tree_connect.rb +60 -0
  40. data/lib/ruby_smb/server/server_client.rb +214 -24
  41. data/lib/ruby_smb/server/session.rb +71 -0
  42. data/lib/ruby_smb/server/share/provider/disk.rb +437 -0
  43. data/lib/ruby_smb/server/share/provider/pipe.rb +27 -0
  44. data/lib/ruby_smb/server/share/provider/processor.rb +76 -0
  45. data/lib/ruby_smb/server/share/provider.rb +38 -0
  46. data/lib/ruby_smb/server/share.rb +11 -0
  47. data/lib/ruby_smb/server.rb +35 -3
  48. data/lib/ruby_smb/signing.rb +37 -11
  49. data/lib/ruby_smb/smb1/commands.rb +4 -0
  50. data/lib/ruby_smb/smb1/tree.rb +87 -79
  51. data/lib/ruby_smb/smb1.rb +0 -1
  52. data/lib/ruby_smb/smb2/bit_field/smb2_header_flags.rb +2 -1
  53. data/lib/ruby_smb/smb2/commands.rb +4 -0
  54. data/lib/ruby_smb/smb2/create_context/request.rb +64 -0
  55. data/lib/ruby_smb/smb2/create_context/response.rb +62 -0
  56. data/lib/ruby_smb/smb2/create_context.rb +74 -22
  57. data/lib/ruby_smb/smb2/packet/create_request.rb +44 -11
  58. data/lib/ruby_smb/smb2/packet/create_response.rb +17 -3
  59. data/lib/ruby_smb/smb2/packet/query_directory_request.rb +1 -1
  60. data/lib/ruby_smb/smb2/packet/query_directory_response.rb +2 -2
  61. data/lib/ruby_smb/smb2/packet/query_info_request.rb +43 -0
  62. data/lib/ruby_smb/smb2/packet/query_info_response.rb +23 -0
  63. data/lib/ruby_smb/smb2/packet/tree_connect_response.rb +1 -1
  64. data/lib/ruby_smb/smb2/packet/tree_disconnect_response.rb +1 -0
  65. data/lib/ruby_smb/smb2/packet.rb +2 -0
  66. data/lib/ruby_smb/smb2/tree.rb +80 -70
  67. data/lib/ruby_smb/smb2.rb +11 -0
  68. data/lib/ruby_smb/smb_error.rb +110 -0
  69. data/lib/ruby_smb/version.rb +1 -1
  70. data/lib/ruby_smb.rb +2 -0
  71. data/ruby_smb.gemspec +1 -1
  72. data/spec/lib/ruby_smb/client_spec.rb +10 -0
  73. data/spec/lib/ruby_smb/dcerpc/encrypting_file_system/efs_rpc_encrypt_file_srv_request_spec.rb +30 -0
  74. data/spec/lib/ruby_smb/dcerpc/encrypting_file_system/efs_rpc_encrypt_file_srv_response_spec.rb +30 -0
  75. data/spec/lib/ruby_smb/dcerpc/encrypting_file_system/efs_rpc_open_file_raw_request_spec.rb +38 -0
  76. data/spec/lib/ruby_smb/dcerpc/encrypting_file_system/efs_rpc_open_file_raw_response_spec.rb +38 -0
  77. data/spec/lib/ruby_smb/dcerpc/print_system/driver_container_spec.rb +41 -0
  78. data/spec/lib/ruby_smb/dcerpc/print_system/driver_info2_spec.rb +64 -0
  79. data/spec/lib/ruby_smb/dcerpc/print_system/rpc_add_printer_driver_ex_request_spec.rb +59 -0
  80. data/spec/lib/ruby_smb/dcerpc/print_system/rpc_add_printer_driver_ex_response_spec.rb +30 -0
  81. data/spec/lib/ruby_smb/dcerpc/print_system/rpc_enum_printer_drivers_request_spec.rb +62 -0
  82. data/spec/lib/ruby_smb/dcerpc/print_system/rpc_enum_printer_drivers_response_spec.rb +54 -0
  83. data/spec/lib/ruby_smb/dcerpc/print_system/rpc_get_printer_driver_directory_request_spec.rb +62 -0
  84. data/spec/lib/ruby_smb/dcerpc/print_system/rpc_get_printer_driver_directory_response_spec.rb +46 -0
  85. data/spec/lib/ruby_smb/field/nt_status_spec.rb +6 -2
  86. data/spec/lib/ruby_smb/gss/provider/ntlm/authenticator_spec.rb +4 -0
  87. data/spec/lib/ruby_smb/server/server_client_spec.rb +36 -53
  88. data/spec/lib/ruby_smb/server/session_spec.rb +38 -0
  89. data/spec/lib/ruby_smb/server/share/provider/disk_spec.rb +61 -0
  90. data/spec/lib/ruby_smb/server/share/provider/pipe_spec.rb +31 -0
  91. data/spec/lib/ruby_smb/server/share/provider_spec.rb +13 -0
  92. data/spec/lib/ruby_smb/smb1/tree_spec.rb +3 -3
  93. data/spec/lib/ruby_smb/smb2/bit_field/header_flags_spec.rb +8 -2
  94. data/spec/lib/ruby_smb/smb2/{create_context_spec.rb → create_context/create_context_request_spec.rb} +1 -1
  95. data/spec/lib/ruby_smb/smb2/packet/create_request_spec.rb +5 -5
  96. data/spec/lib/ruby_smb/smb2/packet/create_response_spec.rb +9 -5
  97. data/spec/lib/ruby_smb/smb2/packet/query_directory_response_spec.rb +3 -2
  98. data/spec/lib/ruby_smb/smb2/tree_spec.rb +3 -3
  99. data.tar.gz.sig +0 -0
  100. metadata +71 -7
  101. metadata.gz.sig +0 -0
  102. data/lib/ruby_smb/smb1/create_actions.rb +0 -20
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fb07e11fb5720a38ab9c1c1ba57b47ff291c048bb4b0ca404aad9c4bf05273d8
4
- data.tar.gz: bd0512b6e64200103ea611d5bc0616dc939beaf5a10cd15f2219ffcd1ee131e6
3
+ metadata.gz: a5143b8e8c62f4e51a00da4db3379ee8060a6f650bc91c0b5476f7587df3a513
4
+ data.tar.gz: 5005cf21af243f8925ddd7fc221b39589ec036df3b57a03af8e26a29cf8bf03a
5
5
  SHA512:
6
- metadata.gz: c12456264fc7eb9fe49b8a62e083e01adf62521ffb39c5a0748904800cd6e2c99d594c259043dcdf4d967edbb52ccaa0fed0255125d8f85df803156e344aa0c1
7
- data.tar.gz: 17781d318b042e2b0a76af4fc11b1430f42a224bd775696a882a19009303efe02f2b9285477475d10db8dd29272894ad87312281f125ce76382966ec6806941e
6
+ metadata.gz: a69b666d6a0199e0efa5df505ef03c312a9701cec10cc0774b4bed4e006c2c63ff461c1a0472060191dea0737ed483229bd7e78057f950d40c81fa02a5754683
7
+ data.tar.gz: cb87a7b4cef92975dac1ddc4e9edc72e170b6066a30f2cd9c321ef0f3e25557eae862dd2fe46b147a1ecd8c192ee81782f024858625e0a064c9ab9156084b715
checksums.yaml.gz.sig CHANGED
Binary file
@@ -4,14 +4,15 @@
4
4
  # including protocol negotiation and authentication.
5
5
 
6
6
  require 'bundler/setup'
7
+ require 'optparse'
7
8
  require 'ruby_smb'
8
9
 
9
- def run_authentication(address, smb1, smb2, smb3, username, password)
10
+ def run_authentication(address, smb1, smb2, smb3)
10
11
  # Create our socket and add it to the dispatcher
11
12
  sock = TCPSocket.new address, 445
12
13
  dispatcher = RubySMB::Dispatcher::Socket.new(sock)
13
14
 
14
- client = RubySMB::Client.new(dispatcher, smb1: smb1, smb2: smb2, smb3: smb3, username: username, password: password)
15
+ client = RubySMB::Client.new(dispatcher, smb1: smb1, smb2: smb2, smb3: smb3, username: '', password: '')
15
16
  protocol = client.negotiate
16
17
  status = client.authenticate
17
18
  puts "#{protocol} : #{status}"
@@ -22,9 +23,31 @@ def run_authentication(address, smb1, smb2, smb3, username, password)
22
23
  end
23
24
  end
24
25
 
25
- address = ARGV[0]
26
- username = ''
27
- password = ''
26
+ args = ARGV.dup
27
+ options = {
28
+ smbv1: true,
29
+ smbv2: true,
30
+ smbv3: true,
31
+ target: nil
32
+ }
33
+ options[:target ] = args.pop
34
+ optparser = OptionParser.new do |opts|
35
+ opts.banner = "Usage: #{File.basename(__FILE__)} [options] target"
36
+ opts.on("--[no-]smbv1", "Enable or disable SMBv1 (default: #{options[:smbv1] ? 'Enabled' : 'Disabled'})") do |smbv1|
37
+ options[:smbv1] = smbv1
38
+ end
39
+ opts.on("--[no-]smbv2", "Enable or disable SMBv2 (default: #{options[:smbv2] ? 'Enabled' : 'Disabled'})") do |smbv2|
40
+ options[:smbv2] = smbv2
41
+ end
42
+ opts.on("--[no-]smbv3", "Enable or disable SMBv3 (default: #{options[:smbv3] ? 'Enabled' : 'Disabled'})") do |smbv3|
43
+ options[:smbv3] = smbv3
44
+ end
45
+ end
46
+ optparser.parse!(args)
47
+
48
+ if options[:target].nil?
49
+ abort(optparser.help)
50
+ end
28
51
 
29
52
  # Negotiate with only SMB1 enabled
30
- run_authentication(address, true, false, false, username, password)
53
+ run_authentication(options[:target], options[:smbv1], options[:smbv2], options[:smbv3])
@@ -1,12 +1,31 @@
1
1
  #!/usr/bin/ruby
2
2
 
3
3
  require 'bundler/setup'
4
+ require 'optparse'
4
5
  require 'ruby_smb'
5
6
  require 'ruby_smb/gss/provider/ntlm'
6
7
 
7
8
  # we just need *a* default encoding to handle the strings from the NTLM messages
8
9
  Encoding.default_internal = 'UTF-8' if Encoding.default_internal.nil?
9
10
 
11
+ options = {
12
+ smbv1: true,
13
+ smbv2: true,
14
+ smbv3: true
15
+ }
16
+ OptionParser.new do |opts|
17
+ opts.banner = "Usage: #{File.basename(__FILE__)} [options]"
18
+ opts.on("--[no-]smbv1", "Enable or disable SMBv1 (default: #{options[:smbv1] ? 'Enabled' : 'Disabled'})") do |smbv1|
19
+ options[:smbv1] = smbv1
20
+ end
21
+ opts.on("--[no-]smbv2", "Enable or disable SMBv2 (default: #{options[:smbv2] ? 'Enabled' : 'Disabled'})") do |smbv2|
22
+ options[:smbv2] = smbv2
23
+ end
24
+ opts.on("--[no-]smbv3", "Enable or disable SMBv3 (default: #{options[:smbv3] ? 'Enabled' : 'Disabled'})") do |smbv3|
25
+ options[:smbv3] = smbv3
26
+ end
27
+ end.parse!
28
+
10
29
  def bin_to_hex(s)
11
30
  s.each_byte.map { |b| b.to_s(16).rjust(2, '0') }.join
12
31
  end
@@ -63,6 +82,15 @@ end
63
82
  server = RubySMB::Server.new(
64
83
  gss_provider: HaxorNTLMProvider.new
65
84
  )
85
+ server.dialects.select! { |dialect| RubySMB::Dialect[dialect].family != RubySMB::Dialect::FAMILY_SMB1 } unless options[:smbv1]
86
+ server.dialects.select! { |dialect| RubySMB::Dialect[dialect].family != RubySMB::Dialect::FAMILY_SMB2 } unless options[:smbv2]
87
+ server.dialects.select! { |dialect| RubySMB::Dialect[dialect].family != RubySMB::Dialect::FAMILY_SMB3 } unless options[:smbv3]
88
+
89
+ if server.dialects.empty?
90
+ puts "at least one version must be enabled"
91
+ exit false
92
+ end
93
+
66
94
  puts "server is running"
67
95
  server.run do
68
96
  puts "received connection"
@@ -0,0 +1,76 @@
1
+ #!/usr/bin/ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'optparse'
5
+ require 'ruby_smb'
6
+ require 'ruby_smb/gss/provider/ntlm'
7
+
8
+ # we just need *a* default encoding to handle the strings from the NTLM messages
9
+ Encoding.default_internal = 'UTF-8' if Encoding.default_internal.nil?
10
+
11
+ options = {
12
+ allow_anonymous: true,
13
+ domain: nil,
14
+ username: 'RubySMB',
15
+ password: 'password',
16
+ share_name: 'home',
17
+ share_path: '.',
18
+ smbv1: true,
19
+ smbv2: true,
20
+ smbv3: true
21
+ }
22
+ OptionParser.new do |opts|
23
+ opts.banner = "Usage: #{File.basename(__FILE__)} [options]"
24
+ opts.on("--path PATH", "The path to share (default: #{options[:share_path]})") do |path|
25
+ options[:share_path] = path
26
+ end
27
+ opts.on("--share SHARE", "The share name (default: #{options[:share_name]})") do |share|
28
+ options[:share_name] = share
29
+ end
30
+ opts.on("--[no-]anonymous", "Allow anonymous access (default: #{options[:allow_anonymous]})") do |allow_anonymous|
31
+ options[:allow_anonymous] = allow_anonymous
32
+ end
33
+ opts.on("--[no-]smbv1", "Enable or disable SMBv1 (default: #{options[:smbv1] ? 'Enabled' : 'Disabled'})") do |smbv1|
34
+ options[:smbv1] = smbv1
35
+ end
36
+ opts.on("--[no-]smbv2", "Enable or disable SMBv2 (default: #{options[:smbv2] ? 'Enabled' : 'Disabled'})") do |smbv2|
37
+ options[:smbv2] = smbv2
38
+ end
39
+ opts.on("--[no-]smbv3", "Enable or disable SMBv3 (default: #{options[:smbv3] ? 'Enabled' : 'Disabled'})") do |smbv3|
40
+ options[:smbv3] = smbv3
41
+ end
42
+ opts.on("--username USERNAME", "The account's username (default: #{options[:username]})") do |username|
43
+ if username.include?('\\')
44
+ options[:domain], options[:username] = username.split('\\', 2)
45
+ else
46
+ options[:username] = username
47
+ end
48
+ end
49
+ opts.on("--password PASSWORD", "The account's password (default: #{options[:password]})") do |password|
50
+ options[:password] = password
51
+ end
52
+ end.parse!
53
+
54
+ ntlm_provider = RubySMB::Gss::Provider::NTLM.new(allow_anonymous: options[:allow_anonymous])
55
+ ntlm_provider.put_account(options[:username], options[:password], domain: options[:domain]) # password can also be an NTLM hash
56
+
57
+ server = RubySMB::Server.new(
58
+ gss_provider: ntlm_provider,
59
+ logger: :stdout
60
+ )
61
+ server.dialects.select! { |dialect| RubySMB::Dialect[dialect].family != RubySMB::Dialect::FAMILY_SMB1 } unless options[:smbv1]
62
+ server.dialects.select! { |dialect| RubySMB::Dialect[dialect].family != RubySMB::Dialect::FAMILY_SMB2 } unless options[:smbv2]
63
+ server.dialects.select! { |dialect| RubySMB::Dialect[dialect].family != RubySMB::Dialect::FAMILY_SMB3 } unless options[:smbv3]
64
+
65
+ if server.dialects.empty?
66
+ puts "at least one version must be enabled"
67
+ exit false
68
+ end
69
+
70
+ server.add_share(RubySMB::Server::Share::Provider::Disk.new(options[:share_name], options[:share_path]))
71
+ puts "server is running"
72
+ server.run do
73
+ puts "received connection"
74
+ true
75
+ end
76
+
@@ -7,34 +7,75 @@
7
7
  # and read the file short.txt
8
8
 
9
9
  require 'bundler/setup'
10
+ require 'optparse'
10
11
  require 'ruby_smb'
11
12
 
12
- address = ARGV[0]
13
- username = ARGV[1]
14
- password = ARGV[2]
15
- share = ARGV[3]
16
- file = ARGV[4]
17
- smb_versions = ARGV[5]&.split(',') || ['1','2','3']
13
+ args = ARGV.dup
14
+ options = {
15
+ domain: '.',
16
+ username: '',
17
+ password: '',
18
+ share: nil,
19
+ smbv1: true,
20
+ smbv2: true,
21
+ smbv3: true,
22
+ target: nil
23
+ }
24
+ options[:file] = args.pop
25
+ options[:share] = args.pop
26
+ options[:target ] = args.pop
27
+ optparser = OptionParser.new do |opts|
28
+ opts.banner = "Usage: #{File.basename(__FILE__)} [options] target share file"
29
+ opts.on("--[no-]smbv1", "Enable or disable SMBv1 (default: #{options[:smbv1] ? 'Enabled' : 'Disabled'})") do |smbv1|
30
+ options[:smbv1] = smbv1
31
+ end
32
+ opts.on("--[no-]smbv2", "Enable or disable SMBv2 (default: #{options[:smbv2] ? 'Enabled' : 'Disabled'})") do |smbv2|
33
+ options[:smbv2] = smbv2
34
+ end
35
+ opts.on("--[no-]smbv3", "Enable or disable SMBv3 (default: #{options[:smbv3] ? 'Enabled' : 'Disabled'})") do |smbv3|
36
+ options[:smbv3] = smbv3
37
+ end
38
+ opts.on("--username USERNAME", "The account's username (default: #{options[:username]})") do |username|
39
+ if username.include?('\\')
40
+ options[:domain], options[:username] = username.split('\\', 2)
41
+ else
42
+ options[:username] = username
43
+ end
44
+ end
45
+ opts.on("--password PASSWORD", "The account's password (default: #{options[:password]})") do |password|
46
+ options[:password] = password
47
+ end
48
+ end
49
+ optparser.parse!(args)
50
+
51
+ if options[:target].nil? || options[:share].nil? || options[:file].nil?
52
+ abort(optparser.help)
53
+ end
18
54
 
19
- path = "\\\\#{address}\\#{share}"
55
+ path = "\\\\#{options[:target]}\\#{options[:share]}"
20
56
 
21
- sock = TCPSocket.new address, 445
57
+ sock = TCPSocket.new options[:target], 445
22
58
  dispatcher = RubySMB::Dispatcher::Socket.new(sock)
23
59
 
24
- client = RubySMB::Client.new(dispatcher, smb1: smb_versions.include?('1'), smb2: smb_versions.include?('2'), smb3: smb_versions.include?('3'), username: username, password: password)
60
+ client = RubySMB::Client.new(dispatcher, smb1: options[:smbv1], smb2: options[:smbv2], smb3: options[:smbv3], username: options[:username], password: options[:password], domain: options[:domain])
25
61
  protocol = client.negotiate
26
62
  status = client.authenticate
27
63
 
28
64
  puts "#{protocol} : #{status}"
65
+ unless status == WindowsError::NTStatus::STATUS_SUCCESS
66
+ puts 'Authentication failed!'
67
+ exit(1)
68
+ end
29
69
 
30
70
  begin
31
71
  tree = client.tree_connect(path)
32
72
  puts "Connected to #{path} successfully!"
33
73
  rescue StandardError => e
34
74
  puts "Failed to connect to #{path}: #{e.message}"
75
+ exit(1)
35
76
  end
36
77
 
37
- file = tree.open_file(filename: file)
78
+ file = tree.open_file(filename: options[:file])
38
79
 
39
80
  data = file.read
40
81
  puts data
@@ -6,24 +6,64 @@
6
6
  # This will try to connect to \\192.168.172.138\TEST_SHARE with the msfadmin:msfadmin credentials
7
7
 
8
8
  require 'bundler/setup'
9
+ require 'optparse'
9
10
  require 'ruby_smb'
10
11
 
11
- address = ARGV[0]
12
- username = ARGV[1]
13
- password = ARGV[2]
14
- share = ARGV[3]
15
- smb_versions = ARGV[4]&.split(',') || ['1','2','3']
12
+ args = ARGV.dup
13
+ options = {
14
+ domain: '.',
15
+ username: '',
16
+ password: '',
17
+ share: nil,
18
+ smbv1: true,
19
+ smbv2: true,
20
+ smbv3: true,
21
+ target: nil
22
+ }
23
+ options[:share] = args.pop
24
+ options[:target ] = args.pop
25
+ optparser = OptionParser.new do |opts|
26
+ opts.banner = "Usage: #{File.basename(__FILE__)} [options] target share"
27
+ opts.on("--[no-]smbv1", "Enable or disable SMBv1 (default: #{options[:smbv1] ? 'Enabled' : 'Disabled'})") do |smbv1|
28
+ options[:smbv1] = smbv1
29
+ end
30
+ opts.on("--[no-]smbv2", "Enable or disable SMBv2 (default: #{options[:smbv2] ? 'Enabled' : 'Disabled'})") do |smbv2|
31
+ options[:smbv2] = smbv2
32
+ end
33
+ opts.on("--[no-]smbv3", "Enable or disable SMBv3 (default: #{options[:smbv3] ? 'Enabled' : 'Disabled'})") do |smbv3|
34
+ options[:smbv3] = smbv3
35
+ end
36
+ opts.on("--username USERNAME", "The account's username (default: #{options[:username]})") do |username|
37
+ if username.include?('\\')
38
+ options[:domain], options[:username] = username.split('\\', 2)
39
+ else
40
+ options[:username] = username
41
+ end
42
+ end
43
+ opts.on("--password PASSWORD", "The account's password (default: #{options[:password]})") do |password|
44
+ options[:password] = password
45
+ end
46
+ end
47
+ optparser.parse!(args)
48
+
49
+ if options[:target].nil? || options[:share].nil?
50
+ abort(optparser.help)
51
+ end
16
52
 
17
- path = "\\\\#{address}\\#{share}"
53
+ path = "\\\\#{options[:target]}\\#{options[:share]}"
18
54
 
19
- sock = TCPSocket.new address, 445
55
+ sock = TCPSocket.new options[:target], 445
20
56
  dispatcher = RubySMB::Dispatcher::Socket.new(sock)
21
57
 
22
- client = RubySMB::Client.new(dispatcher, smb1: smb_versions.include?('1'), smb2: smb_versions.include?('2'), smb3: smb_versions.include?('3'), username: username, password: password)
58
+ client = RubySMB::Client.new(dispatcher, smb1: options[:smbv1], smb2: options[:smbv2], smb3: options[:smbv3], username: options[:username], password: options[:password], domain: options[:domain])
23
59
  protocol = client.negotiate
24
60
  status = client.authenticate
25
61
 
26
62
  puts "#{protocol} : #{status}"
63
+ unless status == WindowsError::NTStatus::STATUS_SUCCESS
64
+ puts 'Authentication failed!'
65
+ exit(1)
66
+ end
27
67
 
28
68
  begin
29
69
  tree = client.tree_connect(path)
@@ -31,4 +71,5 @@ begin
31
71
  tree.disconnect!
32
72
  rescue StandardError => e
33
73
  puts "Failed to connect to #{path}: #{e.message}"
74
+ exit(1)
34
75
  end
@@ -212,9 +212,17 @@ module RubySMB
212
212
 
213
213
  raw = smb2_ntlmssp_authenticate(type3_message, @session_id)
214
214
  response = smb2_ntlmssp_final_packet(raw)
215
-
216
- if @smb3 && !@session_encrypt_data && response.session_flags.encrypt_data == 1
217
- @session_encrypt_data = true
215
+ @session_is_guest = response.session_flags.guest == 1
216
+
217
+ if @smb3
218
+ if response.session_flags.encrypt_data == 1
219
+ # if the server indicates that encryption is required, enable it
220
+ @session_encrypt_data = true
221
+ elsif (@session_is_guest && password != '') || (username == '' && password == '')
222
+ # disable encryption when necessary
223
+ @session_encrypt_data = false
224
+ end
225
+ # otherwise, leave encryption to the default value that it was initialized to
218
226
  end
219
227
  ######
220
228
  # DEBUG
@@ -129,6 +129,11 @@ module RubySMB
129
129
  # @return [Integer]
130
130
  attr_accessor :session_id
131
131
 
132
+ # Whether or not the current session has the guest flag set
133
+ # @!attribute [rw] session_is_guest
134
+ # @return [Boolean]
135
+ attr_accessor :session_is_guest
136
+
132
137
  # Whether or not the Server requires signing
133
138
  # @!attribute [rw] signing_enabled
134
139
  # @return [Boolean]
@@ -292,6 +297,7 @@ module RubySMB
292
297
  @sequence_counter = 0
293
298
  @session_id = 0x00
294
299
  @session_key = ''
300
+ @session_is_guest = false
295
301
  @signing_required = false
296
302
  @smb1 = smb1
297
303
  @smb2 = smb2
@@ -306,6 +312,8 @@ module RubySMB
306
312
  @server_supports_multi_credit = false
307
313
 
308
314
  # SMB 3.x options
315
+ # this merely initializes the default value for session encryption, it may be changed as necessary when a
316
+ # session setup response is received
309
317
  @session_encrypt_data = always_encrypt
310
318
 
311
319
  @ntlm_client = Net::NTLM::Client.new(
@@ -444,8 +452,13 @@ module RubySMB
444
452
  unless packet.is_a?(RubySMB::SMB2::Packet::SessionSetupRequest) || session_key.empty?
445
453
  if self.smb2 && signing_required
446
454
  packet = smb2_sign(packet)
447
- elsif self.smb3 && (signing_required || packet.is_a?(RubySMB::SMB2::Packet::TreeConnectRequest))
448
- packet = smb3_sign(packet)
455
+ elsif self.smb3
456
+ # see: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/652e0c14-5014-4470-999d-b174d7b2da87
457
+ if @dialect == '0x0311' && (signing_required || (!@session_is_guest && packet.is_a?(RubySMB::SMB2::Packet::TreeConnectRequest)))
458
+ packet = smb3_sign(packet)
459
+ elsif signing_required
460
+ packet = smb3_sign(packet)
461
+ end
449
462
  end
450
463
  end
451
464
  else
@@ -589,6 +602,7 @@ module RubySMB
589
602
  self.session_id = 0x00
590
603
  self.user_id = 0x00
591
604
  self.session_key = ''
605
+ self.session_is_guest = false
592
606
  self.sequence_counter = 0
593
607
  self.smb2_message_id = 0
594
608
  self.client_encryption_key = nil
@@ -0,0 +1,21 @@
1
+ module RubySMB
2
+ # This module holds the Create Actions used in NT_TRANSACT_CREATE,
3
+ # SMB_COM_NT_CREATE_ANDX, and SMB2_CREATE responses. The definitions for these
4
+ # values can be found at
5
+ # [2.2.7.1.2 Response](https://msdn.microsoft.com/en-us/library/ee441961.aspx)
6
+ # and
7
+ # [2.2.14 SMB2 CREATE Response](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-smb2/d166aa9e-0b53-410e-b35e-3933d8131927)
8
+ module CreateActions
9
+ # An existing file was deleted and a new file was created in its place.
10
+ FILE_SUPERSEDED = 0x00000000
11
+
12
+ # An existing file was opened.
13
+ FILE_OPENED = 0x00000001
14
+
15
+ # A new file was created.
16
+ FILE_CREATED = 0x00000002
17
+
18
+ # An existing file was overwritten.
19
+ FILE_OVERWRITTEN = 0x00000003
20
+ end
21
+ end
@@ -0,0 +1,20 @@
1
+ module RubySMB
2
+ module Dcerpc
3
+ module EncryptingFileSystem
4
+
5
+ # [3.1.4.2.5 EfsRpcEncryptFileSrv (Opnum 4)](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-efsr/0d599976-758c-4dbd-ac8c-c9db2a922d76)
6
+ class EfsRpcEncryptFileSrvRequest < BinData::Record
7
+ attr_reader :opnum
8
+
9
+ endian :little
10
+
11
+ ndr_conf_var_wide_stringz :file_name
12
+
13
+ def initialize_instance
14
+ super
15
+ @opnum = EFS_RPC_ENCRYPT_FILE_SRV
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ module RubySMB
2
+ module Dcerpc
3
+ module EncryptingFileSystem
4
+
5
+ # [3.1.4.2.5 EfsRpcEncryptFileSrv (Opnum 4)](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-efsr/0d599976-758c-4dbd-ac8c-c9db2a922d76)
6
+ class EfsRpcEncryptFileSrvResponse < BinData::Record
7
+ attr_reader :opnum
8
+
9
+ endian :little
10
+
11
+ ndr_uint32 :error_status
12
+
13
+ def initialize_instance
14
+ super
15
+ @opnum = EFS_RPC_ENCRYPT_FILE_SRV
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,21 @@
1
+ module RubySMB
2
+ module Dcerpc
3
+ module EncryptingFileSystem
4
+
5
+ # [3.1.4.2.1 EfsRpcOpenFileRaw (Opnum 0)](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-efsr/ccc4fb75-1c86-41d7-bbc4-b278ec13bfb8)
6
+ class EfsRpcOpenFileRawRequest < BinData::Record
7
+ attr_reader :opnum
8
+
9
+ endian :little
10
+
11
+ ndr_conf_var_wide_stringz :file_name
12
+ ndr_uint32 :flags
13
+
14
+ def initialize_instance
15
+ super
16
+ @opnum = EFS_RPC_OPEN_FILE_RAW
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ module RubySMB
2
+ module Dcerpc
3
+ module EncryptingFileSystem
4
+
5
+ # [3.1.4.2.1 EfsRpcOpenFileRaw (Opnum 0)](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-efsr/ccc4fb75-1c86-41d7-bbc4-b278ec13bfb8)
6
+ class EfsRpcOpenFileRawResponse < BinData::Record
7
+ attr_reader :opnum
8
+
9
+ endian :little
10
+
11
+ ndr_context_handle :h_context
12
+ ndr_uint32 :error_status
13
+
14
+ def initialize_instance
15
+ super
16
+ @opnum = EFS_RPC_OPEN_FILE_RAW
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,44 @@
1
+ module RubySMB
2
+ module Dcerpc
3
+ module EncryptingFileSystem
4
+ # see: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-efsr/403c7ae0-1a3a-4e96-8efc-54e79a2cc451
5
+ UUID = EFSRPC_UUID = 'df1941c5-fe89-4e79-bf10-463657acf44d'.freeze
6
+ LSARPC_UUID = 'c681d488-d850-11d0-8c52-00c04fd90f7e'.freeze
7
+ VER_MAJOR = 1
8
+ VER_MINOR = 0
9
+
10
+ # Operation numbers
11
+ EFS_RPC_OPEN_FILE_RAW = 0
12
+ EFS_RPC_WRITE_FILE_RAW = 1
13
+ EFS_RPC_CLOSE_RAW = 3
14
+ EFS_RPC_ENCRYPT_FILE_SRV = 4
15
+ EFS_RPC_DECRYPT_FILE_SRV = 5
16
+ EFS_RPC_QUERY_USERS_ON_FILE = 6
17
+ EFS_RPC_QUERY_RECOVERY_AGENTS = 7
18
+ EFS_RPC_REMOVE_USERS_FROM_FILE = 8
19
+ EFS_RPC_ADD_USERS_TO_FILE = 9
20
+ EFS_RPC_NOT_SUPPORTED = 11
21
+ EFS_RPC_FILE_KEY_INFO = 12
22
+ EFS_RPC_DUPLICATE_ENCRYPTION_INFO_FILE = 13
23
+ EFS_RPC_ADD_USERS_TO_FILE_EX = 15
24
+ EFS_RPC_FILE_KEY_INFO_EX = 16
25
+ EFS_RPC_GET_ENCRYPTED_FILE_METADATA = 18
26
+ EFS_RPC_SET_ENCRYPTED_FILE_METADATA = 19
27
+ EFS_RPC_FLUSH_EFS_CACHE = 20
28
+ EFS_RPC_ENCRYPT_FILE_EX_SRV = 21
29
+ EFS_RPC_QUERY_PROTECTORS = 22
30
+
31
+ # EfsRpcOpenFileRaw flags,
32
+ # see: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-efsr/ccc4fb75-1c86-41d7-bbc4-b278ec13bfb8
33
+ CREATE_FOR_IMPORT = 0x00000001
34
+ CREATE_FOR_DIR = 0x00000002
35
+ OVERWRITE_HIDDEN = 0x00000004
36
+ EFS_DROP_ALTERNATE_STREAMS = 0x00000010
37
+
38
+ require 'ruby_smb/dcerpc/encrypting_file_system/efs_rpc_encrypt_file_srv_request'
39
+ require 'ruby_smb/dcerpc/encrypting_file_system/efs_rpc_encrypt_file_srv_response'
40
+ require 'ruby_smb/dcerpc/encrypting_file_system/efs_rpc_open_file_raw_request'
41
+ require 'ruby_smb/dcerpc/encrypting_file_system/efs_rpc_open_file_raw_response'
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,22 @@
1
+ module RubySMB
2
+ module Dcerpc
3
+ module PrintSystem
4
+
5
+ # [3.1.4.4.8 RpcAddPrinterDriverEx (Opnum 89)](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rprn/b96cc497-59e5-4510-ab04-5484993b259b)
6
+ class RpcAddPrinterDriverExRequest < BinData::Record
7
+ attr_reader :opnum
8
+
9
+ endian :little
10
+
11
+ ndr_wide_stringz_ptr :p_name
12
+ driver_container :p_driver_container
13
+ ndr_uint32 :dw_file_copy_flags
14
+
15
+ def initialize_instance
16
+ super
17
+ @opnum = RPC_ADD_PRINTER_DRIVER_EX
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,20 @@
1
+ module RubySMB
2
+ module Dcerpc
3
+ module PrintSystem
4
+
5
+ # [3.1.4.4.8 RpcAddPrinterDriverEx (Opnum 89)](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rprn/b96cc497-59e5-4510-ab04-5484993b259b)
6
+ class RpcAddPrinterDriverExResponse < BinData::Record
7
+ attr_reader :opnum
8
+
9
+ endian :little
10
+
11
+ def initialize_instance
12
+ super
13
+ @opnum = RPC_ADD_PRINTER_DRIVER_EX
14
+ end
15
+
16
+ ndr_uint32 :error_status
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,24 @@
1
+ module RubySMB
2
+ module Dcerpc
3
+ module PrintSystem
4
+
5
+ # [3.1.4.4.2 RpcEnumPrinterDrivers (Opnum 10)](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rprn/857d00ac-3682-4a0d-86ca-3d3c372e5e4a)
6
+ class RpcEnumPrinterDriversRequest < BinData::Record
7
+ attr_reader :opnum
8
+
9
+ endian :little
10
+
11
+ def initialize_instance
12
+ super
13
+ @opnum = RPC_ENUM_PRINTER_DRIVERS
14
+ end
15
+
16
+ ndr_wide_stringz_ptr :p_name
17
+ ndr_wide_stringz_ptr :p_environment
18
+ ndr_uint32 :level
19
+ rprn_byte_array_ptr :p_drivers
20
+ ndr_uint32 :cb_buf
21
+ end
22
+ end
23
+ end
24
+ end