APC Queue Code Injection
This lab looks at the APC (Asynchronous Procedure Calls) queue code injection - a well known technique I had not played with in the past.
Some simplified context around threads and APC queues:
Threads execute code within processes
Threads can execute code asynchronously by leveraging APC queues
Each thread has a queue that stores all the APCs
Application can queue an APC to a given thread (subject to privileges)
When a thread is scheduled, queued APCs get executed
Disadvantage of this technique is that the malicious program cannot force the victim thread to execute the injected code - the thread to which an APC was queued to, needs to enter/be in an alertable state (i.e
SleepEx
), but you may want to check out Shellcode Execution in a Local Process with QueueUserAPC and NtTestAlert
Execution
A high level overview of how this lab works:
Write a C++ program apcqueue.exe that will:
Find explorer.exe process ID
Allocate memory in explorer.exe process memory space
Write shellcode to that memory location
Find all threads in explorer.exe
Queue an APC to all those threads. APC points to the shellcode
Execute the above program
When threads in explorer.exe get scheduled, our shellcode gets executed
Rain of meterpreter shells
Let's start by creating a meterpreter shellcode to be injected into the victim process:
I will be injecting the shellcode into explorer.exe
since there's usually a lot of thread activity going on, so there is a better chance to encounter a thread in an alertable state that will kick off the shellcode. I will find the process I want to inject into with Process32First
and Process32Next
calls:
Once explorer PID is found, we need to get a handle to the explorer.exe process and allocate some memory for the shellcode. The shellcode is written to explorer's process memory and additionally, an APC routine, which now points to the shellcode, is declared:
If we compile and execute apcqueue.exe
, we can indeed see the shellcode gets injected into the process successully:
A quick detour - the below shows a screenshot from the Process Hacker where our malicious program has a handle to explorer.exe - good to know for debugging and troubleshooting:
Back to the code - we can now enumerate all threads of explorer.exe and queue an APC (points to the shellcode) to them:
Switching gears to the attacking machine - let's fire up a multi handler and set an autorunscript
to migrate meterpreter sessions to some other process before they die with the dying threads:
Once the apcqueue
is compiled and run, a meterpreter session is received - the technique worked:
States
As mentioned earlier, in order for the APC code injection to work, the thread to which an APC is queued, needs to be in an alertable
state.
To get a better feel of what this means, I created another project called alertable
that only did one thing - slept for 60 seconds. The application was sent to sleep using (note the important second parameter):
Let's put the new project to sleep in both alertable and non-alertable states and see what heppens when an APC is queued to it.
Alertable State
Let's compile the alertable.exe
binary with bAleertable = true
first and then launch the apcqueue.exe
.
Since alertable.exe
was in an alertable state, the code got executed immediately and a meterpreter session was established:
Non-Alertable State
Now let's recompile alertable.exe
with bAlertable == false
and try again - shellcode does not get executed:
Powershell -sta
An interesting observation is that if you try injecting into powershell.exe which was started with a -sta
switch (Single Thread Apartment), we do not need to spray the APC across all its threads - main thread is enough and gives a reliable shell:
Note that the injected powershell process becomes unresponsive.
Code
References
Last updated