簡體   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