// Тут некоторые просили мини-уроки, которые были бы меньше, но чаще.
"Урок №5. Крек. Часть 1. Взлом KeyGenMe level2."
Crackin' LibertyorDeaths ASM KeyGenMe #1
Цель взлома сегодня - LibertyorDeaths ASM KeyGenMe #1.
Взять его можно тут -
http://crackmes.de/users/libertyordeath … 1/download
Этот кейгенми 2-го уровня как раз для новичков(НО! как минимум знающих основы).
1. Открываем кейгенми в Олли и видим непонятную картину - один jmp и кучу битого кода. Это значит что код зашифрован, а jmp используется для перехода на декриптор. Код декриптора таков:
004011AE MOV ESI,ASM_KEYG.00401006
004011B3 MOV AL,BYTE PTR DS:[ESI]
004011B5 XOR AL,25
004011B7 MOV BYTE PTR DS:[ESI],AL
004011B9 INC ESI
004011BA CMP ESI,ASM_KEYG.004011A7
004011C0 JNZ SHORT ASM_KEYG.004011B3
004011C2 JMP ASM_KEYG.00401006
Как видишь, в нем никаких антиотладочных трюков, он очень прост, а значит можно запускать программу (F9) - пусть себе код расшифруется. Кстати, чуть выше можно увидеть криворукость создателя кейгенми:
004011A9 . E8 1A000000 CALL <JMP.&kernel32.ExitProcess> ; \ExitProcess
Код не до конца зашифрован, а значит боятся нечего - создатель не профи))
2. Когда кейгенми запустится и появится окно, проанализируй код в Олли заново (Ctrl+A). Это нужно для того, чтобы код в отладчике занаво проанализировался и был покрасивее после обработки Олли.
3. Пролистай в Олли чуть выше, и ты увидишь главный код, который генерирует серийник. Там же находится API lstrcmpA - сравнение строк. Пролистай чуть выше до начала процедуры генерации (401114h)
4. Как видишь, код понятен и несложен, и мы можем рипнуть код с 401127h до 401152h для нашего кейгена.
Процедура начинается тут:
00401114 PUSH EDI
00401115 CMP DWORD PTR DS:[403100],0 ; Если длина имени = 0,
0040111C JE SHORT ASM_KEYG.00401191 ; тогда прыгаем к плохому сообщению
0040111E CMP DWORD PTR DS:[403128],0 ; Если длина введеного серийника = 0,
00401125 JE SHORT ASM_KEYG.00401191 ; тогда прыгаем к плохому сообщению
00401127 XOR ESI,ESI
00401129 XOR ECX,ECX
0040112B XOR EDX,EDX
0040112D MOV ECX,0
00401132 MOV EDX,0A
Здесь начинается главный цикл генерации серийника:
00401137 /MOVSX EAX,BYTE PTR DS:[ECX+4030C0] ; Получим букву имени
0040113E |INC EAX ; Математические операции
0040113F |ADD EAX,EDX ; которые генерируют серийник
00401141 |ADD ESI,EAX
00401143 |INC ECX
00401144 |IMUL EDX,ECX
00401147 |MOV EDI,EDX
00401149 |IMUL EDI,ESI
0040114C |CMP ECX,DWORD PTR DS:[403100] ; Сравним количество пройденых циклов с длиной имени
00401152 \JNZ SHORT ASM_KEYG.00401137 ; Прыгаем в начало цикла, если они разные
Теперь мы имеем 2 числа, сгенереных на основе имени в ESi и EDI.
Следующий код форматирует правильный серийник на основе чисел в ESi и EDI.
00401154 PUSH EDI
00401155 PUSH ESI
00401156 PUSH ASM_KEYG.004030AE ; Формат = "LOD-%lu-%lX"
0040115B PUSH ASM_KEYG.00403104 ; В это буфере будет валидный серийник
00401160 CALL <JMP.&user32.wsprintfA>
00401165 ADD ESP,10
Этот код сравнивает серийники:
00401168 PUSH ASM_KEYG.004030E0
0040116D PUSH ASM_KEYG.00403104
00401172 CALL <JMP.&kernel32.lstrcmpA>
Если мы ввели неправильный SN, то прыгаем по адресу 401191h
00401177 CMP EAX,0
0040117A POP EDI
0040117B JNZ SHORT ASM_KEYG.00401191
Если мы ввели правильный SN, показываем "хорошее сообщение" и выходим из процедуры генерации.
0040117D PUSH 0
0040117F PUSH ASM_KEYG.00403092 ; |Title = "Yay!"
00401184 PUSH ASM_KEYG.00403084 ; |Text = "Valid Serial!"
00401189 PUSH 0
0040118B CALL <JMP.&user32.MessageBoxA>
00401190 RETN
Этот код показывает "плохое" сообщение и выходит из программы
00401191 PUSH 0
00401193 PUSH ASM_KEYG.004030A7 ; |Title = "Error!"
00401198 PUSH ASM_KEYG.00403097 ; |Text = "Invalid Serial!"
0040119D PUSH 0
0040119F CALL <JMP.&user32.MessageBoxA>
004011A4 PUSH ASM_KEYG.00403124
004011A9 CALL <JMP.&kernel32.ExitProcess> ; Выход!
Вот кусок исходника моего кейгена, отвечающий за генерацию серийника:
.data?
Buffer1 db 256 dup (?)
Buffer2 db 256 dup (?)
n_length dd ?
.data
fmtstr db "LOD-%lu-%lX",0
.code
Generate proc hWin:HWND
invoke GetDlgItemText,hWin,700,ADDR Buffer1,32
invoke lstrlen, addr Buffer1
mov n_length, eax
XOR ESI,ESI
XOR ECX,ECX
XOR EDX,EDX
MOV ECX,0
MOV EDX,0Ah
here:
MOVSX EAX,BYTE PTR [ECX+Buffer1]
INC EAX
ADD EAX,EDX
ADD ESI,EAX
INC ECX
IMUL EDX,ECX
MOV EDI,EDX
IMUL EDI,ESI
CMP ECX,DWORD PTR [n_length]
JNZ here
invoke wsprintf,ADDR Buffer2,ADDR fmtstr,esi,edi
invoke SetDlgItemText, hWin, 701, addr Buffer2
Generate endp