простейший анти-отладочный прием, распознающий трассировку под некоторыми отладчиками
Главный минус этого приема в том, что его очень легко обойти. Достаточно, например, просто подогнать курсор к команде pushf, сказать отладчику "HERE" (т. е. выполняй программу до этого места без трассировки), затем подогнать курсор к jnz и сказать "HERE" еще раз. Таким образом, защищенный фрагмент будет исполняться в обычным режиме и присутствие отладчика окажется незамеченным, поэтому, многие программисты предпочитают сохранять регистр флагов в одном месте программы, а проверять его в другом. Начинающих хакеров это сбивает с толку, но опытных так не проведешь. На конструкцию pushf/pop reg/xxx reg,100h у них уже давно выработался безусловный рефлекс, к тому же взломщику ничего не стоит заменить and eax,100h на and eax,0h и тогда программа навсегда утратит способность распознавать отладчик. Можно (и нужно), конечно, добавить проверку собственной целостности, но только навряд ли она надолго остановит хакера.
А вот слегка модифицированный вариант той же самой защиты, который распознает присутствие отладчика независимо от того исполняется ли программа в пошаговом режиме или нет. Алгоритм работы в общих чертах выглядит так: мы самостоятельно взводим флаг трассировки и выполняем следующую команду. Процессор послушно генерирует исключение, которые мы перехватываем предварительно установленным SEH-обработчиком, передающим управление нашему коду. Но при наличии отладчика, исключение "поглощается" и SEH-обработчик уже не получает управления!
; устанавливаем новый обработчик структурных исключений
xor eax,eax ; обнуляем регистр eax
push offset SEH_handler ; кладем в стек указатель на новый обработчик
push dword ptr fs:[eax] ; кладем в стек указатель на старый обработчик
mov fs:[eax],esp ; регистрируем новый SEH-обработчик
; взводим флаг трассировки
pushf ; заталкиваем в стек регистр флагов
pop eax ; выталкиваем его содержимое в регистр eax
or ah, 1 ; взводим флаг TF
push eax ; кладем eax
в стек
popf ; выталкиваем его содержимое в регистр флагов
; теперь флаг трассировки взведен!
jmp under_debugger ; после выполнения этой команды генерируется
; исключение и если отладчик не установлен,
; его перехватывает SEH-обработчик, который
; корректирует EIP и эта команда не выполняется
; под отладчиком происходит переход на ветку
; under_debugger
//
... ; основной код программы
//
; SEH-обработчик. может быть расположен в любом месте
; (лучше расположить его подальше от защитного кода,
; чтобы он не так бросался в глаза)
SEH_handler:
mov esi, [esp+0ch] ; указатель на контекст регистров
assume esi: PTR CONTEXT
mov [esi].regEip, offset continue
; откуда продолжать выполнение
; в отсутствии отладчика
xor eax, eax
ret ; выход из SEH-обработчика
continue:
; // отсюда будет продолжено управление, если отладчик не установлен