Взлом

Ghidra vs crackme. Обкатываем конкурента IDA Pro на примере решения хитрой крэкми с VM


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

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

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

Крэкми в анализаторе 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;
}

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

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

Файл ram.bin в HxD Hex Editor

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

Источник: xakep.ru

Оставить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *