如何在Windows Native API中使用NtUnmapViewOfSection?RunPE编译报错
进程掏空(RunPE)中NtUnmapViewOfSection编译失败问题解决
问题背景
我正在用C语言实现进程掏空(RunPE)技术,已找到挂起进程的PEB并获取其镜像基址,需要调用NtUnmapViewOfSection函数清空目标进程虚拟内存并替换为自定义程序,但调用该函数时编译失败。已包含<winternl.h>,并在Visual Studio 2019链接器选项中添加了ntdll.lib依赖,且能正常使用NtQueryInformationProcess等其他Native API函数。
相关代码
#include <windows.h> #include <stdio.h> #include <winternl.h> int main(int argc, char* argv[]) { printf("Creating process\r\n"); LPSTARTUPINFOA si = (LPSTARTUPINFOA)calloc(1, sizeof(STARTUPINFOA)); LPPROCESS_INFORMATION pi = (LPPROCESS_INFORMATION)calloc(1, sizeof(PROCESS_INFORMATION)); if (!CreateProcessA ( "C:\\Windows\\sysWOW64\\calc.exe", // Process uses LoadLibraryA and GetProcAddress. TODO: shellcode with LDR. NULL, NULL, NULL, NULL, CREATE_SUSPENDED, NULL, NULL, si, pi )) { printf("Error with CreateProcessA - %d", GetLastError()); return 1; } if (!pi->hProcess) { printf("Error creating process - %d", GetLastError()); return 1; } HANDLE hDestProcess = pi->hProcess; PROCESS_BASIC_INFORMATION* pbi = (PROCESS_BASIC_INFORMATION*)calloc(1, sizeof(PROCESS_BASIC_INFORMATION)); DWORD retLen = 0; if (NtQueryInformationProcess(hDestProcess, ProcessBasicInformation, pbi, sizeof(PROCESS_BASIC_INFORMATION), &retLen)) { printf("Error finding peb - %d", GetLastError()); return 1; } DWORD pebImageBaseOffset = (DWORD)pbi->PebBaseAddress + 0x8; printf("Peb offset: %p\n", pebImageBaseOffset); LPVOID destImageBase = 0; SIZE_T bytesRead; if (!ReadProcessMemory(hDestProcess, (LPCVOID)pebImageBaseOffset, &destImageBase, 0x4, &bytesRead)) { printf("Error getting process's image base - %d", GetLastError()); return 1; } printf("Process image base: %p\n", destImageBase); if (NtUnmapViewOfSection(pi->hProcess, destImageBase)) { printf("Process view unmapping failed"); } // Read other executable file HANDLE sourceFile = CreateFileA("C:\\Windows\\sysWOW64\\cmd.exe", GENERIC_READ, NULL, NULL, OPEN_EXISTING, NULL, NULL); DWORD sourceFileSize = GetFileSize(sourceFile, NULL); DWORD fileBytesRead = 0; LPVOID sourceFileBytes = (LPVOID)malloc(sourceFileSize); ReadFile(sourceFile, sourceFileBytes, sourceFileSize, &fileBytesRead, NULL); /*DWORD bytesWritten = 0; BOOL writeSuccess = WriteProcessMemory(hDestProcess, entryPointAddr, sourceFileBytes, fileBytesRead, &bytesWritten); if (!writeSuccess) { printf("Problem writing to memory - %d", GetLastError()); return 1; }*/ // Resume the main thread ResumeThread(pi->hThread); printf("Process main thread resumed"); // Close handles CloseHandle(pi->hProcess); CloseHandle(pi->hThread); return 0; }
报错信息
尝试包含wdm.h时的错误
Severity Code Description Project File Line Suppression State Error C1083 Cannot open include file: 'wdm.h': No such file or directory process_hollowing_other_exe D:\other_projects\process_hollowing\process_hollowing_other_exe\process_hollowing_other_exe\main.c 4
未通过头文件直接使用函数时的错误
Error LNK2019 unresolved external symbol _NtUnmapViewOfSection referenced in function _main process_hollowing_other_exe D:\other_projects\process_hollowing\process_hollowing_other_exe\process_hollowing_other_exe\main.obj 1
解决方法
移除
wdm.h的包含:wdm.h是Windows驱动开发专用头文件,用户态程序不需要包含它,否则会出现文件找不到的编译错误。手动声明
NtUnmapViewOfSection函数:<winternl.h>中可能没有导出该函数的符号,导致链接器无法解析。在代码开头添加函数声明:
NTSTATUS NTAPI NtUnmapViewOfSection(HANDLE ProcessHandle, PVOID BaseAddress);
- 显式链接
ntdll.lib:即使已经在链接器选项中添加,也可以在代码中用#pragma comment显式指定,避免配置问题:
#pragma comment(lib, "ntdll.lib")
修改后的代码片段示例
#include <windows.h> #include <stdio.h> #include <winternl.h> #pragma comment(lib, "ntdll.lib") NTSTATUS NTAPI NtUnmapViewOfSection(HANDLE ProcessHandle, PVOID BaseAddress); int main(int argc, char* argv[]) { // 原有代码逻辑不变... }
内容的提问来源于stack exchange,提问作者nortain32
相关产品推荐
相关产品推荐

