Старые антиотладочные приемы на новый лад

       

простейший анти-отладочный прием, распознающий трассировку под некоторыми отладчиками


Главный минус этого приема в том, что его очень легко обойти. Достаточно, например, просто подогнать курсор к команде 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:

       ; // отсюда будет продолжено управление, если отладчик не установлен


Содержание раздела