subj --- Сообщение объединено, 28 мар 2026 --- или даже как то их редактировать... потому что вродь на все уровни открывается, анн какая то "заshita" 8D --- Сообщение объединено, 28 мар 2026 --- read - работает почти что со всеми, а вот write... "в процесс писать"
как _программно_ менять уровни защиты процесса? может секретная апи? --- Сообщение объединено, 28 мар 2026 --- ну вродь да --- Сообщение объединено, 28 мар 2026 --- еще интересует как это обновляется... там вродь как хэндлу... !!!!!!!!!!!! --- Сообщение объединено, 28 мар 2026 --- вот кодес --- Сообщение объединено, 28 мар 2026 --- может UAC программно как то снять можно?!
Правильно ли я понимаю, что под «уровнями защиты процесса» вы имеете в виду механизмы вроде изоляции, привилегий, или, например, такие вещи как Protected Process / Protected Process Light в Windows? В этом контексте мне интересно, существует ли какой-либо программный способ (в том числе через недокументированные или внутренние API) изменить эти уровни для уже запущенного процесса. Насколько я понимаю, стандартные документированные средства операционной системы обычно не предоставляют подобной возможности из пользовательского режима, так как это напрямую связано с моделью безопасности и разграничением привилегий. Тем не менее, иногда в сообществе упоминаются «секретные» или внутренние механизмы — хотелось бы уточнить, есть ли в этом хоть какая-то практическая основа, или это скорее область теоретических/исследовательских хакингов с участием драйверов и работы на уровне ядра. Если есть какие-то известные подходы, ограничения или подводные камни (например, зависимость от версии ОС или необходимость подписанных драйверов), буду признателен за разъяснение. Хочешь, могу дополнительно разобрать, как именно в современных ОС реализована модель защиты процессов и почему такие вещи обычно нельзя менять «на лету».
Если речь про intergity level, то как ассемблерщик ассемблерщику докладываю: Код (Python): import ctypes from ctypes import wintypes import os # Константы Windows API PROCESS_QUERY_LIMITED_INFORMATION = 0x1000 TOKEN_QUERY = 0x0008 TokenIntegrityLevel = 25 TH32CS_SNAPPROCESS = 0x00000002 # Структуры для перечисления процессов class PROCESSENTRY32(ctypes.Structure): _fields_ = [ ("dwSize", wintypes.DWORD), ("cntUsage", wintypes.DWORD), ("th32ProcessID", wintypes.DWORD), ("th32DefaultHeapID", ctypes.POINTER(ctypes.c_ulong)), ("th32ModuleID", wintypes.DWORD), ("cntThreads", wintypes.DWORD), ("th32ParentProcessID", wintypes.DWORD), ("pcPriClassBase", wintypes.LONG), ("dwFlags", wintypes.DWORD), ("szExeFile", ctypes.c_char * 260) ] def get_integrity_level(pid): advapi32 = ctypes.windll.advapi32 kernel32 = ctypes.windll.kernel32 # 1. Открываем процесс h_process = kernel32.OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, False, pid) if not h_process: return "Access Denied" h_token = wintypes.HANDLE() try: # 2. Открываем токен процесса if not advapi32.OpenProcessToken(h_process, TOKEN_QUERY, ctypes.byref(h_token)): return "Access Denied" # 3. Получаем размер структуры TOKEN_MANDATORY_LABEL dw_size = wintypes.DWORD() advapi32.GetTokenInformation(h_token, TokenIntegrityLevel, None, 0, ctypes.byref(dw_size)) buffer = ctypes.create_string_buffer(dw_size.value) if advapi32.GetTokenInformation(h_token, TokenIntegrityLevel, buffer, dw_size, ctypes.byref(dw_size)): # В буфере лежит TOKEN_MANDATORY_LABEL. Первый член — SID_AND_ATTRIBUTES # Извлекаем указатель на SID (первые 4/8 байт в зависимости от архитектуры) p_sid = ctypes.cast(buffer, ctypes.POINTER(ctypes.c_void_p)).contents # 4. Получаем RID (уровень целостности) из SID # Берем последний SubAuthority get_count = advapi32.GetSidSubAuthorityCount get_count.restype = ctypes.POINTER(ctypes.c_ubyte) sub_auth_count = get_count(p_sid).contents.value get_auth = advapi32.GetSidSubAuthority get_auth.restype = ctypes.POINTER(wintypes.DWORD) rid = get_auth(p_sid, sub_auth_count - 1).contents.value # Маппинг уровней if rid < 0x1000: return "Untrusted" if rid < 0x2000: return "Low" if rid < 0x3000: return "Medium" if rid < 0x4000: return "High" return "System" finally: if h_token: kernel32.CloseHandle(h_token) kernel32.CloseHandle(h_process) return "Unknown" def list_processes_integrity(): kernel32 = ctypes.windll.kernel32 h_snapshot = kernel32.CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) entry = PROCESSENTRY32() entry.dwSize = ctypes.sizeof(PROCESSENTRY32) print(f"{'PID':<8} {'Integrity':<15} {'Name'}") print("-" * 40) if kernel32.Process32First(h_snapshot, ctypes.byref(entry)): while True: pid = entry.th32ProcessID name = entry.szExeFile.decode('ansi') level = get_integrity_level(pid) print(f"{pid:<8} {level:<15} {name}") if not kernel32.Process32Next(h_snapshot, ctypes.byref(entry)): break kernel32.CloseHandle(h_snapshot) if __name__ == "__main__": list_processes_integrity()
Если рассуждать логически, то при входе юзера в сессию, lsass.exe вручает ему токен, где описываются привилегии и многое другое. Это массивная структура, которая будет подключаться во-все запускаемые от имени данного юзера процессы. Для наглядности можно запросить токен у WinDbg - в EPROCESS имеется линк на него. Вот пример для запущенного мною AkelPad: Код (Text): 0: kd> !process 0 1 akelpad.exe PROCESS fffffa800cf721c0 SessionId: 1 Cid: 0e3c Peb: 7efdf000 ParentCid: 0680 DirBase : 216483000 ObjectTable: fffff8a001d05a00 HandleCount: 95. Image : AkelPad.exe VadRoot : fffffa800fbad310 Vads 89 Clone 0 Private 681. Modified 496. Locked 0. DeviceMap: fffff8a0012e14f0 Token : fffff8a00ce924f0 ;<-------------- .......... 0: kd> dt _token fffff8a00ce924f0 nt!_TOKEN +0x000 TokenSource : _TOKEN_SOURCE +0x010 TokenId : _LUID +0x018 AuthenticationId : _LUID +0x020 ParentTokenId : _LUID +0x028 ExpirationTime : 0x7fffffff`ffffffff +0x030 TokenLock : 0xfffffa80`111336c0 _ERESOURCE +0x038 ModifiedId : _LUID +0x040 Privileges : _SEP_TOKEN_PRIVILEGES +0x058 AuditPolicy : _SEP_AUDIT_POLICY +0x074 SessionId : 1 +0x078 UserAndGroupCount : 0xf +0x07c RestrictedSidCount : 0 +0x080 VariableLength : 0x2bc +0x084 DynamicCharged : 0x400 +0x088 DynamicAvailable : 0 +0x08c DefaultOwnerIndex : 4 +0x090 UserAndGroups : 0xfffff8a0`0ce92800 _SID_AND_ATTRIBUTES ;<------ +0x098 RestrictedSids : (null) +0x0a0 PrimaryGroup : 0xfffff8a0`02f15ab0 +0x0a8 DynamicPart : 0xfffff8a0`02f15ab0 -> 0x501 +0x0b0 DefaultDacl : 0xfffff8a0`02f15acc _ACL +0x0b8 TokenType : 1 ( TokenPrimary ) +0x0bc ImpersonationLevel : 0 ( SecurityAnonymous ) +0x0c0 TokenFlags : 0x2000 +0x0c4 TokenInUse : 0x1 '' +0x0c8 IntegrityLevelIndex : 0xe ;<---------------------- +0x0cc MandatoryPolicy : 3 +0x0d0 LogonSession : 0xfffff8a0`0105e720 _SEP_LOGON_SESSION_REFERENCES +0x0d8 OriginLogonSession : _LUID +0x0e0 SidHash : _SID_AND_ATTRIBUTES_HASH +0x1f0 RestrictedSidHash : _SID_AND_ATTRIBUTES_HASH +0x300 pSecurityAttributes : 0xfffff8a0`0451f7b0 _AUTHZBASEP_SECURITY_ATTRIBUTES_INFO +0x308 SessionObject : 0xfffffa80`0fef6470 +0x310 VariablePart : 0xfffff8a0`0ce928f0 0: kd> Имеется таблица по адресу "UserAndGroups", а кол-во записей SID_AND_ATTRIBUTES в ней указывается в поле "UserAndGroupCount=16". При этом уровень доверенности объекта описывает запись "IntergiryLevelIndex=15" в этой таблице. Полями в структуре оперируют Get/SetTokenInformation(). Права всем объектам ядра (включая процессам) задаются в его дескрипторе безопасности "Security Desc" SD - он хранится в заголовке объекта OBJECT_HEADER. Например объектом для процессов является структура EPROCESS, а заголовок будет лежать на 0x30 байт выше самого объекта. Поскольку в логе уже имеем адрес EPROCESS, то получить хидер того-же AkelPad можно так: Код (Text): 0: kd> dt _object_header fffffa800cf721c0-30 nt!_OBJECT_HEADER +0x000 PointerCount : 0n65 +0x008 HandleCount : 0n5 +0x008 NextToFree : 0x00000000`00000005 Void +0x010 Lock : _EX_PUSH_LOCK +0x018 TypeIndex : 0x7 +0x019 TraceFlags : 0 +0x01a InfoMask : 0x8 +0x01b Flags : 0 +0x020 ObjectCreateInfo : 0xfffffa80`10b5f040 _OBJECT_CREATE_INFORMATION +0x020 QuotaBlockCharged : 0xfffffa80`10b5f040 +0x028 SecurityDescriptor : 0xfffff8a0`01aa5036 ;<---- адрес SD (сбросить мл.тетраду) +0x030 Body : _QUAD ;<------------------ здесь начинается EPROCESS 0: kd> Младшие 4-бита в адресе SD - это счётчик, а потому нужно сбросить их в нуль. Уровень "Integrity Level" задаётся в списке SACL (system access control list) дескриптора SD, и здесь видно, что у меня он имеет значение 12288=0x3000=HIGH (см.софт ProcessHacker): Код (Text): 0: kd> !sd 0xfffff8a0`01aa5030 ->Revision: 0x1 ->Control : 0x8814 SE_DACL_PRESENT SE_SACL_PRESENT SE_SACL_AUTO_INHERITED SE_SELF_RELATIVE ->Owner : S-1-5-32-544 ->Group : S-1-5-21-xxxx-xxxx-xxxx-513 ->Dacl : ->AclRevision: 0x2 ->Dacl : ->AclSize : 0x50 ->Dacl : ->AceCount : 0x3 ->Dacl : ->Ace[0]: ->Type : ACCESS_ALLOWED_ACE_TYPE ->Dacl : ->Ace[0]: ->Flags: 0x0 ->Dacl : ->Ace[0]: ->Size : 0x18 ->Dacl : ->Ace[0]: ->Mask : 0x001fffff ->Dacl : ->Ace[0]: ->SID : S-1-5-32-544 ->Sacl : ->AclRevision: 0x2 ->Sacl : ->AclSize : 0x1c ->Sacl : ->AceCount : 0x1 ->Sacl : ->Ace[0]: ->Type : SYSTEM_MANDATORY_LABEL_ACE_TYPE ->Sacl : ->Ace[0]: ->Flags: 0x0 ->Sacl : ->Ace[0]: ->Size : 0x14 ->Sacl : ->Ace[0]: ->Mask : 0x00000003 <---------------- ->Sacl : ->Ace[0]: ->SID : S-1-16-12288 <------ IL ------ 0: kd> ;//------ Значение маски --------------------- TOKEN_MANDATORY_POLICY_OFF = 0x0 ;// Руль! Для токена не применяется обязательная политика целостности. TOKEN_MANDATORY_POLICY_NO_WRITE_UP = 0x1 ;// Процесс не может выполнять запись в объекты с более высоким уровнем. TOKEN_MANDATORY_POLICY_NEW_PROCESS_MIN = 0x2 ;// Уровень, который является меньшим из уровня родителя и уровня exe-файла. TOKEN_MANDATORY_POLICY_VALID_MASK = 0x3 ;// NO_WRITE_UP + NEW_PROCESS_MIN ;//--- Integrity Level (уровень целостности) ;//--- ML = MANDATORY_LEVEL. RID увеличивается на 1000h ;// SetTokenInformation (hToken, TokenUIAccess, &UIAccess, sizeof(DWORD)); ML_UNTRUSTED db 'S-1-16-0' ,0 ;// недоверенный (Anonymous, нет доступа на запись) ML_LOW db 'S-1-16-4096' ,0 ;// нет доступа на запись к большинству объектов системы ML_MEDIUM db 'S-1-16-8192' ,0 ;// используется обычными приложениями ML_HIGH db 'S-1-16-12288' ,0 ;// <------ права администратора ML_SYSTEM db 'S-1-16-16384' ,0 ;// службы и другие приложения системного уровня ML_PROTECTED_PROCESS db 'S-1-16-20480' ,0 ;// защищённый (используется в ядре, юзеру не доступен) ML_SECURE_PROCESS db 'S-1-16-28672' ,0 ;// наивысший (используется только в Win10) SECURITY_MANDATORY_UNTRUSTED_RID = 0x0000 SECURITY_MANDATORY_LOW_RID = 0x1000 SECURITY_MANDATORY_MEDIUM_RID = 0x2000 SECURITY_MANDATORY_HIGH_RID = 0x3000 <-------- SECURITY_MANDATORY_SYSTEM_RID = 0x4000 SECURITY_MANDATORY_PROTECTED_RID = 0x5000 SECURITY_MANDATORY_SECURE_RID = 0x7000 В advapi32.dll есть много функций для операций с токеном и SD отдельно, и все они через kernelbase уходят корнями в ntdll.dll. Одна из них RtlSetSaclSecurityDescriptor(), которая призвана выставлять флаги в SACL, но по факту кастрирована (видимо в тушке имеются проверки аргументов). Типичной практикой является патч кода функции, чтобы тест аргументов всегда возвращал false. Эти изменения коснутся только проекции ntdll в нашем процессе, т.к. при записи сработает механизм CopyOnWrite. Более того в штате ОС есть мощная утилита ком.строки icacls - тоже оперирует дескриптором SD. Общие сведения (см.меню слева): https://learn.microsoft.com/en-us/windows/win32/secauthz/about-authorization
Давно это всё также разбирал, и даже тулзу написал сурки на Си тут https://github.com/LunarResearch/SystemResearch