Injecting shellcode into processes with Syringe


1) Opens a handle to the remote process

2) Uses VirtualAllocEx to allocate memory in the remote process with the necessary permissions of read, write, and execute. Then uses WriteProcessMemory to copy the shellcode to the remote buffer.

3) Repeats step #2 with the assembly stub

4) Starts the assembly stub via a call to CreateRemoteThread, with a pointer to the assembly stub as the function to execute and a pointer to the remote shellcode as the argument.

When I initially used this technique, I was disappointed to discover a problem with the assembly stub. When the assembly stub is written, the SEH chain contains addresses from the injecting process (in this case, Syringe), which are not valid in the victim process. Because of this, when the SEH chain is created, the remote process will crash with an access violation. In order to get around this issue, I created an additional assembly stub within Syringe that does not contain the SEH chain specifically for injecting into remote processes.

Once the SEH chain was removed, the shellcode would inject and execute successfully; however, when the shellcode exited once again, the remote process would crash. After reviewing this behavior, I determined that the problem was that the shell code I was generating with the Metasploit Framework was using Thread as its exit method. With this being the case, it is necessary for the assembly stub to make a call to ExitThread before returning. The ExitThread function is called to clean up current thread's resources before returning. With the call to ExitThread in place, the remote process is not affected when the shellcode terminates.

The final code used to generate the assembly stub for injection into remote processes is:

DWORD WINAPI RemoteExecPayloadStub(LPVOID lpParameter) {

                __asm {

                                mov eax, [lpParameter]

                                call eax

                                push 0

                                call ExitThread


                return 0;



Lines 3 and 4 move the pointer passed to the function as the argument into register EAX before calling it, just like ShellCodeExec does. Lines 5 and 6, push 0 (the argument) onto the stack, before making a call to ExitThread.

We can inject this modified version into the remote process and successfully execute shellcode in its context, interact with our shellcode and exit out of it, without damaging the remote process. A couple of things for users to keep in mind is that, when generating shellcode, to inject into the remote process the user must be sure to always select “Thread” as the exit function both when generating the shellcode and when setting up the handler for it when necessary.

Join us:






Spotlight on ...
Online Training

    Upgrade your skills and earn higher pay

    Readers to share their best tips for maximizing training dollars and getting the most out self-directed learning. Here’s what they said.


    Learn more

Answers - Powered by ITworld

Ask a Question