 |

27.07.2021, 13:17
|
|
Постоянный
Регистрация: 01.09.2019
Сообщений: 378
С нами:
3526561
Репутация:
0
|
|
..продолжимпервую часть статьи, где были представлены общие сведения о системных объектах Win. Чтобы не потерять логическую нить, предыдущая рекомендуется к прочтению, поскольку здесь ставка делается на то, что вы уже знакомы с понятиями: идентификатор пользователя SID, дескриптор безопасности объекта и его список DACL. Организовать качественную подсистему безопасности можно лишь в том случае, когда есть чёткая модель того, что нужно защищать и кому/что разрешается делать. В этой области инженерами Microsoft проделан огромный объём работы, так-что сконцентрируем своё внимание исключительно на основных моментах. За роялем сегодня токен юзера, его права и привилегии.
Содержание:
1. Аутентификация пользователей в системе;
2. Маркер доступа к объектам (токен);
3. Права и привилегии пользователей;
4. Практика – информация о токенах и дескрипторах(SD) процесса;
5. Подводим итоги.
------------------------------------------------
1. Регистрация пользователя в системе
Ядром подсистемы безопасности является служба Lsass.exe, или "Local Security Authority Sub-System". В автозагрузке Win лежит процесс входа пользователей Winlogon.exe, который как швейцар проводит фейс-контроль вновь прибывших и открывает им двери в систему. Winlogon является критическим важным процессом (если убить, то рухнет вся ОС), поэтому провайдер аутентификации Authui.dll и интерфейсное окно входа в систему запускаются внутри дочернего процесса Winlogon, под названием LogonUI.exe (см.папку system32). После того-как пользователь вводит свои учётные данные, процесс LogonUI завершается, а Winlogon остаётся активным, чтобы в фоне отлавливать комбинацию клавиш юзера [Ctrl+Alt+Delete] для смены пользователей. При обнаружении таковой, Winlogon опять зовёт LogonUI и так в бесконечном цикле.
На следующем этапе, Winlogon передаёт имя и пароль юзера в службу безопасности LSA, которая обращается к Authui.dll для аутентификации пользователя. Если всё в порядке и юзер с таким именем существует, провайдер вычисляет NTLM-хеш введённого пасворда и сравнивает его с дайджестом (хешем) из базы данных "диспетчера учётных записей" SAM – Security Account Manager. Если проверка подтвердит пользователя и не найдёт оснований, чтобы выпроводить его за порог, провайдер формирует и возвращает в Lsass уже знакомый нам идентификатор безопасности пользователя SID (Security Identifier). В противном случае, на территории охранной зоны включается ревун, и на незадачливого юзверя направляются сразу несколько ярких прожекторов.
Теперь получив SID, подсистема Lsass вызывает функцию NtCreateToken() в мониторе безопасности SRM, чтобы создать т.н. маркер-доступа клиента "AccessToken". На системах х86-32, структура токена имеет размер 480-байт и в неё заложен профиль безопасности пользователя. Помимо прочего, он содержит в себе SID'ы юзера и группы в которую он входит, а так-же его привилегии. Остальные поля в токене носят информационный характер и в данном случае не представляют для нас интереса. Примерно так выглядит взаимодействие субъектов в этом сообществе:
Обратите внимание, что создавать токены доступа к объектам может не только служба безопасности Lsass, но и мы и с вами, как рядовые пользователи. Благодаря именно этой возможности консольной утилите "runas.exe" удаётся запускать процессы выдавая себя за админа системы. Она использует функцию из библиотеки advapi32.dll LogonUser(), которая пытается зарегать нового юзверя на локальном узле. При удачных обстоятельствах, функция создаёт токен с настройками по умолчанию, и теперь он будет представлять новорождённого юзера во-всех его начинаниях, то как старт процессов и прочее. Если функция нарвётся на шипы подсистемы безопасности и по какой-либо причине не сможет выполнить свою задачу, то в EAX вернёт логический нуль. Вот её прототип:
C-подобный:
Код:
BOOL
LogonUserA
(
LPCSTR lpszUsername
,
;
// имя юзера = произвольное
LPCSTR lpszDomain
,
;
// имя домена/сервера = GetComputerName()
LPCSTR lpszPassword
,
;
// пароль юзера = 0
DWORD dwLogonType
,
;
// тип входа в систему = LOGON32_LOGON_NEW_CREDENTIALS
DWORD dwLogonProvider
,
;
// провайдер обеспечения входа = LOGON32_PROVIDER_DEFAULT (Authui.dll)
PHANDLE phToken
)
;
// сюда вернётся дескриптор токена нового пользователя!
Далее, установив в этом токене нужные привилегии, можно будет вызывать процессы от чужого имени, посредством функции CreateProcessAsUser(). В качестве альтернативы, имеется ещё одна обёртка, сочетающая в себе сразу две функции выше под названием CreateProcessWithLogonW(). Одним выстрелом дробью она и создаёт нового юзера, и сразу запускает указанный в аргументе процесс. В общем выбор у нас широкий, правда в клинических случаях нам как "художникам" самим потребуются некоторые привилегии, но это уже дело техники и всегда можно найти забытый инженерами люк (например использовать не первичный токен, а токен олицетворения, или ограниченный токен).
2. Маркер доступа к объектам "AccessToken"
Токен сам является системным объектом, который хранит SID и привилегии пользователя. Он создаётся локальным органом безопасности LSA после того-как идентификация юзера успешно пройдёт цензуру. В последующем, каждый процесс, который так или иначе запускается от имени данного пользователя, сопровождается копией его токена. Токен используется системой исключительно для предоставления процессу доступа к защищённым объектам, и в зависимости от указанных в нём привилегий позволяет выполнять различные системные операции. Уже упоминалось, что защищённые объекты ожидают пользовательский SID в своих списках DACL, который как-раз и берётся из токена пользователя. В отличии от имени и пароля в базе реестра SAM, токен нигде не сохраняется, а при каждой загрузке системы создаётся вновь.
Алгоритм проверки прав доступа к объекту со стороны нашего процесса выглядит так:
1. Если SID из токена не совпадает с SID в элементе ACE объекта, то осуществляется переход к следующему ACE в цепочке, иначе переход к п.2.
2. Если элемент ACE запрещает доступ к объекту обладателю данного SID, но он является владельцем объекта (и запрос только на чтение), доступ к объекту разрешается, иначе переход к п.3.
3. Если достигнут конец списка DACL – попытка доступа отклоняется.
4. Если DACL объекта пуст, доступ к нему запрещён всем субъектам, за исключением владельца, которому разрешены чтение и изменение списка DACL (право WRITE_DAC).
5. Если у объекта нет дескриптора безопасности SD (например, у файлов на диске FAT), то все могут получить любые права-доступа к данному объекту.
Обсуждать коня в вакууме как-то не комильфо, поэтому проведём небольшой эксперимент в отладчике WinDbg, чтобы посмотреть на токен реального приложения. Значит даём команду
для сбора инфы об активных процессах, и находим среди них адрес окружения своего – я получил
. Теперь передаю этот адрес той-же команде !process, чтобы она отфильтровала лог и вернула информацию только о моём процессе, забросив в топку все остальные. Объём выводимой инфы можно контролировать параметром в диапазоне 0-7, где нуль минимум, а 7 макс.инфы – нам достаточно единицы. В выхлопе отладчика будет красоваться адрес структуры принадлежащего нам токена =
:
C-подобный:
[CODE]
lkd
>
!
process
8
a058d20
1
PROCESS
8
a058d20 SessionId
:
1
Cid
:
0
ab0 Peb
:
7
ffdf000 ParentCid
:
0
abc
DirBase
:
5
f524a40 ObjectTable
:
a8c2b388 HandleCount
:
33.
Image
:
EXAMPLE
.
EXE
Token a5e41030
;
// TOKEN_SOURCE"? Для этого, в конце команды указываем имя интересующего нас поля, и завершаем команду жирной точкой. Можно даже связывать отображение вложенных структур по типу:
Код:
dt _token a5e41030 TokenSource.SourceIdentifier.
(отобразит локальный идентификатор LUID):
C-подобный:
Код:
lkd
>
dt _token a5e41030 TokenSource
.
nt
!
_TOKEN
+
0x000
TokenSource
:
+
0x000
SourceName
:
[
8
]
"User32 "
+
0x008
SourceIdentifier
:
_LUID
2.1. Типы токенов
Обратите внимание на поле по смещению 0x0a4 под названием "TokenType" – это тип токена. Здесь оно хранит константу(1) = TOKEN_PRIMARY. Дело в том, что в природе мирно сосуществуют две разновидности токенов: первичный и наследуемый.
• Первичный токен: Token_Primary = 1
Это основной токен процесса, и создается он только ядром Win. Содержимое представляет информацию о безопасности по умолчанию. Функция UserLogon() и подсистема Lsass всегда создаёт только первичный токен, хэндл которого можно получить вызовом OpenProcessToken(). Ещё одна функция CreateRestrictedToken() тоже создаёт его, но только урезанный в привилегиях вариант, о чём собственно и говорит название "Restricted" (ограниченный). На вход ей нужно подать первичный токен, а на выходе получим только шелуху от него. Такие токены Lsass обычно "дарит" гостям системы.
• Токен олицетворения: Token_Impersonation = 2
Токен данного типа заимствует права первичного токена, чтобы олицетворять клиентский процесс на сервере. К примеру токены олицетворения передаются от процессов к каждому из его потоков, так-что получить дескриптор можно функцией OpenThreadToken(). Однако в полной мере достоинства наследуемых токенов раскрываются в клиент-серверных приложениях, когда серверы предоставляют клиентам такие расшаренные объекты как: файлы, принтеры, базы-данных и прочее.
Получив запрос сервер должен убедиться, что у клиента есть разрешение на доступ к запрашиваемому объекту – для этого ему нужен SID учётной записи клиента, который и передаётся в токене олицетворения механизмом заимствования прав. Меняет тип токена с первичного на токен-олицетворения функция ImpersonateLoggedOnUser(), а обратную операцию проводят RevertToSelf() или DuplicateTokenEx().
3. Привилегии пользователей
Рассмотрим некоторые вопросы лингвистики..
Знаете-ли вы, какая разница между привилегией и правом пользователя? На сайте MSDN привилегией называют расширенные права юзеров, что собственно ничуть не проясняет ситуацию. Однако если уйти в доки с головой, то найти тонкую грань между двумя этими терминами всё-таки можно.
• Права "Rights" (так-же известные как разрешения) всегда связаны с определенным объектом системы, который выдаёт нам право на открытие файла, запись, чтение из него и прочее. Монитор безопасности SRM разграничивает права пользователей на доступ к объекту, просматривая его список DACL. Обычно DACL'ы и их записи АСЕ сохраняются вместе с объектом. Например файловая запись АСЕ лежит прямо рядом с ним на диске – атрибут безопасности файла в NTFS равен 50h (см.спеки Ntfs):
•Привилегии-же связаны с определенными действиями в системе, и предоставляются пользователям, а не объектам. Они позволяют переопределять права на доступ к объекту, поэтому с их назначением мы (как админы) должны быть очень осторожны. Например юзер с привилегией
может без проблем перезаписать практически любой файл в системе, а привилегия
наоборот позволяет считать защищённый системный файл.
Добавляет привилегий в токен функция AdjustTokenPrivileges(), но перед этим не помешало-бы узнать полный их список в системе. Проблема в том, что за время своего существования Win не однократно редактировала этот лист и может получиться так, что поддержка требуемой нам привилегии просто прекратилась и её место заняла какая-нибудь новая. Например начиная с Win-7, широко известной привилегии SeTcbPrivilege с идентификатором(7) уже не существует, и можно долго гадать, почему-же она не выставляется.
Функции для работы с подсистемой безопасности Lsass сосредоточены в библиотеке пользовательского уровня Advapi32.dll (advanced, расширенные API). Среди них имеются две интересные функции Set/GetTokenInformation(), которые как и следует из названий оперируют информацией в токене. Вот их прототип:
C-подобный:
Код:
BOOL GetTokenInformation
TokenHandle dd
0
;
// дескриптор токена
TokenInformationClass dd
0
;
// класс запрашиваемой информации
TokenInformation dd
0
;
// линк на буфер под инфу
TokenInformationLength dd
0
;
// размер буфера
ReturnLength dd
0
;
// переменная, куда вернётся кол-во байт
Значит в первый аргумент передаём дескриптор токена, который возвращает OpenProcessToken(). Во-втором аргументе нужно указать класс/тип запрашиваемой информации – поскольку мы планируем получить список системных привилегий, то ставим константу(3) "TokenPrivileges". Для этих функции всего предусмотрено 48 разнообразных классов, и соответственно такое-же количество информации о токене они способны вернуть. В следующих аргументах указываем адрес и размер буфера, а так-же адрес переменной, куда функция вернёт требуемый размер буфа для конкретного типа инфы.
Если функция отработает успешно, вернёт в EAX логическую единицу и в буфере получим данные, которые описывает структура "TOKEN_PRIVILEGES". Первое поле в ней "PrivilegeCount" – это общее число поддерживаемых привилегий, а дальше следует массив вложенных структур "LUID_AND_ATTRIBUTES" с описанием каждой привилегии в отдельности. Таким образом, первое поле хранит кол-во вложенных структур, что совпадает с кол-вом зареганных в системе привилегий. Чтобы узнать, какие из общего списка назначены нам, нужно будет проверить поле с атрибутом во-вложенных структурах.
C-подобный:
Код:
struct TOKEN_PRIVILEGES
PrivilegeCount dd
0
Privileges LUID_AND_ATTRIBUTES
ends
;
//--------------------
struct LUID_AND_ATTRIBUTES
Luid dq
0
;
// ID привилегии (8-байт)
Attributes dd
0
;
// откл(0), вкл.в дефолте(1), вкл.программно(2)
ends
Так мы получим в буфере идентификаторы LUID всех привилегий (Local Identifier), и чтобы привести их в дружелюбный текстовый вид, нужно будет позвать функцию LookupPrivilegeName(). Она ожидает на входе идентификатор, и возвращает соответствующую ему строку. Родственная ей функция LookupPrivilegeValue() проводит обратную операцию, т.е. принимая имя, возвращает LUID. Завернём всё вышесказанное в код:
C-подобный:
Код:
format pe console
entry start
;
//------------
section
'.inc'
data readable
include
'win32ax.inc'
include
'equates\advapi32.inc'
;
//------------
.
data
szEnabled db
'
;
//----- Открываем первичный токен своего процесса
invoke GetCurrentProcess
invoke OpenProcessToken
,
eax
,
TOKEN_QUERY
,
hToken
;
//----- Запрос списка привелегий в токене
;
//----- (первый вызов возвращает требуемый размер буфера)
invoke GetTokenInformation
,
[
hToken
]
,
TokenPrivileges
,
buff
,
0
,
pReturn
invoke GetTokenInformation
,
[
hToken
]
,
TokenPrivileges
,
buff
,
[
pReturn
]
,
pReturn
cinvoke printf
,
,
dword
[
buff
]
;
//----- В буфере лежат все привилегии - перебираем их..
align
16
mov ecx
,
dword
[
buff
]
;
// PrivilegeCount
mov esi
,
buff
+
4
;
// начало массива "LUID_AND_ATTRIBUTES"
@@
:
push esi ecx esi
mov
[
strSize
]
,
128
;
// обновить длину строки
mov eax
,
[
esi
]
;
// LUID очередной привилегии
push eax
invoke LookupPrivilegeName
,
0
,
esi
,
privStr
,
strSize
;
// в строку его,
pop eax
cinvoke printf
,
,
eax
,
privStr
;
// ..и на консоль
pop eax
mov eax
,
[
eax
+
8
]
;
// взять атрибут
or eax
,
eax
;
// если нуль (отключена),
je @next
;
// ..пропустить.
mov esi
,
szEnabled
;
// иначе: попалась активная привилегия!
cmp eax
,
SE_PRIVILEGE_ENABLED
;
// программно включена?
je @prn
mov esi
,
szDefault
;
// значит идёт в дефолте.
@prn
:
cinvoke printf
,
,
esi
@next
:
pop ecx esi
add esi
,
sizeof
.
LUID_AND_ATTRIBUTES
;
// перейти в массиве на сл.привилегию
dec ecx
;
// счётчик -1
jnz @b
;
// повторить, если не нуль..
@exit
:
cinvoke _getch
cinvoke exit
,
0
;
//------------
section
'.idata'
import data readable
library kernel32
,
'kernel32.dll'
,
msvcrt
,
'msvcrt.dll'
,
advapi32
,
'advapi32.dll'
include
'api\kernel32.inc'
include
'api\msvcrt.inc'
include
'api\advapi32.inc'
Если верить функции GetTokenInformation() (а не верить ей у нас нет причин), то семёрка поддерживает всего 24 привилегии, причём по-умолчанию у меня (как входящего в группу админов) включены только три из них. "ChangeNotify" имеют все пользователи, "Impersonate" позволяет олицетворять себя с другими лицами, а привилегию "CreateGlobal" система назначает только админам, что даём им право создавать глобальные объекты в пространстве имён. Список всех привилегий и заложенный в них глубокий смысл можно найти в репозитории MSDNпо этой ссылке.
Обратите внимание на идентификаторы – первые четыре привилегии(0,1,2,3) под семёркой уже отправлены в утиль, причём и дальше порядок не последовательный. Более того, содержимое листа привязано и к версии операционной системы. Так, запустив этот код на своём буке с Win-10 я обнаружил, что в ней пропала привилегия с идентификатором(4), зато появилась новая с LUID=36, под громким названием "SeDelegateSessionUserImpersonatePrivilege". На сайте RSDN есть статья"Что такое привилегии?"– можете почитать на досуге.
3.1. Включение привилегий в токене
Ладно, лист поддержки получили.. теперь попробуем повысить себя в ранге и добавить парочку привилегий в токен функцией AdjustTokenPrivileges(). Она может как включать, так и отключать ненужные привилегии. Данная операция требует, чтобы токен был открыт с доступом
Код:
TOKEN_QUERY + TOKEN_ADJUST_PRIVILEGES
. Вот её описание:
C-подобный:
Код:
BOOL AdjustTokenPrivileges
TokenHandle dd
0
;
// хендл токена безопасности
DisableAllPrivileges dd
0
;
// 1 = отмена всех привилегий, 0 = добавить в токен
NewState dd
0
;
// нужные привилегии в виде структуры TOKEN_PRIVILEGES
BufferLength dd
0
;
// размер буфера (опционально)
PreviousState dd
0
;
// лист предыдущих (опционально)
ReturnLength dd
0
;
// размер PreviousState (опционально)
Если во-второй аргумент запихать логическую единицу, функция превратит токен в ограниченный "Resticted", удалив из него все привилегии кроме "SeChangeNotify". Особого внимания заслуживает здесь аргумент "NewState", который является указателем на структуру "TOKEN_PRIVILEGES". Как упоминалось выше, в первом поле этой структуры лежит счётчик вложенных структур "LUID_AND_ATTRIBUTES", за которым следует и сам массив. Значит чтобы добавить в токен, например, четыре какие-нибудь дополнительные привилегии, можно воспользоваться такой конструкцией в секции-данных программы:
C-подобный:
Код:
align
16
newState
:
;
//
cinvoke printf
,
;
//----- Открываем первичный токен своего процесса
invoke GetCurrentProcess
invoke OpenProcessToken
,
eax
,
\
TOKEN_QUERY
+
TOKEN_ADJUST_PRIVILEGES
,
\
hToken
or eax
,
eax
jnz @f
cinvoke printf
,
jmp @exit
;
//----- Получаем LUID'ы привилегий по их именам
@@
:
invoke LookupPrivilegeValue
,
0
,
,
Luid1
invoke LookupPrivilegeValue
,
0
,
,
Luid2
invoke LookupPrivilegeValue
,
0
,
,
Luid3
invoke LookupPrivilegeValue
,
0
,
,
Luid4
;
//----- Выставляем привилегии в токене!
invoke AdjustTokenPrivileges
,
[
hToken
]
,
0
,
newState
,
0
,
0
,
0
or eax
,
eax
jnz @f
cinvoke printf
,
jmp @exit
;
//----- Запрос списка привелегий
;
//----- (первый вызов возвращает требуемый размер буфера)
@@
:
invoke GetTokenInformation
,
[
hToken
]
,
TokenPrivileges
,
buff
,
0
,
pReturn
invoke GetTokenInformation
,
[
hToken
]
,
TokenPrivileges
,
buff
,
[
pReturn
]
,
pReturn
cinvoke printf
,
,
dword
[
buff
]
;
//..............
;
//
invoke OpenProcessToken
,
-
1
,
TOKEN_QUERY
,
hToken
;
//----- SID юзера в системе ----------
invoke GetTokenInformation
,
[
hToken
]
,
TokenUser
,
buff
,
0
,
pReturn
invoke GetTokenInformation
,
[
hToken
]
,
TokenUser
,
buff
,
[
pReturn
]
,
pReturn
mov eax
,
dword
[
buff
]
invoke ConvertSidToStringSid
,
eax
,
buff
mov eax
,
dword
[
buff
]
cinvoke printf
,
,
eax
;
//----- Получим SID из токена ----------
invoke GetTokenInformation
,
[
hToken
]
,
TokenGroups
,
buff
,
0
,
pReturn
invoke GetTokenInformation
,
[
hToken
]
,
TokenGroups
,
buff
,
[
pReturn
]
,
pReturn
mov ecx
,
dword
[
buff
]
mov esi
,
buff
+
4
@@
:
mov eax
,
[
esi
+
SID_AND_ATTRIBUTES
.
Attributes
]
and eax
,
SE_GROUP_LOGON_ID
cmp eax
,
SE_GROUP_LOGON_ID
je @found
add esi
,
sizeof
.
SID_AND_ATTRIBUTES
dec ecx
jnz @b
cinvoke printf
,
jmp @exit
@found
:
mov eax
,
dword
[
esi
]
invoke ConvertSidToStringSid
,
eax
,
buff
mov eax
,
dword
[
buff
]
cinvoke printf
,
,
eax
;
//----- Перечислим привелегии в токене ----------
invoke GetTokenInformation
,
[
hToken
]
,
TokenPrivileges
,
buff
,
0
,
pReturn
invoke GetTokenInformation
,
[
hToken
]
,
TokenPrivileges
,
buff
,
[
pReturn
]
,
pReturn
cinvoke printf
,
,
dword
[
buff
]
mov ecx
,
dword
[
buff
]
mov esi
,
buff
+
4
@@
:
cmp
[
esi
+
LUID_AND_ATTRIBUTES
.
Attributes
]
,
0
jz @fuck
push esi ecx
mov
[
strSize
]
,
128
invoke LookupPrivilegeName
,
0
,
esi
,
privStr
,
strSize
cinvoke printf
,
,
privStr
pop ecx esi
@fuck
:
add esi
,
sizeof
.
LUID_AND_ATTRIBUTES
dec ecx
jnz @b
;
//----- Общая статистика токена ----------
;
invoke GetTokenInformation
,
[
hToken
]
,
TokenStatistics
,
buff
,
0
,
pReturn
;
invoke GetTokenInformation
,
[
hToken
]
,
TokenStatistics
,
buff
,
[
pReturn
]
,
pReturn
;
cinvoke printf
,
,
eax
;
//**************************************************************
cinvoke printf
,
;
//----- Owner (владелец).
;
//----- SID, который будет записан как владелец любых объектов,
;
//----- созданных процессом с этим токеном доступа.
invoke GetTokenInformation
,
[
hToken
]
,
TokenOwner
,
buff
,
0
,
pReturn
invoke GetTokenInformation
,
[
hToken
]
,
TokenOwner
,
buff
,
[
pReturn
]
,
pReturn
mov eax
,
dword
[
buff
]
invoke ConvertSidToStringSid
,
eax
,
buff
mov eax
,
dword
[
buff
]
cinvoke printf
,
,
eax
;
//----- PrimaryGroup.
;
//----- SID, который будет записан как основная группа любых объектов,
;
//----- созданных процессом с этим токеном доступа.
invoke GetTokenInformation
,
[
hToken
]
,
TokenPrimaryGroup
,
buff
,
0
,
pReturn
invoke GetTokenInformation
,
[
hToken
]
,
TokenPrimaryGroup
,
buff
,
[
pReturn
]
,
pReturn
mov eax
,
dword
[
buff
]
invoke ConvertSidToStringSid
,
eax
,
buff
mov eax
,
dword
[
buff
]
cinvoke printf
,
,
eax
;
//----- DefaultDacl.
;
//----- DACL, который будет назначен любым объектам,
;
//----- созданным процессом c этим токеном, если не указан явный ACL.
invoke GetTokenInformation
,
[
hToken
]
,
TokenDefaultDacl
,
buff
,
0
,
pReturn
invoke GetTokenInformation
,
[
hToken
]
,
TokenDefaultDacl
,
buff
,
[
pReturn
]
,
pReturn
mov esi
,
dword
[
buff
]
push esi
movzx eax
,
[
esi
+
DACL_HEADER
.
AclRevision
]
movzx ebx
,
[
esi
+
DACL_HEADER
.
AclSize
]
movzx ecx
,
[
esi
+
DACL_HEADER
.
AceCount
]
mov
[
counter
]
,
ecx
cinvoke printf
,
,
eax
,
ebx
,
ecx
pop esi
add esi
,
sizeof
.
DACL_HEADER
mov ecx
,
[
counter
]
@@
:
push esi ecx
movzx eax
,
[
esi
+
ACCESS_ALLOWED_ACE
.
AceFlags
]
movzx ebx
,
[
esi
+
ACCESS_ALLOWED_ACE
.
AceSize
]
mov ecx
,
[
esi
+
ACCESS_ALLOWED_ACE
.
Mask
]
mov
[
offset
]
,
ebx
push esi
cinvoke printf
,
,
[
number
]
,
ebx
,
\
[
number
]
,
eax
,
\
[
number
]
,
ecx
pop esi
add esi
,
ACCESS_ALLOWED_ACE
.
SidStart
invoke ConvertSidToStringSid
,
esi
,
sidBuff
mov eax
,
dword
[
sidBuff
]
cinvoke printf
,
,
[
number
]
,
eax
pop ecx esi
inc
[
number
]
add esi
,
[
offset
]
dec ecx
jnz @b
@exit
:
cinvoke _getch
cinvoke exit
,
0
;
//------------
;
//------------
section
'.idata'
import data readable
library kernel32
,
'kernel32.dll'
,
msvcrt
,
'msvcrt.dll'
,
advapi32
,
'advapi32.dll'
include
'api\kernel32.inc'
include
'api\msvcrt.inc'
include
'api\advapi32.inc'
5. Под занавес..
Информация на уровне токенов позволяет нам приобретать права и привилегии. Здесь играет роль каждый бит, который мы указываем в масках доступа, поэтому знать их назначение наша обязанность. Практика ничто, перед теорией, и можно долго ломиться в открытые двери, даже не подразумевая, что ключ лежит в единственном бите. К сожалению, здесь не было возможности в полной мере освятить эту тему, т.к. говорить о ней можно бесконечно. В результате у меня осталось впечатление, что тема не раскрыта всё-таки до конца, и будем считать ей отправной точкой. В скрепке готовые примеры и инклуд. Всем желаю удачи, и до следующего..
|
|
|

27.07.2021, 14:43
|
|
Новичок
Регистрация: 23.01.2018
Сообщений: 0
С нами:
4371257
Репутация:
0
|
|
Как всегда, нет слов. Одни восхищения!
|
|
|

30.09.2021, 16:57
|
|
Новичок
Регистрация: 29.09.2021
Сообщений: 0
С нами:
2433688
Репутация:
0
|
|
Всем привет, немного, наверное, простой вопрос, но почему не срабатывает !process 0 0?
************* Path validation summary **************
Response Time (ms) Location
OK D:\test\symbols
0:000> !process 0 0
kdexts!DebugExtensionInitialize failed with 0x80004005
The !process extension command was not found in loaded extensions, but is
available as part of the kdexts extension. Run .update kdexts to install
No export process found
0:000> .load kdexts
kdexts!DebugExtensionInitialize failed with 0x80004005
0:000> .load D:\test\kdexts.dll
**** WARNING loaded *kernel* extension dll for usermode
0:000> !process 0 0
**** WARNING loaded *kernel* extension dll for usermode
**** NT ACTIVE PROCESS DUMP ****
unable to get nt!MmUserProbeAddress
NT symbols are incorrect, please fix symbols
...
как заставить работать комманду?
|
|
|

30.09.2021, 21:50
|
|
Постоянный
Регистрация: 01.09.2019
Сообщений: 378
С нами:
3526561
Репутация:
0
|
|
попробуйте запустить отладчик в режиме ядра CTRL+K, и загрузите символы
**** NT ACTIVE PROCESS DUMP ****
невозможно получить nt! MmUserProbeAddress
Символы NT неверны, исправьте символы
|
|
|
|
 |
Предыдущая тема
Следующая тема
|
Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
|
|
|
|