ruby_smb 3.3.6 → 3.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - checksums.yaml.gz.sig +0 -0
 - data/examples/registry_key_security_descriptor.rb +109 -0
 - data/lib/ruby_smb/client/winreg.rb +12 -0
 - data/lib/ruby_smb/dcerpc/ndr.rb +10 -4
 - data/lib/ruby_smb/dcerpc/request.rb +18 -16
 - data/lib/ruby_smb/dcerpc/rrp_rpc_unicode_string.rb +1 -1
 - data/lib/ruby_smb/dcerpc/winreg/get_key_security_request.rb +26 -0
 - data/lib/ruby_smb/dcerpc/winreg/get_key_security_response.rb +26 -0
 - data/lib/ruby_smb/dcerpc/winreg/query_value_response.rb +2 -0
 - data/lib/ruby_smb/dcerpc/winreg/set_key_security_request.rb +26 -0
 - data/lib/ruby_smb/dcerpc/winreg/set_key_security_response.rb +25 -0
 - data/lib/ruby_smb/dcerpc/winreg.rb +121 -9
 - data/lib/ruby_smb/field/security_descriptor.rb +17 -0
 - data/lib/ruby_smb/version.rb +1 -1
 - data/spec/lib/ruby_smb/dcerpc/ndr_spec.rb +80 -0
 - data/spec/lib/ruby_smb/dcerpc/winreg_spec.rb +267 -18
 - data.tar.gz.sig +0 -0
 - metadata +8 -3
 - metadata.gz.sig +0 -0
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 228afeef84601354373c132ceaa48341ed9f5f4bbab4e625c37d2f2d71864146
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 71512d0529ba352d0cc0ee7c27a27e03116d50f31801beed3fd04cb19e73f4ff
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 3c7dede328c8d637b9088da518649deba6d758a1093e3591bb0cd9e2f4c458a5c5a82a37640aa14523586aa6e83b61d59d4fab21d3fa33739c47d687367cede3
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 6c72f0673379264f71a55935dec05f13f195614c9cd8d6f44935687ab028545e233496ad04f4157a07d1f5f74092fac8dd43f69713d2ac1aeeb7006a12c47e21
         
     | 
    
        checksums.yaml.gz.sig
    CHANGED
    
    | 
         Binary file 
     | 
| 
         @@ -0,0 +1,109 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #!/usr/bin/ruby
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            # This example script is used for testing the Winreg registry key security descriptor functionalities.
         
     | 
| 
      
 4 
     | 
    
         
            +
            # It will attempt to connect to a host and reads (or writes) the security descriptor of a specified registry key.
         
     | 
| 
      
 5 
     | 
    
         
            +
            #
         
     | 
| 
      
 6 
     | 
    
         
            +
            # Example usage:
         
     | 
| 
      
 7 
     | 
    
         
            +
            # - read:
         
     | 
| 
      
 8 
     | 
    
         
            +
            # ruby examples/read_registry_key_security.rb --username msfadmin --password msfadmin -i 7 -o r 192.168.172.138 'HKLM\SECURITY\Policy\PolEKList'
         
     | 
| 
      
 9 
     | 
    
         
            +
            # This will try to connect to \\192.168.172.138 with the msfadmin:msfadmin
         
     | 
| 
      
 10 
     | 
    
         
            +
            # credentialas and read the security descriptor of the
         
     | 
| 
      
 11 
     | 
    
         
            +
            # `HKLM\SECURITY\Policy\PolEKList` registry key with the security information 7
         
     | 
| 
      
 12 
     | 
    
         
            +
            # (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
         
     | 
| 
      
 13 
     | 
    
         
            +
            # DACL_SECURITY_INFORMATION).
         
     | 
| 
      
 14 
     | 
    
         
            +
            #
         
     | 
| 
      
 15 
     | 
    
         
            +
            # - write:
         
     | 
| 
      
 16 
     | 
    
         
            +
            # ruby examples/read_registry_key_security.rb --username msfadmin --password msfadmin -i 4 --sd 01000480000000000000000000000000140000000200340002000000000214003f000f00010100000000000512000000000218000000060001020000000000052000000020020000 -o w 192.168.172.138 'HKLM\SECURITY\Policy\PolEKList'
         
     | 
| 
      
 17 
     | 
    
         
            +
            # This will try to connect to \\192.168.172.138 with the msfadmin:msfadmin
         
     | 
| 
      
 18 
     | 
    
         
            +
            # credentialas and write the given security descriptor to the
         
     | 
| 
      
 19 
     | 
    
         
            +
            # `HKLM\SECURITY\Policy\PolEKList` registry key with the security information 4
         
     | 
| 
      
 20 
     | 
    
         
            +
            # (DACL_SECURITY_INFORMATION).
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
            require 'bundler/setup'
         
     | 
| 
      
 23 
     | 
    
         
            +
            require 'optparse'
         
     | 
| 
      
 24 
     | 
    
         
            +
            require 'ruby_smb'
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
            OPERATIONS = %w{read write}
         
     | 
| 
      
 27 
     | 
    
         
            +
            OPERATION_ALIASES = { "r" => "read", "w" => "write" }
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
            args = ARGV.dup
         
     | 
| 
      
 30 
     | 
    
         
            +
            options = {
         
     | 
| 
      
 31 
     | 
    
         
            +
              domain: '.',
         
     | 
| 
      
 32 
     | 
    
         
            +
              username: '',
         
     | 
| 
      
 33 
     | 
    
         
            +
              password: '',
         
     | 
| 
      
 34 
     | 
    
         
            +
              smbv1: true,
         
     | 
| 
      
 35 
     | 
    
         
            +
              smbv2: true,
         
     | 
| 
      
 36 
     | 
    
         
            +
              smbv3: true,
         
     | 
| 
      
 37 
     | 
    
         
            +
              target: nil,
         
     | 
| 
      
 38 
     | 
    
         
            +
              key: nil,
         
     | 
| 
      
 39 
     | 
    
         
            +
              operation: 'read',
         
     | 
| 
      
 40 
     | 
    
         
            +
              info: RubySMB::Field::SecurityDescriptor::OWNER_SECURITY_INFORMATION | RubySMB::Field::SecurityDescriptor::GROUP_SECURITY_INFORMATION | RubySMB::Field::SecurityDescriptor::DACL_SECURITY_INFORMATION,
         
     | 
| 
      
 41 
     | 
    
         
            +
              sd: nil
         
     | 
| 
      
 42 
     | 
    
         
            +
            }
         
     | 
| 
      
 43 
     | 
    
         
            +
            options[:key] = args.pop
         
     | 
| 
      
 44 
     | 
    
         
            +
            options[:target ] = args.pop
         
     | 
| 
      
 45 
     | 
    
         
            +
            optparser = OptionParser.new do |opts|
         
     | 
| 
      
 46 
     | 
    
         
            +
              opts.banner = "Usage: #{File.basename(__FILE__)} [options] target reg_key"
         
     | 
| 
      
 47 
     | 
    
         
            +
              opts.on('--[no-]smbv1', "Enable or disable SMBv1 (default: #{options[:smbv1] ? 'Enabled' : 'Disabled'})") do |smbv1|
         
     | 
| 
      
 48 
     | 
    
         
            +
                options[:smbv1] = smbv1
         
     | 
| 
      
 49 
     | 
    
         
            +
              end
         
     | 
| 
      
 50 
     | 
    
         
            +
              opts.on('--[no-]smbv2', "Enable or disable SMBv2 (default: #{options[:smbv2] ? 'Enabled' : 'Disabled'})") do |smbv2|
         
     | 
| 
      
 51 
     | 
    
         
            +
                options[:smbv2] = smbv2
         
     | 
| 
      
 52 
     | 
    
         
            +
              end
         
     | 
| 
      
 53 
     | 
    
         
            +
              opts.on('--[no-]smbv3', "Enable or disable SMBv3 (default: #{options[:smbv3] ? 'Enabled' : 'Disabled'})") do |smbv3|
         
     | 
| 
      
 54 
     | 
    
         
            +
                options[:smbv3] = smbv3
         
     | 
| 
      
 55 
     | 
    
         
            +
              end
         
     | 
| 
      
 56 
     | 
    
         
            +
              opts.on('-u', '--username [USERNAME]', "The account's username (default: #{options[:username]})") do |username|
         
     | 
| 
      
 57 
     | 
    
         
            +
                if username.include?('\\')
         
     | 
| 
      
 58 
     | 
    
         
            +
                  options[:domain], options[:username] = username.split('\\', 2)
         
     | 
| 
      
 59 
     | 
    
         
            +
                else
         
     | 
| 
      
 60 
     | 
    
         
            +
                  options[:username] = username
         
     | 
| 
      
 61 
     | 
    
         
            +
                end
         
     | 
| 
      
 62 
     | 
    
         
            +
              end
         
     | 
| 
      
 63 
     | 
    
         
            +
              opts.on('-p', '--password [PASSWORD]', "The account's password (default: #{options[:password]})") do |password|
         
     | 
| 
      
 64 
     | 
    
         
            +
                options[:password] = password
         
     | 
| 
      
 65 
     | 
    
         
            +
              end
         
     | 
| 
      
 66 
     | 
    
         
            +
              operation_list = (OPERATION_ALIASES.keys + OPERATIONS).join(', ')
         
     | 
| 
      
 67 
     | 
    
         
            +
              opts.on('-o', '--operation OPERATION', OPERATIONS, OPERATION_ALIASES, "The operation to perform on the registry key (default: #{options[:operation]})", "(#{operation_list})") do |operation|
         
     | 
| 
      
 68 
     | 
    
         
            +
                options[:operation] = operation
         
     | 
| 
      
 69 
     | 
    
         
            +
              end
         
     | 
| 
      
 70 
     | 
    
         
            +
              opts.on('-i', '--info [SECURITY INFORMATION]', Integer, "The security information value (default: #{options[:info]})") do |password|
         
     | 
| 
      
 71 
     | 
    
         
            +
                options[:info] = password
         
     | 
| 
      
 72 
     | 
    
         
            +
              end
         
     | 
| 
      
 73 
     | 
    
         
            +
              opts.on('-s', '--sd [SECURITY DESCRIPTOR]', "The security descriptor to write as an hex string") do |sd|
         
     | 
| 
      
 74 
     | 
    
         
            +
                options[:sd] = sd
         
     | 
| 
      
 75 
     | 
    
         
            +
              end
         
     | 
| 
      
 76 
     | 
    
         
            +
            end
         
     | 
| 
      
 77 
     | 
    
         
            +
            optparser.parse!(args)
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
            if options[:target].nil? || options[:key].nil?
         
     | 
| 
      
 80 
     | 
    
         
            +
              abort(optparser.help)
         
     | 
| 
      
 81 
     | 
    
         
            +
            end
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
            sock = TCPSocket.new options[:target], 445
         
     | 
| 
      
 84 
     | 
    
         
            +
            dispatcher = RubySMB::Dispatcher::Socket.new(sock)
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
            client = RubySMB::Client.new(dispatcher, smb1: options[:smbv1], smb2: options[:smbv2], smb3: options[:smbv3], username: options[:username], password: options[:password], domain: options[:domain])
         
     | 
| 
      
 87 
     | 
    
         
            +
            protocol = client.negotiate
         
     | 
| 
      
 88 
     | 
    
         
            +
            status = client.authenticate
         
     | 
| 
      
 89 
     | 
    
         
            +
             
     | 
| 
      
 90 
     | 
    
         
            +
            puts "#{protocol}: #{status}"
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
            case options[:operation]
         
     | 
| 
      
 93 
     | 
    
         
            +
            when 'read', 'r'
         
     | 
| 
      
 94 
     | 
    
         
            +
              puts "Read registry key #{options[:key]} security descriptor with security information #{options[:info]}"
         
     | 
| 
      
 95 
     | 
    
         
            +
              security_descriptor = client.get_key_security_descriptor(options[:target], options[:key], options[:info])
         
     | 
| 
      
 96 
     | 
    
         
            +
              puts "Security descriptor: #{security_descriptor.b.bytes.map {|c| "%02x" % c.ord}.join}"
         
     | 
| 
      
 97 
     | 
    
         
            +
            when 'write', 'w'
         
     | 
| 
      
 98 
     | 
    
         
            +
              unless options[:sd] && !options[:sd].empty?
         
     | 
| 
      
 99 
     | 
    
         
            +
                puts "Security descriptor missing"
         
     | 
| 
      
 100 
     | 
    
         
            +
                abort(optparser.help)
         
     | 
| 
      
 101 
     | 
    
         
            +
              end
         
     | 
| 
      
 102 
     | 
    
         
            +
              puts "Write security descriptor #{options[:sd]} to registry key #{options[:key]} with security information #{options[:info]}"
         
     | 
| 
      
 103 
     | 
    
         
            +
              sd = options[:sd].chars.each_slice(2).map {|c| c.join.to_i(16).chr}.join
         
     | 
| 
      
 104 
     | 
    
         
            +
              status = client.set_key_security_descriptor(options[:target], options[:key], sd, options[:info])
         
     | 
| 
      
 105 
     | 
    
         
            +
              puts "Success!"
         
     | 
| 
      
 106 
     | 
    
         
            +
            end
         
     | 
| 
      
 107 
     | 
    
         
            +
             
     | 
| 
      
 108 
     | 
    
         
            +
            client.disconnect!
         
     | 
| 
      
 109 
     | 
    
         
            +
             
     | 
| 
         @@ -40,6 +40,18 @@ module RubySMB 
     | 
|
| 
       40 
40 
     | 
    
         
             
                    end
         
     | 
| 
       41 
41 
     | 
    
         
             
                  end
         
     | 
| 
       42 
42 
     | 
    
         | 
| 
      
 43 
     | 
    
         
            +
                  def get_key_security_descriptor(host, key, security_information = RubySMB::Field::SecurityDescriptor::OWNER_SECURITY_INFORMATION)
         
     | 
| 
      
 44 
     | 
    
         
            +
                    connect_to_winreg(host) do |named_pipe|
         
     | 
| 
      
 45 
     | 
    
         
            +
                      named_pipe.get_key_security_descriptor(key, security_information)
         
     | 
| 
      
 46 
     | 
    
         
            +
                    end
         
     | 
| 
      
 47 
     | 
    
         
            +
                  end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                  def set_key_security_descriptor(host, key, security_descriptor, security_information = RubySMB::Field::SecurityDescriptor::OWNER_SECURITY_INFORMATION)
         
     | 
| 
      
 50 
     | 
    
         
            +
                    connect_to_winreg(host) do |named_pipe|
         
     | 
| 
      
 51 
     | 
    
         
            +
                      named_pipe.set_key_security_descriptor(key, security_descriptor, security_information)
         
     | 
| 
      
 52 
     | 
    
         
            +
                    end
         
     | 
| 
      
 53 
     | 
    
         
            +
                  end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
       43 
55 
     | 
    
         
             
                end
         
     | 
| 
       44 
56 
     | 
    
         
             
              end
         
     | 
| 
       45 
57 
     | 
    
         
             
            end
         
     | 
    
        data/lib/ruby_smb/dcerpc/ndr.rb
    CHANGED
    
    | 
         @@ -567,8 +567,11 @@ module RubySMB::Dcerpc::Ndr 
     | 
|
| 
       567 
567 
     | 
    
         
             
                def get_max_count(val)
         
     | 
| 
       568 
568 
     | 
    
         
             
                  if is_a?(BinData::Stringz)
         
     | 
| 
       569 
569 
     | 
    
         
             
                    max_count = val.to_s.strip.length
         
     | 
| 
       570 
     | 
    
         
            -
                    #  
     | 
| 
       571 
     | 
    
         
            -
                     
     | 
| 
      
 570 
     | 
    
         
            +
                    # Add one to count the terminator. According to
         
     | 
| 
      
 571 
     | 
    
         
            +
                    # https://pubs.opengroup.org/onlinepubs/9629399/chap14.htm#tagcjh_19_03_04_02,
         
     | 
| 
      
 572 
     | 
    
         
            +
                    # the NDR String must contain at least one element, the terminator. So,
         
     | 
| 
      
 573 
     | 
    
         
            +
                    # add one even if it is an empty string.
         
     | 
| 
      
 574 
     | 
    
         
            +
                    max_count += 1
         
     | 
| 
       572 
575 
     | 
    
         
             
                    return max_count
         
     | 
| 
       573 
576 
     | 
    
         
             
                  else
         
     | 
| 
       574 
577 
     | 
    
         
             
                    return val.to_s.length
         
     | 
| 
         @@ -622,8 +625,11 @@ module RubySMB::Dcerpc::Ndr 
     | 
|
| 
       622 
625 
     | 
    
         
             
                def update_actual_count(val)
         
     | 
| 
       623 
626 
     | 
    
         
             
                  if is_a?(BinData::Stringz)
         
     | 
| 
       624 
627 
     | 
    
         
             
                    @actual_count = val.to_s.strip.length
         
     | 
| 
       625 
     | 
    
         
            -
                    #  
     | 
| 
       626 
     | 
    
         
            -
                     
     | 
| 
      
 628 
     | 
    
         
            +
                    # Add one to count the terminator. According to
         
     | 
| 
      
 629 
     | 
    
         
            +
                    # https://pubs.opengroup.org/onlinepubs/9629399/chap14.htm#tagcjh_19_03_04,
         
     | 
| 
      
 630 
     | 
    
         
            +
                    # the NDR String must contain at least one element, the terminator. So,
         
     | 
| 
      
 631 
     | 
    
         
            +
                    # add one even if it is an empty string.
         
     | 
| 
      
 632 
     | 
    
         
            +
                    @actual_count += 1
         
     | 
| 
       627 
633 
     | 
    
         
             
                  else
         
     | 
| 
       628 
634 
     | 
    
         
             
                    @actual_count = val.to_s.length
         
     | 
| 
       629 
635 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -18,22 +18,24 @@ module RubySMB 
     | 
|
| 
       18 
18 
     | 
    
         
             
                  choice :stub, label: 'Stub', selection: -> { @obj.parent.get_parameter(:endpoint) || '' } do
         
     | 
| 
       19 
19 
     | 
    
         
             
                    string 'Encrypted'
         
     | 
| 
       20 
20 
     | 
    
         
             
                    choice 'Winreg', selection: -> { opnum } do
         
     | 
| 
       21 
     | 
    
         
            -
                      open_root_key_request 
     | 
| 
       22 
     | 
    
         
            -
                      open_root_key_request 
     | 
| 
       23 
     | 
    
         
            -
                      open_root_key_request 
     | 
| 
       24 
     | 
    
         
            -
                      open_root_key_request 
     | 
| 
       25 
     | 
    
         
            -
                      open_root_key_request 
     | 
| 
       26 
     | 
    
         
            -
                      open_root_key_request 
     | 
| 
       27 
     | 
    
         
            -
                      open_root_key_request 
     | 
| 
       28 
     | 
    
         
            -
                      open_root_key_request 
     | 
| 
       29 
     | 
    
         
            -
                      close_key_request 
     | 
| 
       30 
     | 
    
         
            -
                      enum_key_request 
     | 
| 
       31 
     | 
    
         
            -
                      enum_value_request 
     | 
| 
       32 
     | 
    
         
            -
                      open_key_request 
     | 
| 
       33 
     | 
    
         
            -
                      query_info_key_request 
     | 
| 
       34 
     | 
    
         
            -
                      query_value_request 
     | 
| 
       35 
     | 
    
         
            -
                      create_key_request 
     | 
| 
       36 
     | 
    
         
            -
                      save_key_request 
     | 
| 
      
 21 
     | 
    
         
            +
                      open_root_key_request     Winreg::OPEN_HKCR, opnum: Winreg::OPEN_HKCR
         
     | 
| 
      
 22 
     | 
    
         
            +
                      open_root_key_request     Winreg::OPEN_HKCU, opnum: Winreg::OPEN_HKCU
         
     | 
| 
      
 23 
     | 
    
         
            +
                      open_root_key_request     Winreg::OPEN_HKLM, opnum: Winreg::OPEN_HKLM
         
     | 
| 
      
 24 
     | 
    
         
            +
                      open_root_key_request     Winreg::OPEN_HKPD, opnum: Winreg::OPEN_HKPD
         
     | 
| 
      
 25 
     | 
    
         
            +
                      open_root_key_request     Winreg::OPEN_HKU,  opnum: Winreg::OPEN_HKU
         
     | 
| 
      
 26 
     | 
    
         
            +
                      open_root_key_request     Winreg::OPEN_HKCC, opnum: Winreg::OPEN_HKCC
         
     | 
| 
      
 27 
     | 
    
         
            +
                      open_root_key_request     Winreg::OPEN_HKPT, opnum: Winreg::OPEN_HKPT
         
     | 
| 
      
 28 
     | 
    
         
            +
                      open_root_key_request     Winreg::OPEN_HKPN, opnum: Winreg::OPEN_HKPN
         
     | 
| 
      
 29 
     | 
    
         
            +
                      close_key_request         Winreg::REG_CLOSE_KEY
         
     | 
| 
      
 30 
     | 
    
         
            +
                      enum_key_request          Winreg::REG_ENUM_KEY
         
     | 
| 
      
 31 
     | 
    
         
            +
                      enum_value_request        Winreg::REG_ENUM_VALUE
         
     | 
| 
      
 32 
     | 
    
         
            +
                      open_key_request          Winreg::REG_OPEN_KEY
         
     | 
| 
      
 33 
     | 
    
         
            +
                      query_info_key_request    Winreg::REG_QUERY_INFO_KEY
         
     | 
| 
      
 34 
     | 
    
         
            +
                      query_value_request       Winreg::REG_QUERY_VALUE
         
     | 
| 
      
 35 
     | 
    
         
            +
                      create_key_request        Winreg::REG_CREATE_KEY
         
     | 
| 
      
 36 
     | 
    
         
            +
                      save_key_request          Winreg::REG_SAVE_KEY
         
     | 
| 
      
 37 
     | 
    
         
            +
                      get_key_security_request  Winreg::REG_GET_KEY_SECURITY
         
     | 
| 
      
 38 
     | 
    
         
            +
                      set_key_security_request  Winreg::REG_SET_KEY_SECURITY
         
     | 
| 
       37 
39 
     | 
    
         
             
                      string                 :default
         
     | 
| 
       38 
40 
     | 
    
         
             
                    end
         
     | 
| 
       39 
41 
     | 
    
         
             
                    choice 'Netlogon', selection: -> { opnum } do
         
     | 
| 
         @@ -20,7 +20,7 @@ module RubySMB 
     | 
|
| 
       20 
20 
     | 
    
         
             
                    when BinData::Stringz, BinData::String, String
         
     | 
| 
       21 
21 
     | 
    
         
             
                      self.buffer = val.to_s
         
     | 
| 
       22 
22 
     | 
    
         
             
                      val_length = val.strip.length
         
     | 
| 
       23 
     | 
    
         
            -
                      val_length += 1 
     | 
| 
      
 23 
     | 
    
         
            +
                      val_length += 1
         
     | 
| 
       24 
24 
     | 
    
         
             
                      self.buffer_length = val_length * 2
         
     | 
| 
       25 
25 
     | 
    
         
             
                      self.maximum_length = val_length * 2
         
     | 
| 
       26 
26 
     | 
    
         
             
                    else
         
     | 
| 
         @@ -0,0 +1,26 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module RubySMB
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Dcerpc
         
     | 
| 
      
 3 
     | 
    
         
            +
                module Winreg
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                  # This class represents a GetKeySecurity Request Packet as defined in
         
     | 
| 
      
 6 
     | 
    
         
            +
                  # [3.1.5.13 BaseRegGetKeySecurity (Opnum 12)](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rrp/b0e1868c-f4fd-4b43-959f-c0f0cac3ee26)
         
     | 
| 
      
 7 
     | 
    
         
            +
                  class GetKeySecurityRequest < BinData::Record
         
     | 
| 
      
 8 
     | 
    
         
            +
                    attr_reader :opnum
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                    endian :little
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                    rpc_hkey                :hkey
         
     | 
| 
      
 13 
     | 
    
         
            +
                    uint32                  :security_information
         
     | 
| 
      
 14 
     | 
    
         
            +
                    rpc_security_descriptor :prpc_security_descriptor_in
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                    def initialize_instance
         
     | 
| 
      
 17 
     | 
    
         
            +
                      super
         
     | 
| 
      
 18 
     | 
    
         
            +
                      @opnum = REG_GET_KEY_SECURITY
         
     | 
| 
      
 19 
     | 
    
         
            +
                    end
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
              end
         
     | 
| 
      
 24 
     | 
    
         
            +
            end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
         @@ -0,0 +1,26 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module RubySMB
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Dcerpc
         
     | 
| 
      
 3 
     | 
    
         
            +
                module Winreg
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                  # This class represents a GetKeySecurity Response Packet as defined in
         
     | 
| 
      
 6 
     | 
    
         
            +
                  # [3.1.5.13 BaseRegGetKeySecurity (Opnum 12)](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rrp/b0e1868c-f4fd-4b43-959f-c0f0cac3ee26)
         
     | 
| 
      
 7 
     | 
    
         
            +
                  class GetKeySecurityResponse < BinData::Record
         
     | 
| 
      
 8 
     | 
    
         
            +
                    attr_reader :opnum
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                    endian :little
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                    rpc_security_descriptor :prpc_security_descriptor_out
         
     | 
| 
      
 13 
     | 
    
         
            +
                    ndr_uint32              :error_status
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                    def initialize_instance
         
     | 
| 
      
 16 
     | 
    
         
            +
                      super
         
     | 
| 
      
 17 
     | 
    
         
            +
                      @opnum = REG_GET_KEY_SECURITY
         
     | 
| 
      
 18 
     | 
    
         
            +
                    end
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
              end
         
     | 
| 
      
 23 
     | 
    
         
            +
            end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
         @@ -0,0 +1,26 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module RubySMB
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Dcerpc
         
     | 
| 
      
 3 
     | 
    
         
            +
                module Winreg
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                  # This class represents a SetKeySecurity Request Packet as defined in
         
     | 
| 
      
 6 
     | 
    
         
            +
                  # [3.1.5.21 BaseRegSetKeySecurity (Opnum 21)](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rrp/da18856c-8a6d-4217-8e93-3625865e562c)
         
     | 
| 
      
 7 
     | 
    
         
            +
                  class SetKeySecurityRequest < BinData::Record
         
     | 
| 
      
 8 
     | 
    
         
            +
                    attr_reader :opnum
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                    endian :little
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                    rpc_hkey                :hkey
         
     | 
| 
      
 13 
     | 
    
         
            +
                    uint32                  :security_information
         
     | 
| 
      
 14 
     | 
    
         
            +
                    rpc_security_descriptor :prpc_security_descriptor
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                    def initialize_instance
         
     | 
| 
      
 17 
     | 
    
         
            +
                      super
         
     | 
| 
      
 18 
     | 
    
         
            +
                      @opnum = REG_SET_KEY_SECURITY
         
     | 
| 
      
 19 
     | 
    
         
            +
                    end
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
              end
         
     | 
| 
      
 24 
     | 
    
         
            +
            end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
         @@ -0,0 +1,25 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module RubySMB
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Dcerpc
         
     | 
| 
      
 3 
     | 
    
         
            +
                module Winreg
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                  # This class represents a SetKeySecurity Response Packet as defined in
         
     | 
| 
      
 6 
     | 
    
         
            +
                  # [3.1.5.21 BaseRegSetKeySecurity (Opnum 21)](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rrp/da18856c-8a6d-4217-8e93-3625865e562c)
         
     | 
| 
      
 7 
     | 
    
         
            +
                  class SetKeySecurityResponse < BinData::Record
         
     | 
| 
      
 8 
     | 
    
         
            +
                    attr_reader :opnum
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                    endian :little
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                    ndr_uint32 :error_status
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                    def initialize_instance
         
     | 
| 
      
 15 
     | 
    
         
            +
                      super
         
     | 
| 
      
 16 
     | 
    
         
            +
                      @opnum = REG_SET_KEY_SECURITY
         
     | 
| 
      
 17 
     | 
    
         
            +
                    end
         
     | 
| 
      
 18 
     | 
    
         
            +
                  end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
              end
         
     | 
| 
      
 22 
     | 
    
         
            +
            end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
         @@ -16,10 +16,12 @@ module RubySMB 
     | 
|
| 
       16 
16 
     | 
    
         
             
                  REG_CREATE_KEY        = 0x06
         
     | 
| 
       17 
17 
     | 
    
         
             
                  REG_ENUM_KEY          = 0x09
         
     | 
| 
       18 
18 
     | 
    
         
             
                  REG_ENUM_VALUE        = 0x0a
         
     | 
| 
      
 19 
     | 
    
         
            +
                  REG_GET_KEY_SECURITY  = 0x0c
         
     | 
| 
       19 
20 
     | 
    
         
             
                  REG_OPEN_KEY          = 0x0f
         
     | 
| 
       20 
21 
     | 
    
         
             
                  REG_QUERY_INFO_KEY    = 0x10
         
     | 
| 
       21 
22 
     | 
    
         
             
                  REG_QUERY_VALUE       = 0x11
         
     | 
| 
       22 
23 
     | 
    
         
             
                  REG_SAVE_KEY          = 0x14
         
     | 
| 
      
 24 
     | 
    
         
            +
                  REG_SET_KEY_SECURITY  = 0x15
         
     | 
| 
       23 
25 
     | 
    
         
             
                  OPEN_HKCC             = 0x1b
         
     | 
| 
       24 
26 
     | 
    
         
             
                  OPEN_HKPT             = 0x20
         
     | 
| 
       25 
27 
     | 
    
         
             
                  OPEN_HKPN             = 0x21
         
     | 
| 
         @@ -43,6 +45,10 @@ module RubySMB 
     | 
|
| 
       43 
45 
     | 
    
         
             
                  require 'ruby_smb/dcerpc/winreg/create_key_response'
         
     | 
| 
       44 
46 
     | 
    
         
             
                  require 'ruby_smb/dcerpc/winreg/save_key_request'
         
     | 
| 
       45 
47 
     | 
    
         
             
                  require 'ruby_smb/dcerpc/winreg/save_key_response'
         
     | 
| 
      
 48 
     | 
    
         
            +
                  require 'ruby_smb/dcerpc/winreg/get_key_security_request'
         
     | 
| 
      
 49 
     | 
    
         
            +
                  require 'ruby_smb/dcerpc/winreg/get_key_security_response'
         
     | 
| 
      
 50 
     | 
    
         
            +
                  require 'ruby_smb/dcerpc/winreg/set_key_security_request'
         
     | 
| 
      
 51 
     | 
    
         
            +
                  require 'ruby_smb/dcerpc/winreg/set_key_security_response'
         
     | 
| 
       46 
52 
     | 
    
         | 
| 
       47 
53 
     | 
    
         
             
                  ROOT_KEY_MAP = {
         
     | 
| 
       48 
54 
     | 
    
         
             
                    "HKEY_CLASSES_ROOT"         => OPEN_HKCR,
         
     | 
| 
         @@ -65,6 +71,8 @@ module RubySMB 
     | 
|
| 
       65 
71 
     | 
    
         | 
| 
       66 
72 
     | 
    
         
             
                  BUFFER_SIZE = 1024
         
     | 
| 
       67 
73 
     | 
    
         | 
| 
      
 74 
     | 
    
         
            +
                  RegValue = Struct.new(:type, :data)
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
       68 
76 
     | 
    
         
             
                  # Open the registry root key and return a handle for it. The key can be
         
     | 
| 
       69 
77 
     | 
    
         
             
                  # either a long format (e.g. HKEY_LOCAL_MACHINE) or a short format
         
     | 
| 
       70 
78 
     | 
    
         
             
                  # (e.g. HKLM)
         
     | 
| 
         @@ -105,10 +113,7 @@ module RubySMB 
     | 
|
| 
       105 
113 
     | 
    
         
             
                  # @raise [RubySMB::Dcerpc::Error::WinregError] if the response error status is not ERROR_SUCCESS
         
     | 
| 
       106 
114 
     | 
    
         
             
                  def open_key(handle, sub_key)
         
     | 
| 
       107 
115 
     | 
    
         
             
                    openkey_request_packet = RubySMB::Dcerpc::Winreg::OpenKeyRequest.new(hkey: handle, lp_sub_key: sub_key)
         
     | 
| 
       108 
     | 
    
         
            -
                    openkey_request_packet.sam_desired. 
     | 
| 
       109 
     | 
    
         
            -
                    openkey_request_packet.sam_desired.key_query_value = 1
         
     | 
| 
       110 
     | 
    
         
            -
                    openkey_request_packet.sam_desired.key_enumerate_sub_keys = 1
         
     | 
| 
       111 
     | 
    
         
            -
                    openkey_request_packet.sam_desired.key_notify = 1
         
     | 
| 
      
 116 
     | 
    
         
            +
                    openkey_request_packet.sam_desired.maximum_allowed = 1
         
     | 
| 
       112 
117 
     | 
    
         
             
                    response = dcerpc_request(openkey_request_packet)
         
     | 
| 
       113 
118 
     | 
    
         
             
                    begin
         
     | 
| 
       114 
119 
     | 
    
         
             
                      open_key_response = RubySMB::Dcerpc::Winreg::OpenKeyResponse.read(response)
         
     | 
| 
         @@ -124,11 +129,12 @@ module RubySMB 
     | 
|
| 
       124 
129 
     | 
    
         
             
                  end
         
     | 
| 
       125 
130 
     | 
    
         | 
| 
       126 
131 
     | 
    
         
             
                  # Retrieve the data associated with the named value of a specified
         
     | 
| 
       127 
     | 
    
         
            -
                  # registry open key.
         
     | 
| 
      
 132 
     | 
    
         
            +
                  # registry open key. This will also return the type if required.
         
     | 
| 
       128 
133 
     | 
    
         
             
                  #
         
     | 
| 
       129 
134 
     | 
    
         
             
                  # @param handle [Ndr::NdrContextHandle] the handle for the key
         
     | 
| 
       130 
135 
     | 
    
         
             
                  # @param value_name [String] the name of the value
         
     | 
| 
       131 
     | 
    
         
            -
                  # @ 
     | 
| 
      
 136 
     | 
    
         
            +
                  # @param value_name [Boolean] also return the data type if set to true
         
     | 
| 
      
 137 
     | 
    
         
            +
                  # @return [RegValue] a RegValue struct containing the data type and the actual data of the value entry
         
     | 
| 
       132 
138 
     | 
    
         
             
                  # @raise [RubySMB::Dcerpc::Error::InvalidPacket] if the response is not a QueryValueResponse packet
         
     | 
| 
       133 
139 
     | 
    
         
             
                  # @raise [RubySMB::Dcerpc::Error::WinregError] if the response error status is not ERROR_SUCCESS
         
     | 
| 
       134 
140 
     | 
    
         
             
                  def query_value(handle, value_name)
         
     | 
| 
         @@ -161,7 +167,7 @@ module RubySMB 
     | 
|
| 
       161 
167 
     | 
    
         
             
                        "#{WindowsError::Win32.find_by_retval(query_value_response.error_status.value).join(',')}"
         
     | 
| 
       162 
168 
     | 
    
         
             
                    end
         
     | 
| 
       163 
169 
     | 
    
         | 
| 
       164 
     | 
    
         
            -
                    query_value_response.data
         
     | 
| 
      
 170 
     | 
    
         
            +
                    RegValue.new(query_value_response.lp_type, query_value_response.data)
         
     | 
| 
       165 
171 
     | 
    
         
             
                  end
         
     | 
| 
       166 
172 
     | 
    
         | 
| 
       167 
173 
     | 
    
         
             
                  # Close the handle to the registry key.
         
     | 
| 
         @@ -323,6 +329,7 @@ module RubySMB 
     | 
|
| 
       323 
329 
     | 
    
         
             
                  # exists, false otherwise.
         
     | 
| 
       324 
330 
     | 
    
         
             
                  #
         
     | 
| 
       325 
331 
     | 
    
         
             
                  # @param key [String] the registry key to check
         
     | 
| 
      
 332 
     | 
    
         
            +
                  # @param bind [Boolean] Bind to the winreg endpoint if true (default)
         
     | 
| 
       326 
333 
     | 
    
         
             
                  # @return [Boolean]
         
     | 
| 
       327 
334 
     | 
    
         
             
                  def has_registry_key?(key, bind: true)
         
     | 
| 
       328 
335 
     | 
    
         
             
                    bind(endpoint: RubySMB::Dcerpc::Winreg) if bind
         
     | 
| 
         @@ -345,6 +352,7 @@ module RubySMB 
     | 
|
| 
       345 
352 
     | 
    
         
             
                  #
         
     | 
| 
       346 
353 
     | 
    
         
             
                  # @param key [String] the registry key
         
     | 
| 
       347 
354 
     | 
    
         
             
                  # @param value_name [String] the name of the value to read
         
     | 
| 
      
 355 
     | 
    
         
            +
                  # @param bind [Boolean] Bind to the winreg endpoint if true (default)
         
     | 
| 
       348 
356 
     | 
    
         
             
                  # @return [String] the data of the value entry
         
     | 
| 
       349 
357 
     | 
    
         
             
                  def read_registry_key_value(key, value_name, bind: true)
         
     | 
| 
       350 
358 
     | 
    
         
             
                    bind(endpoint: RubySMB::Dcerpc::Winreg) if bind
         
     | 
| 
         @@ -352,8 +360,8 @@ module RubySMB 
     | 
|
| 
       352 
360 
     | 
    
         
             
                    root_key, sub_key = key.gsub(/\//, '\\').split('\\', 2)
         
     | 
| 
       353 
361 
     | 
    
         
             
                    root_key_handle = open_root_key(root_key)
         
     | 
| 
       354 
362 
     | 
    
         
             
                    subkey_handle = open_key(root_key_handle, sub_key)
         
     | 
| 
       355 
     | 
    
         
            -
                     
     | 
| 
       356 
     | 
    
         
            -
                     
     | 
| 
      
 363 
     | 
    
         
            +
                    reg_value = query_value(subkey_handle, value_name)
         
     | 
| 
      
 364 
     | 
    
         
            +
                    reg_value.data
         
     | 
| 
       357 
365 
     | 
    
         
             
                  ensure
         
     | 
| 
       358 
366 
     | 
    
         
             
                    close_key(subkey_handle) if subkey_handle
         
     | 
| 
       359 
367 
     | 
    
         
             
                    close_key(root_key_handle) if root_key_handle
         
     | 
| 
         @@ -363,6 +371,7 @@ module RubySMB 
     | 
|
| 
       363 
371 
     | 
    
         
             
                  # is provided, it enumerates its subkeys.
         
     | 
| 
       364 
372 
     | 
    
         
             
                  #
         
     | 
| 
       365 
373 
     | 
    
         
             
                  # @param key [String] the registry key
         
     | 
| 
      
 374 
     | 
    
         
            +
                  # @param bind [Boolean] Bind to the winreg endpoint if true (default)
         
     | 
| 
       366 
375 
     | 
    
         
             
                  # @return [Array<String>] the subkeys
         
     | 
| 
       367 
376 
     | 
    
         
             
                  def enum_registry_key(key, bind: true)
         
     | 
| 
       368 
377 
     | 
    
         
             
                    bind(endpoint: RubySMB::Dcerpc::Winreg) if bind
         
     | 
| 
         @@ -389,6 +398,7 @@ module RubySMB 
     | 
|
| 
       389 
398 
     | 
    
         
             
                  # Enumerate the values for the specified registry key.
         
     | 
| 
       390 
399 
     | 
    
         
             
                  #
         
     | 
| 
       391 
400 
     | 
    
         
             
                  # @param key [String] the registry key
         
     | 
| 
      
 401 
     | 
    
         
            +
                  # @param bind [Boolean] Bind to the winreg endpoint if true (default)
         
     | 
| 
       392 
402 
     | 
    
         
             
                  # @return [Array<String>] the values
         
     | 
| 
       393 
403 
     | 
    
         
             
                  def enum_registry_values(key, bind: true)
         
     | 
| 
       394 
404 
     | 
    
         
             
                    bind(endpoint: RubySMB::Dcerpc::Winreg) if bind
         
     | 
| 
         @@ -412,6 +422,108 @@ module RubySMB 
     | 
|
| 
       412 
422 
     | 
    
         
             
                    close_key(root_key_handle) if root_key_handle && root_key_handle != subkey_handle
         
     | 
| 
       413 
423 
     | 
    
         
             
                  end
         
     | 
| 
       414 
424 
     | 
    
         | 
| 
      
 425 
     | 
    
         
            +
             
     | 
| 
      
 426 
     | 
    
         
            +
                  # Retrieve the security descriptor for the given registry key handle.
         
     | 
| 
      
 427 
     | 
    
         
            +
                  #
         
     | 
| 
      
 428 
     | 
    
         
            +
                  # @param handle [String] the handle to the registry key
         
     | 
| 
      
 429 
     | 
    
         
            +
                  # @param security_information [] the security information to query (see https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/23e75ca3-98fd-4396-84e5-86cd9d40d343). These constants are defined in the `RubySMB::Field::SecurityDescriptor` class
         
     | 
| 
      
 430 
     | 
    
         
            +
                  # @return [String] The security descriptor as a byte stream
         
     | 
| 
      
 431 
     | 
    
         
            +
                  # @raise [RubySMB::Dcerpc::Error::InvalidPacket] if the response is not a GetKeySecurityResponse packet
         
     | 
| 
      
 432 
     | 
    
         
            +
                  # @raise [RubySMB::Dcerpc::Error::WinregError] if the response error status is not ERROR_SUCCESS
         
     | 
| 
      
 433 
     | 
    
         
            +
                  def get_key_security(handle, security_information = RubySMB::Field::SecurityDescriptor::OWNER_SECURITY_INFORMATION)
         
     | 
| 
      
 434 
     | 
    
         
            +
                    get_key_security_request = RubySMB::Dcerpc::Winreg::GetKeySecurityRequest.new(
         
     | 
| 
      
 435 
     | 
    
         
            +
                      hkey: handle,
         
     | 
| 
      
 436 
     | 
    
         
            +
                      security_information: security_information,
         
     | 
| 
      
 437 
     | 
    
         
            +
                      prpc_security_descriptor_in: { cb_in_security_descriptor: 4096 }
         
     | 
| 
      
 438 
     | 
    
         
            +
                    )
         
     | 
| 
      
 439 
     | 
    
         
            +
                    response = dcerpc_request(get_key_security_request)
         
     | 
| 
      
 440 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 441 
     | 
    
         
            +
                      get_key_security_response = RubySMB::Dcerpc::Winreg::GetKeySecurityResponse.read(response)
         
     | 
| 
      
 442 
     | 
    
         
            +
                    rescue IOError
         
     | 
| 
      
 443 
     | 
    
         
            +
                      raise RubySMB::Dcerpc::Error::InvalidPacket, "Error reading the GetKeySecurity response"
         
     | 
| 
      
 444 
     | 
    
         
            +
                    end
         
     | 
| 
      
 445 
     | 
    
         
            +
                    unless get_key_security_response.error_status == WindowsError::Win32::ERROR_SUCCESS
         
     | 
| 
      
 446 
     | 
    
         
            +
                      raise RubySMB::Dcerpc::Error::WinregError, "Error returned when querying information: "\
         
     | 
| 
      
 447 
     | 
    
         
            +
                        "#{WindowsError::Win32.find_by_retval(get_key_security_response.error_status.value).join(',')}"
         
     | 
| 
      
 448 
     | 
    
         
            +
                    end
         
     | 
| 
      
 449 
     | 
    
         
            +
             
     | 
| 
      
 450 
     | 
    
         
            +
                    get_key_security_response.prpc_security_descriptor_out.lp_security_descriptor.to_a.pack('C*')
         
     | 
| 
      
 451 
     | 
    
         
            +
                  end
         
     | 
| 
      
 452 
     | 
    
         
            +
             
     | 
| 
      
 453 
     | 
    
         
            +
                  # Retrieve the security descriptor for the given key.
         
     | 
| 
      
 454 
     | 
    
         
            +
                  #
         
     | 
| 
      
 455 
     | 
    
         
            +
                  # @param key [String] the registry key
         
     | 
| 
      
 456 
     | 
    
         
            +
                  # @param security_information [] the security information to query (see https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/23e75ca3-98fd-4396-84e5-86cd9d40d343). These constants are defined in the `RubySMB::Field::SecurityDescriptor` class
         
     | 
| 
      
 457 
     | 
    
         
            +
                  # @param bind [Boolean] Bind to the winreg endpoint if true (default)
         
     | 
| 
      
 458 
     | 
    
         
            +
                  # @return [String] The security descriptor as a byte stream
         
     | 
| 
      
 459 
     | 
    
         
            +
                  # @raise [RubySMB::Dcerpc::Error::InvalidPacket] if the response is not a GetKeySecurityResponse packet
         
     | 
| 
      
 460 
     | 
    
         
            +
                  # @raise [RubySMB::Dcerpc::Error::WinregError] if the response error status is not ERROR_SUCCESS
         
     | 
| 
      
 461 
     | 
    
         
            +
                  def get_key_security_descriptor(key, security_information = RubySMB::Field::SecurityDescriptor::OWNER_SECURITY_INFORMATION, bind: true)
         
     | 
| 
      
 462 
     | 
    
         
            +
                    bind(endpoint: RubySMB::Dcerpc::Winreg) if bind
         
     | 
| 
      
 463 
     | 
    
         
            +
             
     | 
| 
      
 464 
     | 
    
         
            +
                    root_key, sub_key = key.gsub(/\//, '\\').split('\\', 2)
         
     | 
| 
      
 465 
     | 
    
         
            +
                    root_key_handle = open_root_key(root_key)
         
     | 
| 
      
 466 
     | 
    
         
            +
                    subkey_handle = open_key(root_key_handle, sub_key)
         
     | 
| 
      
 467 
     | 
    
         
            +
                    get_key_security(subkey_handle, security_information)
         
     | 
| 
      
 468 
     | 
    
         
            +
                  ensure
         
     | 
| 
      
 469 
     | 
    
         
            +
                    close_key(subkey_handle) if subkey_handle
         
     | 
| 
      
 470 
     | 
    
         
            +
                    close_key(root_key_handle) if root_key_handle
         
     | 
| 
      
 471 
     | 
    
         
            +
                  end
         
     | 
| 
      
 472 
     | 
    
         
            +
             
     | 
| 
      
 473 
     | 
    
         
            +
                  # Set the security descriptor for the given registry key handle.
         
     | 
| 
      
 474 
     | 
    
         
            +
                  #
         
     | 
| 
      
 475 
     | 
    
         
            +
                  # @param handle [String] the handle to the registry key
         
     | 
| 
      
 476 
     | 
    
         
            +
                  # @param security_descriptor [String] the new security descriptor to set as a byte stream
         
     | 
| 
      
 477 
     | 
    
         
            +
                  # @param security_information [] the security information to query (see https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/23e75ca3-98fd-4396-84e5-86cd9d40d343). These constants are defined in the `RubySMB::Field::SecurityDescriptor` class
         
     | 
| 
      
 478 
     | 
    
         
            +
                  # @param bind [Boolean] Bind to the winreg endpoint if true (default)
         
     | 
| 
      
 479 
     | 
    
         
            +
                  # @return [Integer] The error status returned by the DCERPC call
         
     | 
| 
      
 480 
     | 
    
         
            +
                  # @raise [RubySMB::Dcerpc::Error::InvalidPacket] if the response is not a SetKeySecurityResponse packet
         
     | 
| 
      
 481 
     | 
    
         
            +
                  # @raise [RubySMB::Dcerpc::Error::WinregError] if the response error status is not ERROR_SUCCESS
         
     | 
| 
      
 482 
     | 
    
         
            +
                  def set_key_security(handle, security_descriptor, security_information = RubySMB::Field::SecurityDescriptor::OWNER_SECURITY_INFORMATION)
         
     | 
| 
      
 483 
     | 
    
         
            +
                    set_key_security_request = RubySMB::Dcerpc::Winreg::SetKeySecurityRequest.new(
         
     | 
| 
      
 484 
     | 
    
         
            +
                      hkey: handle,
         
     | 
| 
      
 485 
     | 
    
         
            +
                      security_information: security_information,
         
     | 
| 
      
 486 
     | 
    
         
            +
                      prpc_security_descriptor: {
         
     | 
| 
      
 487 
     | 
    
         
            +
                        lp_security_descriptor: security_descriptor.bytes,
         
     | 
| 
      
 488 
     | 
    
         
            +
                        cb_in_security_descriptor: security_descriptor.b.size,
         
     | 
| 
      
 489 
     | 
    
         
            +
                        cb_out_security_descriptor: security_descriptor.b.size
         
     | 
| 
      
 490 
     | 
    
         
            +
                      }
         
     | 
| 
      
 491 
     | 
    
         
            +
                    )
         
     | 
| 
      
 492 
     | 
    
         
            +
                    response = dcerpc_request(set_key_security_request)
         
     | 
| 
      
 493 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 494 
     | 
    
         
            +
                      set_key_security_response = RubySMB::Dcerpc::Winreg::SetKeySecurityResponse.read(response)
         
     | 
| 
      
 495 
     | 
    
         
            +
                    rescue IOError
         
     | 
| 
      
 496 
     | 
    
         
            +
                      raise RubySMB::Dcerpc::Error::InvalidPacket, "Error reading the SetKeySecurity response"
         
     | 
| 
      
 497 
     | 
    
         
            +
                    end
         
     | 
| 
      
 498 
     | 
    
         
            +
                    unless set_key_security_response.error_status == WindowsError::Win32::ERROR_SUCCESS
         
     | 
| 
      
 499 
     | 
    
         
            +
                      raise RubySMB::Dcerpc::Error::WinregError, "Error returned when setting the registry key: "\
         
     | 
| 
      
 500 
     | 
    
         
            +
                        "#{WindowsError::Win32.find_by_retval(set_key_security_response.error_status.value).join(',')}"
         
     | 
| 
      
 501 
     | 
    
         
            +
                    end
         
     | 
| 
      
 502 
     | 
    
         
            +
             
     | 
| 
      
 503 
     | 
    
         
            +
                    set_key_security_response.error_status
         
     | 
| 
      
 504 
     | 
    
         
            +
                  end
         
     | 
| 
      
 505 
     | 
    
         
            +
             
     | 
| 
      
 506 
     | 
    
         
            +
                  # Set the security descriptor for the given key.
         
     | 
| 
      
 507 
     | 
    
         
            +
                  #
         
     | 
| 
      
 508 
     | 
    
         
            +
                  # @param key [String] the registry key
         
     | 
| 
      
 509 
     | 
    
         
            +
                  # @param security_descriptor [String] the new security descriptor to set as a byte stream
         
     | 
| 
      
 510 
     | 
    
         
            +
                  # @param security_information [] the security information to query (see https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/23e75ca3-98fd-4396-84e5-86cd9d40d343). These constants are defined in the `RubySMB::Field::SecurityDescriptor` class
         
     | 
| 
      
 511 
     | 
    
         
            +
                  # @param bind [Boolean] Bind to the winreg endpoint if true (default)
         
     | 
| 
      
 512 
     | 
    
         
            +
                  # @return [Integer] The error status returned by the DCERPC call
         
     | 
| 
      
 513 
     | 
    
         
            +
                  # @raise [RubySMB::Dcerpc::Error::InvalidPacket] if the response is not a SetKeySecurityResponse packet
         
     | 
| 
      
 514 
     | 
    
         
            +
                  # @raise [RubySMB::Dcerpc::Error::WinregError] if the response error status is not ERROR_SUCCESS
         
     | 
| 
      
 515 
     | 
    
         
            +
                  def set_key_security_descriptor(key, security_descriptor, security_information = RubySMB::Field::SecurityDescriptor::OWNER_SECURITY_INFORMATION, bind: true)
         
     | 
| 
      
 516 
     | 
    
         
            +
                    bind(endpoint: RubySMB::Dcerpc::Winreg) if bind
         
     | 
| 
      
 517 
     | 
    
         
            +
             
     | 
| 
      
 518 
     | 
    
         
            +
                    root_key, sub_key = key.gsub(/\//, '\\').split('\\', 2)
         
     | 
| 
      
 519 
     | 
    
         
            +
                    root_key_handle = open_root_key(root_key)
         
     | 
| 
      
 520 
     | 
    
         
            +
                    subkey_handle = open_key(root_key_handle, sub_key)
         
     | 
| 
      
 521 
     | 
    
         
            +
                    set_key_security(subkey_handle, security_descriptor, security_information)
         
     | 
| 
      
 522 
     | 
    
         
            +
                  ensure
         
     | 
| 
      
 523 
     | 
    
         
            +
                    close_key(subkey_handle) if subkey_handle
         
     | 
| 
      
 524 
     | 
    
         
            +
                    close_key(root_key_handle) if root_key_handle
         
     | 
| 
      
 525 
     | 
    
         
            +
                  end
         
     | 
| 
      
 526 
     | 
    
         
            +
             
     | 
| 
       415 
527 
     | 
    
         
             
                end
         
     | 
| 
       416 
528 
     | 
    
         
             
              end
         
     | 
| 
       417 
529 
     | 
    
         
             
            end
         
     | 
| 
         @@ -3,6 +3,23 @@ module RubySMB 
     | 
|
| 
       3 
3 
     | 
    
         
             
                # Class representing a SECURITY_DESCRIPTOR as defined in
         
     | 
| 
       4 
4 
     | 
    
         
             
                # [2.4.6 SECURITY_DESCRIPTOR](https://msdn.microsoft.com/en-us/library/cc230366.aspx)
         
     | 
| 
       5 
5 
     | 
    
         
             
                class SecurityDescriptor < BinData::Record
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                  # Security Information as defined in
         
     | 
| 
      
 8 
     | 
    
         
            +
                  # [2.4.7 SECURITY_INFORMATION](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-dtyp/23e75ca3-98fd-4396-84e5-86cd9d40d343)
         
     | 
| 
      
 9 
     | 
    
         
            +
                  OWNER_SECURITY_INFORMATION               = 0x00000001
         
     | 
| 
      
 10 
     | 
    
         
            +
                  GROUP_SECURITY_INFORMATION               = 0x00000002
         
     | 
| 
      
 11 
     | 
    
         
            +
                  DACL_SECURITY_INFORMATION                = 0x00000004
         
     | 
| 
      
 12 
     | 
    
         
            +
                  SACL_SECURITY_INFORMATION                = 0x00000008
         
     | 
| 
      
 13 
     | 
    
         
            +
                  LABEL_SECURITY_INFORMATION               = 0x00000010
         
     | 
| 
      
 14 
     | 
    
         
            +
                  UNPROTECTED_SACL_SECURITY_INFORMATION    = 0x10000000
         
     | 
| 
      
 15 
     | 
    
         
            +
                  UNPROTECTED_DACL_SECURITY_INFORMATION    = 0x20000000
         
     | 
| 
      
 16 
     | 
    
         
            +
                  PROTECTED_SACL_SECURITY_INFORMATION      = 0x40000000
         
     | 
| 
      
 17 
     | 
    
         
            +
                  PROTECTED_DACL_SECURITY_INFORMATION      = 0x80000000
         
     | 
| 
      
 18 
     | 
    
         
            +
                  ATTRIBUTE_SECURITY_INFORMATION           = 0x00000020
         
     | 
| 
      
 19 
     | 
    
         
            +
                  SCOPE_SECURITY_INFORMATION               = 0x00000040
         
     | 
| 
      
 20 
     | 
    
         
            +
                  PROCESS_TRUST_LABEL_SECURITY_INFORMATION = 0x00000080
         
     | 
| 
      
 21 
     | 
    
         
            +
                  BACKUP_SECURITY_INFORMATION              = 0x00010000
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
       6 
23 
     | 
    
         
             
                  endian  :little
         
     | 
| 
       7 
24 
     | 
    
         
             
                  uint8   :revision,  label: 'Revision', initial_value: 0x01
         
     | 
| 
       8 
25 
     | 
    
         
             
                  uint8   :sbz1,      label: 'Resource Manager Control Bits'
         
     | 
    
        data/lib/ruby_smb/version.rb
    CHANGED
    
    
| 
         @@ -1352,6 +1352,15 @@ RSpec.describe RubySMB::Dcerpc::Ndr::NdrVarString do 
     | 
|
| 
       1352 
1352 
     | 
    
         
             
                }
         
     | 
| 
       1353 
1353 
     | 
    
         
             
                let(:value) { 'ABCD' }
         
     | 
| 
       1354 
1354 
     | 
    
         
             
              end
         
     | 
| 
      
 1355 
     | 
    
         
            +
              context 'with an empty string' do
         
     | 
| 
      
 1356 
     | 
    
         
            +
                it_behaves_like 'a NDR String', conformant: false, char_size: 1, null_terminated: false do
         
     | 
| 
      
 1357 
     | 
    
         
            +
                  let(:binary_stream) {
         
     | 
| 
      
 1358 
     | 
    
         
            +
                    "\x00\x00\x00\x00"\
         
     | 
| 
      
 1359 
     | 
    
         
            +
                    "\x00\x00\x00\x00".b
         
     | 
| 
      
 1360 
     | 
    
         
            +
                  }
         
     | 
| 
      
 1361 
     | 
    
         
            +
                  let(:value) { '' }
         
     | 
| 
      
 1362 
     | 
    
         
            +
                end
         
     | 
| 
      
 1363 
     | 
    
         
            +
              end
         
     | 
| 
       1355 
1364 
     | 
    
         
             
            end
         
     | 
| 
       1356 
1365 
     | 
    
         | 
| 
       1357 
1366 
     | 
    
         
             
            RSpec.describe RubySMB::Dcerpc::Ndr::NdrVarStringz do
         
     | 
| 
         @@ -1368,6 +1377,16 @@ RSpec.describe RubySMB::Dcerpc::Ndr::NdrVarStringz do 
     | 
|
| 
       1368 
1377 
     | 
    
         
             
                }
         
     | 
| 
       1369 
1378 
     | 
    
         
             
                let(:value) { 'ABCD' }
         
     | 
| 
       1370 
1379 
     | 
    
         
             
              end
         
     | 
| 
      
 1380 
     | 
    
         
            +
              context 'with an empty string' do
         
     | 
| 
      
 1381 
     | 
    
         
            +
                it_behaves_like 'a NDR String', conformant: false, char_size: 1, null_terminated: true do
         
     | 
| 
      
 1382 
     | 
    
         
            +
                  let(:binary_stream) {
         
     | 
| 
      
 1383 
     | 
    
         
            +
                    "\x00\x00\x00\x00"\
         
     | 
| 
      
 1384 
     | 
    
         
            +
                    "\x01\x00\x00\x00"\
         
     | 
| 
      
 1385 
     | 
    
         
            +
                    "\x00".b
         
     | 
| 
      
 1386 
     | 
    
         
            +
                  }
         
     | 
| 
      
 1387 
     | 
    
         
            +
                  let(:value) { '' }
         
     | 
| 
      
 1388 
     | 
    
         
            +
                end
         
     | 
| 
      
 1389 
     | 
    
         
            +
              end
         
     | 
| 
       1371 
1390 
     | 
    
         
             
            end
         
     | 
| 
       1372 
1391 
     | 
    
         | 
| 
       1373 
1392 
     | 
    
         
             
            RSpec.describe RubySMB::Dcerpc::Ndr::NdrVarWideString do
         
     | 
| 
         @@ -1383,6 +1402,15 @@ RSpec.describe RubySMB::Dcerpc::Ndr::NdrVarWideString do 
     | 
|
| 
       1383 
1402 
     | 
    
         
             
                }
         
     | 
| 
       1384 
1403 
     | 
    
         
             
                let(:value) { 'ABCD'.encode('utf-16le') }
         
     | 
| 
       1385 
1404 
     | 
    
         
             
              end
         
     | 
| 
      
 1405 
     | 
    
         
            +
              context 'with an empty string' do
         
     | 
| 
      
 1406 
     | 
    
         
            +
                it_behaves_like 'a NDR String', conformant: false, char_size: 2, null_terminated: false do
         
     | 
| 
      
 1407 
     | 
    
         
            +
                  let(:binary_stream) {
         
     | 
| 
      
 1408 
     | 
    
         
            +
                    "\x00\x00\x00\x00"\
         
     | 
| 
      
 1409 
     | 
    
         
            +
                    "\x00\x00\x00\x00".b
         
     | 
| 
      
 1410 
     | 
    
         
            +
                  }
         
     | 
| 
      
 1411 
     | 
    
         
            +
                  let(:value) { '' }
         
     | 
| 
      
 1412 
     | 
    
         
            +
                end
         
     | 
| 
      
 1413 
     | 
    
         
            +
              end
         
     | 
| 
       1386 
1414 
     | 
    
         
             
            end
         
     | 
| 
       1387 
1415 
     | 
    
         | 
| 
       1388 
1416 
     | 
    
         
             
            RSpec.describe RubySMB::Dcerpc::Ndr::NdrVarWideStringz do
         
     | 
| 
         @@ -1398,6 +1426,16 @@ RSpec.describe RubySMB::Dcerpc::Ndr::NdrVarWideStringz do 
     | 
|
| 
       1398 
1426 
     | 
    
         
             
                }
         
     | 
| 
       1399 
1427 
     | 
    
         
             
                let(:value) { 'ABCD'.encode('utf-16le') }
         
     | 
| 
       1400 
1428 
     | 
    
         
             
              end
         
     | 
| 
      
 1429 
     | 
    
         
            +
              context 'with an empty string' do
         
     | 
| 
      
 1430 
     | 
    
         
            +
                it_behaves_like 'a NDR String', conformant: false, char_size: 2, null_terminated: true do
         
     | 
| 
      
 1431 
     | 
    
         
            +
                  let(:binary_stream) {
         
     | 
| 
      
 1432 
     | 
    
         
            +
                    "\x00\x00\x00\x00"\
         
     | 
| 
      
 1433 
     | 
    
         
            +
                    "\x01\x00\x00\x00"\
         
     | 
| 
      
 1434 
     | 
    
         
            +
                    "\x00\x00".b
         
     | 
| 
      
 1435 
     | 
    
         
            +
                  }
         
     | 
| 
      
 1436 
     | 
    
         
            +
                  let(:value) { '' }
         
     | 
| 
      
 1437 
     | 
    
         
            +
                end
         
     | 
| 
      
 1438 
     | 
    
         
            +
              end
         
     | 
| 
       1401 
1439 
     | 
    
         
             
            end
         
     | 
| 
       1402 
1440 
     | 
    
         | 
| 
       1403 
1441 
     | 
    
         
             
            RSpec.describe RubySMB::Dcerpc::Ndr::NdrConfVarString do
         
     | 
| 
         @@ -1415,6 +1453,16 @@ RSpec.describe RubySMB::Dcerpc::Ndr::NdrConfVarString do 
     | 
|
| 
       1415 
1453 
     | 
    
         
             
                }
         
     | 
| 
       1416 
1454 
     | 
    
         
             
                let(:value) { 'ABCD' }
         
     | 
| 
       1417 
1455 
     | 
    
         
             
              end
         
     | 
| 
      
 1456 
     | 
    
         
            +
              context 'with an empty string' do
         
     | 
| 
      
 1457 
     | 
    
         
            +
                it_behaves_like 'a NDR String', conformant: true, char_size: 1, null_terminated: false do
         
     | 
| 
      
 1458 
     | 
    
         
            +
                  let(:binary_stream) {
         
     | 
| 
      
 1459 
     | 
    
         
            +
                    "\x00\x00\x00\x00"\
         
     | 
| 
      
 1460 
     | 
    
         
            +
                    "\x00\x00\x00\x00"\
         
     | 
| 
      
 1461 
     | 
    
         
            +
                    "\x00\x00\x00\x00".b
         
     | 
| 
      
 1462 
     | 
    
         
            +
                  }
         
     | 
| 
      
 1463 
     | 
    
         
            +
                  let(:value) { '' }
         
     | 
| 
      
 1464 
     | 
    
         
            +
                end
         
     | 
| 
      
 1465 
     | 
    
         
            +
              end
         
     | 
| 
       1418 
1466 
     | 
    
         
             
            end
         
     | 
| 
       1419 
1467 
     | 
    
         | 
| 
       1420 
1468 
     | 
    
         
             
            RSpec.describe RubySMB::Dcerpc::Ndr::NdrConfVarStringz do
         
     | 
| 
         @@ -1432,6 +1480,17 @@ RSpec.describe RubySMB::Dcerpc::Ndr::NdrConfVarStringz do 
     | 
|
| 
       1432 
1480 
     | 
    
         
             
                }
         
     | 
| 
       1433 
1481 
     | 
    
         
             
                let(:value) { 'ABCD' }
         
     | 
| 
       1434 
1482 
     | 
    
         
             
              end
         
     | 
| 
      
 1483 
     | 
    
         
            +
              context 'with an empty string' do
         
     | 
| 
      
 1484 
     | 
    
         
            +
                it_behaves_like 'a NDR String', conformant: true, char_size: 1, null_terminated: true do
         
     | 
| 
      
 1485 
     | 
    
         
            +
                  let(:binary_stream) {
         
     | 
| 
      
 1486 
     | 
    
         
            +
                    "\x01\x00\x00\x00"\
         
     | 
| 
      
 1487 
     | 
    
         
            +
                    "\x00\x00\x00\x00"\
         
     | 
| 
      
 1488 
     | 
    
         
            +
                    "\x01\x00\x00\x00"\
         
     | 
| 
      
 1489 
     | 
    
         
            +
                    "\x00".b
         
     | 
| 
      
 1490 
     | 
    
         
            +
                  }
         
     | 
| 
      
 1491 
     | 
    
         
            +
                  let(:value) { '' }
         
     | 
| 
      
 1492 
     | 
    
         
            +
                end
         
     | 
| 
      
 1493 
     | 
    
         
            +
              end
         
     | 
| 
       1435 
1494 
     | 
    
         
             
            end
         
     | 
| 
       1436 
1495 
     | 
    
         | 
| 
       1437 
1496 
     | 
    
         
             
            RSpec.describe RubySMB::Dcerpc::Ndr::NdrConfVarWideString do
         
     | 
| 
         @@ -1448,6 +1507,16 @@ RSpec.describe RubySMB::Dcerpc::Ndr::NdrConfVarWideString do 
     | 
|
| 
       1448 
1507 
     | 
    
         
             
                }
         
     | 
| 
       1449 
1508 
     | 
    
         
             
                let(:value) { 'ABCD'.encode('utf-16le') }
         
     | 
| 
       1450 
1509 
     | 
    
         
             
              end
         
     | 
| 
      
 1510 
     | 
    
         
            +
              context 'with an empty string' do
         
     | 
| 
      
 1511 
     | 
    
         
            +
                it_behaves_like 'a NDR String', conformant: true, char_size: 2, null_terminated: false do
         
     | 
| 
      
 1512 
     | 
    
         
            +
                  let(:binary_stream) {
         
     | 
| 
      
 1513 
     | 
    
         
            +
                    "\x00\x00\x00\x00"\
         
     | 
| 
      
 1514 
     | 
    
         
            +
                    "\x00\x00\x00\x00"\
         
     | 
| 
      
 1515 
     | 
    
         
            +
                    "\x00\x00\x00\x00".b
         
     | 
| 
      
 1516 
     | 
    
         
            +
                  }
         
     | 
| 
      
 1517 
     | 
    
         
            +
                  let(:value) { '' }
         
     | 
| 
      
 1518 
     | 
    
         
            +
                end
         
     | 
| 
      
 1519 
     | 
    
         
            +
              end
         
     | 
| 
       1451 
1520 
     | 
    
         
             
            end
         
     | 
| 
       1452 
1521 
     | 
    
         | 
| 
       1453 
1522 
     | 
    
         
             
            RSpec.describe RubySMB::Dcerpc::Ndr::NdrConfVarWideStringz do
         
     | 
| 
         @@ -1464,6 +1533,17 @@ RSpec.describe RubySMB::Dcerpc::Ndr::NdrConfVarWideStringz do 
     | 
|
| 
       1464 
1533 
     | 
    
         
             
                }
         
     | 
| 
       1465 
1534 
     | 
    
         
             
                let(:value) { 'ABCD'.encode('utf-16le') }
         
     | 
| 
       1466 
1535 
     | 
    
         
             
              end
         
     | 
| 
      
 1536 
     | 
    
         
            +
              context 'with an empty string' do
         
     | 
| 
      
 1537 
     | 
    
         
            +
                it_behaves_like 'a NDR String', conformant: true, char_size: 1, null_terminated: true do
         
     | 
| 
      
 1538 
     | 
    
         
            +
                  let(:binary_stream) {
         
     | 
| 
      
 1539 
     | 
    
         
            +
                    "\x01\x00\x00\x00"\
         
     | 
| 
      
 1540 
     | 
    
         
            +
                    "\x00\x00\x00\x00"\
         
     | 
| 
      
 1541 
     | 
    
         
            +
                    "\x01\x00\x00\x00"\
         
     | 
| 
      
 1542 
     | 
    
         
            +
                    "\x00\x00".b
         
     | 
| 
      
 1543 
     | 
    
         
            +
                  }
         
     | 
| 
      
 1544 
     | 
    
         
            +
                  let(:value) { '' }
         
     | 
| 
      
 1545 
     | 
    
         
            +
                end
         
     | 
| 
      
 1546 
     | 
    
         
            +
              end
         
     | 
| 
       1467 
1547 
     | 
    
         
             
            end
         
     | 
| 
       1468 
1548 
     | 
    
         | 
| 
       1469 
1549 
     | 
    
         | 
| 
         @@ -73,12 +73,7 @@ RSpec.describe RubySMB::Dcerpc::Winreg do 
     | 
|
| 
       73 
73 
     | 
    
         
             
                before :example do
         
     | 
| 
       74 
74 
     | 
    
         
             
                  allow(described_class::OpenKeyRequest).to receive(:new).and_return(openkey_request_packet)
         
     | 
| 
       75 
75 
     | 
    
         
             
                  allow(openkey_request_packet).to receive(:sam_desired).and_return(regsam)
         
     | 
| 
       76 
     | 
    
         
            -
                  allow(regsam).to  
     | 
| 
       77 
     | 
    
         
            -
                    :read_control=           => nil,
         
     | 
| 
       78 
     | 
    
         
            -
                    :key_query_value=        => nil,
         
     | 
| 
       79 
     | 
    
         
            -
                    :key_enumerate_sub_keys= => nil,
         
     | 
| 
       80 
     | 
    
         
            -
                    :key_notify=             => nil,
         
     | 
| 
       81 
     | 
    
         
            -
                  )
         
     | 
| 
      
 76 
     | 
    
         
            +
                  allow(regsam).to receive(:maximum_allowed=)
         
     | 
| 
       82 
77 
     | 
    
         
             
                  allow(winreg).to receive(:dcerpc_request).and_return(response)
         
     | 
| 
       83 
78 
     | 
    
         
             
                  allow(described_class::OpenKeyResponse).to receive(:read).and_return(open_key_response)
         
     | 
| 
       84 
79 
     | 
    
         
             
                  allow(open_key_response).to receive_messages(
         
     | 
| 
         @@ -94,10 +89,7 @@ RSpec.describe RubySMB::Dcerpc::Winreg do 
     | 
|
| 
       94 
89 
     | 
    
         | 
| 
       95 
90 
     | 
    
         
             
                it 'sets the expected user rights on the request packet' do
         
     | 
| 
       96 
91 
     | 
    
         
             
                  winreg.open_key(handle, sub_key)
         
     | 
| 
       97 
     | 
    
         
            -
                  expect(regsam).to have_received(: 
     | 
| 
       98 
     | 
    
         
            -
                  expect(regsam).to have_received(:key_query_value=).with(1)
         
     | 
| 
       99 
     | 
    
         
            -
                  expect(regsam).to have_received(:key_enumerate_sub_keys=).with(1)
         
     | 
| 
       100 
     | 
    
         
            -
                  expect(regsam).to have_received(:key_notify=).with(1)
         
     | 
| 
      
 92 
     | 
    
         
            +
                  expect(regsam).to have_received(:maximum_allowed=).with(1)
         
     | 
| 
       101 
93 
     | 
    
         
             
                end
         
     | 
| 
       102 
94 
     | 
    
         | 
| 
       103 
95 
     | 
    
         
             
                it 'sends the expected dcerpc request' do
         
     | 
| 
         @@ -132,12 +124,13 @@ RSpec.describe RubySMB::Dcerpc::Winreg do 
     | 
|
| 
       132 
124 
     | 
    
         
             
              describe '#query_value' do
         
     | 
| 
       133 
125 
     | 
    
         
             
                let(:handle)                      { double('Handle') }
         
     | 
| 
       134 
126 
     | 
    
         
             
                let(:value_name)                  { double('Value Name') }
         
     | 
| 
       135 
     | 
    
         
            -
                let(:query_value_request_packet) 
     | 
| 
       136 
     | 
    
         
            -
                let(:lp_data) 
     | 
| 
      
 127 
     | 
    
         
            +
                let(:query_value_request_packet)  { double('Query Value Request Packet #1') }
         
     | 
| 
      
 128 
     | 
    
         
            +
                let(:lp_data)                     { double('LpData #2') }
         
     | 
| 
       137 
129 
     | 
    
         
             
                let(:response1)                   { double('Response #1') }
         
     | 
| 
       138 
130 
     | 
    
         
             
                let(:response2)                   { double('Response #2') }
         
     | 
| 
       139 
131 
     | 
    
         
             
                let(:query_value_response1)       { double('Query Value Response #1') }
         
     | 
| 
       140 
132 
     | 
    
         
             
                let(:query_value_response2)       { double('Query Value Response #2') }
         
     | 
| 
      
 133 
     | 
    
         
            +
                let(:lp_type)                     { double('Type') }
         
     | 
| 
       141 
134 
     | 
    
         
             
                let(:data)                        { double('Data') }
         
     | 
| 
       142 
135 
     | 
    
         
             
                let(:lpcb_data)                   { double('LpcbData') }
         
     | 
| 
       143 
136 
     | 
    
         
             
                let(:max_count)                   { 5 }
         
     | 
| 
         @@ -164,8 +157,9 @@ RSpec.describe RubySMB::Dcerpc::Winreg do 
     | 
|
| 
       164 
157 
     | 
    
         
             
                  allow(described_class::QueryValueResponse).to receive(:read).with(response2).and_return(query_value_response2)
         
     | 
| 
       165 
158 
     | 
    
         
             
                  allow(query_value_response1).to receive(:error_status).and_return(WindowsError::Win32::ERROR_SUCCESS)
         
     | 
| 
       166 
159 
     | 
    
         
             
                  allow(query_value_response2).to receive_messages(
         
     | 
| 
       167 
     | 
    
         
            -
                    : 
     | 
| 
       168 
     | 
    
         
            -
                    : 
     | 
| 
      
 160 
     | 
    
         
            +
                    error_status: WindowsError::Win32::ERROR_SUCCESS,
         
     | 
| 
      
 161 
     | 
    
         
            +
                    lp_type:      lp_type,
         
     | 
| 
      
 162 
     | 
    
         
            +
                    data:         data
         
     | 
| 
       169 
163 
     | 
    
         
             
                  )
         
     | 
| 
       170 
164 
     | 
    
         
             
                  allow(query_value_response1).to receive(:lpcb_data).and_return(lpcb_data)
         
     | 
| 
       171 
165 
     | 
    
         
             
                  allow(lpcb_data).to receive(:to_i).and_return(max_count)
         
     | 
| 
         @@ -234,8 +228,9 @@ RSpec.describe RubySMB::Dcerpc::Winreg do 
     | 
|
| 
       234 
228 
     | 
    
         
             
                end
         
     | 
| 
       235 
229 
     | 
    
         | 
| 
       236 
230 
     | 
    
         
             
                it 'returns the expected response data' do
         
     | 
| 
       237 
     | 
    
         
            -
                  expect(winreg.query_value(handle, value_name)).to eq(data)
         
     | 
| 
      
 231 
     | 
    
         
            +
                  expect(winreg.query_value(handle, value_name)).to eq(RubySMB::Dcerpc::Winreg::RegValue.new(lp_type, data))
         
     | 
| 
       238 
232 
     | 
    
         
             
                end
         
     | 
| 
      
 233 
     | 
    
         
            +
             
     | 
| 
       239 
234 
     | 
    
         
             
              end
         
     | 
| 
       240 
235 
     | 
    
         | 
| 
       241 
236 
     | 
    
         
             
              describe '#close_key' do
         
     | 
| 
         @@ -529,13 +524,14 @@ RSpec.describe RubySMB::Dcerpc::Winreg do 
     | 
|
| 
       529 
524 
     | 
    
         
             
                let(:value_name)      { 'registry_value_name' }
         
     | 
| 
       530 
525 
     | 
    
         
             
                let(:root_key_handle) { double('Root Key Handle') }
         
     | 
| 
       531 
526 
     | 
    
         
             
                let(:subkey_handle)   { double('Subkey Handle') }
         
     | 
| 
       532 
     | 
    
         
            -
                let(: 
     | 
| 
      
 527 
     | 
    
         
            +
                let(:data)            { double('Reg value data') }
         
     | 
| 
      
 528 
     | 
    
         
            +
                let(:reg_value)       { RubySMB::Dcerpc::Winreg::RegValue.new(nil, data) }
         
     | 
| 
       533 
529 
     | 
    
         
             
                before :example do
         
     | 
| 
       534 
530 
     | 
    
         
             
                  allow(winreg).to receive_messages(
         
     | 
| 
       535 
531 
     | 
    
         
             
                    :bind          => nil,
         
     | 
| 
       536 
532 
     | 
    
         
             
                    :open_root_key => root_key_handle,
         
     | 
| 
       537 
533 
     | 
    
         
             
                    :open_key      => subkey_handle,
         
     | 
| 
       538 
     | 
    
         
            -
                    :query_value   =>  
     | 
| 
      
 534 
     | 
    
         
            +
                    :query_value   => reg_value,
         
     | 
| 
       539 
535 
     | 
    
         
             
                    :close_key     => nil
         
     | 
| 
       540 
536 
     | 
    
         
             
                  )
         
     | 
| 
       541 
537 
     | 
    
         
             
                end
         
     | 
| 
         @@ -572,7 +568,7 @@ RSpec.describe RubySMB::Dcerpc::Winreg do 
     | 
|
| 
       572 
568 
     | 
    
         
             
                end
         
     | 
| 
       573 
569 
     | 
    
         | 
| 
       574 
570 
     | 
    
         
             
                it 'returns expect registry key value' do
         
     | 
| 
       575 
     | 
    
         
            -
                  expect(winreg.read_registry_key_value(key, value_name)).to eq( 
     | 
| 
      
 571 
     | 
    
         
            +
                  expect(winreg.read_registry_key_value(key, value_name)).to eq(data)
         
     | 
| 
       576 
572 
     | 
    
         
             
                end
         
     | 
| 
       577 
573 
     | 
    
         
             
              end
         
     | 
| 
       578 
574 
     | 
    
         | 
| 
         @@ -864,4 +860,257 @@ RSpec.describe RubySMB::Dcerpc::Winreg do 
     | 
|
| 
       864 
860 
     | 
    
         
             
                  end
         
     | 
| 
       865 
861 
     | 
    
         
             
                end
         
     | 
| 
       866 
862 
     | 
    
         
             
              end
         
     | 
| 
      
 863 
     | 
    
         
            +
             
     | 
| 
      
 864 
     | 
    
         
            +
              describe '#get_key_security_descriptor' do
         
     | 
| 
      
 865 
     | 
    
         
            +
                let(:root_key)                  { 'HKLM' }
         
     | 
| 
      
 866 
     | 
    
         
            +
                let(:sub_key)                   { 'my\\sub\\key\\path' }
         
     | 
| 
      
 867 
     | 
    
         
            +
                let(:key)                       { "#{root_key}\\#{sub_key}" }
         
     | 
| 
      
 868 
     | 
    
         
            +
                let(:root_key_handle)           { double('Root Key Handle') }
         
     | 
| 
      
 869 
     | 
    
         
            +
                let(:subkey_handle)             { double('Subkey Handle') }
         
     | 
| 
      
 870 
     | 
    
         
            +
                before :example do
         
     | 
| 
      
 871 
     | 
    
         
            +
                  allow(winreg).to receive_messages(
         
     | 
| 
      
 872 
     | 
    
         
            +
                    :bind           => nil,
         
     | 
| 
      
 873 
     | 
    
         
            +
                    :open_root_key  => root_key_handle,
         
     | 
| 
      
 874 
     | 
    
         
            +
                    :open_key       => subkey_handle,
         
     | 
| 
      
 875 
     | 
    
         
            +
                    :get_key_security => nil,
         
     | 
| 
      
 876 
     | 
    
         
            +
                    :close_key      => nil
         
     | 
| 
      
 877 
     | 
    
         
            +
                  )
         
     | 
| 
      
 878 
     | 
    
         
            +
                end
         
     | 
| 
      
 879 
     | 
    
         
            +
             
     | 
| 
      
 880 
     | 
    
         
            +
                it 'binds a DCERPC connection to the expected remote endpoint' do
         
     | 
| 
      
 881 
     | 
    
         
            +
                  winreg.get_key_security_descriptor(key)
         
     | 
| 
      
 882 
     | 
    
         
            +
                  expect(winreg).to have_received(:bind).with(endpoint: RubySMB::Dcerpc::Winreg)
         
     | 
| 
      
 883 
     | 
    
         
            +
                end
         
     | 
| 
      
 884 
     | 
    
         
            +
             
     | 
| 
      
 885 
     | 
    
         
            +
                it 'does not bind a DCERPC connection if #bind argument is false' do
         
     | 
| 
      
 886 
     | 
    
         
            +
                  winreg.get_key_security_descriptor(key, bind: false)
         
     | 
| 
      
 887 
     | 
    
         
            +
                  expect(winreg).to_not have_received(:bind)
         
     | 
| 
      
 888 
     | 
    
         
            +
                end
         
     | 
| 
      
 889 
     | 
    
         
            +
             
     | 
| 
      
 890 
     | 
    
         
            +
                it 'opens the expected root key' do
         
     | 
| 
      
 891 
     | 
    
         
            +
                  winreg.get_key_security_descriptor(key)
         
     | 
| 
      
 892 
     | 
    
         
            +
                  expect(winreg).to have_received(:open_root_key).with(root_key)
         
     | 
| 
      
 893 
     | 
    
         
            +
                end
         
     | 
| 
      
 894 
     | 
    
         
            +
             
     | 
| 
      
 895 
     | 
    
         
            +
                it 'opens the expected registry key' do
         
     | 
| 
      
 896 
     | 
    
         
            +
                  winreg.get_key_security_descriptor(key)
         
     | 
| 
      
 897 
     | 
    
         
            +
                  expect(winreg).to have_received(:open_key).with(root_key_handle, sub_key)
         
     | 
| 
      
 898 
     | 
    
         
            +
                end
         
     | 
| 
      
 899 
     | 
    
         
            +
             
     | 
| 
      
 900 
     | 
    
         
            +
                it 'calls #get_key_security with the expected arguments' do
         
     | 
| 
      
 901 
     | 
    
         
            +
                  winreg.get_key_security_descriptor(key)
         
     | 
| 
      
 902 
     | 
    
         
            +
                  security_information = RubySMB::Field::SecurityDescriptor::OWNER_SECURITY_INFORMATION
         
     | 
| 
      
 903 
     | 
    
         
            +
                  expect(winreg).to have_received(:get_key_security).with(subkey_handle, security_information)
         
     | 
| 
      
 904 
     | 
    
         
            +
                end
         
     | 
| 
      
 905 
     | 
    
         
            +
             
     | 
| 
      
 906 
     | 
    
         
            +
                context 'with a non-default security informaiton' do
         
     | 
| 
      
 907 
     | 
    
         
            +
                  it 'calls #get_key_security with the expected arguments' do
         
     | 
| 
      
 908 
     | 
    
         
            +
                    security_information = RubySMB::Field::SecurityDescriptor::GROUP_SECURITY_INFORMATION
         
     | 
| 
      
 909 
     | 
    
         
            +
                    winreg.get_key_security_descriptor(key, security_information)
         
     | 
| 
      
 910 
     | 
    
         
            +
                    expect(winreg).to have_received(:get_key_security).with(subkey_handle, security_information)
         
     | 
| 
      
 911 
     | 
    
         
            +
                  end
         
     | 
| 
      
 912 
     | 
    
         
            +
                end
         
     | 
| 
      
 913 
     | 
    
         
            +
              end
         
     | 
| 
      
 914 
     | 
    
         
            +
             
     | 
| 
      
 915 
     | 
    
         
            +
              describe '#get_key_security' do
         
     | 
| 
      
 916 
     | 
    
         
            +
                let(:handle)                    { double('Handle') }
         
     | 
| 
      
 917 
     | 
    
         
            +
                let(:get_key_security_request)  { double('GetKeySecurity Request') }
         
     | 
| 
      
 918 
     | 
    
         
            +
                let(:response)                  {
         
     | 
| 
      
 919 
     | 
    
         
            +
                  '0000020000100000940000000010000000000000940000000100048078000000880000'\
         
     | 
| 
      
 920 
     | 
    
         
            +
                  '0000000000140000000200640004000000000214003f000f0001010000000000051200'\
         
     | 
| 
      
 921 
     | 
    
         
            +
                  '0000000218000000060001020000000000052000000020020000000218000900060001'\
         
     | 
| 
      
 922 
     | 
    
         
            +
                  '0200000000000520000000200200000002180009000600010200000000000520000000'\
         
     | 
| 
      
 923 
     | 
    
         
            +
                  '2002000001020000000000052000000020020000010100000000000512000000000000'\
         
     | 
| 
      
 924 
     | 
    
         
            +
                  '00'.unhexlify
         
     | 
| 
      
 925 
     | 
    
         
            +
                }
         
     | 
| 
      
 926 
     | 
    
         
            +
                let(:security_descriptor) {
         
     | 
| 
      
 927 
     | 
    
         
            +
                  '01000480780000008800000000000000140000000200640004000000000214003f000f'\
         
     | 
| 
      
 928 
     | 
    
         
            +
                  '0001010000000000051200000000021800000006000102000000000005200000002002'\
         
     | 
| 
      
 929 
     | 
    
         
            +
                  '0000000218000900060001020000000000052000000020020000000218000900060001'\
         
     | 
| 
      
 930 
     | 
    
         
            +
                  '0200000000000520000000200200000102000000000005200000002002000001010000'\
         
     | 
| 
      
 931 
     | 
    
         
            +
                  '0000000512000000'.unhexlify
         
     | 
| 
      
 932 
     | 
    
         
            +
                }
         
     | 
| 
      
 933 
     | 
    
         
            +
                before :example do
         
     | 
| 
      
 934 
     | 
    
         
            +
                  allow(described_class::GetKeySecurityRequest).to receive(:new).and_return(get_key_security_request)
         
     | 
| 
      
 935 
     | 
    
         
            +
                  allow(winreg).to receive(:dcerpc_request).and_return(response)
         
     | 
| 
      
 936 
     | 
    
         
            +
                end
         
     | 
| 
      
 937 
     | 
    
         
            +
             
     | 
| 
      
 938 
     | 
    
         
            +
                it 'create the expected GetKeySecurityRequest packet with the default options' do
         
     | 
| 
      
 939 
     | 
    
         
            +
                  opts = {
         
     | 
| 
      
 940 
     | 
    
         
            +
                    hkey:                   handle,
         
     | 
| 
      
 941 
     | 
    
         
            +
                    security_information:   RubySMB::Field::SecurityDescriptor::OWNER_SECURITY_INFORMATION,
         
     | 
| 
      
 942 
     | 
    
         
            +
                    prpc_security_descriptor_in: { cb_in_security_descriptor: 4096 }
         
     | 
| 
      
 943 
     | 
    
         
            +
                  }
         
     | 
| 
      
 944 
     | 
    
         
            +
                  winreg.get_key_security(handle)
         
     | 
| 
      
 945 
     | 
    
         
            +
                  expect(described_class::GetKeySecurityRequest).to have_received(:new).with(opts)
         
     | 
| 
      
 946 
     | 
    
         
            +
                end
         
     | 
| 
      
 947 
     | 
    
         
            +
             
     | 
| 
      
 948 
     | 
    
         
            +
                it 'create the expected SaveKeyRequest packet with custom options' do
         
     | 
| 
      
 949 
     | 
    
         
            +
                  security_information = RubySMB::Field::SecurityDescriptor::GROUP_SECURITY_INFORMATION
         
     | 
| 
      
 950 
     | 
    
         
            +
                  opts = {
         
     | 
| 
      
 951 
     | 
    
         
            +
                    hkey:                   handle,
         
     | 
| 
      
 952 
     | 
    
         
            +
                    security_information:   security_information,
         
     | 
| 
      
 953 
     | 
    
         
            +
                    prpc_security_descriptor_in: { cb_in_security_descriptor: 4096 }
         
     | 
| 
      
 954 
     | 
    
         
            +
                  }
         
     | 
| 
      
 955 
     | 
    
         
            +
                  winreg.get_key_security(handle, security_information)
         
     | 
| 
      
 956 
     | 
    
         
            +
                  expect(described_class::GetKeySecurityRequest).to have_received(:new).with(opts)
         
     | 
| 
      
 957 
     | 
    
         
            +
                end
         
     | 
| 
      
 958 
     | 
    
         
            +
             
     | 
| 
      
 959 
     | 
    
         
            +
                it 'sends the expected dcerpc request' do
         
     | 
| 
      
 960 
     | 
    
         
            +
                  winreg.get_key_security(handle)
         
     | 
| 
      
 961 
     | 
    
         
            +
                  expect(winreg).to have_received(:dcerpc_request).with(get_key_security_request)
         
     | 
| 
      
 962 
     | 
    
         
            +
                end
         
     | 
| 
      
 963 
     | 
    
         
            +
             
     | 
| 
      
 964 
     | 
    
         
            +
                it 'creates a GetKeySecurityResponse structure from the expected dcerpc response' do
         
     | 
| 
      
 965 
     | 
    
         
            +
                  expect(described_class::GetKeySecurityResponse).to receive(:read).with(response).and_call_original
         
     | 
| 
      
 966 
     | 
    
         
            +
                  winreg.get_key_security(handle)
         
     | 
| 
      
 967 
     | 
    
         
            +
                end
         
     | 
| 
      
 968 
     | 
    
         
            +
             
     | 
| 
      
 969 
     | 
    
         
            +
                context 'when an IOError occurs while parsing the response' do
         
     | 
| 
      
 970 
     | 
    
         
            +
                  it 'raises a RubySMB::Dcerpc::Error::InvalidPacket' do
         
     | 
| 
      
 971 
     | 
    
         
            +
                    allow(described_class::GetKeySecurityResponse).to receive(:read).and_raise(IOError)
         
     | 
| 
      
 972 
     | 
    
         
            +
                    expect { winreg.get_key_security(handle) }.to raise_error(RubySMB::Dcerpc::Error::InvalidPacket)
         
     | 
| 
      
 973 
     | 
    
         
            +
                  end
         
     | 
| 
      
 974 
     | 
    
         
            +
                end
         
     | 
| 
      
 975 
     | 
    
         
            +
             
     | 
| 
      
 976 
     | 
    
         
            +
                context 'when the response error status is not WindowsError::Win32::ERROR_SUCCESS' do
         
     | 
| 
      
 977 
     | 
    
         
            +
                  it 'raises a RubySMB::Dcerpc::Error::WinregError' do
         
     | 
| 
      
 978 
     | 
    
         
            +
                    response[-4..-1] = [WindowsError::Win32::ERROR_INVALID_DATA.value].pack('V')
         
     | 
| 
      
 979 
     | 
    
         
            +
                    expect { winreg.get_key_security(handle) }.to raise_error(RubySMB::Dcerpc::Error::WinregError)
         
     | 
| 
      
 980 
     | 
    
         
            +
                  end
         
     | 
| 
      
 981 
     | 
    
         
            +
                end
         
     | 
| 
      
 982 
     | 
    
         
            +
             
     | 
| 
      
 983 
     | 
    
         
            +
                it 'returns the expected security descriptor' do
         
     | 
| 
      
 984 
     | 
    
         
            +
                  expect(winreg.get_key_security(handle)).to eq(security_descriptor)
         
     | 
| 
      
 985 
     | 
    
         
            +
                end
         
     | 
| 
      
 986 
     | 
    
         
            +
              end
         
     | 
| 
      
 987 
     | 
    
         
            +
             
     | 
| 
      
 988 
     | 
    
         
            +
              describe '#set_key_security_descriptor' do
         
     | 
| 
      
 989 
     | 
    
         
            +
                let(:root_key)                  { 'HKLM' }
         
     | 
| 
      
 990 
     | 
    
         
            +
                let(:sub_key)                   { 'my\\sub\\key\\path' }
         
     | 
| 
      
 991 
     | 
    
         
            +
                let(:key)                       { "#{root_key}\\#{sub_key}" }
         
     | 
| 
      
 992 
     | 
    
         
            +
                let(:security_descriptor)       { 'Security Descriptor' }
         
     | 
| 
      
 993 
     | 
    
         
            +
                let(:root_key_handle)           { double('Root Key Handle') }
         
     | 
| 
      
 994 
     | 
    
         
            +
                let(:subkey_handle)             { double('Subkey Handle') }
         
     | 
| 
      
 995 
     | 
    
         
            +
                before :example do
         
     | 
| 
      
 996 
     | 
    
         
            +
                  allow(winreg).to receive_messages(
         
     | 
| 
      
 997 
     | 
    
         
            +
                    :bind           => nil,
         
     | 
| 
      
 998 
     | 
    
         
            +
                    :open_root_key  => root_key_handle,
         
     | 
| 
      
 999 
     | 
    
         
            +
                    :open_key       => subkey_handle,
         
     | 
| 
      
 1000 
     | 
    
         
            +
                    :set_key_security => nil,
         
     | 
| 
      
 1001 
     | 
    
         
            +
                    :close_key      => nil
         
     | 
| 
      
 1002 
     | 
    
         
            +
                  )
         
     | 
| 
      
 1003 
     | 
    
         
            +
                end
         
     | 
| 
      
 1004 
     | 
    
         
            +
             
     | 
| 
      
 1005 
     | 
    
         
            +
                it 'binds a DCERPC connection to the expected remote endpoint' do
         
     | 
| 
      
 1006 
     | 
    
         
            +
                  winreg.set_key_security_descriptor(key, security_descriptor)
         
     | 
| 
      
 1007 
     | 
    
         
            +
                  expect(winreg).to have_received(:bind).with(endpoint: RubySMB::Dcerpc::Winreg)
         
     | 
| 
      
 1008 
     | 
    
         
            +
                end
         
     | 
| 
      
 1009 
     | 
    
         
            +
             
     | 
| 
      
 1010 
     | 
    
         
            +
                it 'does not bind a DCERPC connection if #bind argument is false' do
         
     | 
| 
      
 1011 
     | 
    
         
            +
                  winreg.set_key_security_descriptor(key, security_descriptor, bind: false)
         
     | 
| 
      
 1012 
     | 
    
         
            +
                  expect(winreg).to_not have_received(:bind)
         
     | 
| 
      
 1013 
     | 
    
         
            +
                end
         
     | 
| 
      
 1014 
     | 
    
         
            +
             
     | 
| 
      
 1015 
     | 
    
         
            +
                it 'opens the expected root key' do
         
     | 
| 
      
 1016 
     | 
    
         
            +
                  winreg.set_key_security_descriptor(key, security_descriptor)
         
     | 
| 
      
 1017 
     | 
    
         
            +
                  expect(winreg).to have_received(:open_root_key).with(root_key)
         
     | 
| 
      
 1018 
     | 
    
         
            +
                end
         
     | 
| 
      
 1019 
     | 
    
         
            +
             
     | 
| 
      
 1020 
     | 
    
         
            +
                it 'opens the expected registry key' do
         
     | 
| 
      
 1021 
     | 
    
         
            +
                  winreg.set_key_security_descriptor(key, security_descriptor)
         
     | 
| 
      
 1022 
     | 
    
         
            +
                  expect(winreg).to have_received(:open_key).with(root_key_handle, sub_key)
         
     | 
| 
      
 1023 
     | 
    
         
            +
                end
         
     | 
| 
      
 1024 
     | 
    
         
            +
             
     | 
| 
      
 1025 
     | 
    
         
            +
                it 'calls #set_key_security with the expected arguments' do
         
     | 
| 
      
 1026 
     | 
    
         
            +
                  winreg.set_key_security_descriptor(key, security_descriptor)
         
     | 
| 
      
 1027 
     | 
    
         
            +
                  security_information = RubySMB::Field::SecurityDescriptor::OWNER_SECURITY_INFORMATION
         
     | 
| 
      
 1028 
     | 
    
         
            +
                  expect(winreg).to have_received(:set_key_security).with(subkey_handle, security_descriptor, security_information)
         
     | 
| 
      
 1029 
     | 
    
         
            +
                end
         
     | 
| 
      
 1030 
     | 
    
         
            +
             
     | 
| 
      
 1031 
     | 
    
         
            +
                context 'with a non-default security informaiton' do
         
     | 
| 
      
 1032 
     | 
    
         
            +
                  it 'calls #get_key_security with the expected arguments' do
         
     | 
| 
      
 1033 
     | 
    
         
            +
                    security_information = RubySMB::Field::SecurityDescriptor::GROUP_SECURITY_INFORMATION
         
     | 
| 
      
 1034 
     | 
    
         
            +
                    winreg.set_key_security_descriptor(key, security_descriptor, security_information)
         
     | 
| 
      
 1035 
     | 
    
         
            +
                    expect(winreg).to have_received(:set_key_security).with(subkey_handle, security_descriptor, security_information)
         
     | 
| 
      
 1036 
     | 
    
         
            +
                  end
         
     | 
| 
      
 1037 
     | 
    
         
            +
                end
         
     | 
| 
      
 1038 
     | 
    
         
            +
              end
         
     | 
| 
      
 1039 
     | 
    
         
            +
             
     | 
| 
      
 1040 
     | 
    
         
            +
              describe '#set_key_security' do
         
     | 
| 
      
 1041 
     | 
    
         
            +
                let(:handle)                    { double('Handle') }
         
     | 
| 
      
 1042 
     | 
    
         
            +
                let(:set_key_security_request)  { double('GetKeySecurity Request') }
         
     | 
| 
      
 1043 
     | 
    
         
            +
                let(:response)                  { '00000000'.unhexlify }
         
     | 
| 
      
 1044 
     | 
    
         
            +
                let(:security_descriptor) {
         
     | 
| 
      
 1045 
     | 
    
         
            +
                  '0100048014000000240000000000000030000000010200000000000520000000200200'\
         
     | 
| 
      
 1046 
     | 
    
         
            +
                  '0001010000000000051200000002007c0005000000000214003f000f00010100000000'\
         
     | 
| 
      
 1047 
     | 
    
         
            +
                  '0005120000000002180000000600010200000000000520000000200200000002180009'\
         
     | 
| 
      
 1048 
     | 
    
         
            +
                  '0006000102000000000005200000002002000000021800090006000102000000000005'\
         
     | 
| 
      
 1049 
     | 
    
         
            +
                  '2000000020020000000218000900060001020000000000052000000020020000'.unhexlify
         
     | 
| 
      
 1050 
     | 
    
         
            +
                }
         
     | 
| 
      
 1051 
     | 
    
         
            +
                before :example do
         
     | 
| 
      
 1052 
     | 
    
         
            +
                  allow(described_class::SetKeySecurityRequest).to receive(:new).and_return(set_key_security_request)
         
     | 
| 
      
 1053 
     | 
    
         
            +
                  allow(winreg).to receive(:dcerpc_request).and_return(response)
         
     | 
| 
      
 1054 
     | 
    
         
            +
                end
         
     | 
| 
      
 1055 
     | 
    
         
            +
             
     | 
| 
      
 1056 
     | 
    
         
            +
                it 'create the expected SetKeySecurityRequest packet with the default options' do
         
     | 
| 
      
 1057 
     | 
    
         
            +
                  opts = {
         
     | 
| 
      
 1058 
     | 
    
         
            +
                    hkey: handle,
         
     | 
| 
      
 1059 
     | 
    
         
            +
                    security_information: RubySMB::Field::SecurityDescriptor::OWNER_SECURITY_INFORMATION,
         
     | 
| 
      
 1060 
     | 
    
         
            +
                    prpc_security_descriptor: {
         
     | 
| 
      
 1061 
     | 
    
         
            +
                      lp_security_descriptor: security_descriptor.bytes,
         
     | 
| 
      
 1062 
     | 
    
         
            +
                      cb_in_security_descriptor: security_descriptor.size,
         
     | 
| 
      
 1063 
     | 
    
         
            +
                      cb_out_security_descriptor: security_descriptor.size
         
     | 
| 
      
 1064 
     | 
    
         
            +
                    }
         
     | 
| 
      
 1065 
     | 
    
         
            +
                  }
         
     | 
| 
      
 1066 
     | 
    
         
            +
                  winreg.set_key_security(handle, security_descriptor)
         
     | 
| 
      
 1067 
     | 
    
         
            +
                  expect(described_class::SetKeySecurityRequest).to have_received(:new).with(opts)
         
     | 
| 
      
 1068 
     | 
    
         
            +
                end
         
     | 
| 
      
 1069 
     | 
    
         
            +
             
     | 
| 
      
 1070 
     | 
    
         
            +
                it 'create the expected SaveKeyRequest packet with custom options' do
         
     | 
| 
      
 1071 
     | 
    
         
            +
                  security_information = RubySMB::Field::SecurityDescriptor::GROUP_SECURITY_INFORMATION
         
     | 
| 
      
 1072 
     | 
    
         
            +
                  opts = {
         
     | 
| 
      
 1073 
     | 
    
         
            +
                    hkey:                   handle,
         
     | 
| 
      
 1074 
     | 
    
         
            +
                    security_information:   security_information,
         
     | 
| 
      
 1075 
     | 
    
         
            +
                    prpc_security_descriptor: {
         
     | 
| 
      
 1076 
     | 
    
         
            +
                      lp_security_descriptor: security_descriptor.bytes,
         
     | 
| 
      
 1077 
     | 
    
         
            +
                      cb_in_security_descriptor: security_descriptor.size,
         
     | 
| 
      
 1078 
     | 
    
         
            +
                      cb_out_security_descriptor: security_descriptor.size
         
     | 
| 
      
 1079 
     | 
    
         
            +
                    }
         
     | 
| 
      
 1080 
     | 
    
         
            +
                  }
         
     | 
| 
      
 1081 
     | 
    
         
            +
                  winreg.set_key_security(handle, security_descriptor, security_information)
         
     | 
| 
      
 1082 
     | 
    
         
            +
                  expect(described_class::SetKeySecurityRequest).to have_received(:new).with(opts)
         
     | 
| 
      
 1083 
     | 
    
         
            +
                end
         
     | 
| 
      
 1084 
     | 
    
         
            +
             
     | 
| 
      
 1085 
     | 
    
         
            +
                it 'sends the expected dcerpc request' do
         
     | 
| 
      
 1086 
     | 
    
         
            +
                  winreg.set_key_security(handle, security_descriptor)
         
     | 
| 
      
 1087 
     | 
    
         
            +
                  expect(winreg).to have_received(:dcerpc_request).with(set_key_security_request)
         
     | 
| 
      
 1088 
     | 
    
         
            +
                end
         
     | 
| 
      
 1089 
     | 
    
         
            +
             
     | 
| 
      
 1090 
     | 
    
         
            +
                it 'creates a SetKeySecurityResponse structure from the expected dcerpc response' do
         
     | 
| 
      
 1091 
     | 
    
         
            +
                  expect(described_class::SetKeySecurityResponse).to receive(:read).with(response).and_call_original
         
     | 
| 
      
 1092 
     | 
    
         
            +
                  winreg.set_key_security(handle, security_descriptor)
         
     | 
| 
      
 1093 
     | 
    
         
            +
                end
         
     | 
| 
      
 1094 
     | 
    
         
            +
             
     | 
| 
      
 1095 
     | 
    
         
            +
                context 'when an IOError occurs while parsing the response' do
         
     | 
| 
      
 1096 
     | 
    
         
            +
                  it 'raises a RubySMB::Dcerpc::Error::InvalidPacket' do
         
     | 
| 
      
 1097 
     | 
    
         
            +
                    allow(described_class::SetKeySecurityResponse).to receive(:read).and_raise(IOError)
         
     | 
| 
      
 1098 
     | 
    
         
            +
                    expect { winreg.set_key_security(handle, security_descriptor) }.to raise_error(RubySMB::Dcerpc::Error::InvalidPacket)
         
     | 
| 
      
 1099 
     | 
    
         
            +
                  end
         
     | 
| 
      
 1100 
     | 
    
         
            +
                end
         
     | 
| 
      
 1101 
     | 
    
         
            +
             
     | 
| 
      
 1102 
     | 
    
         
            +
                context 'when the response error status is not WindowsError::Win32::ERROR_SUCCESS' do
         
     | 
| 
      
 1103 
     | 
    
         
            +
                  it 'raises a RubySMB::Dcerpc::Error::WinregError' do
         
     | 
| 
      
 1104 
     | 
    
         
            +
                    response[-4..-1] = [WindowsError::Win32::ERROR_INVALID_DATA.value].pack('V')
         
     | 
| 
      
 1105 
     | 
    
         
            +
                    expect { winreg.set_key_security(handle, security_descriptor) }.to raise_error(RubySMB::Dcerpc::Error::WinregError)
         
     | 
| 
      
 1106 
     | 
    
         
            +
                  end
         
     | 
| 
      
 1107 
     | 
    
         
            +
                end
         
     | 
| 
      
 1108 
     | 
    
         
            +
             
     | 
| 
      
 1109 
     | 
    
         
            +
                it 'returns the expected error status' do
         
     | 
| 
      
 1110 
     | 
    
         
            +
                  expect(winreg.set_key_security(handle, security_descriptor)).to eq(WindowsError::Win32::ERROR_SUCCESS)
         
     | 
| 
      
 1111 
     | 
    
         
            +
                end
         
     | 
| 
      
 1112 
     | 
    
         
            +
              end
         
     | 
| 
      
 1113 
     | 
    
         
            +
             
     | 
| 
      
 1114 
     | 
    
         
            +
             
     | 
| 
      
 1115 
     | 
    
         
            +
             
     | 
| 
       867 
1116 
     | 
    
         
             
            end
         
     | 
    
        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.3. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 3.3.7
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Metasploit Hackers
         
     | 
| 
         @@ -38,7 +38,7 @@ cert_chain: 
     | 
|
| 
       38 
38 
     | 
    
         
             
              DgscAao7wB3xW2BWEp1KnaDWkf1x9ttgoBEYyuYwU7uatB67kBQG1PKvLt79wHvz
         
     | 
| 
       39 
39 
     | 
    
         
             
              Dxs+KOjGbBRfMnPgVGYkORKVrZIwlaboHbDKxcVW5xv+oZc7KYXWGg==
         
     | 
| 
       40 
40 
     | 
    
         
             
              -----END CERTIFICATE-----
         
     | 
| 
       41 
     | 
    
         
            -
            date: 2024-04- 
     | 
| 
      
 41 
     | 
    
         
            +
            date: 2024-04-30 00:00:00.000000000 Z
         
     | 
| 
       42 
42 
     | 
    
         
             
            dependencies:
         
     | 
| 
       43 
43 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       44 
44 
     | 
    
         
             
              name: redcarpet
         
     | 
| 
         @@ -219,6 +219,7 @@ files: 
     | 
|
| 
       219 
219 
     | 
    
         
             
            - examples/read_file.rb
         
     | 
| 
       220 
220 
     | 
    
         
             
            - examples/read_file_encryption.rb
         
     | 
| 
       221 
221 
     | 
    
         
             
            - examples/read_registry_key_value.rb
         
     | 
| 
      
 222 
     | 
    
         
            +
            - examples/registry_key_security_descriptor.rb
         
     | 
| 
       222 
223 
     | 
    
         
             
            - examples/rename_file.rb
         
     | 
| 
       223 
224 
     | 
    
         
             
            - examples/tree_connect.rb
         
     | 
| 
       224 
225 
     | 
    
         
             
            - examples/virtual_file_server.rb
         
     | 
| 
         @@ -375,6 +376,8 @@ files: 
     | 
|
| 
       375 
376 
     | 
    
         
             
            - lib/ruby_smb/dcerpc/winreg/enum_key_response.rb
         
     | 
| 
       376 
377 
     | 
    
         
             
            - lib/ruby_smb/dcerpc/winreg/enum_value_request.rb
         
     | 
| 
       377 
378 
     | 
    
         
             
            - lib/ruby_smb/dcerpc/winreg/enum_value_response.rb
         
     | 
| 
      
 379 
     | 
    
         
            +
            - lib/ruby_smb/dcerpc/winreg/get_key_security_request.rb
         
     | 
| 
      
 380 
     | 
    
         
            +
            - lib/ruby_smb/dcerpc/winreg/get_key_security_response.rb
         
     | 
| 
       378 
381 
     | 
    
         
             
            - lib/ruby_smb/dcerpc/winreg/open_key_request.rb
         
     | 
| 
       379 
382 
     | 
    
         
             
            - lib/ruby_smb/dcerpc/winreg/open_key_response.rb
         
     | 
| 
       380 
383 
     | 
    
         
             
            - lib/ruby_smb/dcerpc/winreg/open_root_key_request.rb
         
     | 
| 
         @@ -386,6 +389,8 @@ files: 
     | 
|
| 
       386 
389 
     | 
    
         
             
            - lib/ruby_smb/dcerpc/winreg/regsam.rb
         
     | 
| 
       387 
390 
     | 
    
         
             
            - lib/ruby_smb/dcerpc/winreg/save_key_request.rb
         
     | 
| 
       388 
391 
     | 
    
         
             
            - lib/ruby_smb/dcerpc/winreg/save_key_response.rb
         
     | 
| 
      
 392 
     | 
    
         
            +
            - lib/ruby_smb/dcerpc/winreg/set_key_security_request.rb
         
     | 
| 
      
 393 
     | 
    
         
            +
            - lib/ruby_smb/dcerpc/winreg/set_key_security_response.rb
         
     | 
| 
       389 
394 
     | 
    
         
             
            - lib/ruby_smb/dcerpc/wkssvc.rb
         
     | 
| 
       390 
395 
     | 
    
         
             
            - lib/ruby_smb/dcerpc/wkssvc/netr_wksta_get_info_request.rb
         
     | 
| 
       391 
396 
     | 
    
         
             
            - lib/ruby_smb/dcerpc/wkssvc/netr_wksta_get_info_response.rb
         
     | 
| 
         @@ -959,7 +964,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement 
     | 
|
| 
       959 
964 
     | 
    
         
             
                - !ruby/object:Gem::Version
         
     | 
| 
       960 
965 
     | 
    
         
             
                  version: '0'
         
     | 
| 
       961 
966 
     | 
    
         
             
            requirements: []
         
     | 
| 
       962 
     | 
    
         
            -
            rubygems_version: 3.4 
     | 
| 
      
 967 
     | 
    
         
            +
            rubygems_version: 3.1.4
         
     | 
| 
       963 
968 
     | 
    
         
             
            signing_key: 
         
     | 
| 
       964 
969 
     | 
    
         
             
            specification_version: 4
         
     | 
| 
       965 
970 
     | 
    
         
             
            summary: A pure Ruby implementation of the SMB Protocol Family
         
     | 
    
        metadata.gz.sig
    CHANGED
    
    | 
         Binary file 
     |