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

为何NtQuerySystemInformation在x32编译版本中无法正常工作?

问题原因与解决方案

你的代码在32位编译下返回STATUS_INFO_LENGTH_MISMATCH的核心原因是缓冲区分配逻辑错误:你没有根据NtQuerySystemInformation返回的ReturnLength调整缓冲区大小,且循环中始终用0作为ImageName.MaximumLength分配内存,导致无法满足系统要求的缓冲区长度。

关键修正点

  1. 先调用一次NtQuerySystemInformation获取所需的总缓冲区大小(包含结构体和进程路径字符串的完整长度)。
  2. 分配连续的缓冲区,将SYSTEM_PROCESS_ID_INFORMATION结构体和字符串空间放在同一块内存中(系统要求缓冲区连续)。
  3. 用ULONG_PTR转换PID到HANDLE,保证32/64位平台的兼容性。
  4. 正确设置ImageName的Buffer指向结构体后的内存区域,MaximumLength设为总缓冲区大小减去结构体本身的大小。

修正后的完整代码

#include <Windows.h>
#include <ntstatus.h>
#include <winternl.h>
#include <stdio.h>
#pragma comment(lib, "ntdll.lib")

struct SYSTEM_PROCESS_ID_INFORMATION
{
    HANDLE ProcessId;
    UNICODE_STRING ImageName;
};

NTSTATUS GetProcessPath(const DWORD pid)
{
    SYSTEM_PROCESS_ID_INFORMATION info = { 0 };
    info.ProcessId = reinterpret_cast<HANDLE>(static_cast<ULONG_PTR>(pid));

    ULONG ReturnLength = 0;
    // 第一次调用获取所需的总缓冲区大小
    NTSTATUS status = NtQuerySystemInformation(static_cast<SYSTEM_INFORMATION_CLASS>(0x58), &info, sizeof(info), &ReturnLength);
    if (status != STATUS_INFO_LENGTH_MISMATCH)
    {
        return status;
    }

    // 分配包含结构体和字符串的连续缓冲区
    PBYTE pBuffer = static_cast<PBYTE>(LocalAlloc(LMEM_FIXED, ReturnLength));
    if (!pBuffer)
    {
        return STATUS_NO_MEMORY;
    }

    // 初始化缓冲区中的结构体
    SYSTEM_PROCESS_ID_INFORMATION* pInfo = reinterpret_cast<SYSTEM_PROCESS_ID_INFORMATION*>(pBuffer);
    pInfo->ProcessId = info.ProcessId;
    pInfo->ImageName.MaximumLength = static_cast<USHORT>(ReturnLength - sizeof(SYSTEM_PROCESS_ID_INFORMATION));
    pInfo->ImageName.Buffer = reinterpret_cast<PWSTR>(pBuffer + sizeof(SYSTEM_PROCESS_ID_INFORMATION));
    pInfo->ImageName.Length = 0;

    // 第二次调用获取进程路径
    status = NtQuerySystemInformation(static_cast<SYSTEM_INFORMATION_CLASS>(0x58), pInfo, ReturnLength, &ReturnLength);
    if (NT_SUCCESS(status))
    {
        wprintf(L"PID %u 的路径: %s\n", pid, pInfo->ImageName.Buffer);
    }

    LocalFree(pBuffer);
    return status;
}

int main()
{
    // 替换为实际存在的进程ID
    GetProcessPath(9200);
    return 0;
}

补充说明

  • SystemProcessIdInformation(编号0x58)属于未公开API,其行为可能随Windows版本变化,使用时需注意兼容性。
  • 该方法确实可以在非管理员权限下获取其他用户进程的路径(只要当前用户有足够权限访问目标进程)。

内容的提问来源于stack exchange,提问作者Ricky

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 14:25:59