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

如何通过Windows API获取运行进程命令行?PBI结构访问异常

问题分析与修复

核心问题

你遇到的读取访问违例,本质是三个关键错误:

  1. 未检查NtQueryInformationProcess返回值:调用失败时,PROCESS_BASIC_INFORMATION里的PebBaseAddress会是无效值(比如你看到的0xFFFFFFFFFFFFFFDF),直接访问必然触发内存错误。
  2. 跨进程内存访问逻辑错误:PebBaseAddress是目标进程的虚拟地址,不能在当前进程里直接解引用,必须用ReadProcessMemory读取目标进程的内存数据。
  3. 进程句柄权限不足:即使以管理员身份运行,若打开进程时未申请PROCESS_QUERY_INFORMATION或PROCESS_QUERY_LIMITED_INFORMATION权限,NtQueryInformationProcess也会调用失败。

修复后的代码

#include <windows.h>
#include <winternl.h>
#include <cstdlib>
#include <cstring>

// 声明NtQueryInformationProcess函数(若头文件未自动引入)
extern "C" NTSTATUS NTAPI NtQueryInformationProcess(
    HANDLE ProcessHandle,
    PROCESSINFOCLASS ProcessInformationClass,
    PVOID ProcessInformation,
    ULONG ProcessInformationLength,
    PULONG ReturnLength
);

char* handle_commandline(HANDLE hProcess) {
    PROCESS_BASIC_INFORMATION pbi = {0};
    ULONG returnLength = 0;
    NTSTATUS status = NtQueryInformationProcess(
        hProcess,
        ProcessBasicInformation,
        &pbi,
        sizeof(PROCESS_BASIC_INFORMATION),
        &returnLength
    );

    // 检查NtQueryInformationProcess调用是否成功
    if (!NT_SUCCESS(status)) {
        return nullptr;
    }

    // 第一步:读取目标进程的PEB结构
    PEB peb = {0};
    if (!ReadProcessMemory(
        hProcess,
        pbi.PebBaseAddress,
        &peb,
        sizeof(PEB),
        nullptr
    )) {
        return nullptr;
    }

    // 第二步:读取目标进程的RTL_USER_PROCESS_PARAMETERS结构
    RTL_USER_PROCESS_PARAMETERS params = {0};
    if (!ReadProcessMemory(
        hProcess,
        peb.ProcessParameters,
        &params,
        sizeof(RTL_USER_PROCESS_PARAMETERS),
        nullptr
    )) {
        return nullptr;
    }

    // 第三步:读取命令行的Unicode字符串内容
    wchar_t* wcCommandLine = (wchar_t*)malloc(params.CommandLine.Length + sizeof(wchar_t));
    if (!wcCommandLine) {
        return nullptr;
    }
    if (!ReadProcessMemory(
        hProcess,
        params.CommandLine.Buffer,
        wcCommandLine,
        params.CommandLine.Length,
        nullptr
    )) {
        free(wcCommandLine);
        return nullptr;
    }
    wcCommandLine[params.CommandLine.Length / sizeof(wchar_t)] = L'\0'; // 确保Unicode字符串终止

    // 第四步:转换为ANSI字符串
    size_t ansiLength = 0;
    wcstombs_s(&ansiLength, nullptr, 0, wcCommandLine, params.CommandLine.Length);
    char* ansiCommandLine = (char*)malloc(ansiLength + 1);
    if (!ansiCommandLine) {
        free(wcCommandLine);
        return nullptr;
    }
    wcstombs_s(&ansiLength, ansiCommandLine, ansiLength + 1, wcCommandLine, params.CommandLine.Length);
    ansiCommandLine[ansiLength] = '\0';

    free(wcCommandLine);
    return ansiCommandLine;
}

关键修复点说明

  • 添加错误检查:每次系统调用后都验证返回值,避免使用无效数据。
  • 跨进程内存读取:用ReadProcessMemory依次读取目标进程的PEB、进程参数、命令行字符串,确保访问的是目标进程的有效内存空间。
  • 权限补充:打开进程时需指定对应权限,示例代码:
    HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_VM_READ, FALSE, dwProcessId);
    
  • 内存管理:明确内存分配与释放逻辑,避免内存泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 09:42:31