繁体   English   中英

查找Python中每个正在运行的进程的路径

[英]Find the path of every running process in Python

我想在Windows中找到每个正在运行的进程的路径。 我尝试使用psutil模块,但并未显示所有路径。 由于以下错误,它找不到许多进程的路径:“ psutil.AccessDenied”

c = wmi.WMI()
for process in c.Win32_Process():
        p = psutil.Process(int(process.ProcessId))
        try:
            path = p.exe()
        except:
            path = "-"

还有另一种方法来获取流程的路径吗?

作为管理员,如果您无法获得PROCESS_QUERY_INFORMATION (0x400),则可能可以获取给定进程的PROCESS_QUERY_LIMITED_INFORMATION (0x1000)访问权限。 QueryFullProcessImageNameW只需要有限的访问权限。 但是,这并非在所有情况下都可行。 例如,csrss.exe上的安全描述符仅授予对SYSTEM帐户的访问权限,而不授予管理员访问权限。 另一个示例是services.exe,它以System (S-1-16-16384)完整性级别运行,而管理员令牌仅处于High (S-1-16-12288)完整性级别。

通常,您无法打开此类进程的句柄。 但是作为管理员,您几乎可以选择无所不能的SeDebugPrivilege 如果启用此特权,则Windows AccessCheck会突然成为您最好的朋友(但即使是最好的朋友也有其限制)。

以下是一些ctypes代码,用于启用和禁用当前进程访问令牌中的特权。 特权必须首先存在于令牌中,因此请确保使用管理员帐户或以高级管理员(如果使用UAC)运行此特权。

from ctypes import *
from ctypes.wintypes import *

kernel32 = WinDLL('kernel32', use_last_error=True)
advapi32 = WinDLL('advapi32', use_last_error=True)

SE_PRIVILEGE_ENABLED = 0x00000002
TOKEN_ALL_ACCESS = 0x000F0000 | 0x01FF

class LUID(Structure):
    _fields_ = (('LowPart',  DWORD),
                ('HighPart', LONG))

class LUID_AND_ATTRIBUTES(Structure):
    _fields_ = (('Luid',       LUID),
                ('Attributes', DWORD))

class TOKEN_PRIVILEGES(Structure):
    _fields_ = (('PrivilegeCount', DWORD),
                ('Privileges', LUID_AND_ATTRIBUTES * 1))
    def __init__(self, PrivilegeCount=1, *args):
        super(TOKEN_PRIVILEGES, self).__init__(PrivilegeCount, *args)

PDWORD = POINTER(DWORD)
PHANDLE = POINTER(HANDLE)
PLUID = POINTER(LUID)
PTOKEN_PRIVILEGES = POINTER(TOKEN_PRIVILEGES)

def errcheck_bool(result, func, args):
    if not result:
        raise WinError(get_last_error())
    return args

kernel32.CloseHandle.argtypes = (HANDLE,)

kernel32.GetCurrentProcess.errcheck = errcheck_bool
kernel32.GetCurrentProcess.restype = HANDLE

# https://msdn.microsoft.com/en-us/library/aa379295
advapi32.OpenProcessToken.errcheck = errcheck_bool
advapi32.OpenProcessToken.argtypes = (
    HANDLE,  # _In_  ProcessHandle
    DWORD,   # _In_  DesiredAccess
    PHANDLE) # _Out_ TokenHandle

# https://msdn.microsoft.com/en-us/library/aa379180
advapi32.LookupPrivilegeValueW.errcheck = errcheck_bool
advapi32.LookupPrivilegeValueW.argtypes = (
    LPCWSTR, # _In_opt_ lpSystemName
    LPCWSTR, # _In_     lpName
    PLUID)   # _Out_    lpLuid

# https://msdn.microsoft.com/en-us/library/aa375202
advapi32.AdjustTokenPrivileges.errcheck = errcheck_bool
advapi32.AdjustTokenPrivileges.argtypes = (
    HANDLE,            # _In_      TokenHandle
    BOOL,              # _In_      DisableAllPrivileges
    PTOKEN_PRIVILEGES, # _In_opt_  NewState
    DWORD,             # _In_      BufferLength
    PTOKEN_PRIVILEGES, # _Out_opt_ PreviousState
    PDWORD)            # _Out_opt_ ReturnLength

def enable_privilege(privilege):
    hToken = HANDLE()
    luid = LUID()
    advapi32.LookupPrivilegeValueW(None, privilege, byref(luid))
    try:
        advapi32.OpenProcessToken(kernel32.GetCurrentProcess(),
                                  TOKEN_ALL_ACCESS,
                                  byref(hToken))
        tp = TOKEN_PRIVILEGES()
        tp.Privileges[0].Luid = luid
        tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED
        advapi32.AdjustTokenPrivileges(hToken, False,
                                       byref(tp),
                                       sizeof(tp),
                                       None, None)
    finally:
        if hToken:
            kernel32.CloseHandle(hToken)

def disable_privilege(privilege):
    hToken = HANDLE()
    luid = LUID()
    advapi32.LookupPrivilegeValueW(None, privilege, byref(luid))
    try:
        advapi32.OpenProcessToken(kernel32.GetCurrentProcess(),
                                  TOKEN_ALL_ACCESS,
                                  byref(hToken))
        tp = TOKEN_PRIVILEGES()
        tp.Privileges[0].Luid = luid
        tp.Privileges[0].Attributes = 0
        advapi32.AdjustTokenPrivileges(hToken, False,
                                       byref(tp),
                                       sizeof(tp),
                                       None, None)
    finally:
        if hToken:
            kernel32.CloseHandle(hToken)

测试:

if __name__ == '__main__':
    import psutil
    system_process_names = {'smss.exe',
                            'csrss.exe',
                            'wininit.exe',
                            'winlogon.exe',
                            'services.exe',
                            'lsass.exe',
                            'lsm.exe'}
    system_processes = []

    print('SeDebugPrivilege Enabled')
    enable_privilege('SeDebugPrivilege')    
    for proc in psutil.process_iter():
        try:
            name = proc.name().lower()
            path = proc.exe()
        except psutil.AccessDenied:
            print('{:04d} ACCESS_DENIED'.format(proc.pid))
            continue
        if name in system_process_names:
            system_process_names.remove(name)
            system_processes.append(proc)
            print('{:04d} {}'.format(proc.pid, path))
    assert not system_process_names

    print('\nSeDebugPrivilege Disabled')
    disable_privilege('SeDebugPrivilege')
    for proc in system_processes:
        try:
            path = psutil.Process(proc.pid).exe() # avoid cache
        except psutil.AccessDenied:
            path = 'ACCESS DENIED'
        print('{:04d} {}'.format(proc.pid, path))

产量

SeDebugPrivilege Enabled
0000 ACCESS_DENIED
0004 ACCESS_DENIED
0256 C:\Windows\System32\smss.exe
0404 C:\Windows\System32\csrss.exe
0492 C:\Windows\System32\wininit.exe
0540 C:\Windows\System32\winlogon.exe
0588 C:\Windows\System32\services.exe
0596 C:\Windows\System32\lsass.exe
0604 C:\Windows\System32\lsm.exe
4704 ACCESS_DENIED

SeDebugPrivilege Disabled
0256 ACCESS DENIED
0404 ACCESS DENIED
0492 ACCESS DENIED
0540 ACCESS DENIED
0588 ACCESS DENIED
0596 ACCESS DENIED
0604 ACCESS DENIED

拒绝访问空闲(0)和系统(4)进程是可以理解的。 但是,有趣的是,即使对调试器,也无法访问PID 4704。 这是audiodg.exe,它是受保护的进程,如“受保护的进程”白皮书中所述,可从Windows Hardware Dev Center存档下载。 受保护的进程允许查询有限的信息,例如图像路径。 让我们快速验证是否是这种情况:

>>> kernel32.OpenProcess(0x1000, 0, 4704)
304
>>> path = (c_wchar * 260)()
>>> size = c_uint(260)
>>> kernel32.QueryFullProcessImageNameW(304, 0, path, byref(size))
1
>>> path.value
'C:\\Windows\\System32\\audiodg.exe'

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM