explorer.exe/iexplore.exe)OpenProcess 獲取進程句柄(需 PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE)VirtualAllocEx 在目標進程分配內存,寫入 DLL 路徑字符串CreateRemoteThread 在目標進程創建線程,起始地址 = LoadLibraryA,參數 = 分配的內存地址WaitForSingleObject 等待線程結束,清理資源
#include
#include
#include
#include
// 目標進程名
LPTSTR TARGET_PROCESS = _T("iexplore.exe");
// 獲取進程 PID
DWORD FindProcess(LPTSTR name) {
HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (snap == INVALID_HANDLE_VALUE) return 0;
PROCESSENTRY32 pe = { sizeof(pe) };
DWORD pid = 0;
if (Process32First(snap, &pe)) {
do {
if (_tcsicmp(pe.szExeFile, name) == 0) {
pid = pe.th32ProcessID;
break;
}
} while (Process32Next(snap, &pe));
}
CloseHandle(snap);
return pid;
}
// 遠程注入 DLL
BOOL RemoteLoadLibrary(DWORD pid, LPCSTR dllPath) {
HANDLE hProcess = OpenProcess(
PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE,
FALSE, pid);
if (!hProcess) return FALSE;
// 分配內存寫入 DLL 路徑
SIZE_T size = strlen(dllPath) + 1;
LPVOID remoteMem = VirtualAllocEx(hProcess, NULL, size, MEM_COMMIT, PAGE_READWRITE);
if (!remoteMem) { CloseHandle(hProcess); return FALSE; }
SIZE_T written;
if (!WriteProcessMemory(hProcess, remoteMem, dllPath, size, &written) || written != size) {
VirtualFreeEx(hProcess, remoteMem, 0, MEM_RELEASE);
CloseHandle(hProcess);
return FALSE;
}
// 創建遠程線程調用 LoadLibraryA
LPTHREAD_START_ROUTINE pLoadLibrary = (LPTHREAD_START_ROUTINE)GetProcAddress(
GetModuleHandle(_T("kernel32.dll")), "LoadLibraryA");
HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, pLoadLibrary, remoteMem, 0, NULL);
if (!hThread) {
VirtualFreeEx(hProcess, remoteMem, 0, MEM_RELEASE);
CloseHandle(hProcess);
return FALSE;
}
WaitForSingleObject(hThread, INFINITE);
// 清理
VirtualFreeEx(hProcess, remoteMem, 0, MEM_RELEASE);
CloseHandle(hThread);
CloseHandle(hProcess);
return TRUE;
}
int main() {
DWORD pid = FindProcess(TARGET_PROCESS);
if (!pid) { printf("Process not found\n"); return 1; }
// 獲取當前目錄下的 injectdll.dll
TCHAR dllPath[MAX_PATH];
GetModuleFileName(NULL, dllPath, MAX_PATH);
_tcscpy(_tcsrchr(dllPath, _T('\\')) + 1, _T("injectdll.dll"));
if (RemoteLoadLibrary(pid, dllPath))
printf("Inject Success! PID=%u\n", pid);
else
printf("Inject Failed!\n");
return 0;
}
| API | 用途 | 關鍵參數 |
|---|---|---|
CreateToolhelp32Snapshot | 進程快照 | TH32CS_SNAPPROCESS |
Process32First/Next | 遍歷進程 | PROCESSENTRY32.szExeFile |
OpenProcess | 打開進程 | 權限組合、PID |
VirtualAllocEx | 遠程分配內存 | MEM_COMMIT | PAGE_READWRITE |
WriteProcessMemory | 寫入遠程內存 | 驗證 written == size |
GetProcAddress(LoadLibraryA) | 獲取載入函數地址 | kernel32.dll 系統 DLL 基址同進程共享 |
CreateRemoteThread | 創建遠程線程 | 起始函數=LoadLibraryA、參數=DLL路徑地址 |
LoadLibraryA 地址在 64 位下不同,但 kernel32.dll 基址通常共享(ASLR 可能不同,需動態獲取)CreateRemoteThread、WriteProcessMemory、VirtualAllocEx 敏感調用鏈OpenProcess 會失敗⚠️ **DLL 注入屬於敏感技術,僅供安全研究、調試、合法擴展場景使用。**
未授權注入他人進程可能違反《計算機信息系統安全保護條例》等法律,構成非法侵入計算機信息系統罪。請嚴格遵守法律法規,僅在授權環境下進行研究。
遠程線程注入是 Windows 平台最經典的 DLL 注入方式。理解其進程間內存操作、線程創建、模塊加載機制,有助於逆向分析、調試器開發、安全防禦。實戰中需處理 32/64 位、ASLR、權限、防禦繞過等工程細節。