ruby_smb 3.0.3 → 3.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/.github/workflows/verify.yml +1 -1
  4. data/.simplecov +1 -1
  5. data/CONTRIBUTING.md +28 -3
  6. data/README.md +8 -0
  7. data/examples/pwsh_service.rb +112 -0
  8. data/lib/ruby_smb/client/negotiation.rb +1 -1
  9. data/lib/ruby_smb/client.rb +23 -2
  10. data/lib/ruby_smb/dcerpc/request.rb +2 -0
  11. data/lib/ruby_smb/dcerpc/svcctl/create_service_w_request.rb +35 -0
  12. data/lib/ruby_smb/dcerpc/svcctl/create_service_w_response.rb +24 -0
  13. data/lib/ruby_smb/dcerpc/svcctl/delete_service_request.rb +21 -0
  14. data/lib/ruby_smb/dcerpc/svcctl/delete_service_response.rb +21 -0
  15. data/lib/ruby_smb/dcerpc/svcctl.rb +66 -5
  16. data/lib/ruby_smb/dcerpc/winreg/open_root_key_request.rb +1 -1
  17. data/lib/ruby_smb/dcerpc/winreg/regsam.rb +1 -1
  18. data/lib/ruby_smb/dcerpc/winreg.rb +1 -1
  19. data/lib/ruby_smb/server/session.rb +6 -0
  20. data/lib/ruby_smb/smb1/bit_field/directory_access_mask.rb +1 -1
  21. data/lib/ruby_smb/smb1/bit_field/file_access_mask.rb +1 -1
  22. data/lib/ruby_smb/smb2/bit_field/directory_access_mask.rb +1 -1
  23. data/lib/ruby_smb/smb2/bit_field/file_access_mask.rb +1 -1
  24. data/lib/ruby_smb/smb2/packet/session_setup_request.rb +11 -0
  25. data/lib/ruby_smb/version.rb +1 -1
  26. data/ruby_smb.gemspec +1 -1
  27. data/spec/lib/ruby_smb/client_spec.rb +10 -0
  28. data/spec/lib/ruby_smb/dcerpc/svcctl/create_service_w_request_spec.rb +143 -0
  29. data/spec/lib/ruby_smb/dcerpc/svcctl/create_service_w_response_spec.rb +45 -0
  30. data/spec/lib/ruby_smb/dcerpc/svcctl/delete_service_request_spec.rb +29 -0
  31. data/spec/lib/ruby_smb/dcerpc/svcctl/delete_service_response_spec.rb +29 -0
  32. data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_request_spec.rb +8 -8
  33. data/spec/lib/ruby_smb/dcerpc/winreg/regsam_spec.rb +1 -1
  34. data/spec/lib/ruby_smb/dcerpc/winreg_spec.rb +1 -1
  35. data/spec/lib/ruby_smb/smb1/bit_field/directory_access_mask_spec.rb +4 -4
  36. data/spec/lib/ruby_smb/smb1/bit_field/file_access_mask_spec.rb +4 -4
  37. data/spec/lib/ruby_smb/smb1/tree_spec.rb +5 -0
  38. data/spec/lib/ruby_smb/smb2/bit_field/directory_access_mask_spec.rb +4 -4
  39. data/spec/lib/ruby_smb/smb2/bit_field/file_access_mask_spec.rb +4 -4
  40. data/spec/lib/ruby_smb/smb2/tree_spec.rb +6 -1
  41. data/spec/spec_helper.rb +2 -3
  42. data.tar.gz.sig +0 -0
  43. metadata +17 -4
  44. metadata.gz.sig +2 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e7ce1d9892eb5ccf2881dd78a8e1983926554f69de301560539e7d7da37061b0
4
- data.tar.gz: '01692d97a27c63f470b7c2899ad9cfb2828c9e254f0747176a29555d462bbf1d'
3
+ metadata.gz: 4dd0be012c18ad4e243cbfa2948fc620448766612b2f33be278583981fa2cf90
4
+ data.tar.gz: '07309ce54e701f2c3654a9cdbc8b3eff9d42d54451321e6e17a49d46ae4ce162'
5
5
  SHA512:
6
- metadata.gz: 2fafe3f08b518b285b33832e0809c9b5f4687800457bec2c1945dd33f4c7109466926a5f55a537a3cdf9851f1c0c6b9979aa0f8d75f0004749f8bdd56ba26ab4
7
- data.tar.gz: 070550512fe2ffadaecb97ea014e8fa5563b722b0184303c022f901bb60466991979673adf0dedfb411585b910e92d435308f7d900326ee6d8aa8ead5e1cdf0c
6
+ metadata.gz: ee506f05e67f8fa1a61b0d0f05470b41e20c5972c9c9584e8fe8069352a2cd09704b66d42856fb1330a93def276525b0d50047e93b981479c064c36f35f8298a
7
+ data.tar.gz: 78c37f1157393e17c51a6de7ff55fb25206e84f68740c958c406c36432ca90bc572716670640b9153a3ff66247dfcbeae8f4305f3c17cd91af64e8a4fc092894
checksums.yaml.gz.sig CHANGED
Binary file
@@ -17,10 +17,10 @@ jobs:
17
17
  fail-fast: true
18
18
  matrix:
19
19
  ruby:
20
- - 2.5
21
20
  - 2.6
22
21
  - 2.7
23
22
  - 3.0.3
23
+ - 3.1.1
24
24
  test_cmd:
25
25
  - bundle exec rspec
26
26
 
data/.simplecov CHANGED
@@ -2,7 +2,7 @@
2
2
  # controlled by running with coverage, so don't explicitly start coverage (and
3
3
  # therefore generate a report) when in Rubymine. This _will_ generate a report
4
4
  # whenever `rake spec` is run.
5
- unless ENV['RM_INFO']
5
+ unless ENV['RM_INFO'] || SimpleCov.running
6
6
  SimpleCov.start
7
7
  end
8
8
 
data/CONTRIBUTING.md CHANGED
@@ -1,8 +1,33 @@
1
1
  # Contributing
2
2
 
3
+ ## Versioning
4
+
5
+ RubySMB attempts to follow [the Semantic Versioning 2.0.0](https://semver.org/) standard, however due to certain key architectural qualities, some reservations are made regarding what will trigger major and minor version bumps. A large component of RubySMB are the data definitions written using [BinData](https://github.com/dmendel/bindata). These definitions are implemented in an incremental fashion, causing some to be missing while others are only partially implemented (particularly in cases where fields are dependent on other types that may or may not be defined). Because of this, the RubySMB project reserves the right to update these definitions without incrementing the major version. In most cases, the definitions and their fields do not need to be used to perform standard operations such as connecting to, authenticating to and reading a file from a remote SMB server. The API provided by non-BinData objects will remain stable across minor versions, with backwards incompatible changes triggering a major version bump. Backwards incompatible changes to data structure definitions in BinData will cause the RubySMB maintianers to perform a minor version bump. These changes include but are not limited to:
6
+
7
+ * Changes to the class name due to how BinData's internal registration works
8
+ * Their field names which may be updated to avoid conflicts
9
+ * Their field types which may be extended with more functionality or switched from integers to full-flag based definitions
10
+
11
+ ### Usage Examples
12
+ The following two examples show dangerous operations that may not be stable across minor version bumps, and safe operations.
13
+
14
+ ```
15
+ # dangerous operation, the BinData object name (TransformHeader) may change in the future
16
+ header = RubySMB::SMB2::Packet::TransformHeader.read(raw_request)
17
+ # also dangerous operation, the field name may change in the future
18
+ header.flags = 0
19
+ ```
20
+
21
+ ```
22
+ # safe operation, the API exposed on the Client won't change without a major version bump
23
+ client = RubySMB::Client.new(dispatcher, smb1: options[:smbv1], smb2: options[:smbv2], smb3: options[:smbv3], username: options[:username], password: options[:password], domain: options[:domain])
24
+ # safe operation, methods on non-BinData objects won't change without a major version bump
25
+ protocol = client.negotiate
26
+ ```
27
+
3
28
  ## Forking
4
29
 
5
- [Fork this repository](https://github.com/rapid7/smb2/fork)
30
+ [Fork this repository](https://github.com/rapid7/ruby_smb/fork)
6
31
 
7
32
  ## Branching
8
33
 
@@ -14,7 +39,7 @@ Branch names follow the format `TYPE/ISSUE/SUMMARY`. You can create it with `gi
14
39
 
15
40
  ### `ISSUE`
16
41
 
17
- `ISSUE` is either a [Github issue](https://github.com/rapid7/smb2/issues) or an issue from some other
42
+ `ISSUE` is either a [Github issue](https://github.com/rapid7/ruby_smb/issues) or an issue from some other
18
43
  issue tracking software.
19
44
 
20
45
  ### `SUMMARY`
@@ -49,7 +74,7 @@ Push your branch to your fork on gitub: `git push TYPE/ISSUE/SUMMARY`
49
74
 
50
75
  ### Pull Request
51
76
 
52
- * [Create new Pull Request](https://github.com/rapid7/smb2/compare/)
77
+ * [Create new Pull Request](https://github.com/rapid7/ruby_smb/compare/)
53
78
  * Add a Verification Steps to the description comment
54
79
 
55
80
  ```
data/README.md CHANGED
@@ -12,6 +12,12 @@ The RubySMB library provides client-level and packet-level support for the proto
12
12
 
13
13
  See the Wiki for more information on this project's long-term goals, style guide, and developer tips.
14
14
 
15
+
16
+ ## Versioning
17
+ RubySMB attempts to follow [the Semantic Versioning 2.0.0](https://semver.org/) standard, however due to certain key architectural qualities, some reservations are made regarding what will trigger major and minor version bumps. Upstream consumers utilizing higher-level SMB operations can lock to minor (`~= 3.0`) versions however consumers utilizing raw SMB packet manipulation are recommended to set restrictions for compatibility to allow update resolution for patch versions (`~= 3.0.0`).
18
+
19
+
20
+
15
21
  ## Installation
16
22
 
17
23
  Add this line to your application's Gemfile:
@@ -34,6 +40,8 @@ Or install it yourself as:
34
40
 
35
41
  All packets are implemented in a declarative style with BinData. Nested data structures are used where appropriate to give users an easy method of manipulating individual fields inside of a packet.
36
42
 
43
+ Note that these packets are defined using [BinData](https://github.com/dmendel/bindata) and that their struction is subject to change across minor version bumps. See [CONTRIBUTING.md](https://github.com/rapid7/ruby_smb/blob/master/CONTRIBUTING.md#versioning) for more information.
44
+
37
45
  #### SMB1
38
46
 
39
47
  SMB1 Packets are made up of three basic components:
@@ -0,0 +1,112 @@
1
+ #!/usr/bin/ruby
2
+
3
+ # This example script is used for launching a powershell command as a service on a host.
4
+ # It will attempt to connect to a host and create a new service to launch the command using powershell.exe.
5
+ # Example usage: ruby pwsh_service.rb --username msfadmin --password msfadmin 192.168.172.138 "echo test > C:\\Users\\User\\Desktop\\test.txt"
6
+ # This will try to connect to \\192.168.172.138 with the msfadmin:msfadmin credentials and create a new service to run the powershell command.
7
+
8
+ def random_string(length)
9
+ return (1..length).map { (('a'..'z').to_a + ('A'..'Z').to_a)[rand(26*2)] }.join
10
+ end
11
+
12
+ require 'bundler/setup'
13
+ require 'optparse'
14
+ require 'ruby_smb'
15
+
16
+ args = ARGV.dup
17
+ options = {
18
+ domain: '.',
19
+ username: '',
20
+ password: '',
21
+ command: nil,
22
+ smbv1: true,
23
+ smbv2: true,
24
+ smbv3: true,
25
+ target: nil
26
+ }
27
+ options[:command] = args.pop
28
+ options[:target] = args.pop
29
+ optparser = OptionParser.new do |opts|
30
+ opts.banner = "Usage: #{File.basename(__FILE__)} [options] target command"
31
+ opts.on("--[no-]smbv1", "Enable or disable SMBv1 (default: #{options[:smbv1] ? 'Enabled' : 'Disabled'})") do |smbv1|
32
+ options[:smbv1] = smbv1
33
+ end
34
+ opts.on("--[no-]smbv2", "Enable or disable SMBv2 (default: #{options[:smbv2] ? 'Enabled' : 'Disabled'})") do |smbv2|
35
+ options[:smbv2] = smbv2
36
+ end
37
+ opts.on("--[no-]smbv3", "Enable or disable SMBv3 (default: #{options[:smbv3] ? 'Enabled' : 'Disabled'})") do |smbv3|
38
+ options[:smbv3] = smbv3
39
+ end
40
+ opts.on("--username USERNAME", "The account's username (default: #{options[:username]})") do |username|
41
+ if username.include?('\\')
42
+ options[:domain], options[:username] = username.split('\\', 2)
43
+ else
44
+ options[:username] = username
45
+ end
46
+ end
47
+ opts.on("--password PASSWORD", "The account's password (default: #{options[:password]})") do |password|
48
+ options[:password] = password
49
+ end
50
+ end
51
+ optparser.parse!(args)
52
+
53
+ if options[:target].nil? || options[:command].nil?
54
+ abort(optparser.help)
55
+ end
56
+
57
+ sock = TCPSocket.new options[:target], 445
58
+ dispatcher = RubySMB::Dispatcher::Socket.new(sock, read_timeout: 60)
59
+
60
+ client = RubySMB::Client.new(dispatcher, smb1: options[:smbv1], smb2: options[:smbv2], smb3: options[:smbv3], username: options[:username], password: options[:password], domain: options[:domain])
61
+ protocol = client.negotiate
62
+ status = client.authenticate
63
+
64
+ puts "#{protocol} : #{status}"
65
+
66
+ tree = client.tree_connect("\\\\#{options[:target]}\\IPC$")
67
+ svcctl = tree.open_file(filename: 'svcctl', write: true, read: true)
68
+
69
+ puts('Binding to \\svcctl...')
70
+ svcctl.bind(endpoint: RubySMB::Dcerpc::Svcctl)
71
+ puts('Bound to \\svcctl')
72
+
73
+ puts('Opening Service Control Manager')
74
+ scm_handle = svcctl.open_sc_manager_w(options[:target])
75
+
76
+ service_name = random_string(8)
77
+ display_name = random_string(8)
78
+ binary_path_name = "%COMSPEC% /c start /b /min powershell.exe -nop -win hid -noni -en #{[options[:command].encode("UTF-16LE")].pack("m0")}"
79
+ puts "Full Command: #{binary_path_name}"
80
+ svc_handle = svcctl.create_service_w(scm_handle, service_name, display_name, binary_path_name)
81
+
82
+ puts('Created new service')
83
+
84
+ svcctl.close_service_handle(svc_handle)
85
+
86
+ puts('Opening the service')
87
+
88
+ svc_handle = svcctl.open_service_w(scm_handle, service_name)
89
+
90
+ puts('Starting the service')
91
+
92
+ begin
93
+ svcctl.start_service_w(svc_handle)
94
+ rescue RubySMB::Dcerpc::Error::SvcctlError => e
95
+ if e.message.include?('ERROR_SERVICE_REQUEST_TIMEOUT')
96
+ puts "Service start timed out, OK if running a command or non-service executable..."
97
+ else
98
+ puts "Service start error: #{e}"
99
+ end
100
+ end
101
+
102
+ puts('Deleting the service')
103
+
104
+ svcctl.delete_service(svc_handle)
105
+
106
+ puts('Closing Service Control Manager')
107
+
108
+ svcctl.close_service_handle(scm_handle)
109
+
110
+ puts('Done')
111
+
112
+ client.disconnect!
@@ -251,7 +251,7 @@ module RubySMB
251
251
  raise ArgumentError, 'Must be an array of strings' unless dialect.is_a? String
252
252
  packet.add_dialect(dialect.to_i(16))
253
253
  end
254
- packet.capabilities.encryption = 1
254
+ packet.capabilities.encryption = @session_encrypt_data ? 1 : 0
255
255
 
256
256
  if packet.dialects.include?(0x0311)
257
257
  nc = RubySMB::SMB2::NegotiateContext.new(
@@ -29,10 +29,26 @@ module RubySMB
29
29
  # It indicates that the server implements SMB 2.1 or future dialect revisions
30
30
  # Note that this must be used for SMB3
31
31
  SMB1_DIALECT_SMB2_WILDCARD = 'SMB 2.???'.freeze
32
+
33
+ SMB2_DIALECT_0202 = '0x0202'.freeze
34
+ SMB2_DIALECT_0210 = '0x0210'.freeze
35
+ SMB2_DIALECT_0300 = '0x0300'.freeze
36
+ SMB2_DIALECT_0302 = '0x0302'.freeze
37
+ SMB2_DIALECT_0311 = '0x0311'.freeze
38
+
32
39
  # Dialect values for SMB2
33
- SMB2_DIALECT_DEFAULT = ['0x0202', '0x0210']
40
+ SMB2_DIALECT_DEFAULT = [
41
+ SMB2_DIALECT_0202,
42
+ SMB2_DIALECT_0210,
43
+ ].freeze
44
+
34
45
  # Dialect values for SMB3
35
- SMB3_DIALECT_DEFAULT = ['0x0300', '0x0302', '0x0311']
46
+ SMB3_DIALECT_DEFAULT = [
47
+ SMB2_DIALECT_0300,
48
+ SMB2_DIALECT_0302,
49
+ SMB2_DIALECT_0311
50
+ ].freeze
51
+
36
52
  # The default maximum size of a SMB message that the Client accepts (in bytes)
37
53
  MAX_BUFFER_SIZE = 64512
38
54
  # The default maximum size of a SMB message that the Server accepts (in bytes)
@@ -129,6 +145,11 @@ module RubySMB
129
145
  # @return [Integer]
130
146
  attr_accessor :session_id
131
147
 
148
+ # Whether or not the current session has the guest flag set
149
+ # @!attribute [rw] session_is_guest
150
+ # @return [Boolean]
151
+ attr_accessor :session_is_guest
152
+
132
153
  # Whether or not the Server requires signing
133
154
  # @!attribute [rw] signing_enabled
134
155
  # @return [Boolean]
@@ -48,6 +48,7 @@ module RubySMB
48
48
  end
49
49
  choice 'Svcctl', selection: -> { opnum } do
50
50
  open_sc_manager_w_request Svcctl::OPEN_SC_MANAGER_W
51
+ create_service_w_request Svcctl::CREATE_SERVICE_W
51
52
  open_service_w_request Svcctl::OPEN_SERVICE_W
52
53
  query_service_status_request Svcctl::QUERY_SERVICE_STATUS
53
54
  query_service_config_w_request Svcctl::QUERY_SERVICE_CONFIG_W
@@ -55,6 +56,7 @@ module RubySMB
55
56
  start_service_w_request Svcctl::START_SERVICE_W
56
57
  control_service_request Svcctl::CONTROL_SERVICE
57
58
  close_service_handle_request Svcctl::CLOSE_SERVICE_HANDLE
59
+ delete_service_request Svcctl::DELETE_SERVICE
58
60
  string :default
59
61
  end
60
62
  choice 'Samr', selection: -> { opnum } do
@@ -0,0 +1,35 @@
1
+ module RubySMB
2
+ module Dcerpc
3
+ module Svcctl
4
+
5
+ # [3.1.4.12 RCreateServiceW (Opnum 12)](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-scmr/6a8ca926-9477-4dd4-b766-692fab07227e)
6
+ class CreateServiceWRequest < BinData::Record
7
+ attr_reader :opnum
8
+
9
+ endian :little
10
+
11
+ sc_rpc_handle :h_sc_object
12
+ ndr_conf_var_wide_stringz :lp_service_name
13
+ ndr_wide_stringz_ptr :lp_display_name
14
+ ndr_uint32 :dw_desired_access
15
+ ndr_uint32 :dw_service_type
16
+ ndr_uint32 :dw_start_type
17
+ ndr_uint32 :dw_error_control
18
+ ndr_conf_var_wide_stringz :lp_binary_path_name
19
+ ndr_wide_stringz_ptr :lp_load_order_group
20
+ ndr_uint32_ptr :lp_dw_tag_id
21
+ svcctl_byte_array_ptr :lp_dependencies, type: :ndr_uint8
22
+ ndr_uint32 :dw_depend_size, initial_value: -> { lp_dependencies.size }
23
+ ndr_wide_stringz_ptr :lp_service_start_name
24
+ svcctl_byte_array_ptr :lp_password, type: :ndr_uint8
25
+ ndr_uint32 :dw_pw_size, initial_value: -> { lp_password.size }
26
+
27
+ def initialize_instance
28
+ super
29
+ @opnum = CREATE_SERVICE_W
30
+ end
31
+ end
32
+
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,24 @@
1
+ module RubySMB
2
+ module Dcerpc
3
+ module Svcctl
4
+
5
+ # [3.1.4.12 RCreateServiceW (Opnum 12)](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-scmr/6a8ca926-9477-4dd4-b766-692fab07227e)
6
+ class CreateServiceWResponse < BinData::Record
7
+ attr_reader :opnum
8
+
9
+ endian :little
10
+
11
+ ndr_uint32_ptr :lp_dw_tag_id
12
+ sc_rpc_handle :lp_sc_handle
13
+ ndr_uint32 :error_status
14
+
15
+ def initialize_instance
16
+ super
17
+ @opnum = CREATE_SERVICE_W
18
+ end
19
+
20
+ end
21
+
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,21 @@
1
+ module RubySMB
2
+ module Dcerpc
3
+ module Svcctl
4
+
5
+ # [3.1.4.2 RDeleteService (Opnum 2)](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-scmr/6744cdb8-f162-4be0-bb31-98996b6495be)
6
+ class DeleteServiceRequest < BinData::Record
7
+ attr_reader :opnum
8
+
9
+ endian :little
10
+
11
+ sc_rpc_handle :lp_sc_handle
12
+
13
+ def initialize_instance
14
+ super
15
+ @opnum = DELETE_SERVICE
16
+ end
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ module RubySMB
2
+ module Dcerpc
3
+ module Svcctl
4
+
5
+ # [3.1.4.2 RDeleteService (Opnum 2)](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-scmr/6744cdb8-f162-4be0-bb31-98996b6495be)
6
+ class DeleteServiceResponse < 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 = DELETE_SERVICE
16
+ end
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -9,8 +9,10 @@ module RubySMB
9
9
  # Operation numbers
10
10
  CLOSE_SERVICE_HANDLE = 0x0000
11
11
  CONTROL_SERVICE = 0x0001
12
+ DELETE_SERVICE = 0x0002
12
13
  QUERY_SERVICE_STATUS = 0x0006
13
14
  CHANGE_SERVICE_CONFIG_W = 0x000B
15
+ CREATE_SERVICE_W = 0x000C
14
16
  OPEN_SC_MANAGER_W = 0x000F
15
17
  OPEN_SERVICE_W = 0x0010
16
18
  QUERY_SERVICE_CONFIG_W = 0x0011
@@ -19,6 +21,10 @@ module RubySMB
19
21
 
20
22
  class ScRpcHandle < Ndr::NdrContextHandle; end
21
23
 
24
+ class SvcctlByteArrayPtr < Ndr::NdrConfArray
25
+ default_parameters type: :ndr_uint8
26
+ extend Ndr::PointerClassPlugin
27
+ end
22
28
 
23
29
  #################################
24
30
  # Constants #
@@ -254,10 +260,14 @@ module RubySMB
254
260
  require 'ruby_smb/dcerpc/svcctl/open_service_w_response'
255
261
  require 'ruby_smb/dcerpc/svcctl/query_service_status_request'
256
262
  require 'ruby_smb/dcerpc/svcctl/query_service_status_response'
263
+ require 'ruby_smb/dcerpc/svcctl/delete_service_request'
264
+ require 'ruby_smb/dcerpc/svcctl/delete_service_response'
257
265
  require 'ruby_smb/dcerpc/svcctl/query_service_config_w_request'
258
266
  require 'ruby_smb/dcerpc/svcctl/query_service_config_w_response'
259
267
  require 'ruby_smb/dcerpc/svcctl/change_service_config_w_request'
260
268
  require 'ruby_smb/dcerpc/svcctl/change_service_config_w_response'
269
+ require 'ruby_smb/dcerpc/svcctl/create_service_w_request'
270
+ require 'ruby_smb/dcerpc/svcctl/create_service_w_response'
261
271
  require 'ruby_smb/dcerpc/svcctl/start_service_w_request'
262
272
  require 'ruby_smb/dcerpc/svcctl/start_service_w_response'
263
273
  require 'ruby_smb/dcerpc/svcctl/control_service_request'
@@ -289,10 +299,41 @@ module RubySMB
289
299
  open_sc_manager_w_response.lp_sc_handle
290
300
  end
291
301
 
302
+ # Creates an RPC context handle to a new service record.
303
+ #
304
+ # @param scm_handle [RubySMB::Dcerpc::Svcctl::ScRpcHandle] handle to the SCM database
305
+ # @param service_name [String] the ServiceName of the service record
306
+ # @param display_name [String] the DisplayName of the service record
307
+ # @param binary_path_name [String] the BinaryPathName of the service record
308
+ # @return [RubySMB::Dcerpc::Svcctl::ScRpcHandle] handle to the created service record
309
+ # @raise [RubySMB::Dcerpc::Error::InvalidPacket] if the response is not a CreateServiceWResponse packet
310
+ # @raise [RubySMB::Dcerpc::Error::SvcctlError] if the response error status is not ERROR_SUCCESS
311
+ def create_service_w(scm_handle, service_name, display_name, binary_path_name)
312
+ create_service_w_request = CreateServiceWRequest.new(dw_desired_access: SERVICE_ALL_ACCESS)
313
+ create_service_w_request.dw_service_type = SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS
314
+ create_service_w_request.dw_start_type = SERVICE_DEMAND_START
315
+ create_service_w_request.h_sc_object = scm_handle
316
+ create_service_w_request.lp_service_name = service_name
317
+ create_service_w_request.lp_display_name = display_name
318
+ create_service_w_request.lp_binary_path_name = binary_path_name
319
+ response = dcerpc_request(create_service_w_request)
320
+ begin
321
+ create_service_w_response = CreateServiceWResponse.read(response)
322
+ rescue IOError
323
+ raise RubySMB::Dcerpc::Error::InvalidPacket, 'Error reading CreateServiceWResponse'
324
+ end
325
+ unless create_service_w_response.error_status == WindowsError::Win32::ERROR_SUCCESS
326
+ raise RubySMB::Dcerpc::Error::SvcctlError,
327
+ "Error returned when creating #{service_name} service: "\
328
+ "#{WindowsError::Win32.find_by_retval(create_service_w_response.error_status.value).join(',')}"
329
+ end
330
+ create_service_w_response.lp_sc_handle
331
+ end
332
+
292
333
  # Creates an RPC context handle to an existing service record.
293
334
  #
294
335
  # @param scm_handle [RubySMB::Dcerpc::Svcctl::ScRpcHandle] handle to the SCM database
295
- # @param service_name [Srting] the ServiceName of the service record
336
+ # @param service_name [String] the ServiceName of the service record
296
337
  # @param access [Integer] access right
297
338
  # @return [RubySMB::Dcerpc::Svcctl::ScRpcHandle] handle to the found service record
298
339
  # @raise [RubySMB::Dcerpc::Error::InvalidPacket] if the response is not a OpenServiceWResponse packet
@@ -303,16 +344,16 @@ module RubySMB
303
344
  open_service_w_request.lp_service_name = service_name
304
345
  response = dcerpc_request(open_service_w_request)
305
346
  begin
306
- open_sercice_w_response = OpenServiceWResponse.read(response)
347
+ open_service_w_response = OpenServiceWResponse.read(response)
307
348
  rescue IOError
308
349
  raise RubySMB::Dcerpc::Error::InvalidPacket, 'Error reading OpenServiceWResponse'
309
350
  end
310
- unless open_sercice_w_response.error_status == WindowsError::Win32::ERROR_SUCCESS
351
+ unless open_service_w_response.error_status == WindowsError::Win32::ERROR_SUCCESS
311
352
  raise RubySMB::Dcerpc::Error::SvcctlError,
312
353
  "Error returned when opening #{service_name} service: "\
313
- "#{WindowsError::Win32.find_by_retval(open_sercice_w_response.error_status.value).join(',')}"
354
+ "#{WindowsError::Win32.find_by_retval(open_service_w_response.error_status.value).join(',')}"
314
355
  end
315
- open_sercice_w_response.lp_sc_handle
356
+ open_service_w_response.lp_sc_handle
316
357
  end
317
358
 
318
359
  # Returns the current status of the specified service
@@ -472,6 +513,26 @@ module RubySMB
472
513
  "#{WindowsError::Win32.find_by_retval(csh_response.error_status.value).join(',')}"
473
514
  end
474
515
  end
516
+
517
+ # Deletes the specified service
518
+ #
519
+ # @param scm_handle [RubySMB::Dcerpc::Svcctl::ScRpcHandle] handle to the service record
520
+ # @raise [RubySMB::Dcerpc::Error::InvalidPacket] if the response is not a DeleteServiceResponse packet
521
+ # @raise [RubySMB::Dcerpc::Error::SvcctlError] if the response error status is not ERROR_SUCCESS
522
+ def delete_service(svc_handle)
523
+ ds_request = DeleteServiceRequest.new(lp_sc_handle: svc_handle)
524
+ response = dcerpc_request(ds_request)
525
+ begin
526
+ ds_response = DeleteServiceResponse.read(response)
527
+ rescue IOError
528
+ raise RubySMB::Dcerpc::Error::InvalidPacket, 'Error reading DeleteServiceResponse'
529
+ end
530
+ unless ds_response.error_status == WindowsError::Win32::ERROR_SUCCESS
531
+ raise RubySMB::Dcerpc::Error::SvcctlError,
532
+ "Error returned when deleting the service: "\
533
+ "#{WindowsError::Win32.find_by_retval(ds_response.error_status.value).join(',')}"
534
+ end
535
+ end
475
536
  end
476
537
  end
477
538
  end
@@ -33,7 +33,7 @@ module RubySMB
33
33
  super
34
34
  @opnum = get_parameter(:opnum) if has_parameter?(:opnum)
35
35
  self.server_name = :null
36
- self.sam_desired.maximum = 1 unless [OPEN_HKPD, OPEN_HKPT, OPEN_HKPN].include?(@opnum)
36
+ self.sam_desired.maximum_allowed = 1 unless [OPEN_HKPD, OPEN_HKPT, OPEN_HKPN].include?(@opnum)
37
37
  end
38
38
  end
39
39
 
@@ -33,7 +33,7 @@ module RubySMB
33
33
  bit1 :generic_execute, label: 'Generic Execute'
34
34
  bit1 :generic_all, label: 'Generic All'
35
35
  bit2 :reserved4, label: 'Reserved Space'
36
- bit1 :maximum, label: 'Maximum Allowed'
36
+ bit1 :maximum_allowed, label: 'Maximum Allowed'
37
37
  bit1 :system_security, label: 'System Security'
38
38
  end
39
39
 
@@ -274,7 +274,7 @@ module RubySMB
274
274
  lp_sub_key: sub_key,
275
275
  lp_class: opts[:lp_class] || :null,
276
276
  dw_options: opts[:dw_options] || RubySMB::Dcerpc::Winreg::CreateKeyRequest::REG_KEY_TYPE_VOLATILE,
277
- sam_desired: opts[:sam_desired] || RubySMB::Dcerpc::Winreg::Regsam.new(maximum: 1),
277
+ sam_desired: opts[:sam_desired] || RubySMB::Dcerpc::Winreg::Regsam.new(maximum_allowed: 1),
278
278
  lp_security_attributes: opts[:lp_security_attributes] || RubySMB::Dcerpc::RpcSecurityAttributes.new,
279
279
  lpdw_disposition: opts[:lpdw_disposition] || RubySMB::Dcerpc::Winreg::CreateKeyRequest::REG_CREATED_NEW_KEY,
280
280
  }
@@ -13,6 +13,7 @@ module RubySMB
13
13
  @user_id = user_id
14
14
  @state = state
15
15
  @signing_required = false
16
+ @metadata = {}
16
17
  # tree id => provider processor instance
17
18
  @tree_connect_table = {}
18
19
  @creation_time = Time.now
@@ -62,6 +63,11 @@ module RubySMB
62
63
  # @return [Hash]
63
64
  attr_accessor :tree_connect_table
64
65
 
66
+ # Untyped hash for storing additional arbitrary metadata about the current session
67
+ # @!attribute [rw] metadaa
68
+ # @return [Hash]
69
+ attr_accessor :metadata
70
+
65
71
  # The time at which this session was created.
66
72
  # @!attribute [r] creation_time
67
73
  # @return [Time]
@@ -30,7 +30,7 @@ module RubySMB
30
30
  bit1 :generic_execute, label: 'Generic Execute'
31
31
  bit1 :generic_all, label: 'Generic All'
32
32
  bit2 :reserved3
33
- bit1 :maximum, label: 'Maximum Allowed'
33
+ bit1 :maximum_allowed, label: 'Maximum Allowed'
34
34
  bit1 :system_security, label: 'System Security'
35
35
  end
36
36
  end
@@ -30,7 +30,7 @@ module RubySMB
30
30
  bit1 :generic_execute, label: 'Generic Execute'
31
31
  bit1 :generic_all, label: 'Generic All'
32
32
  bit2 :reserved3
33
- bit1 :maximum, label: 'Maximum Allowed'
33
+ bit1 :maximum_allowed, label: 'Maximum Allowed'
34
34
  bit1 :system_security, label: 'System Security'
35
35
  end
36
36
  end
@@ -30,7 +30,7 @@ module RubySMB
30
30
  bit1 :generic_execute, label: 'Generic Execute'
31
31
  bit1 :generic_all, label: 'Generic All'
32
32
  bit2 :reserved3
33
- bit1 :maximum, label: 'Maximum Allowed'
33
+ bit1 :maximum_allowed, label: 'Maximum Allowed'
34
34
  bit1 :system_security, label: 'System Security'
35
35
  end
36
36
  end
@@ -30,7 +30,7 @@ module RubySMB
30
30
  bit1 :generic_execute, label: 'Generic Execute'
31
31
  bit1 :generic_all, label: 'Generic All'
32
32
  bit2 :reserved3
33
- bit1 :maximum, label: 'Maximum Allowed'
33
+ bit1 :maximum_allowed, label: 'Maximum Allowed'
34
34
  bit1 :system_security, label: 'System Security'
35
35
  end
36
36
  end
@@ -18,6 +18,17 @@ module RubySMB
18
18
  uint64 :previous_session_id, label: 'Previous Session ID'
19
19
  string :buffer, label: 'Security Buffer', length: -> { security_buffer_length }
20
20
 
21
+ # Takes the specified security buffer string and inserts it into the {RubySMB::SMB2::Packet::SessionSetupRequest#buffer}
22
+ # as well as updating the {RubySMB::SMB2::Packet::SessionSetupRequest#security_buffer_length}
23
+ # This method DOES NOT wrap the security buffer in any way.
24
+ #
25
+ # @param buffer [String] the security buffer
26
+ # @return [void]
27
+ def set_security_buffer(buffer)
28
+ self.security_buffer_length = buffer.length
29
+ self.buffer = buffer
30
+ end
31
+
21
32
  # Takes a serialized NTLM Type 1 message and wraps it in the GSS ASN1 encoding
22
33
  # and inserts it into the {RubySMB::SMB2::Packet::SessionSetupRequest#buffer}
23
34
  # as well as updating the {RubySMB::SMB2::Packet::SessionSetupRequest#security_buffer_length}
@@ -1,3 +1,3 @@
1
1
  module RubySMB
2
- VERSION = '3.0.3'.freeze
2
+ VERSION = '3.0.6'.freeze
3
3
  end
data/ruby_smb.gemspec CHANGED
@@ -34,7 +34,7 @@ Gem::Specification.new do |spec|
34
34
  spec.add_development_dependency 'yard'
35
35
 
36
36
  spec.add_runtime_dependency 'rubyntlm'
37
- spec.add_runtime_dependency 'windows_error', '>= 0.1.3'
37
+ spec.add_runtime_dependency 'windows_error', '>= 0.1.4'
38
38
  spec.add_runtime_dependency 'bindata'
39
39
  spec.add_runtime_dependency 'openssl-ccm'
40
40
  spec.add_runtime_dependency 'openssl-cmac'
@@ -557,6 +557,16 @@ RSpec.describe RubySMB::Client do
557
557
  end
558
558
  end
559
559
 
560
+ describe '#wipe_state!' do
561
+ context 'with SMB1' do
562
+ it { expect { smb1_client.wipe_state! }.to_not raise_error }
563
+ end
564
+
565
+ context 'with SMB2' do
566
+ it { expect { smb2_client.wipe_state! }.to_not raise_error }
567
+ end
568
+ end
569
+
560
570
  describe '#logoff!' do
561
571
  context 'with SMB1' do
562
572
  let(:raw_response) { double('Raw response') }
@@ -0,0 +1,143 @@
1
+ RSpec.describe RubySMB::Dcerpc::Svcctl::CreateServiceWRequest do
2
+ subject(:packet) { described_class.new }
3
+
4
+ it { is_expected.to respond_to :h_sc_object }
5
+ it { is_expected.to respond_to :lp_service_name }
6
+ it { is_expected.to respond_to :lp_display_name }
7
+ it { is_expected.to respond_to :dw_desired_access }
8
+ it { is_expected.to respond_to :dw_service_type }
9
+ it { is_expected.to respond_to :dw_start_type }
10
+ it { is_expected.to respond_to :dw_error_control }
11
+ it { is_expected.to respond_to :lp_binary_path_name }
12
+ it { is_expected.to respond_to :lp_load_order_group }
13
+ it { is_expected.to respond_to :lp_dw_tag_id }
14
+ it { is_expected.to respond_to :lp_dependencies }
15
+ it { is_expected.to respond_to :dw_depend_size }
16
+ it { is_expected.to respond_to :lp_service_start_name }
17
+ it { is_expected.to respond_to :lp_password }
18
+ it { is_expected.to respond_to :dw_pw_size }
19
+
20
+ it 'is little endian' do
21
+ expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
22
+ end
23
+
24
+
25
+ describe '#h_sc_object' do
26
+ it 'is a ScRpcHandle structure' do
27
+ expect(packet.h_sc_object).to be_a RubySMB::Dcerpc::Svcctl::ScRpcHandle
28
+ end
29
+ end
30
+
31
+ describe '#lp_service_name' do
32
+ it 'is a NdrConfVarWideStringz structure' do
33
+ expect(packet.lp_service_name).to be_a RubySMB::Dcerpc::Ndr::NdrConfVarWideStringz
34
+ end
35
+ end
36
+
37
+ describe '#lp_display_name' do
38
+ it 'is a NdrWideStringzPtr structure' do
39
+ expect(packet.lp_display_name).to be_a RubySMB::Dcerpc::Ndr::NdrWideStringzPtr
40
+ end
41
+ end
42
+
43
+ describe '#dw_desired_access' do
44
+ it 'is a NdrUint32' do
45
+ expect(packet.dw_desired_access).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
46
+ end
47
+ end
48
+
49
+ describe '#dw_service_type' do
50
+ it 'is a NdrUint32' do
51
+ expect(packet.dw_service_type).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
52
+ end
53
+ end
54
+
55
+ describe '#dw_start_type' do
56
+ it 'is a NdrUint32' do
57
+ expect(packet.dw_start_type).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
58
+ end
59
+ end
60
+
61
+ describe '#dw_error_control' do
62
+ it 'is a NdrUint32' do
63
+ expect(packet.dw_error_control).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
64
+ end
65
+ end
66
+
67
+ describe '#lp_binary_path_name' do
68
+ it 'is a NdrConfVarWideStringz structure' do
69
+ expect(packet.lp_binary_path_name).to be_a RubySMB::Dcerpc::Ndr::NdrConfVarWideStringz
70
+ end
71
+ end
72
+
73
+ describe '#lp_load_order_group' do
74
+ it 'is a NdrWideStringzPtr structure' do
75
+ expect(packet.lp_load_order_group).to be_a RubySMB::Dcerpc::Ndr::NdrWideStringzPtr
76
+ end
77
+ end
78
+
79
+ describe '#lp_dw_tag_id' do
80
+ it 'is a NdrUint32Ptr' do
81
+ expect(packet.lp_dw_tag_id).to be_a RubySMB::Dcerpc::Ndr::NdrUint32Ptr
82
+ end
83
+ end
84
+
85
+ describe '#lp_dependencies' do
86
+ it 'is a SvcctlByteArrayPtr structure' do
87
+ expect(packet.lp_dependencies).to be_a RubySMB::Dcerpc::Svcctl::SvcctlByteArrayPtr
88
+ end
89
+ end
90
+
91
+ describe '#dw_depend_size' do
92
+ it 'is a NdrUint32' do
93
+ expect(packet.dw_depend_size).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
94
+ end
95
+ end
96
+
97
+ describe '#lp_service_start_name' do
98
+ it 'is a NdrWideStringzPtr structure' do
99
+ expect(packet.lp_service_start_name).to be_a RubySMB::Dcerpc::Ndr::NdrWideStringzPtr
100
+ end
101
+ end
102
+
103
+ describe '#lp_password' do
104
+ it 'is a SvcctlByteArrayPtr structure' do
105
+ expect(packet.lp_password).to be_a RubySMB::Dcerpc::Svcctl::SvcctlByteArrayPtr
106
+ end
107
+ end
108
+
109
+ describe '#dw_pw_size' do
110
+ it 'is a NdrUint32' do
111
+ expect(packet.dw_pw_size).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
112
+ end
113
+ end
114
+
115
+ it 'should keep #dw_desired_access 4-byte aligned' do
116
+ 5.times do |i1|
117
+ 5.times do |i2|
118
+ packet.lp_service_name = "A" * i1
119
+ packet.lp_display_name = "B" * i2
120
+ expect(packet.dw_desired_access.abs_offset % 4).to eq 0
121
+ end
122
+ end
123
+ end
124
+
125
+ describe '#initialize_instance' do
126
+ it 'sets #opnum to CREATE_SERVICE_W constant' do
127
+ expect(packet.opnum).to eq(RubySMB::Dcerpc::Svcctl::CREATE_SERVICE_W)
128
+ end
129
+ end
130
+
131
+ it 'reads its own binary representation and outputs the same packet' do
132
+ packet = described_class.new(
133
+ h_sc_object: {context_handle_attributes: 0, context_handle_uuid: '367abb81-9844-35f1-ad32-98f038001003'},
134
+ lp_service_name: 'test',
135
+ lp_display_name: 'Test',
136
+ dw_desired_access: 3,
137
+ lp_binary_path_name: 'test',
138
+ lp_password: 'test'.bytes
139
+ )
140
+ binary = packet.to_binary_s
141
+ expect(described_class.read(binary)).to eq(packet)
142
+ end
143
+ end
@@ -0,0 +1,45 @@
1
+ RSpec.describe RubySMB::Dcerpc::Svcctl::CreateServiceWResponse do
2
+ subject(:packet) { described_class.new }
3
+
4
+ it { is_expected.to respond_to :lp_dw_tag_id }
5
+ it { is_expected.to respond_to :lp_sc_handle }
6
+ it { is_expected.to respond_to :error_status }
7
+
8
+ it 'is little endian' do
9
+ expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
10
+ end
11
+
12
+ describe '#lp_dw_tag_id' do
13
+ it 'is a NdrUint32Ptr' do
14
+ expect(packet.lp_dw_tag_id).to be_a RubySMB::Dcerpc::Ndr::NdrUint32Ptr
15
+ end
16
+ end
17
+
18
+ describe '#lp_sc_handle' do
19
+ it 'is a ScRpcHandle structure' do
20
+ expect(packet.lp_sc_handle).to be_a RubySMB::Dcerpc::Svcctl::ScRpcHandle
21
+ end
22
+ end
23
+
24
+ describe '#error_status' do
25
+ it 'is a NdrUint32' do
26
+ expect(packet.error_status).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
27
+ end
28
+ end
29
+
30
+ describe '#initialize_instance' do
31
+ it 'sets #opnum to CREATE_SERVICE_W constant' do
32
+ expect(packet.opnum).to eq(RubySMB::Dcerpc::Svcctl::CREATE_SERVICE_W)
33
+ end
34
+ end
35
+
36
+ it 'reads its own binary representation and outputs the same packet' do
37
+ packet = described_class.new(
38
+ lp_dw_tag_id: 3,
39
+ lp_sc_handle: {context_handle_attributes: 0, context_handle_uuid: '367abb81-9844-35f1-ad32-98f038001003'},
40
+ error_status: 3
41
+ )
42
+ binary = packet.to_binary_s
43
+ expect(described_class.read(binary)).to eq(packet)
44
+ end
45
+ end
@@ -0,0 +1,29 @@
1
+ RSpec.describe RubySMB::Dcerpc::Svcctl::DeleteServiceRequest do
2
+ subject(:packet) { described_class.new }
3
+
4
+ it { is_expected.to respond_to :lp_sc_handle }
5
+
6
+ it 'is little endian' do
7
+ expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
8
+ end
9
+
10
+ describe '#lp_sc_handle' do
11
+ it 'is a ScRpcHandle structure' do
12
+ expect(packet.lp_sc_handle).to be_a RubySMB::Dcerpc::Svcctl::ScRpcHandle
13
+ end
14
+ end
15
+
16
+ describe '#initialize_instance' do
17
+ it 'sets #opnum to DELETE_SERVICE constant' do
18
+ expect(packet.opnum).to eq(RubySMB::Dcerpc::Svcctl::DELETE_SERVICE)
19
+ end
20
+ end
21
+
22
+ it 'reads its own binary representation and outputs the same packet' do
23
+ packet = described_class.new(
24
+ lp_sc_handle: {context_handle_attributes: 0, context_handle_uuid: '367abb81-9844-35f1-ad32-98f038001003'}
25
+ )
26
+ binary = packet.to_binary_s
27
+ expect(described_class.read(binary)).to eq(packet)
28
+ end
29
+ end
@@ -0,0 +1,29 @@
1
+ RSpec.describe RubySMB::Dcerpc::Svcctl::DeleteServiceResponse do
2
+ subject(:packet) { described_class.new }
3
+
4
+ it { is_expected.to respond_to :error_status }
5
+
6
+ it 'is little endian' do
7
+ expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
8
+ end
9
+
10
+ describe '#error_status' do
11
+ it 'is a NdrUint32' do
12
+ expect(packet.error_status).to be_a RubySMB::Dcerpc::Ndr::NdrUint32
13
+ end
14
+ end
15
+
16
+ describe '#initialize_instance' do
17
+ it 'sets #opnum to DELETE_SERVICE constant' do
18
+ expect(packet.opnum).to eq(RubySMB::Dcerpc::Svcctl::DELETE_SERVICE)
19
+ end
20
+ end
21
+
22
+ it 'reads its own binary representation and outputs the same packet' do
23
+ packet = described_class.new(
24
+ error_status: 3
25
+ )
26
+ binary = packet.to_binary_s
27
+ expect(described_class.read(binary)).to eq(packet)
28
+ end
29
+ end
@@ -57,30 +57,30 @@ RSpec.describe RubySMB::Dcerpc::Winreg::OpenRootKeyRequest do
57
57
  end
58
58
 
59
59
  context 'when #opnum is not OPEN_HKPD, OPEN_HKPT or OPEN_HKPN' do
60
- it 'sets the #sam_desired.maximum flag' do
60
+ it 'sets the #sam_desired.maximum_allowed flag' do
61
61
  packet = described_class.new(opnum: RubySMB::Dcerpc::Winreg::OPEN_HKCR)
62
- expect(packet.sam_desired.maximum).to eq(1)
62
+ expect(packet.sam_desired.maximum_allowed).to eq(1)
63
63
  end
64
64
  end
65
65
 
66
66
  context 'when #opnum is OPEN_HKPD' do
67
- it 'does not set the #sam_desired.maximum flag' do
67
+ it 'does not set the #sam_desired.maximum_allowed flag' do
68
68
  packet = described_class.new(opnum: RubySMB::Dcerpc::Winreg::OPEN_HKPD)
69
- expect(packet.sam_desired.maximum).to eq(0)
69
+ expect(packet.sam_desired.maximum_allowed).to eq(0)
70
70
  end
71
71
  end
72
72
 
73
73
  context 'when #opnum is OPEN_HKPT' do
74
- it 'does not set the #sam_desired.maximum flag' do
74
+ it 'does not set the #sam_desired.maximum_allowed flag' do
75
75
  packet = described_class.new(opnum: RubySMB::Dcerpc::Winreg::OPEN_HKPT)
76
- expect(packet.sam_desired.maximum).to eq(0)
76
+ expect(packet.sam_desired.maximum_allowed).to eq(0)
77
77
  end
78
78
  end
79
79
 
80
80
  context 'when #opnum is OPEN_HKPN' do
81
- it 'does not set the #sam_desired.maximum flag' do
81
+ it 'does not set the #sam_desired.maximum_allowed flag' do
82
82
  packet = described_class.new(opnum: RubySMB::Dcerpc::Winreg::OPEN_HKPN)
83
- expect(packet.sam_desired.maximum).to eq(0)
83
+ expect(packet.sam_desired.maximum_allowed).to eq(0)
84
84
  end
85
85
  end
86
86
  end
@@ -22,7 +22,7 @@ RSpec.describe RubySMB::Dcerpc::Winreg::Regsam do
22
22
  it { is_expected.to respond_to :generic_execute }
23
23
  it { is_expected.to respond_to :generic_all }
24
24
  it { is_expected.to respond_to :reserved4 }
25
- it { is_expected.to respond_to :maximum }
25
+ it { is_expected.to respond_to :maximum_allowed }
26
26
  it { is_expected.to respond_to :system_security }
27
27
 
28
28
 
@@ -755,7 +755,7 @@ RSpec.describe RubySMB::Dcerpc::Winreg do
755
755
  lp_sub_key: sub_key,
756
756
  lp_class: :null,
757
757
  dw_options: RubySMB::Dcerpc::Winreg::CreateKeyRequest::REG_KEY_TYPE_VOLATILE,
758
- sam_desired: RubySMB::Dcerpc::Winreg::Regsam.new(maximum: 1),
758
+ sam_desired: RubySMB::Dcerpc::Winreg::Regsam.new(maximum_allowed: 1),
759
759
  lp_security_attributes: RubySMB::Dcerpc::RpcSecurityAttributes.new,
760
760
  lpdw_disposition: RubySMB::Dcerpc::Winreg::CreateKeyRequest::REG_CREATED_NEW_KEY
761
761
  }
@@ -19,7 +19,7 @@ RSpec.describe RubySMB::SMB1::BitField::DirectoryAccessMask do
19
19
  it { is_expected.to respond_to :generic_write }
20
20
  it { is_expected.to respond_to :generic_execute }
21
21
  it { is_expected.to respond_to :generic_all }
22
- it { is_expected.to respond_to :maximum }
22
+ it { is_expected.to respond_to :maximum_allowed }
23
23
  it { is_expected.to respond_to :system_security }
24
24
 
25
25
  it 'is little endian' do
@@ -146,12 +146,12 @@ RSpec.describe RubySMB::SMB1::BitField::DirectoryAccessMask do
146
146
  it_behaves_like 'bit field with one flag set', :system_security, 'V', 0x01000000
147
147
  end
148
148
 
149
- describe '#maximum' do
149
+ describe '#maximum_allowed' do
150
150
  it 'should be a 1-bit field per the SMB spec' do
151
- expect(flags.maximum).to be_a BinData::Bit1
151
+ expect(flags.maximum_allowed).to be_a BinData::Bit1
152
152
  end
153
153
 
154
- it_behaves_like 'bit field with one flag set', :maximum, 'V', 0x02000000
154
+ it_behaves_like 'bit field with one flag set', :maximum_allowed, 'V', 0x02000000
155
155
  end
156
156
 
157
157
  describe '#generic_all' do
@@ -19,7 +19,7 @@ RSpec.describe RubySMB::SMB1::BitField::FileAccessMask do
19
19
  it { is_expected.to respond_to :generic_write }
20
20
  it { is_expected.to respond_to :generic_execute }
21
21
  it { is_expected.to respond_to :generic_all }
22
- it { is_expected.to respond_to :maximum }
22
+ it { is_expected.to respond_to :maximum_allowed }
23
23
  it { is_expected.to respond_to :system_security }
24
24
 
25
25
  it 'is little endian' do
@@ -146,12 +146,12 @@ RSpec.describe RubySMB::SMB1::BitField::FileAccessMask do
146
146
  it_behaves_like 'bit field with one flag set', :system_security, 'V', 0x01000000
147
147
  end
148
148
 
149
- describe '#maximum' do
149
+ describe '#maximum_allowed' do
150
150
  it 'should be a 1-bit field per the SMB spec' do
151
- expect(flags.maximum).to be_a BinData::Bit1
151
+ expect(flags.maximum_allowed).to be_a BinData::Bit1
152
152
  end
153
153
 
154
- it_behaves_like 'bit field with one flag set', :maximum, 'V', 0x02000000
154
+ it_behaves_like 'bit field with one flag set', :maximum_allowed, 'V', 0x02000000
155
155
  end
156
156
 
157
157
  describe '#generic_all' do
@@ -118,6 +118,11 @@ RSpec.describe RubySMB::SMB1::Tree do
118
118
  end
119
119
  tree.open_file(filename: unicode_filename.chop)
120
120
  end
121
+
122
+ it 'removes the leading \\ from the filename if needed' do
123
+ expect(tree).to receive(:_open).with(filename: filename)
124
+ tree.open_file(filename: '\\' + filename)
125
+ end
121
126
  end
122
127
 
123
128
  describe 'flags' do
@@ -19,7 +19,7 @@ RSpec.describe RubySMB::SMB2::BitField::DirectoryAccessMask do
19
19
  it { is_expected.to respond_to :generic_write }
20
20
  it { is_expected.to respond_to :generic_execute }
21
21
  it { is_expected.to respond_to :generic_all }
22
- it { is_expected.to respond_to :maximum }
22
+ it { is_expected.to respond_to :maximum_allowed }
23
23
  it { is_expected.to respond_to :system_security }
24
24
 
25
25
  it 'is little endian' do
@@ -146,12 +146,12 @@ RSpec.describe RubySMB::SMB2::BitField::DirectoryAccessMask do
146
146
  it_behaves_like 'bit field with one flag set', :system_security, 'V', 0x01000000
147
147
  end
148
148
 
149
- describe '#maximum' do
149
+ describe '#maximum_allowed' do
150
150
  it 'should be a 1-bit field per the SMB spec' do
151
- expect(flags.maximum).to be_a BinData::Bit1
151
+ expect(flags.maximum_allowed).to be_a BinData::Bit1
152
152
  end
153
153
 
154
- it_behaves_like 'bit field with one flag set', :maximum, 'V', 0x02000000
154
+ it_behaves_like 'bit field with one flag set', :maximum_allowed, 'V', 0x02000000
155
155
  end
156
156
 
157
157
  describe '#generic_all' do
@@ -19,7 +19,7 @@ RSpec.describe RubySMB::SMB2::BitField::FileAccessMask do
19
19
  it { is_expected.to respond_to :generic_write }
20
20
  it { is_expected.to respond_to :generic_execute }
21
21
  it { is_expected.to respond_to :generic_all }
22
- it { is_expected.to respond_to :maximum }
22
+ it { is_expected.to respond_to :maximum_allowed }
23
23
  it { is_expected.to respond_to :system_security }
24
24
 
25
25
  it 'is little endian' do
@@ -146,12 +146,12 @@ RSpec.describe RubySMB::SMB2::BitField::FileAccessMask do
146
146
  it_behaves_like 'bit field with one flag set', :system_security, 'V', 0x01000000
147
147
  end
148
148
 
149
- describe '#maximum' do
149
+ describe '#maximum_allowed' do
150
150
  it 'should be a 1-bit field per the SMB spec' do
151
- expect(flags.maximum).to be_a BinData::Bit1
151
+ expect(flags.maximum_allowed).to be_a BinData::Bit1
152
152
  end
153
153
 
154
- it_behaves_like 'bit field with one flag set', :maximum, 'V', 0x02000000
154
+ it_behaves_like 'bit field with one flag set', :maximum_allowed, 'V', 0x02000000
155
155
  end
156
156
 
157
157
  describe '#generic_all' do
@@ -348,6 +348,11 @@ RSpec.describe RubySMB::SMB2::Tree do
348
348
  end
349
349
  tree.open_file(filename: filename)
350
350
  end
351
+
352
+ it 'removes the leading \\ from the filename if needed' do
353
+ expect(tree).to receive(:_open).with(filename: filename)
354
+ tree.open_file(filename: "\\".encode('UTF-16LE') + filename)
355
+ end
351
356
  end
352
357
 
353
358
  describe 'attributes' do
@@ -544,7 +549,7 @@ RSpec.describe RubySMB::SMB2::Tree do
544
549
  tree.open_pipe(**opts)
545
550
  end
546
551
 
547
- it 'remove the leading \\ from the filename if needed' do
552
+ it 'removes the leading \\ from the filename if needed' do
548
553
  expect(tree).to receive(:_open).with(filename: 'test', write: true)
549
554
  tree.open_pipe(**opts)
550
555
  end
data/spec/spec_helper.rb CHANGED
@@ -1,8 +1,7 @@
1
1
  require 'simplecov'
2
2
 
3
- SimpleCov.start do
4
- add_filter '/spec/'
5
- end
3
+ SimpleCov.start unless SimpleCov.running
4
+ SimpleCov.add_filter '/spec/'
6
5
 
7
6
  require 'coveralls'
8
7
  require 'ruby_smb'
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby_smb
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.3
4
+ version: 3.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Metasploit Hackers
@@ -97,7 +97,7 @@ cert_chain:
97
97
  EknWpNgVhohbot1lfVAMmIhdtOVaRVcQQixWPwprDj/ydB8ryDMDosIMcw+fkoXU
98
98
  9GJsSaSRRYQ9UUkVL27b64okU8D48m8=
99
99
  -----END CERTIFICATE-----
100
- date: 2022-02-11 00:00:00.000000000 Z
100
+ date: 2022-04-01 00:00:00.000000000 Z
101
101
  dependencies:
102
102
  - !ruby/object:Gem::Dependency
103
103
  name: redcarpet
@@ -189,14 +189,14 @@ dependencies:
189
189
  requirements:
190
190
  - - ">="
191
191
  - !ruby/object:Gem::Version
192
- version: 0.1.3
192
+ version: 0.1.4
193
193
  type: :runtime
194
194
  prerelease: false
195
195
  version_requirements: !ruby/object:Gem::Requirement
196
196
  requirements:
197
197
  - - ">="
198
198
  - !ruby/object:Gem::Version
199
- version: 0.1.3
199
+ version: 0.1.4
200
200
  - !ruby/object:Gem::Dependency
201
201
  name: bindata
202
202
  requirement: !ruby/object:Gem::Requirement
@@ -272,6 +272,7 @@ files:
272
272
  - examples/negotiate_with_netbios_service.rb
273
273
  - examples/net_share_enum_all.rb
274
274
  - examples/pipes.rb
275
+ - examples/pwsh_service.rb
275
276
  - examples/query_service_status.rb
276
277
  - examples/read_file.rb
277
278
  - examples/read_file_encryption.rb
@@ -371,6 +372,10 @@ files:
371
372
  - lib/ruby_smb/dcerpc/svcctl/close_service_handle_response.rb
372
373
  - lib/ruby_smb/dcerpc/svcctl/control_service_request.rb
373
374
  - lib/ruby_smb/dcerpc/svcctl/control_service_response.rb
375
+ - lib/ruby_smb/dcerpc/svcctl/create_service_w_request.rb
376
+ - lib/ruby_smb/dcerpc/svcctl/create_service_w_response.rb
377
+ - lib/ruby_smb/dcerpc/svcctl/delete_service_request.rb
378
+ - lib/ruby_smb/dcerpc/svcctl/delete_service_response.rb
374
379
  - lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_request.rb
375
380
  - lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_response.rb
376
381
  - lib/ruby_smb/dcerpc/svcctl/open_service_w_request.rb
@@ -670,6 +675,10 @@ files:
670
675
  - spec/lib/ruby_smb/dcerpc/svcctl/close_service_handle_response_spec.rb
671
676
  - spec/lib/ruby_smb/dcerpc/svcctl/control_service_request_spec.rb
672
677
  - spec/lib/ruby_smb/dcerpc/svcctl/control_service_response_spec.rb
678
+ - spec/lib/ruby_smb/dcerpc/svcctl/create_service_w_request_spec.rb
679
+ - spec/lib/ruby_smb/dcerpc/svcctl/create_service_w_response_spec.rb
680
+ - spec/lib/ruby_smb/dcerpc/svcctl/delete_service_request_spec.rb
681
+ - spec/lib/ruby_smb/dcerpc/svcctl/delete_service_response_spec.rb
673
682
  - spec/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_request_spec.rb
674
683
  - spec/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_response_spec.rb
675
684
  - spec/lib/ruby_smb/dcerpc/svcctl/open_service_w_request_spec.rb
@@ -950,6 +959,10 @@ test_files:
950
959
  - spec/lib/ruby_smb/dcerpc/svcctl/close_service_handle_response_spec.rb
951
960
  - spec/lib/ruby_smb/dcerpc/svcctl/control_service_request_spec.rb
952
961
  - spec/lib/ruby_smb/dcerpc/svcctl/control_service_response_spec.rb
962
+ - spec/lib/ruby_smb/dcerpc/svcctl/create_service_w_request_spec.rb
963
+ - spec/lib/ruby_smb/dcerpc/svcctl/create_service_w_response_spec.rb
964
+ - spec/lib/ruby_smb/dcerpc/svcctl/delete_service_request_spec.rb
965
+ - spec/lib/ruby_smb/dcerpc/svcctl/delete_service_response_spec.rb
953
966
  - spec/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_request_spec.rb
954
967
  - spec/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_response_spec.rb
955
968
  - spec/lib/ruby_smb/dcerpc/svcctl/open_service_w_request_spec.rb
metadata.gz.sig CHANGED
@@ -1 +1,2 @@
1
- ��d����3��xߦ�� (��X��q�"2��=�|;3�AQn��� e8���u�8��s��4���-`����=�w^��"+$R�X`J�Z8J���#K�>M^+f����Jہ�X�3~�a��άo+ �2������ ��|�0�nr�%��Op�K,�}y��yn:TRBP�šBx=aN�&�h)M �߫��Y!)ԛ}au:#{�P��`��O5b�?lJo%7�\�IM�F.�^�_���9 0+����x�
1
+ �������;���'��LY�^w% �!���"*�������
2
+ �J��u�l�lź�$�_��7B`pdɰ�4��ӓ�/Ë��I���.��o��#S�v�f�o�=I�w�8ڳ�Vv�]�˃��u��2��~�x��� �jj�`���l?'B����Ip��E�?�^����GW�����Yq�^'Ӷ���y{P��y����K&K&��8�<��Q�^��p�kS��F1�󯧾G�t"�瓺evoc.����