В качестве администратора вы можете получить доступ к PROCESS_QUERY_LIMITED_INFORMATION
(0x1000) для данного процесса, если вы не можете получить PROCESS_QUERY_INFORMATION
(0x400). QueryFullProcessImageNameW
требует ограниченного доступа. Однако даже это не будет работать во всех случаях. Например, дескриптор безопасности на csrss.exe предоставляет только доступ к учетной записи SYSTEM, а не администраторам. Другим примером является service.exe, который работает на уровне целостности (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
Это понятно, чтобы быть отказано в доступе к Idle (0) и системы (4) процессов. Однако интересно, что доступ был отключен PID 4704 даже отладчику. Это audiodg.exe, который является защищенным процессом, как описано в белой бумаге «Защищенные процессы», доступной для загрузки на Windows Hardware Dev Center Archive. Защищенные процессы позволяют запрашивать ограниченную информацию, такую как путь к изображению. Давайте быстро проверим, что это так:
>>> 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'
Вы пытались запустить это под Администратором? – cdarke
да я пробовал ..... – Hila