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

Чтобы испытать новое средство для реверса, созданное в стенах АНБ США, я решил поломать замечательную и несложную крэкми 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;
}

Я добавил отступы для удобочитаемости — отделил объявления переменных от остального кода. Код весьма простой: сначала выделяется память в куче GetProcessHeap -> HeapAlloc, далее в нее копируется 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.

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

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

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

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

Читать новость в источнике Xakep

0