使用QueueUserAPC线程注入,

回眸只為那壹抹淺笑 提交于 2020-03-03 18:48:04
代码1
#define _WIN32_WINNT 0x0400
#define WIN32_LEAN_AND_MEAN   // 从 Windows 头中排除极少使用的资料

#include 
<iostream>
#include 
<windows.h>
#include 
<Winbase.h>
using namespace std;


DWORD  WINAPI WorkThread(LPVOID pParam)
{
    HANDLE Event 
= (HANDLE)pParam;
    
for(;;)
    {
        DWORD dwRet 
= WaitForSingleObjectEx(Event, INFINITE, TRUE);
        
if(dwRet == WAIT_OBJECT_0)
            
break;
        
else 
            
if(dwRet == WAIT_IO_COMPLETION)
                printf(
"WAIT_IO_COMPLETION\n");
            
            
return 0;
    }
}


VOID  WINAPI APCProc(LPVOID dwParam)
{
    printf(
"%s", (PVOID)dwParam);
}

void TestAPC(BOOL bFast)
{
    
    HANDLE QuitEvent 
= CreateEvent(NULL, FALSE, FALSE, NULL);
    HANDLE hThread 
= CreateThread(NULL,
        
0,
        WorkThread,
        (LPVOID)QuitEvent,
        
0,
        NULL);
    
    
    Sleep(
100); // Wait for WorkThread initialized.
    
    
    
for(int i=5; i>0; i--)
    {    
        QueueUserAPC((PAPCFUNC)APCProc, hThread, (DWORD)(PVOID)
"APC here\n");
        
if(!bFast)
            Sleep(
1000);
    }
    
    
    SetEvent(QuitEvent);
    
    WaitForSingleObject(hThread, INFINITE);
    
    CloseHandle(hThread);    
}

int main()
{
    TestAPC(
true);
    
return 0;
}

 

代码2
#define _WIN32_WINNT 0x0400
#define WIN32_LEAN_AND_MEAN   // 从 Windows 头中排除极少使用的资料

#include 
<windows.h>
#include 
<Tlhelp32.h>
#include 
<stdio.h>
#include 
<stdlib.h>

typedef HANDLE (CALLBACK 
*OPENTHREAD) (DWORD dwFlag, BOOL bUnknow, DWORD dwThreadId); 
typedef   unsigned   
long      ULONG_PTR; 


typedef 
struct _TIDLIST 
{
    DWORD dwTid ;
    _TIDLIST 
*pNext ;
}TIDLIST;

DWORD EnumThread(HANDLE hProcess, TIDLIST 
*pThreadIdList)
{
    TIDLIST 
*pCurrentTid = pThreadIdList ;
    HANDLE hThread;
    
const char szInjectModName[] = "c:\\sysnap.dll" ;
    DWORD dwLen 
= strlen(szInjectModName) ;
    HMODULE hDll 
= GetModuleHandle("Kernel32.dll"); 
    
    PVOID param 
= VirtualAllocEx(hProcess, \
        NULL, dwLen, MEM_COMMIT 
| MEM_TOP_DOWN, PAGE_EXECUTE_READWRITE) ;
    
    
if (param != NULL)
    {
        DWORD dwRet ;
        
if (WriteProcessMemory(hProcess, param, (LPVOID)szInjectModName, dwLen, &dwRet))
        {
            
            
while (pCurrentTid)
            {
                OPENTHREAD lpfnOpenThread 
= (OPENTHREAD)::GetProcAddress(hDll, "OpenThread"); 
                hThread 
= lpfnOpenThread(THREAD_ALL_ACCESS,FALSE,pCurrentTid->dwTid);
                
if (hThread != NULL)
                {
                    
//
                    
// 注入DLL到指定进程
                    
//
                    QueueUserAPC((PAPCFUNC)LoadLibraryA, hThread, (ULONG_PTR)param) ;
                }
                
                printf(
"TID:%d\n", pCurrentTid->dwTid) ;
                pCurrentTid 
= pCurrentTid->pNext ;
            }
        }
    }
    
return 0 ;
}

DWORD GetProcID(
const char *szProcessName)
{
    PROCESSENTRY32 pe32 
= {0} ;
    pe32.dwSize 
= sizeof(PROCESSENTRY32);
    
    HANDLE hSnapshot 
= CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) ;
    
    
if (hSnapshot == INVALID_HANDLE_VALUE)
    {
        
return 0xFFFFFFFF ;
    }
    
    
if (!Process32First(hSnapshot, &pe32))
    {
        
return 0xFFFFFFFF ;
    }
    
    
do 
    {
        
if (!_strnicmp(szProcessName, pe32.szExeFile, strlen(szProcessName)))
        {
            printf(
"%s的PID是:%d\n", pe32.szExeFile, pe32.th32ProcessID);
            
return pe32.th32ProcessID ;
        }
    } 
while(Process32Next(hSnapshot, &pe32));
    
    
return 0xFFFFFFFF ;
    
}

TIDLIST
* InsertTid(TIDLIST *pdwTidListHead, DWORD dwTid)
{
    TIDLIST 
*pCurrent = NULL ;
    TIDLIST 
*pNewMember = NULL ;
    
    
if (pdwTidListHead == NULL)
    {
        
return NULL ;
    }
    pCurrent 
= pdwTidListHead ;
    
    
while (pCurrent != NULL)
    {
        
        
if (pCurrent->pNext == NULL)
        {
            
//
            
// 定位到链表最后一个元素
            
//
            pNewMember = (TIDLIST *)malloc(sizeof(TIDLIST)) ;
            
            
if (pNewMember != NULL)
            {
                pNewMember
->dwTid = dwTid ;
                pNewMember
->pNext = NULL ;
                pCurrent
->pNext = pNewMember ;
                
return pNewMember ;
            }
            
else
            {
                
return NULL ;
            }
        }
        pCurrent 
= pCurrent->pNext ;
    }
    
    
return NULL ;
}

int EnumThreadID(DWORD dwPID, TIDLIST *pdwTidList)
{
    
int i = 0 ;
    
    THREADENTRY32 te32 
= {0} ;
    te32.dwSize
= sizeof(THREADENTRY32) ;
    
    HANDLE hSnapshot 
= CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD,dwPID) ;
    
    
if(hSnapshot != INVALID_HANDLE_VALUE)
    {
        
if(Thread32First(hSnapshot,&te32)) 
        {
            
do
            {
                
if(te32.th32OwnerProcessID==dwPID) 
                {
                    
if (pdwTidList->dwTid == 0)
                    {
                        pdwTidList
->dwTid = te32.th32ThreadID ;
                    }
                    
else
                    {
                        
if (NULL == InsertTid(pdwTidList, te32.th32ThreadID))
                        {
                            printf(
"插入失败!\n") ;
                            
return 0 ;
                        }
                    }
                    
                } 
            }
while(Thread32Next(hSnapshot,&te32));
        }
    }
    
return 1 ;
}

void RemoveTid(TIDLIST *pdwTidListHead)
{
    TIDLIST 
*pCurrent = NULL ;
    TIDLIST 
*pNext = NULL ;
    
    
    
if (pdwTidListHead == NULL)
    {
        
return;
    }
    pCurrent 
= pdwTidListHead ;
    
    
while (pCurrent != NULL)
    {
        
        pNext 
= pCurrent->pNext;
        free(pCurrent);
        pCurrent 
= pNext;
    }
    
}
int main(int argc, char* argv[])
{
    TIDLIST 
*pTidHead = (TIDLIST *)malloc(sizeof(TIDLIST)) ;
    
    
if (pTidHead == NULL)
    {
        
return 1 ;
    }

    RtlZeroMemory(pTidHead, 
sizeof(TIDLIST)) ;
    
    DWORD dwPID 
= 0 ;
    
    
if ((dwPID = GetProcID("explorer.exe")) == 0xFFFFFFFF)
    {
        printf(
"进程ID获取失败!\n") ;
        
return 1 ;
    }
    
    
//
    
// 枚举线程ID
    
//
    EnumThreadID(dwPID, pTidHead) ;
    
    HANDLE hProcess 
= OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID) ;
    
    
if (hProcess == NULL)
    {
        
return 1 ;
    }
    EnumThread(hProcess, pTidHead) ;
    
    CloseHandle(hProcess);
    
    RemoveTid(pTidHead);
    
    
return 0;
}


 

Alertable IO(告警IO)提供了更有效的异步通知形式。ReadFileEx / WriteFileEx在发出IO请求的同时,提供一个回调函数(APC过程),当IO请求完成后,一旦线程进入可告警状态,回调函数将会执行。
   以下五个函数能够使线程进入告警状态:
   SleepEx
   WaitForSingleObjectEx
   WaitForMultipleObjectsEx
   SignalObjectAndWait
   MsgWaitForMultipleObjectsEx
   线程进入告警状态时,内核将会检查线程的APC队列,如果队列中有APC,将会按FIFO方式依次执行。如果队列为空,线程将会挂起等待事件对象。以后的某个时刻,一旦APC进入队列,线程将会被唤醒执行APC,同时等待函数返回WAIT_IO_COMPLETION。
   QueueUserAPC可以用来人为投递APC,只要目标线程处于告警状态时,APC就能够得到执行。
   使用告警IO的主要缺点是发出IO请求的线程也必须是处理结果的线程,如果一个线程退出时还有未完成的IO请求,那么应用程序将永远丢失IO完成通知。然而以后我们将会看到IO完成端口没有这个限制。
  
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!