Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
Themida считается одним из самых сложных инструментов защиты программ от нелицензионного копирования — не только из‑за обфускации и навороченных механизмов антиотладки, но и из‑за широкого использования виртуализации. В предыдущей статье мы узнали, как сбросить триал в защищенной Themida программе. Теперь настало время поковыряться в ее виртуальной машине.
warning
Статья имеет ознакомительный характер и предназначена для специалистов по безопасности, проводящих тестирование в рамках контракта. Автор и редакция не несут ответственности за любой вред, причиненный с применением изложенной информации. Распространение вредоносных программ, нарушение работы систем и нарушение тайны переписки преследуются по закону.
В прошлых статьях я уже упоминал об одной очень зловредной особенности серьезных протекторов: чтобы осложнить жизнь хакерам, разработчики обфусцируют критические участки скомпилированного кода в макрокоманды виртуальной машины, щедро разбавленные ловушками и безумным кодом. При таком раскладе объем кода может увеличиваться в тысячи раз, делая реверс чудовищно сложным. Вдобавок его можно делать мутирующим, реализуя одну и ту же команду сотнями разных способов. Мы уже сталкивались с подобным в статье про Enigma, теперь попробуем разобрать более сложный способ виртуализации на примере снятия триала с одного из графических плагинов.
Итак, условия задачи: у нас есть 64-битная библиотека, привязанная к определенному ознакомительному периоду. Халявный сброс триала, методы которого я описывал в предыдущих статьях, невозможен: при загрузке библиотека стучится на сервер, который проверяет текущую дату и дает добро на запуск. При отсутствии соединения программа просто не работает. Код упакован и зашифрован, исследованию в дизассемблере не подлежит, но детекторы не видят на нем никакого известного протектора. В общем, ситуация начинает слегка пугать.
Но мы не из пугливых! Загружаем программу в наш любимый отладчик x64dbg и при помощи описанного мною в предыдущих статьях замечательного плагина ScyllaHide подбираем антиантиотладочную конфигурацию (Themida). Теперь включаем уже опробованный нами в боях плагин Themidie и наконец получаем возможность поковыряться в расшифрованном и распакованном коде (включая его трассировку). Чтобы расшифрованный код было удобнее изучать, я сдампил его еще одним описанным ранее плагином — Scylla. Если теперь мы загрузим сдампленный код в дизассемблер IDA, то увидим примерно такую картину.
Cдампленный код в дизассемблере IDA
Бегло взглянув на карту нашего модуля, мы увидим коротенькую синюю полоску слева. Она подсказывает, что в начале модуля сосредоточен нормальный вменяемый код функций, который по каким‑то причинам (обычно скорость исполнения) не подвергся виртуализации. Пестрая полоска с преобладанием коричневого цвета справа — шитый код виртуальной машины Themida, перемежающийся обработчиками команд.
Побродив немного отладчиком по дебрям кода и слегка расстроившись, переходим к более прогрессивному методу работы. Попробуем отследить и проанализировать трассу между вызываемыми невиртуализированными функциями. В качестве отправного пункта берем функцию HTTP-запроса лицензии на сервер, благо она по понятным причинам не обфусцирована. Ставим на нее точку останова и при ее достижении жмем Ctrl-F9, выполняя функцию до возврата в обработчик шитого кода, из которого она вызывается.
На входе обнаруживаем такой огромный кусок бессмысленных команд, что его бесполезно пытаться пройти вручную. Возложим эту тяжкую задачу на отладчик. Для этого откроем вкладку «Трассировка» (крайняя справа) и правой кнопкой мыши выберем «Начать выполнение трассировки». Затем для быстроты запускаем трассировку через Ctrl-Alt-F8 (трассировка с обходом). Памятуя о том, что невиртуализированный код находится в секции с меньшими адресами, в качестве условия остановки ставим RIP
до начала секции, содержащей виртуализированный код.
Ставим RIP до начала секции, содержащей виртуализированный код
В окне трассировки шустро побежали исполняемые команды, а вот и остановка на следующем вызове какой‑то функции. Ого, нам потребовалась пара десятков тысяч шагов, чтобы преодолеть промежуток между ними! Это нас не пугает: попробуем проанализировать полученную трассу.
Источник: xakep.ru