我需要找到一个特定的svchost进程。我唯一拥有的是命令行语句(二进制路径):c:\windows\system32\svchost.exe -k netsvcs -s Themes
。
如何从中获取processID?
答案 0 :(得分:0)
当然不可能从命令行直接获取进程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
,我们也无法打开受保护的进程,如果我们没有它 - 我们通常可以从自己的登录会话中打开进程(因此对于所有提升的进程,所有系统进程都会失败)。在第二个需要为native和wow64编写不同的代码:如果我们的代码是32位 - 需要检查我们是否wow64进程,如果是 - 首先查询NtWow64QueryInformationProcess64
和NtWow64ReadVirtualMemory64
,然后才能开始查询过程cmd line。
本机进程的代码:
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版本和(如果版本&lt; 8.1)wow64和一旦选择get process 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">