Чтобы испытать новое средство для реверса, созданное в стенах АНБ США, я решил поломать замечательную и несложную крэкми MalwareTech. Выбрал ее неслучайно. В одной из своих статей я рассказывал о том, как устроена виртуализация кода, и мы даже написали простенькую виртуалку. А теперь давай посмотрим, как ломать такую защиту.

Скачать крэкми можно с сайта MalwareTech, пароль к архиву — тоже MalwareTech.

Итак, для начала посмотрим, что в архиве. Видим исполняемый файл vm1.exe и файл дампа ram.bin. В пояснении на сайте написано, что мы имеем дело с восьмибитной виртуальной машиной. Файл дампа — не что иное, как кусок памяти, в котором вперемешку расположены рандомные данные и флаг, который мы должны найти. Оставим пока в покое файл дампа и посмотрим на vm1.exe через программу DiE.

Крэкми в анализаторе Detect It Easy
Крэкми в анализаторе Detect It Easy

DiE не показывает ничего интересного, с энтропией все в порядке. Значит, никакой навесной защиты нет, но проверить все равно стоило. Давай загрузим этот файл в Ghidra и посмотрим, что она выдаст. Я приведу полный листинг приложения без функций (он совсем небольшой) — чтобы ты понял, с чем мы имеем дело.

PUSH   EBP
MOV    EBP ,ESP
SUB    ESP ,0x94
LEA    ECX =>local_94 ,[0xffffff70  + EBP ]
CALL   MD5::MD5
PUSH   0x1fb
PUSH   0x0
CALL   dword ptr [->KERNEL32.DLL::GetProcessHeap ]
PUSH   EAX
CALL   dword ptr [->KERNEL32.DLL::HeapAlloc ]
MOV    [DAT_0040423c ],EAX
PUSH   0x1fb
PUSH   DAT_00404040
MOV    EAX ,[DAT_0040423c ]
PUSH   EAX
CALL   memcpy
ADD    ESP ,0xc
CALL   FUN_004022e0
MOV    ECX ,dword ptr [DAT_0040423c ]
PUSH   ECX
LEA    ECX =>local_94 ,[0xffffff70  + EBP ]
CALL   MD5::digestString
MOV    dword ptr [local_98  + EBP ],EAX
PUSH   0x30
PUSH   s_We've_been_compromised!_0040302c
MOV    EDX ,dword ptr [local_98  + EBP ]
PUSH   EDX
PUSH   0x0
CALL   dword ptr [->USER32.DLL::MessageBoxA ]
PUSH   0x0
CALL   dword ptr [->KERNEL32.DLL::ExitProcess ]
XOR    EAX ,EAX
MOV    ESP ,EBP
POP    EBP
RET

Как видишь, код простой и легко читается. Давай воспользуемся декомпилятором Ghidra и посмотрим, что он выдаст.

undefined4 entry(void)
{
HANDLE hHeap;
char *lpText;
DWORD dwFlags;
SIZE_T dwBytes;
MD5 local_94 [144];

MD5(local_94);

dwBytes = 0x1fb;
dwFlags = 0;

hHeap = GetProcessHeap();
DAT_0040423c = (char *)HeapAlloc(hHeap,dwFlags,dwBytes);
memcpy(DAT_0040423c,&DAT_00404040,0x1fb);

FUN_004022e0();

lpText = digestString(local_94,DAT_0040423c);
MessageBoxA((HWND)0x0,lpText,"We\'ve been compromised!",0x30);

ExitProcess(0);
return 0;
}

Я добавил отступы для удобочитаемости — отделил объявления переменных от остального кода. Код весьма простой: сначала выделяется память в куче (GetProcessHeapHeapAlloc), далее в нее копируется 0x1fb(507) байт из DAT_00404040. Но у нас нет ничего интересного в 00404040! Вспоминаем, что в инструкции к крэкми говорилось, что ram.bin — это кусок памяти. Разумеется, если посмотреть размер файла, он оказывается равным 507 байт.

Загружаем ram.bin в HxD или любой другой шестнадцатеричный редактор и смотрим.

Файл ram.bin в HxD Hex Editor
Файл ram.bin в HxD Hex Editor

Увы, ничего внятного там не обнаруживаем. Но логика работы немного проясняется: DAT_0040423c — это ram.bin (наши выделенные 507 байт в куче). Давай переименуем DAT_0040423c в RAM, чтобы было удобнее ориентироваться в коде. Далее заходим в функцию FUN_004022e0.

Продолжение доступно только подписчикам

Материалы из последних выпусков можно покупать отдельно только через два месяца после публикации. Чтобы продолжить чтение, необходимо купить подписку.

Подпишись на «Хакер» по выгодной цене!

Подписка позволит тебе в течение указанного срока читать ВСЕ платные материалы сайта. Мы принимаем оплату банковскими картами, электронными деньгами и переводами со счетов мобильных операторов. Подробнее о подписке

4 комментария

  1. Аватар

    0ri0n

    22.03.2019 at 10:21

    Хорошо но мало!

    Вопрос к Экспертам. У гидры есть скрипты встроенные скрипты, каковых их задачи что они решают?

    • Аватар

      s00mbre

      03.04.2019 at 00:38

      Похоже, что скриптами (Java) можно делать все, что и вручную, это макросы для Гидры. Для написания скрипта необходимо унаследовать свой класс от GhidraScript, пример (пишет строку «Hello world» в консоли Гидры):
      public class HelloWorldScript extends GhidraScript {
      public void run() throws Exception {
      println(«Hello World!»);
      }
      }
      Подробнее тут: http://ghidra.re/ghidra_docs/api/ghidra/app/script/GhidraScript.html
      А вот полный онлайн курс по скриптингу в Гидре: http://ghidra.re/courses/GhidraClass/Intermediate/Scripting_withNotes.html#Scripting.html

    • Аватар

      s00mbre

      03.04.2019 at 00:45

      Еще лучше просто открыть Script Manager в Гидре и посмотреть коллекцию скриптов. По двойному клику скрипт выполняется (как в MS Office), а в контекстном меню можно выбрать |Edit with basic editor, и код откроется во встроенном редакторе тут же.

  2. Аватар

    s00mbre

    05.04.2019 at 05:46

    Мое первое видео — пример crackme в Гидре:
    https://www.youtube.com/watch?v=Lu3O6ikXMm4

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

Check Also

Хроники битвы при Denuvo. Как «непробиваемая» игровая защита EA Origin оказалась пробиваемой

Защита от пиратства Denuvo пришла на смену SecuROM и связана с одним действующим лицом – Р…