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

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


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

Исследование CrackMe #4 от Fantom и написание KeyGen'а

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

Хорошая подборка видеоуроков, инструментов крэкера, книг и статей - здесь.

Автор: sh_temp_el <newprogramer@mail.ru>

Исследование CrackMe4 от Fantom и написание кейгена.

Инструменты : IDA 4.1
Любой компилер C/C++

Статья написана для совсем начинающих,дабы внести хоть какой-нибудзь порядок в головы новичков(а порядок в оных ой как необходим!!)
Не претендуя на уникальность и вообще на что бы там ни было,с вашего позволения рискну начать.
И так-с...
Четвёртый крякмис от Фантома не намного сложнее предыдущих(не вертье мне на слово да и вообще никому не верьте, а сами всё проверяйте ;-)
Ну начнём проверять правильность моего утверждения :
Запускаем <Crackme4.exe> ... ага, два edit-control’а : Name ... Serial ... Чтож вводим в Name - "Cool" , в Serial - "1234" .
Жмём Check - Wrohg serial ! ......... и т.д. типа пытайтесь ещё. Предложение попытаться это для юзеров, а мы крутые кракеры - нам и одной
попытки хватило чтобы понять, что без взлома ну никак :-)) Будем ломать (чувствуете как греют душу эти слова ?!! ещё НЕТ ???)
те, кто ответил "нет" - идут играть в HalfLive, остальные уже запустили IDA и дёргают PgUp и PgDn в надежде у видеть пароль.
Что, говорите нет пароля и быть не может ? Правильно он генерится в памяти из имени , которое мы вводим в поле Name... Что же тогда мы будем искать в
дизассамблере ? Давайте подумаем ... Получается (думать)? Правильно - чтоб сравнивать данные введённые нами с корректными, программа должна их получить
Как прога их получает ? Есть несколько способов, но чаще остальных используются два :
GetWindowTextA()
GetDlgItemTextA()
Скажу вам по секрету - в данном случае это GetDlgItemTextA() (но не верьте мне !!! всё проверяйте сами !!!) ;-)
Итак в IDA жмём Alt+T ( Search->Text ) в появившемся окне набиваем : GetDlgItemTextA <Enter>
Мы дожны появиться где-то здесь :
.text:00401205 ; ---------------------------------------------------------------------------
.text:00401205
.text:00401205 loc_401205: ; CODE XREF: sub_401123+56j
.text:00401205 push 100h ; nMaxCount
.text:0040120A push offset unk_403084 ; lpString
.text:0040120F push 3E8h ; nIDDlgItem
.text:00401214 push [ebp+hWnd] ; hDlg
.text:00401217 call GetDlgItemTextA <-Здесь мы
.text:0040121C push 100h ; nMaxCount
.text:00401221 push offset unk_403184 ; lpString
.text:00401226 push 3E9h ; nIDDlgItem
.text:0040122B push [ebp+hWnd] ; hDlg
.text:0040122E call GetDlgItemTextA
.text:00401233 push [ebp+hWnd]
.text:00401236 call sub_4012F9
.text:0040123B cmp eax, 0
.text:0040123E jz short loc_401255
.text:00401240 push 40h ; uType
.text:00401242 push offset aCheckSerial ; lpCaption
.text:00401247 push offset aYouGotItCongra ; lpText
.text:0040124C push 0 ; hWnd
.text:0040124E call MessageBoxA
.text:00401253 jmp short loc_401268
.text:00401255 ; ---------------------------------------------------------------------------
Коментировать нечего - и так всё понятно . Но всё таки, чтоб не осталось ничего не ясного ни для кого -
.text:00401217 здесь вызывается функция , которую мы искали , и которая где-то в памяти сохраняет наше имя (точнее не где-то, а по смещению 403084 это третий
параметр функции GetDlgItemTextA)но нам сейчас не это важно . Идем дальше -
.text:0040122E здесь второй раз вызывается GetDlgItemTextA и делает тоже самое с нашим серийником.
.text:00401233 команда засылки в стек значения, конкретно - заносится адрес того места, где лежит введённый нами Serial(наверное сейчас вам пока будет сложно понять что да как, поэтому здесь уж вам придется мне поверить позднее
вы в этом убедитесь и не будете больше на меня материться !!!)
.text:00401236 вызов какой-то функции.Так скорее всего и подумает новичок, ну и ладно скажу я - идём дальше, а потом хош не хош, а вернуться сюда придётся вот тогда и разберёмся что это за
функция такая и "откуда она ваще здесь нарисовалась" ;-)
Я закурил - двигаем дальше ...
.text:0040123B здесь сравниваем EAX с нулём и в зависимости от результата прыгаем на 401255 или не прыгаем, а идём дальше.
а что у нас дальше ? А дальше засылка в стек параметров функции MessageBoxA с последуюшим её вызовом.А что это за месага? Второй её параметр - текст, который она собственно и показывает
об этом нам напоминает коментарий IDA - ; lpText. Что она получает в этом параметре ? - адрес какой то переменной.Какой именно мы узнаем если поместим курсор на строку
с этим параметром и нажмём <Enter>.
Вот, что мы увидим :

.data:00403060 aYouGotItCongra db ’You got it! Congrats! :)’,0 ; DATA XREF: sub_401123+124o

Ниочём не говорит ? Конечно же это сообщение о правильной регистрации.Жмём <Esc> и возвращаемся обратно.Что же будет, если по адресу 0040123E
мы всё же совершим переход ? А попадём мы сюда :
.text:00401255 loc_401255: ; CODE XREF: sub_401123+11Bj
.text:00401255 push 30h ; uType
.text:00401257 push offset aCheckSerial ; lpCaption
.text:0040125C push offset aWrongSerialKee ; lpText
.text:00401261 push 0 ; hWnd
.text:00401263 call MessageBoxA
Опять MessageBoxA, только уже с сообщением о неправильной регистрации(его то мы и видели,при первой попытке зарегиться !!!)
Теперь особо ленивые открывают HIEW, и меняют jz на jnz. Что это даст и как это сделать - думайте сами, данная статья совсем не об этом !
в принципе - прога поломана, можете ходить и орать на право и налево ,
что вы крутые кракеры :-)
Кто эти путём не пошёл и кому интересен сам процесс ( да ещё и написаниё Кейгена !!!) - те за мной !
Помните ту функцию,на которую мы вскольз обратили внимание(подсказываю - та , что по адресу 00401236)? Ведь это после неё идет выбор на какую месагу прыгать!!!
Догадываетесь теперь что это за функ-я ? Правильно - скорее всего(даже точно)- это процедура генерации правильного серийника и сравнения его с нашим !!!
Заходим в неё (ставим на неё курсор и жмём <Enter>).

.text:004012F9 sub_4012F9 proc near ; CODE XREF: sub_401123+113p
.text:004012F9 push ebp <---------------------------------------Мы здесь---------------------
.text:004012FA mov ebp, esp
.text:004012FC push esi
.text:004012FD push edi
.text:004012FE lea esi, ds:403084h
.text:00401304 lea edi, ds:403284h
.text:0040130A xor eax, eax
.text:0040130C xor ecx, ecx
.text:0040130E mov bl, 1Ah
.text:00401310
.text:00401310 loc_401310: ; CODE XREF: sub_4012F9+2Fj
.text:00401310 cmp byte ptr [esi], 0
.text:00401313 jz short loc_40132A
.text:00401315 mov al, [esi]
.text:00401317 add al, cl
.text:00401319 xor al, cl
.text:0040131B div bl
.text:0040131D shr ax, 8
.text:00401321 add al, 41h
.text:00401323 mov [edi], al
.text:00401325 inc edi
.text:00401326 inc esi
.text:00401327 inc ecx
.text:00401328 jmp short loc_401310
.text:0040132A ; ---------------------------------------------------------------------------
.text:0040132A
.text:0040132A loc_40132A: ; CODE XREF: sub_4012F9+1Aj
.text:0040132A mov byte ptr [edi], 0
.text:0040132D xor eax, eax
.text:0040132F cmp ecx, 0
.text:00401332 jz short loc_40134E
.text:00401334 push offset unk_403284 ; lpString2
.text:00401339 push offset unk_403184 ; lpString1
.text:0040133E call lstrcmpA
.text:00401343 cmp eax, 0
.text:00401346 jz short loc_40134C
.text:00401348 xor eax, eax
.text:0040134A jmp short loc_40134E
.text:0040134C ; ---------------------------------------------------------------------------
.text:0040134C
.text:0040134C loc_40134C: ; CODE XREF: sub_4012F9+4Dj
.text:0040134C mov eax, ecx
.text:0040134E
.text:0040134E loc_40134E: ; CODE XREF: sub_4012F9+39j
.text:0040134E ; sub_4012F9+51j
.text:0040134E pop edi
.text:0040134F pop esi
.text:00401350 leave
.text:00401351 retn 4
.text:00401351 sub_4012F9 endp

Вот её полный листинг. Полностью каждую команду я описывать не собираюсь - читайте Криса Касперски.Я остановлюсь только на самых важных
местах.
.text:004012FE lea esi, ds:403084h ; в esi заносим смещение нашего имени(на основе его будет генериться серийник.
.text:00401304 lea edi, ds:403284h ; в edi смещение того места, куда этот серийник запишется.
Затем очищаем eax и ecx. В bl заносим 1A - он будет использоваться при генерации. Всё. Далее собственно пошла процедура генерации.

cmp byte ptr [esi], 0 ; 1
jz short loc_40132A ; 2
mov al, [esi] ; 3
add al, cl ; 4
xor al, cl ; 5
div bl ; 6
shr ax, 8 ; 7
add al, 41h ; 8
mov [edi], al ; 9
inc edi ; A
inc esi ; B
inc ecx ; C
jmp short loc_401310 ; D

1.Сравниваем первый символ с нулём (читай проверяем на конец строки)
2.Если 0 - прыгаем, нет - идём дальше
3.заносим первый символ в al
4.складываем al и cl (в cl пока ноль - команда xor ecx,ecx по адресу 0040130C)
5.поразрядное исключающее ИЛИ (см. описани команд ассемблера)
6,7 остаток от деления на bl (помните заносили в него 1А ?)
8.прибавляем 41
9.результат записываем в адрес который хранится в edi (теперь там первый символ правильного серийника !)
A,B,C - увеличиваем на один адрес приёмника, адрес откуда берём символы и счётчик соответственно
D.прыгаем на начало прцедуры шифрования дабы проделать все операции с оставшимися символани имени.
Всё !!! Ну что трудно ? Вот и я говорил, что нет!
Если посмотреть листинг дальше, то увидим процедуру сравнения двух строк(lstrcmpA) - нашего серийника, и того, который получился после шифровки !
Ну что, пива ещё хватит на написание кейгена ?? ;-) Не буду вас долго мучить - вам ещё сегодня нужно много чего поломать,
чтоб завтра в разговоре с вездесущими ламерами какбы вскольз сказать, что вот вчера я мол то да то поламал =)
Привожу исходник на С :

#include<conio.h>
#include<stdio.h>

void main()
{
char Name[20]; //введёное имя
int i; //счётчик
int bl = 0x1A;

printf("\n Enter your Name");
printf("\n-> ");
gets(Name);
i = 0;

while(Name) // вот она - процедура генерации
{ // что ещё раз её объяснять ? :-)
Name += i;
Name ^= i;
Name %= bl;
Name += 0x41;
i++;
}

printf("\n%s\n",Name);
getch();
}

Правда не большой ? И не сложный - та же процедура генерации,которую мы разобрали.Осталось только вывести строки о вашем авторстве этой
замечательной проги, и нести показывать друзьям ! ;-)



//Как я уже писал - статья не претендует на уникальность да и вообще ни на какие лавры(это моя первая статья, если кому понравится, то не последняя ;-) )
//Написал я её для совсем начинающих, потому, что сам на таких статьях учился(спасибо Bad_Gay’ю)
//Мылить можно сюда: newprogramer@mail.ru


Обсуждение статьи: Исследование CrackMe #4 от Fantom и написание KeyGen'а >>>


Комментарии к статье: Исследование CrackMe #4 от Fantom и написание KeyGen'а

Mafia32/[ROCK] 25.07.2004 20:33:05
\"статья не претендует на уникальность\"

а нафиг тогда писать?
---
sh_temp_el 25.07.2004 22:08:27
Просто пытался подробно и понятно описать то, что не все ещё понимают ...
---
Zer0 27.07.2004 12:45:19
Нормальный тутор для новичков. Статей по кейгенингу для ньюбисов вообще мало.
---
arnix 27.07.2004 13:33:34
аи-аи-аи, ну как так можно? :)
Я опоздал на несколько часов, вот моя статья про это же :)
http://freenet.am/~arnix/crackme3.htm
---
Dr@kon 28.07.2004 13:41:42
По поводу того что тутор нормальный я не спорю но в проге во первых ошибки а во вторых я на асме сам писал кейген а проге полученный пасворд и моим и вашим кейгеном не нравится
---
sh_temp_el 01.08.2004 15:20:44
***но в проге во первых ошибки ***
Енто не ошибки , а описки !
И вообще у меня в черновике их нет !!!
Это при генерации страницы они появились...
*** а проге полученный пасворд и моим и вашим кейгеном не нравится ***
Я свой проверял - прога хавает и не пищит (Хотя возможно там есть проверка на длинну имени и я (и Dr@kon)её не заметили ... надо посмотреть в чём дело...)
СПАСИБО ЗА КРИТИКУ !!!!!
---

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



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


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