УРОКИ ПО КРЕКИНГУ

КОМПЬЮТЕРНЫЕ КУРСЫ "ПОИСК"

[Главная страница] [Контакты]

Реверсинг и защита программ от взлома - Урок 3 [Александр Панов]


Улучшенная защита программ с зашифрованием сообщений

Файлы к статье: CrakMe-3.

Как мы видели, защитить программу бывает довольно непросто, однако даже простые mетоды усложняют крекеру жизнь. К сожалению (или к счастью, это кому как), программисты не хотят тратить времени даже на простую, элементарную защиту своих программ. А ведь это не так сложно, как кажемся на первый взгляд. Я покажу на примере, как выростут затраты труда и времени, если сделагь простейшую защиту.

Давайте посмотрим, что же изменится, если применить правила, о которых я говорил, а именно:

  • никогда не храните ваши сообщения в открытом виде:
  • никогда не выводите сообщения сразу после проверки пароля на правильность.

Будем исследовать программу CRAKME-3.EXE. Запускаем ее и смотрим на окно программы.

pan3-1

Мы опять видим практически то же самое окно с полем для ввода пароля. Попробуем ввести любые символы и посмотреть на результат. Вводим "12345", нажимаем кнопку ОК. Сначала ничего не происходит; немного погодя получаем сообщение о неверном пароле.

pan3-2

Что же мы имеем на этот раз? Па первый взгляд, ничего нового. Однако если хорошо подумать, то получается, что программа запрашивает у нас пароль, что-то с ним делает (или ждет какое-то время) и выдает нам результат (мы уже занимаемся анализом!). Давайте запустим PEiD и посмотрим, что он нам скажет.

з3

Так. Значит, программа не запакована и не зашифрована. Это уже хорошо. Запускаем OlyDbg и загружаем в него нашу программу.

p3-4

Теперь пробуем найти все текстовые строки программы. Вдруг нам повезло, и программист не стал шифровать свои данные, как это было в программе CRAKME-1.EXE.

а

Мы видим, что не все строки зашифрованы, но вот самих сообщений, которые выводятся в случае правильности (или неправильности) пароля нет. Значит, программист все-таки зашифровал свои сообщения.

в

Откроем CrackMe-3.exe в IDA. Создадим MAP файл. Далее открываем крэкми в OllyDbg и при помощи плагина GODUP подкючаем MAP файл. Как это делать - смотри в уроке 2.

Что же нам делать? Попробуем поставить BPX на функцию MessageBoxA. Запускаем программу в отладчике, вводим в окне пароль "12345" и нажимаем кнопку ОК. Теперь мы в отладчике. Что же мы видим? Вывод сообщения о неверном пароле. Если посмотреть чуть выше, то мы увидим, что там находится сообщение о верном пароле.

pan3-7

Причем все сообщения уже расшифрованы. Это значит, что где-то в программе сообщения расшифровываются. А раз так, то расшифровывается и пароль (хотя формально это вовсе не обязательно, поскольку сравниваться могут не пароли, а хеш-функции). Что же делать? Можно, конечно, попытаться проследить, откуда эта функция вызывается, но нет гарантии, что мы найдем нужное место достаточно быстро (хотя этот метод довольно часто срабатывает). В данном случае этот способ нам не подходит. Давайте подумаем. Есть программа, в которую вводится пароль, он сравнивается с паролем, который есть в самой программе. Стоп! Раз он "сравнивается", значит можно попробовать "отловить" функцию сравнения. Какие же функции нам нужны? А вот для этого мы и пытались определить язык, на котором написана программа. Поскольку она написана на Borland C++, берем справочник по этому компилятору. Там есть несколько функций сравнения:

extern PACKAGE int __fastcall CompareStr(const AnsiString S1, const AnsiString S2);
extern PACKAGE int __fastcall CompareText(const AnsiString S1, const AnsiString S2);
int strcmp(const char *s1, const char *s2);

Эти функции предназначены для сравнения строк. И не забудьте, что еще есть простой оператор сравнения:

(const1*) == (const2*)

Его применяют, когда надо сравнить, например, так, как показано в листинге ниже.

AnsiString pas1 = "Pas1234";
AnsiString pas2 = "456Pas3";
if(pas1 == pas2)
    ShowMessage("Password is TRUE");
else
    ShowMessage("Password is FALSE");

Эту комбинацию довольно часто применяют в программах на языке С++, поэтому о ней ни в коем случае не стоит забывать.

Теперь давайте поставим брекпойнт на функцию CompareStr. Поставили, запускаем программу, вводим в нее любые значения, нажимаем кнопку ОК и... Ничего не происходит. Значит, как я уже говорил, эта функция не используется. Попробуем поставить брекпойнты на функции CompareText и strcmp. Поставили, запускаем программу. И опять ничего. Значит и эти функции не используются для сравнения.

Посмотрим какие функции используются (вызываются) в программе - для этого в окне OllyDbg надо нажать комбинацию клавиш Ctrl + N.

В столбце Name отображается имя функции. Конечно их тут много, но ведь нам не нужны все. Самые интересные — системные функции. Если просто набрать "system", то быстрый поиск перенесет нас к ним.

Мы видим очень интересные системные функции, в том числе:

System::AnsiString::operator==(System::AnsiString &)

Давайте поставим на нее брекпойнт. Для этого выделим ее строку и нажмем клавишу F2.

pan3-8

Запускаем программу, вводим любые символы (я ввел "12345") и попадаем вот сюда.

pan3-9

Начинаем трассировать программу при помощи F8. Выполняем функцию LStrCmp.

pan3-10

При этом вызове функции ничего не происходит. Нажимаем клавишу F8 еще раз и попадаем сюда же.

А вот тут при вызове функции в регистрах ЕАХ, EDX есть интересные значения!

pan3-11

Мы нашли пароль! Вот так использование программистом правил помогает защитить программу. Конечно, защита не будет полной, если использовать только эти два правила, но начинающего крекера уже сможет остановить. А для еще большего осложнения жизни крекеров рекомендуется использовать в программе две строки — одну зашифрованную, а другую нет. С зашифрованной работают, а незашифрованную оставляют для ловушки (или просто ничего с ней не делают). Крекеру придется поломать голову, каким образом вы добираетесь до этой строки (про ловушки мы поговорим позднее).