|
Motorcode, 2009
Uraniumcode@gmail.com
Защита приложений от взлома.
Как бывает неприятно когда хорошая программа заканчивает свою жизнь, после 30 дней работы. Ну мы(тут подразумеваются большенство людей) в свою очередь сразу же лезим в инет, чтобы скачать кряк (я бы не советовал так делать)и довольные дальше продолжаем работу. А каково человеку, который делал эту программу? Об этом никто не думает(Это отдельная тема, достоиная отдельной заметки). Ну что ж пришло время осложнить жизнь хакерам(крякерам) чтобы хотя бы как — то продлить время до которого кряк ещё не выбросят на «свободу». Сразу хочется оговориться, что некотрые разработчики специально делают защиту, которая очень легко ломается. Мне это не совсем понятно, ведь проще же перейти во Free, чем открывать счёт, вести базу пользователей и.т.д. Во многом «защита» сводится к такому виду:
if(strcmp(Строка_введённая_пользователем,настоящий_код)) //Сравнение двух строк
printf("You not true user!You... Hacker!");
else
printf("Hello,user!\n");
Тут ничего не стоит отловить нужный переход, хотя бы просто найдя строчки, которые заключины в printf(). Проверим нашу догадку. Откроем Hacker`s disassembler и найдём трочку «Hello, user!». И сразу же находим строчку:
004135A4 68 B85A4100 PUSH 98544.00415AB8 ; ASCII "Hello,user!"
004135A9 FF15 B8824100 CALL DWORD PTR DS:[<&MSVCR90D.printf>]; MSVCR90D.printf
004135AF 83C4 04 ADD ESP,4
Если мы поднимимся выше, то увидим и первую строчку, а если ещё выше то увидим такую магическую комбинацию:
00413585 85C0 TEST EAX,EAX
00413587 74 19 JE SHORT 98544.004135A2
00413589 8BF4 MOV ESI,ESP
Тут проверяется если EAX равно нулю(после выполнения функции strcmp()), то прыгаем к строке «You not true user! You.. Hacker!!», а если нет то ко второй строке. Естественно нам ничего не мешает изменить JE(Jump Equal) на JNE(Jump Not Equal). После чего наш код будет работать в прямопротивоположном направлении. Все «зарегистрированные» пользователи получают фигу, а все «хакеры» - добро.
Это как говорится как не надо делать. А теперь собственно о том как надо делать. Мы отловили нужный нам участок кода по словам. Следовательно нам надо так, чтобы этих фраз не было видно. Существует несколько способов это сделать. Например, написать фразы не в строку, а посмивольно:
if(strcmp(buff,pass))
cout << 'Y' << 'o' << 'u' << ' ' << 'n'
<<'o' << 't' << ' ' << 't' << 'r' << 'u' << 'e' << ' '
<< 'u' << 's' << 'e' << 'r' << '!' << 'Y' << 'o' << 'u'
<< '.' << '.' << '.' << ' ' << 'H' << 'a' << 'c' << 'k'
<< 'e' << 'r' << '!';
else
cout << 'H' << 'e' << 'l' << 'l' << 'o'
<<',' << 'u' << 's' << 'e' << 'r' << '!';
И Hacker`s Disassembler уже не может найти эти строки. Да и не строки это вообще. Поэтому такой ход может отпугнуть начинающих хакеров. Но чтобы пуганых крякеров было ещё больше, можно никуда строчки не прятать, а их зашифровать(это кстати более по хакерски).
Один из самых простых алгоритмов шифровки, это передвижение символов(сдвиг). Если к примеру b – это 61h. Прибавляем единицу и b уже превращается в с. Ну мы так делать не будем, ибо утку всё — равно будет видно. Поэтому сделаем по другому:
#define one_part "\x02\x14\x0e\x51\x15\x14\x0f" //Символы
void crypto()
{
char buff[MAX_PATH] = one_part; //Тут они хранятся
char debuff[MAX_PATH] = " "; //Разделитель
for(int i = 0;i < strlen(buff);i++) //Расшифровываем
{
debuff[1] = buff[i]^-0x85;
cout << debuff[1]; //Вывод
}
}
Я не стал полностью переписывать строку, ограничевшись только «you not». Аналогично можно записать вторую строку. Для простоты второую строку переделаем в просто «Yes».
Полный код звучит так:
#define one_part "\x02\x14\x0e\x51\x15\x14\x0f"
#define two_part "\x02\x3e\10"
void crypto(char baff[MAX_PATH])
{
char buff[MAX_PATH] = one_part;
char debuff[MAX_PATH] = " ";
char buff2[MAX_PATH] = two_part;
char debuff2[MAX_PATH] = " ";
if(strcmp(baff,pass)) //pass -123
{
for(int i = 0;i < strlen(buff);i++)
{
debuff[1] = buff[i]^-0x85;
cout << debuff[1];
}
}else
{
for(int i = 0;i < strlen(buff2);i++)
{
debuff2[1] = buff2[i]^-0x85;
cout << debuff2[1];
}
}
}
И этот способ тоже скрывает «критические» строки. Но это только первый этап, функция strcmp() - выдаёт нас и более менее опытный взломщик, безпроблем пройдёт этот рубеж. Итак, с этой функцией надо что — то делать. Существует вариант прямого вызова из библиотеки. Что позволит нам её скрыть. Только функции GetProcAddress() или GetModuleHandle() - откроют наш маленький секрет. Хотя вышеперечисленные функции в большом приложении вызываются раз по 100. В таком отладчике как Soft-Ice отсеить эти вызовы не вызовит затруднения. Но мы пойдём другой дорожкой — это вызов API – функции не сначала, а со второй позиции(если за систему счисления, принять отладчик). Мы добавим в нашу программу счётчик времени, чтобы совсем уж быть похожими на триальное приложение:)Для этого потесним функцию strcmp() и заменим ею функцией GetLocalTime(). Но пока немного отвлечёмся. «Временные» вызовы в Windows NT, основываются га двух функциях GetLocalTime() и GetSystemTime()(Которые без структуры _SYSTEMTIME – просто набор букв). Те в свою очередь обращаются к NTDLL`ной функции RtlTimeToTimeFields. Как мы видим, простора для фантазии двольно немного. Приходится исхитряться и искать новые пути. Ведь в Windows, доовольно сложно что — что скрыть. Это все — равно что прятать свинью за ширму, которая немного меньше её. Вы её хоть как разверните, она все — равно хоть чуть — чуть, но будет видна(имеется в виду свинья). Так и тут, вы можите придумать суперские сопособы, но «ущи» всё — равно будут видны. Теперь давайте напишем функцию, которая будет проверять какой на дворе год. Если больше 2007, то время истекло. Сразу скажу, что естественно это обходится простым переводом часов назад. Но как обхитрить часы, мы как — нибудь ещё поговорим, а сейчас у нас другая цель. Спрятать GetLocalTime, что отпугнёт хоть каких- нибудь хакеров.
void crypto()
{
_SYSTEMTIME sys;
GetLocalTime(&sys);
if (sys.wYear > 2007)
cout << "Oh, NO!";
else
cout << "Oh,Yes";
}
Если запустить программу, то она выдаст вполне ожидаемое «Oh, NO!”, потому что на дворе уже 2009 год. Ну что ж брякним GetLocalTime()(bpx GetLocalTime). Отладчик естественно тормозит в коде. Если мы заёдем непосредственно в функцию, во — первых мы окажемся прямо в kernel32.dll, а во — вторых увидим вот такой вот код:
7C80A874 > 8BFF MOV EDI,EDI
7C80A876 55 PUSH EBP
7C80A877 8BEC MOV EBP,ESP
7C80A879 83EC 18 SUB ESP,18
Стартуем мы там, где >. А что если стартонуть с 7С80A876? Давайте попробуем, для этого где идут вызов GetLocalTime, пишем следующее:
CALL 7C80A876.
После этого пробуем поставить бряк сначала в файл (bpx GetLocalTime()).Тишина. Хорошо, неплохо а вот справится он с bp GetLocalTime())? Да! И тут не заметил. Ну что ж, отлично. Теперь попробуем обойти эту защиту. А обходится онаm естественно остановкой бряка не в начало функции, а в середину. Только это не каждый додумается. На стрелянных, конечно это не пройдёт, а вот на новичков — вполне. Да и если посматривать на регистры, то тоже всё довольно быстро откроется.
Теперь поговорим о психологических моментах ведения боя. Об этом к сожалению многие разработчики забывают, а зря. Ведь с лепить хорошую защиту — это всего лишь пол дела, надо хорошо знать психологию хакера. Надо сделать много левых проверок в программе. Т.е, несколько вызовов функций OpenFile(), после которого должна быть проверка времени. И если хакер попадётся на эту удочку, то написать «Register complite». На самом деле регистрации никакой не было! Об этом многие забывают, но как приятно обломать крякера, когда он уже чувствует победу и потом такое западло. Опять же это не идеальный вариант защиты, но какое — то время на этом можно протянуть. Дальше следует поместить в код большое количество переходов(je,jne, jl,jz,jnz...). Это не является хорошим стилем, но в войне все средства хороши. Поэтому не стесняйтесь добавлять в свою программу кучу ничего не значащих проверок. Это очень может осложнить жизнь взломщику. Конечно метод научного тыка(который кстати говоря, используют все тру-хакеры)никто не отменял, но опять же время на отладку, может не соизмеримо вырасти. Не доверяйтесь пакерам, которых сейчас навалом. Ну то есть доверяться то можно, только не полностью. Мне много раз попадались программы, которые упакованы например ASProtect, а вот после распаковки — там полный ноль. Чуть ли не прямо пароль пишут:)Надо понимать, что человечество уже давно научилось обходить протекторы. Существуют конечно довольно тяжёлые защиты типа Armadillo, но это скорее проблемы автора этой статьи,у которого возникают проблемы с этим пакером.
Многие разработчики переносят активацию ни на клиентской машине, а у себя. Т.е активация через инет. Они это делают в надежде что так усилится защита. И в чём то они правы, если крякеру надо получить заветный номерок. Только взлом программ может происходить двумя способами. Это получение ключевого номера или обман времени. Первый вариант, провернуть сложнее, а вот второй вариант — вполне. Если вы отладите программу по второму способу, то впринципе ничего не измениться. У вс будет таже самая программа — только не зареганная. Но кто на это смотрит? Поддержкой всё — равно никто не пользуется, поэтому не суть важно. Конечно есть программы, которые только после регистрации открвают дополнительные возможности, но чтобы проверить является ли программа легальной или нет, достаточно посидеть внутри и можно найти тот «волшебный» переход. Поэтому смысл в активации через инет — довольно туманный.
Также многие забывают о том, что надо убирать комментарии. Ну согласитесь, довольно глупо когда защита доаольно устойчива, а попадается примерно такой комментарий
//It is trial time
Плохо получается. Поэтому надо проверить, чтобы ни один комментарий не выдал, то что не надо. Также не следует помещать в код прямой вызов функций типа MessageBox(). Они обычно используются как раз для того, чтобы проинформировать пользователья о том сколько осталось у него времени или правильный код. Поэтому или шифруем вызов или вообще не вызываем. Для этого надо предварительно написать в справке, чтобы не вызывать панику у порльзователей. А отсутствие MessageBox() - может сильно затруднить работу крякера. Ведь осложняется возможность отловить нужный переход.
Мы рассмотрели только некотрые способы защиты приложений. Конечно, их гораздо больше, но о них в другие разы.
P.S. При написании этой заметки были прослушаны следующие альбомы:
Rammstein – Rosenrot (2005).
The Beatles - Australian Tour 1964 (1964).
The Rolling Stones - Raritetes 1971-2003.
The Rolling Stones - Tattoo You (1981).
Спасибо им! Они создавали приятную атмосферу и способствовали работе.
Автор: Motorcode | Добавлено: 12.10.2009, 12:18 | Просмотров: 14228
Добавить комментарий
|
|