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

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


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

CR@CK с N00ля

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

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

Автор: payhash <runsolar@mail.ru>



Памятка начинающему крэкsoftмейкеру.

План:
1) Вступление.
2) Анализ FaNt0m's CrackMe #4 (fant0m.cjb.net сложность 0-1).
3) Анализ ReHPer KeyGenMe v1.1 (crackmes.de сложность 3-4/10).
4) Взлом KeygenMe No.4 by n00b (crackmes.de сложность 5-6/10).


Здравствуй наш юный читатель (и будущий уберкрекмейкер),...

Эта статья написана только в ознакомительных целях и не является руководством для осуществления действий связанных с нарушением законодательств РФ, так же в результате написания этой статьи не пострадала, ни одна система защиты, лицензионного авторского программного обеспечения.

Технология патчинга практически любого не freeварного софта есть нечто иное, как модификация программного кода (даже в пределах одного байта/бита), а это уже попадает в рамки статей УК РФ. Поэтому необходимо лицензировать софт, который вы приобретаете, бывает, так что денег нет или их просто не хватает и приходиться просто-напросто выкручиваться из ситуации любыми законными способами. Хотя написание самопального кейгена к тому или иному программному обеспечению с точки зрения законодательства все же остается спорным вопросом (так как вы ни чего не модифицируете), но все же куда лучше, чем его модификация.

Что необходимо нам знать и какие инструменты вам понадобятся:
0) Терпение и много свободного времени, а так же позитивные мысли (очень важный аспект, пожалуй, самый важный).
1) Немножко почитать рассылку Калашникова, а потом туториалы Айсзелеона (поупражняться с ними в assembler).
2) Мы будем использовать OllyDbg, дружественный интерфейс, дизассемблер и отладчик в одном флаконе (скачали туториал на русском с cracklab.ru и тоже с ним поупражняться).
3) Какой ни будь Turbo C 3.0 (или компилятор на ваш вкус), с помощью него будем писать keygen/ы.
4) Атмосфера в виде треков «Underworld.CowGirl» и «Xzibit.Muthafucka».

Для каждого, этот вопрос по-разному остается открытым, для кого-то это средство к существованию, для кого-то просто умственная спортивная игра в виде разгадывания очередного логического PAZLE и не более.

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

Изучать, что-либо всегда лучше на практике, поэтому не будем много разглагольствовать в теории, так как «crack - это точная наука».

Для начала начнем с уровня сложности 0 (или 1), что бы было понятно и наглядно для начинания, и по ходу событий примеры постепенно будут усложняться, естественно повышая ваше мастерство.


Анализ FaNt0m's CrackMe #4 (fant0m.cjb.net)

-Анализируй это!
Начинаем штурм кракмиса (или кейгемиса)

FaNt0m's CrackMe #4 (сложность 0), это очень простой и интуитивно понятный кракмис. С ним думаем ни каких сложностей не должно возникнуть, итак приступим к препарированию. Берем скальпель в руки (OllyDbg), жмем «F3», производим вскрытие файла. В данном случае поступим классическим способом, вызовем командную строку отладчика через «Alt+F1» (это плагин). Поставим break point (далее бряк) на вызов процедуры с именем «GetDlgItemTextA», для этого нужно в окне «command» ввести команду «bpx GetDlgItemTextA», жмем Enter. Теперь запускаем программу через «F9», появилась форма с вероятными полями Edit1.Name и Edit2.Serial (такую символику полей мы будем использовать в этой статье), вводим в них абсолютно любые данные и жмем подтверждение.

Отладчик остановился в нужном месте при вызове тех точек, на которые мы с вами поставили бряки.

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00401205 |> 68 00010000 PUSH 100 ; /Count = 100 (256.)
0040120A |. 68 84304000 PUSH CRACKME4.00403084 ; |Buffer = CRACKME4.00403084
0040120F |. 68 E8030000 PUSH 3E8 ; |ControlID = 3E8 (1000.)
00401214 |. FF75 08 PUSH DWORD PTR SS:[EBP+8] ; |hWnd
00401217 |. E8 62010000 CALL <JMP.&USER32.GetDlgItemTextA> ; GetDlgItemTextA
0040121C |. 68 00010000 PUSH 100 ; /Count = 100 (256.)
00401221 |. 68 84314000 PUSH CRACKME4.00403184 ; |Buffer = CRACKME4.00403184
00401226 |. 68 E9030000 PUSH 3E9 ; |ControlID = 3E9 (1001.)
0040122B |. FF75 08 PUSH DWORD PTR SS:[EBP+8] ; |hWnd
0040122E |. E8 4B010000 CALL <JMP.&USER32.GetDlgItemTextA> ; GetDlgItemTextA
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Ниже сразу же в глаза бросается следующий код, который нам интуитивно подсказывает, для чего он необходим.

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00401233 |. FF75 08 PUSH DWORD PTR SS:[EBP+8]
00401236 |. E8 BE000000 CALL CRACKME4.004012F9
0040123B |. 83F8 00 CMP EAX,0
0040123E |. 74 15 JE SHORT CRACKME4.00401255
00401240 |. 6A 40 PUSH 40 ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
00401242 |. 68 29304000 PUSH CRACKME4.00403029 ; |Title = "Check Serial"
00401247 |. 68 60304000 PUSH CRACKME4.00403060 ; |Text = "You got it! Congrats! :)"
0040124C |. 6A 00 PUSH 0 ; |hOwner = NULL
0040124E |. E8 49010000 CALL <JMP.&USER32.MessageBoxA> ; MessageBoxA
00401253 |. EB 13 JMP SHORT CRACKME4.00401268
00401255 |> 6A 30 PUSH 30 ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL
00401257 |. 68 29304000 PUSH CRACKME4.00403029 ; |Title = "Check Serial"
0040125C |. 68 36304000 PUSH CRACKME4.00403036 ; |Text = "Wrong Serial! Keep trying, you'll get it!"
00401261 |. 6A 00 PUSH 0 ; |hOwner = NULL
00401263 |. E8 34010000 CALL <JMP.&USER32.MessageBoxA> ; MessageBoxA
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Особый интерес для нас привлекают строчки с кодом, в котором, идет какое то сравнение с «0» и если равно прыгаем, куда то не далеко а именно по адресу «0x00401255».

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
0040123B |. 83F8 00 CMP EAX,0
0040123E |. 74 15 JE SHORT CRACKME4.00401255
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


Не сложно догадаться, да и это наглядно видно, что по адресу «0x00401255», расположился код, который выводит строку о не правильном серийном номере. Теперь возникает вопрос, в каком месте происходит этап сверки верного серийного номера с фальшивым. Посмотрев внимательно выше приведенный декомпилированный код, а именно на строку «CALL CRACKME4.004012F9» видим, что это вероятно происходит по адресу «004012F9», отправляемся по этому адресу, зажав комбинацию клавиш «Ctrl+G» увидим нечто похожее на участок кода приведенного ниже, это и будет искомое место.

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
004012F9 /$ 55 PUSH EBP
004012FA |. 8BEC MOV EBP,ESP
004012FC |. 56 PUSH ESI
004012FD |. 57 PUSH EDI
004012FE |. 8D35 84304000 LEA ESI,DWORD PTR DS:[403084]
00401304 |. 8D3D 84324000 LEA EDI,DWORD PTR DS:[403284]
0040130A |. 33C0 XOR EAX,EAX ; al=al^al;
0040130C |. 33C9 XOR ECX,ECX
0040130E |. B3 1A MOV BL,1A ; bl=0x1A;
00401310 |> 803E 00 /CMP BYTE PTR DS:[ESI],0
00401313 |. 74 15 |JE SHORT CRACKME4.0040132A
00401315 |. 8A06 |MOV AL,BYTE PTR DS:[ESI] ; al=*(name+i);
00401317 |. 02C1 |ADD AL,CL ; al=al+i;
00401319 |. 32C1 |XOR AL,CL ; al=al^i;
0040131B |. F6F3 |DIV BL ; ah=al%bl; ah=ah<<8; al=al/bl; al=al+ah;
0040131D |. 66:C1E8 08 |SHR AX,8 ; al=al>>8;
00401321 |. 04 41 |ADD AL,41 ; al=al+0x41;
00401323 |. 8807 |MOV BYTE PTR DS:[EDI],AL ; *(name+i)=(unsigned char)al;
00401325 |. 47 |INC EDI
00401326 |. 46 |INC ESI
00401327 |. 41 |INC ECX
00401328 |.^EB E6 JMP SHORT CRACKME4.00401310
0040132A |> C607 00 MOV BYTE PTR DS:[EDI],0
0040132D |. 33C0 XOR EAX,EAX
0040132F |. 83F9 00 CMP ECX,0
00401332 |. 74 1A JE SHORT CRACKME4.0040134E
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

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

/*
KeyGen для FaNt0m's CrackMe #4
payhash [l00p.org]
*/

#define BUFSIZE 255

unsigned char *main(void)
{
unsigned int i, ah, al, bl;
unsigned char name[BUFSIZE];

memset(name, 0x0, BUFSIZE);
puts("nnKeyGen for FaNt0m's CrackMe #4");
printf("fant0m.cjb.netnn");
printf("Name: ");
gets(name);

(unsigned int ) al=al^al;
(unsigned int ) bl=0x1A;

for((unsigned char)i=i^i; i < strlen(&name); i++)
{
(unsigned char )al=*(name+i);
(unsigned char )al=al+i;
(unsigned char )al=al^i;

//div bl
(unsigned int ) ah=al%bl;
(unsigned int ) ah=ah<<8;
(unsigned int ) al=al/bl;
(unsigned int ) al=al+ah;

(unsigned short ) al=al>>8;
(unsigned char) al=al+0x41;
*(name+i)=(unsigned char)al;
}

printf("Serial: %s nn", &name);
return name;
}

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

Теперь перейдем к более сложному заданию требующий некоторых дополнительных усилий в виде шевеления мозгов, так как сложность уже уровень 3-4 по 10 бальной шкале.

Анализ ReHPer KeyGenMe v1.1 (crackmes.de)

-Это не правильные пчелы!
-И они делают не правильный мёд.


Скачиваем, запускаем ReHPer KeyGenMe v1.1 (уровень сложности 3-4).
Встречаемся с первой же ловушкой, а именно не подписанные поля для ввода Edit1 и Edit2. Наверное, не подписывать поля ввода Edit стало модным у разработчиков кракмисов, что действительно по началу пугает начинающего крекера, но не стоит на это обращать внимание, а просто на это улыбаемся, потому что это действительно веселит. Видим два TextEdit скорей всего это поля Name и Serial, от «фонаря» вводим в них данные, жмем Check – обламываемся, «а вы чего ожидали &#61514;?».
Загружаем OllyDbg, жмем «F3», вскрываем объект для изучения. Смотрим на первый взгляд ни чем не упаковано, можете проверить через PEiD, но мы не станем прибегать к его помощи, так как с первого взгляда видно, что код чистенький и не упакованный (автор гарантирует), и это уже радует, спасибо ReHPer.
Поднимаемся выше, бегло просматривая декомпилированный код, сразу же в глаза бросается «Incorrect Password», где-то это уже видели.

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00464FA4 |> 6A 10 PUSH 10
00464FA6 |. A1 28704600 MOV EAX,DWORD PTR DS:[467028]
00464FAB |. E8 10F8F9FF CALL KeyGenMe.004047C0
00464FB0 |. 50 PUSH EAX
00464FB1 |. 68 44504600 PUSH KeyGenMe.00465044 ; ASCII "Incorrect Password!"
00464FB6 |. 8BC3 MOV EAX,EBX
00464FB8 |. E8 B7A5FDFF CALL KeyGenMe.0043F574
00464FBD |. 50 PUSH EAX ; |hOwner
00464FBE |. E8 AD1EFAFF CALL <JMP.&user32.MessageBoxA> ; MessageBoxA
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Чуть выше расположился следующий радостный код (это наглядно видно), который выводит сообщение «Good work! Write keygen!», а это значит, что истина где-то рядом, ставим бряки «F2» на адреса где начинаются вызовов этих функций.

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00464F83 |. 6A 40 PUSH 40
00464F85 |. A1 28704600 MOV EAX,DWORD PTR DS:[467028]
00464F8A |. E8 31F8F9FF CALL KeyGenMe.004047C0
00464F8F |. 50 PUSH EAX
00464F90 |. 68 28504600 PUSH KeyGenMe.00465028 ; ASCII "Good work! Write keygen! :)"
00464F95 |. 8BC3 MOV EAX,EBX
00464F97 |. E8 D8A5FDFF CALL KeyGenMe.0043F574
00464F9C |. 50 PUSH EAX ; |hOwner
00464F9D |. E8 CE1EFAFF CALL <JMP.&user32.MessageBoxA> ; MessageBoxA
00464FA2 |. EB 1F JMP SHORT KeyGenMe.00464FC3
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Если вы уже имели дело с патчингом софта то еще выше, есть код, который можно изменить и кейгенмис будет покрякан (из правильного условия делаем неправильное) и дело в шляпе, но условия программы не патчинг а кейгенинг и мы не ищем простых путей &#61514;, тогда двигаем мозг дальше. Останавливаемся в окрестностях этого куска кода и немного призадумаемся, так как именно тут существует точка входа на подпрограмму генерации серийного номера. Если быть внимательней, то это примерно где-то между куском кода:

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00464ED0 |. 68 0C504600 PUSH KeyGenMe.0046500C ; ASCII "Fill a name and password!"
00464ED5 |. 8BC3 MOV EAX,EBX
00464ED7 |. E8 98A6FDFF CALL KeyGenMe.0043F574
00464EDC |. 50 PUSH EAX ; |hOwner
00464EDD |. E8 8E1FFAFF CALL <JMP.&user32.MessageBoxA> ; MessageBoxA
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

и результирующими сообщениями о правильности и не правильности введенных данных (с.м. отладчик), пускай это будет отправной нашей окрестностью, так как сейчас нам необходимо найти кусок подпрограммы, где генерируется серийный номер.
На вскидку, таких точек входа много, но не стоит отчаиваться, если присмотреться, то существуют некоторые точки входа в процедуры адреса которых повторяются, а это уже кое-что (у нас это 00404680), ставим на все эти адреса бряки «F2» и перезапускаем отладчик «Ctrl+F12», далее «F9», заполняем форму (в поле Edit1.Name мы ввели “payhash”).
Если все было сделано правильно, то отладчик остановиться на одной из наших меток (0x00404680). Обратим свое внимание на нижнее правое окно, в котором происходят изменения в буфере. Что же мы видим здесь интересного?
Вас не заинтересовало, то, что в нем появился указатель на ASCII строку имени вашего компьютера (отметим это у себя в голове). Вероятно, что выше, где-то произвелся вызов подпрограммы, которая запросила имя вашего компьютера, посмотрим выше и видим точку входа в подпрограмму (у нас это CALL 00464DF8), перейдем по этому адресу («Ctrl+G») и действительно видим вызов функции GetComputerName.

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00464DF8 /$ 53 PUSH EBX
00464DF9 |. 81C4 FCFEFFFF ADD ESP,-104
00464DFF |. 8BD8 MOV EBX,EAX
00464E01 |. C70424 0001000>MOV DWORD PTR SS:[ESP],100
00464E08 |. 54 PUSH ESP ; /pBufferSize
00464E09 |. 8D4424 08 LEA EAX,DWORD PTR SS:[ESP+8] ; |
00464E0D |. 50 PUSH EAX ; |Buffer
00464E0E |. E8 8519FAFF CALL <JMP.&kernel32.GetComputerNameA> ; GetComputerNameA
00464E13 |. 85C0 TEST EAX,EAX
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


Начинаем догадываться, к чему бы это понадобилось программе?- Вероятно, это как-то связанно с генерацией серийного номера. Нажимаем на «F8» для продолжения трассирования изучаемого кракмиса. Сразу же после выполнения первой процедуры расположенной по адресу 0x00408640 (CALL 00408640), в нашем стековом окне появился указатель на число «70» (у вас это может быть другое число), трассируем далее «F8», встречаем следующий CALL 00408640.
После вызова подпрограммы видим, что в нашем стеке произошли некоторые преобразования – появился новый указатель, но уже на другое число, у нас это «5159». Что-то уж подозрительный какой, то адрес подпрограммы, ниже он встречается еще раз, ручаемся, что будет еще одно число, проверим это нажав «F8».
Действительно наши ожидания подтвердились, появился еще один указатель на число "5229000" – из этого делаем вывод, что по этому адресу 0x00408640 расположилась процедура генерации некой числовой последовательности (далее зададимся вопросом, случайна ли эта последовательность?).
Настало время перейти по этому адресу, нажимаем «Ctrl+G» в окно вводим «0x00408640» - OK, смотрим декомпилированный участок процедуры. Вроде бы ни чего не понятно, но видим, что подпрограмма вызывает две процедуры.

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00408640 /$ 56 PUSH ESI
00408641 |. 89E6 MOV ESI,ESP
00408643 |. 83EC 10 SUB ESP,10
00408646 |. 31C9 XOR ECX,ECX
00408648 |. 52 PUSH EDX
00408649 |. 31D2 XOR EDX,EDX
0040864B |. E8 A4FFFFFF CALL KeyGenMe.004085F4
00408650 |. 89F2 MOV EDX,ESI
00408652 |. 58 POP EAX
00408653 |. E8 98BDFFFF CALL KeyGenMe.004043F0
00408658 |. 83C4 10 ADD ESP,10
0040865B |. 5E POP ESI
0040865C . C3 RETN
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Внимательно отслеживая изменения в стеке, мы замечаем, что при вызове одной из двух подпрограмм, которые вызываются по точкам входа «0x004085F4» и «0x004043F0», в стеке образуются одно из выше указанных «волшебных» чисел.
Теперь необходимо заново трассировать программу, но уже с элементами входа в подпрограммы (не стоит входить в каждую процедуру, вы запутаетесь), нас интересуют несколько точек входа, а именно «0x00408640», «0x004085F4» и «004043F0» поэтому, когда курсор выполняемых инструкций достигнет точки входа «00408640» в место «F8» нужно нажать «F7».
Далее продолжаем трассировать процедуру расположенному по адресу «00408640», используя клавишу «F7», пока не попадем в подпрограмму расположенному по адресу «004085F4».
Проникнув в подпрограмму по адресу «004085F4» мы увидим некоторый код, в котором наибольший интерес привлекает следующий цикл:

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00408611 |> 31D2 /XOR EDX,EDX
00408613 |. F7F1 |DIV ECX
00408615 |. 4E |DEC ESI
00408616 |. 80C2 30 |ADD DL,30
00408619 |. 80FA 3A |CMP DL,3A
0040861C |. 72 03 |JB SHORT KeyGenMe.00408621
0040861E |. 80C2 07 |ADD DL,7
00408621 |> 8816 |MOV BYTE PTR DS:[ESI],DL
00408623 |. 09C0 |OR EAX,EAX
00408625 |.^75 EA JNZ SHORT KeyGenMe.00408611
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Как раз в этом коде и происходит генерация нашего некого волшебного числа, а точнее трех её частей сначала «70» потом «5159» и «5229000», соответственно адрес «0x00408640» вызывается трижды. Теперь зададимся вопросом на основании, каких входных данных образуются эти волшебные числа. Давайте рассмотрим, какие данные попадают в подпрограмму «0x00408640».
Заново запускаем объект для изучения и шагово его трассируем через «F8», доходим до первого вызова «0x00408640» запоминаем, какие у нас значения хранятся в регистрах, для нас наиболее важными являются регистры EAX и EDI в них содержится число 0x46, нажимаем «F7» заходим в подпрограмму «0x00408640». Далее трассируем через «F8» до того места, где происходит вызов «CALL KeyGenMe.004085F4», смотрим содержимое регистров EAX и EDI, в них содержится все тоже самые 0x46, жмем «F7» и переходим на адрес «0x004085F4».
Продолжаем трассировать подпрограмму через «F8» и по пути замечаем интересную инструкцию «MOV ECX,0A» после чего в цикле присутствует инструкция «DIV ECX», а в EAX содержится 0x46, значит после DIV в EDX теперь, содержатся остаток от деления 0x0, в EAX содержится целая часть 0x7. В следующей итерации в EDX будет содержаться остаток 0x7, а в EAX будет 0x0.
Вы уже, наверное, догадались, что волшебные числа это есть ряд из остатка от деления EAX на ECX, который помещается в EDX, объединив эти операции в месте, получим число «70», не забываем, что числа в компьютере хранятся с права налево.
Аналогичным образом поступаем и с остальными вхождениями в адрес «0x00408640», но для числа «5159» в EAX помещается число «0x1427», а для набора символов «5229000» это будет число «0x004FC9C8».
Обозначим комбинации цифр «0x46», «0x1427» и «0x004FC9C8» через X1, X2, X3 и теперь изучим, откуда взялись эти странные числа? Забегая вперед, мы выясним, что X2 и X3 получаются из X1, значит, для нас необходимым является поиск X1.
Просматривая внимательно код выше, мы натыкаемся на такие строчки:

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00464E9B |. 8BF0 MOV ESI,EAX
00464E9D |. 81C6 20140000 ADD ESI,1420
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Посмотрите внимательно – вы ни чего странного не заметили, а именно «0x1420», да и еще сложение с регистром ESI. Очевидно, что после этого сложения ESI будет содержать «0x1427». Давайте это проверим, поставив бряку «F2» на эту инструкцию, для нас это адрес «0x00464E9D». После перезапуска программы мы опять ввели в после «Name.Edit1» payhash, нажимаем «Check». Отладчик остановился на недавно поставленном Break Point («0x00464E9D»). Посмотрев на регистры EAX и ESI, видим, что в них содержится число 0x7.
Сделав предположение на вскидку, приходим к выводу, что 0x7 это есть, длинна введенного имени в после Name.Edit1 (payhash), проверить это очень легко, для этого необходимо ввести имя другой длины (тогда EAX и ESI будут содержать другое значение) или найти участок кода, где эта длинна подсчитывается. Найти участок кода не составляет особого труда, так как это выполняется при вызове процедуры «CALL 004045C0» (посмотрите выше на одну операцию, где происходит MOV ESI,EAX) именно в эту процедуру передается указатель на ASCII нашего введенного имени (ставим бряк на этом вызове и проверяем). И так X1 мы найдем, если полученное число в нашем случи это число 0x41 (у вас это может быть другое число, все зависит от длины введенного имени) разделим на длину введенного имени.

Z=X1/length(“payhash”)
Z=0x0A

Естественно у вас это тоже будет число 0x0A, значит:

X1=length(Edit1)*0x0A;
X2=length(Edit1)+0x1420;

Внимательно проанализировав участок кода ниже операции «ADD ESI, 1420», где:

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00464EA3 |. 8D043E LEA EAX,DWORD PTR DS:[ESI+EDI]
00464EA6 |. 69C0 E8030000 IMUL EAX,EAX,3E8
00464EAC |. 8945 FC MOV DWORD PTR SS:[EBP-4],EAX
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Из выше приведенного участка кода не сложно догадаться, что X3 находится по следующей формуле:

X3=(X1+X2)* 0x3E8.

Проанализировав выше указанную работу, приходим к выводу, что система защиты данного crackme формирует следующую строковую комбинацию, которая состоит из имени компьютера и некой магической цифровой последовательности, у нас получилось «BLACKSMITH7051595229000». Эту сигнатуру видно в буфере при трассировании программы после вызова процедуры по адресу 0x00404680 (CALL 00404680).

Какой можно сделать вывод, проанализировав выше проведенную работу? Можно догадаться, что автор защиты при написании своей программы не зря провел данную операцию по формированию некой логической строки, на базе которой и будет формирование серийного номера. Осталось найти участок кода программы, где на базе найденной строковой комбинации производиться генерация другой строковой комбинации (искомого серийного номера). Найти участок кода, где происходит генерация серийного номера не сложно, это происходит по адресу «0x00464C8C». Вызов этой подпрограммы происходим сразу же вслед после вызова подпрограммы расположенной по адресу 0x00404680.

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00464F68 |. E8 13F7F9FF CALL KeyGenMe.00404680
00464F6D |. 8B45 D8 MOV EAX,DWORD PTR SS:[EBP-28]
00464F70 |. 8D55 DC LEA EDX,DWORD PTR SS:[EBP-24]
00464F73 |. E8 14FDFFFF CALL KeyGenMe.00464C8C
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

В подпрограмму «0x00464C8C» в EAX передается указатель на ASCII строку нашей волшебной сигнатуры (смотрим стек). Теперь перейдем к небольшому изучению генератора ключей.

Кусок кода, генерирующий серийный номер на базе найденной сигнатуры.
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00464CDB |> 8B45 FC /MOV EAX,DWORD PTR SS:[EBP-4]
00464CDE |. 8B55 F4 |MOV EDX,DWORD PTR SS:[EBP-C]
00464CE1 |. 0FB67C10 FF |MOVZX EDI,BYTE PTR DS:[EAX+EDX-1]
00464CE6 |. 8BC6 |MOV EAX,ESI ; eax:=esi;
00464CE8 |. C1E0 08 |SHL EAX,8 ; eax:=eax<<8;
00464CEB |. 03F8 |ADD EDI,EAX ; edi:=edi+eax;
00464CED |. 8BF7 |MOV ESI,EDI ; esi:=edi;
00464CEF |. 83C3 08 |ADD EBX,8 ; ebx:=ebx+8;
00464CF2 |. 83FB 06 |CMP EBX,6 ; (ebx < 0x06)? Go to 00464D45;
00464CF5 |. 7C 4E |JL SHORT KeyGenMe.00464D45
00464CF7 |> 83EB 06 |/SUB EBX,6 ; ebx:=ebx-0x6;
00464CFA |. 8BCB ||MOV ECX,EBX ; ecx:=ebx;
00464CFC |. B8 01000000 ||MOV EAX,1 ; eax:=1;
00464D01 |. D3E0 ||SHL EAX,CL ; eax:=eax<<ecx;
00464D03 |. 50 ||PUSH EAX ; eax1=eax;
00464D04 |. 8BC6 ||MOV EAX,ESI ; eax=esi;
00464D06 |. 5A ||POP EDX ; edx=eax1;
00464D07 |. 8BCA ||MOV ECX,EDX ; ecx=edx;
00464D09 |. 99 ||CDQ ; edx=0;
00464D0A |. F7F9 ||IDIV ECX ; edx=eax%ecx; eax=eax/ecx;
00464D0C |. 8BF8 ||MOV EDI,EAX ; edi=eax;
00464D0E |. 8BCB ||MOV ECX,EBX ; ecx=ebx;
00464D10 |. B8 01000000 ||MOV EAX,1 ; eax=1;
00464D15 |. D3E0 ||SHL EAX,CL ; eax=eax<<ecx;
00464D17 |. 50 ||PUSH EAX ; eax1=eax;
00464D18 |. 8BC6 ||MOV EAX,ESI ; eax=esi;
00464D1A |. 5A ||POP EDX ; edx=eax1;
00464D1B |. 8BCA ||MOV ECX,EDX ; ecx=edx;
00464D1D |. 99 ||CDQ ; edx=0;
00464D1E |. F7F9 ||IDIV ECX ; edx=eax%ecx; eax=eax/ecx;
00464D20 |. 8BF2 ||MOV ESI,EDX ; esi=edx;
00464D22 |. 8D45 EC ||LEA EAX,DWORD PTR SS:[EBP-14]
; ASCII "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/"
00464D25 |. BA B44D4600 ||MOV EDX,KeyGenMe.00464DB4
00464D2A |. 8A143A ||MOV DL,BYTE PTR DS:[EDX+EDI] ; serial[k]=alpha[edi];
00464D2D |. E8 B6F7F9FF ||CALL KeyGenMe.004044E8
00464D32 |. 8B55 EC ||MOV EDX,DWORD PTR SS:[EBP-14]
00464D35 |. 8B45 F8 ||MOV EAX,DWORD PTR SS:[EBP-8]
00464D38 |. E8 8BF8F9FF ||CALL KeyGenMe.004045C8
00464D3D |. 8B45 F8 ||MOV EAX,DWORD PTR SS:[EBP-8]
00464D40 |. 83FB 06 ||CMP EBX,6
00464D43 |.^7D B2 |JGE SHORT KeyGenMe.00464CF7
00464D45 |> FF45 F4 |INC DWORD PTR SS:[EBP-C]
00464D48 |. FF4D F0 |DEC DWORD PTR SS:[EBP-10]
00464D4B |.^75 8E JNZ SHORT KeyGenMe.00464CDB
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Конец куска.

Код представляет собой два вложенных цикла, а так же в нем присутствует указатель на ASCII
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/", это и говорит о том, что очевидно символы из этого небольшого цифрового набора будут составлять наш серийный номер и вся задача кода сводиться к поиску индекса указывающего на конкретный элемент из этого массива.
Ну, вот вроде бы все секреты кейгенмиса раскрыты, осталось за малым - написать сам keygen, что не составляет большого труда, делается это по аналогии с предыдущим примером. Вообще существует два метода создания генератора кода – традиционный (классический) и не традиционный (секретный), мы рассмотрим два способа.

Традиционный способ заключается в обычном написании генератора ключей, на каком либо языке.
/*
KeyGen для ReHPer KeyGenMe v1.1
payhash [l00p.org]
*/

int main(void)
{
Unsigned char alpha[]=
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";

unsigned char name[255];
unsigned char compname[255];
unsigned char magic_s1[255];
unsigned char magic_s2[255];
unsigned char signature[255];
unsigned char serial[255];

unsigned char a;
unsigned int i,j,k;

unsigned int eax, eax1, ebx, ecx, edx, esi, edi;

/*
В этих переменных будут храниться волшебные
числа которые будут составлять одно магическое
число =)
*/
long int magic0=0x0A;
long int magic1=0x1420;
long int magic2=0;
long int magic3=0;

puts("");
puts("");
puts("KeyGen for ReHPer KeyGenMe v1.1");
puts("ReHPer. (Saint-Petersburg, Khabarovsk) ;)");

printf("Computer name: ");
memset(compname, 0x0, 255);
gets(compname);

printf("Some Any Name: ");
memset(name, 0x0, 255);
gets(name);

memset(magic_s1, 0x0, 255);
memset(magic_s2, 0x0, 255);

//получаем магическое число
magic2=magic0*strlen(&name);

i=0;
j=0;

while(magic2 != 0)
{
magic_s1[i]=magic2%magic0;
magic2=magic2/magic0;
i=i+1;
}
i--;

for(; i!=-1; i--)
{
magic_s2[j] = (magic_s1[i]+0x30);
j=j+1;
}

i=0;
magic2=magic1+strlen(&name);
while(magic2 != 0)
{
magic_s1[i]=magic2%magic0;
magic2=magic2/magic0;
i=i+1;
}
i--;

for(; i!=-1; i--)
{
magic_s2[j] = (magic_s1[i]+0x30);
j=j+1;
}

i=0;
magic2=((magic0*strlen(&name))+(magic1+strlen(&name)))*0x3E8;
while(magic2 != 0)
{
magic_s1[i]=magic2%magic0;
magic2=magic2/magic0;
i=i+1;
}
i--;

for(; i!=-1; i--)
{
magic_s2[j] = (magic_s1[i]+0x30);
j=j+1;
}

i=j;
memset(signature, 0x0, 255);
memcpy(signature, compname, strlen(compname));
memcpy(signature+strlen(compname), magic_s2, i);

j=j+strlen(compname);

/*
for(i=0; i<j; i++)
printf("%x", signature[i]);
printf("n");
*/

memset(serial, 0x0, 255);

eax=0;
eax1=0;
ecx=0;
ebx=0;
edx=1;
esi=0;
edi=0;
k=0;

for(i=0; i<j; i++)
{
edi=signature[i];
eax=esi;
eax=eax<<8;
edi=edi+eax;
esi=edi;
ebx=ebx+8;

if(ebx < 0x06) goto L2;

L1:
ebx=ebx-0x6;
ecx=ebx;
eax=1;
eax=eax<<ecx;
eax1=eax;
eax=esi;
edx=eax1;
ecx=edx;
edx=0;
//idiv ecx
edx=eax%ecx;
eax=eax/ecx;
//

edi=eax;
ecx=ebx;
eax=1;
eax=eax<<ecx;
eax1=eax;
eax=esi;
edx=eax1;
ecx=edx;
edx=0;
//idiv ecx
edx=eax%ecx;
eax=eax/ecx;
//
esi=edx;

//printf("esi=%x, ebx=%x, eax=%x, edi=%xn", esi, ebx, eax, edi);

serial[k]=alpha[edi];
k++;

if(ebx >= 0x06)goto L1;

L2:
;
}
/*
Проверка на конечный контрольный символ в зависимости от содержимого
регистра ebx - нужен если в ebx не 0.
*/
if(ebx != 0)
{
ecx=6;
ecx=ecx-ebx;
edi=esi;
edi=edi<<ecx;
serial[k]=alpha[edi];
k++;
}
//Выводим нашь серийник
printf("Serial: ");
for(i=0; i<k; i++)
printf("%c", serial[i]);
printf("n");
return 0;
}

Нетрадиционный способ, да простят меня за подобные вещи крекмейкеры, заключается и применяется в тех случаях, когда под рукой у нас только отладчик и больше ни чего нет или поиск и анализ процедуры генерации ключей очень сложен, тогда хакерам приходиться прибегать к некоторым уловкам. Для этого вам необходимо ознакомиться с процедурой патчинга кода на этапе отладки и сохранением нового результата программы в измененном виде.
Открываем keygenme (ReHPer KeyGenMe v1.1) в отладчике далее как обычно программу стартуем через «F9», заполняем в произвольном виде форму (включая поле Edit2 «Serial»), подтверждаем через Check, пошагово трассируем программу через «F8» до тех пор, пока не дойдете до процедуры о не правильности ввода поля Edit2.Serial.

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00464FA4 |> 6A 10 PUSH 10
00464FA6 |. A1 28704600 MOV EAX,DWORD PTR DS:[467028]
00464FAB |. E8 10F8F9FF CALL KeyGenMe.004047C0
00464FB0 |. 50 PUSH EAX
00464FB1 68 44504600 PUSH KeyGenMe.00465044 ; ASCII "Incorrect Password!"
00464FB6 |. 8BC3 MOV EAX,EBX
00464FB8 |. E8 B7A5FDFF CALL KeyGenMe.0043F574
00464FBD |. 50 PUSH EAX ; |hOwner
00464FBE |. E8 AD1EFAFF CALL <JMP.&user32.MessageBoxA> ; MessageBoxA
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Теперь посмотрите в правое нижнее окошечко отладчика. Внимательно присмотревшись, вы увидите, что в буфере присутствует сгенерированный искомый ключик (у нас это «Gan1GqjJJKbKI3SmDJ4rEJKoCZamC30»).

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
0012FC08 009763A4 ASCII "5229000"
0012FC0C 00976390 ASCII "5159"
0012FC10 00976380 ASCII "70"
0012FC14 00976368 ASCII "BLACKSMITH"
0012FC18 00973C20 ASCII "BLACKSMITH7051595229000" ; искомая сигнатура
0012FC1C 009763D8 ASCII "Gan1GqjJJKbKI3SmDJ4rEJKoCZamC30" ; нужный ключик
0012FC20 00976358 ASCII "lol"
0012FC24 00976344 ASCII "payhash"
0012FC28 00976330 ASCII "payhash"
0012FC2C 0097631C ASCII "payhash"
0012FC30 00976308 ASCII "payhash"
0012FC34 00973F4C ASCII "BLACKSMITH"
0012FC38 009762F4 ASCII "payhash"
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

В нашем случае найденный ключ храниться в области памяти по адресу «0x009763D8» и представляет собой ASCII строку, у вас это может быть другой адрес. Теперь посмотрите на инструкцию расположившейся по адресу «0x00464FB1» (PUSH 465044).

00464FB1 68 44504600 PUSH KeyGenMe.00465044 ; ASCII "Incorrect Password!"

Немного подумав, вас осеняет, что если в стек перед вызовом функции MessageBoxA в место адреса, по которому располагается строка ASCII "Incorrect Password!" («0x465044»), подменить адрес, указывающий на ASCII строку с искомым ключом находящийся в буфере («0x009763D8»), то в место ASCII "Incorrect Password!" мы увидим Gan1GqjJJKbKI3SmDJ4rEJKoCZamC30». То есть в место окна с надписью, что мы неудачники высветится искомый серийный номер.

Выделяем инструкцию PUSH 465044, нажимаем пробел, заменяем PUSH 465044 на PUSH 009763D8, нажимаем правую кнопку мыши в окне с нашей декомпилированной программы, выбираем «Copy to Executable -> All Modifications», «Copy All», в появившемся окне снова нажимаем правую кнопку мыши, выбираем «Save to File», после сохранения результата кейген написан. Для правильной генерации серийного ключа строка, введенная в поле Edit1.Name должна превышать по длине строку введенной в поле Edit2.Serial и быть не короче чем 4 символа (так же стоит помнить, что на других компьютерах и ОС адреса меняются). Техника написания универсального генератора ключей с использованием нетрадиционного метода рассмотрим в следующей части статьи, так как пример описанный выше не очень хороший, но объяснят суть принципа механизма.

Теперь перейдем к более продвинутой защите (уровень примерно возле пяти), которую для нас мило предоставил некто n00b, надеясь, что его защиту ни кто не вскроет (не вскрывают ту защиту, которую не анализируют и не крякают).


Взлом KeygenMe No.4 by n00b (crackmes.de) или против лома нет приема.

-Кто вы?
-Я Мерлин, Волшебник!
-Волшебников больше нет!
-Я, последний.

Продемонстрируем еще один способ написания генератора ключей, который тоже сводиться к нетрадиционному способу, но с более прогрессивными фишками.

По желанию вы можете взять в руки отладчик и неделю анализировать механизм программной защиты настоящего keygenme, отметив для себя очень полезные выводы, но я, посидев под отладкой KeygenMe No.4 by n00b некоторое время понял, что механизм генерации серийного номера этого софта может привести к инсульту. И мой ленивый и не молодой мозг уже не может переживать подобные перегрузки, да и нервы уже не те. В общем, заочный респект автору (n00b), молодец, хорошая защита, я потратил целые сутки, и из всего понял только принцип генерации ключа, но вот с алгоритмом было лень разбираться. Но кейген, все же удалось нарисовать (как ни как это условие crackme/са.). И так приступим.
Запускаем в отладчике KeygenMe No.4 by n00b, жмем «F9» и видим идентичную картинку, как и в предыдущем примере. Заполняем форму, нажимаем «Is it correct?» и ни чего не происходит. Очевидно, что праздничное событие произойдет при правильно введенном серийном номере. Огорчает то факт, что это в некотором смысле затрудняет использование нетрадиционного метода написания генератора ключей (как в предыдущей части статьи), как говориться все дело техники.
Перезапускаем программу «Ctrl+F12» и пробуем провести поверхностный анализ декомпилированного кода. Не спеша, поднимаемся выше, внимательно смотрим, за что можно зацепиться, в голове помним, что нам необходимо найти участок, где выводиться сообщение с поздравлением, так как в большинстве случаев радом находиться точки входа в нужные процедуры и действительно искомый код не заставил себя долго ожидать.

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
0045AFE7 |. 58 POP EAX
0045AFE8 E8 5393FAFF CALL keygenme.00404340
0045AFED 75 0A JNZ SHORT keygenme.0045AFF9
; ASCII "Damn, your good! Make a keygen and send me the solution!"
0045AFEF B8 ECB14500 MOV EAX,keygenme.0045B1EC
; вызываем процедуру вывода сообщения
0045AFF4 |. E8 D730FDFF CALL keygenme.0042E0D0
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Теперь подумаем, что можно такого придумать для того, что бы выполнить задание. Интересным нам показался вызов «CALL 00404340», что же поставим на него break point «F2», далее стартуем программу на выполнение «F9» и заполняем необходимые поля, подтверждаем выполнение. После выполнения отладчик остановился в забронированном нами месте (там, где ставили бряк), теперь смотрим правое нижнее окошечко и видим, что в памяти уютно расположился искомый серийный номерок.

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
0012F5A4 00926368 ASCII "ad" ; третья часть ключика
0012F5A8 009260FC ASCII "3A5A" ; вторая часть ключика
0012F5AC 009260E8 ASCII "0189" ; первая часть ключика
0012F5B0 00926378 ASCII "0189-3A5A-ad" ; нужный ключик
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Задумаемся, как мы можем написать генератор, если не выводиться печальное сообщение? Все просто мы будем использовать сообщение, которое выводит праздничное сообщение, изменив условие программы (вернее вообще ликвидировать всю условность проверки). Но метод прямой подмены адреса строки в процедуру как это выполнялось выше, в этом случае не работает, соответственно немножко будем модифицировать код (тут надо вспоминать уроки по ассемблер). Взглянем, что твориться в регистрах нашего ЦПУ, перед тем как будет, произведет вызов «CALL 00404340». Радует то, что в регистре EDX указатель на адрес в буфере, по которому расположился искомый серийный номер.

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
EAX 009260D4 ASCII "lolz"
ECX 00000001
EDX 00926378 ASCII "0189-3A5A-ad"
EBX 00921978
ESP 0012F590
EBP 0012F618
ESI 0042AE2C keygenme.0042AE2C
EDI 0012F798
EIP 0045AFE8 keygenme.0045AFE8
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


Очевидно, что по этому адресу происходит сравнение введенного серийного номера нами и тот, который сейчас в EDX. Сделаем так, что вызов «CALL 00404340» на этом участке ни когда больше не вызовется, сотрем эту инструкцию, выполняя закон сохранения байтов, заполнив его NOP. Выделяем данную инструкцию, нажимаем правую клавишу мыши на ней, выбираем «Binary->Fill with NOPs», Теперь у вас должен получиться следующий вид.

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
0045AFE7 |. 58 POP EAX
0045AFE8 90 NOP
0045AFE9 90 NOP
0045AFEA 90 NOP
0045AFEB 90 NOP
0045AFEC 90 NOP
0045AFED 75 0A JNZ SHORT keygenme.0045AFF9
; ASCII "Damn, your good! Make a keygen and send me the solution!"
0045AFEF B8 ECB14500 MOV EAX,keygenme.0045B1EC
0045AFF4 |. E8 D730FDFF CALL keygenme.0042E0D0
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Очевидно, что и в инструкции «JNZ SHORT keygenme.0045AFF9», мы тоже не нуждаемся, поэтому мы её тоже заполняем NOPs или поправим на JNZ SHORT 0045AFEF. Теперь у нас есть «куда» выводить, осталось «что» выводить. Операция MOV EAX,keygenme.0045B1EC загружает указатель на ASCII строку "Damn, your good! Make a keygen and send me the solution!", но наша задача выводить правильный серийный номер, а указатель на него храниться в регистре EDX, поэтому изменим эту инструкцию на «MOV EAX, EDX», а после инструкции «POP EAX», запишем инструкцию «PUSH EAX» после выполненных операций у вас должен получиться следующий вид.

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
0045AFE7 |. 58 POP EAX
0045AFE8 52 PUSH EDX
0045AFE9 90 NOP
0045AFEA 90 NOP
0045AFEB 90 NOP
0045AFEC 90 NOP
0045AFED 75 00 JNZ SHORT keygenme.0045AFEF
0045AFEF 8BC2 MOV EAX,EDX
0045AFF1 90 NOP
0045AFF2 90 NOP
0045AFF3 90 NOP
0045AFF4 |. E8 D730FDFF CALL keygenme.0042E0D0
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


Сохраняем модифицированный код, на пример как serial.exe, согласно выше описанному способу или как описано в документации OllyDbg. Запускаем serial.exe вводим в поле «Yer name....» любое слово нажимаем подтверждение, радуемся ключику и готовому халявному генератору ключей.
Теперь в нас полетело куча камней и криков со словами – «Так не честно! Аффтар Жжот!», но извиняемся, мы выполнили все условия задания кракмиса KeygenMe No.4 by n00b:

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
KeygenMe No.4 by n00b README:
ЁЁЁЁЁЁЁЁЁЁЁЁЁЁЁЁЁЁЁЁЁЁЁЁЁЁЁЁЁ
Tasks:
1:=) Code a complete keygen...
2:=) Send your solution to me...
NOTE:
-----
This keygenme IS NOT RATED for newbies!
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


Тут не написано, что генератор ключей должен быть честным и для этого необходимо сидеть и углубляться в дебри мышления автора программной защиты. Модифицировав немного код, программной системы защиты мы его превратили в генератор халявный ключиков.
Данный не традиционный метод создания генератора ключей имеет кучу плюсов и минусов, которые и так очевидны. Основной его жирный плюс это экономия время за счет поверхностного анализа программной защиты, то есть не нужно терять время на углубленный анализ механизма программной защиты и тратить свои силы.

Усовершенствовав пример из ReHPer KeyGenMe v1.1, следующим образом, получим 100% работающий генератор ключей, для этого необходимо модифицировать фрагмент кода,

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00464F68 |. E8 13F7F9FF CALL KeyGenMe.00404680
00464F6D |. 8B45 D8 MOV EAX,DWORD PTR SS:[EBP-28]
00464F70 |. 8D55 DC LEA EDX,DWORD PTR SS:[EBP-24]
00464F73 |. E8 14FDFFFF CALL KeyGenMe.00464C8C
00464F78 |. 8B55 DC MOV EDX,DWORD PTR SS:[EBP-24] ;EDX указывает на серийный номер
00464F7B 58 POP EAX
00464F7C E8 8BF7F9FF CALL KeyGenMe.0040470C ;обращаем в NOPs
00464F81 75 21 JNZ SHORT KeyGenMe.00464FA4 ;обращаем в NOPs
00464F83 |. 6A 40 PUSH 40
00464F85 A1 28704600 MOV EAX,DWORD PTR DS:[467028] ;обращаем в NOPs
00464F8A E8 31F8F9FF CALL KeyGenMe.004047C0 ;обращаем в NOPs
00464F8F |. 50 PUSH EAX
; указатель на ASCII заменям на указатель с паролем
00464F90 68 28504600 PUSH KeyGenMe.00465028 ; ASCII "Good work! Write keygen! :)"
00464F95 |. 8BC3 MOV EAX,EBX
00464F97 |. E8 D8A5FDFF CALL KeyGenMe.0043F574
00464F9C |. 50 PUSH EAX ; |hOwner
00464F9D |. E8 CE1EFAFF CALL <JMP.&user32.MessageBoxA> ; MessageBoxA
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

следующим образом,

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
00464F68 |. E8 13F7F9FF CALL KeyGenMe.00404680
00464F6D |. 8B45 D8 MOV EAX,DWORD PTR SS:[EBP-28]
00464F70 |. 8D55 DC LEA EDX,DWORD PTR SS:[EBP-24]
00464F73 |. E8 14FDFFFF CALL KeyGenMe.00464C8C
00464F78 |. 8B55 DC MOV EDX,DWORD PTR SS:[EBP-24] ;EDX указывает на серийный номер
00464F7B 58 POP EAX
00464F7C 52 PUSH EDX
00464F7D 90 NOP
00464F7E 90 NOP
00464F7F 90 NOP
00464F80 90 NOP
00464F81 90 NOP
00464F82 90 NOP
00464F83 |. 6A 40 PUSH 40
00464F85 90 NOP
00464F86 90 NOP
00464F87 90 NOP
00464F88 90 NOP
00464F89 90 NOP
00464F8A 90 NOP
00464F8B 90 NOP
00464F8C 90 NOP
00464F8D 90 NOP
00464F8E 90 NOP
00464F8F |. 50 PUSH EAX
00464F90 52 PUSH EDX ;в место "Good work! Write keygen! :)" в стек заносим EDX
00464F91 90 NOP
00464F92 90 NOP
00464F93 90 NOP
00464F94 90 NOP
00464F95 |. 8BC3 MOV EAX,EBX
00464F97 |. E8 D8A5FDFF CALL KeyGenMe.0043F574
00464F9C |. 50 PUSH EAX ; |hOwner
00464F9D |. E8 CE1EFAFF CALL <JMP.&user32.MessageBoxA> ; MessageBoxA
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


Пожалуй, на этом все, хотелось бы так же отметить, что многие крекеры не приветствуют данный способ написания генератора ключей, так как это практически хитрая увертка и как бы не честно и для этого не требуются специальные необходимые знания в ассемблер, но понятия «честный взлом» и хакер не совместимы. Что касается нашего мнения - нужно стремиться к простоте, так как для хакера главное результат взлома, а не его способ нахождения.

Теперь мы дадим вам некоторые рекомендации, которые возможно облегчат вашу не легкую жизнь начинающего крекера.

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

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

Для того, что бы грамотно научиться исследовать программный код необходимо поставить себя на место разработчика программной защиты, для более эффективно разгадывания его планов защиты.

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

В ремесле реверсного инженера ни чего не дается даром, поэтому если, что-то не понятно читайте дополнительную литературу и источники Интернет, но ни когда не останавливайтесь, не достигнув свой цели.







Обсуждение статьи: CR@CK с N00ля >>>


Комментарии к статье: CR@CK с N00ля

gloom 07.06.2007 01:55:13
Ничего нового я для себя не нашел, но хотелось бы отметить, что автор довольно-таки, не побоюсь этого слова, красноречив, чего редко встретишь. Статья легка к прочтению и в то же время интересна для начинающих. Молодец.
---
mister_binn 07.06.2007 11:54:38
Честно говоря по-моему не очень!
Прыгни туда,прыгни сюда в голове возникает путаница. А про нестандарный взлом,где вместо сообщения о левом серийники, подсунуть вывод правильного серийника видели мы это, например: в статьях Fess'a и др. (насколько я помню).
Так что твоя статья не заслуживает больше 3 .
Будем ждать еще статей, но более интересных!
---
ARCHANGEL 03.08.2007 17:46:00
Чесно говоря, не впечетлило по причине сильной поверхностности написанного. Я ожидал реального разбора крутых алгоритмов, ведь, как правило, крякми с crackmes.de, точнее, именно те, которые имеют сложность 3 и выше, содержат в себе некий криптоалгоритм (или их комбинацию), например crackme N4 by mucki, где можно увидеть CRC32,MD5 u RSA. Если сложность более 6, то тогда мы сталкиваемся либо с упаковкой кода, либо с виртуальными машинами. Весьма крутые защиты, основанные на дизассемблерных движках, можно встретить на 8 уровне сложности. Тут про это - ни слова, у новичка может создаться впечатление, что кряки писать легко, но это не так, в особенности, когда речь идёт о crackmes.de
---
nechto 30.11.2007 16:42:45
Защиту от вышеизложенного способа я описал в году эдак 2000 и выложил на печально известном dore.on.ru. Достаточно кодировать не имя а преобразовывать серийник к имени. Или преобразовывать имя и преобразовывать серийник и сравнивать.
Короче - никогда не сравнивайте серийник.
---
oddBit 04.12.2007 09:14:02
ко всем, безжалостно откомментировавшим!!!!
человек жа написал, что для начинающих,
если не есть начинающие, то вам тут делать нечего,
и соответственно комменты не рулят, вы не есть целевая аудитория этой статьи,
чем больше таких статей, тем лучше, пусть вступающие на путь реверсинга имеют как можно больше различных источников, сами потом разберутся.

---
Talula 18.05.2008 08:26:12
прочитал... дошёл до конца повествования о кейгенми от фантома. и что? вот мы видим участок кода. теперь давайте писать кейген. а как? где вся теория о том, в каком месте что генерируется? что мы пишем в компиляторе? ничего не понятно... для новичков - тем более...
---
coderess 19.07.2008 20:35:57
Уже сколько видел решений крэкми от фантома номер 4, ни где не разобрано, как генерируется номер, найти то для своего ника легко, да и конечно реверснуть алгоритм генерации не тяжело, но авторы почему то не уделяют этому внимания.

Складывается ощущение, что опять демонстрация возможностей! Да простит меня автор статьи. За статью спасибо, всякий труд ценен (особенно, когда сам пишешь)
---

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



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


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