[英]Get ProcessID from binary path (command line statement) in C++
我需要找到一个特定的svchost进程。 我唯一拥有的是命令行语句(二进制路径): c:\\windows\\system32\\svchost.exe -k netsvcs -s Themes
。 如何从中获取processID?
当然不可能直接从命令行获取进程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进程,如果是-首先查询NtWow64QueryInformationProcess64
和NtWow64ReadVirtualMemory64
,然后才可以开始查询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=%x\n", 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> <\SystemRoot\System32\smss.exe>
000001D4 <csrss.exe> <%SystemRoot%\system32\csrss.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%\system32\csrss.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:\Windows\system32\services.exe>
000002C8 <lsass.exe> <C:\Windows\system32\lsass.exe>
0000032C <svchost.exe> <C:\Windows\system32\svchost.exe -k DcomLaunch>
0000036C <svchost.exe> <C:\Windows\system32\svchost.exe -k RPCSS>
000003D8 <dwm.exe> <"dwm.exe">
00000060 <svchost.exe> <C:\Windows\system32\svchost.exe -k netsvcs>
00000144 <svchost.exe> <C:\Windows\System32\svchost.exe -k LocalServiceNetworkRestricted>
00000300 <svchost.exe> <C:\Windows\system32\svchost.exe -k LocalSystemNetworkRestricted>
00000408 <svchost.exe> <C:\Windows\system32\svchost.exe -k LocalServiceNoNetwork>
0000044C <svchost.exe> <C:\Windows\system32\svchost.exe -k LocalService>
00000518 <svchost.exe> <C:\Windows\System32\svchost.exe -k LocalServiceNetworkRestricted>
00000550 <svchost.exe> <C:\Windows\system32\svchost.exe -k LocalServiceNetworkRestricted>
00000564 <svchost.exe> <C:\Windows\system32\svchost.exe -k NetworkService>
00000670 <svchost.exe> <C:\Windows\system32\svchost.exe -k imgsvc>
00000688 <svchost.exe> <C:\Windows\system32\svchost.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:\Windows\Explorer.EXE>
00000A64 <RuntimeBroker.exe> <C:\Windows\System32\RuntimeBroker.exe -Embedding>
00000C2C <ShellExperienceHost.exe> <"C:\Windows\SystemApps\ShellExperienceHost_cw5n1h2txyewy\ShellExperienceHost.exe" -ServerName:App.AppXtk181tbxbce2qsex02s8tw7hfxa9xb3t.mca>
00000C84 <SearchUI.exe> <"C:\Windows\SystemApps\Microsoft.Windows.Cortana_cw5n1h2txyewy\SearchUI.exe" -ServerName:CortanaUI.AppXa50dqqa5gqv4a428c9y1jjw7m3btvepj.mca>
00000E38 <InstallAgent.exe> <C:\Windows\System32\InstallAgent.exe -Embedding>
00000E8C <InstallAgentUserBroker.exe> <C:\Windows\System32\InstallAgentUserBroker.exe -Embedding>
0000089C <WUDFHost.exe> <"C:\Windows\System32\WUDFHost.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">
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.