В предыдущих частях, мы говорили о методах борьбы с отладчиком. Но не отладчиком едины хакеры, поэтому сегодня будем рассматривать методы защиты от дизассемблера. Конечно, этому можно было бы посвятить отдельную серию, но мы пока ограничимся одной заметкой.
Какие приходят на ум мысли, когда мы хотим защититься от дизассемблера?Конечно, это затруднение анализа кода. Это и будет являться основной темой статьи. Правда от таких корифеев типа IDA-pro различные трюки не помогут(а может и помогут), главным в этом дела остаётся человек, которому мы и будем сегодня пусть мозги.
Теперь поговорим для чего всё это и где лучше размещать код. Для чего, вроде понятно. Мы будем скрывать ключевые участки кода программы. Будь это защитный механизм для регистрации или вы просто не хотите раскрывать работу кода в данном участке, да и другие причины тоже могут тут присутствовать. Я довольно много говорю, что «опытных взломщикам это не остановит»(ну или примерно так), это фразу я хочу произнести и тут, но вы можете выиграть время пока вашу программу не взломают, а это уже хорошо.
Вообще кода должно быть довольно много, чтобы прятать эти участки. Потому что если написать просто “Hello world”, и кода в 10 раз больше, то конечно, всё сразу выйдет наружу, надо использовать дурман для дизассемблера, как бы между делом, как так и должно быть. Вот тогда защита будет довольно грозной.
Ещё хочется сказать о тех, кто разбирается в программах, исключительно отладчиком. Данные трюки их вряд ли остановят, потому что ваших шаманств, они просто не заметят и не оценят(даже новички), но дополнительная защита, ещё никому не вредила, поэтому смысл её подключать, несомненно есть.
Но давайте уже перейдём к практике. Я естественно буду показывать всё на обычных, чисто символических примерах, которые по идеи, должны работать и в больших проектах.
Первым делом, заменим вот так обычный JMP
Листинг 1.1
int _tmain(int argc, _TCHAR* argv[])
{
_asm
{
mov eax,esp
ret
}
return 0;
}
Заносим в регистр EAX,стек(так конечно делать не рекомендуется) и потом делаем возврат.
Ещё способ, сделать тоже самое
Листинг 1.2
_asm
{
push[esp]
call [esp]
}
Производим в ручную вызов адреса стека.
А теперь напишем небольшую программку, которая сравнивает два числа, если прогнать её через дизассемблер, то код будет довольно простой, но после наших преобразований, уже не так просто будет понять что к чему.
Листинг 1.3
int _tmain(int argc, _TCHAR* argv[])
{
int number;
cin >> number;
if(number == 12)
MessageBoxA(NULL,"YES","YES",MB_OK);
else
MessageBoxA(NULL,"NO","NO",MB_OK);
return 0;
}
Приведу лишь ту часть дизассемблированного листинга, где выполняется непосредственно проверка, является введённое число двенадцати или нет.
Листинг 1.4
00401011 833C240c cmp dword ptr[esp],0000000C
00401015 6A00 push 00000000
00401017 7516 jne 0040102F
Теперь попробуем немного усложнить этот код для понимания, потому что тут всё предельно просто, число, которая находится по адресу в стеке, сравнивается с Ch(12)и если они не равны, то прыжок на MessageBox, одни, а если равны, то на другой. Вот другой вариант этого кода:
Листинг 1.5
int number;
cin >> number;
_asm
{
xor eax,eax
mov eax,[number]
push eax
cmp[number],0xC
jne pt
tr: push 0x00000000L
push n1
push n1
push 0
call ds:[MessageBoxA] ; косвенный вызов API-функции MessageBox
jmp ex;
pt:
push 0x00000000L
push n2
push n2
push 0
call ds:[MessageBoxA] ; косвенный вызов API-функции MessageBox
ex:
}
Сей код, является интерпретацией того что было написано в листинге 1.3, теперь посмотрим, как это выглядит в дизассемблере:
Листинг 1.6
0040103C 33C0 xor eax,eax
0040103E 8B45FC mov eax,[ebp-04]
00401041 50 push eax
00401042 837DFC0C cmp dword ptr[ebp-04],0000000C
00401046 7513 jne 0040105B
Согласитесь, немного, да, но и этого может быть достаточно, чтобы дезориентировать крякера, конечно очень не опытного. Желательно этот код, помещать куда нибудь в середину основного кода, чтобы он не вызывал никаких подозрений.
Как мы видим, можно обложить подобными командами любой код, главное желание, умение и терпение. Естественно, это только поверхность работы по сокрытию кода в дизассемблере, но для начала достаточно. Удачи!