Хакер - Мертвая эра. Изучаем приложение, созданное в BioEra
hacker_frei
МВК
Диковинных сред разработки софта существует множество. Сред визуального программирования — чуть меньше, а популярные среди них и вовсе можно пересчитать по пальцам. Сегодня я покажу, как можно обойти парольную защиту в программах, созданных с помощью довольно редкого инструмента под названием BioEra.
Этой статьей я продолжаю тему визуального программирования, свое отношение к которому я уже подробно и исчерпывающе выразил в статье с говорящим названием «Полное G. Ломаем приложение на языке G, созданное в LabVIEW». А что, если программу из этой статьи написать на Java, потом частично скомпилировать, а частично — зашифровать код? Получится софтина, собранная с использованием проекта BioEra!
Из информации на сайте (имеющем весьма спартанский дизайн, как и сама среда программирования) можно узнать, что инструмент позволяет создавать кросс‑платформенные приложения для обработки сигналов с датчиков и игровых контроллеров. Еще в BioEra можно разрабатывать софт для обработки звука, что характерно, абсолютно не имея навыков программирования — как раз то, что нужно современному начинающему кодеру!
WARNING
Статья имеет ознакомительный характер и предназначена для специалистов по безопасности, проводящих тестирование в рамках контракта. Автор и редакция не несут ответственности за любой вред, причиненный с применением изложенной информации. Распространение вредоносных программ, нарушение работы систем и нарушение тайны переписки преследуются по закону.
Дабы не нарушать законы, скачаем с сайта триальную версию этой среды разработки и попробуем решить простую задачу: обойти парольную защиту на редактирование скомпилированных в BioEra файлов визуальных проектов .BPD (разработчики гордо называют их «дизайнами»). Как и в любой другой среде разработки visual programming language (типа LabView), проект тут в прямом смысле рисуется в визуальном редакторе в виде блок‑схемы.

Разумеется, при такой открытости исходников в BioEra существуют способы оградить «дизайн» от шаловливых ручек хакеров, которым вздумается дизассемблировать, а то и поправить проект. Защита тут используется попроще, чем в LabView, но все равно можно поставить на «дизайн» пароль на открытие и редактирование визуальной блок‑схемы. Именно такую защиту мы и попробуем обойти, ведь это путь к постижению логики построения приложений данной среды разработки.
Сразу забегая вперед, скажу, что существует и более простой способ — сервисный режим разработчика, в котором парольная защита просто игнорируется, но мы легких путей не ищем и занимаемся решением этой задачи исключительно из спортивного интереса в познавательных целях.
Итак, смотрим файл bioera.exe из скачанного и установленного триала. DetectItEasy не видит на нем никакой защиты и предполагает, что приложение написано на си. Запускаем его и пытаемся им открыть запароленный дизайн. Выскакивает окошко ввода пароля.

Таких строк нет в EXE-файле, более того, их нет вообще ни в одном файле установленного пакета, когда мы пытаемся их отыскать глобальным поиском. Топорный дизайн окон напоминает Java, в пакете действительно обнаруживается великое множество Jar-библиотек, но поиск по их содержимому тоже ничего не дает. Аттачимся к запущенному процессу при помощи нашего любимого отладчика x32dbg и видим, что это не то чтобы совсем явная Java, — виртуальная машина JVM интегрирована прямо в EXE-файл. Нечто подобное я описывал в своей статье «Суровая жаба. Изучаем защиту Excelsior JET для программ на Java».

То, что ядро этого монстра написано на примитивной 32-битной Java, — вне всякого сомнения, нужно лишь выяснить, где именно находится этот код, ведь простым поиском его в файлах проекта не обнаружить. Значит, он или хитро упакован, или зашифрован.
Попробуем подойти к решению задачи с другой стороны: отследим файлы, к которым приложение обращается при загрузке. Для этого запускаем утилиту Process Monitor (ProcMon), устанавливаем фильтр на процесс bioera.exe и отслеживаем все его обращения к файловой системе. Очень непростое решение, поскольку мы по опыту уже знаем, насколько длинные простыни обращений к самым разным файлам нам придется отслеживать в результате.
В нашем случае самым главным кандидатом на вместилище кода будет довольно увесистый файл be.cbe из подкаталога \ext, который грузится в память целиком последовательными порциями по 65 535 (0xFFFF) байт. При беглом просмотре этот файл (за исключением 5-байтового заголовка CBE01) представляет собой умеренно энтропическую кашу из символов — он явно упакован или зашифрован каким‑то алгоритмом собственного изобретения.
Ну что ж, попробуем его изучить. Для этого снова загружаем отладчик x32dbg и запускаем оттуда файл bioera.exe, предварительно установив условную точку останова на ReadFile с условием остановки [esp+0xC]==0x0FFFF. В первый раз нас ждет осечка — программа в отладчике завершается, не достигнув точки останова. Однако на экране окно программы все‑таки загрузилось, уже вне отладчика.
Пробуем приаттачиться к ее процессу и видим, что программа просто перезагрузила сама себя со следующими параметрами командной строки:
"C:\Program Files (x86)\BioEraTrial\bioera.exe" launcher -root C:\Program%20Files%20(x86)\BioEraTrial\ -j15
Меняем в x32dbg командную строку на эту и снова запускаем приложение. На этот раз точка останова срабатывает. Искомый вызов из — это стандартный Java- загрузчик заданного количества байтов из файла:
<_Java_java_io_FileInputStream_readBytes@20>
Попробуем отследить дальнейшую судьбу прочитанных с его помощью байтов. Эта задача будет чуть посложнее. Для начала ставим точку останова на доступ к какому‑нибудь байту из свежесчитанного буфера. Прочитанные байты будут несколько раз перемещаться из массива в массив, и каждый раз придется убирать аппаратную точку останова в прежней локации и переставлять ее на новое место. В конце концов наши усилия увенчиваются успехом: нужный байт выбирается из массива из скомпилированного JVM-кода:
movsx ebx,byte ptr ds:[edx+eax+C]
mov eax,ebx ; eax <- считанный из буфера байт
movzx ebx,byte ptr ds:[esi+1] ; esi — указатель на следующий JVM-опкод, который загружается в ebx
inc esi ; Следующий опкод в esi
jmp dword ptr ds:[ebx*4+6DA6C148] ; Переход на обработчик следующего опкода
Как видим, в нашей версии приложения реализована довольно примитивная 32-битная Java-машина. JVM-код даже не скомпилирован, а просто интерпретируется в процессе выполнения, чем объясняется изрядная неповоротливость программы. В принципе, если у тебя есть в запасе уйма свободного времени, ты можешь дизассемблировать алгоритм расшифровки, попрыгав в отладчике по коду, но мы поступим проще. Ведь это не какие‑нибудь Themida или VMProtect, а вполне заурядная и широко известная JVM, ее система команд задокументирована, и у нас в регистре esi есть адрес на исполняемый в данный момент шитый код.

К примеру, код текущей исполняемой инструкции (обработчик которой приведен выше, на скриншоте jy выделен красным) — 33h, это baload. Можно даже угадать имя исполняемого метода (decode) и его класс (be.read.Cipher). Осталось только найти этот класс и по‑человечески декомпилировать.
К сожалению, глобальным поиском нужный нам класс тоже не находится. Похоже, мы вышли на ядро какого‑то более глубокого уровня, копать который по описанному выше методу нам уже надоело и неинтересно. Поэтому на этот раз мы схалтурим — просто найдем этот класс в исходном виде в памяти процесса по шаблону (скажем, тот же be/read/Cipher) и сдампим его в файл, начиная с сигнатуры CAFEBABE.

Декомпилировав этот класс, мы получаем используемые в BioEra алгоритмы шифрования и дешифрования. Они совершенно примитивны, хотя чуть сложнее по исполнению обычного XOR:
package be.read;
public class Cipher {
public static final int LEN = 311;
static final int BIGLEN = 79616;
protected byte[] buffer = new byte[311];
private byte[] eb = new byte[311];
static final int k1 = 19;
static final int k2 = 236;
protected void decrypt() {
int i = 311;
while (--i >= 0) {
this.eb[i] = (byte)((this.buffer[i] & 0x13) + (this.buffer[(i + 7) % 311] & 0xEC));
}
i = 311;
while (--i >= 0) {
this.buffer[i] = (byte)(this.eb[i] - i * 13 % 17);
}
}
protected void encrypt() {
int i = 311;
while (--i >= 0) {
this.eb[i] = (byte)(this.buffer[i] + i * 13 % 17);
}
i = 311;
while (--i >= 0) {
this.buffer[i] = (byte)((this.eb[i] & 0x13) + (this.eb[(i - 7 + 79616) % 311] & 0xEC));
}
}
}
Теперь, когда у нас есть эти алгоритмы, компилируем простенький декодер и расшифровываем им файл be.cbe. В раскодированном виде он представляет собой последовательность откомпилированных и обфусцированных классов, которые можно выделять и отрезать по сигнатурам CAFEBABE для декомпиляции. Поиск по строке "Protected design" выводит нас на класс mF, который, помимо проверки пароля для защищенного дизайна, содержит множество других вкусняшек типа проверки донгла, лицензии, сигнатур (в частности, упомянутый выше сервисный режим). Но наша задача — обойти проверку пароля. Искомое место легко находится в декомпилированном коде в методе public static final int a(Pi pi, uI uI2, String string) и выглядит так:
PF pF = new PF(m.p.J(), "Protected design");
pF.c = true;
if (nE.c()) {
System.out.println("DEV - Skipping nes des pwd dlg");
} else {
pF.b("Password");
}
if (nE.c() || pF.b && pF.q().equals(uI2.l.toString())) // Если убрать эту проверку, то любой введенный пароль будет приниматься как родной
{
m.p.R = false;
rA.f = true;
return 5;
}
Как видно из кода, по‑хорошему можно было бы пропатчить класс nE.c(), тогда окно пароля вообще не будет появляться, но нам уже все надоело и искать, а потом декомпилировать этот класс просто лень. Поэтому берем нашего любимого «Грязного Джо» (я писал о нем в статье «Грязный Джо. Взламываем Java-приложения с помощью dirtyJOE») и ищем последовательность опкодов, соответствующих выражению nE.c() внутри условия if (...). Выглядит это вот так.

Чтобы условный переход всегда отрабатывал, выделенную красным последовательность нужно заменить true (04). В итоге нам надо в расшифрованном файле be.cbe найти последовательность байтов B8 01 B7 9A 00 1D, первые три из которых исправить на 00 00 04, а потом зашифровать файл обратно. Проделываем это и убеждаемся, что теперь защищенные дизайны открываются при вводе любого пароля безо всякого сервисного режима.
ВЫВОДЫ
Возможно, читатель упрекнет меня в том, что мы потратили столько времени и сил впустую. Ведь, судя по последним новостям на этом сайте, эта среда разработки не завоевала популярности и, скорее всего, не успела расползтись по миру. Поэтому вероятность встретиться с созданными при помощи BioEra программами у читателя невысока. Однако мы препарировали этого мертворожденного монстра просто из любви к экзотике и в ознакомительных целях — для приобретения опыта реверса нестандартных Java-приложений.
Читайте ещё больше платных статей бесплатно: https://t.me/hacker_frei