Get your Xojo. Реверсим приложение на REALbasic
the Matrix
Часто реверсить программный продукт сложно не потому, что его код запутан или на него навесили какую‑то особенную защиту, а потому, что разработчики использовали редкий и малораспространенный фреймворк. Сегодня в нашем меню — экзотическая среда разработки под названием REALbasic (Xojo).
Это один из пионеров кросс‑платформенного программирования. REALbasic неоднократно менял название, архитектуру и хозяев и в последнее время серьезно растерял как свои рыночные позиции, так и актуальность. Написанные на нем приложения встречаются все реже и реже, в основном в таких узкоспециализированных областях, как колориметрия. Из‑за малой распространенности для него, в отличие от известных сред разработки (вроде Delphi, .NET или VBS), практически отсутствуют специализированные инструменты для реверса. Поэтому мы, как обычно, на примере конкретных приложений разберем принципы и лайфхаки для изучения кода таких приложений.
Начнем с самого простого случая. Как ни странно, легче всего исследовать приложение, созданное в современных актуальных версиях Xojo (да‑да, он мало того что еще поддерживается, вдобавок стал 64-битным, Википедия врет).
Итак, нам попалось графическое приложение, при анализе которого наш безотказный Detect It Easy (DIE) утверждает, что это Xojo (x64).

Нам понадобится самая малость: включить функции приложения, которые отказываются работать в незарегистрированной версии, выдавая вместо этого окошки с требованием регистрации. Загрузив программу в отладчик x64dbg и притормозив ее в этом месте, мы с облегчением замечаем, что программа не зашифрована, не упакована и лишена средств антиотладки. Она даже сообщение выдает стандартным MessageBoxA, при этом программа прекрасно дизассемблируется при помощи IDA. Полученный код, правда, как и следовало ожидать от кросс‑платформенного бейсика, чудовищно неуклюж и сложен для понимания.

Хочется как‑то облегчить себе жизнь, хотя бы восстановив имена вызываемых методов. Наш предыдущий опыт работы со скомпилированным кодом, изначально предназначенным под интерпретатор, подсказывает, что эта информация где‑то обязательно должна храниться. Просмотрев в IDA все ссылки на процедуру, из которой была вызвана ошибка демоверсии, находим интересную конструкцию:
Бегло просмотрев код, обнаруживаем великое множество подобных конструкций по всему дизассемблированному приложению. Очевидно, что это инициализация каких‑то внутренних REALbasic-овских таблиц методов. Вероятнее всего, за это ответственна функция RuntimeAllocateAttributeTable из модуля XojoGUIFramework64.dll, вызывает сомнение только способ передачи параметров. Вроде как строки и адреса перед вызовом RuntimeAllocateAttributeTable записываются в стек, однако не в область параметров, а в область локальных переменных, причем по совершенно разным адресам. Попробуем проанализировать еще пару подобных конструкций:
Вот еще один пример:
Немного пораскинув мозгами, мы приходим к выводу, что на входе в RuntimeAllocateAttributeTable в регистре RCX находится указатель на некую таблицу, каждый элемент которой занимает 0x40 байт и имеет примерно следующую структуру:
А в регистре RDX хранится относительное смещение на текущий элемент данной таблицы в байтах. В принципе, поковырявшись в коде и отладчике, при желании можно раскопать сакральный смысл и остальных полей этой таблицы, но мы не будем отвлекаться: полученной информации нам уже почти достаточно для дальнейшего исследования структуры кода.
Итак, ставим условную точку останова на функцию RuntimeAllocateAttributeTable со следующим текстом журнала:
ClassName: {s:[rcx+rdx+0x20]} MethodName: {s:[rcx+rdx]} Address: {[rcx+rdx+0x28]} called at {[rsp]}
Последний параметр, адрес вызова, нам необходим на всякий случай, чтобы отследить место, в котором что‑то пошло не так при вызове. Перезагружаем программу и — бинго! — в журнале x64dbg видим не идеальный, но относительно вменяемый список имен методов с адресами:
К сожалению, суть этого метода состоит в том, что он чисто динамический, то есть нельзя получить список имен просто из дизассемблера, не запустив программу. Но если тебя вдруг настигнет приступ перфекционизма, можно просто распарсить этот список и скриптом расставить в IDA или x64dbg метки с именами методов по нужным адресам.
Нам же некогда отвлекаться на подобные мелочи. Пока вполне достаточно того, что при заходе в каждую процедуру, которую IDA не детектит как стандартную бейсиковскую, мы можем найти ее имя по адресу в полученном списке. Если, конечно, она там вообще находится, а такое тоже бывает. В любом случае у нас уже есть неплохой инструмент, благодаря которому за десять минут работы с отладчиком и IDA мы обнаруживаем и патчим все проверки на жадность в программном модуле и готовы продолжать дальнейшее знакомство с особенностями Xojo.
Чтобы немного усложнить себе жизнь, рассмотрим чуть более старый, 32-битный вариант REALbasic. Итак, у нас есть другая программа, загрузка которой в DIE показывает следующее окошко.

Казалось бы, 32-битная версия Xojo должна быть проще, ан нет. Загрузив приложение в IDA, мы с удивлением обнаруживаем практически полное отсутствие кода и импорта при внушительном размере EXE-модуля.

Разгадка проста: практически весь EXE-модуль состоит из огромного оверлея, который подгружается на произвольные адреса во время загрузки программы. А значит, даже дампить для изучения уже загруженный модуль особого смысла нет, хотя сама программа не мешает ни отладке, ни дампу. Погуглив, обнаруживаем, что более старую версию нашего фреймворка народ уже изучал и даже запилил на ее основе питоновский скрипт под IDA, который парсит оверлей.
Желающие могут ознакомиться с этим скриптом самостоятельно, я же не стану останавливаться на нем подробно, поскольку скрипт на нашем модуле не работает, а структура оверлея немного отличается от описанной в упомянутой статье. Будь у нас в запасе побольше времени, мы бы могли разобрать новую структуру по винтикам, понять, что изменилось, и создать на основе старого новый работоспособный скрипт, поддерживающий наш формат. Но мы пойдем другим путем.
Помнишь, как мы выкрутились в случае 64-битной версии? Повесили бряк на функцию RuntimeAllocateAttributeTable из модуля XojoGUIFramework64.dll и ловили им инициализацию каждого метода. Разумеется, при загрузке в отладчик программы в ней нет никакого импорта, кроме нескольких базовых функций kernel32, необходимых для загрузки оверлея. Однако, прервавшись в отладчике внутри уже загруженной программы, мы видим необходимый модуль в списке — здесь он называется XojoGUIFramework32.dll, и необходимая функция RuntimeAllocateAttributeTable там есть.
Ставим на нее бряк и перезагружаем программу в отладчике. Бряк стопится уже при вызове из загруженного оверлея, код вызова RuntimeAllocateAttributeTable до боли похож на аналогичный из 64-битного модуля. Поскольку мы уже в курсе, как все было устроено там, нам не составит большого труда придумать аналогию для каждого нужного нам поля:
Судя по всему, эта структура в 32-битном исполнении занимает 0x28 байт и состоит из десяти полей. Несложно переделать текст журнала в условной точке останова под новую информацию. Что я и предлагаю читателю сделать самостоятельно.
Источник
Наши проекты:
- Кибер новости: the Matrix
- Хакинг: /me Hacker
- Кодинг: Minor Code
👁 Пробить человека? Легко через нашего бота: Мистер Пробиватор