Оригинальный DVD-ROM: eXeL@B DVD !
eXeL@B ВИДЕОКУРС !

ВИДЕОКУРС ВЗЛОМ
выпущен 12 ноября!


УЗНАТЬ БОЛЬШЕ >>
Домой | Статьи | RAR-cтатьи | FAQ | Форум | Скачать | Видеокурс
Новичку | Ссылки | Программирование | Интервью | Архив | Связь

Крутая защита или CRACKL@B CrackMe #1

Обсудить статью на форуме

Очень удобно, когда все крэкерские инструменты, книги и статьи в одном месте. Используйте сборник от EXELAB - вот тут.

Статью написал: Bad_guy
Статья создана: 28.07.03

Однажды я придумал одну интересную защиту и решил реализовать её в виде CrackMe, дабы проверить её на прочность, что ж - это было сделано и этот крэкми вы можете скачать и попробовать сломать прямо сейчас, не читая до конца эту статью, а иначе будет неинтересно. СКАЧАТЬ (140 Кб)

В этой защите было применено

1. Защита от String Reference взлома.
2. Использование самомодифицирующегося кода.
3. Немножко самодельной криптографии (хэш).
4. Использование регистрационного кода в качестве адреса процедуры.

Давайте по порядку разберёмся с каждым из этих пунктов, что они нам дают и зачем.

Защита от String Reference взлома

О таком способе взлома своих программ программисты обычно никогда не задумываются. А суть взлома здесь в следующем: в скомпилированной программе содержатся строки типа "Registered", "UNREGISTERED", в общем все, которые программист "вбил" в исходники. Начинающих крэкеров учат ломать проги таким способом: дизассемблируем программу с помощью WinDASM, нажимаем кнопочку String Reference и ищем вот такие подозрительные строки, потом кликаем по подорительной строчке и смотрим откуда она вызывается, смотрим выше, находим jne,jnz,jz или je и меняем на противоположную команду, после чего программа становится зарегистрированной.

Как здесь от этого я избавился: сначала написал всю программу, затем скопировал все строковые константы в отдельный текстовый файл, вот такие там были строки:

 lKeoOIwjk34uGFqi
 *
 Name:
 Serial#:
 Register
 About
 ! Unregistered !
 REGISTERED
 Ошибочка, видимо ключ поддельный.
 До взлома ещё очень далеко.
 До взлома ещё далеко.
 Поднапрягись !
 А ключик то поддельный !
 Ты ещё ничего не сделал !
 
А потом берём и пишем простую программку:
 program Project1;
 {$APPTYPE CONSOLE}
 uses SysUtils;
 
 var f,f1: textfile;
 s,s1: string;
 i: integer;
 
 begin
 assignfile(f,'name.txt');
 reset(f);
 assignfile(f1,'name2.txt');
 rewrite(f1);
 while not eof(f) do
 begin
 readln(f,s); s1 := '';
 for i:= 1 to length(s) do
 s1 := s1+'cr('+Inttostr(integer(s[i]))+')+';
 writeln(f1,s1);
 end;
 closefile(f);
 closefile(f1);
 end.
 
затем берём получивишийся файл name2.txt и из него вставляем вместо строковых констант в исходники новые строки:
cr(78)+cr(97)+cr(109)+cr(101)+cr(58); - Так выглядит слово "Name:" и так далее.
И ещё вставляем в код программы процедуру cr:
 function cr(bb: byte):string;
 begin
 cr := chr(bb);
 end;
 
Вот так легко избавится от String Reference крэкеров-новичков.

Использование самомодифицирующегося кода (СМК)

C СМК всё сложнее, тут нам надо будет вмешиваться в скомпилированный файл:
у меня была процедура:

 procedure Reg;
 var il2: longint;
 begin
 {расшифровщик кода}
 asm
 push eax
 push edx
 push ecx
 mov edx, 10 // длина полезного кода (в байтах / 4) (1)
 mov eax,ilong
 mov il2,eax
 add il2,40 //указатель на начало полезного кода (2)
 @im:
 mov ecx, [il2]
 mov eax, [ecx]
 xor eax, $96969696
 mov [ecx], eax
 add il2, 4
 dec edx
 jnz @im
 pop ecx
 pop edx
 pop eax
 end;
 {полезный код}
 form1.Status.Color := clGreen;
 form1.Status.Caption := cr(82)+cr(69)+cr(71)+cr(73)+cr(83)+cr(84)+cr(69)+cr(82)+cr(69)+cr(68);
 end;
 
Константы (1) и (2) пришлось подправить вручную в скомпилированном файле. Также кусок полезного кода был сложен по модулю 2 (xor) с константой 96h, затем я поменял атрибуты секции .code исполняемого файла с помощью программы LordPE на E0000020, чтобы код мог самомодифицироваться, то есть был бы доступен на запись. (...мало кто это поймёт с десятого раза...)

Немножко самодельной криптографии (хэш)

Вспомним криптографию и сделаем небольшую простенькую хэш функцию:

 Function Md5(ms: string):int64;
 var mt,ms2: string; imt: int64; imt1: integer;
 w: array [0..7] of byte absolute imt;
 begin
 mt := cr(108)+cr(75)+cr(101)+cr(111)+cr(79)+cr(73)+cr(119)+cr(106)+cr(107)+cr(51)+cr(52)+cr(117)+cr(71)+cr(70)+cr(113)+cr(105);
 ms2 := '';
 ms2 := ms + cr(42);
 imt := $1AFD2FDE3ABC4975;
 for imt1 := 1 to length(mt) do
 begin
 w[imt1 mod 8] := (w[imt1 mod 8]*integer(ms2[(imt1 mod length(ms2))+1])) mod 256;
 end;
 md5 := imt;
 end;
 
Не подумайте, что это правда алгоритм MD5 - это простенькая самоделка созданная для возможности реализации электронной подписи и контрольной суммы, а она будет полезна для проверок формата регистрационного кода.

Использование регистрационного кода в качестве адреса процедуры

О таком способе я писал уже в своей статье "Ещё одна защита ваших shareware программ и как её снять", но теперь могу сказать, что в той статье много смешных для опытного крэкера вещей, хотя сам принцип никуда не делся.

Вкратце: Для использование регистрационного кода в качестве адреса процедуры надо чтобы регистрационный код так или иначе нёс в себе константу - адрес процедуры, к тому же придётся залезть в отладчик, а ещё пропатчить скомпилированный исполняемый файл, дабы убрать вызов процедуры вида

 Call 0040213D
 
и заменить на вызов вида
 mov eax, Regaddr
 Call eax
 
где Regaddr это тоже самое число 0040213D, но передаваемое в регистрационном коде. Помнится, что пару лет назад все в своих статья писали, что "на вашем компьютере адрес может быть и другой", но мой опыт в крэкерстве и знания формата PE позволяют мне сделать вывод, что адрес этот на всех компьютерах будет абсолютно одинаков, а даже если это и не так, то есть хитрые функции, которые позволяют узнать содержимое EIP (текущий логический адрес в исполняющемся коде), и тем самым подкорректировать значение RegAddr.

Теперь подробно. В данном крэкми было сделано всё так:

 procedure TForm1.Button1Click(Sender: TObject);
 var snm : string; inm: integer;
 begin
 if length(Edit2.Text) = 20 then
 begin
 snm := InttoHex(md5(Edit1.Text),16);
 for inm := 1 to length(Edit2.Text) do
 begin
 if not(Edit2.Text[inm] in ['0'..'9','A'..'F']) then
 begin Showmessage('До взлома ещё очень далеко.'); exit; end;
 end;
 if copy(snm,1,8) <> copy(Edit2.Text,1,8) then
 begin Showmessage('До взлома ещё далеко.'); exit; end;
 if Copy(InttoHex(md5(Copy(Edit2.Text,1,16)),16),4,4) <> copy(Edit2.Text,17,4) then
 begin Showmessage('Поднапрягись !'); exit; end;
 ilong := StrToInt('$'+Copy(Edit2.Text,1,8));
 ilong := ilong xor StrToInt('$'+Copy(Edit2.Text,9,8));
 //Проверим правильность адреса.
 if Copy(InttoHex(md5(IntToHEX(ilong,8)),16),5,8) <> IntToHEx($E8484694,8) then
 begin Showmessage('А ключик то поддельный !'); ilong := 0; exit; end;
 ilong := ilong xor $5CD37EA6;
 end
 else
 Showmessage('Ты ещё ничего не сделал !');
 end;
 
Переменная ilong после всех проверок будет содержать адрес процедуры, если был введён правильный код, если нет, то ноль.

Теперь подробно расскажу алгоритм этой процедуры.

 Edit1.Text - туда вводится имя пользователя (ИП)
 Edit2.Text - сюда регистрационный код (РК).
 
Сначала сравниваем длину РК - она должна быть 20 символов. Вычисляем хэш ИП. Затем проверяем, чтобы РК содержал только HEX символьные числа ('0'..'9','A'..'F'). Первые восемь символов РК сравниваем с 8 символами хэша ИП. Вычисляем контрольную сумму первых 16 символов РК и сравниваем ее с 4 последними символами РК. Если все предыдущие проверки прошли успешно, то ксорим первые восемь символов РК, с последующими 8 символами, то есть не символы, а числа, полученные на основе перевода из строкового в числовой формат и помещаем их в переменную, которая и будет являться хранителем адреса процедуры (ilong).

Мы дошли до места отмеченного в коде, как

 //Проверим правильность адреса.
 
Всё, что было до этого в данной процедуре, является ерундой и тренировкой для крэкера-новичка, а теперь уже серьёзные вещи пойдут.

Copy(InttoHex(md5(IntToHEX(ilong,8)),16),5,8) - этот код считает хэш получившегося в ilong адреса и возращает его в виде 8-символьной строки. А этот код IntToHEx($E8484694,8) возвращает также 8-символьную строку, но с хэшем правильного кода. Прошу обратить внимание на то, что это ничего не даёт крэкеру, потому как хэш - необратимая функция. Однако здесь есть небольшая слабость защиты. Однако её никто не заметил. Но я всё же расскажу о ней:

Если взять переменную $E8484694 и процедуру md5, то можно написать небольшой брутфорсер, то есть меняя ilong подвергать её хэшированию и сравнивать с константой. Вы скажете, что это долго и так далее... нет, вы ошибаетесь. Дело в том, что адресное простраство исполняемого кода - не велико, ну к примеру от 401000 до 44A26C в моём случае, а это - всего лишь 300'000 комбинаций, что брутфорсится очень быстро. Так что я поступил весьма легкомысленно в этом месте кода.

Вернёмся к коду и увидим, что при положительном результате проверок он заканчивается следующей строкой, значение которой я поясню ниже.

 ilong := ilong xor $5CD37EA6;
 
И что же дальше... А дальше надо было бы вызвать процедуру регистрации подобным образом:
 mov eax, ilong
 Call eax
 
но я решил ещё раз поиздеваться над своими коллегами и поставил для этого аж целый таймер, который работал со скважностью 512 миллисекунд.
 procedure TForm1.Timer2Timer(Sender: TObject);
 begin
 Test(ilong);
 end;
 
Теперь посмотрим процедуру Test:
 procedure Test(kk: longint);
 begin
 if kk = 0 then exit;
 try
 asm
 mov eax,kk // Неявный вызов процедуры Reg;
 call eax   //
 end;
 except ilong := 0; ShowMessage('Ошибочка, видимо ключ поддельный.');
 end;
 end;
 
Если адрес нулевой - то выходим из процедуры, а если ненулевой, то пытаемся сделать вызов процедуры, находящейся по этому адресу. Если же крэкер решил обмануть программу и подсунуть другой адрес, то он обломается, потому как программа попадёт на случайный код или вообще не в адресное пространство программы (это опасно, но ведь скока проверок было... так что крэкер рискует сам своими компом) и, естественно, полезет окно с ошибкой, которое мы поймаем с помощью блока try...except и выдадим в except свой обработчик ошибки вместо стандартного окошка.

Честно говоря поначалу нужно писать не так:

 asm
 mov eax,kk // Неявный вызов процедуры Reg;
 call eax   //
 end;
 
а вот так:
 Reg;
 asm
 mov eax,kk // Неявный вызов процедуры Reg;
 call eax   //
 end;
 
Reg откомпилировалось у меня как Call 00449F34 и я заменил это на NOP команды с помощью отладчика и HEX редактора, а число 00449F34 запомнил.

Строка

 ilong := ilong xor $5CD37EA6;
 
в коде процедуры Button1Click позволяет за счёт ксоринья с константой подгонять код до нужного нам 00449F34 без перекомпиляции, которая может нарушить адрес функции. Это делается опять же путём правки этой константы в HEX-редакторе.

Что-то ещё...

Также был поставлен ещё один таймер, который должен был мешать крэкеру прерываться по hmemcpy. Но он работает у меня с интервалом 666 миллисекунд, а это, как я потом понял, слишком большой интервал и можно успеть прерваться по реальному вызову. Но это скорее что-то типа дополнительного прибамбаса, который вообще-то просто обойти в любом случае, особенно учитывая, что сейчас модным стало использование дизассемблеров WinDASM, IDA и прочих, которые дают крэкеру адрес полезного кода.

 procedure TForm1.Timer1Timer(Sender: TObject);
 var stm: string; itm : integer;
 begin
 stm := Edit1.Text; // вызов hmemcpy
 for itm := 1 to length(stm) do stm[itm] := cr(42)[1]; // затираем строку звездочками
 end;
 
Есть ещё одна хитрость, которая была замечена начинающими крэкерами. Дело в том, что после всех необходимых правок в скомпилированном файле, я его решил еще и запаковать компрессором UPX. Но у меня есть ещё и GUI оболочка для него UPXShell называется. И эта программка позволяет сделать так, чтобы запакованный с помощью UPX файл нельзя было распаковать командой
 upx -d crackme.exe
 
Однако мне стало интересно, как же это достигается. А достигается это просто: после запаковки UPX файл содержит код 555058210С который выглядит в блокноте, как "UPX!.", а программка UPXShell заменяет последний байт в этом коде на FF, то есть получается 55505821FF и в блокноте "UPX!я". После этого программу не распаковать UPX'ом, но если вручную поменять этот байт обратно на 0C, то всё восстановится и программа распакуется.

Как это взломали

Пока эту защиту реально смогли взломать 2 человека и ещё третий не до конца аккуратно разобрался, хотя и дошел до функции регистрации. Не буду говорить, что это им далось легко - потребовалась фантазия и нестандартный подход к взлому, именно поэтому не каждый, кто называет себя крэкером и может запускать игрушки "без диска", сможет взломать данную защиту.

Возможно, вам будет интересно почитать обсуждение взлома данного крэкми, которое проводилось на форуме CRACKL@B, поэтому не поленюсь привести его здесь:

ТЕМА: Взломай CRACKL@B CrackMe #1
Bad_guy
 Написан первый крэкми "CRACKL@B CrackMe #1" -
 http://cracklab.narod.ru/dload/clab1.rar
 Предлагаю всем попробовать сломать этот крэкми, а у кого получится срочно
 сообщите мне !
 Думаю, вам будет интересно посидеть над взломом этой защиты.
 Особенно мне интересно, что смогут сделать с
 этой защитой (если конечно станут ломать) такие
 люди, как freeExec, Hex, Moonshiner, Fess, Perch (ну
 и все остальные, кто там... звиняйте, кого забыл).
 
MozgC
 Да ниче не смогут сделать =)
 
MoonShiner
 Yes!!!! Меня поставили в один ряд с такими монстрами:)
 ЗЫ Кстати, нужна ли статья по распакове нового аспра который в ISOCommander 14?
 Там много новых интересных штучек:)
 
freeExec
 Можно просто фичи перечислить
 
MozgC
 Не надо фичи просто перечислять. Нужна статья конечно, что глупости спрашиваешь
 =)
 
 И убери эту идиотскую подпись =)
 
MoonShiner
 Фичи там веселые...
 1) SuperBpm и патч ntdll.dll не проходят, аспр их как то палит или хз, что еще,
 лень было разбираться. Короче, когда они активизированы, прога просто не пойдет.
 2) Новый (может только для меня) метод спирания байтов. К примеру спертая
 команда "push ebp" там эмулится как "mov [esp],ebp sub esp,1B add esp,17", и все
 это разбавлено кучей полиморфного бреда и самого рабочего кода аспра.
 3) Немного изменен механизм эмуляции некоторых АПИ-функций.
 Ну и еще всякая разная несущетсвенная шняга...
 
 ЗЫ Че то Bad_guy там намутил, у меня уж крыша едет:(
 
MozgC
 Блин, Мунш, молодец, а метод спирания байтов дейтствительно новый, нигде такого
 еще не видел.
 Ты скажи как ты антиотладочные приемы то обошел ?
 
MoonShiner
 Я по ним по F8 и F10 просто не гулял:)
 
 
MozgC
 А можно поподробне чуть-чуть а то я изведусь пока статьи дождусь =)
 
dragon
 Я писал статью про этот аспр, у Bad_guy’я валяется. Обещал на сайт выложить, да
 чего-то не выложил...
 
MozgC
 Ты когда успел ? =) Я думал этот АСПР только пару неделек назад в инете
 появился...
 
 А Bad_guy тебя наебал =))
 
dragon
 Он уже давно появился, месяц назад, а может и ещё раньше. А насчёт Bad_guy не
 понял, ему же выгоднее чтобы статей на сайте больше было.
 
MozgC
 да я пошутил, попробуй ему написать еще раз
 
MoonShiner
 Нифига не поддельный ключик!!! Bad_guy, сам ты поддельный!
 
MozgC
 Лех, ты про че ?
 
Bad_guy
 Какой-то заговор вокруг меня затевается, я еле догадался о чем это MoonShiner
 говорил, что я поддельный. А ведь он единственный кто тут по теме топика
 высказался, а кто про что (и про Аспр любимый и про остальное...).
 2 MoonShiner: Если мой крэкми говорит, чта ключ поддельный, значит он
 поддельный, понимаишш. А статью почему бы нет - размещу, только она должна быть
 на _русском_ языке (подчеркиваю).
 2 MozgC: Не надо так шутить... и скоро выложу твою статью.
 2 Dragon: Взлом alcohol 120% уже готова для публикации - завтра-послезавтра
 будет большое обновление - 10-12 статей разных авторов, что мне пришло за
 последний месяц.
 2 freeExec & all: ну так как у вас дела с моим крэкмисом ???? Ежели никто не
 справится придется до Hex’a стучаться.
 
freeExec
 До конца месяца не колись. Счас просто со временем напряг :(
 
MozgC
 "А статью почему бы нет - размещу, только она должна быть на _русском_ языке
 (подчеркиваю)."
 
 Вот в этот то вся и проблема... Муншайнер то у нас только на древне-индийском
 пишет =)))))))))))))))
 
MoonShiner
 Тааак... Не ходил ночью сюда и уже всякие камни в мой огород. На нормальном я
 языке пишу, это только некоторым людям описалово давай на уровне букваря:) А
 freeExec прав - подожди хоть пару недель, щас косяки со временем...
 
dragon
 Я тоже поддельный ключик нашёл - D0C8345C901234565708, на своё имя. Осталось
 только настоящий найти...
 
Bad_guy
 Для dragon: Поддельный - это недоделанный настоящий. Только вот в этом то и
 главная хитрость...
 2 All: Кстати, гружу сейчас 12 новых статей на CRACKL@B/DOC
 
dragon
 Да, конечно, попробуй этот адрес подбери... Единственное, что я знаю про эту
 процедуру, то, что она должна подменить адрес в стеке с 44A242 на какой-то
 другой, а вот какой, хрен знает. Так что это даже двойная защита.
 
Bad_guy
 Да уж, это не Аспротект какой-нибудь сраненький, а Бэдгайпротект. Только я вот
 непонял почему эта процедура должна адрес в стеке поменять - она только делает
 вот что: расшифровывает свой код и изменяет статус зарегистрированности
 программы (пишет в статусе, что она зарегистрирована и меняет цвет с красного на
 зелёный). А вот где она находится - в этом и есть вся суть защиты (я лично найти
 это место не смогу, потеряв бумажку, где у меня это записано). А первые 8
 символов в регистрационном коде кто угодно найдёт - это не проблема.
 
MozgC
 "Да уж, это не Аспротект какой-нибудь сраненький, а Бэдгайпротект."
 
 Это будет Бэдгай протект когда можно будет запустить файлик,и он запротектит
 программку, причем каждый раз с разными адресами/и другими данными =)
 
Bad_guy
 Для MozgC: да знаю я всё, только тогда я уже буду вам не коллегой, а
 противником...
 
MozgC
 BGProtect 2.3x [SuperMegaNew Strain]
 =)))
 
MoonShiner
 Народ, а мож нам Bad_guy’a замочить, пока не поздно, чтобы в будущем нам жизнь
 не портил?
 
MozgC
 да не, он вроде написал что не собирается сторону менять =)
 
Bad_guy
 Для MozgC: BGProtect 2.3x [SuperMegaNew Strain] - а что, мне нравится
 Для MoonShiner: Вы сначала с Солодовниковым разберитесь. Да, кстати, сижу тут
 разбираюсь, как архиваторы делать... намёк понят ???
 
 Пора составить Аспротекту конкуренцию, а то очень хотса стипендию побольше
 получать
 
freeExec
 Врятли у тебя получится архив запаролить не одним паролем. Намёк понял?
 
Bad_guy
 Конечно, велосипед мне уже не изобрести. И узнав один ключ можно наделать своих
 для любого имени. Это уже давно известно и в ASProtect и в продуктах Elcomsoft.
 
ТЕМА: CrackME от Bad_guy’я ВЗЛОМАН!!!
dragon
 Проверяйте, имя dragon, код D0C8345C9917A3000E4B.
 
 В общем я нашёл эту процедуру, которая регистрирует прогу. Я уже всё перебрал,
 но наконец, мне взбрело в голову поискать в листинге IDA редкие инструкции. Вот
 ищу, по алфавиту, и мне в глаза бросилась aaa по адресу 449F7C. Начало этой
 процедуры - 449F34. В ней же я увидел xor eax, 96969696h, т.е. стало понятно,
 что эта процедура что-то расшифровывает. Я сунул в 44D880 этот адрес, и всё,
 типа зарегил. По алгоритму проверки подобрал код. Короче, код подбирается так -
 первые 8 символов подсматриваются, затем ксорим 5CD3407D с адресом 449F34,
 получаем 5C97DF49, затем этот результат ксорим с перевёрнутыми первыми 8
 символами(у меня 5C34C8D0), и ставим этот результат в середину, причём тоже
 наоборот. Последние 4 символа тоже подсматриваются. Вот и весь CrackMe
 
MoonShiner
 Блин, опередили меня:(((
 MoonShiner
 44A6686670392C664D86
 Тока я че то не понял, почему он хоть цвет надписи и меняет, но все равно пишет,
 что ключик поддельный:(
 2dragon А ты молодчина:)) Я то как кретин сидел в ИДЕ и почти весь код
 просматривал насчет закриптованности и подозрительных инструкций рядом. И
 наконец нашел... Скажи, почему ты стал искать подозрительные инструкции? С чем
 это связано?
 
 
dragon
 Ну в описании же написано, что код полиморфный, обычно в листинге видны
 идиотсткие команды, типа aaa, aam, aas, cli, in, out, lock XXX, и.т.д. Вот я
 стал их искать, и с первой попытки нашёл aaa. Вот так. А код цвет меняет, но
 пишет, что ключ поддельный, потому что не от того адреса наверное расчитывал.
 Рассчитый по моей методике, и он будет точно правильный.
 
Bad_guy
 Браво, dragon !!!
 Действительно, у меня на бумажке написан код 449F34 - это адрес процедуры.
 Но, не думайте, что всё так просто, я ведь могу и не xor eax, 96969696 делать, а
 xor eax, КЛЮЧ или того пуще криптографический алгоритм взять: DES, Blowfish. Так
 что это был лишь шанс для взлома. Хотя это всё и не умаляет достижения dragon’a.
 
Bad_guy
 >Проверяйте, имя dragon, код D0C8345C9917A3000E4B.
 На всякий случай проверил - всё сходится с моим кейгеном !
 
Bad_guy
 А у Moоnshiner’a код неправильный !
 Регистрационному имени MoonShiner не соответствует.
 
 2 dragon: интересно, сколько раз ты комп себе вешал моим крэкмисом. Я так, пока
 отлаживал - раз 8-10 перегружался.
 
MozgC
 А Муншайнер че не молодец ? =))
 
Hex
 Похоже только я пошел научным путем :) А не поиском хз чего :)
 Я шел по коду Button1Click и увидел вот это
 UPX1:0044AAE5 xor esi, eax
 UPX1:0044AAE7 mov ds:dword_0_44D880, esi
 и это
 UPX1:0044AD5A xor ds:dword_0_44D880, 5CD3407Dh
 сразу навело на мысль о том что 44D880 - это переменная содержащая адрес
 процедуры расшифровки. Банальный просмотр XREF на этот адрес привел к:
 UPX1:00449F59 mov eax, ds:dword_0_44D880
 UPX1:00449F5F mov [ebp+var_4], eax
 UPX1:00449F62 add [ebp+var_4], 48h
 UPX1:00449F66 mov ecx, [ebp+var_4]
 UPX1:00449F69 mov eax, [ecx]
 UPX1:00449F6B xor eax, 96969696h
 и т.д.
 
 Ну дальше вы знаете.
 Код искать в лом, ибо и так все ясно.
 P.S. Если бы не эта мелочь, то я тоже бы сидел и искал "редковстречающиеся
 инструкции" :)
 
MoonShiner
 Как так? У меня меняет надпись на зеленую и говорит, что порегена. Правда
 табличку все равно выдает, что ключ поддельный:) Но мне влом дальше ковыряться,
 хоть там и не долго...
 
 
 
 
 Убравший идиотскую подпись
 
MozgC
 Да это наверно косяк bad_guy’я, что табличка цвет меняет и прога гаворит что
 зарегена =)
 
Bad_guy
 Чтож, Hex и есть Hex. А MoonShiner, писал, что рад, что его записали в один ряд
 с ... - немножко больше аккуратности и терпения и ты оправдаешь этот статус.
 2 MozgC: нет, не косяк, просто видимо Moonshiner немножко промахнулся с входом в
 процедуру (попозже входит).
 
 В заключение могу сказать, что вообще я догадывался об обоих осуществлённых
 способах взлома и маленькие лазейки были оставленны мной намеренно. Что касается
 метода Hex’а -просто я поторопился. Хотел сделать массивчик, который бы содержал
 N копий той переменной и чтоб он читался по таймеру и писался тоже, в общем
 путать исследователя.
 
 А вот, как только я применю ...xor eax, КЛЮЧ... - все обломаются. Буду знать на
 будущее.
 
 Кстати, уже начал работу не над BGProtect, а пока над BGPack 1.0. Так что,
 возможно через год ситуация поменяется.
 Когдя я хорошо разберусь в PE, архивировании, Debug API и подобном.
 
 Всем спасибо за внимание !
 
 
MozgC
 "А MoonShiner, писал, что рад, что его записали в один ряд с ... - немножко
 больше аккуратности и терпения и ты оправдаешь этот статус."
 
 Вот это ты зря, я не думаю, что MoonShiner в этом списке рыжий. Во всяком случае
 не думаю, что он хуже чем тот же dragon, fess, perch в этом деле. Думаю даже
 наоборот, так как часто с ним общаюсь и представляю его общий уровень. А 1
 крякмис не дает судить об уровне.
 
MozgC
 2Bad_guy
 Будешь мне 5% прибыли отбашлять за придуманное название =)
 
freeExec
 Bad_guy пишет:
 А вот, как только я применю ...xor eax, КЛЮЧ... - все обломаются. Буду знать на
 будущее.
 UPX1:00449F6B xor eax, 96969696h
 тут что не ключ, а всякие крипторы не позволяют расшифровывать разными ключами,
 вот их самый минус
 
MoonShiner
 И вы туда же:) все мне за лень и раздолбайство втыки делают:)
 
dragon
 Короче так, MoonShiner, вот твой код - 44A668660D79FF3AAB0F
 
 Кто-то там писал, что 10 раз перезагружался. Странно, я не разу, наверное у тебя
 там Windows не NT-шный стоит. Ставь XP и не будешь перезагружаться.
 
 xor eax, КЛЮЧ - какая разница? Если адрес правильный, то и ключ будет
 правильный, если его дополнительно в код не вделать. Но тогда он будет всё время
 одинаковый, хотя подобрать его будет нелегко.
 
 И ещё, может хватит наконец разбираться, кто хуже ломает, а кто лучше? Все
 хорошо ломают!
 
Bad_guy
 2 MozgC: Хорошо хоть не 50% К тому же я не собираюсь релиз сей проги на
 CRACKL@B’e устраивать - кому нужен пакер от крэкера Bad_guy’я ?. Им подавай
 Stefan Fleischmann, А.С.,... Так что и имя будет другое и название.
 
 На тему xor eax, ключ: это тоже условно говоря - я же говорил про DES, RC5. А
 прятать буду не адрес процедуры в регистрационный ключ, а пароль зашифрованного
 участка - вот и всё. Ну, действительно, пароль этот будет единственный, но ведь
 для того, чтобы его найти понадобится либо умный брутфорс, либо купить
 программу. А если в каждой версии программы этот пароль будет меняться и если
 прогу выпускать по законам shareware (не менее 1 новой версии в месяц) - о чем
 тогда говорить ?
 
 Про Moonshiner’a: люблю делать выводы, хотя, наверное, и не имею на это права.
 
 А вообще, такая защита, которая была мной тут осуществлена обломает 90%
 крэкеров: вы же забываете, что Hex и dragon и MoonShiner - их единицы, а
 Bad_guy’ев и MozgC’ов много. Так что реальную прогу с такой защитой сломают
 где-то не менее, чем через полгода после релиза (если не кричать, что защита в
 ней навороченная и вообще не говорить про защиту).
 
Bad_guy
 А вот ваша любимая процедура как сначала в Delphi выглядела:
 
 procedure Reg;
 var il2: longint;
 begin
 asm
 push eax
 push edx
 push ecx
 mov edx, 10
 mov eax,ilong // это для Hex’а
 mov il2,eax
 add il2,40
 @im:
 mov ecx, [il2]
 mov eax, [ecx]
 xor eax, $96969696
 mov [ecx], eax
 add il2, 4
 dec edx
 jnz @im
 pop ecx
 pop edx
 pop eax
 end;
 form1.Status.Color := clGreen;
 form1.Status.Caption := cr(82)+cr(69)+cr(71)+cr(73)+cr(83)+cr(84)+cr(69)+
 cr(82)+cr(69)+cr(68);
 end;
 

В Общем, все из проделанных способов взлома были возможны либо по моей оплошности и недоделке (в случае метода Hex'a) , либо исходя из оставленной лазейки (самомодифицирующийся код был слабо зашифрован), а также, в основном из-за того, что я давал достаточно конкретные намёки на то, как сделана защита.

Что нужно доделать

В принципе, даже использование регистрационного кода в качестве адреса не даёт большой гарантии стойкости защиты. Поэтому вижу только один весьма надёжный трюк - зашифровать самомодифицирующийся код, доступный только в зарегистрированном варианте программы, используя надёжные криптографические алгоритмы, такие как: RC6, DES, Blowfish. Таким образом можно свести вероятность взлома программы практически к нулю. Хотя, лично я думаю, что нет надобности в такой стойкости защиты какой бы то ни было программы.

Заключение

Пока я писал эту статью я понял, что почти не существует таких программистов, которые справятся с созданием такой защиты... так что, по-видимому это "академичная" защита, которую в реальности делать никто не станет.

Удачи вам в вашей деятельности, чем бы вы ни занимались, Bad_guy.



Обсуждение статьи: Крутая защита или CRACKL@B CrackMe #1 >>>


Комментарии к статье: Крутая защита или CRACKL@B CrackMe #1

elishe 13.03.2006 12:59:57
прикольно. я сперва сломала, прогу - потом нашла описание взлома от dragon'a - делала также. правда долго искала вызов на функцию расшифровки, но потом забросила и подогнала код
elishe
D84ACEF0919559ACE136
---
Wyfinger 05.05.2008 12:16:52
Потратил два дня на взлом, поначалу ничего не получалось, но потом все стало проясняться.
Сначала я сделал патч:распаковал UPX, и подправил в месте перехода после последней проверки (все предыдущие проверки легко просчитываются и у меня был код-заготовка, который проходил все проверки, кроме последней и вываливался на "Поднапрягись") и вместо XOR 5CD37EA6 поставил MOV 00449F34 (адрес Reg).

Да, найти процедуру Reg было довольно сложно, сначала я искал по вызовам TControl.SetText, но потом прочитал, что используется шифрование кода.

Мой код: Solitary / F46ACC58BDB55B040DA6

Код моего кейгена:
// ** Hash
function Hash(ms: string):int64;
var
ms2 : string;
imt : int64;
imt1 : integer;
w : array [0..7] of byte absolute imt;
const
mt = 'lKeoOIwjk34uGFqi';
begin
ms2 := '';
ms2 := ms chr(42);
imt := $1AFD2FDE3ABC4975;
for imt1 := 1 to length(mt) do
begin
w[imt1 mod 8] := (w[imt1 mod 8]*integer(ms2[(imt1 mod length(ms2)) 1])) mod 256;
end;
Result := imt;
end;

procedure TForm1.Edit1Change(Sender: TObject);
var
nam,
ch1,
ch2,
ch3 : string;
vv : DWORD;
begin
nam := Edit1.Text;

ch1 := Copy( IntToHex( Hash(nam), 16), 1, 8 );
vv := StrToInt( '$' ch1 );
vv := vv xor $49DF975C;
ch2 := Copy( IntToHex( vv , 8), 1, 8 );
ch3 := Copy( IntToHex( Hash(ch1 ch2) , 16), 4, 4 );

Edit2.Text := ch1 ch2 ch3;
end;

P.S. Когда увидел заветную зеленую надпись "REGISTERED" получил настоящее, здоровое моральное удовлетворение. Спасибо.
---
Wyfinger 05.05.2008 12:19:47
Еще одно, такую защиту не стоит использовать в реальных программах. Я например большую часть времени искал адрес функции Register, но в reallive крекер может иметь готовый рабочий пароль и тогда он будет знать и этот адрес.
---

Материалы находятся на сайте https://exelab.ru



Оригинальный DVD-ROM: eXeL@B DVD !


Вы находитесь на EXELAB.rU
Проект ReactOS