本文介绍如何根据进程 ID 获取进程命令行参数,使用 Windows NTDLL 提供的未公开 API 实现。
由于需要使用到Windows应用层未公开的 API,而且这些 API 在 Windows 头文件中未提供函数定义,因此我们需要使用GetProcessAddress
动态地从 ntdll.dll 中获取函数地址。
动态获取函数地址本不是一件困难的事情,但是当涉及调用函数比较多时,这个操作就显得比较繁琐了,我们可以直接使用下面的库来简化上述操作。
https://github.com/winsoft666/ndk
下面介绍如何使用ndk
库来根据进程 ID 获取进程命令行参数。
首先需要包含头文件:
1 2 3 4
| extern "C" { #pragma warning(disable : 4005) #include "ntndk.h" }
|
并引入对应 lib:x86\ntdll.lib
或x64\ntdll.lib
。
拿去用吧
具体获取命令行参数的方式已封装到下面GetProcessCommandLine
函数,方便读者食用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
| DWORD GetProcessCommandLine(unsigned int pid, std::wstring& strResult) { BOOL result = false;
SetLastError(0); HANDLE hProcess = NULL; PPEB ppebCopy = NULL; PRTL_USER_PROCESS_PARAMETERS pRtlProcParamCopy = NULL; PWSTR wBufferCopy = NULL; do { hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); if (!hProcess) break;
PROCESS_BASIC_INFORMATION basicInfo; ZeroMemory(&basicInfo, sizeof(PROCESS_BASIC_INFORMATION));
NTSTATUS status = NtQueryInformationProcess(hProcess, ProcessBasicInformation, &basicInfo, sizeof(PROCESS_BASIC_INFORMATION), NULL);
if (!NT_SUCCESS(status)) break;
PPEB ppeb = basicInfo.PebBaseAddress; ppebCopy = (PPEB)malloc(sizeof(PEB)); if (!ppebCopy) break;
result = ReadProcessMemory(hProcess, ppeb, ppebCopy, sizeof(PEB), NULL);
if (!result) break;
PRTL_USER_PROCESS_PARAMETERS pRtlProcParam = ppebCopy->ProcessParameters; pRtlProcParamCopy = (PRTL_USER_PROCESS_PARAMETERS)malloc(sizeof(RTL_USER_PROCESS_PARAMETERS)); if (!pRtlProcParamCopy) break;
result = ReadProcessMemory(hProcess, pRtlProcParam, pRtlProcParamCopy, sizeof(RTL_USER_PROCESS_PARAMETERS), NULL); if (!result) break;
PWSTR wBuffer = pRtlProcParamCopy->CommandLine.Buffer; USHORT len = pRtlProcParamCopy->CommandLine.Length; wBufferCopy = (PWSTR)malloc(len + 2); if (!wBufferCopy) break; memset(wBufferCopy, 0, len + 2);
result = ReadProcessMemory(hProcess, wBuffer, wBufferCopy, len, NULL);
if (result) strResult = wBufferCopy; } while (false);
DWORD dwGLE = 0; if (!result) { dwGLE = GetLastError(); }
if (ppebCopy) free(ppebCopy);
if (pRtlProcParamCopy) free(pRtlProcParamCopy);
if (wBufferCopy) free(wBufferCopy);
if (hProcess) CloseHandle(hProcess);
return dwGLE; }
|