Теперь необходимо понять каким образом создается сам ключ и собственно написать кейген.
Итак, вернемся назад, к началу функции по адресу 009C27D0 и начнем разбираться.
Протрейсим ее еще раз, но теперь всем вызовам будем давать имя.
Тот вызов что вываливает в HexView циферки по адресу 009C2891 - будет называться create_numer
Вызов который на выходе показывает буковки по адресу 009C289C - будет называться Create_code
А вызов функции который делает буковки заглавными по адресу 009C28B3 - будет называться Upper_string
Если проскроллить вниз, то можно увидеть, что эти функции встречаются еще 3 раза. Это подтверждает, что серийник состоит из 4х частей. Только если приглядется, 1 часть, очень длинная и похоже там производится инициализация расчетов.
Возвращаемся снова к началу функции и начинаем ее выполнять по шагам.
Первым делом обращаем внимание на код типа
.text:009C2816 mov eax, 2AAAAAABh
.text:009C281B imul esi
Как я говорил в предыдущей части, если есть некие константы вшитые в код, то это не спроста.
В этом коде производится умножение eax на esi. Причем в esi находится значение 04D2h. Тут у меня в голове щелкнуло и я запустил калькулятор, если перевести десятичнку цифру 1234 в шеснадцетиричный, то получится как раз 04D2h. Вот и наше введеное iD. Позапускав несколько раз программу и повводя в нее разные циферки, я понял, что этой функции передается параметр через ecx следующим кодом.
.text:009C2517 mov ecx, [esp+240h+var_22C] ; тут и передается число в HEX
.text:009C251B add esp, 4
.text:009C251E call Enter_String_SE ; а это вызов функции расчета серийника
Как я писал раньше, я забил на выяснение, где и как преобразуется эта строчка, сделав упор на разбор самого алгоритма вычисления серийника.
Делаем вывод, что надо внимательно смотреть какие операции делаются с ecx. В принципе дальше все просто, надо тупо выписывать все операции связанные с ecx в отдельный файлик, или сразу как я копировать генерацию в код, по этому буду показывать уже на своем кейгене.
KeyGen proc num:DWORD ;######## init calc and part 1 invoke GetSystemTime, offset systime ; get system time xor esi, esi ; clear esi mov eax, num ; in eax put number in HEX mov esi, eax ; copy eax in esi cdq ; clear edx and edx, 0fh ; edx = edx AND 0Fh lea ecx, [edx+eax] ; ecx = edx + eax mov eax, 2AAAAAABh ; eax = 2AAAAAABh imul esi ; eax = eax * esi sar edx, 2 ; edx right shift on 2 mov eax, edx ; eax = edx shr eax, 1Fh ; eax right shift on 1Fh add eax, edx ; eax = eax + edx imul eax, esi ; eax = eax * esi mov serialtmp1, eax ; remember eax in serialtmp1 mov eax, esi ; eax = esi cdq ; clear edx and edx, 1Fh ; edx = edx AND 1Fh lea edi, [edx+eax] ; edi = edx + eax xor ebx, ebx ; clear ebx mov bx, WORD PTR [systime] ; in bx put current Year in HEX(DEC 2013 == HEX 07DD) mov eax, 66666667h ; eax = 66666667h imul esi ; eax = eax * esi sar edx, 4 ; edx right shift on 4 mov eax, edx ; eax = edx shr eax, 1Fh ; eax right shift on 1Fh add eax, edx ; eax = eax + edx imul eax, esi ; eax = eax * esi sar edi, 5 ; edi right shift on 5 imul edi, esi ; edi = edi * esi sar ecx, 4 ; ecx right shift on 4 imul ecx, esi ; ecx = ecx * esi add ebx, eax ; ebx = ebx + eax add ebx, edi ; ebx = ebx + eedi add ebx, serialtmp1 ; ebx = ebx + serialtmp1 mov serialtmp2, eax ; remember eax in serialtmp2 add ebx, ecx ; ebx = ebx + ecx mov serialtmp3, ecx ; remember ecx in serialtmp3 lea ecx, [eax+17h] ; ecx = eax+17h mov eax, ebx ; eax = ebx cdq ; clear edx idiv ecx ; eax = eax / ecx mov serialtmp4, edi ; remember edi in serialtmp4 invoke HEX2DEC, edx ; convert HEX in ASCII number invoke CreateSerial, eax, ecx, offset serial ; generate string for 1 part serial mov BYTE PTR [edi], 2Dh ; add in serial string dymbol "-" ;######## calc part 2 mov ecx, serialtmp4 ; put in ecx serialtmp4 mov eax, ebx ; eax = ebx cdq ; clear edx add ecx, 13h ; ecx = ecx + 13h idiv ecx ; eax = eax / ecx invoke HEX2DEC, edx ; convert HEX in ASCII number inc edi ; move position in serial on 1 invoke CreateSerial, eax, ecx, edi ; generate string for 2 part serial mov BYTE PTR [edi], 2Dh ; add in serial string dymbol "-" ;######## calc part 3 mov ecx, serialtmp1 ; put in ecx serialtmp1 mov eax, ebx ; eax = ebx cdq ; clear edx add ecx, 0Fh ; ecx = ecx + 0Fh idiv ecx ; eax = eax / ecx invoke HEX2DEC, edx ; convert HEX in ASCII number inc edi ; move position in serial on 1 invoke CreateSerial, eax, ecx, edi ; generate string for 3 part serial mov BYTE PTR [edi], 2Dh ; add in serial string dymbol "-" ;######## calc part 4 mov ecx, serialtmp3 ; put in ecx serialtmp3 mov eax, ebx ; eax = ebx cdq ; clear edx add ecx, 25h ; ecx = ecx + 25h idiv ecx ; eax = eax / ecx invoke HEX2DEC, edx ; convert HEX in ASCII number inc edi ; move position in serial on 1 invoke CreateSerial, eax, ecx, edi ; generate string for 4 part serial ret KeyGen endpМне честно говоря сложно перевести это все в псевдокод, но в принципе тут все достаточно понятно.
Теперь посмотрим на процедуру, которая переводит ключевое число в строку буков, которые и являются частью серийника.
CreateSerial proc uses ebx num:DWORD, count:DWORD, pPos:DWORD mov esi, num ; in esi number mov edi, pPos ; in edi position on serial xor ecx, ecx ; clear ecx mov ebx, count ; in ebx count digits shr ebx, 1 ; right shift on 1 @@: .if ecx <= ebx ; if ecx <= ebx mov al, BYTE PTR [esi] ; on al put digit on temp ASCII number add al, 32h ; al = al + 32h .elseif mov al, BYTE PTR [esi] ; on al put digit on temp ASCII number add al, 3Ch ; al = al + 3Ch .endif sub al, 20h ; upper symbol al = al - 20h mov BYTE PTR [edi], al ; put cymbol in serial inc ecx ; ecx = ecx + 1 inc esi ; esi = esi + 1 inc edi ; edi = edi + 1 .if ecx >= count ; if curent position bigger or eq count jmp @f ; exit .endif jmp @b ; next digit @@: ret CreateSerial endpТут проще, можно расписать алгоритм на русском.
Сначало берется общее количество цифр в ключевой номере и сдвигается в право на 1 и поместим получившееся в ebx.
После чего сравнивается с текущей позицией, если текущая позиция меньше или равна с ebx, то к 16ричному значению текущий цифры в номере прибавляется 32h. если же меньше, то прибавляется 3Ch. Ну и т.д. пока не кончатся цифры в текущем наборе.
На этом в принципе и все, кейгенми достаточно простой, хоть и стоит оценка сложности в 3.
Яб поставил не больше двойки за такое, так как все достаточно просто отыскивается. Целиком мой кодъ кейгена можно посмотреть на депозите.
Комментариев нет:
Отправить комментарий