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

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


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

Пишем кейген для @stake LC 5 v5.00

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

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

Автор: Devastator <trotsevskiy@u-b.ru>

Цель статьи: научиться думать
Предмет исследования: LC5 v5.00 http://www.atstake.com
Конечная цель исследования: Создание генератора ключей
Инструментарий: Отладчик SoftIce v4.05 (WinNT)
Дизассемблер IDA v4.3.0.740a
Мозги (желательно обученные ассемблеру)

0. Знакомство с защитой


После запуска приложения имеет место быть nag(не путать с нах), в котором нас любезно проинформируют о триале. З кнопки: Trial , Register и Help(с редиректом на web). Юзим Trial...какая красота....тока не работает брутфорсер и генератор таблиц хешей. Это плохо.
Юзим кнопачку Register. Нам говорят Serial Number, а взамен хотять Unlock Code. Ну и дэ иго узять? (altavistu не предлагать) Прийдётся покупать. Юзаем Help....а вот тута пора вспомнить о нах...Single License от $650 до $7,495.
Нда...за такие бабки мона ядерную боеголовку купить наверное :)

1. Локализация защиты.


Вопрос номер 0: где именно находица защита(exe dll аль ишо хде).
Вопрос номер 1: упакован ли код какой либо гадостью али нет.
Вопрос номер 2: есть ли атидебугерные(о слово то какое) выкрутасы.
Читобы атфетить не сии вопросы....проверим (какой неожиданный поворот событий :) ).
на последние вопросы отвэт нэт.

Ладно посмотрим чего там унутрях.
Юзим Register(кнопачка такая) вводим в поле UnlockCode отсебятину типа qwerty. Запускаем SoftIce, ставим брекпоинт на функции типа GetWindowTextA аль GetDlgItemTextA ... короче за описанием чего они делають юзать API Help.
собственно bpx GetWindowTextA нам нада.
Кстати Касперский верно в своей книжке подметил, что если отладчик останвился на вызове этой функции то в регистре EAX будет указатель на буфер содержащий нашу (или ненашу) строчку.
Поставили бряк на функцию? Юзим кнопачку OK. Всплывает отладчик (как г"№но не тонет :))
Симотрим хде мы. USER32!GetWindowTextA
Эта мы в самой API функции, а нам нада узнать аткуда ана была вызвана.

Но сперва просмотрите какие строки она читает d eax.Лучше записать на листик порядок вызова функции и строки, с какими она работала.
Так получаем:
вызов 0 Serial Number
вызов 1 наш Unlock Code

Кстати коль мы в отладчике, узнаем по какой базе загрузился exe.
Переключаемся в контекст проги
addr lc5
посмотрим инфу
mod lc5
Говорит base 400000 ... поверим потом проверим

Давайте забьём на отладчик и позырим в IDA чего в ехе такого вкусного есть.
Нда 2.7 мега это долго... Извиняйте к HIEW не приучен.
Хотя не долго - там секция ресурсов ОЧЕНЬ большая.
Итак смотрим в IDA на секцию .text(Ctrl+S просмотр секций)
Flags 60000020: Text Executable Readable отсюда вывод что никаких пакеров скорее всего нет(им надо писать в секцию).
Offset to raw data for section: 00001000 смещение секции от начала ехе.
Ну а база как и в большенстве exe 400000
То есть при загрузке ехе в память начало секции будет в памяти по адресу (База + Смещеие = 400000 + 1000 = 401000)

Теперь сопоставим данные полученные с помощью отладчика и IDA - всё сходится. Посему в IDA адреса будут такие же, как и в отладчике.

Ага вернёмся к поискам вызовов.
Делаем в отладчике p ret.
оказываемся по адресу 1B:4B4D5B (второй вызов оттуда же) модуль lc5!.text
Значит вызов идёт из lc5.exe секция .text
Видимо и защита где-то недолеко.(Из личного опыта)
Кстати, если вызов функции чтения происходит из одного и того же места, то тут несколько вариантов.
0:Либо функция из которой вызывается GetWindowTextA читает в цикле.
1:Либо функция из которой вызывается GetWindowTextA сама вызывается неоднократно
2:либо варианты 0 и 1
Кому интересно здесь вариант 0.
Конечно выяснить это полезно, но как паказавает практика отнимает время (ОЧЕНЬ отнимает).

Куда как лехче воспользоваться прогрессом и поставить брекпоит(на чтение) на буфер со строкой непосредственно после того как вылезем из вызова библиотечной функции (В нашем случае USER32!GetWindowTextA) и посмотреть чего прога с ней делает дальше.
Так и зделаем - поставим бряк на буфер с нашим Unlock Code.
Как узнать адрес буфера смотри выше.
bpmd адрес r (почему bmpd а не bpm - а вдруг защита не обращается к одному или нескольким первым байтам?)
Почему именно на Unlock Code, а не на Serial Number?
Очень просто...вы знаете сколько символов должен быть Unlock Code? Правильно, я тоже не знаю. А что стоит проге проверить длину Unlock Code, а только затем производить с ним (и с Serial Number) всяческие телодвижения... логика блин.


Всплывае по адресу cs:427c00 причём код принадлежит lc5!.text ,а это значит что обращение происходит из самой проги, а не из библиотечной функции.

Посмотрим в IDA на сей кусочек кода (G далее ввести .text:427C00).


.text:00427BE0 sub_427BE0      proc near               ; CODE XREF: sub_4A4CCC+86p  >>0
 .text:00427BE0                                         ; sub_4A4CCC+F9p ...
 .text:00427BE0 
 .text:00427BE0 arg_0           = dword ptr  4		>>1
 .text:00427BE0 
 .text:00427BE0                 mov     eax, [esp+arg_0]
 .text:00427BE4                 cmp     eax, 0FFFFFFFFh	>>2
 .text:00427BE7                 jnz     short loc_427C0A
 .text:00427BE9                 mov     eax, [ecx]	>>3
 .text:00427BEB                 test    eax, eax
 .text:00427BED                 jnz     short loc_427BFC
 .text:00427BEF                 mov     edx, eax		>>4
 .text:00427BF1                 mov     [edx-0Ch], eax
 .text:00427BF4                 mov     ecx, [ecx]
 .text:00427BF6                 mov     [eax+ecx], al
 .text:00427BF9                 retn    4
 .text:00427BFC ; ---------------------------------------------------------------------------
 .text:00427BFC 
 .text:00427BFC loc_427BFC:                             ; CODE XREF: sub_427BE0+Dj
 .text:00427BFC                 push    esi
 .text:00427BFD                 lea     esi, [eax+1]	>>5
 .text:00427C00 
 .text:00427C00 loc_427C00:                             ; CODE XREF: sub_427BE0+25j
 .text:00427C00                 mov     dl, [eax]
 .text:00427C02                 inc     eax
 .text:00427C03                 test    dl, dl
 .text:00427C05                 jnz     short loc_427C00
 .text:00427C07                 sub     eax, esi		>>6
 .text:00427C09                 pop     esi
 .text:00427C0A 
 .text:00427C0A loc_427C0A:                             ; CODE XREF: sub_427BE0+7j
 .text:00427C0A                 mov     edx, [ecx]
 .text:00427C0C                 mov     [edx-0Ch], eax
 .text:00427C0F                 mov     ecx, [ecx]
 .text:00427C11                 mov     byte ptr [eax+ecx], 0 	>>7
 .text:00427C15                 retn    4
 .text:00427C15 sub_427BE0      endp

>>0 Нда около 29 вызовов...это плохо.(Тонеш тонеш... не потонеш. Может выпьешь яду... Мумифицированный Троль)
>>1 У функции 1 аргумент скорее всего указатель на строку
>>2 Очень похоже на проверку INVALID HANDLE
>>3 Кажися точно аргумент указатель на строку - проверка на 0 (конец строки)
>>4 Выход из процедуры по ошибке
>>5 ага в ESI указатель на первый байт строки(первый не нулевой)
>>6 в eax длина строки
>>7 чего-то куда-то сохранили
Нда...мимо...отсутствие результата тоже результат.

Вернёмся к отладчику.Проделаем заново установку бряка на буфер.
Несколько всплытий в cs:427c00 (нах). О на cs:49BB79 всплыли. С первого взгляда видно огромное количество арифметических операций. К чему бы это. Посмотрите на размерность регистров, с которыми производятся операции...1 байт, с чего бы ето 32-х разрядному компилятору сформировать такой странный код. Правильно, потому что его так попросили (тип данных такой). Ну соображаете что пахнет защитой... Правильно...ну, а вдруг разработчик специально мозги пудрит, а на самом деле все эти вычисления напрасны...проверим.

С приобритением опыта начинаеш замечать защиту, так сказать чуять. Это легко. Если выполняются арифметические операции в ограниченном объёме кода, то ОЧЕНЬ может быть, что здесь защита. Если в начале какой-либо функции загоняются в переменные(локальные) константы, то возможно тоже защита.Некоторые проги используют для хеширования циклы(обычно несколько вложений) вкупе с case. Такие защиты особенно трудны для создания кейгена,и обычно ломаются брутфорс методом...или патчеванием.

2.Анализ защиты.


И с чего же начинать. Резонный вопрос. Начинать с то же с чего и начинали - сбор сведений.
В общем - это узнать назначение функции. В частности - чего эта функция принимает и чего отдаёт, а также определить зависимость функции от других(какие сама вызывает).Сначала попробуем определить аргументы и их типы.Скорее всего один из аргументов является указателем на строку(ведь здесь же сработал брекпоинт).Лучше всего использовать отладчик,т.к. экономится время на анализе, однако если не поможет, то IDA.


.text:0049BB60 sub_49BB60      proc near               ; CODE XREF: sub_497948+28p
 .text:0049BB60 
 .text:0049BB60 arg_0           = dword ptr  8		>>0
 .text:0049BB60 arg_4           = dword ptr  0Ch		>>1
 .text:0049BB60 
 .text:0049BB60                 push    ebp
 .text:0049BB61                 mov     ebp, esp		>>2
 .text:0049BB63                 push    edi
 .text:0049BB64                 push    esi
 .text:0049BB65                 push    ebx		>>3
 .text:0049BB66                 mov     esi, [ebp+arg_4]
 .text:0049BB69                 mov     edi, [ebp+arg_0] >>4 
 .text:0049BB6C                 mov     al, 0FFh
 .text:0049BB6E                 mov     edi, edi
 .text:0049BB70 
 .text:0049BB70 loc_49BB70:                             ; CODE XREF: sub_49BB60+20j
 .text:0049BB70                                         ; sub_49BB60+40j
 .text:0049BB70                 or      al, al
 .text:0049BB72                 jz      short loc_49BBA6 5>>
 .text:0049BB74                 mov     al, [esi]	   	
 .text:0049BB76                 add     esi, 1
 .text:0049BB79                 mov     ah, [edi]
 .text:0049BB7B                 add     edi, 1
 .text:0049BB7E                 cmp     ah, al
 .text:0049BB80                 jz      short loc_49BB70	5>>
 .text:0049BB82                 sub     al, 41h		6>>
 .text:0049BB84                 cmp     al, 1Ah
 .text:0049BB86                 sbb     cl, cl
 .text:0049BB88                 and     cl, 20h
 .text:0049BB8B                 add     al, cl
 .text:0049BB8D                 add     al, 41h
 .text:0049BB8F                 xchg    ah, al
 .text:0049BB91                 sub     al, 41h
 .text:0049BB93                 cmp     al, 1Ah
 .text:0049BB95                 sbb     cl, cl
 .text:0049BB97                 and     cl, 20h
 .text:0049BB9A                 add     al, cl
 .text:0049BB9C                 add     al, 41h		
 .text:0049BB9E                 cmp     al, ah
 .text:0049BBA0                 jz      short loc_49BB70 6>>
 .text:0049BBA2                 sbb     al, al		
 .text:0049BBA4                 sbb     al, 0FFh		
 .text:0049BBA6 
 .text:0049BBA6 loc_49BBA6:                             ; CODE XREF: sub_49BB60+12j
 .text:0049BBA6                 movsx   eax, al		7>>
 .text:0049BBA9                 pop     ebx
 .text:0049BBAA                 pop     esi
 .text:0049BBAB                 pop     edi
 .text:0049BBAC                 leave		
 .text:0049BBAD                 retn
 .text:0049BBAD sub_49BB60      endp


Внимательно посмотрите на код из IDA,а именно на арифметические выражения: add esi,1 и add edi,1 .... Я не знаю компилятор, который бы сгенерил такой бред. add esi,1 ТРИ БАЙТА!!!!! inc esi ОДИН БАЙТ!!!! Не товарищи, тут не у компилятора руки кривые, это у того кто писал этот код, причём на ассемблере и по всей видимости наспех. И как вы думаете какому программеру прийдет в голову делать вставку на асме если пишеш на С++. Правильно, ленивому... свой hash-мейкер придумывать впадлу, вот и вставили чей-то алгоритм даже не смотря на него. Кстати если есть желание можно посмотреть в BoundsCheker на предмет справедливости моих слов...у меня его небыло(желания):). Ну да ладно...
0>> указатель на наш Unlock Code
1>> указатель на пустую строку при вызове процедуры и на какую-то строку (hash) опосля процедуры.Кстати попробуйте её ввести как Unlock Code... Гы...Гы...
2>> Стандартный пролог функции.
3>> Сохраняем используемые регистры
4>> Инициализация регистров
5>> Ой циклик , а чего делает? побайтово сравнивает две строчки, если очередные байты НЕ равны, то см. 6>> а если равны, то:) Причём хитро... описание коанды OR: команда выполняет операцию логического ИЛИ над соответствующими парами бит операндов...флаги CF=OF=0 (ОЧЕНЬ важно) SF,ZF,AF,PF по результату выполнения операции. Т.е. если результат комманды 0 (только если ОБА операнда 0, а значит мы имеем полностью совпавшие строки,т.к. 0 конец строки), то ZF=1 отсюда и переход. Причём 0 не имеет знака(старший бит ведь тоже 0),а соответственно и SF = 0.
6>> Смотри за моими пальцами...:) сравните код до xchg ah, al и после... КОПИЯ... то есть если над одинаковыми числами провести одинаковые операции то получится....правильно другие числа ... но одинаковые , дальше веселее... Проведите над двумя НЕ одинаковыми числами (а после цикла они НЕ одинаковые) одинаковые операции чего получится...правильно НЕ одинаковые числа и переход jz short loc_49BB70 !!!НИКОГДА!!! не выполнится. Логическая бомба блин....
7>> Тута формируем результат функции. Особо вникать, что функция вернёт если строки не равны я думаю не стоит, так как нам достаточно знать что она вернёт 0 при правильном результате.

Нда замутил... однако очень полезно думать. Кто ничё не понял читаем описание мнемоник кода для x86 процессоров.
Вот такая функция проверки. Исполнение по-моему довольно оригинально. Кстати по поводу add esi,1 : разница между add esi,1 и inc esi кроме размера в том что inc не воздействует на флаг переноса CF, ну так и использовали бы в защите, а не в качестве индексов массива...для того чтобы возникло переполнение длина строки должна быть 2^32.

Ну чё не надоело читать, а то мона уже регестрировать подсмотренным Unlock Code...хотя он тока для Basic версии и снимает тока ограничение по времени использования.А самые догадливые заметили, что сия функция вызывается ещё 2 раза,и arg_4 содержит другие пасворды.

Ладно терпеливые вы мои поехали дальше. Теперя охота узнать откуда появился arg_4 (правильный Unlock Code), а для етого нада узнать откуда процедура вызывалась. Как сие провернуть расказывалось ранее.

А процедура вызывается по адресу cs:497970. Лезем в IDA.
Маленький фрагмент:

.text:0049796A                 push    [ebp+arg_4]
 .text:0049796D                 push    [ebp+arg_0]
 .text:00497970                 call    sub_49BB60

видно что указатели на строки являются аргументами функции sub_497948, в теле которой происходит вызов sub_49BB60.
Посмотрим вверх на наличие изменений этих строк...должно быть нечто вроде lea esi,[ebp+arg_4]. Чегото не видать, а сие значит что они и не меняются.Тогда посмотрим откуда вызывается sub_497948.
Ага вызов cs:48e8be в функции sub_48E896 ...нда ситуация абсолютна аналогична предидущей - строки не меняются.

ТЕРПЕНИЕ я думаю одно из главных качеств кодокопателя... после желания чего-то добиться естественно.

Итак вызов по адресу cs:40FFD7 в функции... ни!"№я себе функция sub_40FBA0. ОГО. Отето размерчик... Ну да ладно...
Лезте в IDA. Углядели вызов функции по адресу .text:40FFD7. Ой а чего это рядом (чуть ниже) перекрёстные ссылочки какиета интересныя...

.text:0040FFE6 push offset aUnlockCode ; "Unlock Code"
.text:0040FFEB push offset aRegistration ; "Registration"

.text:0040FFFF push offset aYouHaveSuccess ; "You have successfully registered the Ba"...
Ням-Ням... Во какие вкусности.
Чуетца аромат зажаренной до хрустящей корочкой... защиты.

Ладно давайте выеснять откель взялись аргументы для нашей функции sub_48E896.
Ага один аргумент в локальной переменной ,а второй нипойми откуда.

.text:0040FFCF                 mov     eax, [edi]
 .text:0040FFD1                 lea     edx, [esp+490h+var_478]
 .text:0040FFD5                 push    edx
 .text:0040FFD6                 push    eax
 .text:0040FFD7                 call    sub_48E896
Так теперь определим ху из ху. Отладчиком проще.Установим бряк на 0040FFD5, а затем посмотрим чего ма засылаем в стек d edx и d eax.
Итак push edx - это засылка в стек указателя на искомую строку , а push eax введённую нами от балды.
Нас интересует откуда берётся искомая строка.Посмотрим...из переменной var_478. Где она изменяется?

.text:0040FFC1                 mov     eax, [ebp+0]
 .text:0040FFC4                 lea     ecx, [esp+488h+var_478]
 .text:0040FFC8                 push    ecx
 .text:0040FFC9                 push    eax
 .text:0040FFCA                 call    sub_403CF0

О она в качестве аргумента передаётся функции sub_403CF0.
Давайте потрошить :)


.text:00403CF0 sub_403CF0      proc near               ; CODE XREF: sub_40FBA0+A1p
 .text:00403CF0                                         ; sub_40FBA0+42Ap
 .text:00403CF0 
 .text:00403CF0 var_C           = byte ptr -0Ch
 .text:00403CF0 var_4           = byte ptr -4
 .text:00403CF0 arg_0           = dword ptr  4
 .text:00403CF0 arg_4           = dword ptr  8
 .text:00403CF0 
 .text:00403CF0                 sub     esp, 0Ch
 .text:00403CF3                 mov     eax, [esp+0Ch+arg_0]
 .text:00403CF7                 push    8
 .text:00403CF9                 inc     eax
 .text:00403CFA                 push    eax
 .text:00403CFB                 lea     ecx, [esp+14h+var_C]
 .text:00403CFF                 push    ecx
 .text:00403D00                 call    sub_48D200
 .text:00403D05                 lea     edx, [esp+18h+arg_0]
 .text:00403D09                 push    edx
 .text:00403D0A                 lea     eax, [esp+1Ch+var_C]
 .text:00403D0E                 push    offset a08x     ; "%08x"
 .text:00403D13                 push    eax
 .text:00403D14                 mov     [esp+24h+var_4], 0
 .text:00403D19                 call    sub_48D720
 .text:00403D1E                 mov     eax, [esp+24h+arg_0]
 .text:00403D22                 xor     eax, 3D9F4A7Dh
 .text:00403D27                 mov     ecx, eax
 .text:00403D29                 shl     ecx, 1Bh
 .text:00403D2C                 shr     eax, 5
 .text:00403D2F                 add     ecx, eax
 .text:00403D31                 push    ecx
 .text:00403D32                 mov     [esp+28h+arg_0], ecx
 .text:00403D36                 mov     ecx, [esp+28h+arg_4]
 .text:00403D3A                 push    offset a04x     ; "%04x"
 .text:00403D3F                 push    ecx
 .text:00403D40                 call    sub_48D6C8
 .text:00403D45                 xor     eax, eax
 .text:00403D47                 add     esp, 30h
 .text:00403D4A                 retn
 .text:00403D4A sub_403CF0      endp


Смотрим внимательно! Опять арефметические действия подозрительного характера! И подозрительного вида перекрёстные ссылки. Обычно такие иcпользуются при форматировании строк.
Итак функция возвращает всегда 0, о чём свидетельствует .text:00403D45 xor eax, eax - наверное тип результата void.
В отладчике смотрим какие аргументы получает функция.
Имеем arg_0 указатель на строку (до боли похожую на Serial Number), а в arg_4 (методом исключения) указатель на строку для генерации Unlock Code.
Вот собственно и нашли процедуру, в которой происходит генерация Unlock Code.
Так, теперь нам нужно разрешить функциональные зависимости. Рассмотрим sub_48D200 по накатанной схеме.
Аргументами являются указатель на Serial Number и локальная переменная какая-то и константа 8. А хде возгласы возмущения?
Что прошляпили?

.text:00403CF3                 mov     eax, [esp+0Ch+arg_0]
 .text:00403CF7                 push    8
 .text:00403CF9                 inc     eax
 .text:00403CFA                 push    eax
 .text:00403CFB                 lea     ecx, [esp+14h+var_C]
 .text:00403CFF                 push    ecx
 .text:00403D00                 call    sub_48D200

А inc eax? Хех, стало быть в eax указатель на первый (не нулевой!) байт Serial Number. Константа странная... У вас какая длина Serial Number? У меня 8. Может быть это длина,а может и нет. Локальную переменную зачем-то запихивают. Скорее всего там результат работы функции. Посмотрим в отладчике что там будет после того, как функция отработала. Цифры какие-то... А если сравнить эти цифры со строкой Serial Number. Напрягите воображение. Ну... напрягается? Нет? Тогда пойдите попейте пифка али кофе, покурите, дефку румяную полюбите (или кто вам там по душе),а потом ещё раз напрягайтесь.
Правильно, по адресу в var_C имеем теже самые цифры что и в [Serial Number+1], тока в шестнадцатеричном виде. Отсель вывод, что sub_48D200 есть ни что иное как аналог API функции atoi(Ansi TO Integer). Как видите не всегда обязательно копаться в коде и понимать логику его работы. Нередко внимательность к аргументам функций и капелька смекалки помогут вам сэкономить массу времени.

Поехали дальше.Фунуция sub_48D720.

.text:00403D05                 lea     edx, [esp+18h+arg_0]
 .text:00403D09                 push    edx
 .text:00403D0A                 lea     eax, [esp+1Ch+var_C]
 .text:00403D0E                 push    offset a08x     ; "%08x"
 .text:00403D13                 push    eax
 .text:00403D14                 mov     [esp+24h+var_4], 0
 .text:00403D19                 call    sub_48D720


Аргументы: Указатель на указатель(о как!) на строку с Serial Number, указатель на константу, локальная переменная содержащая в шестнадцатеричном виде [Serial Number+1].
Посмотрим в отладчике, что изменилось после выполнения функции. Указатель на указатель(японский бог) затёрся значением [Serial Number+1] в шестнадцатеричном виде, а всё остальное осталось без изменения.Нда оказывается .text:00403D05 lea edx, [esp+18h+arg_0] не что иное как создание локальной(временной) переменой в стеке. Остальное вроде не поменялось.
Смотрим дальше.


.text:00403D1E                 mov     eax, [esp+24h+arg_0]	>>0 
 .text:00403D22                 xor     eax, 3D9F4A7Dh		>>1
 .text:00403D27                 mov     ecx, eax			>>2
 .text:00403D29                 shl     ecx, 1Bh			>>3
 .text:00403D2C                 shr     eax, 5			>>4
 .text:00403D2F                 add     ecx, eax			>>5
 .text:00403D31                 push    ecx			>>6
 .text:00403D32                 mov     [esp+28h+arg_0], ecx	>>7

>>0 Загружаем значение нашей временной переменной (обзовём её var)
eax = var
>>1 eax = eax ^ 0x3D9F4A7D
>>2 ecx = eax
>>3 ecx = ecx << 0x1B
>>4 eax = eax >> 5
>>5 ecx = ecx + eax

>>6 это агргумент для следующей функции
>>7 и сохраняем наш хеш во временную переменную.

Ну а теперь приведём всё в более читабельный вид.
Введём для удобства переменную TMP
TMP = var ^ 0x3D9F4A7D;
ecx = (TMP<<0x1B) + (TMP>>0x5);
Вот...
Проследим в отладчике за параметрами sub_48D6C8.

.text:00403D31                 push    ecx
 .text:00403D32                 mov     [esp+28h+arg_0], ecx
 .text:00403D36                 mov     ecx, [esp+28h+arg_4]
 .text:00403D3A                 push    offset a04x     ; "%04x"
 .text:00403D3F                 push    ecx
 .text:00403D40                 call    sub_48D6C8


Ага... arg_4 теперь указывает на наш хеш, представленный в виде строки,т.е. sub_48D6C8 есть аналог API функции itoa (Integer TO Ansi).

Вот мы и разобрали с вами алгоритм генерации ключа для Basic версии.
Вернёмся в IDA к sub_40FBA0. И посмотрим на перекрёстные ссылочки вида
.rdata:004D145C aYouHaveSuccess db ’You have successfully registered the Basic version of LC5.’,0
Оказывается в ресурсах упоменается ещё о Professional и Administrator версиях.

Теперь подумаем, как бы их найти.


.text:0040FFD1                 lea     edx, [esp+490h+var_478]
 .text:0040FFD5                 push    edx
 .text:0040FFD6                 push    eax
 .text:0040FFD7                 call    sub_48E896      ; сравнение строк
 .text:0040FFDC                 add     esp, 10h
 .text:0040FFDF                 test    eax, eax
 .text:0040FFE1                 jnz     short loc_410026


Смотрим в IDA куда пошлёт наc переход после сравнения Unlock Code для версии Basic с неверно нами введённым кодом? Что будет если код введён правильно мы знаем - получим зарегистрированную Basic версию.
Преходим на вот такой фрагментик.

.text:00410026 loc_410026:                             ; CODE XREF: sub_40FBA0+441j
 .text:00410026                 mov     eax, [ebp+0]
 .text:00410029                 lea     ecx, [esp+488h+var_478]
 .text:0041002D                 push    ecx
 .text:0041002E                 push    eax
 .text:0041002F                 call    sub_403DB0
 .text:00410034                 mov     eax, [edi]
 .text:00410036                 lea     edx, [esp+490h+var_478]
 .text:0041003A                 push    edx
 .text:0041003B                 push    eax
 .text:0041003C                 call    sub_48E896
 .text:00410041                 add     esp, 10h
 .text:00410044                 test    eax, eax
 .text:00410046                 jnz     loc_4100F6
 .text:0041004C                 push    ebx
 .text:0041004D                 lea     ecx, [esp+48Ch+var_364]
 .text:00410054                 call    sub_41BB80

Вы только посмотрите! Функции sub_403DB0 зачем-то потребовалась строка с кодом для Basic версии. Зачем? посмотрите что у неё в утробе:)

.text:00403DB0 sub_403DB0      proc near               ; CODE XREF: sub_40FBA0+E0p
 .text:00403DB0                                         ; sub_40FBA0+48Fp
 .text:00403DB0 
 .text:00403DB0 var_C           = byte ptr -0Ch
 .text:00403DB0 var_4           = byte ptr -4
 .text:00403DB0 arg_0           = dword ptr  4
 .text:00403DB0 arg_4           = dword ptr  8
 .text:00403DB0 
 .text:00403DB0                 sub     esp, 0Ch
 .text:00403DB3                 mov     eax, [esp+0Ch+arg_0]
 .text:00403DB7                 push    8
 .text:00403DB9                 inc     eax
 .text:00403DBA                 push    eax
 .text:00403DBB                 lea     ecx, [esp+14h+var_C]
 .text:00403DBF                 push    ecx
 .text:00403DC0                 call    sub_48D200
 .text:00403DC5                 lea     edx, [esp+18h+arg_0]
 .text:00403DC9                 push    edx
 .text:00403DCA                 lea     eax, [esp+1Ch+var_C]
 .text:00403DCE                 push    offset a08x     ; "%08x"
 .text:00403DD3                 push    eax
 .text:00403DD4                 mov     [esp+24h+var_4], 0
 .text:00403DD9                 call    sub_48D720
 .text:00403DDE                 mov     eax, [esp+24h+arg_0]
 .text:00403DE2                 xor     eax, 8132FF17h
 .text:00403DE7                 mov     ecx, eax
 .text:00403DE9                 shl     ecx, 1Bh
 .text:00403DEC                 shr     eax, 5
 .text:00403DEF                 add     ecx, eax
 .text:00403DF1                 push    ecx
 .text:00403DF2                 mov     [esp+28h+arg_0], ecx
 .text:00403DF6                 mov     ecx, [esp+28h+arg_4]
 .text:00403DFA                 push    offset a04x     ; "%04x"
 .text:00403DFF                 push    ecx
 .text:00403E00                 call    sub_48D6C8
 .text:00403E05                 xor     eax, eax
 .text:00403E07                 add     esp, 30h
 .text:00403E0A                 retn
 .text:00403E0A sub_403DB0      endp

Называется найди одно отличие:) С детсва обожал искать отличия на всякого рода картинках.
Нашли? Нет? Потренеруйтесь тогда на картинках:)

3.General Protection Fault или вместо заключения.


Как стало видно из всего выше описанного защита сначала генерирует ключ на основе Serial Number для версии Basic, затем на основе полученного ключа для версии Pro и так далее.
Процедуры генерации ключей однотипны, и различаются лишь одним 4-х байтным полиномом, учавствующим в формировании очередного ключа. Писать кейген? Ну напишите... мне не интересно.
Усё. Пошёл пить пиво и любить жену.
Надеюсь эта статья вам немного помогла разобраться в кодокопании.

Коминг сун:

0. Гарант или вскрытие выродка.
1. XOR всему голова или что делают на www.security.ru

Обсуждение статьи: Пишем кейген для @stake LC 5 v5.00 >>>


Комментарии к статье: Пишем кейген для @stake LC 5 v5.00

Ara 01.07.2005 00:55:45
E-моё, прочитал только раздел \"Инструменты\", дальше не стал - слишком много. На дворе 2005 год, инструменты морально устарели =)

---
dinisok 01.07.2005 01:23:35
cooooooool!
Мне бы так!

---
Devastator 01.07.2005 10:11:30
Ara
Я вот с ностальгией вспоминаю debuger.com
Некоторые вещи иногда даже в нём смотрю.
А вообще-то ты наверное пропустил ЦЕЛЬ СТАТЬИ.

---
ValdiS 01.07.2005 11:37:16
Сама статья классная, ничего не скажешь. Но сленг...
---
ViNCE 01.07.2005 16:00:34
Слэнг - аля старые туторы по реверсингу + свои метаморфизмы %)
---
Devastator 01.07.2005 16:07:32
Люди, будте благосклонны - я не филолог и по русскому языку у меня была тройка. Сленг такой потому что на душе так было, ведь от души писал. Конечно излагать мозно и без сленга, но по-моему занудно получиться.
---
new 02.07.2005 13:28:45
\"На дворе 2005 год, инструменты морально устарели\"
Какая хрен разница в инструментах самое главное, это знания......
---
Ara 02.07.2005 17:30:48
Какая хрен разница в инструментах самое главное, это знания (ц)
Разница существенная - новички, читая статью и предложенные инструменты, начнут искать точно такие же, задавая попутно вопросы, почему не хочет работать SI 4.05 и т.п.

А вообще-то ты наверное пропустил ЦЕЛЬ СТАТЬИ. (ц)
Вовсе нет. Название статьи-Пишем кейген, а в самом конце - пишите сами, мне лень. Название не соответствует теме статьи. :)
---
Devastor 04.07.2005 18:35:28
Ara
Название статьи-Пишем кейген, а в самом конце - пишите сами, мне лень. Название не соответствует теме статьи. :) (ц)
Да, есть название статьи И(&) есть цель статьи. По поводу того что дело не доведено до конца Вы АБСОЛЮТНО ПРАВЫ.
И Ваше утверждение о несоответствии названия и конечному результату АБСОЛЮТНО ПРАВОМЕРНО(а как стоило назвать статью?).
Уважаемый Ara я НАМЕРЕННО не стал опубликовывать код кейгена(и я надеюсь мне никогда этого не доведётся делать). Пусть читатель САМ это сделает,т.к. я считаю это заставит его ДУМАТЬ и ВНИКАТЬ!
По поводу моей лени выводы пусть каждый делает для себя сам.
Как говорил один человек(или не человек) я могу показать дверь,а открывать ты должен сам.
Ara огромное Вам спасибо за обоснованную критику. Так и надо!!!!! Я ведь тоже чему-то учусь.
Мой вам респект.
---
InsidePro 09.07.2005 19:00:44
\"... Усё. Пошёл пить пиво и любить жену.\"
Джигит!

А за статью - спасибо.
---
Ruslan 20.07.2005 17:27:28
Я эту прогу еще в январе поломал минуты за две и легче раз в 100!!! Если интересно
пиши.
---
retailer2006 30.08.2008 06:37:53
Авторам статей....заливайте свои проги (и те чем пользуетесь, и то что исследуете) куда нить на стороний сайт. По вашим ссылкам вот сейчас мне (на дворе 2008 год) этой проги врятли найти. Вот автор specz заливает в текст ссылки на стороние сайты, проги и инструменты (кстати проги именно тех версий которые исследуются), все качаеться без проблем. Не то что тут. Статья норм, ток сделать так-же не могу, нет исследуемой проги :(
---

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



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


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