Total Commander (ранее Windows Commander) — популярный файловый менеджер с графическим интерфейсом для Windows. В интернете на варезных сайтах можно найти множество решений для взлома Total’а. Их неизменный недостаток — костыльность: с выходом новой версии надо проделывать ту же процедуру «лечения» программы вновь и вновь. Но можно и по-другому. Хочешь узнать как и заодно прокачать скиллы в реверсе? Читай эту статью!

Какое-то время назад мой друг Jupiter предложил вместе разобрать алгоритм лицензирования Total’а. Пораскинув мозгами, мы написали генератор лицензии — файлов-ключей. И все было бы замечательно, если бы не присутствие в основе алгоритма лицензирования криптосистемы с открытым ключом — LUC. И ключи, разумеется, для успешного прохождения лицензирования нужно знать.

LUC — это похожая на RSA криптосистема. Ее отличие от RSA заключается в использовании последовательностей Люка вместо возведения в степень. Как и для RSA, для генерации закрытого ключа необходимо знать множители (P и Q), которые можно получить через факторизацию модуля (N). Но в нашем случае длина модуля — 832 бита. Естественно, ни у меня, ни у Jupiter’а таких вычислительных мощностей нет. А на квантовый компьютер мы еще денег не накопили. 🙂

Как повлияло бы на описанную атаку увеличение модуля (N) до 2048 бит?

Загрузка ... Загрузка ...

Для решения этой проблемы мы сами сгенерируем приватный и публичный ключ криптоалгоритма LUC. Приватным зашифруем лицензию, публичным программа будет расшифровывать лицензию. А чтобы публичный ключ проходил, мы пропатчим его в памяти.

Помимо LUC, в Total’е присутствуют механизмы самозащиты, защита от модификации исполняемого файла. Можно, конечно, хардкорно запатчить файл, но это как раз и есть «костыль», который лишает обход защиты универсальности.

WARNING

Статья публикуется в образовательных целях. Редакция не несет ответственности за любой вред, причиненный материалами данной публикации. В статье намеренно не рассматривается сам алгоритм лицензирования, а демонстрируются практические аспекты имплементации обхода защиты с помощью техники proxy DLL.
 

Что делаем?

Наша задача — заменить модуль (N) в исполняемом файле программы, не нарушая его целостности. Тогда наш сгенерированный файл ключа будет верно расшифрован и программа будет зарегистрирована.

Существует два варианта решения данной задачи:

  1. Написать загрузчики для х86- и х64-версий программы (Loader).
  2. Написать proxy DLL, которые будут выполнять ту же функцию, что и загрузчики.

Оба варианта позволяют беспрепятственно обновлять программу. Но я выбираю второй вариант, он более удобный. В этом варианте не нужно будет исправлять пути в свойствах ярлыков программы с исполняемого файла Total’а на наш лоадер. Достаточно просто скопировать DLL’ки и файл ключа в папку с установленной программой.

 

Инструменты

  • x64dbg — отладчик;
  • masm x32 — компилятор;
  • masm x64 — компилятор;
  • wincmd.key — ключ для программы, сгенерированный моим с Jupiter’ом кейгеном.
 

Процесс

Что делает proxy DLL?

Загрузка ... Загрузка ...

Я скачал с официального сайта последнюю бета-версию, включающую в себя обе версии программы (х86 и х64). Установил в директорию, которую предложил инсталлятор (C:\totalcmd).

Установленные файлы
Установленные файлы

Теперь запускаем на выбор TOTALCMD.EXE или TOTALCMD64.EXE, без разницы. Получаем вот такое окно.


Это было ожидаемо. 😉 Теперь запускаем Total под отладчиком и заходим в закладку Symbols.


В левой половине окна видим загруженные в память процесса модули (DLL). Из всех модулей нас интересуют только две динамические библиотеки — это version.dll и winspool.drv.

Пусть тебя не смущает, что у winspool.drv расширение не dll, на самом деле внутренняя структура у winspool.drv как у обычной динамической библиотеки. Эти два модуля и будут кандидатами для написания одноименных proxy DLL для Total’а.

INFO

Мы пишем два модуля потому, что у нас две версии программы: х86 и х64. Для каждой версии мы будем использовать proxy DLL соответствующей разрядности.

 

Как работает механизм proxy DLL

В основе механизма proxy DLL лежит особенность загрузки модулей (DLL) в память процесса Windows загрузчиком (NTLDR или NT Loader).

В Windows-загрузчике этим занимается API LdrLoadDll, который находится в модуле ntdll.dll. Обертками этого API служат такие API, как LoadLibrary и LoadLibraryEx.

Один из этапов загрузки исполняемого файла (в нашем случае это модуль с расширением EXE) — это заполнение таблицы импорта исполняемого файла адресами API из DLL, необходимых для работы программы. В начале этого процесса LdrLoadDll начинает искать модуль (DLL) по имени файла, к примеру version.dll, который находится в таблице импорта в виде строки в кодировке ASCII. LdrLoadDll ищет DLL в текущей директории созданного процесса, в нашем случае это C:\totalcmd. Далее, если модуль не был найден, в зависимости от битности процесса (х86 или х64) LdrLoadDll продолжает поиск требуемой DLL в системной директории (C:\Windows\System32 или C:\Windows\SysWOW64). Если и в системной директории модуль не будет найден, мы получим сообщение об ошибке.

LdrLoadDll позволяет загружать в адресное пространство созданного процесса модули, имеющие одно и то же название, из разных директорий. К примеру, в нашем случае proxy DLL загружает в память NTLDR из директории, где находится TOTALCMD.EXE, а оригинальную DLL (из системной директории) мы загружаем в память из proxy DLL с помощью API LoadLibrary, передавая ей в качестве параметра абсолютный путь к оригинальной DLL. Это еще один нюанс, который позволяет реализовать механизм proxy DLL. Далее из приведенного кода proxy DLL ты поймешь, как это работает. 🙂

Продолжаем. В процессах TOTALCMD.EXE и TOTALCMD64.EXE обе DLL присутствуют. Для TOTALCMD.EXE мы будем использовать version.dll, а для TOTALCMD64.EXEwinspool.drv.

В Total’е модуль (N), участвующий в расшифровке файла ключа (wincmd.key), имеет вид строковой константы в кодировке ASCII:

AAD4474DC8387E81BB095D810F4F4F21D5D7CCC756E3D6E5DEE48AC000C25AA0EFAD0AD3A5AC46F15B50249597461BBB87CDC3F1BA37C17A9A207A3603E38E718F9927A5EB38005D8B72EAFDC63931C3D93C1FAD457A17CA85BEB40F3FA9152770DAC12E8E3B912D

Его необходимо, для правильной расшифровки нашего ключа, заменить на наш модуль (N):

E813039FB5F248DDA582F1C411D3B5B7A4C97CBB6982388EB354A8B78324A6A7B494ABAB4A0A97728BAC585FCD856D2173F4C3ADE89E8176AE53F7BF7AEC39FCACEC907829B31FE1C3BB3E2E4C30925525655F967B52A0318FCE0BA0BAE065D8A68DBE86167F67A1

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

Итак, запускаем х86-версию и переходим в закладку Memory Map. Нажимаем сочетание клавиш Ctrl + B, откроется окно бинарного поиска в памяти процесса, копируем оригинальный модуль (N) и вставляем его в поле ASCII.


Нажимаем OK, и у нас откроется закладка References с результатами поиска.


Видим адрес, по которому был найден модуль (N), — 0x004E219C.


Переходим в окно дампа памяти по данному адресу и скроллом поднимаемся вверх.



Видим адрес 0x00401000. Это верхний адрес секции, в которой находится модуль (N).

Опять возвращаемся в закладку Memory Map и видим, что адрес 0x00401000 соответствует адресу первой секции исполняемого файла TOTALCMD.EXECODE.


Для х64-версии проделываем те же самые манипуляции с отладчиком.

В результате выясняем, что ASCII-строка модуля (N) для х86-версии находится в секции CODE (0x00401000), а для х64-версии — в секции .data (0x0000000000AD9000).

Ну что же, необходимую информацию для написания proxy DLL мы получили. Начинаем кодить. 🙂

Что позволяет выполнять proxy DLL?

Загрузка ... Загрузка ...
 

Кодинг

Разберем код для х86-версии, а именно version.dll. Для х64-версии все аналогично. Точка входа proxy DLL (EntryPoint). Здесь все стандартно.


API DisableThreadLibraryCalls использовать не обязательно. Я пользовался им для отключения уведомлений DLL_THREAD_ATTACH и DLL_THREAD_DETACH, на всякий случай.

Далее переходим в MainProc.


Здесь я объявляю глобальные переменные, для сохранения адресов оригинальных API.

Резервирую область памяти для сохранения полученного пути к оригинальной version.dll.


Здесь я прокомментировал все шаги исполнения кода MainProc.


Чуть ниже MainProc я объявляю экспортируемые функции с безусловными переходами (JMP) из proxy DLL в оригинальную DLL. В файле version.def определены имена экспортируемых функций proxy DLL, которые аналогичны именам функций в оригинальной DLL.

Как еще загрузить proxy DLL в адресное пространство атакуемого процесса?

Загрузка ... Загрузка ...
LIBRARY version
EXPORTS
GetFileVersionInfoA=__GetFileVersionInfoA@0
GetFileVersionInfoByHandle=__GetFileVersionInfoByHandle@0
GetFileVersionInfoExW=__GetFileVersionInfoExW@0
GetFileVersionInfoSizeA=__GetFileVersionInfoSizeA@0
GetFileVersionInfoSizeExW=__GetFileVersionInfoSizeExW@0
GetFileVersionInfoSizeW=__GetFileVersionInfoSizeW@0
GetFileVersionInfoW=__GetFileVersionInfoW@0
VerFindFileA=__VerFindFileA@0
VerFindFileW=__VerFindFileW@0
VerInstallFileA=__VerInstallFileA@0
VerInstallFileW=__VerInstallFileW@0
VerLanguageNameA=__VerLanguageNameA@0
VerLanguageNameW=__VerLanguageNameW@0
VerQueryValueA=__VerQueryValueA@0
VerQueryValueW=__VerQueryValueW@0

И главная функция proxy DLL — это ReplaceModulus.


В секции данных proxy DLL у меня находятся оригинальный модуль (Original) и модуль (New), на который необходимо заменить оригинальный.


Здесь тоже все шаги выполнения кода прокомментированы.

 

Финал

Результатом всех описанных действий будет зарегистрированная версия программы. Причем в данном случае можно спокойно обновлять программу, не боясь того, что регистрация «слетит». 🙂

Копируем в папку с Total’ом три файла — это наш ключ wincmd.key и наши DLL’ки: version.dll и winspool.drv. Запускаем программу.


В диспетчере задач видим, что в процесс загружены обе DLL’ки.


Радуемся. 🙂

Насколько легален метод proxy DLL?

Загрузка ... Загрузка ...
 

Итоги

Как видишь, механизм proxy DLL — удобный и мощный инструмент. С его помощью ты можешь беспрепятственно эмулировать работу оригинальных функций и при этом комфортно модифицировать данные и код в памяти процесса.

 

Исходники и ключ

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

Пароль — xakep.ru.

10 комментариев

  1. Аватар

    baragoz

    16.05.2018 в 14:43

    А зачем нужно ставить новые версии ТС? У меня старая, серийник Университета Амстердама 😉

  2. Аватар

    Egor3f

    16.05.2018 в 16:33

    Double Commander бесплатный, опенсорсный, кросплатформенный, копирует интерфейс TC и выполняет большую часть его функционала.
    Статья интересная, автору спасибо!

    • Аватар

      Kakoluk

      16.05.2018 в 23:16

      Двухпанельный файловый менеджер. Что может быть проще и гениальнее? Только трехпанельный.(Шучу) А теперь серьёзно: это не какой то там позорный busybox или же command.com .
      Это интерфейс с «человеческим» лицом. 🙂

  3. Андрей Васильков

    Андрей Васильков

    16.05.2018 в 18:24

    Double Commander только внешне похож, а TTCMD с плагинами заменяет 100500 других программ.

  4. Аватар

    inkognito.o

    16.05.2018 в 20:43

    Как честный пользователь Total Commanderа я в шоке!

  5. Аватар

    inkognito.o

    16.05.2018 в 20:47

    я вот по ностальгии по Amiga использую Directory Opus. Разработчики эту прогу успешно развивают и хорошии фичи вливают. Ещё есть чешская Altap Salamander!

  6. Аватар

    il--ya

    18.05.2018 в 12:07

    Total Commander — первая и одна из очень немногих программ, за которую я оплатил лицензию. Просто потому, что она того заслуживает. Да не так и дорого стоит для такого незаменимого и удобного инструмента — EUR 37, студентам и школьникам 28.

  7. Аватар

    JK_MIB

    21.05.2018 в 08:46

    Годный пример как пропатчить чужой код.
    И файлы целы и юзеры (хакеры) довольны)

    З.Ы. пользуюсь FARом

  8. Аватар

    TuMyP

    21.05.2018 в 11:50

    Блин, это, конечно, хакерский подход, но ведь есть способ намного проще, хоть и не труъ: скрипт на autoit, который нажимает нужную кнопочку 🙂

Оставить мнение