• Что бы вступить в ряды "Принятый кодер" Вам нужно:
    Написать 10 полезных сообщений или тем и Получить 10 симпатий.
    Для того кто не хочет терять время,может пожертвовать средства для поддержки сервеса, и вступить в ряды VIP на месяц, дополнительная информация в лс.

  • Пользаватели которые будут спамить, уходят в бан без предупреждения. Спам сообщения определяется администрацией и модератором.

  • Гость, Что бы Вы хотели увидеть на нашем Форуме? Изложить свои идеи и пожелания по улучшению форума Вы можете поделиться с нами здесь. ----> Перейдите сюда
  • Все пользователи не прошедшие проверку электронной почты будут заблокированы. Все вопросы с разблокировкой обращайтесь по адресу электронной почте : info@guardianelinks.com . Не пришло сообщение о проверке или о сбросе также сообщите нам.

Ломаный Excel. Обходим защиту VBA-скриптов в DoneEx Compiler

Sascha Оффлайн

Sascha

Заместитель Администратора
Команда форума
Администратор
Регистрация
9 Май 2015
Сообщения
1,480
Баллы
155
Сегодня мы разберемся с тем, как устроена «непробиваемая» защита VBA-скриптов в Excel, предлагаемая компилятором DoneEx VBA Compiler. Мы посмотрим, как этот инструмент компилирует макросы в нативные DLL, какие трюки использует для контроля целостности, и шаг за шагом покажем, как обходить проверки и восстанавливать исходный код из скомпилированных модулей.

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

Я уже писал статьи про подобные защиты, разработанные на JavaScript, Python, PHP и даже AutoIT. Сегодня у меня наконец‑то дошли руки до темы защиты экселевских VBA-скриптов.

Недавно я наткнулся на известный в очень узких кругах компилятор

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

. Он позиционируется ни много ни мало, как полноценный компилятор Excel VBA в нативный код со встроенной защитой. Сразу предупреждаю: это поделие достаточно кривое — лично мне, чтобы скомпилировать на нем хоть какой‑то более‑менее работоспособный пример, понадобилось гораздо больше времени, чем разобраться, как снимать саму защиту. Однако ее описание изобилует громкими претенциозными заявлениями вроде «код VBA не может быть скопирован или восстановлен и имеет самый высокий уровень защиты от пиратства». Давай попробуем оспорить это утверждение.

К слову сказать, эти ребята еще и

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

, который, правда, без установленного Excel не запускается, но это совсем другая история, которой мы сегодня касаться не будем.

Итак, предположим, что нам в руки попал необычный экселевский файл. К нему прилагается одна (или две) DLL-библиотека с тем же именем, но возможны суффиксы *_64 или *_32 в зависимости от разрядности. Если натравить на них Detect It Easy, программа показывает компилятор MinGW(GCC: (GNU)), однако ординалы из них экспортируются довольно подозрительные.

alt


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

alt


Пока оно висит, откроем наш любимый отладчик x64dbg и приаттачимся к процессу Excel. Принудительно прервав его выполнение, мы видим занятный стек вызовов.

alt


Из него как на ладони видна последовательность вызовов, порождающих это окно. Вначале непосредственно из VBA-кода вызывается функция SetThisWorkbook, экспортируемая из нашей скомпилированной библиотеки testvba1_xlsm_64.dll. Эта функция вызывает функцию DummyFunc05 некоей загадочной библиотеки cbinrtl.dll, отсутствующей в каталоге макроса и вообще непонятно откуда взявшейся. А уже она выкидывает окно предупреждения, реализованное через функцию DialogBoxIndirectParamW.

При детальном рассмотрении мы обнаруживаем эту библиотеку в подкаталоге v6n3vk66ej (название при каждом вызове случайное) временной папки Windows. Скомпилированный модуль testvba1_xlsm_64.dll сохраняет ее туда из соответствующего собственного ресурса при вызове SetThisWorkbook, а затем подчищает за собой при отработке. Собственно, скомпилированный модуль практически целиком и состоит из библиотеки cbinrtl.dll, хранящейся в нем в явном незашифрованном виде, так же как и в самом модуле компилятора vbaclr4e.exe, от которого ее и получает. Это дает надежду на убиение двух зайцев патчем файла testvba1_xlsm_64.dll — можно патчить код и библиотеки testvba1_xlsm_64.dll, и порождаемой ею библиотеки cbinrtl.dll.

Попробуем это реализовать. Сразу напрашивается гипотеза, что защита сосредоточена в функции DummyFunc05, — ведь именно ее вызов и выводит сообщение о незарегистрированной версии. Однако ее нельзя просто так взять и закоротить — Excel при этом падает с ошибкой. При ближайшем рассмотрении мы видим ее вызовы в IDA. Почему так происходит? Эта функция заполняет некую жизненно важную для программы структуру qword_62FC9180.

alt


Значит, придется копать вглубь кода DummyFunc05, благо основные вызовы у нас уже размечены на стеке. Довольно быстро мы натыкаемся на развилку в коде cbinrtl.dll, которая ведет к заполнению структуры qword_62FC9180 (на следующем скриншоте она обозначена как a2, поскольку передается вторым параметром в процедуру).

alt


Функция sub_180047A20 в незарегистрированной версии выкидывает окна c предупреждениями, однако, если скомпилировать модуль без защиты, эта функция просто возвращает 1 без лишних слов. Если в отладчике закоротить ее на return 1, все тоже работает безо всяких предупреждений, но при попытке патча модуля testvba1_xlsm_64.dll нас ждет сюрприз. Находим во вложенном в файл testvba1_xlsm_64.dll модуле cbinrtl.dll место, соответствующее sub_180047A20, и патчим его нужным образом.

alt


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

Первое, что бросается в глаза, — проверка 128-битного хеша SHA-1 непосредственно перед загрузкой cbinrtl.dll. Обрати внимание на верхнюю часть скриншота — загрузка модуля происходит только тогда, когда функция sub_62FC28D4 дает добро.

alt


Внутри она реализована так.

alt


Функция sub_62FC27F7 читает весь модуль, sub_62FC2095 считает его хеш, который затем сравнивается с тестовым значением при помощи memcmp (его возвращает sub_62FC1720). Эту проверку легко можно закоротить, однако ей дело не ограничивается. Если мы это сделаем, то модуль cbinrtl.dll загружается, патченная функция DummyFunc05 корректно отрабатывает, однако в самом конце SetThisWorkbook вылетает по эксепшену при вызове некоего безымянного callback из того же cbinrtl.dll.

alt


В непатченном варианте указатель на функцию qword_62FC90B0 содержит совершенно другой адрес, который отрабатывает нормально. Помнишь, в начале нашего повествования я упоминал некую жизненно важную структуру qword_62FC9180, заполняемую в DummyFunc05? Она как раз и содержит этот адрес и, если модуль пропатчен, заполняется некорректно. Разработчики решили поумничать и максимально запутать этот путь, но мы хитрее их и поэтому поищем обходную тропинку.

Нам известно, что существует как минимум еще одна проверка целостности, помимо sub_62FC28D4, которая заново перечитывает файл cbinrtl.dll (все данные, считанные функцией sub_62FC28D4, остаются локально внутри нее). Поэтому мы сразу по отработке sub_62FC28D4 ставим точку останова на ядерную функцию ReadFile, и — о чудо! — она тут же срабатывает на новом чтении файла cbinrtl.dll. Снова смотрим на стек вызовов.

alt


Очень интересно: выходит, на этот раз новорожденная cbinrtl.dll перепроверяет сама себя на невинность. Двигаясь по стеку вызовов вверх, мы обнаруживаем саму процедуру подсчета хеша.

alt


На скриншоте функция cbinrtl.7FF9985145B0 возвращает в регистре RAX адрес указателя на 512-битный хеш Whirlpool от модуля cbinrtl.dll (выделен в дампе). В этом случае запатчить проверку не так просто, в отличие от предыдущего случая, где хеши тупо сравнивались при помощи memcmp. Разработчики решили заморочиться по максимуму, проделывая над полученным хешем множество мудреных манипуляций, которые в итоге и приводят к неочевидному перемешиванию данных в структуре qword_62FC9180.

Источник:

Пожалуйста Авторизируйтесь или Зарегистрируйтесь для просмотра скрытого текста.

 
Вверх Снизу