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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/examples/anonymous_auth.rb +29 -6
- data/examples/auth_capture.rb +28 -0
- data/examples/file_server.rb +76 -0
- data/examples/read_file.rb +51 -10
- data/examples/tree_connect.rb +49 -8
- data/lib/ruby_smb/client/authentication.rb +11 -3
- data/lib/ruby_smb/client.rb +16 -2
- data/lib/ruby_smb/create_actions.rb +21 -0
- data/lib/ruby_smb/dcerpc/encrypting_file_system/efs_rpc_encrypt_file_srv_request.rb +20 -0
- data/lib/ruby_smb/dcerpc/encrypting_file_system/efs_rpc_encrypt_file_srv_response.rb +20 -0
- data/lib/ruby_smb/dcerpc/encrypting_file_system/efs_rpc_open_file_raw_request.rb +21 -0
- data/lib/ruby_smb/dcerpc/encrypting_file_system/efs_rpc_open_file_raw_response.rb +21 -0
- data/lib/ruby_smb/dcerpc/encrypting_file_system.rb +44 -0
- data/lib/ruby_smb/dcerpc/print_system/rpc_add_printer_driver_ex_request.rb +22 -0
- data/lib/ruby_smb/dcerpc/print_system/rpc_add_printer_driver_ex_response.rb +20 -0
- data/lib/ruby_smb/dcerpc/print_system/rpc_enum_printer_drivers_request.rb +24 -0
- data/lib/ruby_smb/dcerpc/print_system/rpc_enum_printer_drivers_response.rb +23 -0
- data/lib/ruby_smb/dcerpc/print_system/rpc_get_printer_driver_directory_request.rb +24 -0
- data/lib/ruby_smb/dcerpc/print_system/rpc_get_printer_driver_directory_response.rb +22 -0
- data/lib/ruby_smb/dcerpc/print_system.rb +69 -0
- data/lib/ruby_smb/dcerpc.rb +2 -2
- data/lib/ruby_smb/field/nt_status.rb +20 -1
- data/lib/ruby_smb/fscc/file_information/file_ea_information.rb +14 -0
- data/lib/ruby_smb/fscc/file_information/file_network_open_information.rb +22 -0
- data/lib/ruby_smb/fscc/file_information/file_stream_information.rb +16 -0
- data/lib/ruby_smb/fscc/file_information.rb +29 -0
- data/lib/ruby_smb/fscc/file_system_information/file_fs_attribute_information.rb +46 -0
- data/lib/ruby_smb/fscc/file_system_information/file_fs_volume_information.rb +19 -0
- data/lib/ruby_smb/fscc/file_system_information.rb +22 -0
- data/lib/ruby_smb/fscc.rb +1 -0
- data/lib/ruby_smb/generic_packet.rb +6 -0
- data/lib/ruby_smb/gss/provider/authenticator.rb +4 -0
- data/lib/ruby_smb/gss/provider/ntlm.rb +13 -3
- data/lib/ruby_smb/server/server_client/negotiation.rb +0 -2
- data/lib/ruby_smb/server/server_client/session_setup.rb +43 -32
- data/lib/ruby_smb/server/server_client/share_io.rb +28 -0
- data/lib/ruby_smb/server/server_client/tree_connect.rb +60 -0
- data/lib/ruby_smb/server/server_client.rb +214 -24
- data/lib/ruby_smb/server/session.rb +71 -0
- data/lib/ruby_smb/server/share/provider/disk.rb +437 -0
- data/lib/ruby_smb/server/share/provider/pipe.rb +27 -0
- data/lib/ruby_smb/server/share/provider/processor.rb +76 -0
- data/lib/ruby_smb/server/share/provider.rb +38 -0
- data/lib/ruby_smb/server/share.rb +11 -0
- data/lib/ruby_smb/server.rb +35 -3
- data/lib/ruby_smb/signing.rb +37 -11
- data/lib/ruby_smb/smb1/commands.rb +4 -0
- data/lib/ruby_smb/smb1/tree.rb +87 -79
- data/lib/ruby_smb/smb1.rb +0 -1
- data/lib/ruby_smb/smb2/bit_field/smb2_header_flags.rb +2 -1
- data/lib/ruby_smb/smb2/commands.rb +4 -0
- data/lib/ruby_smb/smb2/create_context/request.rb +64 -0
- data/lib/ruby_smb/smb2/create_context/response.rb +62 -0
- data/lib/ruby_smb/smb2/create_context.rb +74 -22
- data/lib/ruby_smb/smb2/packet/create_request.rb +44 -11
- data/lib/ruby_smb/smb2/packet/create_response.rb +17 -3
- data/lib/ruby_smb/smb2/packet/query_directory_request.rb +1 -1
- data/lib/ruby_smb/smb2/packet/query_directory_response.rb +2 -2
- data/lib/ruby_smb/smb2/packet/query_info_request.rb +43 -0
- data/lib/ruby_smb/smb2/packet/query_info_response.rb +23 -0
- data/lib/ruby_smb/smb2/packet/tree_connect_response.rb +1 -1
- data/lib/ruby_smb/smb2/packet/tree_disconnect_response.rb +1 -0
- data/lib/ruby_smb/smb2/packet.rb +2 -0
- data/lib/ruby_smb/smb2/tree.rb +80 -70
- data/lib/ruby_smb/smb2.rb +11 -0
- data/lib/ruby_smb/smb_error.rb +110 -0
- data/lib/ruby_smb/version.rb +1 -1
- data/lib/ruby_smb.rb +2 -0
- data/ruby_smb.gemspec +1 -1
- data/spec/lib/ruby_smb/client_spec.rb +10 -0
- data/spec/lib/ruby_smb/dcerpc/encrypting_file_system/efs_rpc_encrypt_file_srv_request_spec.rb +30 -0
- data/spec/lib/ruby_smb/dcerpc/encrypting_file_system/efs_rpc_encrypt_file_srv_response_spec.rb +30 -0
- data/spec/lib/ruby_smb/dcerpc/encrypting_file_system/efs_rpc_open_file_raw_request_spec.rb +38 -0
- data/spec/lib/ruby_smb/dcerpc/encrypting_file_system/efs_rpc_open_file_raw_response_spec.rb +38 -0
- data/spec/lib/ruby_smb/dcerpc/print_system/driver_container_spec.rb +41 -0
- data/spec/lib/ruby_smb/dcerpc/print_system/driver_info2_spec.rb +64 -0
- data/spec/lib/ruby_smb/dcerpc/print_system/rpc_add_printer_driver_ex_request_spec.rb +59 -0
- data/spec/lib/ruby_smb/dcerpc/print_system/rpc_add_printer_driver_ex_response_spec.rb +30 -0
- data/spec/lib/ruby_smb/dcerpc/print_system/rpc_enum_printer_drivers_request_spec.rb +62 -0
- data/spec/lib/ruby_smb/dcerpc/print_system/rpc_enum_printer_drivers_response_spec.rb +54 -0
- data/spec/lib/ruby_smb/dcerpc/print_system/rpc_get_printer_driver_directory_request_spec.rb +62 -0
- data/spec/lib/ruby_smb/dcerpc/print_system/rpc_get_printer_driver_directory_response_spec.rb +46 -0
- data/spec/lib/ruby_smb/field/nt_status_spec.rb +6 -2
- data/spec/lib/ruby_smb/gss/provider/ntlm/authenticator_spec.rb +4 -0
- data/spec/lib/ruby_smb/server/server_client_spec.rb +36 -53
- data/spec/lib/ruby_smb/server/session_spec.rb +38 -0
- data/spec/lib/ruby_smb/server/share/provider/disk_spec.rb +61 -0
- data/spec/lib/ruby_smb/server/share/provider/pipe_spec.rb +31 -0
- data/spec/lib/ruby_smb/server/share/provider_spec.rb +13 -0
- data/spec/lib/ruby_smb/smb1/tree_spec.rb +3 -3
- data/spec/lib/ruby_smb/smb2/bit_field/header_flags_spec.rb +8 -2
- data/spec/lib/ruby_smb/smb2/{create_context_spec.rb → create_context/create_context_request_spec.rb} +1 -1
- data/spec/lib/ruby_smb/smb2/packet/create_request_spec.rb +5 -5
- data/spec/lib/ruby_smb/smb2/packet/create_response_spec.rb +9 -5
- data/spec/lib/ruby_smb/smb2/packet/query_directory_response_spec.rb +3 -2
- data/spec/lib/ruby_smb/smb2/tree_spec.rb +3 -3
- data.tar.gz.sig +0 -0
- metadata +71 -7
- metadata.gz.sig +0 -0
- 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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a5143b8e8c62f4e51a00da4db3379ee8060a6f650bc91c0b5476f7587df3a513
|
4
|
+
data.tar.gz: 5005cf21af243f8925ddd7fc221b39589ec036df3b57a03af8e26a29cf8bf03a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a69b666d6a0199e0efa5df505ef03c312a9701cec10cc0774b4bed4e006c2c63ff461c1a0472060191dea0737ed483229bd7e78057f950d40c81fa02a5754683
|
7
|
+
data.tar.gz: cb87a7b4cef92975dac1ddc4e9edc72e170b6066a30f2cd9c321ef0f3e25557eae862dd2fe46b147a1ecd8c192ee81782f024858625e0a064c9ab9156084b715
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data/examples/anonymous_auth.rb
CHANGED
@@ -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
|
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:
|
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
|
-
|
26
|
-
|
27
|
-
|
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(
|
53
|
+
run_authentication(options[:target], options[:smbv1], options[:smbv2], options[:smbv3])
|
data/examples/auth_capture.rb
CHANGED
@@ -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
|
+
|
data/examples/read_file.rb
CHANGED
@@ -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
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
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 = "\\\\#{
|
55
|
+
path = "\\\\#{options[:target]}\\#{options[:share]}"
|
20
56
|
|
21
|
-
sock = TCPSocket.new
|
57
|
+
sock = TCPSocket.new options[:target], 445
|
22
58
|
dispatcher = RubySMB::Dispatcher::Socket.new(sock)
|
23
59
|
|
24
|
-
client = RubySMB::Client.new(dispatcher, smb1:
|
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
|
data/examples/tree_connect.rb
CHANGED
@@ -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
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
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
|
53
|
+
path = "\\\\#{options[:target]}\\#{options[:share]}"
|
18
54
|
|
19
|
-
sock = TCPSocket.new
|
55
|
+
sock = TCPSocket.new options[:target], 445
|
20
56
|
dispatcher = RubySMB::Dispatcher::Socket.new(sock)
|
21
57
|
|
22
|
-
client = RubySMB::Client.new(dispatcher, smb1:
|
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
|
-
|
217
|
-
|
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
|
data/lib/ruby_smb/client.rb
CHANGED
@@ -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
|
448
|
-
|
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
|