DLL注入-APC注入
APC注入
APC注入的原理是利用當(dāng)線程被喚醒時(shí)APC中的注冊(cè)函數(shù)會(huì)被執(zhí)行的機(jī)制,并以此去執(zhí)行我們的DLL加載代碼,進(jìn)而完成DLL注入的目的,其具體流程如下:
? ? 1)當(dāng)EXE里某個(gè)線程執(zhí)行到SleepEx()或者WaitForSingleObjectEx()時(shí),系統(tǒng)就會(huì)產(chǎn)生一個(gè)軟中斷(或者是Messagebox彈窗的時(shí)候不點(diǎn)OK的時(shí)候也能注入)。
? ? 2)當(dāng)線程再次被喚醒時(shí),此線程會(huì)首先執(zhí)行APC隊(duì)列中的被注冊(cè)的函數(shù)。
? ? 3)利用QueueUserAPC()這個(gè)API可以在軟中斷時(shí)向線程的APC隊(duì)列插入一個(gè)函數(shù)指針,如果我們插入的是Loadlibrary()執(zhí)行函數(shù)的話,就能達(dá)到注入DLL的目的。
核心函數(shù):
局限:
? 這種注入方式局限性很明顯,一是必須要等待時(shí)機(jī),而是當(dāng)注入成功后,SleepEx或者其他等待函數(shù)直接就會(huì)跳過(guò)當(dāng)前等待繼續(xù)往下走,這樣可能造成被注入程序的不穩(wěn)定行,經(jīng)常導(dǎo)致被注入程序崩潰。
代碼:
// LoadExeWin32.cpp : 定義控制臺(tái)應(yīng)用程序的入口點(diǎn)。 // #include "stdafx.h" #include <string> #include <windows.h> #include <shlwapi.h> #include <tlhelp32.h> #include <winternl.h> #pragma comment(lib, "shlwapi.lib") #pragma comment(lib,"ntdll.lib")using namespace std;//根據(jù)進(jìn)程名字獲取pid DWORD GetPidFromName(wstring wsProcessName) { HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (hSnapshot == INVALID_HANDLE_VALUE){ return FALSE; } PROCESSENTRY32W pe = {sizeof(pe)}; BOOL bOk; for (bOk = Process32FirstW(hSnapshot, &pe); bOk; bOk = Process32NextW(hSnapshot, &pe)){ wstring wsNowProcName = pe.szExeFile; if(StrStrI(wsNowProcName.c_str() ,wsProcessName.c_str())!= NULL){ CloseHandle(hSnapshot); return pe.th32ProcessID; } } CloseHandle(hSnapshot); return 0; } //把wcCacheInDllPath DLL文件注入進(jìn)程wsProcessName BOOL Injection_APC(const wstring &wsProcessName ,const WCHAR wcCacheInDllPath[]){ //初始化 DWORD dwProcessId = GetPidFromName(wsProcessName); HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwProcessId); if (!hProcess){ return FALSE; } PVOID lpData = VirtualAllocEx(hProcess, NULL, 1024, MEM_COMMIT, PAGE_EXECUTE_READWRITE); DWORD dwRet; if (lpData) { //在遠(yuǎn)程進(jìn)程申請(qǐng)空間中寫(xiě)入待注入DLL的路徑 WriteProcessMemory(hProcess, lpData, (LPVOID)wcCacheInDllPath, MAX_PATH,&dwRet); } CloseHandle(hProcess); //開(kāi)始注入 THREADENTRY32 te = {sizeof(THREADENTRY32)}; //得到線程快照 HANDLE handleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD ,0); if (INVALID_HANDLE_VALUE == handleSnap) { return FALSE; } BOOL bStat = FALSE; //得到第一個(gè)線程 if (Thread32First(handleSnap,&te)){ do { //進(jìn)行進(jìn)程ID對(duì)比 if (te.th32OwnerProcessID == dwProcessId) { //得到線程句柄 HANDLE handleThread = OpenThread(THREAD_ALL_ACCESS ,FALSE ,te.th32ThreadID); if (handleThread) { //向線程插入APC DWORD dwRet = QueueUserAPC( (PAPCFUNC)LoadLibraryW, handleThread, (ULONG_PTR)lpData); if (dwRet > 0) { bStat = TRUE; } //關(guān)閉句柄 CloseHandle(handleThread); } } //循環(huán)下一個(gè)線程 } while (Thread32Next(handleSnap,&te)); } CloseHandle(handleSnap); return bStat; } //Adds a user-mode asynchronous procedure call (APC) int main(int argc, char* argv[]){ //Sleep(1000*100); Injection_APC(L"Sleep3M.exe" ,L"M.dll");return 0; }然后寫(xiě)一個(gè)測(cè)試DLL:
然后再寫(xiě)一個(gè)被注入程序:
?
測(cè)試結(jié)果:
注入自己的程序成功:
隨便嘗試了下注入QQ.exe,直接崩潰退出了。
總結(jié)
以上是生活随笔為你收集整理的DLL注入-APC注入的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: WindowsPE 第五章 导出表
- 下一篇: Windows核心编程 第十四章 虚拟内