For the complete documentation index, see llms.txt. This page is also available as Markdown.

Local Thread Hijacking / Context Injection

Code execution by hijacking local thread execution flow

Thread Hijacking

Thread hijacking (A.K.A Thread Context Injection) is a technique in which the execution flow of a running thread is altered in order to execute an arbitrary code (shellcode). the benefit of this technique, is that code execution is performed without creating a new thread. The main difference between thread creation and thread hijacking is that creating a new thread will expose the base address of the payload, and thus the payload's content ,because a new thread's entry point must point to the payload base address in memory. exposing the payload address might trigger the memory scanner in some security products which in turn will scan the memory region and probably find some signatures in it, which leads to process termination.


Thread Context

The thread context represents the complete state of a thread at a particular point in time. It includes the values of all the registers, flags, and pointers that determine what the thread is doing and where it’s located in its execution. By manipulating this context, one can control a thread’s execution, making it useful for debugging, altering program flow, and even injecting code, as seen in techniques like thread hijacking.

Manipulating Threads

Windows provides two key APIs to interact with a thread’s context:

GetThreadContext : Retrieves the current context of a specified thread. This includes values of all registers, flags, and more, allowing developers or attackers to view the thread's exact execution state.

SetThreadContext : Sets or updates the context of a specified thread, allowing modification of the thread’s execution by changing registers, flags, or the instruction pointer (such as redirecting execution to injected code).

And two APIs for changing threads running state (suspend/resume):

SuspendThread : Suspends the specified thread.

ResumeThread : Decrements a thread's suspend count. When the suspend count is decremented to zero, the execution of the thread is resumed.

Here's an example of these APIs:

Here is a quick run down of the code:

  1. The program's Main function (the main thread) creates a new thread (thread1) using CreateThread API. thread1 will execute the thread_function function.

  2. Thread1 will start a count down from 10 to 0 while the main thread is waiting for 5 seconds after thread1 creation to suspend thread1 using SuspendThread API call.

  3. After suspension, the main thread retrieves the thread context from thread1 using GetThreadContext API and prints the information.

  4. The main thread then resumes thread1 using ResumeThread and thread1 keeps counting down to 0 from where is has been suspended.

These APIs are used in the process of hijacking a local or remote thread.


Local Thread Hijacking

Following the previous example code, here’s an overview of how local thread hijacking generally works:

  1. Create a benign thread (dummy thread) in local process and a benign function for it to execute. the thread can be created in suspended state or be suspended later.

  2. Suspend the dummy thread (if not already suspended)

  3. allocate memory and copy the shellcode, make it executable/readable

  4. Get dummy thread context, set instruction pointer to shellcode address

  5. Resume the dummy thread to execute the shellcode


Hijacking a Suspended Thread

First way is to create a local thread in suspended state (using CREATE_SUSPENDED flag in CreateThread API call), changing thread context and then resuming the modified thread to execute our shellcode.

Here is an example of a dummy thread getting hijacked from suspended mode:

If we setup a netcat listener and run the code:

As you can see the dummy function did not get a chance to execute the countdown code. thats because the Hijacker function modified the RIP to point to the shellcode, so the countdown loop could never be reached.


Hijack a Running Thread

Another way is to let the thread run and then hijack its execution.

Here is an example code of a dummy function being hijacked mid-execution:

Executing the code, we see this:

This time, the dummy thread is running, until its suspended and the shellcode gets executed instead of the countdown loop:

The process is then paused until we hit Ctrl+C in the terminal and terminate the reverse shell.


Code Samples

Code snippets are available on GitHub:

Last updated