APC机制两个问题
一、特定情况下WaitForSingleObjectEx返回值的问题
- 等待内核对象处于**状态 (下面是hEvent)
- 线程处于警觉状态,且APC队列中有函数(APCProc)
两个条件同时满足的时候,WaitForSingleObjectEx这个函数的返回值是什么?
代码:
#include <stdio.h>
#include <windows.h>
VOID CALLBACK APCProc(__in ULONG_PTR dwParam)
{
printf("This APC has been running other\n");
for (int i = 0; i < 10; i++)
{
printf("%d\n", i);
Sleep(500);
}
return;
}
/*
WAIT_IO_COMPLETION
0x000000C0L
The wait was ended by one or more user-mode asynchronous procedure calls (APC) queued to the thread.
WAIT_OBJECT_0
0x00000000L
The state of the specified object is signaled.
*/
int main()
{
HANDLE hEvent = CreateEvent(NULL, FALSE,TRUE, NULL); //创建一个事件内核对象
QueueUserAPC(APCProc, GetCurrentThread(), NULL);
DWORD re = WaitForSingleObjectEx(hEvent, INFINITE, TRUE); //在调试的时候给人的感觉就好像是APCProc是在这个WaitForSingleObject这个函数当中
printf("re = %X\n", re); //0XC0 WAIT_IO_COMPLETION
re = WaitForSingleObject(hEvent, INFINITE);
printf("re = %X\n", re); //0 WAIT_OBJECT_0
getchar();
return 0;
}
通过测试,发现两个条件同时满足的时候,函数会返回WAIT_IO_COMPLETION,并且内核对象仍然处于未**状态
二、一个进程是否可以把自己的APC注入到另一个进程
先看两个程序:
进程1代码(被注入):
#include <stdio.h>
#include <windows.h>
VOID CALLBACK APCProc(__in ULONG_PTR dwParam)
{
printf("This APC has been running\n");
return;
}
int main()
{
printf("TID = %d, APCProc = %d\n", GetCurrentThreadId(), APCProc);
SleepEx(INFINITE, TRUE); //设置为警觉状态
getchar();
return 0;
}
在运行进程2之前,运行进程1显示为:
进程2代码(注入):
#include <stdio.h>
#include <windows.h>
VOID CALLBACK APCProc(ULONG_PTR dwParam)
{
printf("This APC has been running\n");
}
typedef VOID(CALLBACK * PFunc)(ULONG_PTR dwParam);//定义一个函数指针
int main()
{
HANDLE hThread = OpenThread(GENERIC_ALL, FALSE, 14532);
DWORD re = QueueUserAPC((PFunc)20255480, hThread, NULL);
printf("re = %d\n", re);
getchar();
return 0;
}
过程:
进程1先运行,进程2再运行,这个时候进程1会变为
所以进程1可以通过获得进程2的某个线程ID,并且获得进程2的APC函数地址,然后采用QueueUserAPC函数,把进程2的某个APC函数地址,放入进程2的某个线程的APC队列当中去。
但是这里一定要注意,APC函数的地址一定是进程2的地址空间的函数,不能是进程1的,否则会出错,因为不同进程的地址空间是相互隔离的,进程1的APC函数的地址在进程2的地址空间中很可能是一段无效的地址,所以会出错。