JustPaste.it

Хакер - Deleaker, не болей! Ломаем защиту в обход VMProtect и пишем proxy DLL

nopaywall

https://t.me/nopaywall

Не так давно на глаза мне попалась программа Deleaker. Софтина, из описания на сайте, предназначена для поиска в приложениях утечек памяти, GDI-ресурсов и незакрытых хендлов. А мне стало интересно, как у нее обстоят дела с защитой от взлома.
warning-icon.jpg

WARNING

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

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

 

Greetings

Мои благодарности завсегдатаям форума exelab.ru:

  • Mak;
  • VodoleY;
  • ELF_7719116;
  • Kindly

и многим другим.

 

Процесс

Программа устанавливается в директорию C:\Program Files (x86)\Deleaker как standalone, хотя есть вариант интеграции Deleaker в Visual Studio в виде дополнения (.vsix). Но я не пользуюсь Visual Studio, и для меня такой способ был недоступен.

В директорию были установлены такие файлы.

Запускаем программу и вводим присланный ключ. Софтина обещает нам пробный период использования.

Замечательно. ?

 

Инструменты, которые нам понадобятся

  • x64dbg — отладчик;
  • DIE aka Detect It Easy — анализатор файлов;
  • CFF Explorer — PE-редактор;
  • MASM — компилятор.

Итак, проверив все исполняемые файлы анализатором DIE, в директории установленной программы находим две DLL’ки, «накрытые» VMProtect:

  • deleakersdk32.dll;
  • deleakersdk64.dll.

Я предположил, что механизм (код) лицензирования (регистрации) находится именно в них.

 

Зачем нужны две DLL’ки?

Забегу вперед: DLL’ки идентичны, единственное различие — одна 32-битная, другая 64-битная. Механизм лицензирования (регистрации) используется только из deleakersdk32.dll, что облегчает нашу задачу.

Далее я открыл deleakersdk32.dll в CFF Explorer и зашел в директорию Export. Там нашлись четыре экспортируемые функции с говорящими именами.

Эти функции как раз и отвечают за лицензирование (регистрацию) программы.

Все бы хорошо, если бы файл Deleaker.exe, который, собственно, и использует в данном случае deleakersdk32.dll, не был написан на .NET, а сама DLL — на Visual C++. То есть запустить Deleaker.exe напрямую в отладчике x64dbg у нас не получится.

Но это не беда, мы просто запускаем Deleaker.exe и аттачимся к процессу x64dbg.

В окне Symbols отладчика, в левой половине находим и выделяем курсором нашу DLL. Справа мы увидим список ее импортируемых и экспортируемых функций. Нас интересуют только те, что мы обнаружили ранее в CFF Explorer. Выделяя по очереди курсором функции, нажимаем клавишу F2, тем самым устанавливая точки останова (breakpoints) на начало исполнения кода этих функций.

После этого возвращаемся в окно Deleaker. Кликаем Help → About.

В отладчике останавливаемся в начале функции DeleakerSDK_IsRegistered. Эта функция, по логике, должна возвращать флаг TRUE или FALSE. Прокрутив в отладчике функцию до конца, видим, что программа открывает и читает файл ключа DeleakerLicense.key в директории C:\ProgramData\Deleaker.

Файл содержит пробный регистрационный ключ, который я ввел раньше в программе. В отладчике, в окне стека (правый нижний угол) кликаем по первому адресу правой кнопкой мыши, выбираем Follow DWORD in Disassembler и в окне CPU отладчика оказываемся на адресе, куда поток вернется после выхода из функции. Устанавливаем на этом адресе точку останова, нажав клавишу F2.

Далее отпускаем поток нажатием клавиши F9. Отладчик останавливается на данном адресе, и в регистре EAX мы видим TRUE, запоминаем это.

Опять нажимаем F9, и отладчик встает уже на второй функции DeleakerSDK_GetRegisteredUserName. Из названия понятно, что функция возвращает имя зарегистрированного пользователя. В функцию передается указатель на ячейку памяти, куда функция должна вернуть указатель на буфер с именем пользователя. Этот буфер обязательно должен быть выделен в памяти API SysAllocString.

В окне стека кликаем правой кнопкой мыши по адресу, который располагается ниже адреса возврата из функции. Выбираем из списка Follow in Dump и в окне дампа памяти по адресу в стеке видим пустую ячейку — вот там и должен оказаться адрес буфера.

Далее перемещаемся в окне отладчика CPU на адрес возврата из функции и ставим там точку останова. «Отпускаем» отладчик и останавливаемся на выходе из функции. Видим, что в ячейке памяти появился адрес буфера и в EAX у нас TRUE, — это говорит об «удачном» завершении функции.

В окне дампа кликаем опять правой кнопкой мыши по адресу в ячейке памяти и выбираем Follow DWORD in Current Dump.

Мы попадаем непосредственно в буфер памяти, где в формате double char или Unicode находится сообщение, что срок пробной версии истекает 24 января 2018 года. В «зарегистрированной» версии программы в буфере находится имя пользователя.

 

Движемся дальше

У нас остались еще две функции, в которые мы тоже заглянем.

Снимаем точки останова, которые мы ставили на выходе из функций, и «отпускаем» отладчик, нажимая F9.

Теперь в окне Deleaker кликаем License → License Status… и отладчик теперь остановился в третьей интересующей нас функции DeleakerSDK_GetLicenseInformation. В эту функцию для получения необходимой информации из ключа передается указатель на уже «подготовленный» буфер размером 1296 (0х510) байт. В него копируются данные о текущей лицензии, а именно первые четыре байта, или DWORD, — это флаг, который указывает, действующая лицензия или нет, и остальные байты — это информация о лицензии в формате Unicode.

Ставим точку останова на выходе из функции, в окне стека кликаем по второму сверху адресу правой кнопкой и выбираем Follow in Dump, в окне дампа памяти увидим «пустую» область памяти — это и есть буфер-приемник. Далее «отпускаем» отладчик, нажимая F9, и останавливаемся уже на точке останова на выходе из функции. В регистре EAX находится TRUE. В буфере — информация о текущей лицензии.

И последняя функция. В окне Deleaker кликаем License → VieW Serial… Отладчик остановится в функции DeleakerSDK_GetSerialKey.

Она аналогична по формату приема параметров и отдачи данных DeleakerSDK_GetRegisteredUserName, разница только в том, что она возвращает указатель на буфер с Unicode-строкой в формате Base64 из файла DeleakerLicense.key, выделенный API SysAllocString, и флаг TRUE в EAX.

 

Кодинг

Теперь мы знаем все необходимые параметры и возвращаемые данные функций.

Для решения задачи я выбрал путь написания proxy DLL. Переименовываем deleakersdk32.dll в deleaker32.dll. Нужно написать свою deleakersdk32.dll, которая будет перенаправлять все обращения через себя в оригинальную deleakersdk32.dll за исключением функций, участвующих в лицензировании (регистрации) программы. Приведу код только тех функций, которые мы будем эмулировать. Исходный код proxy DLL прикреплен к статье ниже.

Итак, код написан на макроассемблере, синтаксис MASM. Это эмулированные мной функции:

И конечный результат.

info-icon.jpg

INFO

Так как Deleaker устанавливается и в Microsoft Visual Studio в виде дополнения (.vsix), то процедуру с переименованием оригинальной DLL и заменой ее нашей следует повторить и в директории, куда установлена студия в папке Extensions.

 

Выводы

Ты спросишь, а где же во всей этой истории VMProtect? И я отвечу, что он в данном случае присутствует в программе чисто номинально. Серьезный потенциал VMProtect автор программы просто свел к нулю своими безграмотными действиями. Защитив, как ему казалось, критичные участки кода в программе, он оставил дыру размером с футбольное поле.

  • Связывать разные платформы в одном продукте (в нашем случае это .NET и VC++) нужно грамотно. Именно «на стыке» платформ и образовалась гигантская «дыра». Если тебе важна безопасность, лучше вообще отказаться от чего-то одного.
  • Стоит избавиться от «узких мест». Проверку лицензии и функционал программы, зависящий от результатов проверки лицензии, необходимо разместить в одном и том же модуле, накрыв критичные куски кода и код, который использует результат их работы, тем же самым VMProtect. Эффективность защиты при этом возрастет в разы.

Надеюсь, что разработчик прочитает эту статью и учтет все описанные недостатки в защите своего ПО.

Читайте ещё больше платных статей бесплатно: https://t.me/nopaywall