如何通过Windows API获取运行进程命令行?PBI结构访问异常
问题分析与修复
核心问题
你遇到的读取访问违例,本质是三个关键错误:
- 未检查
NtQueryInformationProcess返回值:调用失败时,PROCESS_BASIC_INFORMATION里的PebBaseAddress会是无效值(比如你看到的0xFFFFFFFFFFFFFFDF),直接访问必然触发内存错误。 - 跨进程内存访问逻辑错误:
PebBaseAddress是目标进程的虚拟地址,不能在当前进程里直接解引用,必须用ReadProcessMemory读取目标进程的内存数据。 - 进程句柄权限不足:即使以管理员身份运行,若打开进程时未申请
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, ¶ms, 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
相关产品推荐
相关产品推荐

