c++ 如何實(shí)現(xiàn)線程注入
簡單編寫DLL文件:
#include <Windows.h> extern "C" __declspec(dllexport) void MsgBox(LPCWSTR szMsg, LPCWSTR Title) { MessageBox(NULL, szMsg, Title, MB_OK); } BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: // 進(jìn)程被加載后執(zhí)行 break; case DLL_THREAD_ATTACH: // 線程被創(chuàng)建后加載 break; case DLL_THREAD_DETACH: // 正常退出執(zhí)行的代碼 break; case DLL_PROCESS_DETACH: // 進(jìn)程卸載本Dll后執(zhí)行的代碼 break; } return TRUE; }
#include <Windows.h> #include <iostream> typedef VOID(*PFUNMSG)(LPCWSTR szMsg, LPCWSTR Title); int main(int argc, char *argv[]) { HMODULE hModule = LoadLibrary("./hook.dll"); if (hModule != NULL) { PFUNMSG pMsgBox = (PFUNMSG)GetProcAddress(hModule, "MsgBox"); pMsgBox(L"hello lyshark", L"msgbox"); } system("pause"); return 0; }
x86 實(shí)現(xiàn)遠(yuǎn)程線程注入:
注入原理是利用了Windows系統(tǒng)中提供的CreateRemoteThread()這個API函數(shù),該函數(shù)第四個參數(shù)是準(zhǔn)備運(yùn)行的線程,我們將LoadLibrary()函數(shù)填入其中,這樣就可以執(zhí)行遠(yuǎn)程進(jìn)程中的LoadLibrary()函數(shù),進(jìn)而將我們自己準(zhǔn)備的DLL加載到遠(yuǎn)程進(jìn)程空間中執(zhí)行,DLL在被裝載后則會自動執(zhí)行初始化部分,X86注入代碼如下.
#include <windows.h> #include <stdio.h> // 使用 CreateRemoteThread 實(shí)現(xiàn)遠(yuǎn)線程注入 BOOL CreateRemoteThreadInjectDll(DWORD Pid, char *DllName) { HANDLE hProcess = NULL; SIZE_T dwSize = 0; LPVOID pDllAddr = NULL; FARPROC pFuncProcAddr = NULL; // 打開注入進(jìn)程,獲取進(jìn)程句柄 hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, Pid); if (NULL == hProcess) { return FALSE; } // 計(jì)算欲注入 DLL 文件完整路徑的長度 dwSize = sizeof(char)+lstrlen(DllName); // 在目標(biāo)進(jìn)程申請一塊長度為 nDllLen 大小的內(nèi)存空間 pDllAddr = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE); if (NULL == pDllAddr) { return FALSE; } // 將欲注入 DLL 文件的完整路徑寫入在目標(biāo)進(jìn)程中申請的空間內(nèi) if (FALSE == WriteProcessMemory(hProcess, pDllAddr, DllName, dwSize, NULL)) { return FALSE; } // 獲得 LoadLibraryA()函數(shù)的地址 pFuncProcAddr = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA"); if (NULL == pFuncProcAddr) { return FALSE; } // 使用 CreateRemoteThread 創(chuàng)建遠(yuǎn)線程, 實(shí)現(xiàn) DLL 注入 HANDLE hRemoteThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pFuncProcAddr, pDllAddr, 0, NULL); if (NULL == hRemoteThread) { return FALSE; } // 關(guān)閉句柄 CloseHandle(hProcess); return TRUE; } int main(int argc, char *argv[]) { CreateRemoteThreadInjectDll(4668, "./x86.dll"); system("pause"); return 0; }
x64 實(shí)現(xiàn)遠(yuǎn)程線程注入:
如果想要注入X64程序,則需要在編譯時指定為64位編譯模式,并且使用LoadLibraryW()來加載動態(tài)鏈接庫,我們只需要在上面代碼的基礎(chǔ)上稍加改進(jìn)就可以實(shí)現(xiàn)64位進(jìn)程的注入了.
#include <windows.h> #include <stdio.h> // 使用 CreateRemoteThread 實(shí)現(xiàn)遠(yuǎn)線程注入 BOOL CreateRemoteThreadInjectDll(DWORD Pid, PCWSTR DllName) { BOOL ret = FALSE; HANDLE hProcess, hThread = NULL; FARPROC pfnThreadRtn = NULL; PWSTR pwszPara = NULL; // 打開注入進(jìn)程,獲取進(jìn)程句柄 hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, Pid); if (NULL == hProcess) { return FALSE; } // 計(jì)算欲注入 DLL 文件完整路徑的長度 size_t iProxyFileLen = wcslen(DllName) * sizeof(WCHAR); // 在目標(biāo)進(jìn)程申請一塊長度為 nDllLen 大小的內(nèi)存空間 pwszPara = (PWSTR)VirtualAllocEx(hProcess, NULL, iProxyFileLen, MEM_COMMIT, PAGE_READWRITE); if (NULL == pwszPara) { return FALSE; } // 將欲注入 DLL 文件的完整路徑寫入在目標(biāo)進(jìn)程中申請的空間內(nèi) if (FALSE == WriteProcessMemory(hProcess, pwszPara, (PVOID)DllName, iProxyFileLen, NULL)) { return FALSE; } // 獲得 LoadLibraryW()函數(shù)的地址 pfnThreadRtn = GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryW"); if (NULL == pfnThreadRtn) { return FALSE; } // 使用 CreateRemoteThread 創(chuàng)建遠(yuǎn)線程, 實(shí)現(xiàn) DLL 注入 hThread = CreateRemoteThread(hProcess, NULL, 1024, (LPTHREAD_START_ROUTINE)pfnThreadRtn, pwszPara, 0, NULL); WaitForSingleObject(hThread, INFINITE); if (NULL != hThread) { CloseHandle(hThread); CloseHandle(hProcess); VirtualFreeEx(hProcess, pwszPara, 0, MEM_RELEASE); return TRUE; } return FALSE; } int main(int argc, char *argv[]) { CreateRemoteThreadInjectDll(8224, L"./x64.dll"); system("pause"); return 0; }
實(shí)現(xiàn)普通消息鉤子注入:
Windows提供的鉤子類型非常多,其中一種類型的鉤子非常實(shí)用,那就是WH_GETME SSAGE鉤子,它可以很方便地將DLL文件注入到所有的基于消息機(jī)制的目標(biāo)程序中,代碼非常簡單,這里直接給出DLL文件的代碼,具體如下:
#include <windows.h> extern "C" __declspec(dllexport) VOID SetHookOn(); extern "C" __declspec(dllexport) VOID SetHookOff(); HHOOK g_HHook = NULL; HINSTANCE g_hInst = NULL; VOID DoSomeThing() { MessageBoxA(0, "hello lyshark", 0, 0); } BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved) { switch (fdwReason) { case DLL_PROCESS_ATTACH: { g_hInst = hinstDLL; DoSomeThing(); break; } } return TRUE; } LRESULT CALLBACK GetMsgProc(int code,WPARAM wParam,LPARAM lParam) { return CallNextHookEx(g_HHook, code, wParam, lParam); } VOID SetHookOn() { g_HHook = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, g_hInst, 0); } VOID SetHookOff() { UnhookWindowsHookEx(g_HHook); }
實(shí)現(xiàn)全局消息鉤子注入:
該注入的原理是利用系統(tǒng)中的SetWindowHookEx()這個API函數(shù),該函數(shù)可以攔截目標(biāo)進(jìn)程的消息到指定DLL中的導(dǎo)出函數(shù)上,利用這個特性,我們可以將DLL注入到全局進(jìn)程中,但是在使用SetWindowsHookEx()之前首先需要將HOOK的DLL加載到本身的進(jìn)程中,以此得到DLL的模塊句柄,再使用GetProcAddress()得到DLL中公開的函數(shù)地址,最后遍歷出待注入進(jìn)程的線程ID,這樣SetWindowHookEx()就可以利用這些參數(shù)進(jìn)行HOOK了.
我們先來編寫DLL文件,創(chuàng)建Dll工程hook.cpp然后將SetHook()函數(shù)導(dǎo)出,由于該注入方式是全局注入,所以如果我們想要注入到指定進(jìn)程中,則需要在DllMain()也就是動態(tài)鏈接庫開頭位置進(jìn)行判斷,如果是我們需要Hook的進(jìn)程,則加載Dll到指定進(jìn)程中,如果不是則不執(zhí)行任何操作,這樣一來即可實(shí)現(xiàn)指定進(jìn)程注入.
#include <windows.h> HHOOK Global_Hook; // 設(shè)置全局消息回調(diào)函數(shù) LRESULT CALLBACK MyProc(int nCode, WPARAM wParam, LPARAM lParam) { return CallNextHookEx(Global_Hook, nCode, wParam, lParam); } // 安裝全局鉤子,此處的hook.dll可以是外部其他的dll extern "C" __declspec(dllexport) void SetHook() { Global_Hook = SetWindowsHookEx(WH_CBT, MyProc, GetModuleHandle(TEXT("hook.dll")), 0); } // 卸載全局鉤子 extern "C" __declspec(dllexport) void UnHook() { if(Global_Hook) UnhookWindowsHookEx(Global_Hook); } bool APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { HWND hwnd = FindWindowW(L"valve001",NULL); DWORD pid; GetWindowThreadProcessId(hwnd, &pid); if (GetCurrentProcessId() == pid) { MessageBox(hwnd, TEXT("hello lyshark"), 0, 0); } return true; }
調(diào)用代碼:注意必須將上方編譯好的hook.dll與下方工程放到同一個目錄下,通過LoadLibrary()函數(shù)獲取到模塊句柄,然后通過GetProcAddress()獲取到導(dǎo)出函數(shù)地址,并通過函數(shù)指針調(diào)用,由于全局注入依賴于父進(jìn)程,所以下面的代碼必須一直運(yùn)行.
#include <windows.h> int main(int argc, char *argv[]) { HMODULE hMod = LoadLibrary(TEXT("hook.dll")); typedef void(*pSetHook)(void); pSetHook SetHook = (pSetHook)GetProcAddress(hMod, "SetHook"); SetHook(); while (1) { Sleep(1000); } return 0; }
APC應(yīng)用層異步注入:
APC 是異步過程調(diào)用,在Windows下每個線程在可被喚醒時在其APC鏈中的函數(shù)將有機(jī)會執(zhí)行被執(zhí)行,每一個線程都具有一個APC鏈,那么只要在可以在APC鏈中添加一個APC,就可以完成我們所需要的DLL注入的功能.
1.將需要加載的DLL的完整路徑寫入目標(biāo)進(jìn)程空間.
2.獲得LoadLibraryA()函數(shù)的地址,當(dāng)然也可以是LoadLibraryW()函數(shù)的地址.
3.枚舉目標(biāo)進(jìn)程中的所有線程,為每個線程添加一個APC函數(shù),這樣增加了注入成功的機(jī)會.
該注入的原理是利用當(dāng)線程被喚醒時APC中的注冊函數(shù)會被執(zhí)行的機(jī)制,并以此去執(zhí)行我們的DLL加載代碼,進(jìn)而完成DLL注入的
目的,通過APC注入的流程步驟大致如下
1.當(dāng)EXE里某個線程執(zhí)行到SleepEx()或者WaitForSingleObjectEx()時,系統(tǒng)就會產(chǎn)生一個軟中斷.
2.當(dāng)線程再次被喚醒時,此線程會首先執(zhí)行APC隊(duì)列中的被注冊的函數(shù).
3.利用QueueUserAPC()這個API可以在軟中斷時向線程的APC隊(duì)列插入一個函數(shù)指針,如果我們插入的是Loadlibrary()執(zhí)行函數(shù)的話,就能達(dá)到注入DLL的目的,不論如何目標(biāo)程序必須有執(zhí)行SleepEx()或者WaitForSingleObjectEx()否則DLL不會加載.
#include <windows.h> #include <tlhelp32.h> #include <stdio.h> // APC注入 BOOL ApcInjectDll(DWORD dwPid, char * szDllName) { // 計(jì)算欲注入 DLL 文件完整路徑的長度 int nDllLen = lstrlen(szDllName) + sizeof(char); // 打開目標(biāo)進(jìn)程 HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE, dwPid); if (hProcess == NULL) { return FALSE; } // 在目標(biāo)進(jìn)程申請一塊長度為 nDllLen 大小的內(nèi)存空間 PVOID pDllAddr = VirtualAllocEx(hProcess,NULL, nDllLen,MEM_COMMIT,PAGE_READWRITE); if (pDllAddr == NULL) { CloseHandle(hProcess); return FALSE; } DWORD dwWriteNum = 0; // 將欲注入 DLL 文件的完整路徑寫入在目標(biāo)進(jìn)程中申請的空間內(nèi) WriteProcessMemory(hProcess, pDllAddr, szDllName,nDllLen, &dwWriteNum); CloseHandle(hProcess); THREADENTRY32 te = { 0 }; te.dwSize = sizeof(THREADENTRY32); //得到線程快照 HANDLE handleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); if (INVALID_HANDLE_VALUE == handleSnap) { CloseHandle(hProcess); return FALSE; } // 獲得 LoadLibraryA()函數(shù)的地址 FARPROC pFunAddr = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA"); DWORD dwRet = 0; //得到第一個線程 if (Thread32First(handleSnap, &te)) { do { //進(jìn)行進(jìn)程 ID 對比 if (te.th32OwnerProcessID == dwPid) { //得到線程句柄 HANDLE hThread = OpenThread(THREAD_ALL_ACCESS,FALSE,te.th32ThreadID); if (hThread) { //向線程插入 APC dwRet = QueueUserAPC((PAPCFUNC)pFunAddr,hThread,(ULONG_PTR)pDllAddr); //關(guān)閉句柄 CloseHandle(hThread); } } //循環(huán)下一個線程 } while (Thread32Next(handleSnap, &te)); } CloseHandle(handleSnap); return TRUE; } int main(int argc, char *argv[]) { ApcInjectDll(9608, "c:/x86.dll"); system("pause"); return 0; }
ZwCreateThreadEx強(qiáng)力注入:
在前面的注入方式中,我們使用了CreateRemoteThread()這個函數(shù)來完成線程注入,此方式可以注入普通的進(jìn)程,但卻無法注入到系統(tǒng)進(jìn)程中,因?yàn)橄到y(tǒng)進(jìn)程是處在SESSION0高權(quán)限級別的會話層.
由于CreateRemoteThread()底層會調(diào)用ZwCreateThreadEx()這個未公開的內(nèi)核函數(shù),所以我們必須手動調(diào)用ZwCreateThread()這一內(nèi)核函數(shù),將第七個參數(shù)設(shè)置為0即可,ZwCreateThreadEx函數(shù)在ntdll.dll中并未聲明,所以必須手動使用GetProcAddress函數(shù)將其地址導(dǎo)出.
#include <windows.h> #include <stdio.h> // 使用 ZwCreateThreadEx 實(shí)現(xiàn)遠(yuǎn)線程注入 BOOL ZwCreateThreadExInjectDll(DWORD dwProcessId, char * pDllName) { HANDLE hProcess = NULL; SIZE_T dwSize = 0; LPVOID pDllAddr = NULL; FARPROC pFuncProcAddr = NULL; HANDLE hRemoteThread = NULL; DWORD dwStatus = 0; // 打開注入進(jìn)程,獲取進(jìn)程句柄 hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId); if (NULL == hProcess) { return FALSE; } // 在注入進(jìn)程中申請內(nèi)存 dwSize = sizeof(char)+lstrlen(pDllName); pDllAddr = ::VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE); if (NULL == pDllAddr) { return FALSE; } // 向申請的內(nèi)存中寫入數(shù)據(jù) if (FALSE == ::WriteProcessMemory(hProcess, pDllAddr, pDllName, dwSize, NULL)) { return FALSE; } // 加載 ntdll.dll HMODULE hNtdllDll = ::LoadLibrary("ntdll.dll"); if (NULL == hNtdllDll) { return FALSE; } // 獲取LoadLibraryA函數(shù)地址 pFuncProcAddr = ::GetProcAddress(::GetModuleHandle("Kernel32.dll"), "LoadLibraryA"); if (NULL == pFuncProcAddr) { return FALSE; } // 獲取ZwCreateThread函數(shù)地址 #ifdef _WIN64 typedef DWORD(WINAPI *typedef_ZwCreateThreadEx)( PHANDLE ThreadHandle, ACCESS_MASK DesiredAccess, LPVOID ObjectAttributes, HANDLE ProcessHandle, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, ULONG CreateThreadFlags, SIZE_T ZeroBits, SIZE_T StackSize, SIZE_T MaximumStackSize, LPVOID pUnkown); #else typedef DWORD(WINAPI *typedef_ZwCreateThreadEx)( PHANDLE ThreadHandle, ACCESS_MASK DesiredAccess, LPVOID ObjectAttributes, HANDLE ProcessHandle, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, BOOL CreateSuspended, DWORD dwStackSize, DWORD dw1, DWORD dw2, LPVOID pUnkown); #endif typedef_ZwCreateThreadEx ZwCreateThreadEx = (typedef_ZwCreateThreadEx)::GetProcAddress(hNtdllDll, "ZwCreateThreadEx"); if (NULL == ZwCreateThreadEx) { return FALSE; } // 使用 ZwCreateThreadEx 創(chuàng)建遠(yuǎn)線程, 實(shí)現(xiàn) DLL 注入 dwStatus = ZwCreateThreadEx(&hRemoteThread, PROCESS_ALL_ACCESS, NULL, hProcess, (LPTHREAD_START_ROUTINE)pFuncProcAddr, pDllAddr, 0, 0, 0, 0, NULL); if (NULL == hRemoteThread) { return FALSE; } // 關(guān)閉句柄 ::CloseHandle(hProcess); ::FreeLibrary(hNtdllDll); return TRUE; } int main(int argc, char *argv[]) { BOOL bRet = ZwCreateThreadExInjectDll(2940, "hook.dll"); system("pause"); return 0; }
強(qiáng)制卸載進(jìn)程中的DLL:
#include <Windows.h> #include <stdio.h> #include <TlHelp32.h> BOOL UnLoad_Module(DWORD dwPID, LPCTSTR szDllName) { BOOL bMore = FALSE, bFound = FALSE; HANDLE hSnapshot, hProcess, hThread; HMODULE hModule = NULL; MODULEENTRY32 me = { sizeof(me) }; LPTHREAD_START_ROUTINE pThreadProc; hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID); bMore = Module32First(hSnapshot, &me); for (; bMore; bMore = Module32Next(hSnapshot, &me)) { if (!_tcsicmp((LPCTSTR)me.szModule, szDllName) || !_tcsicmp((LPCTSTR)me.szExePath, szDllName)) { bFound = TRUE; break; } } if (!(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID))) return FALSE; hModule = GetModuleHandle(L"kernel32.dll"); pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hModule, "FreeLibrary"); hThread = CreateRemoteThread(hProcess, NULL, 0, pThreadProc, me.modBaseAddr, 0, NULL); WaitForSingleObject(hThread, INFINITE); if (hThread != 0) { CloseHandle(hThread); CloseHandle(hProcess); CloseHandle(hSnapshot); return TRUE; } return FALSE; } int main(int argc, char *argv[]) { UnLoad_Module(2012, "lyshark.dll"); system("pause"); return 0; }
純匯編實(shí)現(xiàn)遠(yuǎn)程Dll注入:
.data szMyDll db "\lyshark.dll",0h ; 要注入的DLL szDllKernel db "Kernel32.dll",0h szLoadLibrary db "LoadLibraryA",0h lpFileName db "Tutorial-i386",0h ; 指定要注入進(jìn)程 lpDllName dd ? .data? szMyDllFull db MAX_PATH dup (?) lpLoadLibrary dd ? dwProcessID dd ? dwThreadID dd ? hProcess dd ? .code main PROC ; 準(zhǔn)備工作:獲取dll的全路徑文件名、獲取LoadLibrary函數(shù)地址等 invoke GetCurrentDirectory,MAX_PATH,addr szMyDllFull invoke lstrcat,addr szMyDllFull,addr szMyDll invoke GetModuleHandle,addr szDllKernel invoke GetProcAddress,eax,offset szLoadLibrary mov lpLoadLibrary,eax ; 查找文件管理器窗口并獲取進(jìn)程ID,然后打開進(jìn)程 invoke FindWindow,NULL,addr lpFileName invoke GetWindowThreadProcessId,eax,offset dwProcessID mov dwThreadID,eax invoke OpenProcess,PROCESS_ALL_ACCESS,FALSE,dwProcessID mov hProcess,eax ; 在進(jìn)程中分配空間并將DLL文件名拷貝過去,然后創(chuàng)建一個LoadLibrary線程 invoke VirtualAllocEx,hProcess,NULL,MAX_PATH,MEM_COMMIT,PAGE_READWRITE mov lpDllName,eax invoke WriteProcessMemory,hProcess,eax,offset szMyDllFull,MAX_PATH,NULL invoke CreateRemoteThread,hProcess,NULL,0,lpLoadLibrary,lpDllName,0,NULL ret main endp end main
純匯編實(shí)現(xiàn)遠(yuǎn)程代碼注入:
1.首先使用匯編編寫一個代碼注入器,其命名為main.asm
.data lpLoadLibrary dd ? lpGetProcAddress dd ? lpGetModuleHandle dd ? dwProcessID dd ? dwThreadID dd ? hProcess dd ? lpRemoteCode dd ? .const ProcHandle db "lyshark.exe",0h KernelBase db "Kernel32.dll",0h szLoadLibrary db "LoadLibraryA",0h szGetProcAddress db "GetProcAddress",0h szGetModuleHandle db "GetModuleHandleA",0h .code include Macro.inc include ShellCode.asm main proc invoke GetModuleHandle,addr KernelBase mov ebx,eax invoke GetProcAddress,ebx,offset szLoadLibrary mov lpLoadLibrary,eax invoke GetProcAddress,ebx,offset szGetProcAddress mov lpGetProcAddress,eax invoke GetProcAddress,ebx,offset szGetModuleHandle mov lpGetModuleHandle,eax invoke FindWindow,NULL,addr ProcHandle invoke GetWindowThreadProcessId,eax,offset dwProcessID mov dwThreadID,eax invoke OpenProcess,PROCESS_ALL_ACCESS,FALSE,dwProcessID mov hProcess,eax invoke VirtualAllocEx,hProcess,NULL,2048,MEM_COMMIT,PAGE_EXECUTE_READWRITE .if eax mov lpRemoteCode,eax invoke WriteProcessMemory,hProcess,lpRemoteCode,offset REMOTE_CODE_START,1024,NULL invoke WriteProcessMemory,hProcess,lpRemoteCode,offset lpLoadLibrary,sizeof dword * 3,NULL mov eax,lpRemoteCode add eax,offset _RemoteThread - offset REMOTE_CODE_START invoke CreateRemoteThread,hProcess,NULL,0,eax,0,0,NULL invoke CloseHandle,eax .endif invoke CloseHandle,hProcess invoke ExitProcess,NULL ret main endp end main
為了后期編程方便,編寫一個反轉(zhuǎn)宏Macro.inc用來翻轉(zhuǎn)參數(shù),使用定義_invoke調(diào)用更方便
; -------------------------------------------- ; 翻轉(zhuǎn)參數(shù)字節(jié)序 reverseArgs macro arglist:VARARG LOCAL txt,count txt TEXTEQU <> count=0 for i,<arglist> count = count+1 txt TEXTEQU @CatStr(i,<!,>,<%txt>) endm if count GT 0 txt SUBSTR txt,1,@SizeStr(%txt)-1 endif exitm txt endm ; -------------------------------------------- ; 創(chuàng)建類似于INVOKE的宏代碼 _invoke macro _Proc,args:VARARG LOCAL count count = 0 % for i,< reverseArgs( args ) > count = count+1 push i endm call dword ptr _Proc endm
最后編寫注入代碼,此處命名為shellcode.asm該代碼包括了子定位功能.
REMOTE_CODE_START equ this byte _lpLoadLibrary dd ? _lpGetProcAddress dd ? _lpGetModuleHandle dd ? ; -------------------------------------------- ; 存放靜態(tài)資源,比如常量,字符串等. _hInstance dd ? _szShowTitle db "hello lyshark",0h ; -------------------------------------------- ; 存放獲取到的指針 _lpDllUser dd ? _lpMessageBox dd ? ; -------------------------------------------- ; 放入導(dǎo)入函數(shù)的字符串 _szDllUser db "user32.dll",0h _szMessageBox db "MessageBoxA",0h,0 ; -------------------------------------------- _RemoteThread proc uses ebx esi edi LOCAL @hModule ; -------------------------------------------- ; 計(jì)算指令的偏移地址,用ebx作為基址指針 call @F @@: pop ebx sub ebx,offset @B ; -------------------------------------------- _invoke [ebx + _lpGetModuleHandle],NULL ; 取當(dāng)前模塊句柄 mov [ebx + _hInstance],eax lea eax,[ebx + offset _szDllUser] _invoke [ebx + _lpGetModuleHandle],eax ; 取user32.dll模塊句柄 mov @hModule,eax ; -------------------------------------------- ; 循環(huán)獲取每個導(dǎo)入函數(shù)的地址,并放入指針變量保存 lea esi,[ebx + offset _szMessageBox] ; 循環(huán)獲取,從該函數(shù)起始地址處 lea edi,[ebx + offset _lpMessageBox] .while TRUE _invoke [ebx + _lpGetProcAddress],@hModule,esi mov [edi],eax ; 獲取到函數(shù)地址后,放入導(dǎo)入函數(shù)字符串中 add edi,4 ; 每次遞增4字節(jié),指向下一個函數(shù),遇到0則停止 @@: lodsb or al,al jnz @B .break .if !byte ptr [esi] .endw ; -------------------------------------------- ;lea esi,[ebx+ offset _szMessageBox] ; 取msgbox模塊地址 ;_invoke [ebx+_lpGetProcAddress],@hModule,esi ; 獲取地址 ;mov [ebx+_lpMessageBox],eax ; 存入變量中 lea esi,[ebx + offset _szShowTitle] ; 獲取彈窗資源 _invoke [ebx + _lpMessageBox],0,esi,eax,0 ; 調(diào)用信息框 ret _RemoteThread endp
文章出處:https://www.cnblogs.com/lyshark
以上就是c++ 如何實(shí)現(xiàn)線程注入的詳細(xì)內(nèi)容,更多關(guān)于c++ 實(shí)現(xiàn)線程注入的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C語言實(shí)現(xiàn)電話訂餐管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)電話訂餐管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-01-01如何用C寫一個web服務(wù)器之GCC項(xiàng)目編譯
本文主要介紹了,如何用C寫一個web服務(wù)器,Linux下用GCC進(jìn)行項(xiàng)目編譯,對此感興趣的同學(xué),可以參考下。2021-05-05使用單鏈表實(shí)現(xiàn)多項(xiàng)式計(jì)算示例
這篇文章主要介紹了使用單鏈表實(shí)現(xiàn)多項(xiàng)式計(jì)算示例,需要的朋友可以參考下2014-03-03C++使用宏函數(shù)實(shí)現(xiàn)單例模板詳解
在我們?nèi)粘i_發(fā)中,無可避免需要使用單例模式進(jìn)行設(shè)計(jì)類對象。這篇文章主要介紹了如何使用宏函數(shù)實(shí)現(xiàn)單例模板,感興趣的小伙伴可以了解一下2023-02-02