Исследуем Lavalys Everest Ultimate Edition 2006 v.3.01.652 и пишем KeyGen
Обсудить статью на форуме Очень удобно, когда все крэкерские инструменты, книги и статьи в одном месте. Используйте сборник от EXELAB - вот тут.
Автор: RSI <RS1@tut.by>
Привет Всем! Как уже принято писать начинающим в этом «нелегком» деле, «Это моя первая статья….» и т.д. и. т.п., поэтому не будем особо на этом останавливаться, просто отнеситесь к этому с пониманием! И к орфографии, которая периодически хромает... ;)
И так приступим, нам понадобится:
1) OllyDbg 1.10
2) PEiD v0.93
3) Visual C++ 6.0 SE (для написания Keygen)
4) UPX 1.90w
5) И немножко выдержки и терпения
О самой программе: (сайт проги www.lavalys.com)
Эта программа для диагностики и теста вашего железа ,там еще есть всякие полезные фичи… В целом прикольная программа иногда приходится пользоваться :)
Что нам не нравится:
1) Выскакивает NAG окно из трея где написано, что это Триал
2) В заголовке окна присутствует надпись [Trial version]
3) Не выводится некоторая информация о системе и железе
4) Срок действия программы 3 месяца
Ну чтож попробуем от этого избавится!!!
Проверка программы на упакованность:
PEiD нам показывает UPX 0.89.6 - 1.02 / 1.05 - 1.24 -> Markus & Laszlo,
но только настораживает что размер такого exe файла всего 42 Kb, для такой многофункциональной программы это очень мало
(скорее всего программа либо юзает DLL или где-то еще есть исполняемый модуль), ну ладно, не будем загоняться, а посмотрим что там!
Для распаковки используем UPX 1.90w (т.к. 1.24 у меня отказался ее распаковать)!
В командной строке пишем: upx.exe –d everest.exe (теперь размер распакованного файла 75 Кб)
Итак грузим распакованный everest.exe в OllyDbg и немножно потрейсим по F8, Дойдем вот до такой функции:
004015E1 > 6A 0A PUSH 0A
004015E3 . 59 POP ECX
004015E4 > 51 PUSH ECX ; /Arg4
004015E5 . 50 PUSH EAX ; |Arg3
004015E6 . 6A 00 PUSH 0 ; |Arg2 = 00000000
004015E8 . 68 00004000 PUSH everest.00400000 ; |Arg1 = 00400000
004015ED . E8 0EFAFFFF CALL everest.00401000 ; \everest.00401000
После нее запускается наша программа, поэтому интересно посмотреть, что эта функция делает. Для этого на адрес 004015ED ставим бряк(F2)
и перезапускаем программу (Ctrl+F2), нажимаем F9 чтобы запуститть программу, прервались на нашем бряке, теперь чтобы зайти во внутрь функции нажимаем F7, и дальше продолжаем трейсить по F8, идем дальше и натыкаемся на такой кусок:
0040117A |. 50 PUSH EAX ; /pProcessInfo
0040117B |. 8D8D 50FEFFFF LEA ECX,DWORD PTR SS:[EBP-1B0] ; |
00401181 |. 51 PUSH ECX ; |pStartupInfo
00401182 |. 6A 00 PUSH 0 ; |CurrentDir = NULL
00401184 |. 6A 00 PUSH 0 ; |pEnvironment = NULL
00401186 |. 6A 00 PUSH 0 ; |CreationFlags = 0
00401188 |. 6A 01 PUSH 1 ; |InheritHandles = TRUE
0040118A |. 6A 00 PUSH 0 ; |pThreadSecurity = NULL
0040118C |. 6A 00 PUSH 0 ; |pProcessSecurity = NULL
0040118E |. FF15 08804000 CALL DWORD PTR DS:[<&KERNEL32.GetCommand>; |[GetCommandLineA
00401194 |. 50 PUSH EAX ; |CommandLine
00401195 |. 68 90B44000 PUSH everest.0040B490 ; |ModuleFileName = ""
0040119A |. FF15 04804000 CALL DWORD PTR DS:[<&KERNEL32.CreateProc>; \CreateProcessA
004011A0 |. 85C0 TEST EAX,EAX
004011A2 |. 74 2A JE SHORT everest.004011CE
004011A4 |. 68 5C814000 PUSH everest.0040815C ; ASCII "/WAIT"
004011A9 |. 8B55 10 MOV EDX,DWORD PTR SS:[EBP+10]
004011AC |. 52 PUSH EDX
Немного теории:
Функция CreateProcessA – создает новый процесс, из исполняемого файла! То есть в данном случае эта функция запускает файл everest.bin
(как исполняемый .exe)! Значит, как мы и предполагали, главный исполняемый файл – это everest.bin, поэтому закрываем файл в OllyDbg (Alt+F2),
удаляем файл everest.exe, он нам больше не нужен, затем переименовываем файл everest.bin в everest.exe - далее мы будем работать уже с ним!
Он тоже запакован UPX 0.89.6 - 1.02 / 1.05 - 1.24 -> Markus & Laszlo, но у этого размер уже посолидней (1,5 Mb) :) !!! Продолжаем…
Распакуем его, для этого опять пишем: upx.exe -d everest.exe
Смотрим в PeiD и видим Borland Delphi 6.0 - 7.0 – это хорошо! (Теперь после распаковки файл весит аж 4,5 Mb)
Итак грузим файл в OllyDbg и запускаем(F9). Все запустилось…
Ну что будем регить? Но есть загвоздка - нет вкладки для ввода серийника… :(
Ну что попробуем подумать ( логика так сказать :) )! Значит при запуске прога проверяет наличие какого-нибудь ключа
после чего появляются надписи [Trial Version]!
Полез в инет посмотреть мож есть кряки на ранюю версию этой проги и скачал keygen powered by VRL forse (для версии 2.50.480).
Запустил, вписал свое свое имя «RSI» и в папке с keygen-ом появился файл everest.key - ага значит вот какой ключ должен быть!!!
На всякий случай попробовал: переписал файл в папку с прогой и запустил - авось ключ подойдет :), но облом!
Вываливается собщение:
KEY file of this product is modified or corrupted
Product has reverted back to Evaluation mode
Значит нам надо искать место, где прога открывает файл everest.key и проверяет его! Попробуем в OllyDbg поискать строку с именем файла.
Жмем(Ctrl+B) в поле ASCII вводим everest.key и OK – ничего! Ладно, значит она потом в процессе «собирается» или зашифрована, чтобы мы ее не нашли!
Теперь есть 2 пути:
1)Будем пробовать искать строки содержащие имя или расширение KEY файла
2)Если пункт 1 не помог, тогда будем ставить бряки на функции открытия или чтения файлов (такие как CreateFileA, OpenFile, ReadFile и др…..)
Начнем с пункта 1 - попробуем поискать «.key» и:
сначала находим какие-то
URL http://www.keytronic.com/home/keyboards/mice/mice.html, но нам это не надо, поэтому ищем дальше (Ctrl+L) и через пару раз – о ДА!!! Ура! Есть такая строчка, поднимемся выше и бряк(F2) на начало той функции по адресу 0075E858:
0075E858 /$ 55 PUSH EBP ; <- Начало функции
0075E859 |. 8BEC MOV EBP,ESP
0075E85B |. B9 46000000 MOV ECX,46
0075E860 |> 6A 00 /PUSH 0
0075E862 |. 6A 00 |PUSH 0
0075E864 |. 49 |DEC ECX
0075E865 |.^75 F9 \JNZ SHORT everest.0075E860
0075E867 |. 53 PUSH EBX
0075E868 |. 56 PUSH ESI
0075E869 |. 57 PUSH EDI
0075E86A |. 8BD8 MOV EBX,EAX
0075E86C |. 33C0 XOR EAX,EAX
0075E86E |. 55 PUSH EBP
0075E86F |. 68 FEEC7500 PUSH everest.0075ECFE
0075E874 |. 64:FF30 PUSH DWORD PTR FS:[EAX]
0075E877 |. 64:8920 MOV DWORD PTR FS:[EAX],ESP
0075E87A |. C783 C4000700 010000>MOV DWORD PTR DS:[EBX+700C4],1
0075E884 |. 66:B9 0100 MOV CX,1
0075E888 |. 66:BA 0B00 MOV DX,0B
0075E88C |. 66:B8 D607 MOV AX,7D6
0075E890 |. E8 9FD6CAFF CALL everest.0040BF34
0075E895 |. DD9B C8000700 FSTP QWORD PTR DS:[EBX+700C8]
0075E89B |. 9B WAIT
. . .
. . . ; <- кусок пропущен
. . .
0075ECF3 |. BA 05000000 MOV EDX,5
0075ECF8 |. E8 1766CAFF CALL everest.00405314
0075ECFD \. C3 RETN
Ну что же посмотрим, что у нас там – перезапускаем прогу и останавливаемся на бряке. Видно , что это функция что-то делает с содержимым KEY файла, но ничего не понятно… Идем по F8 и уже подошли к выходу, ладно выходим из этой функции и что мы видим:
0072F99F |. 8B03 MOV EAX,DWORD PTR DS:[EBX]
0072F9A1 |. E8 B2EE0200 CALL everest.0075E858 ;<- Отсюда мы вышли
0072F9A6 |. 8B03 MOV EAX,DWORD PTR DS:[EBX]
0072F9A8 |. 83B8 C0000700 00 CMP DWORD PTR DS:[EAX+700C0],0 ; <- Проверка если там не 0
0072F9AF |. 75 0C JNZ SHORT everest.0072F9BD ; то прыгаем
0072F9B1 |. 8B03 MOV EAX,DWORD PTR DS:[EBX]
0072F9B3 |. 05 BC000700 ADD EAX,700BC
0072F9B8 |. E8 3359CDFF CALL everest.004052F0 ; иначе, заносим 0 в [EAX+700BC]
0072F9BD |> 6A 02 PUSH 2 ; /Index = SM_CXVSCROLL
0072F9BF |. E8 F88ACDFF CALL <JMP.&user32.GetSystemMetrics> ; \GetSystemMetrics
0072F9C4 |. 8B13 MOV EDX,DWORD PTR DS:[EBX]
0072F9C6 |. 8982 444F0000 MOV DWORD PTR DS:[EDX+4F44],EAX
0072F9CC |. 6A 05 PUSH 5 ; /Index = COLOR_WINDOW
0072F9CE |. E8 D18ACDFF CALL <JMP.&user32.GetSysColor> ; \GetSysColor
0072F9D3 |. 3D FFFFFF00 CMP EAX,0FFFFFF
0072F9D8 |. 75 19 JNZ SHORT everest.0072F9F3
0072F9DA |. 6A 08 PUSH 8 ; /Index = COLOR_WINDOWTEXT
0072F9DC |. E8 C38ACDFF CALL <JMP.&user32.GetSysColor> ; \GetSysColor
0072F9E1 |. 85C0 TEST EAX,EAX
0072F9E3 |. 75 0E JNZ SHORT everest.0072F9F3
0072F9E5 |. 8B03 MOV EAX,DWORD PTR DS:[EBX]
0072F9E7 |. C780 C4060000 316AC5>MOV DWORD PTR DS:[EAX+6C4],0C56A31
0072F9F1 |. EB 0F JMP SHORT everest.0072FA02
0072F9F3 |> 6A 0D PUSH 0D ; /Index = COLOR_HIGHLIGHT
0072F9F5 |. E8 AA8ACDFF CALL <JMP.&user32.GetSysColor> ; \GetSysColor
0072F9FA |. 8B13 MOV EDX,DWORD PTR DS:[EBX]
0072F9FC |. 8982 C4060000 MOV DWORD PTR DS:[EDX+6C4],EAX
0072FA02 |> 8D55 E4 LEA EDX,DWORD PTR SS:[EBP-1C]
0072FA05 |. 33C0 XOR EAX,EAX
0072FA07 |. E8 EC31CDFF CALL everest.00402BF8
0072FA0C |. 8B45 E4 MOV EAX,DWORD PTR SS:[EBP-1C]
0072FA0F |. 8D4D E8 LEA ECX,DWORD PTR SS:[EBP-18]
0072FA12 |. BA E8FF7200 MOV EDX,everest.0072FFE8 ; ASCII "ProductVersion"
0072FA17 |. E8 80F0D8FF CALL everest.004BEA9C
0072FA1C |. 8B55 E8 MOV EDX,DWORD PTR SS:[EBP-18]
0072FA1F |. 8B03 MOV EAX,DWORD PTR DS:[EBX]
0072FA21 |. 05 68070000 ADD EAX,768
0072FA26 |. E8 1959CDFF CALL everest.00405344
0072FA2B |. 8D55 DC LEA EDX,DWORD PTR SS:[EBP-24]
0072FA2E |. 33C0 XOR EAX,EAX
0072FA30 |. E8 C331CDFF CALL everest.00402BF8
0072FA35 |. 8B45 DC MOV EAX,DWORD PTR SS:[EBP-24]
0072FA38 |. 8D4D E0 LEA ECX,DWORD PTR SS:[EBP-20]
0072FA3B |. BA 00007300 MOV EDX,everest.00730000 ; ASCII "FileVersion"
0072FA40 |. E8 57F0D8FF CALL everest.004BEA9C
0072FA45 |. 8B55 E0 MOV EDX,DWORD PTR SS:[EBP-20]
0072FA48 |. 8B03 MOV EAX,DWORD PTR DS:[EBX]
0072FA4A |. 05 6C070000 ADD EAX,76C
0072FA4F |. E8 F058CDFF CALL everest.00405344
0072FA54 |. 8D55 F8 LEA EDX,DWORD PTR SS:[EBP-8]
0072FA57 |. B8 14007300 MOV EAX,everest.00730014 ; ASCII "EVEREST Ultimate Edition 2006"
0072FA5C |. E8 C3A2CDFF CALL everest.00409D24
0072FA61 |. 8B03 MOV EAX,DWORD PTR DS:[EBX]
0072FA63 |. 83B8 BC000700 00 CMP DWORD PTR DS:[EAX+700BC],0 ; <- Проверка если там не 0,
0072FA6A |. 75 1A JNZ SHORT everest.0072FA86 ; то прыгаем и не добавляем надпись
0072FA6C |. FF75 F8 PUSH DWORD PTR SS:[EBP-8]
0072FA6F |. 68 3C007300 PUSH everest.0073003C ; ASCII " "
0072FA74 |. 68 48007300 PUSH everest.00730048 ; ASCII "[ TRIAL VERSION ]"
0072FA79 |. 8D45 F8 LEA EAX,DWORD PTR SS:[EBP-8]
Вот оно: по адресу 0072FA63 проверка, если по адресу [EAX+700BC] лежит 0, тогда прибавляем строку [Trial Version] в заголовок окна , а как мы видели выше (строка 0072F9A8) там идет проверка, если в [EAX+700C0] был не ноль, то и в [EAX+700BC] не заносится ноль. Значит будем искать место, где в [EAX+700C0] заносится ноль. И где же вы думаете это место??? Правильно! В функции проверки ключа ( CALL everest.0075E858 ), значит будем смотреть ее более подробно!!!
Для начала посмотрим что у нас в сгенерином key файле (который выдал KeyGen):
RSI
Unlimited
20501231
00D0050000F0060000D005000090060000D005000040060000D0050000A0060000D0050000F0060000D0050000500600
Пока нам это ни о чем не говорит, итак идем по адресу 0075E858 на начало функции проверки и трейсим по F8, только уже смотрим внимательно, что там делается :)
0075E971 |> 8B55 D4 MOV EDX,DWORD PTR SS:[EBP-2C]
0075E974 |. 8D85 08FEFFFF LEA EAX,DWORD PTR SS:[EBP-1F8]
0075E97A |. E8 C546CAFF CALL everest.00403044
0075E97F |. A1 88E57900 MOV EAX,DWORD PTR DS:[79E588]
0075E984 |. C600 00 MOV BYTE PTR DS:[EAX],0
0075E987 |. 8D85 08FEFFFF LEA EAX,DWORD PTR SS:[EBP-1F8]
0075E98D |. E8 3644CAFF CALL everest.00402DC8
0075E992 |. E8 B540CAFF CALL everest.00402A4C
0075E997 |. 85C0 TEST EAX,EAX ; Если нет KEY файла, то
0075E999 |. 0F85 24030000 JNZ everest.0075ECC3 ; прыгаем на облом
0075E99F |. 8D45 E4 LEA EAX,DWORD PTR SS:[EBP-1C]
0075E9A2 |. E8 4969CAFF CALL everest.004052F0
0075E9A7 |. 8D45 E0 LEA EAX,DWORD PTR SS:[EBP-20]
0075E9AA |. E8 4169CAFF CALL everest.004052F0
Хорошо! Файл у нас есть – поэтому не прыгаем, идем дальше
0075EA92 |. E8 9D3ECAFF CALL everest.00402934
0075EA97 |. 837D E4 00 CMP DWORD PTR SS:[EBP-1C],0 ; <- Проверка, что 1-я строка KEY файла не 0
0075EA9B |. 74 3D JE SHORT everest.0075EADA
0075EA9D |. 837D E0 00 CMP DWORD PTR SS:[EBP-20],0 ; <- Проверка, что 2-я строка KEY файла не 0
0075EAA1 |. 74 37 JE SHORT everest.0075EADA
0075EAA3 |. 837D D8 00 CMP DWORD PTR SS:[EBP-28],0 ; <- Проверка, что 4-я строка KEY файла не 0
0075EAA7 |. 74 31 JE SHORT everest.0075EADA
0075EAA9 |. 8D95 E4FDFFFF LEA EDX,DWORD PTR SS:[EBP-21C]
0075EAAF |. 8B45 E0 MOV EAX,DWORD PTR SS:[EBP-20]
0075EAB2 |. E8 6DB2CAFF CALL everest.00409D24 ; Приводим 2-ю строку к верхнему регистру
0075EAB7 |. 8B85 E4FDFFFF MOV EAX,DWORD PTR SS:[EBP-21C]
0075EABD |. 8D95 E8FDFFFF LEA EDX,DWORD PTR SS:[EBP-218]
0075EAC3 |. E8 0CB0CAFF CALL everest.00409AD4
0075EAC8 |. 8B85 E8FDFFFF MOV EAX,DWORD PTR SS:[EBP-218] ; указатель на 2-ю строку файла
0075EACE |. BA 58ED7500 MOV EDX,everest.0075ED58 ; указатель на строку "UNLIMITED"
0075EAD3 |. E8 406CCAFF CALL everest.00405718 ; сравнение строк
0075EAD8 |. 75 0C JNZ SHORT everest.0075EAE6 ; Если они равны, то не прыгаем
0075EADA |> C683 D0000700 01 MOV BYTE PTR DS:[EBX+700D0],1
0075EAE1 |. E9 DD010000 JMP everest.0075ECC3 ; Прыжок на облом...
0075EAE6 |> 8D95 E0FDFFFF LEA EDX,DWORD PTR SS:[EBP-220]
Ага значит 2-я строка KEY файла на должна быть UNLIMITED, а у нас там как раз она, поэтому откроем KEY файл и вместо нее напишем, например, «Never»!!! Хорошо, снова перезапустились, теперь прыгнули в этом месте и идем дальше:
0075EAE6 |> 8D95 E0FDFFFF LEA EDX,DWORD PTR SS:[EBP-220] ; передаем в функцию 4-ю строку
0075EAEC |. 8B45 D8 MOV EAX,DWORD PTR SS:[EBP-28]
0075EAEF |. E8 D08FE3FF CALL everest.00597AC4 ; функция отработала
0075EAF4 |. 8B85 E0FDFFFF MOV EAX,DWORD PTR SS:[EBP-220] ; получаем на выходе строку "249728"
0075EAFA |. 8D55 F8 LEA EDX,DWORD PTR SS:[EBP-8]
0075EAFD |. E8 2254CAFF CALL everest.00403F24 ; <- переводим строку в число
0075EB02 |. DD5D E8 FSTP QWORD PTR SS:[EBP-18] ; <- сохраняем число в [EBP-18]
0075EB05 |. 9B WAIT
0075EB06 |. 33C0 XOR EAX,EAX
Видим функция 00597AC4 ( далее функция_1) вернула нам "249728", пока назовем его число_1, ХЗ зачем идем дальше и видим:
0075EB06 |. 33C0 XOR EAX,EAX
0075EB08 |. 8945 F0 MOV DWORD PTR SS:[EBP-10],EAX ; <- [EBP-10] = 0
0075EB0B |. 8945 F4 MOV DWORD PTR SS:[EBP-C],EAX
0075EB0E |. 8B45 E4 MOV EAX,DWORD PTR SS:[EBP-1C] ; <- наша 1-я строка (Имя)
0075EB11 |. E8 B66ACAFF CALL everest.004055CC
0075EB16 |. 8BD0 MOV EDX,EAX ; <- в EDX длина 1-ой строки
0075EB18 |. 85D2 TEST EDX,EDX
0075EB1A |. 7E 2C JLE SHORT everest.0075EB48
0075EB1C |. B8 01000000 MOV EAX,1
0075EB21 |> 8B4D E4 /MOV ECX,DWORD PTR SS:[EBP-1C] ; <- в ЕСХ наше имя
0075EB24 |. 0FB64C01 FF |MOVZX ECX,BYTE PTR DS:[ECX+EAX-1] ; <- берем eax-1 символ имени (т.е 0,1,2...)
0075EB29 |. 8BF0 |MOV ESI,EAX
0075EB2B |. 83F6 6D |XOR ESI,6D ; <- ксорим номер символа с константой 6Dh = 109
0075EB2E |. 0FAFCE |IMUL ECX,ESI ; <- умножаем на наш символ имени
0075EB31 |. 898D DCFDFFFF |MOV DWORD PTR SS:[EBP-224],ECX
0075EB37 |. DB85 DCFDFFFF |FILD DWORD PTR SS:[EBP-224]
0075EB3D |. DC45 F0 |FADD QWORD PTR SS:[EBP-10] ; <- результат прибавляем в [EBP-10]
0075EB40 |. DD5D F0 |FSTP QWORD PTR SS:[EBP-10]
0075EB43 |. 9B |WAIT
0075EB44 |. 40 |INC EAX
0075EB45 |. 4A |DEC EDX
0075EB46 |.^75 D9 \JNZ SHORT everest.0075EB21 ; <- выполняем пока не дошли до конца имени
0075EB48 |> 8B45 E0 MOV EAX,DWORD PTR SS:[EBP-20] ; <- наша 2-я строка "Never"
0075EB4B |. E8 7C6ACAFF CALL everest.004055CC
0075EB50 |. 8BD0 MOV EDX,EAX
0075EB52 |. 85D2 TEST EDX,EDX
0075EB54 |. 7E 2F JLE SHORT everest.0075EB85
0075EB56 |. B8 01000000 MOV EAX,1 ; <- все тоже самое, только
0075EB5B |> 8B4D E0 /MOV ECX,DWORD PTR SS:[EBP-20]
0075EB5E |. 0FB64C01 FF |MOVZX ECX,BYTE PTR DS:[ECX+EAX-1]
0075EB63 |. 8BF0 |MOV ESI,EAX
0075EB65 |. 81F6 E6000000 |XOR ESI,0E6 ; <- ксорим с E6h = 230
0075EB6B |. 0FAFCE |IMUL ECX,ESI
0075EB6E |. 898D DCFDFFFF |MOV DWORD PTR SS:[EBP-224],ECX
0075EB74 |. DB85 DCFDFFFF |FILD DWORD PTR SS:[EBP-224]
0075EB7A |. DC45 F0 |FADD QWORD PTR SS:[EBP-10]
0075EB7D |. DD5D F0 |FSTP QWORD PTR SS:[EBP-10]
0075EB80 |. 9B |WAIT
0075EB81 |. 40 |INC EAX
0075EB82 |. 4A |DEC EDX
0075EB83 |.^75 D6 \JNZ SHORT everest.0075EB5B
0075EB85 |> 8B45 DC MOV EAX,DWORD PTR SS:[EBP-24] ; <- наша 3-я строка
0075EB88 |. E8 3F6ACAFF CALL everest.004055CC
0075EB8D |. 8BD0 MOV EDX,EAX
0075EB8F |. 85D2 TEST EDX,EDX
0075EB91 |. 7E 2C JLE SHORT everest.0075EBBF
0075EB93 |. B8 01000000 MOV EAX,1 ; <- все тоже самое, только
0075EB98 |> 8B4D DC /MOV ECX,DWORD PTR SS:[EBP-24]
0075EB9B |. 0FB64C01 FF |MOVZX ECX,BYTE PTR DS:[ECX+EAX-1]
0075EBA0 |. 8BF0 |MOV ESI,EAX
0075EBA2 |. 83F6 11 |XOR ESI,11 ; <- ксорим с 11h = 17
0075EBA5 |. 0FAFCE |IMUL ECX,ESI
0075EBA8 |. 898D DCFDFFFF |MOV DWORD PTR SS:[EBP-224],ECX
0075EBAE |. DB85 DCFDFFFF |FILD DWORD PTR SS:[EBP-224]
0075EBB4 |. DC45 F0 |FADD QWORD PTR SS:[EBP-10]
0075EBB7 |. DD5D F0 |FSTP QWORD PTR SS:[EBP-10]
0075EBBA |. 9B |WAIT
0075EBBB |. 40 |INC EAX
0075EBBC |. 4A |DEC EDX
0075EBBD |.^75 D9 \JNZ SHORT everest.0075EB98
0075EBBF |> DD45 F0 FLD QWORD PTR SS:[EBP-10]
0075EBC2 |. DC5D E8 FCOMP QWORD PTR SS:[EBP-18] ; сравниваем [EBP-10] и [EBP-18]
0075EBC5 |. DFE0 FSTSW AX
0075EBC7 |. 9E SAHF
0075EBC8 |. 74 0C JE SHORT everest.0075EBD6 ; если они равны,то прыгаем
0075EBCA |. C683 D0000700 >MOV BYTE PTR DS:[EBX+700D0],1
0075EBD1 |. E9 ED000000 JMP everest.0075ECC3
Ну вот! Основной алгоритм в принципе стал понятен:
Берется 4-я строка из нашего KEY файла и на основаниее ее мы получаем число_1, после этого мы подсчитываем суммы от первой второй и третей строки, предварительно с кладывая их в одну переменную(число_2), затем сравниваются число_1 и число_2 если они равны, тогда мы прыгаем и в адрес [EAX+700C0] заносится указатель на строку "Never", и дальше все в идет как по маслу... ;)
Итак алгоритм создания KeyGen-a:
1. Надо сделать цикл подсчета нашего имени
Он будет следующим:
for( int i=1; i <= strlen(name) ; i++)
{
c = name[i-1]; // c = [eax-1] символ нашего имени
a = i; // mov esi,eax
a ^= 109; // xor esi,6Dh
b = c*a; // imul ecx,esi
result += b; // fadd qword ptr ss:[ebp-10]
}
После этого цикла переменная result будет содержать нашу сумму
2. Прибавить к ней число от цикла строки «Never»,оно будет постоянно и равно 116772.
3. Прибавить к нему число от цикла 3-й строки в файле она может быть любая (в keygen я взял строку «01010101» результат ее цикла = 7960)
4. Сгенерить 4-ю строку, чтобы сумма ее цикла была равна нашему числу
5. Сохранить эти данные в файл everest.key
По поводу генерации 4-ой строки надо сказать! Как генерится число от нее?
После того как в функцию_1 мы передали строку
00D0050000F0060000D005000090060000D005000040060000D0050000A0060000D0050000F0060000D0050000500600
И получили строку «249728», которую потом будем переводить в число и с ней сравнивать!
Не буду вдаваться в подробности, короче эта строка генерится ТАК:
00D0050000X00600 - Вот такой кусок повторяется 6 раз, причем буква X отвечает за генерацию каждого символа в строке.
Вот значения X ( могут и другие символы удовлетворять этим значениям!!! ):
Таблица 1:
--------------------------------------------------------------------------------------------
Символ = 0 1 2 3 4 5 6 7 8 9
--------------------------------------------------------------------------------------------
X = d c f e 9 8 b a 5 4
--------------------------------------------------------------------------------------------
То есть строку «123456» можно зашифровать так(см. Таблицу 1):
00D0050000с0060000D0050000f0060000D0050000e0060000D005000090060000D005000080060000D0050000b00600
1 2 3 4 5 6
Исходя из этого, вот такой ключ получился для моего имени:
RSI
Never
01010101
00D0050000c0060000D005000080060000D0050000d0060000D005000050060000D0050000e0060000D0050000c00600
Исходный код KeyGen-a:(писал на VC++ 6.0 SE под Win32 Console)
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <stdlib.h>
void main()
{
FILE *file;
long result=0;
сhar name[25],data[100];
char str[10],tmp[2];
char mas[]={'d','c','f','e','9','8','b','a','5','4'}; // массив значений X отвечающих за генерацию 4 строки
data[0] = '\0';
tmp[1] = '\0';
printf(" Lavalys Everest Ultimate Edition 2006 v3.01.652\n KeyGen by RSI, 2006\n\n");
printf(" Enter your name: ");
scanf("%s",&name);
for(unsigned int i=1; i <= strlen(name) ; i++) // цикл считает результат имени
{
result += name[i-1]*(i^109);
}
result += 116772; //прибавляем результат цикла от строки "Never"
result += 7960; //прибавляем результат цикла от строки "01010101"
ltoa(result,str,10); // переводим результат из числа в строку
for( i=0; i < strlen(str); i++) // делаем бинарную строку от результата
{
strcat(data,"00D0050000");
tmp[0] = mas[ str[i]-'0' ];
strcat(data,tmp);
strcat(data,"00600");
}
file = fopen("everest.key","w"); // сохраняем файл лицензии
if(file == NULL)
{
printf(" \n Error!!! Key File not is created");
getch();
return;
}
fprintf(file,"%s\n",name);
fprintf(file,"Never\n01010101\n");
fprintf(file,"%s",data);
fclose(file);
printf("\n License file is created\n\n Press any key to quit...");
getch();
}
Вот и все!!!
Огромное спасибо сайту www.cracklab.ru и его создателям за то, что «научили»!!!
Приветы ВСЕМ, а так же тем, кто прочитал эту статью… :)
Если есть вопросы, или что-нибудь по статье пишите RS1@tut.by
Обсуждение статьи: Исследуем Lavalys Everest Ultimate Edition 2006 v.3.01.652 и пишем KeyGen >>>
Комментарии к статье: Исследуем Lavalys Everest Ultimate Edition 2006 v.3.01.652 и пишем KeyGen
Devastator_ 21.10.2006 09:54:32 По-поводу CreateProcessA(W)... есть много способов подгрузить код в адресное пространство существующего процесса например LoadLibraryA(W) (использовалось в OutpostFirewall кажется). Или банально выделить память GlobalAlloc, в качестве флагов функции указать executable, влить туда код из файла или из секции ресурсов например и передать управление коду. Вариантов масса.
--- RSI 23.10.2006 10:19:39 Я написал только то, что здесь использовалось! Еслиб ломал Outpost то написал бы и про это... ;) --- Nitrogen 29.10.2006 19:50:39 Devastator
ну вот ты это к чему сказал, типа показать какой ты умный?
RSI
маладес. статья толковая! --- Z0oMiK 30.10.2006 03:10:43 Хорошая статейка :) тока кейген на С это (_/_) ( для меня ) :) ---
Материалы находятся на сайте
https://exelab.ru
|