Чтобы испытать новое средство для реверса, созданное в стенах АНБ США, я решил поломать замечательную и несложную крэкми MalwareTech. Выбрал ее неслучайно. В одной из своих статей я рассказывал о том, как устроена виртуализация кода, и мы даже написали простенькую виртуалку. А теперь давай посмотрим, как ломать такую защиту.
Скачать крэкми можно с сайта MalwareTech, пароль к архиву — тоже MalwareTech
.
Итак, для начала посмотрим, что в архиве. Видим исполняемый файл vm1.exe
, файл дампа ram.bin
и readme.txt
, в котором написано, что мы имеем дело с восьмибитной виртуальной машиной. Файл дампа — не что иное, как кусок памяти, в котором вперемешку расположены рандомные данные и флаг, который мы должны найти. Оставим пока в покое файл дампа и посмотрим на vm1.exe
через программу DiE.
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 или любой другой шестнадцатеричный редактор и смотрим.
Увы, ничего внятного там не обнаруживаем. Но логика работы немного проясняется: DAT_0040423c
— это ram.bin (наши выделенные 507 байт в куче). Давай переименуем DAT_0040423c
в RAM, чтобы было удобнее ориентироваться в коде. Далее заходим в функцию FUN_004022e0
.
Материалы из последних выпусков можно покупать отдельно только через два месяца после публикации. Чтобы продолжить чтение, необходимо купить подписку.
Подписка позволит тебе в течение указанного срока читать ВСЕ платные материалы сайта. Мы принимаем оплату банковскими картами, электронными деньгами и переводами со счетов мобильных операторов. Подробнее о подписке
1 год7390 р. Экономия 1400 рублей! |
1 месяц720 р. 25-30 статей в месяц |
Уже подписан?
Читайте также
Последние новости