Пользователь
- Статус
- Онлайн
- Регистрация
- 12 Дек 2022
- Сообщения
- 128
- Реакции
- 31
Антиотладка через NtCurrentPeb
Этот метод в одном crackme использовался
все три приведённых условия - это антиотладочные проверки
Уточнение: NtCurrentPeb() — это неофициальная конструкция, используемая для получения указателя на PEB через сегментные регистры (FS:[0x30] в x86, GS:[0x60] в x64). Официально Windows предоставляет NtCurrentTeb(), возвращающую TEB*, а PEB доступна через TEB::ProcessEnvironmentBlock
NtCurrentPeb
NtCurrentTeb — это функция, возвращающая указатель на текущий TEB (Thread Environment Block, блок среды потока)
Возвращаемое значение: указатель на текущий TEB
ProcessHeap
Комментарий:
Функция GetProcessHeaps возвращает дескриптор основного кучи текущего процесса, а также дескрипторы любых других куч, созданных через HeapCreate
Эта функция в основном используется для отладки, так как возвращённые кучи могли быть созданы другими частями кода и могут быть уничтожены после вызова. Уничтожение кучи делает указатель, возвращённый из GetProcessHeap, недействительным и дальнейшее его использование может привести к неопределённому поведению
Чтобы получить дескриптор основной кучи процесса, можно использовать GetProcessHeap
Почему это работает как антиотладка
BeingDebugged
Эта проверка понятна по названию.
BeingDebugged — флаг, указывающий, отлаживается ли текущий процесс. Однако PEB — это внутренняя структура ОС, и Microsoft не гарантирует стабильность её формата между версиями Windows. CheckRemoteDebuggerPresent — более "официальный" способ проверки, но под капотом он также обращается к PEB
ProcessHeap и NtGlobalFlag
Влияет ли отладчик на активную кучу процесса (основную или созданную динамически) — зависит от того, активированы ли в отладочной среде специальные механизмы отладки кучи
1. Механизмы отладки и поведение кучи
(1) Флаги отладки и поведение кучи
Эти флаги изменяют поведение менеджера кучи — размеры блоков, структуру и метаинформацию
(2) Шаблоны заполнения при отладке
В режиме отладки куча может быть заполнена специальными шаблонами :
2. Влияние способа запуска отладчика
(1) Отладчик запускает процесс
3. Практические последствия
(1) Изменение размера и структуры кучи
Если отладчик только аттачнут, без включения специальных механизмов, поведение кучи не изменится. Можно проверить это по NtGlobalFlag или по шаблонам в памяти
Вывод: поведение основной кучи процесса может меняться при отладке из-за установки флагов (например, NtGlobalFlag) в момент инициализации процесса. Это не влияет на функцию GetProcessHeap() напрямую, но влияет на то, как эта куча работает (например, добавление проверок и шаблонов памяти)
И всё зависит от того, был ли процесс запущен отладчиком или к нему аттачнулись позже
Пример с IDA
Можно сравнить: запуск процесса с нуля и аттач отладчика в IDA (Attach to process), установить точки останова и проанализировать
Если регистр EAX равен 0, выполнение перейдёт сразу на строку 63
(Инструкция TEST делает побитовую проверку, IDA обычно подсвечивает стрелкой, куда будет переход)
Если же запустить программу напрямую, выполнится строка 62
То же самое с ProcessHeap - поведение идентично
Однако стоит помнить: этот метод не обходит проверку BeingDebugged
Спасибо за внимание!
Этот метод в одном crackme использовался
C++:
if ((NtCurrentPeb()->ProcessHeap & 0x70) != 0)
v12 = v10 + v11;
if ((NtCurrentPeb()->NtGlobalFlag & 0x70) != 0)
v12 = v10 + v11;
if (*&NtCurrentPeb()->BeingDebugged)
{
v10 = -83;
v11 = 43;
}
все три приведённых условия - это антиотладочные проверки
Уточнение: NtCurrentPeb() — это неофициальная конструкция, используемая для получения указателя на PEB через сегментные регистры (FS:[0x30] в x86, GS:[0x60] в x64). Официально Windows предоставляет NtCurrentTeb(), возвращающую TEB*, а PEB доступна через TEB::ProcessEnvironmentBlock
NtCurrentPeb
Пожалуйста, авторизуйтесь для просмотра ссылки.
:NtCurrentTeb — это функция, возвращающая указатель на текущий TEB (Thread Environment Block, блок среды потока)
C++:
_TEB* NtCurrentTeb();
Возвращаемое значение: указатель на текущий TEB
ProcessHeap
Пожалуйста, авторизуйтесь для просмотра ссылки.
Комментарий:
Функция GetProcessHeaps возвращает дескриптор основного кучи текущего процесса, а также дескрипторы любых других куч, созданных через HeapCreate
Эта функция в основном используется для отладки, так как возвращённые кучи могли быть созданы другими частями кода и могут быть уничтожены после вызова. Уничтожение кучи делает указатель, возвращённый из GetProcessHeap, недействительным и дальнейшее его использование может привести к неопределённому поведению
Чтобы получить дескриптор основной кучи процесса, можно использовать GetProcessHeap
Почему это работает как антиотладка
BeingDebugged
Эта проверка понятна по названию.
Пожалуйста, авторизуйтесь для просмотра ссылки.
BeingDebugged — флаг, указывающий, отлаживается ли текущий процесс. Однако PEB — это внутренняя структура ОС, и Microsoft не гарантирует стабильность её формата между версиями Windows. CheckRemoteDebuggerPresent — более "официальный" способ проверки, но под капотом он также обращается к PEB
ProcessHeap и NtGlobalFlag
Влияет ли отладчик на активную кучу процесса (основную или созданную динамически) — зависит от того, активированы ли в отладочной среде специальные механизмы отладки кучи
1. Механизмы отладки и поведение кучи
(1) Флаги отладки и поведение кучи
- NtGlobalFlag
Если процесс запущен под отладчиком (а не аттачнут), система может установить флаги отладки в PEB, такие как:- FLG_HEAP_ENABLE_TAIL_CHECK (0x10) — добавляет защитные значения в конец блока памяти (например, 0xABABABAB) для обнаружения переполнений
- FLG_HEAP_ENABLE_FREE_CHECK (0x20) — заполняет освобождённую память особыми значениями (например, 0xFEEEFEEE) для обнаружения повреждений
- FLG_HEAP_VALIDATE_PARAMETERS (0x40) — включает строгую проверку параметров при работе с кучей, может вызывать исключения
Эти флаги изменяют поведение менеджера кучи — размеры блоков, структуру и метаинформацию
- Page Heap (страничная куча)
Если включена (через gflags или реестр), каждая куча получает защитную страницу (guard page):- Full Page Heap — каждый блок размещается на отдельной странице памяти, а за ним следует защищённая страница. При переполнении сразу срабатывает исключение STATUS_ACCESS_VIOLATION
(2) Шаблоны заполнения при отладке
В режиме отладки куча может быть заполнена специальными шаблонами :
- Неинициализированная память: 0xBAADF00D
- Освобождённая память: 0xFEEEFEEE
2. Влияние способа запуска отладчика
(1) Отладчик запускает процесс
- Система устанавливает флаги отладки (например, NtGlobalFlag) при инициализации процесса, что влияет на структуру основной кучи (GetProcessHeap)
- Пример: при включённой Page Heap основная куча будет сильно отличаться от обычной
- Простой аттач обычно не меняет конфигурацию уже созданных куч
- Однако можно вручную включить отладку кучи через команды или HeapSetInformation
3. Практические последствия
(1) Изменение размера и структуры кучи
- Отладочные кучи выделяют больше памяти: запрос 100 байт может реально привести к выделению 132 байт (с защитными байтами)
- Разница в адресах: при Page Heap блоки располагаются в изолированных страницах памяти
- Переполнение вызывает сбой: отладочная куча перехватывает такие ошибки, а без отладки программа может просто продолжить выполнение
- Обращение к освобождённой памяти: при чтении/записи отладчик может поймать исключение
- Дополнительные проверки замедляют выделение и освобождение памяти, особенно при частом использовании кучи
- Процесс должен быть запущен под отладчиком (а не аттачнут)
- Должны быть включены отладочные флаги или механизмы (например, Page Heap)
Если отладчик только аттачнут, без включения специальных механизмов, поведение кучи не изменится. Можно проверить это по NtGlobalFlag или по шаблонам в памяти
Вывод: поведение основной кучи процесса может меняться при отладке из-за установки флагов (например, NtGlobalFlag) в момент инициализации процесса. Это не влияет на функцию GetProcessHeap() напрямую, но влияет на то, как эта куча работает (например, добавление проверок и шаблонов памяти)
И всё зависит от того, был ли процесс запущен отладчиком или к нему аттачнулись позже
Пример с IDA
Можно сравнить: запуск процесса с нуля и аттач отладчика в IDA (Attach to process), установить точки останова и проанализировать
Если регистр EAX равен 0, выполнение перейдёт сразу на строку 63
(Инструкция TEST делает побитовую проверку, IDA обычно подсвечивает стрелкой, куда будет переход)
Если же запустить программу напрямую, выполнится строка 62
То же самое с ProcessHeap - поведение идентично
Однако стоит помнить: этот метод не обходит проверку BeingDebugged
Спасибо за внимание!