У уже созданных процессов токены априори являются типом TokenPrimary. В связи с этим при работе с SetTokenInformation некоторые перечисления TOKEN_INFORMATION_CLASS могут выдавать ошибку 1375 - ERROR_TOKEN_ALREADY_IN_USE (The token is already in use as a primary token). Что интересно многие перечисления спокойно выполняются и меняют токен можно сказать в реальном времени применяя эти изменения. Из этого у меня возникают два вопроса: 1. Почему какие-то перечисления спокойно отрабатывают, а другие выдают ошибку (доступа?), что внутри них разного? 2. Из области теории: возможно ли отсоединить токен от процесса, произвести с ним определенные действия и снова присоединить? Если нет, то возможно ли олицетворенный (Impersonation) токен (через DuplicateTokenEx) сделать основным (Primary)?
Имхо замки стоят в токенах самих процессов. На моей Win7-x64 это вложенная в EPROCESS структура размером ~800 байт. Можно установить WinDbg и сравнивая данные в структурах TOKEN, найти соответствующее поле. Если привязать утилиту "LiveKd" к отладчику WinDbg, то даже вторая машина не нужна, т.к. при каждом запуске LiveKd делает дампы ядерной памяти на текущий момент. Например так выглядит поиск и сам токен процесса "System": Код (Text): 0: kd> !process 0 0 system PROCESS fffffa80039ce040 SessionId: none Cid: 0004 Peb: 00000000 ParentCid: 0000 DirBase: 00187000 ObjectTable: fffff8a000001940 HandleCount: 477. Image: System 0: kd> !process fffffa80039ce040 1 ........ Token fffff8a000004040 ....... 0: kd> dt _token fffff8a000004040 nt!_TOKEN +0x000 TokenSource : _TOKEN_SOURCE +0x010 TokenId : _LUID +0x018 AuthenticationId : _LUID +0x020 ParentTokenId : _LUID +0x028 ExpirationTime : 0x06207526`b64ceb90 +0x030 TokenLock : 0xfffffa80`0396df90 _ERESOURCE +0x038 ModifiedId : _LUID +0x040 Privileges : _SEP_TOKEN_PRIVILEGES +0x058 AuditPolicy : _SEP_AUDIT_POLICY +0x074 SessionId : 0 +0x078 UserAndGroupCount : 5 +0x07c RestrictedSidCount : 0 +0x080 VariableLength : 0xa4 +0x084 DynamicCharged : 0x400 +0x088 DynamicAvailable : 0 +0x08c DefaultOwnerIndex : 1 +0x090 UserAndGroups : 0xfffff8a0`00004350 _SID_AND_ATTRIBUTES +0x098 RestrictedSids : (null) +0x0a0 PrimaryGroup : 0xfffff8a0`00004fb0 Void +0x0a8 DynamicPart : 0xfffff8a0`00004fb0 -> 0x101 +0x0b0 DefaultDacl : 0xfffff8a0`00004fbc _ACL +0x0b8 TokenType : 1 ( TokenPrimary ) +0x0bc ImpersonationLevel : 0 ( SecurityAnonymous ) +0x0c0 TokenFlags : 0x2000 +0x0c4 TokenInUse : 0x1 '' +0x0c8 IntegrityLevelIndex : 4 +0x0cc MandatoryPolicy : 1 +0x0d0 LogonSession : 0xfffff8a0`00001270 _SEP_LOGON_SESSION_REFERENCES +0x0d8 OriginLogonSession : _LUID +0x0e0 SidHash : _SID_AND_ATTRIBUTES_HASH +0x1f0 RestrictedSidHash : _SID_AND_ATTRIBUTES_HASH +0x300 pSecurityAttributes : 0xfffff8a0`00001120 _AUTHZBASEP_SECURITY_ATTRIBUTES_INFORMATION +0x308 SessionObject : (null) +0x310 VariablePart : 0xfffff8a0`000043a0 0: kd> Если посмотреть на мемберов "TOKEN_INFORMATION_CLASS", то большая часть инфы берётся из данной структуры. Поскольку WinDbg поддерживает скрипты, всё/это дело легко автоматизировать.
Marylin, из листинга погуглил на тему IntegrityLevelIndex и нашёл довольно интересную https://windows-internals.com/explo...y-part-2-what-if-we-made-exploitation-harder/ Я как раз пытаюсь понят почему уменьшать уровень целостности можно, а вот увеличивать (по крайней мере до первоначального состояния) нельзя. Простейших код, открывающий токен процесса с доступом к объекту по умолчанию (основному (primary) токену), великолепно отрабатывает на понижение уровня целостности. А вот в обратную сторону говорит, что токен уже используется в качестве основного (primary) Код (C): BOOL SetTokenIntegrityLevel(DWORD SubAuthority) { HANDLE hProcess = nullptr, hToken = nullptr; hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, g_dwProcessId); if (!OpenProcessToken(hProcess, TOKEN_ADJUST_DEFAULT, &hToken)) { CloseHandle(hProcess); return FALSE; } CloseHandle(hProcess); TOKEN_MANDATORY_LABEL TokenMandatoryLabel = { 0 }; TokenMandatoryLabel.Label.Attributes = SE_GROUP_INTEGRITY; static SID_IDENTIFIER_AUTHORITY SidAuthority = SECURITY_MANDATORY_LABEL_AUTHORITY; if (!AllocateAndInitializeSid(&SidAuthority, 1, SubAuthority, 0, 0, 0, 0, 0, 0, 0, &TokenMandatoryLabel.Label.Sid)) { CloseHandle(hToken); return FALSE; } if (!SetTokenInformation(hToken, TokenIntegrityLevel, &TokenMandatoryLabel, sizeof(TOKEN_MANDATORY_LABEL))) { FreeSid(TokenMandatoryLabel.Label.Sid); CloseHandle(hToken); return FALSE; } FreeSid(TokenMandatoryLabel.Label.Sid); CloseHandle(hToken); return TRUE; } Логичный шаг - дублировать токен с уровнем олицетворения. Но это делается для последующего создания процесса (например CreateProcessAsUser), но не для созданного. Олицетворять токен для объекта ядра можно, например https://learn.microsoft.com/en-us/w...hreadsapi/nf-processthreadsapi-setthreadtoken Но вот аналогичной функции для процесса к сожалению нет. Есть ещё одна интересная статья https://www.tiraniddo.dev/2021/06/the-much-misunderstood.html (и самый объёмный материал MSDN по WIC, который мне удалось найти https://learn.microsoft.com/en-us/previous-versions/dotnet/articles/bb625963(v=msdn.10) ) Насколько я могу судить привилегия SeRelabelPrivilege как раз и должна позволять увеличивать уровень целостности, но понять как она работает пока не получилось.
Тема мутная, и о ней мне известно только следующее.. Lsass.exe раздаёт токены каждой учётной записи, а загрузчик образов потом копирует их в процессы. В токене могут быть до 16-ти идентификаторов безопасности со-своими атрибутами SID_AND_ATTRIBUTES (см. whoami /all /fo list). Теперь чтобы защитить ядерные объекты, система привязывает к ним дескрипторы безопасности SECURITY_DESCRIPTOR, линк на который прописывается в заголовке OBJECT_HEADER. Размер хидера =30h байт, и он всегда предваряет сам объект (лежит выше). В SD имеются 2 списка контроля доступа DACL и SACL, причём уровень доверия "Integrity-Level" хранится в последнем SACL. Таким образом юзер со-своим "TOKEN" атакует объект, а "SECURITY_DESCRIPTOR" объекта защищается. Процесс тоже является объектом, который описывает структура EPROCESS, а потому в WinDbg можно просмотреть как его заголовок, так и сам SD: Код (Text): 0: kd> !process 0 0 taskmgr.exe PROCESS fffffa8003b30640 SessionId: 1 Cid: 0d90 Peb: 7fffffdf000 ParentCid: 0764 DirBase: a6ab5000 ObjectTable: fffff8a0036d5c40 HandleCount: 125. Image: taskmgr.exe 0: kd> !object fffffa8003b30640 ObjectHeader: fffffa8003b30610 <---------- Заголовок лежит на 30h выше объекта Type: Process HandleCount: 3 PointerCount: 72 0: kd> dt _object_header fffffa8003b30610 nt!_OBJECT_HEADER +0x000 PointerCount : 0n72 +0x008 HandleCount : 0n3 +0x010 Lock : _EX_PUSH_LOCK +0x018 TypeIndex : 0x7 +0x019 TraceFlags : 0 +0x01a InfoMask : 0x8 +0x01b Flags : 0 +0x020 ObjectCreateInfo : 0xfffffa80`05505d80 +0x028 SecurityDescriptor : 0xfffff8a0`01ac8f53 <------ Сбросить мл.тетраду! +0x030 Body : _QUAD <-------------------- Здесь начинается EPROCESS 0: kd> !sd 0xfffff8a0`01ac8f50 1 ->Revision: 0x1 ->Control : 0x8814 SE_DACL_PRESENT SE_SACL_PRESENT SE_SACL_AUTO_INHERITED SE_SELF_RELATIVE ->Owner : S-1-5-32-544 (Alias: BUILTIN\Администраторы) ->Group : S-1-5-21-xxxx-xxxx-xxxx-513 ->Dacl : ->Ace[0]: ->AceType : ACCESS_ALLOWED_ACE_TYPE ->Dacl : ->Ace[0]: ->AceSize : 0x18 ->Dacl : ->Ace[0]: ->Mask : 0x001fffff ->Dacl : ->Ace[0]: ->SID : S-1-5-32-544 (Alias: BUILTIN\Администраторы) ->Dacl : ->Ace[1]: ->AceType : ACCESS_ALLOWED_ACE_TYPE ->Dacl : ->Ace[1]: ->AceSize : 0x14 ->Dacl : ->Ace[1]: ->Mask : 0x001fffff ->Dacl : ->Ace[1]: ->SID : S-1-5-18 (Well Known Group: NT AUTHORITY\System) ->Dacl : ->Ace[2]: ->AceType : ACCESS_ALLOWED_ACE_TYPE ->Dacl : ->Ace[2]: ->AceSize : 0x1c ->Dacl : ->Ace[2]: ->Mask : 0x00121411 ->Dacl : ->Ace[2]: ->SID : S-1-5-5-0-104982 (no name mapped) ->Sacl : ->Ace[0]: ->AceType : SYSTEM_MANDATORY_LABEL_ACE_TYPE ->Sacl : ->Ace[0]: ->AceSize : 0x14 ->Sacl : ->Ace[0]: ->Mask : 0x00000003 ->Sacl : ->Ace[0]: ->SID : S-1-16-12288 (Mandatory Label: High Mandatory Level) 0: kd> Поле "Mask" в списке DACL определяет флаги доступа к объектам типа RWE/Delete/WriteDAC etc, где 0x1fffff = полный доступ. При этом если тип записи ACE стоит ACCESS_ALLOWED это разрешения, а ACCESS_DENIED = запрет (см.свойства файла на вкладке Безопасность). Но в данном случае интересна запись ACE в последнем листе SACL, в которой Mask=3, а SID хранит уровень целостности объекта IL. Эта маска определяет политику доступа MANDATORY_POLICY и может принимать 4 значения: Код (Text): TOKEN_MANDATORY_POLICY_OFF = 0 ; Политика целостности IL отключена. TOKEN_MANDATORY_POLICY_NO_WRITE_UP = 1 ; Запрет на запись в объекты с более высоким уровнем. TOKEN_MANDATORY_POLICY_NEW_PROCESS_MIN = 2 ; / что-то непонятное / TOKEN_MANDATORY_POLICY_VALID_MASK = 3 ; NO_WRITE_UP + NEW_PROCESS_MIN Соответственно если сбросить данную маску в нуль, то проверки IL вообще можно будет обойти. В advapi32.dll есть SetAclInformation(), которая по сути должна была этим заниматься, но функционал её кастрировали, оставив только бесполезную смену версии и размера записей DACL/SACL. Там-же есть класс api Get\SetSecurityDescriptorXX() - наверное можно ими как-то подобраться к маске SACL, но из под юзера врядли что-то получится, и нужен дров. Ну здесь всё прозрачно.. В токене, поле "UserAndGroups" указывает на массив структур SID_AND_ATTRIBUTES, а общее их кол-во в пределах 16 хранится в поле "UserAndGroupCount". В свою очередь, индекс SID уровня целостности IL в этом массиве лежит в поле "IntegrityLevelIndex" - это и будет указателем на SACL выше. Код (Text): 0: kd> dt _token fffff8a0038c4060 UserAndGroupCount UserAndGroups IntegrityLevelIndex MandatoryPolicy nt!_TOKEN +0x078 UserAndGroupCount : 0xf +0x090 UserAndGroups : 0xfffff8a0`038c4370 _SID_AND_ATTRIBUTES +0x0c8 IntegrityLevelIndex : 0xe +0x0cc MandatoryPolicy : 3 0: kd> dq 0xfffff8a0`038c4370 L20 fffff8a0`038c4370 fffff8a0`038c4460 00000000`00000000 fffff8a0`038c4380 fffff8a0`038c447c 00000000`00000007 fffff8a0`038c4390 fffff8a0`038c4498 00000000`00000007 fffff8a0`038c43a0 fffff8a0`038c44a4 00000000`00000007 fffff8a0`038c43b0 fffff8a0`038c44b0 00000000`0000000f fffff8a0`038c43c0 fffff8a0`038c44c0 00000000`00000007 fffff8a0`038c43d0 fffff8a0`038c44d0 00000000`00000007 fffff8a0`038c43e0 fffff8a0`038c44dc 00000000`00000007 fffff8a0`038c43f0 fffff8a0`038c44e8 00000000`00000007 fffff8a0`038c4400 fffff8a0`038c44f4 00000000`00000007 fffff8a0`038c4410 fffff8a0`038c4500 00000000`00000007 fffff8a0`038c4420 fffff8a0`038c450c 00000000`c0000007 fffff8a0`038c4430 fffff8a0`038c4520 00000000`00000007 fffff8a0`038c4440 fffff8a0`038c452c 00000000`00000007 fffff8a0`038c4450 fffff8a0`038c453c 00000000`00000060 <------ SACL fffff8a0`038c4460 05000000`00000501 02cb6e5a`00000015 0: kd> dq fffff8a0`038c453c L4 fffff8a0`038c453c 10000000`00000101 00000000`00003000 <------ 0x3000 = SID-1-16-12288 fffff8a0`038c454c 00000000`00000000 00000000`00000000 Можно было потестить, почему понижать IL разрешено, а обратно нет. Но пока не до этого, может быть после НГ.
Кстати есть консольная команда icacls, которая позволяет менять атрибуты в записях SACL, в том числе и уровень IL. Так-что если есть соответствующие права, можно заюзать и её, что намного проще реализовать программно: Код (Text): ICACLS имя [/grant[:r] Sid:разрешение[...]] [/deny Sid:разрешение [...]] [/remove[:g|:d]] Sid[...]] [/T] [/C] [/L] [/Q] [/setintegritylevel уровень:политика[...]] /grant[:r] Sid:разрешение - предоставление указанных прав доступа пользователя. При использовании параметра :r эти разрешения заменяют любые ранее предоставленные явные разрешения. Если параметр :r не используется, разрешения добавляются к любым ранее предоставленным явным разрешениям. /deny Sid:разрешение - явный отзыв указанных прав доступа пользователя. ACE явного отзыва добавляется для заявленных разрешений, и любое явное предоставление этих же разрешений удаляется. /remove[:[g|d]] Sid - удаление всех вхождений Sid в ACL. При использовании параметра :g удаляются все вхождения предоставленных прав в этом Sid. При использовании параметра :d удаляются все вхождения отозванных прав в этом Sid. /setintegritylevel [(CI)(OI)]уровень - явное добавление ACE уровня целостности ко всем соответствующим файлам. Уровень может принимать одно из следующих значений: L[ow]: низкий M[edium]: средний H[igh]: высокий Перед уровнем могут указываться параметры наследования для ACE целостности, которые применяются только к каталогам.
Вы говорите о том, что в WinDbg называется "debugger command programs" ?? А получилось заставить нормально эту штуку работать?? У меня цикл из 512 повторов, выполняется 7(!!!) минут. По сути пустой цикл из if(0) {}. Может там какая-то хитрая опция есть, как заставить её нормально работать, подскажите кто знает... Ведь по задумке классная штука, но пришибленная . пс. WinDbg у меня ещё старый.
Да, вроде так называется фишка. Раньше у меня ничё не тормозило, правда на старте была пауза ~1 сек. Но после переустановки системы с ломаной/левой на чистую Win7 с ключом, почему-то перестала работать команда организации цикла .foreach и не только - например вывод !idt тоже сократился в 2-раза, ну и так по мелочам.
Нашёл в архиве свои попытки заставить Windbg нормально работать со скриптами. У кого есть 15 минут и Windbg, сделайте плз, ради статистики: 1. Запускаем Windbg от админа. 2. Выбираем File->Kernel Debug => вкладка Local, ОК. 3. Вводим в командную строку: r $t2 = 0; .for (r $t3 = $t2+1000; $t2 < $t3; r $t2 = $t2+8) { .if ($t2 % 40 == 0) { .printf "$t2 %p\n", $t2 } } 4. Жмём ентер и засекаем время, пока не появится lkd>
Ну здесь даже без тестов проблема очевидна. Да, ваш скрипт исполняется долго, и не дожидаясь окончания я прервал его по Ctrl+Break. Когда вы используете 20 своих псевдо-регистров $t0-$t19, значения им присваиваются как обычно r $t2 = 0. Но когда вы обращаетесь к ним позже, нужно предварять их собакой по типу @$t2, в результате чего парсеру ком.строк не нужно будет обходить весь свой огромный список в поисках алиасов. Другими словами, это исключит двумысленность, и он сразу поймёт, что обращаются именно к псевдо-регистрам. Я переписал ваш скрипт в такой вид, и теперь он исполняется за 0.5 сек. Сохраните следущее в файл "script.txt", и запустите его командой $$>a< F:\script.txt (укажите свой путь): Код (Text): r $t2 = 0 .for (r $t3 = @$t2+1000; @$t2 < @$t3; r @$t2 = @$t2+8) { .if (@$t2 % 40 == 0) { .printf "$t2 %p\n", @$t2 } }
Простой скрипт для WinDbg, который обходит все процессы, и выводит информацию из их структур TOKEN. Достаточно вызвать команду !for_each_process " ", и внутри её кавычек указать нужные действия. К ней привязан псевдорегистр @#Process, в который на каждом степе отладчик будет сбрасывать линк на очередную EPROCESS. В файле скрипта *.txt прописываем следующее: Код (Text): r $t0 = @@C++(#FIELD_OFFSET(_EPROCESS, Token)) !for_each_process " r $t1 = @#Process + @$t0 r $t2 = poi(@$t1) r $t2 = @$t2 >> 4 << 4 dt @#Process nt!_EPROCESS -o ImageFileName dt @$t2 nt!_TOKEN -o SessionId MandatoryPolicy TokenType ImpersonationLevel .echo " ..и загружаем его в режиме kd/lkd командой $$>a< путь - как результат получаем такой лог: Код (Text): 0: kd> $$>a< f:\1234.txt ImageFileName : [15] "System" SessionId : 0 TokenType : 1 ( TokenPrimary ) ImpersonationLevel : 0 ( SecurityAnonymous ) MandatoryPolicy : 1 ImageFileName : [15] "smss.exe" SessionId : 0 TokenType : 1 ( TokenPrimary ) ImpersonationLevel : 0 ( SecurityAnonymous ) MandatoryPolicy : 1 ImageFileName : [15] "csrss.exe" SessionId : 0 TokenType : 1 ( TokenPrimary ) ImpersonationLevel : 0 ( SecurityAnonymous ) MandatoryPolicy : 1 ImageFileName : [15] "wininit.exe" SessionId : 0 TokenType : 1 ( TokenPrimary ) ImpersonationLevel : 0 ( SecurityAnonymous ) MandatoryPolicy : 1 ImageFileName : [15] "csrss.exe" SessionId : 1 TokenType : 1 ( TokenPrimary ) ImpersonationLevel : 0 ( SecurityAnonymous ) MandatoryPolicy : 1 ImageFileName : [15] "winlogon.exe" SessionId : 1 TokenType : 1 ( TokenPrimary ) ImpersonationLevel : 0 ( SecurityAnonymous ) MandatoryPolicy : 1 ImageFileName : [15] "services.exe" SessionId : 0 TokenType : 1 ( TokenPrimary ) ImpersonationLevel : 0 ( SecurityAnonymous ) MandatoryPolicy : 1 ImageFileName : [15] "lsass.exe" SessionId : 0 TokenType : 1 ( TokenPrimary ) ImpersonationLevel : 0 ( SecurityAnonymous ) MandatoryPolicy : 1 ImageFileName : [15] "lsm.exe" SessionId : 0 TokenType : 1 ( TokenPrimary ) ImpersonationLevel : 0 ( SecurityAnonymous ) MandatoryPolicy : 1 ImageFileName : [15] "svchost.exe" SessionId : 0 TokenType : 1 ( TokenPrimary ) ImpersonationLevel : 0 ( SecurityAnonymous ) MandatoryPolicy : 3 ImageFileName : [15] "taskhost.exe" SessionId : 1 TokenType : 1 ( TokenPrimary ) ImpersonationLevel : 0 ( SecurityAnonymous ) MandatoryPolicy : 3 ImageFileName : [15] "dwm.exe" SessionId : 1 TokenType : 1 ( TokenPrimary ) ImpersonationLevel : 0 ( SecurityAnonymous ) MandatoryPolicy : 3 ImageFileName : [15] "explorer.exe" SessionId : 1 TokenType : 1 ( TokenPrimary ) ImpersonationLevel : 0 ( SecurityAnonymous ) MandatoryPolicy : 3 ImageFileName : [15] "GoogleCrashHan" SessionId : 0 TokenType : 1 ( TokenPrimary ) ImpersonationLevel : 0 ( SecurityAnonymous ) MandatoryPolicy : 3 ImageFileName : [15] "igfxsrvc.exe" SessionId : 1 TokenType : 1 ( TokenPrimary ) ImpersonationLevel : 0 ( SecurityAnonymous ) MandatoryPolicy : 3 ImageFileName : [15] "hkcmd.exe" SessionId : 1 TokenType : 1 ( TokenPrimary ) ImpersonationLevel : 0 ( SecurityAnonymous ) MandatoryPolicy : 3 ImageFileName : [15] "igfxpers.exe" SessionId : 1 TokenType : 1 ( TokenPrimary ) ImpersonationLevel : 0 ( SecurityAnonymous ) MandatoryPolicy : 3 ImageFileName : [15] "punto.exe" SessionId : 1 TokenType : 1 ( TokenPrimary ) ImpersonationLevel : 0 ( SecurityAnonymous ) MandatoryPolicy : 3 ImageFileName : [15] "ps64ldr.exe" SessionId : 1 TokenType : 1 ( TokenPrimary ) ImpersonationLevel : 0 ( SecurityAnonymous ) MandatoryPolicy : 3 ImageFileName : [15] "svchost.exe" SessionId : 0 TokenType : 1 ( TokenPrimary ) ImpersonationLevel : 0 ( SecurityAnonymous ) MandatoryPolicy : 3 ImageFileName : [15] "Totalcmd.exe" SessionId : 1 TokenType : 1 ( TokenPrimary ) ImpersonationLevel : 0 ( SecurityAnonymous ) MandatoryPolicy : 3 ImageFileName : [15] "AkelPad.exe" SessionId : 1 TokenType : 1 ( TokenPrimary ) ImpersonationLevel : 0 ( SecurityAnonymous ) MandatoryPolicy : 3 ImageFileName : [15] "livekd64.exe" SessionId : 1 TokenType : 1 ( TokenPrimary ) ImpersonationLevel : 0 ( SecurityAnonymous ) MandatoryPolicy : 3 ImageFileName : [15] "conhost.exe" SessionId : 1 TokenType : 1 ( TokenPrimary ) ImpersonationLevel : 0 ( SecurityAnonymous ) MandatoryPolicy : 3 ImageFileName : [15] "audiodg.exe" SessionId : 0 TokenType : 1 ( TokenPrimary ) ImpersonationLevel : 0 ( SecurityAnonymous ) MandatoryPolicy : 3 ImageFileName : [15] "kd.exe" SessionId : 1 TokenType : 1 ( TokenPrimary ) ImpersonationLevel : 0 ( SecurityAnonymous ) MandatoryPolicy : 3 ImageFileName : [15] "dllhost.exe" SessionId : 0 TokenType : 0 (No matching name) ImpersonationLevel : 0 ( SecurityAnonymous ) MandatoryPolicy : 0 0: kd>
Интересную картину возвращает этот скрипт на виртуалке с WinXP-x32. Здесь видно, что процесс "svchost.exe" дублирует свой токен потомкам, и он превращается из "Anonymous" в "Impersonation". Так-же на хрюше не было и "MandatoryPolicy", в результате чего обычная смена указателя на токен в структуре EPROCESS решала все вопросы с привилегиями. Код (Text): kd> $$>a< c:\1234.txt ImageFileName : [16] "svchost.exe" SessionId : 0 TokenType : 1 ( TokenPrimary ) ImpersonationLevel : 0 ( SecurityAnonymous ) ImageFileName : [16] "svchost.exe" SessionId : 0 TokenType : 1 ( TokenPrimary ) ImpersonationLevel : 2 ( SecurityImpersonation ) ImageFileName : [16] "smss.exe" SessionId : 0x6ae7 TokenType : 0xe1017ba8 (No matching name) ImpersonationLevel : 0xe1017bb4 (No matching name) ........... Но как оказалось, скрипт столкнулся с ещё одной проблемой - это число выделенных бит под счётчик-ссылок "RefCount". Дело в том, что в EPROCESS лежит только указатель на токен, а младшие биты в нём отводятся под счётчик, соответственно чтобы получить валидный адрес, нужно сбросить их в нуль. Так вот на х64 под этот count выделяются 4-бита, а на х32 всего 3. Поэтому скрипт не смог правильно вычислить адрес токена "smss.exe" в логе выше, т.к. я писал его для х64 r $t2 = @$t2 >> 4 << 4. Код (Text): kd> !process 0 0 kd.exe <------- WinXP x32 PROCESS 81548950 Image: kd.exe kd> dt _eprocess 81548950 Token. nt!_EPROCESS +0x0c8 Token : +0x000 Object : 0xe15a6d4d +0x000 RefCnt : 0y101 <---- 3 мл.бита +0x000 Value : 0xe15a6d4d ;//********************************************** 0: kd> !process 0 0 kd.exe PROCESS fffffa800402f8d0 Image: kd.exe 0: kd> dt _eprocess fffffa800402f8d0 token. ntdll!_EPROCESS +0x208 Token : +0x000 Object : 0xfffff8a0`04638a38 +0x000 RefCnt : 0y1000 <------------ 4 мл.бита +0x000 Value : 0xfffff8a0`04638a38