EnglishFrenchGermanItalianPortugueseSpanish

Свежий взгляд на антиотладку

Ниже пойдет речь исключительно об OllyDbg и плагинах к ней, но описанный подход и сами идеи при определенных навыках вы сможете использовать применительно и к другим утилитам такого класса.

Если эти строки вы читаете, борясь с желанием закрыть окно браузера оттого, что далеко не уверены, будет ли сказано далее что-то для вас новое и оригинальное, то ответьте для себя на следующие вопросы:

Как работает функция IsDebuggerPresent? Если ее не вызывать из kernel32, а реализовать ее функционал в своем коде, то получится ли обмануть анти-антиотладку? Как плагин скрывает процесс отладчика (чтобы его подопытная программа не завершила по имени или не прекратила свою работу)?

Если на эти вопросы вы с легкостью отвечаете и еще можете рассуждать на эту тему и рассказать в каком плагине что да как, то статья вряд ли откроет вам на что-то глаза или сможет показать хоть что-то новое, но если прочитать все же хочется или вопросы несколько озадачили, то рекомендую к прочтению.

Сам процесс антиотладки и противодействия оной, достаточно автоматизирован — существует приличное количество навесных защит на файлы и специальных анти-антиотладочных плагинов к дебаггерам.

На этот раз пойдет речь о способах обнаружения факта отладки путем выявления и анализа изменений, вносимых плагинами отладчика в исследуемый процесс и систему. Плагины скрывают присутствие отладчика в системе, но скрывают ли они себя самих? Не вызывают ли они каких-то аномалий? При поиске ответов на эти вопросы из под пера (точнее клавиатуры) вышла данная рукопись.

На тему противодействия отладке написано немало статей, как хороших, так и «ни о чем». У меня нет ни малейшего желания изобретать колесо и разжевывать то, что было с успехом сделано и до меня, поэтому если что-то в статье вам покажется непонятным, то запрос «антиотладка» в яндекс/гугл, думаю, все расставит по своим местам.

Все антиотладочные приемы условно можно разделить на две группы:

  • Усложнение возможной отладки. Сюда можно отнести обфускацию кода, паковку/криптовку, использование исключений, разделение кода на потоки/библиотеки, мусорные функции и т.д.
  • Обнаружение отладки. Название говорит само за себя — так или иначе происходит обнаружение самого факта исследования: через созданные для этого функции или через нахождения окна/процесса отладчика, нахождение брекпоинтов (CC, проверка атрибутов доступа и др.), замеры времени и т.д.

Как, наверное, уже понял читатель, наш метод относится ко второй группе. Использовать полученное знание можно по-разному. Про это писалось много, но вкратце сказать об этом все же необходимо: обнаружив отладчик, конечно, можно сразу радостно выкинуть алерт типа «debugger detected» и завершить работу, а можно затаиться и потихонечку портить жизнь взломщику — сбить значения пары переменных, изменить логику работы программы, использовать флаги обнаружения отладчика как слагаемые при вычислении относительного адреса и т.д. Совершенно очевидно, что второй способ способен очень сильно затруднить жизнь исследователю, но все эти возможности оставляю вашей фантазии с базированием на других статья на эту тему, я же только постараюсь показать новые методы обнаружения отладки, а как вы это будете применять далее уже не мое дело.

Ниже будут рассмотрены способы защиты от некоторых антиотладочных приемов следующими популярными плагинами для OllyDbg:

  • Olly Advanced 1.26 Beta 12
  • Hide Debugger v1.2.4 (by Asterix)
  • HideOD v0.12 (pеdiy.соm)
ZwQueryInformationProcess (InfoClass = 7)

Olly Advanced модифицирует данную функцию так, что после ее отработки она сама же зануляет четырехбайтовый буфер и вместо законных FFFFFFFF там будет абсолютный ноль.

HideOD работает более жестко. Функцию он модифицирует так, что она, по сути, и не работает (вызова в ядро не происходит). При этом значение регистра есх остается преждним, хотя нормальная функция его бы изменила, значение edx также остается постоянным или меняется на 00320000 (в зависимости от выбора метода в настройках).

А в Hide Debugger такой функционал не заложен.

GetTickCount

Защиту от этого метода предлагает только Olly Advanced, причем двумя методами. При выборе первого варианта защиты, происходит просто обнуление возвращаемого значения (при любых обстоятельствах данная функция вернет 0), а второй возвращает небольшое значени и при повторных вызовах функции прибавляет к счетчику единицу. Реализованы они по принципу «перехвати себя сам» — код функции изменяется так, что как надо она не работает. В любом случае значения счетчиков выходят до безобразия маленькие, чем можно воспользоваться. Вот самый простой пример:

call GetTickCount
push eax
invoke Sleep, 1000d ; 3e8h
call GetTickCount
pop ecx
sub eax, ecx

В итоге если в eax ноль или единица, а не законный минимум 3E8, то значит, поработал плагин…
Данная функция состоит из четырех строк и не делает каких-либо глубинных вызовов по относительным адресам, поэтому никаких сложностей собственной ее реализации быть не должно:

MOV EDX,7FFE0000
MOV EAX,[DWORD DS:EDX]
MUL [DWORD DS:EDX+4]
SHRD EAX,EDX,18
PUSH EAX
PUSH 3E8                    ; Timeout = 1000. ms
CALL   ; Sleep
MOV EDX,7FFE0000
MOV EAX,[DWORD DS:EDX]
MUL [DWORD DS:EDX+4]
SHRD EAX,EDX,18
POP ECX
SUB EAX,ECX

Чтобы не бросаться в глаза можно обойтись и без Sleep’a, просто проверить один раз использовать код GetTickCount и проверить еах на близость к нулю, и если на данном участке программы такое небольшое значение невозможно, то значит плагин детектед…

Process32Next

Теперь рассмотрим что за жуткую зиродей руткит-технологию используют плагины для сокрытия процесса ollydbg от подопытной программы.
Olly Advanced в этом плане решил не заморачиваться и просто обнуляет еах в функции Process32NextW, на чем, собственно, все листание процессов и заканчивается: Process32First отрабатывает как положено, а процессов next оказывается в системе не существует, ну, на нет и суда нет, видимо юзер так оптимизировал систему убрав ненужные процессы ;)

Кстати, помимо того, что в реальной системе процессов чуть побольше чем один, так и при завершении листания всех процессов, Process32Next помимо выдачи нуля в eax еще и LastError, установленный в ERROR_NO_MORE_FILES, обеспечит…

HideOD работает точно также и обсуждать его посему незачем.

В Hide Debugger такой функционал не замечен, конечно, может там названо это иначе, например защитой от убийства процесса (галочка напротив TerminateProcess), но какого-либо результата от установки этой защиты добиться не удалось, подопытной утилите ничто не помешало пролистать процессы, найти процесс олли и благополучно его прибить, после этого у меня пропало всякое желание исследовать, почему так происходит в этом плагине. К слову сказать, защита от TerminateProcess в Olly Advanced работает как топор — просто и надежно: в самое начало функции поставлен ret.



Теперь, после знакомства с некоторыми принципами работы анти-антиотладочных плагинов можно перейти к выводам. Некоторые из них уже были вкратце озвучены выше, а до каких-то нужно еще дойти посредством мыслительной деятельности — размышляя какие слабости у таких методов реализации защиты отладчика от агрессивно настроенных программ:

  • Поиск аномалий
    • Различия в изменениях регистров. Исследовав работу чистой функции и с плагином можно выявить различия.
    • Используя функцию GetLastError (или самостоятельно находя значение в блоке окружения) после антиотладочных функций (выше есть пример) проверить правильность ее работы. Если функция в случае неудачи возвращает 0 и msdn советует вызывать GetLastError, которая клянется, что все ОК, то это повод задуматься…
    • Можно обнаружить сплайсинг путем поиска опкода jmp в первых байтах функции. Вызвав GetProcAddress, можно не только использовать его для вызова, но и незаметно сохранить первые его байты, а потом в спокойной остановке исследовать.
    • Правдоподобность. Один процесс в системе это похоже на истину? Нет. Вот и ответ.
  • Рыба ищет, где глубже…
    • Использовать NativeAPI. Конечно, в некоторых случаях перехвачены и они, но ведь это общая рекомендация и из примеров выше видно на каком уровне что изменяется.
    • sysenter. В этом случае за собой придется таскать массив номеров системных вызовов, т.к от системы к системе они меняются.
    • Серединный вызов api-функций. На самом деле это не так сложно как кажется и таскать за собой километры кода функций не требуется, достаточно вызывать с $+5, т.к зачастую именно в первых пяти байтах содержится jmp, тем более не стоит забывать о распространенном пятибайтовом прологе.
  • Ищем плагин. Если сам отладчик может быть замаскирован как бревно в собственном глазу (т. е найти почти нереально), то плагин может и не скрываться совсем. Например, CommandBar светится классом окна ComboLBox.

Читайте также:

Share

4 comments to Свежий взгляд на антиотладку

Leave a Reply

  

  

  

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">