Click to See Complete Forum and Search --> : Force a thread to execute an APC?


tcchiu
July 23rd, 2007, 08:24 AM
Hello,

I want to queue a user APC to a thread in the other running process (code injection issue resolved), but it is never executed. I guess the problem is the thread never enter the alertable state. How can I force it to enter the alertable state and executed my queued APC?

However, if I create that foreign process with CREATE_SUSPEND, queue the APC to the primary thread, resume it, the APC will be executed correctly, no problem.

I know it's unusual because it's not the designed purpose of APC. The preempted thread may be in a unstable state when executing APC.

I know it can be done easily in the kernel mode, but I am looking for a userland solution. Maybe using some native APIs in NTDLL.DLL, but I've not got any luck.

(1)
SuspendThread(hThread);
QueueUserAPC(apcFunc, hThread, NULL);
NtAlertResumeThread(hThread, &suspendCount);

(2)
QueueUserAPC(apcFunc, hThread, NULL);
NtAlertThread(hThread);

Neither of the above two method works. Do I miss something?

googler
July 23rd, 2007, 02:27 PM
How can I force it to enter the alertable state and executed my queued APC?You can't. Threads execute user APCs when either 1) They synchronously call NtTestAlert() or 2) They synchronously enter an alertable wait.

However, if I create that foreign process with CREATE_SUSPEND, queue the APC to the primary thread, resume it, the APC will be executed correctly, no problem.
That's a special case. The kernel launches a user-mode thread by queuing a user APC to run loader code in ntdll and then coercing an alertable state. If you queue any other user APC before the thread starts it will execute as well.

I know it's unusual because it's not the designed purpose of APC.
...
Neither of the above two method works. Do I miss something?You missed your own recognition that user APCS were not designed for asynchronous thread interruption and can't be used that way.

I believe that the way the POSIX subsystem (R.I.P.??) implements signals is to suspend the thread and then change its context using SetThreadContext()/NtSetContextThread(). Use this idea at your own risk...

tcchiu
July 25th, 2007, 05:37 AM
You missed your own recognition that user APCS were not designed for asynchronous thread interruption and can't be used that way.
I've known that user APC is not designed to be used in this way, but I wanna *hack* it.

There is an article on CodeProject which shows how to do this with a kernel mode driver:
http://www.codeproject.com/threads/QueueUserAPCEx_v2.asp

but I am exploring an userland technique (if exists). I'm interested in the second comment posted by "mattmurphy" on Jan 2005 under the aforementioned article (subject: "NTDLL interfaces for APCs"). He suggested that it might be done by using NtAlertThread or NtAlertResumeThread. As you've seen in my original post, I tried but in vain.


I believe that the way the POSIX subsystem (R.I.P.??) implements signals is to suspend the thread and then change its context using SetThreadContext()/NtSetContextThread(). Use this idea at your own risk...
This is interesting, but my purpose is to execute the user APC in the context of a target thread in "another" process.

PS: I am not goin' to argue the purpose and usefulness of this kind of techniques as in the aforementioned article. It's a hack.