首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

Windows DLL 注入技術實現:遠程線程注入法完整代碼詳解

     編輯:關於C語言

原理:CreateRemoteThread + LoadLibrary

  1. 獲取目標進程 PID(如 explorer.exe/iexplore.exe)
  2. OpenProcess 獲取進程句柄(需 PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE)
  3. VirtualAllocEx 在目標進程分配內存,寫入 DLL 路徑字符串
  4. CreateRemoteThread 在目標進程創建線程,起始地址 = LoadLibraryA,參數 = 分配的內存地址
  5. WaitForSingleObject 等待線程結束,清理資源

完整 C 代碼


#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 解析

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路徑地址

64 位兼容性注意

  • 注入 64 位進程需編譯 64 位注入器,且 DLL 必須為 64 位
  • LoadLibraryA 地址在 64 位下不同,但 kernel32.dll 基址通常共享(ASLR 可能不同,需動態獲取)
  • 指針大小 8 字節,結構體對齊變化

防禦與檢測

  1. EDR 監控:CreateRemoteThread、WriteProcessMemory、VirtualAllocEx 敏感調用鏈
  2. 完整性校驗:模塊列表異常、內存掃描發現非磁盤映射模塊
  3. PPL/受保護進程:OpenProcess 會失敗
  4. 替代注入技術:APC 隊列、線程劫持、COM 劫持、Pipe/窗口消息注入等

法律與道德警示

⚠️ **DLL 注入屬於敏感技術,僅供安全研究、調試、合法擴展場景使用。**
未授權注入他人進程可能違反《計算機信息系統安全保護條例》等法律,構成非法侵入計算機信息系統罪。請嚴格遵守法律法規,僅在授權環境下進行研究。

總結

遠程線程注入是 Windows 平台最經典的 DLL 注入方式。理解其進程間內存操作、線程創建、模塊加載機制,有助於逆向分析、調試器開發、安全防禦。實戰中需處理 32/64 位、ASLR、權限、防禦繞過等工程細節。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved