从 C++ 中的二进制路径(命令行语句)获取进程 ID



我需要找到一个特定的svchost进程。我唯一拥有的是命令行语句(二进制路径(:c:windowssystem32svchost.exe -k netsvcs -s Themes. 如何从中获取进程 ID?

当然不可能从命令行直接获取进程ID。 可能的签证 反之亦然 - 从进程 ID 获取进程命令行。 因此可以枚举所有进程并查询它命令行。 并将其与您的字符串进行比较(有趣的是,您"拥有命令行语句"? 它硬编码?

WINBLUE开始 (win 8.1( 存在特殊PROCESSINFOCLASS-ProcessCommandLineInformation(从 8.1 或 10 WDK 中查找<ntddk.h>(。 有了这个,我们可以将进程命令行作为 Unicode 字符串。 这将适用于本机和 WOW64 进程。 进程句柄也只有PROCESS_QUERY_LIMITED_INFORMATION访问权限。 如果我们有SE_DEBUG_PRIVILEGE我们可以用它打开所有进程。 如果我们没有 - 所有, 受保护的进程除外。所以WINBLUE+的代码将是:

volatile UCHAR guz;
OBJECT_ATTRIBUTES zoa = { sizeof(zoa) };
// since WINBLUE (8.1)
NTSTATUS GetProcessCommandLine8(HANDLE UniqueProcess, PUNICODE_STRING CommandLine)
{
HANDLE hProcess;
CLIENT_ID cid = { UniqueProcess };
NTSTATUS status = NtOpenProcess(&hProcess, PROCESS_QUERY_LIMITED_INFORMATION, &zoa, &cid);
if (0 <= status)
{
PVOID stack = alloca(guz);
union {
PVOID buf;
PUNICODE_STRING CmdLine;
};
ULONG cb = 0, rcb = 512;
do 
{
if (cb < rcb) cb = RtlPointerToOffset(buf = alloca(rcb - cb), stack);
if (0 <= (status = NtQueryInformationProcess(hProcess, ProcessCommandLineInformation, buf, cb, &rcb)))
{
status = RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, CmdLine, CommandLine);
break;
}
} while (status == STATUS_INFO_LENGTH_MISMATCH);
NtClose(hProcess);
}
return status;
}

但对于旧系统,一切都变得更加复杂。 需要首先查询ProcessBasicInformation获取进程PEB地址,而不是从PEB获取ProcessParameters(RTL_USER_PROCESS_PARAMETERS(的地址。 最后从中读取CommandLine(UNICODE_STRING(。 但对于这个需求,首先需要具有PROCESS_QUERY_INFORMATION|PROCESS_VM_READ访问权限的开放进程。 结果我们失败了 开放受保护的进程, 即使我们有SE_DEBUG_PRIVILEGE,如果我们没有它 - 我们通常可以从自己的登录会话打开进程(因此所有系统进程和所有提升的进程都失败(。其次需要为本机和 WOW64 情况编写不同的代码:如果我们的代码是 32 位 - 需要检查我们是否 WOW64 进程,如果是 - 先查询NtWow64QueryInformationProcess64NtWow64ReadVirtualMemory64,然后才能开始查询进程 cmd 行。

本机进程的代码:

NTSTATUS GetProcessCommandLineOldNative(HANDLE UniqueProcess, PUNICODE_STRING CommandLine)
{
HANDLE hProcess;
CLIENT_ID cid = { UniqueProcess };
NTSTATUS status = NtOpenProcess(&hProcess, PROCESS_QUERY_INFORMATION|PROCESS_VM_READ, &zoa, &cid);
if (0 <= status)
{
PROCESS_BASIC_INFORMATION pbi;
UNICODE_STRING CmdLine;
union {
_RTL_USER_PROCESS_PARAMETERS * ProcessParameters;
PVOID buf;
PWSTR psz;
};
if (
0 <= (status = NtQueryInformationProcess(hProcess, ProcessBasicInformation, &pbi, sizeof(pbi), 0)) &&
0 <= (status = ZwReadVirtualMemory(hProcess, &((_PEB*)pbi.PebBaseAddress)->ProcessParameters, &ProcessParameters, sizeof(ProcessParameters), 0)) &&
0 <= (status = ZwReadVirtualMemory(hProcess, &ProcessParameters->CommandLine, &CmdLine, sizeof(CmdLine), 0)) &&
0 <= (status = ZwReadVirtualMemory(hProcess, CmdLine.Buffer, buf = alloca(CmdLine.Length), CmdLine.Length, 0))
)
{
CmdLine.Buffer = psz;
status = RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, &CmdLine, CommandLine);
}
NtClose(hProcess);
}
return status;
}

对于 WOW64 进程:

#ifndef _WIN64
extern "C" 
{
__declspec(dllimport) 
NTSTATUS NTAPI NtWow64QueryInformationProcess64 (
HANDLE ProcessHandle,
PROCESSINFOCLASS ProcessInformationClass,
PVOID ProcessInformation,
ULONG ProcessInformationLength,
PULONG ReturnLength
);
__declspec(dllimport) 
NTSTATUS NTAPI NtWow64ReadVirtualMemory64(
HANDLE ProcessHandle,
UINT64 BaseAddress,
PVOID Buffer,
ULONG64 Size,
PULONG64 NumberOfBytesRead
);
PVOID __imp_NtWow64ReadVirtualMemory64, __imp_NtWow64QueryInformationProcess64;
}
#ifdef _M_IX86
#pragma comment(linker, "/alternatename:__imp__NtWow64ReadVirtualMemory64@28=___imp_NtWow64ReadVirtualMemory64")
#pragma comment(linker, "/alternatename:__imp__NtWow64QueryInformationProcess64@20=___imp_NtWow64QueryInformationProcess64")
#endif
NTSTATUS GetProcessCommandLineOldWow(HANDLE UniqueProcess, PUNICODE_STRING CommandLine)
{
struct PROCESS_BASIC_INFORMATION_64 {
NTSTATUS ExitStatus;
UINT64 PebBaseAddress;
UINT64 AffinityMask;
KPRIORITY BasePriority;
UINT64 UniqueProcessId;
UINT64 InheritedFromUniqueProcessId;
};
struct PEB_64
{
UCHAR InheritedAddressSpace;
UCHAR ReadImageFileExecOptions;
UCHAR BeingDebugged;
UCHAR SpareBool;
UINT64 Mutant;
UINT64 ImageBaseAddress;
UINT64 Ldr;
UINT64 ProcessParameters;
};
struct UNICODE_STRING_64 {
USHORT Length;
USHORT MaximumLength;
UINT64 Buffer;
};
struct CURDIR_64 {
UNICODE_STRING_64 DosPath;
UINT64 Handle;
};
struct RTL_USER_PROCESS_PARAMETERS_64 {
ULONG MaximumLength;
ULONG Length;
ULONG Flags;
ULONG DebugFlags;
UINT64 ConsoleHandle;
ULONG ConsoleFlags;
UINT64 StandardInput;
UINT64 StandardOutput;
UINT64 StandardError;
CURDIR_64 CurrentDirectory;
UNICODE_STRING_64 DllPath;
UNICODE_STRING_64 ImagePathName;
UNICODE_STRING_64 CommandLine;
/*...*/
};
HANDLE hProcess;
CLIENT_ID cid = { UniqueProcess };
NTSTATUS status = NtOpenProcess(&hProcess, PROCESS_QUERY_INFORMATION|PROCESS_VM_READ, &zoa, &cid);
if (0 <= status)
{
PROCESS_BASIC_INFORMATION_64 pbi;
UNICODE_STRING_64 CmdLine;
UNICODE_STRING cl;
UINT64 ProcessParameters;
if (
0 <= (status = NtWow64QueryInformationProcess64(hProcess, ProcessBasicInformation, &pbi, sizeof(pbi), 0)) &&
0 <= (status = NtWow64ReadVirtualMemory64(hProcess, pbi.PebBaseAddress + FIELD_OFFSET(PEB_64, ProcessParameters), &ProcessParameters, sizeof(ProcessParameters), 0)) &&
0 <= (status = NtWow64ReadVirtualMemory64(hProcess, ProcessParameters + FIELD_OFFSET(RTL_USER_PROCESS_PARAMETERS_64, CommandLine), &CmdLine, sizeof(CmdLine), 0)) &&
0 <= (status = NtWow64ReadVirtualMemory64(hProcess, CmdLine.Buffer, cl.Buffer = (PWSTR)alloca(CmdLine.Length), CmdLine.Length, 0))
)
{
cl.Length = CmdLine.Length, cl.MaximumLength = CmdLine.MaximumLength;
status = RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, &cl, CommandLine);
}
NtClose(hProcess);
}
return status;
}
NTSTATUS GetProcessCommandLineFail(HANDLE , PUNICODE_STRING )
{
return STATUS_UNSUCCESSFUL;
}
#endif//_WIN64

最后,在开始时,我们需要确定Windows版本和(如果版本<8.1(wow64,并一旦选择获取进程cmdline的过程:

NTSTATUS (*GetProcessCommandLine)(HANDLE UniqueProcess, PUNICODE_STRING CommandLine);
WORD gosVersion;
void InitQueryCmdLine()
{
BOOLEAN b;
RtlAdjustPrivilege(SE_DEBUG_PRIVILEGE, TRUE, FALSE, &b);
ULONG dwMajorVersion, dwMinorVersion;
RtlGetNtVersionNumbers(&dwMajorVersion, &dwMinorVersion, 0);
gosVersion = MAKEWORD(dwMinorVersion, dwMajorVersion);
if (gosVersion < _WIN32_WINNT_WINBLUE)
{
#ifdef _WIN64
GetProcessCommandLine = GetProcessCommandLineOldNative;
#else
GetProcessCommandLine = GetProcessCommandLineFail;
PVOID wow64peb;
if (0 <= NtQueryInformationProcess(NtCurrentProcess(), ProcessWow64Information, &wow64peb, sizeof(wow64peb), 0))
{
if (wow64peb)
{
if (HMODULE hmod = GetModuleHandle(L"ntdll"))
{
if ((__imp_NtWow64ReadVirtualMemory64 = GetProcAddress(hmod, "NtWow64ReadVirtualMemory64")) &&
(__imp_NtWow64QueryInformationProcess64 = GetProcAddress(hmod, "NtWow64QueryInformationProcess64")))
{
GetProcessCommandLine = GetProcessCommandLineOldWow;
}
}
}
else
{
GetProcessCommandLine = GetProcessCommandLineOldNative;
}
}
#endif
}
else
{
GetProcessCommandLine = GetProcessCommandLine8;
}
}

在此之后,我们可以枚举进程并为每个进程查询命令行。

void DumpCmdLines()
{
ULONG cb = 0, rcb = 0x10000;
PVOID stack = alloca(guz);
union {
PVOID buf;
PBYTE pb;
PSYSTEM_PROCESS_INFORMATION pspi;
};
NTSTATUS status;
do 
{
if (cb < rcb)
{
cb = RtlPointerToOffset(buf = alloca(0x1000 + rcb - cb), stack);
}
if (0 <= (status = ZwQuerySystemInformation(SystemProcessInformation, buf, cb, &rcb)))
{
ULONG NextEntryOffset = 0;
do 
{
pb += NextEntryOffset;
if (HANDLE UniqueProcessId = pspi->UniqueProcessId)
{
UNICODE_STRING CommandLine;
status = GetProcessCommandLine(UniqueProcessId, &CommandLine);
if (0 > status)
{
DbgPrint("%p <%wZ> error=%xn", UniqueProcessId, &pspi->ImageName, status);
}
else
{
DbgPrint("%p <%wZ> <%wZ>n", UniqueProcessId, &pspi->ImageName, &CommandLine);
RtlFreeUnicodeString(&CommandLine);
}
}
} while (NextEntryOffset = pspi->NextEntryOffset);
break;
}
} while (status == STATUS_INFO_LENGTH_MISMATCH);
}

和可能的结果 (win10(

00000004 <System> error=c0000225
0000015C <smss.exe> <SystemRootSystem32smss.exe>
000001D4 <csrss.exe> <%SystemRoot%system32csrss.exe ObjectDirectory=Windows SharedSection=1024,20480,768 Windows=On SubSystemType=Windows ServerDll=basesrv,1 ServerDll=winsrv:UserServerDllInitialization,3 ServerDll=sxssrv,4 ProfileControl=Off MaxRequestThreads=16>
00000234 <wininit.exe> <wininit.exe>
0000023C <csrss.exe> <%SystemRoot%system32csrss.exe ObjectDirectory=Windows SharedSection=1024,20480,768 Windows=On SubSystemType=Windows ServerDll=basesrv,1 ServerDll=winsrv:UserServerDllInitialization,3 ServerDll=sxssrv,4 ProfileControl=Off MaxRequestThreads=16>
00000294 <winlogon.exe> <winlogon.exe>
000002C0 <services.exe> <C:Windowssystem32services.exe>
000002C8 <lsass.exe> <C:Windowssystem32lsass.exe>
0000032C <svchost.exe> <C:Windowssystem32svchost.exe -k DcomLaunch>
0000036C <svchost.exe> <C:Windowssystem32svchost.exe -k RPCSS>
000003D8 <dwm.exe> <"dwm.exe">
00000060 <svchost.exe> <C:Windowssystem32svchost.exe -k netsvcs>
00000144 <svchost.exe> <C:WindowsSystem32svchost.exe -k LocalServiceNetworkRestricted>
00000300 <svchost.exe> <C:Windowssystem32svchost.exe -k LocalSystemNetworkRestricted>
00000408 <svchost.exe> <C:Windowssystem32svchost.exe -k LocalServiceNoNetwork>
0000044C <svchost.exe> <C:Windowssystem32svchost.exe -k LocalService>
00000518 <svchost.exe> <C:WindowsSystem32svchost.exe -k LocalServiceNetworkRestricted>
00000550 <svchost.exe> <C:Windowssystem32svchost.exe -k LocalServiceNetworkRestricted>
00000564 <svchost.exe> <C:Windowssystem32svchost.exe -k NetworkService>
00000670 <svchost.exe> <C:Windowssystem32svchost.exe -k imgsvc>
00000688 <svchost.exe> <C:Windowssystem32svchost.exe -k appmodel>
00000698 <dasHost.exe> <dashost.exe {d48bf429-3cb0-4538-8bc9147caa7c9ef1}>
00000AE4 <sihost.exe> <sihost.exe>
00000B00 <taskhostw.exe> <taskhostw.exe {222A245B-E637-4AE9-A93F-A59CA119A75E}>
00000A2C <explorer.exe> <C:WindowsExplorer.EXE>
00000A64 <RuntimeBroker.exe> <C:WindowsSystem32RuntimeBroker.exe -Embedding>
00000C2C <ShellExperienceHost.exe> <"C:WindowsSystemAppsShellExperienceHost_cw5n1h2txyewyShellExperienceHost.exe" -ServerName:App.AppXtk181tbxbce2qsex02s8tw7hfxa9xb3t.mca>
00000C84 <SearchUI.exe> <"C:WindowsSystemAppsMicrosoft.Windows.Cortana_cw5n1h2txyewySearchUI.exe" -ServerName:CortanaUI.AppXa50dqqa5gqv4a428c9y1jjw7m3btvepj.mca>
00000E38 <InstallAgent.exe> <C:WindowsSystem32InstallAgent.exe -Embedding>
00000E8C <InstallAgentUserBroker.exe> <C:WindowsSystem32InstallAgentUserBroker.exe -Embedding>
0000089C <WUDFHost.exe> <"C:WindowsSystem32WUDFHost.exe" -HostGUID:{193a1820-d9ac-4997-8c55-be817523f6aa} -IoEventPortName:HostProcess-cfc003bd-dfb8-4921-bf6c-d6392e543bad -SystemEventPortName:HostProcess-91a86d23-34aa-4a16-9d90-8417b8b3531f -IoCancelEventPortName:HostProcess-126930e6-a2d4-492d-87d4-837dcc9de0f1 -NonStateChangingEventPortName:HostProcess-13646e1e-5d48-479e-a391-22f24bfd3b7c -ServiceSID:S-1-5-80-2652678385-582572993-1835434367-1344795993-749280709 -LifetimeId:be105ab5-26a2-45ef-b565-1b2
0000052C <fontdrvhost.exe> <"fontdrvhost.exe">

最新更新