c++ - 创建挂起的进程并在恢复前重写其内存空间
问题描述
我正在分析代码(见下文):
- 创建一个处于挂起状态的新进程 (
CREATE_SUSPENDED
)。 - 使用取消映射内存空间
pZwUnmapViewOfSection()
。 - 将新的 PE 映像(存储在程序中)写入内存空间。
- 将 RAX 设置为进程的入口点。
- 恢复创建的进程。
我想知道为什么这种方法有效。
如果代码将 PE 映像写入新进程的内存空间,则加载程序不会运行以解析导入等 - 还是CREATE_SUSPENDED
在加载程序执行它之前?
此外,EAX(或 RAX)是否总是在 PE 可执行文件启动时保存其入口点?
/* Create suspended process for program (using current module) */
memset(&si, 0, sizeof(si));
memset(&pi, 0, sizeof(pi));
si.cb = sizeof(si);
if (CreateProcessA(szFileName, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi) == FALSE) {
Debug("[Debug] RunPE(): CreateProcessA(): (%lu)\n", GetLastError());
return FALSE;
}
/* Get thread context (processor-specific register data) */
context.ContextFlags = CONTEXT_FULL;
if (GetThreadContext(pi.hThread, &context) == FALSE) {
Debug("[Debug] RunPE(): GetThreadContext()");
}
/* Unmap memory space of program */
pZwUnmapViewOfSection = (PZUVOS)GetProcAddress(GetModuleHandleA("ntdll.dll"), "ZwUnmapViewOfSection");
pZwUnmapViewOfSection(pi.hProcess, (PVOID)pinh->OptionalHeader.ImageBase);
/* Allocate virtual memory for program */
lpAddress = VirtualAllocEx(pi.hProcess, (PVOID)pinh->OptionalHeader.ImageBase, pinh->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (lpAddress == NULL) {
Debug("[Debug] RunPE(): VirtualAllocEx(): (%lu)\n", GetLastError());
return FALSE;
}
/* Write COFF, optional and section headers into virtual memory */
if (WriteProcessMemory(pi.hProcess, (PVOID)pinh->OptionalHeader.ImageBase, fs->pBuffer, pinh->OptionalHeader.SizeOfHeaders, NULL) == FALSE) {
Debug("[Debug] RunPE(): WriteProcessMemory(): (%lu)\n", GetLastError());
return FALSE;
}
/* Write sections into virtual memory */
for (int i = 0; i < pinh->FileHeader.NumberOfSections; i++) {
/* Compute section header of each section */
pish = (PIMAGE_SECTION_HEADER)((DWORD)fs->pBuffer + pidh->e_lfanew + sizeof(IMAGE_NT_HEADERS) + sizeof(IMAGE_SECTION_HEADER) * i);
/* Write section into virtual memory */
WriteProcessMemory(pi.hProcess, (PVOID)(pinh->OptionalHeader.ImageBase + pish->VirtualAddress), (LPVOID)((DWORD)fs->pBuffer + pish->PointerToRawData), pish->SizeOfRawData, NULL);
}
/* Set entry-point as virtual address: address of entry point */
context.Rax = pinh->OptionalHeader.ImageBase + pinh->OptionalHeader.AddressOfEntryPoint;
if (SetThreadContext(pi.hThread, &context) == FALSE) {
Debug("[Debug]: RunPE(): SetThreadContext(): (%lu)\n", GetLastError());
return FALSE;
}
解决方案
推荐阅读
- rust - 如何从 FuturesUnordered 返回错误?
- typescript - 打字稿重载箭头功能不起作用
- sql - PSQL如何使用可变参数进行递归查询
- ios - 如何使用 segue 维护 UITabBar
- php - 有没有办法在php中解决这个问题
- javascript - 在输入值之前/之后添加不可编辑的文本而不更改值
- angular - 如何将 Angular FormBuilder 与 Angular Material mat-datapicker 一起使用
- r - 如何将我的 data.frame 作为 igraph 对象导入?
- javascript - 大写锁定不会在 Chrome 或 Safari 中触发 mac 上的“keyup”事件
- r - 使用循环连接多个数据帧时出现代码逻辑错误