Причуды «Фемиды». Пишем лоадер для программ, защищенных Themida
the Matrix
Статья написана в исследовательских целях, имеет ознакомительный характер и предназначена для специалистов по безопасности. Автор и редакция не несут ответственности за любой вред, причиненный с применением изложенной информации. Использование или распространение ПО без лицензии производителя может преследоваться по закону.
В прошлый раз мы обсуждали принципы внутренней организации виртуальной машины Themida. А теперь давай закрепим полученные знания на конкретном примере — попробуем отучить просить ключ парочку популярных приложений фирмы ConceptWorld. Эти приложения представляют собой набор мелких дешевых полезняшек для работы с файлами, заметками и буфером обмена.
Лично я не совсем понимаю причину популярности этих утилит, более того, меня бесят их назойливые окошки, болтающиеся на экране и возникающие в самый неподходящий момент. Но самое раздражающее заключается в том, что на столь простые и дешевые приложения навесили столь взрослую защиту, в чем можно убедиться при помощи детектора протекторов DetectItEasy (Die). Этот странный факт мы с тобой сейчас исправим.
Приложения ConceptWorld отлично подойдут для демонстрации слабых мест защиты, которые мы с тобой изучим исключительно в академических и исследовательских целях. На всякий случай еще раз напомню, что актуальная Themida не всегда распознается автоматическим сканированием, для подстраховки необходимо подключать Nauz File Detector (NFD), который практически всегда определяет ее правильно.

Итак, начнем с программы RecentX. Ради экономии места я не буду заниматься рекламой, описывая, для чего она служит и что умеет делать (тем более, сам до конца этого не понимаю). Давай сразу перейду к сути защиты. При запуске приложения (а также после перезапуска системы, поскольку эта утилита нагло прописывается в автозагрузку), в верхней части экрана появляется пять вкладок, которые позволяют выполнять различные действия. Тулза отлично работает 30 дней, по прошествии которых превращается в тыкву: нажатие на любой элемент интерфейса приводит к появлению настырного окошка с требованием зарегистрировать программу.

В этот раз я нарушу собственные же правила и начну с описания принципа сброса триала. Если ты уже читал мои статьи, то знаешь, что для начала нам понадобится программа ProcessMonitor (ProcMon). Запускаем ее, ставим фильтр на имя процесса RecentX.exe и для начала анализируем файловый ввод‑вывод этого процесса при его загрузке.
Это непросто, поскольку по своей специфике программа обращается чуть ли не ко всем файлам на жестком диске. Однако полистав список некоторое время, мы натыкаемся на последовательные обращения к файлам со странными непроизносимыми названиями в каталоге ProgramData.

Попробуем удалить, к примеру, файл C:\ProgramData\xmvkknpt.yme. Ничего не происходит, но при перезапуске программы он воссоздается на том же самом месте. Судя по всем признакам, это и есть файл триала.
Внимательно проанализировав лог ProcMon, мы обнаруживаем полный набор подобных файлов. Все они находятся в каталоге ProgramData: acqrldoh.otw, bgjxnlpy.hxt, lapoiwsc.hke, uhthdans.svu, vwnpbcnu.gon, xmvkknpt.yme и mntemp. Причем время от времени вместо файлов acqrldoh.otw и vwnpbcnu.gon программа ищет другую пару — wspjaeoc.kjj и tvmnixvk.oib. Однако даже удалив все файлы из каталога ProgramData, удовлетворения мы не получим — программа упорно продолжает просить регистрацию.
По своему предыдущему опыту я помню, что помимо файлов, информация о триале обычно дублируется в реестре, потому начинаем рыть в этом направлении. Включаем в ProcessMonitor режим Show Registry Activity и начинаем тщательно и кропотливо изучать обращения программы к системному реестру.

Похоже, мы в беде: зацепиться не за что: все ключи реестра, к которым идет обращение, на первый взгляд, ни к "Фемиде", ни к триалу никакого отношения не имеют — программа делает что‑то связанное с сертификтами. Чтобы разрулить тупиковую ситуацию, нам явно потребуются дополнительные инструменты.
Попробуем утилиту Registry Trash Keys Finder, которая предназначена для более интеллектуальной чистки реестра. Грубо говоря, при помощи этой программы можно получить примерное представление, какие ключи в реестре не несут полезной нагрузки и каково было их изначальное предназначение. Мы не прогадали: ключ HKCU\Software\Classes\CertificateAuthority.Request\CLSID\tkgiuafq якобы связанный с сертификатами, оказывается напрямую связан с WinLicense. Причем рядом расположено множество подобных ключей, а мы бы на них никогда и не подумали!

Помимо этого Registry Trash Keys Finder находит в реестре множество скрытых триальных ключей от других протекторов. Внимательно пройдясь по логу обращений к реестру в шаговой доступности от этого места, кроме откровенно фемидовских ключей находим список фиктивных ключей, маркируемых программой как «Неверное имя для CLSID». Что интересно, время их создания соответствует нашему триалу:
Удаляем эти ключи вместе с найденными файлами — бинго, триал сброшен! Попробуем закрепить успех для остальных программ этого производителя. Чтобы не растекаться мыслью по древу, приведу в качестве примера только портабельные 32-битные версии. Возьмем Notezilla. Соответствующие файлы триала для нее тоже живут в каталоге ProgramData, хоть и называются по‑другому: blejnwva.rcm, bueobidn.ojo, cyslknnt.dlv, dyjcmtbi.sxr, fqnyawif.yei, htisjfog.xco, uqvsamsm.gdq, xmvnjmsu.toe. Отвечающие за триал ключи реестра для этой программы выглядят так:
Удаление соответствующих файлов и ключей также приводит к обнулению триала Notezilla.
Наконец разберемся с третьей программой, Copywhiz. С ней дело обстоит чуть сложнее, поскольку «Фемида» навешена не на основном исполняемом файле Copywhiz.exe, а на вспомогательном, CopywhizCopy.exe (который запускается из основного при выполнении какого‑либо действия), а также на соответствующих программе пунктах контекстного меню. Итак, перечислим триальные файлы для нее из того же каталога ProgramData: mntemp, uiqgndne.cop, lnaychdo.pku, ldrbrntx.mrr, nylnduck.ivy, cougyhgc.fqc, vtoynwkm.ggb. А вот ключи реестра:
На примере этих трех программ мы уже можем выработать общую стратегию борьбы с фемидовскими триалами. Судя по всему, все файлы триала располагаются в каталоге ProgramData. Хотя названия у них и формируются случайным образом, однако они всегда одинаковые для конкретной программы, и список расширений у них тоже всегда стандартный. Вероятно, возможны и другие расширения, отличные от вышеперечисленных, однако это легко вычисляется при помощи ProcessMonitor.
Когда мы знаем, что именно искать, эти файлы просто бросаются в глаза. Более того, они имеют еще и одинаковые размеры — всегда 8 или 12 байт (mntemp — 16 байт). Поэтому удалив их, а заодно — все триальные ключи в реестре, помеченные Registry Trash Keys Finder как WinLicense 1.x и «Неверное имя для CLSID», мы практически с полной уверенностью можем сбросить фемидовский триал для любой программы.
Однако давай все‑таки попробуем отвязать подопытные программы от триала полностью. Общие принципы исследования и взлома защищенных Themida приложений мы рассматривали в предыдущей статье, попробуем применить эти знания на практике.
Для начала сдампим программы для исследования, загрузив их в отладчик x64dbg. Антиотладку обходим при помощи плагинов ScyllaHide и Themidie, хотя в данном конкретном случае достаточно и простого ScyllaHide с конфигурацией Themida — программы прекрасно загружаются и трассируются без каких‑либо проблем. Дампим по стандартной схеме при помощи плагина Scylla. Не будем заморачиваться с полной отвязкой и восстановлением импорта, просто загрузим дампы в IDA для исследования.
Что может быть общего у столь разных программ? Правильно — диалог регистрации, выскакивающий при протухании триала. Места загрузки этого диалога однотипные и легко находятся во всех трех программах.
Notezilla:
RecentX:
Copywhiz:
Ты, наверное, заметил, что первый случай самый нехороший: в программах RecentX и Copywhiz код вызова диалога регистрации оформлен в нормальные процедуры, вызываемые из нормального кода, а в Notezilla данный фрагмент просто висит в воздухе, что бывает при вызове из виртуализированного кода. Если ты читал мою предыдущую статью про «Фемиду», то наверняка помнишь, как непросто копаться в ее виртуальной машине.
Поэтому используем способ полегче. Поскольку у нас работает трассировка, попробуем по стеку вызовов отследить точку входа в виртуализированный фрагмент кода, из которого вызывается это окно. Вот она:
Сделаем смелое предположение, что помимо проверки экспирации триала виртуализованный фрагмент кода не несет в себе никаких жизненно важных для программы действий. Проверить эту гипотезу очень просто — прямо в отладчике меняем переход по адресу 45698C с 15A834A на конец процедуры 456A7C, после чего запускаем программу.
И бинго! Программа запускается как ни в чем не бывало безо всякого регистрационного окна! Теперь надо придумать, как оформить этот алгоритм в виде кряка. Прямой патч EXE здесь, по понятным причинам, не годится: код запакован и зашифрован, да еще и с параноидальным контролем целостности, то есть, самое быстрое и простое решение — патч прямо в памяти.
В моей прошлой статье, посвященной Themida, я приводил пример этого метода, опирающегося на вызываемую из основного процесса открытую DLL. Забегая чуть вперед, скажу, что на этот раз мы попробуем такой способ применительно к другой программе — RecentX, но сначала пойдем от простого к сложному. Поэтому для затравки рассмотрим еще более простой способ патча — через лоадер. Причем лоадер даже не обязательно писать самому, добрые и умные люди написали множество разнообразных лоадеров на любой вкус, выбрать подходящий можно на этой странице.
К сожалению, другие добрые люди тоже следят за прогрессом в этой области и, чтобы помешать распространению свободного программного обеспечения, упорно вносят лоадеры в антивирусные базы. Приходится мириться с тем, что свежескачанный лоадер может быть с визгом убит встроенным антивирусом. Я выбрал для примера более‑менее безразличный антивирусам Abel Loader Generator, хотя, как показала практика, и его самого, и произведенные им лоадеры на многих системах тоже придется извлекать из карантинов и вносить в исключения защитного ПО.
Пользоваться этим генератором не просто, а очень просто — нужно выбрать запускаемую программу, подобрать время задержки и, собственно, патч. В нашем случае патч состоит в том, что после распаковки программы по адресу 45698C нужно поменять безусловный переход jmp 15A834A (последовательность байт E9 B9 19 15 01) на другой безусловный переход jmp 456A7C (последовательность байт E9 EB 00 00 00). Выглядит это так.

Нажимаем кнопку Generate! — и лоадер для программы Notezilla готов. Помещаем его в рабочий каталог приложения и перевешиваем на него шоткат. Можно пользоваться.
Однако ты сам понимаешь, что лоадер, тем более чужой — это способ для совсем ленивых. Главный недостаток описанного метода ты уже, наверное, понял: антивирусы такие лоадеры чертовски не любят. Можно, конечно, написать свой собственный уникальный лоадер, возможно, я когда‑нибудь остановлюсь на этом более подробно, но сейчас у нас мало времени.
Поэтому в заключение построим для программы RecentX патч моим любимым способом — на основе зависимой библиотеки mfc140u.dll. Для начала я опишу суть патча. Выше я приводил код процедуры вызова окна лицензии по адресу 480E60. Рассмотрим ссылки на эту процедуру:
Видно, что везде фигурирует глобальная переменная 56A018, при ненулевом значении которой выбранное действие отрабатывает нормально без вызова окошка активации программы. То есть, в сущности, для активации приложения достаточно присвоить этой переменной ненулевое значение.
Но как отследить этот момент и как присвоить нужное значение? Проанализировав сдампленный код в IDA, мы обнаруживаем, что программа написана на майкрософтовском C и активно юзает MFC-шные функции из библиотеки mfc140u.dll. Ставя бряки на различные функции экспорта этой библиотеки и запуская программу, мы приходим к выводу, что больше всего нам подходит функция __thiscall ATL::CSimpleStringT<wchar_t,1>::CSimpleStringT<wchar_t,1>(wchar_t const *,int,struct ATL::IAtlStringMgr *)> (порядковый номер 270). Она вызывается практически сразу после того, как код программы распакован в память и переменная 56A018 проинициализирована.
Нам нужно всего‑навсего поправить данную функцию так, чтобы она перед своим выполнением записывала в переменную 56A018 значение 1. Не буду подробно описывать процесс построения патча, поскольку неоднократно делал это в своих предыдущих статьях. Остановлюсь только на способе получения реального адреса переменной 56A018 из кода патча. Итак, рассмотрим стек процесса в момент вызова функции 270.

Обрати внимание: адрес возврата в процесс RecentX (44F985) лежит в стеке по адресу [esp+0xC]. Отложив от этого адреса смещение 11A693, получаем адрес нужной нам переменной 56A018. Результирующий код патча mfc140u.dll выглядит так:
Заменяем в рабочем каталоге программы библиотеку mfc140u.dll — и можно забыть о триале.
Я думаю, мы разобрали достаточно приложений для того, чтобы пользуясь полученным опытом, ты понимал устройство однотипных защит. Как видишь, несмотря на всю крутизну протектора, достаточно всего лишь найти правильный подход, и тогда задача взлома Themida вполне посильна, и даже местами рутинна. Конечно, всегда возможны нюансы, к разбору которых мы еще обязательно когда‑нибудь вернемся.
Источник
Наши проекты:
- Кибер новости: the Matrix
- Хакинг: /me Hacker
- Кодинг: Minor Code