You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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   

解决方法

  1. 移除wdm.h的包含:wdm.h是Windows驱动开发专用头文件,用户态程序不需要包含它,否则会出现文件找不到的编译错误。

  2. 手动声明NtUnmapViewOfSection函数:<winternl.h>中可能没有导出该函数的符号,导致链接器无法解析。在代码开头添加函数声明:

NTSTATUS NTAPI NtUnmapViewOfSection(HANDLE ProcessHandle, PVOID BaseAddress);
  1. 显式链接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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 05:45:10