Се­год­ня мы будем ломать мой crackme, напич­канный анти­отла­доч­ными при­ема­ми. Они осно­ваны на осо­бен­ностях обра­бот­ки исклю­чений отладчи­ками и на ошиб­ках в debug engine, о которых я рас­ска­жу по ходу дела. А заод­но про­демонс­три­рую интимные под­робнос­ти основных хакер­ских инс­тру­мен­тов — «Оль­ги», «Иды», Syser’а, x86emu и про­чих.

Раз­гадывать загад­ки нам­ного инте­рес­нее, чем читать готовые решения. А потому, пока еще не поз­дно, отор­вись от статьи и поп­робуй рас­ковырять JohoR crackme. В под­сказ­ку не заг­лядывать! Исходный текст не смот­реть! Впро­чем, сам по себе исходный текст (даже с уче­том всех ком­мента­риев) совер­шенно не объ­ясня­ет, как же его отла­живать.

www

Ска­чать crackme-jhr; ко­пия так­же есть в моем репози­тории на OpenRCE.

Здесь отсутс­тву­ют шиф­ровка, самомо­дифи­кация и про­чие при­емы, ослепля­ющие ста­тичес­кий ана­лиз. Дизас­сем­блер выда­ет акку­рат­ный лис­тинг, каж­дая машин­ная коман­да которо­го абсо­лют­но понят­на. Одна­ко резуль­тат дей­ствия прог­раммы в целом очень труд­но пред­ска­зуем и тре­бует доволь­но глу­боких зна­ний устрой­ства про­цес­сора и опе­раци­онной сис­темы. Поис­тине тан­таловы муки! Какой‑то нес­час­тный десяток машин­ных инс­трук­ций (ядро crackme) отде­ляет нас от победы! Что ж, тем боль­шее нас­лажде­ние испы­тыва­ешь от взло­ма! Ну а на слу­чай, если самому взло­мать никак не получа­ется, я даю раз­верну­тое объ­ясне­ние.

 

Что мы будем ломать

Ис­ходный текст JohoR crackme при­веден в лис­тинге 1. Это чудо моей инже­нер­ной мыс­ли пос­ле ком­пиляции занима­ет все­го 832 бай­та, боль­шая часть которых при­ходит­ся на PE-заголо­вок. Конеч­но, его мож­но было бы ужать, прог­рамми­руя в hex-кодах, но это ж сколь­ко тру­да надо пот­ратить! А так — фай­лы лег­ко ком­пилиру­ются штат­ными ути­лита­ми Microsoft.

Syser напрочь отказывается грузить JohoR crackme в release build’е
Syser нап­рочь отка­зыва­ется гру­зить JohoR crackme в release build’е

Кста­ти, о ком­пиляции. По мно­гочис­ленным прось­бам тру­дящих­ся я отка­зал­ся от коман­дных фай­лов и перешел на макак (в смыс­ле, на .mak), обра­баты­ваемых ути­литой NMAKE из ком­плек­та пос­тавки MS Visual Studio. NMAKE /f crackme_jhr.mak собира­ет релиз, а NMAKE /f "crackme_jhr.mak" CFG="crackme_jhr - Win32 Debug" — отла­доч­ную вер­сию. Толь­ко все рав­но отла­дить ее с помощью MS Visual Studio не удас­тся — нет смыс­ла даже пытать­ся.

Так­же под­держи­вает­ся сбор­ка и из IDE — дос­таточ­но открыть макаку и сде­лать build. Тупая «Сту­дия» всег­да ищет ском­пилиро­ван­ный файл в катало­гах \Debug и \Release, тог­да как мыщъх соз­дает его в текущей дирек­тории, поэто­му запуск фай­ла непос­редс­твен­но из 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);
}
Попытка отладки билда JohoR crackme под Syser’ом. Отладчик в панике, система в ауте, хакер на измене
По­пыт­ка отладки бил­да JohoR crackme под Syser’ом. Отладчик в панике, сис­тема в ауте, хакер на изме­не
 

Алгоритм

Пер­вые три коман­ды сох­раня­ют ука­затель на текущую (сис­темную) SEH-запись в регис­тре EBX и затал­кива­ют в стек фла­ги про­цес­сора, попут­но обну­ляя EAX. Сле­дующие три коман­ды уста­нав­лива­ют новый SEH-обра­бот­чик, находя­щий­ся по сме­щению l1, замыкая SEH-цепоч­ку тер­миниру­ющим ука­зате­лем -1 (FFFFFFFFh). Он сиг­нализи­рует сис­теме о том, что дан­ный обра­бот­чик — пос­ледний. Вот такой малень­кий трюк (почему‑то боль­шинс­тво хакеров добав­ляют свой обра­бот­чик к цепоч­ке сущес­тву­ющих — хотя переда­вать им управле­ние все рав­но не собира­ются, зачем же тог­да усложнять код?).

Результат работы JohoR crackme при запуске без отладчика
Ре­зуль­тат работы JohoR crackme при запус­ке без отладчи­ка

Сра­зу же пос­ле уста­нов­ки SEH-обра­бот­чика выпол­няет­ся коман­да XOR EAX, [EAX], «выб­расыва­ющая» исклю­чение дос­тупа типа ACCESS VIOLATION. Опе­раци­онная сис­тема ловит его и переда­ет управле­ние на мет­ку l1, с кодом C0000005h, рас­положен­ным в двой­ном сло­ве по адре­су [ESP + 04h]. Обра­бот­чик видит, что это ACCESS VIOLATION, и, зная, что его выраба­тыва­ет инс­трук­ция XOR EAX, [EAX], лезет в регис­тро­вый кон­текст. При этом он уве­личи­вает зна­чение EIP на два бай­та — sizeof(XOR EAX, [EAX]), пос­коль­ку ACCESS VIOLATION пред­став­ляет собой fault. Если пояс­нять, то в момент генера­ции исклю­чения регистр EIP ука­зыва­ет на начало воз­будив­шей его машин­ной коман­ды. При выходе из обра­бот­чика про­цес­сор будет выпол­нять XOR EAX, [EAX] сно­ва и сно­ва, пока мы либо не изме­ним EAX так, что­бы он ука­зывал на валид­ную область памяти, либо не уве­личим зна­чение EIP, перехо­дя к выпол­нению сле­дующей машин­ной коман­ды. Что мы и дела­ем, попут­но уве­личи­вая счет­чик вызова исклю­чений (count) на еди­ницу.

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

Вариант 1. Присоединись к сообществу «Xakep.ru», чтобы читать все материалы на сайте

Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее

Вариант 2. Открой один материал

Заинтересовала статья, но нет возможности стать членом клуба «Xakep.ru»? Тогда этот вариант для тебя! Обрати внимание: этот способ подходит только для статей, опубликованных более двух месяцев назад.


  • Подпишись на наc в Telegram!

    Только важные новости и лучшие статьи

    Подписаться

  • Подписаться
    Уведомить о
    0 комментариев
    Межтекстовые Отзывы
    Посмотреть все комментарии