ruby_smb 3.0.0 → 3.0.4

Sign up to get free protection for your applications and to get access to all the features.
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