Содержание статьи
Разгадывать загадки намного интереснее, чем читать готовые решения. А потому, пока еще не поздно, оторвись от статьи и попробуй расковырять JohoR crackme. В подсказку не заглядывать! Исходный текст не смотреть! Впрочем, сам по себе исходный текст (даже с учетом всех комментариев) совершенно не объясняет, как же его отлаживать.
Здесь отсутствуют шифровка, самомодификация и прочие приемы, ослепляющие статический анализ. Дизассемблер выдает аккуратный листинг, каждая машинная команда которого абсолютно понятна. Однако результат действия программы в целом очень трудно предсказуем и требует довольно глубоких знаний устройства процессора и операционной системы. Поистине танталовы муки! Какой‑то несчастный десяток машинных инструкций (ядро crackme) отделяет нас от победы! Что ж, тем большее наслаждение испытываешь от взлома! Ну а на случай, если самому взломать никак не получается, я даю развернутое объяснение.
Что мы будем ломать
Исходный текст JohoR crackme приведен в листинге 1. Это чудо моей инженерной мысли после компиляции занимает всего 832 байта, большая часть которых приходится на PE-заголовок. Конечно, его можно было бы ужать, программируя в hex-кодах, но это ж сколько труда надо потратить! А так — файлы легко компилируются штатными утилитами Microsoft.
Кстати, о компиляции. По многочисленным просьбам трудящихся я отказался от командных файлов и перешел на макак (в смысле, на .mak), обрабатываемых утилитой NMAKE из комплекта поставки MS Visual Studio. NMAKE /
собирает релиз, а NMAKE /
— отладочную версию. Только все равно отладить ее с помощью MS Visual Studio не удастся — нет смысла даже пытаться.
Также поддерживается сборка и из IDE — достаточно открыть макаку и сделать build. Тупая «Студия» всегда ищет скомпилированный файл в каталогах \
и \
, тогда как мыщъх создает его в текущей директории, поэтому запуск файла непосредственно из IDE невозможен (хотя, может быть, в последних версиях MS уже пофиксила этот косяк).
Исходный текст JohoR crackme
#include <windows.h>int count; char str[]="0123456789ABCDEF!";__declspec(naked) nezumi(){ __asm{ ; //int 03 ; // For soft-ice xor eax, eax ; // eax := 0 mov ebx, fs:[eax] ; // Old SEH pushfd ; // save EFLAGS ;//-[new seh]-; push offset l1 ; // Handler proc push -1 ; // The last handler in the chain mov fs:[eax], esp ; // Assign the new handler ;//-[hacker time]-; xor eax,[eax] ; // <-- ACCESS VIOLATION ;//-[set TF bit]-; push -1 ; // TF := 1 xor eax,[eax] ; // <-- ACCESS VIOLATION popfd ; // EFLAGS := 00244ED7h ;//-[TRACE-ZONE]-; mov eax, [eax] ; // <-- ACCESS VIOLATION nop ; // <-- INT 01 ud2 ; // <-- ILLEGAL INSTRUCTION nop ; // <-- INT 01 nop ; // <-- INT 01 int 03 ; // <-- INT 01 jmp end_of_line ; // :-- to exit --> ;//-[seh handler]- -; l1: mov eax, [esp + 04h] ; // *EXCEPTION_RECORD l2: mov edx, [esp + 0Ch] ; // EDX -> ContextRecord mov eax, [eax] ; // EXCEPTION CODE cmp eax, 0C000001Dh ; // ILLEGAL INSTRUCTION jz x2 ; // X--> cmp eax, 080000003h ; // INT 03 jz x1 ; // -- skip 1 byte --> cmp eax, 0C0000005h ; // ACCESS VIOLATION jnz set_tf_bit ; // -- don’t skip --> x2:inc dword ptr [edx+0B8h] ; // Skip one byte x1:inc dword ptr [edx+0B8h] ; // Skip one byte set_tf_bit: ; // <--X cmp dword ptr [edx + 0B8h], offset end_of_line jae end_of_handler ; // dont set TF-bit _outside_ trace-zone or dword ptr [edx+0C0h],100h ; // <---- set TF-bit _inside_ trace-zone end_of_handler:xor eax,eax ; // EXCEPTION_CONTINUE_SEARCH inc [count] ; // EXCEPTION COUNT ret ; // end of the handler ;//-[exit]-; end_of_line:mov fs:[eax],ebx ; // Restore the old SEH sub esp, 8 ; // restore the stack popfd ; // restore the flags } // Print EXCEPTION COUNT count = str[(count>0x10)?0x10:count]; MessageBox(0,&count,"JohoR",MB_OK); ExitProcess(0);}
Алгоритм
Первые три команды сохраняют указатель на текущую (системную) SEH-запись в регистре EBX и заталкивают в стек флаги процессора, попутно обнуляя EAX. Следующие три команды устанавливают новый SEH-обработчик, находящийся по смещению l1, замыкая SEH-цепочку терминирующим указателем -1 (FFFFFFFFh
). Он сигнализирует системе о том, что данный обработчик — последний. Вот такой маленький трюк (почему‑то большинство хакеров добавляют свой обработчик к цепочке существующих — хотя передавать им управление все равно не собираются, зачем же тогда усложнять код?).
Сразу же после установки SEH-обработчика выполняется команда XOR
, «выбрасывающая» исключение доступа типа ACCESS VIOLATION. Операционная система ловит его и передает управление на метку l1, с кодом C0000005h
, расположенным в двойном слове по адресу [
. Обработчик видит, что это ACCESS VIOLATION, и, зная, что его вырабатывает инструкция XOR
, лезет в регистровый контекст. При этом он увеличивает значение EIP на два байта — sizeof(
, поскольку ACCESS VIOLATION представляет собой fault. Если пояснять, то в момент генерации исключения регистр EIP указывает на начало возбудившей его машинной команды. При выходе из обработчика процессор будет выполнять XOR
снова и снова, пока мы либо не изменим EAX так, чтобы он указывал на валидную область памяти, либо не увеличим значение EIP, переходя к выполнению следующей машинной команды. Что мы и делаем, попутно увеличивая счетчик вызова исключений (count) на единицу.
Продолжение доступно только участникам
Вариант 1. Присоединись к сообществу «Xakep.ru», чтобы читать все материалы на сайте
Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее
Вариант 2. Открой один материал
Заинтересовала статья, но нет возможности стать членом клуба «Xakep.ru»? Тогда этот вариант для тебя! Обрати внимание: этот способ подходит только для статей, опубликованных более двух месяцев назад.
Я уже участник «Xakep.ru»