實現原理:
修改進程環境塊中的進程路徑以及命令行信息,從而達到進程偽裝的效果。所以,實現的關鍵在於進程環境塊的獲取。可以通過ntdll.dll中的導出函數NtQueryInformationProcess來獲取指定進程的PEB地址。因為該程序進程可能與目標進程並不在同一個進程內。由於進程空間獨立性的緣故,所以需要通過調用WIN32 API函數ReadProcessMemory和WriteProcessMemory來讀寫目標進程內存。
實現過程:
(1).打開指定進程,獲取進程句柄
(2).從ntdll.dll中獲取NtQueryInformationProcess函數的導出地址
(3).使用NtQueryInformationProcess函數獲取指定的進程基本信息 PROCESS_BASIC_INFORMATION,並從中獲取指定進程的PEB
(4).使用WriteProcessMemory修改PEB中的路徑信息、命令行信息
注意:NtQueryInformationProcess函數沒有關聯導入庫,所以只能動態獲取
實現代碼:
//************************************ // 函數名:CHideDlg::DisguiseProcess // 返回類型:BOOL // 功能: 修改指定PEB中的路徑和命令行信息, 實現進程偽裝 // 參數1:DWORD dwProcessId 需要偽裝的程序的PID // 參數2:wchar_t *lpwszPath 偽裝之后程序的路徑 //************************************ BOOL CHideDlg::DisguiseProcess(DWORD dwProcessId, wchar_t *lpwszPath) { // 打開進程獲取句柄 HANDLE hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId); if (NULL == hProcess) { MessageBox(_T("打開進程失敗!")); return FALSE; } //定義函數指針變量 typedef_NtQueryInformationProcess NtQueryInformationProcess = NULL; PROCESS_BASIC_INFORMATION pbi = { 0 }; PEB peb = { 0 }; RTL_USER_PROCESS_PARAMETERS Param = { 0 }; USHORT usCmdLen = 0; USHORT usPathLen = 0; // 需要通過 LoadLibrary、GetProcessAddress 從 ntdll.dll 中獲取地址 NtQueryInformationProcess = (typedef_NtQueryInformationProcess)::GetProcAddress( ::LoadLibrary(_T("ntdll.dll")), "NtQueryInformationProcess"); if (NULL == NtQueryInformationProcess) { MessageBox(_T("獲取NtQueryInformationProcess函數地址失敗!")); return FALSE; } // 獲取指定進程的基本信息 NTSTATUS status = NtQueryInformationProcess(hProcess, ProcessBasicInformation, &pbi, sizeof(pbi), NULL); if (!NT_SUCCESS(status)) { MessageBox(_T("獲取進程的基本信息失敗!")); return FALSE; } // 獲取指定進程基本信息結構中的PebBaseAddress //::ReadProcessMemory(hProcess, pbi.PebBaseAddress, &peb, sizeof(peb), NULL); // 獲取指定進程環境塊結構中的ProcessParameters, 注意指針指向的是指定進程空間 //::ReadProcessMemory(hProcess, peb.ProcessParameters, &Param, sizeof(Param), NULL); // 修改指定PEB中的路徑信息, 注意指針指向的是指定進程空間 usPathLen = 2 + 2 * ::wcslen(lpwszPath); ::WriteProcessMemory(hProcess, &pbi.PebBaseAddress->ProcessParameters->ImagePathName.Buffer, &lpwszPath, sizeof(PWSTR), NULL); ::WriteProcessMemory(hProcess, &pbi.PebBaseAddress->ProcessParameters->ImagePathName.Length, &usPathLen, sizeof(usPathLen), NULL); ::WriteProcessMemory(hProcess, &pbi.PebBaseAddress->ProcessParameters->ImagePathName.MaximumLength, &usPathLen, sizeof(usPathLen), NULL); // 修改指定PEB中的命令行信息, 注意指針指向的是指定進程空間 //usCmdLen = 2 + 2 * ::wcslen(lpwszPath); ::WriteProcessMemory(hProcess, &pbi.PebBaseAddress->ProcessParameters->CommandLine.Buffer, &lpwszPath,sizeof(PWSTR), NULL); ::WriteProcessMemory(hProcess, &pbi.PebBaseAddress->ProcessParameters->CommandLine.Length, &usPathLen, sizeof(usPathLen), NULL); return TRUE; }