Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
Чтобы немного разнообразить свою жизнь, сегодня мы снова займемся разборкой антиквариата. Многие уже забыли о существовании такого инструмента, как давно похороненный P-Code, в который транслировались программы на Visual Basic. Тем не менее созданные с его помощью приложения до сих пор существуют, и сегодня мы с тобой аккуратно сломаем одно из них.
warning
Статья имеет ознакомительный характер и предназначена для специалистов по безопасности, проводящих тестирование в рамках контракта. Автор и редакция не несут ответственности за любой вред, причиненный с применением изложенной информации. Распространение вредоносных программ, нарушение работы систем и нарушение тайны переписки преследуются по закону.
К сожалению (или счастью?), Microsoft поэтапно похоронила P-Code, сперва перейдя на компиляцию пи‑кода в натив, от чего, на мой взгляд, он стал сильно более неуклюжим, а затем и вовсе полностью перевела VB на платформу .NET. Тем не менее из‑за своей простоты и популярности в былые времена созданные на P-Code проекты весьма многочисленны и продолжают работать по сей день.
Чтобы ты не испугался, если вдруг в твои руки попадет подобный раритет, знал, что с ним делать и с какой стороны к нему подойти, рассмотрим специфику и внутреннее устройство P-Code на примере доработки небольшой графической программы. Условия задачи таковы: у нас есть софтина, в текущей поставке которой отключены некоторые полезные функции (нет связанных с ними пунктов меню). Но сама черная кошка в темной комнате присутствует, то есть в модуле имеются и нужные нам пункты меню, и код отвечающих за них функций. Просто они невидимы для нашей лицензии, и открыть их — наша задача.
Для начала определяем тип программы и ее защиту при помощи DetectItEasy.
DIE определил компилятор программы как Microsoft Visual Basic 6.0
Попытка загрузить исследуемую программу в IDA, к сожалению, не принесла никакого полезного результата.
IDA считает, что нативный код отсутствует или зашифрован
Настало время для нашего любимого отладчика x64dbg. Немного повозившись в нем, обнаруживаем, что основной код крутится внутри модуля msvbvm60.dll
.
Программа в отладчике
Налицо классическая виртуальная машина. В ней интерпретируется поток данных, текущий указатель команды находится в регистре esi
. Из потока выбирается байт кода операции, и по его индексу из таблицы адресов обработчиков (6909AA24
в дампе) выбирается адрес обработчика следующей команды, на которую делается переход. По счастью, это не злобный протектор типа Enigma или Themida, никаких обфускаторов и антиотладчиков в коде нет. Более того, нам даже не требуется изобретать велосипед, разбирая виртуальную машину самостоятельно — за время существования VB за нас это сделали другие добрые люди.
Итак, мы наконец вплотную подошли к понятию P-Code. Этот термин был придуман еще полвека назад одним из основоположников современного программирования Никлаусом Виртом для любого аппаратно‑независимого псевдокода виртуальной машины. Однако с легкой руки Microsoft прижилось оно применительно к теперь уже мертвому байт‑коду Visual Basic, преимущественно 6-й версии.
Схема функционирования P-Code предельно проста и видна на скриншоте выше. Из странных особенностей можно отметить наличие целых шести таблиц обработчиков байт‑кодов. Это значит, что не все опкоды псевдокоманд однобайтовые, каждый из последних пяти опкодов главной таблицы (FB-FF
) — «составной» двухбайтовый. То есть обработчик каждого из этих кодов считывает следующий байт и передает управление по его индексу на обработчик из другой таблицы адресов, в которой тоже содержится 256 возможных значений. Непонятно, зачем используется такой хитрый способ, а главное — для чего предусмотрен такой запас опкодов, ведь из 1531 возможного задействовано всего 822, причем некоторые дублируют друг друга.
Я не буду приводить здесь полную таблицу опкодов P-Code, желающие могут найти ее на сайте DotFix или даже в более информативном виде в исходниках проекта Semi-VB-Decompiler. Там же приводятся аргументы и примерный смысл каждого опкода.
Вооружившись данной информацией, гораздо продуктивнее разбирать и отлаживать программу даже в x64dbg. Однако существуют и еще более продвинутые инструменты для отладки и декомпиляции пи‑кода. Два из них ты уже, наверное, увидел по приведенным выше ссылкам: свободный декомпилятор Semi-VB-Decompiler и коммерческий VB Decompiler. Еще один незаменимый инструмент для работы с пи‑кодом — свободный дизассемблер‑отладчик VBDec.
Надо сказать, что эти проекты весьма сырые и имеют массу недочетов (к примеру, Semi-VB-Decompiler у меня вообще не декомпилировал ни одного файла и не смог найти валидную сигнатуру), но их возможности дополняют друг друга. К примеру, VB Decompiler умеет с более‑менее переменным успехом не только дизассемблировать, но и восстанавливать VB-код. Причем не только из P-Code, но и из скомпилированного из него натива, и даже из .NET. А хоть VBDec этого и не умеет, зато его дизассемблер на несколько порядков более прямой и безглючный, а главное, у него есть полнофункциональный дебаггер с возможностью трассировки P-Code.
Вернемся к нашей задаче и попробуем решить ее уже с помощью этих чудесных инструментов. Для начала открываем исследуемую программу в VB Decompiler и ищем главное окно. В VB Decompiler для этого имеется инструмент Tools-Search string (он, правда, временами подглючивает, но потерпеть можно). Хоть программа и обфусцирована, но мы находим и главное окно MDIForm1, и первый пункт меню из скрытых из‑за отсутствия лицензии.
Форма основного окна, вид из VB Decompiler
Источник: xakep.ru