标准用户(XP/Server 2003及以下)如何获取所有运行进程的镜像路径?
Posted
技术标签:
【中文标题】标准用户(XP/Server 2003及以下)如何获取所有运行进程的镜像路径?【英文标题】:How to get the image path of all running processses as a standard user (XP / Server 2003 and below)? 【发布时间】:2014-12-14 14:50:08 【问题描述】:我正在尝试以标准用户的身份获取系统中所有正在运行的进程的完整路径,而无需 Windows XP / Server 2003 上的管理权限。获取所有正在运行的进程的列表和它们的句柄不是问题(Toolhelp“ Process32First”/本机 API“NtQuerySystemInformation”/PsApi“EnumProcesses”)。我的问题是这些调用没有返回正确的进程句柄,而是我首先必须传递给“OpenProcess”以获得正确的进程句柄的某种句柄,然后我可以使用它来查询完整的图像路径(通过调用“ GetProcessImageFileName”或一些低级函数)。但是,对于不是由当前用户启动的进程,如果我不是管理员,“OpenProcess”会失败。
谁能指出我如何检索这些信息的正确方向? Process Hacker 和 Process Explorer 能够做到,所以应该可以。我知道 Process Hacker 的源代码是可用的,但据我了解,它使用某种驱动程序来查询正在运行的进程。
更正:正如 David Heffernan 在他的回答中指出的那样,Process Explorer 和 Process Hacker 在由非管理员用户启动时不会在 Windows XP 上显示完整的图像路径。
这是请求的代码(用 Delphi 编写):
function GetProcessDetails (const th32ProcessID: THandle) : String;
var
szImageFileName : array [0..MAX_PATH] of Char;
hProcess : THandle;
begin
hProcess := OpenProcess (PROCESS_QUERY_INFORMATION or PROCESS_VM_READ,
false, th32ProcessID);
if (hProcess = 0) then
exit;
if (GetProcessImageFileName (hProcess, @szImageFileName [0],
MAX_PATH) > 0) then
Result := szImageFileName;
CloseHandle (hProcess);
end; GetProcessDetails
下面是使用“Process32First / Process32Next”检索进程信息的函数:
procedure FillProcessListToolHelp;
var
hSnapShot : THandle;
PE : TProcessEntry32;
sImageFileName : String;
begin
hSnapShot := CreateToolhelp32Snapshot (TH32CS_SNAPPROCESS, 0);
PE.dwSize := SizeOf (TProcessEntry32);
if (Process32First (hSnapShot, PE)) then
repeat
if (PE.th32ProcessID <> 0) then
sImageFileName := GetProcessDetails (PE.th32ProcessID);
until (Process32Next (hSnapShot, PE) = false);
CloseHandle (hSnapShot);
end; FillProcessListToolHelp
请注意,在调用“FillProcessListToolHelp”之前已经分配了“SeDebugPrivilege”。另外,现在我只对 32 位 Windows 的解决方案感兴趣。
【问题讨论】:
您在 OpenProcess 调用中请求什么权限? OpenProcess 可以被标准用户调用。您只需要传递适当的权限。在您显示代码之前,我们无法告诉您您做错了什么。描述代码本身并没有什么好处。 根据要求,我添加了用于检索进程句柄以及检索进程映像文件名的源代码。 【参考方案1】:您提供的代码按预期工作,并且是您能做的最好的。您可以向其添加更多诊断信息,以更好地了解发生了什么:
hProcess := OpenProcess (PROCESS_QUERY_INFORMATION or PROCESS_VM_READ,
false, th32ProcessID);
if (hProcess = 0) then
begin
Writeln(IntToStr(GetLastError));
exit;
end;
然后您将了解到当OpenProcess
失败时,这是因为GetLastError
正在返回5
,也就是ERROR_ACCESS_DENIED
。这是因为,正如您自己所确定的,有问题的进程由不同的用户拥有。
Windows 安全意味着您的标准用户进程根本无法以必要的访问权限打开这些进程的句柄。如果您希望获取有关这些进程的信息,您需要以足够的权限执行您的代码,例如以管理员身份运行。
我相信在没有管理员权限的情况下你能做的最好的事情就是使用TProcessEntry32
的szExeFile
成员中返回的信息。
$APPTYPE CONSOLE
uses
System.SysUtils, Winapi.Windows, Winapi.TlHelp32;
function GetProcessImageFileName(hProcess: THandle; lpImageFileName: LPTSTR;
nSize: DWORD): DWORD; stdcall;
external 'PSAPI.dll' name 'GetProcessImageFileNameW';
function ImageFileName(const PE: TProcessEntry32): string;
var
szImageFileName: array [0 .. MAX_PATH] of Char;
hProcess: THandle;
begin
Result := PE.szExeFile; // fallback in case the other API calls fail
hProcess := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, false,
PE.th32ProcessID);
if (hProcess = 0) then
exit;
if (GetProcessImageFileName(hProcess, @szImageFileName[0], MAX_PATH) > 0) then
Result := szImageFileName;
CloseHandle(hProcess);
end;
procedure FillProcessListToolHelp;
var
hSnapShot: THandle;
PE: TProcessEntry32;
begin
hSnapShot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PE.dwSize := SizeOf(TProcessEntry32);
if (Process32First(hSnapShot, PE)) then
repeat
if (PE.th32ProcessID <> 0) then
Writeln(ImageFileName(PE));
until (Process32Next(hSnapShot, PE) = false);
CloseHandle(hSnapShot);
end;
begin
FillProcessListToolHelp;
Readln;
end.
现在,在您提出的问题中:
Process Hacker 和 Process Explorer 都能做到,所以应该可以。
但事实并非如此。至少对于我使用的 Process Explorer 而言。以下是 Process Explorer 在以标准用户身份运行时必须为 smss 进程提供的功能:
刚刚试用了 Process Hacker,我可以看到它会产生您想要的信息,即使没有运行提升。因此,如果您想自己执行此操作,您只需要阅读 Process Hacker 并执行其操作即可。
【讨论】:
我的错误——由于某种原因,我错误地认为 Process Hacker 和 Process Explorer 在由非管理员执行时能够返回 Windows XP 上的完整图像路径。所以大卫是正确的。 在 win 7 进程中,黑客可以做到这一点,不知何故 process hacker 的作者有一篇关于 Vista 及更高版本如何工作的文章:wj32.org/wp/2010/03/30/… 可以在此处找到对这些未记录结构的更全面的概述:exploit-monday.com/2013/06/… 整洁。我想这会让你在 Vista 上回家,但 XP 仍然遥不可及。以上是关于标准用户(XP/Server 2003及以下)如何获取所有运行进程的镜像路径?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 JSON 中 datetime 的行为在不同系统(win xp,server 2003)上有所不同?
关于在Windows XP Server 2003下使用libcurl库的一些问题 附编译好的libcurl下载 和使用libcurl访问百度的例子工程