使用QueueUserAPC线程注入,
生活随笔
收集整理的這篇文章主要介紹了
使用QueueUserAPC线程注入,
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
代碼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;
}
#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到指定進(jìn)程
????????????????????//
????????????????????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("進(jìn)程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;
}
以下五個函數(shù)能夠使線程進(jìn)入告警狀態(tài):
SleepEx
WaitForSingleObjectEx
WaitForMultipleObjectsEx
SignalObjectAndWait
MsgWaitForMultipleObjectsEx
線程進(jìn)入告警狀態(tài)時,內(nèi)核將會檢查線程的APC隊列,如果隊列中有APC,將會按FIFO方式依次執(zhí)行。如果隊列為空,線程將會掛起等待事件對象。以后的某個時刻,一旦APC進(jìn)入隊列,線程將會被喚醒執(zhí)行APC,同時等待函數(shù)返回WAIT_IO_COMPLETION。
QueueUserAPC可以用來人為投遞APC,只要目標(biāo)線程處于告警狀態(tài)時,APC就能夠得到執(zhí)行。
使用告警IO的主要缺點(diǎn)是發(fā)出IO請求的線程也必須是處理結(jié)果的線程,如果一個線程退出時還有未完成的IO請求,那么應(yīng)用程序?qū)⒂肋h(yuǎn)丟失IO完成通知。然而以后我們將會看到IO完成端口沒有這個限制。
#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到指定進(jìn)程
????????????????????//
????????????????????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("進(jìn)程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在發(fā)出IO請求的同時,提供一個回調(diào)函數(shù)(APC過程),當(dāng)IO請求完成后,一旦線程進(jìn)入可告警狀態(tài),回調(diào)函數(shù)將會執(zhí)行。以下五個函數(shù)能夠使線程進(jìn)入告警狀態(tài):
SleepEx
WaitForSingleObjectEx
WaitForMultipleObjectsEx
SignalObjectAndWait
MsgWaitForMultipleObjectsEx
線程進(jìn)入告警狀態(tài)時,內(nèi)核將會檢查線程的APC隊列,如果隊列中有APC,將會按FIFO方式依次執(zhí)行。如果隊列為空,線程將會掛起等待事件對象。以后的某個時刻,一旦APC進(jìn)入隊列,線程將會被喚醒執(zhí)行APC,同時等待函數(shù)返回WAIT_IO_COMPLETION。
QueueUserAPC可以用來人為投遞APC,只要目標(biāo)線程處于告警狀態(tài)時,APC就能夠得到執(zhí)行。
使用告警IO的主要缺點(diǎn)是發(fā)出IO請求的線程也必須是處理結(jié)果的線程,如果一個線程退出時還有未完成的IO請求,那么應(yīng)用程序?qū)⒂肋h(yuǎn)丟失IO完成通知。然而以后我們將會看到IO完成端口沒有這個限制。
轉(zhuǎn)載于:https://www.cnblogs.com/chengxin1982/archive/2010/01/20/1652398.html
總結(jié)
以上是生活随笔為你收集整理的使用QueueUserAPC线程注入,的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Javascript学习笔记12——Aj
- 下一篇: 大型Web2.0站点构建技术初探一