A forum for reverse engineering, OS internals and malware analysis 

Forum for discussion about user-mode development.
 #8814  by newgre
 Wed Sep 28, 2011 6:56 pm
So in the end APC injection cannot be done reliably, you need "luck" to find an alertable thread, and you have no means of performing an injection "now". So it's not suitable as a general purpose technique.
 #8816  by Brock
 Wed Sep 28, 2011 8:19 pm
You're correct in what you said. It is however suited as a general purpose injection method if the target process has not been initialized yet, queuing an APC to the main thread would result in that code being executed immediately. For example: Creating a process suspended, queuing an APC to the main thread (pi.hThread) and then resuming the thread.
 #8953  by Fabian Wosar
 Tue Oct 04, 2011 3:33 pm
APC injections into processes you spawn yourself are very reliable indeed. That being said: Trying to inject an APC into an already running process is far from reliable. Especially given the fact how easy a process can defend itself from such kind of attacks.
 #8959  by Brock
 Tue Oct 04, 2011 11:03 pm
Trying to inject an APC into an already running process is far from reliable
Speaking soley about APCs - Not necessarily, granted this depends on which context you are speaking about be it a thread you created in the target process or a preexisting thread in the process which you do not "own". If you spawn a remote dummy thread in a suspended state and queue an APC to it your code will execute as soon as the thread is resumed. I've described this a bit on the forum already in another post.

Anyhow, the remote thread start address parameter can simply point to ExitThread/RtlExitUserThread since it's only needed to signal the thread to execute your APC callback. It is "reliable" for executing APCs immediately within the context of already running foreign processes this way. Queuing an APC to some preexisting thread, which you have not created yourself, may or may not ever enter an alertable wait-state. I assume that you were referring to this when you said "unreliable" initially?

Does the concept of queuing an APC off a remote thread when the thread is already perfectly capable of executing your code without the APC entirely make sense? I think it depends on what your code is doing to determine whether it would be ideal or not but this is a whole different discussion as to why this might be beneficial I believe.
 #8960  by Fabian Wosar
 Wed Oct 05, 2011 12:07 am
Brock wrote:Speaking soley about APCs - Not necessarily, granted this depends on which context you are speaking about be it a thread you created in the target process or a preexisting thread in the process which you do not "own". If you spawn a remote dummy thread in a suspended state and queue an APC to it your code will execute as soon as the thread is resumed. I've described this a bit on the forum already in another post.
I wasn't referring to the general limitations APCs have. I was referring to the fact that, due to the way APCs are actually implemented in Windows, applications can easily defend themselves against them. All usermode APCs are dispatched through KiUserApcDispatcher in their target process. Just hook that function and you gain full control over what APCs are executed inside your process.
 #8963  by Brock
 Wed Oct 05, 2011 1:54 am
Hello Fabian,

I addressed _only_ that APCs are reliable in actuality when assisted by a remote thread to queue off of for "already running processes", please reread what I quoted you saying as I took your statement exactly in this context. I wasn't talking about what-if hook scenarios preventing APC delivery. I assumed you were implying that APCs from an injection perspective are only truly useful when you can control thread creation or manipulate the target thread's alertable state, in which I would have agreed.
 #8967  by Fabian Wosar
 Wed Oct 05, 2011 10:44 am
The context of my original statement was quite clear:
APC injections into processes you spawn yourself are very reliable indeed. That being said: Trying to inject an APC into an already running process is far from reliable. Especially given the fact how easy a process can defend itself from such kind of attacks.
But since we both aren't native speakers we most likely simply talked at cross-purposes. Anyways, to clarify what I meant to say in the first place: APC injection into an already running process is very unreliable not only because of the waiting state requirements APCs have, but also due to the fact that a process can gain complete control of the APC dispatching mechanism for all threads that belong to the process simply by hooking KiUserApcDispatcher in his own address space. So even an unprivileged application can protect itself from APCs issued by privileged applications and even kernel mode drivers.
 #8970  by newgre
 Wed Oct 05, 2011 12:13 pm
Well, couldn't you simply suspend all threads of that process, write the original KiUserAPCDispatcher routine, perform APC injection, restore the APC routine and resume all threads?
 #8971  by EP_X0FF
 Wed Oct 05, 2011 1:18 pm
NTOS locates and keeps pointer to UserApcDispatch routine (btw exactly for this reason ntos loads ntdll into system process). This is not only apc dispatch but also usermode callbacks, exception handler routines, LdrInitializeThunk. This is a part of NTOS initialization.

KeUserApcDispatcher pointer to KiUserApcDispatcher.

IIRC NTOS uses KeUserApcDispatcher pointer while initializing user mode APC (c.f. KiInitializeUserApc) by setting it address for the Eip of the current trap frame. So there are various ways to counteract APC injection.
 #8972  by Fabian Wosar
 Wed Oct 05, 2011 1:26 pm
newgre wrote:Well, couldn't you simply suspend all threads of that process, write the original KiUserAPCDispatcher routine, perform APC injection, restore the APC routine and resume all threads?
Sure, you can. But if you already can do all those nasty things, why do you bother with APCs at all? :) You could simply redirect the code flow by overwriting code you know is going to be executed at one point or another.