Содержание статьи
- IsDebuggerPresent() и структура PEB
- Process Environment Block
- NtGlobalFlag
- Flags и ForceFlags
- CheckRemoteDebuggerPresent() и NtQueryInformationProcess
- Тонкости NtQueryInfoProcess
- DebugObject
- ProcessDebugFlags
- Проверка родительского процесса
- TLS Callbacks
- Отладочные регистры
- NtSetInformationThread
- NtCreateThreadEx
- SeDebugPrivilege
- SetHandleInformation
- Заключение
Поскольку сейчас популярна не только архитектура x86, но и x86-64, многие старые средства обнаружения отладчиков устарели. Другие требуют корректировки, потому что жестко завязаны на смещения в архитектуре x86. В этой статье я расскажу о нескольких методах детекта отладчика и покажу код, который будет работать и на x64, и на x86.
IsDebuggerPresent() и структура PEB
Начинать говорить об антиотладке и не упомянуть о функции IsDebuggerPresent() было бы неправильно. Она универсальна, работает на разных архитектурах и очень проста в использовании. Чтобы определить отладку, достаточно одной строки кода: if (IsDebuggerPresent())
.
Что представляет собой WinAPI IsDebuggerPresent? Эта функция обращается к структуре PEB.
Process Environment Block
Блок окружения процесса (PEB) заполняется загрузчиком операционной системы, находится в адресном пространстве процесса и может быть модифицирован из режима usermode. Он содержит много полей: например, отсюда можно узнать информацию о текущем модуле, окружении и загруженных модулях. Получить структуру PEB можно, обратившись к ней напрямую по адресу fs:[30h]
для x86 и gs:[60h]
для x64.
Соответственно, если загрузить в отладчик функцию IsDebuggerPresent(), на x86-системе мы увидим:
mov eax,dword ptr fs:[30h]
movzx eax,byte ptr [eax+2]
ret
А на x64 код будет таким:
mov rax,qword ptr gs:[60h]
movzx eax,byte ptr [rax+2]
ret
Что значит byte ptr [rax+2]
? По этому смещению находится поле BeingDebugged
в структуре PEB, которое и сигнализирует нам о факте отладки. Как еще можно использовать PEB для обнаружения отладки?
NtGlobalFlag
Во время отладки система выставляет флаги FLG_HEAP_VALIDATE_PARAMETERS
, FLG_HEAP_ENABLE_TAIL_CHECK
, FLG_HEAP_ENABLE_FREE_CHECK
, в поле NtGlobalFlag
, которое находится в структуре PEB. Отладчик использует эти флаги для контроля разрушения кучи посредством переполнения. Битовая маска флагов — 0x70
. Смещение NtGlobalFlag
в PEB для x86 составляет 0x68
, для x64 — 0xBC
. Чтобы показать пример кода детекта отладчика по NtGlobalFlag
, воспользуемся функциями intrinsics, а чтобы код был более универсальным, используем директивы препроцессора:
#ifdef _WIN64
DWORD pNtGlobalFlag = NULL;
PPEB pPeb = (PPEB)__readgsqword(0x60);
pNtGlobalFlag = *(PDWORD)((PBYTE)pPeb + 0xBC);
#else
DWORD pNtGlobalFlag = NULL;
PPEB pPeb = (PPEB)__readfsdword(0x30);
pNtGlobalFlag = *(PDWORD)((PBYTE)pPeb + 0x68);
#endif
if ((pNtGlobalFlag & 0x70) != 0) std::cout << "Debugger detected!\n";
Flags и ForceFlags
PEB также содержит указатель на структуру _HEAP
, в которой есть поля Flags
и ForceFlags
. Когда отладчик подсоединен к приложению, поля Flags
и ForceFlags
содержат признаки отладки. ForceFlags
при отладке не должно быть равно нулю, поле Flags
не должно быть равно 0x00000002
:
#ifdef _WIN64
PINT64 pProcHeap = (PINT64)(__readgsqword(0x60) + 0x30); \\ Получаем структуру _HEAP через PEB
PUINT32 pFlags = (PUINT32)(*pProcHeap + 0x70); \\ Получаем Flags внутри _HEAP
PUINT32 pForceFlags = (PUINT32)(*pProcHeap + 0x74); \\ Получаем ForceFlags внутри _HEAP
#else
PPEB pPeb = (PPEB)(__readfsdword(0x30) + 0x18);
PUINT32 pFlags = (PUINT32)(*pProcessHeap + 0x40);
PUINT32 pForceFlags = (PUINT32)(*pProcessHeap + 0x44);
#endif
if (*pFlags & ~HEAP_GROWABLE || *pForceFlags != 0)
std::cout << "Debugger detected!\n";
Продолжение доступно только участникам
Вариант 1. Присоединись к сообществу «Xakep.ru», чтобы читать все материалы на сайте
Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», увеличит личную накопительную скидку и позволит накапливать профессиональный рейтинг Xakep Score! Подробнее
Вариант 2. Открой один материал
Заинтересовала статья, но нет возможности стать членом клуба «Xakep.ru»? Тогда этот вариант для тебя! Обрати внимание: этот способ подходит только для статей, опубликованных более двух месяцев назад.
Я уже участник «Xakep.ru»
Sage
18.01.2018 at 02:23
Спасибо большое за статью! Открыло глаза на некоторые вещи
Cianid
26.02.2018 at 23:26
Ничего нового, абсолютно. Еще году так в 2012 на WASM эти анти-отладочные трюки описывались.