.:PcWorld Forum:.

Reply

Come creare un keygen

« Older   Newer »
Hacker3™
view post Posted on 17/2/2010, 19:40 Quote




Ecco come creare un keygen per dei gioki o per programmi...

Ci sono 2 modi per creare un key generator. Il primo consiste nel copiare tutto
il codice assembly, fargli qualche piccola modifica e compilare il tutto con un
assembler.
In questo caso e' necessario conoscere dove la routine di registrazione parte,
dove finisce e quali sono le sue variabili.
Il secondo consiste nell'analizzare l'intera routine e trasportarla/modificarla
per un compilatore di un linguaggio di alto livello. Questo sistema prevede una
bella perdita di tempo nell'analisi del sorgente, ma io preferisco questa via
per scrivere tutti i miei key makers.

Qui sotto c'e' la porzione principale della routine di registrazione del livello
2 ottenuta con il W32Dasm, ho commentato un pochino il codice per renderlo
chiaro anche a chi di assembler ci capisce poco.
Entrate nel programma come descritto nel precedente articolo settando un break
point a GetDlgItamTextA, premete [F12] per uscire da USER32 e
MFC42, arriverete cosi' nel codice di CrackMe.
Adesso premete [F10] per andare nella prima riga del codice (:00401ADF)
Come potete notare qui sotto la prima cosa da fare sara' di disabilitare il
break point inserito con: "d *"

----------------------------------------------------------------------
:00401ADF E8FA100000 Call 00402BDE ; MFC42.GetDlgItemTextA
:00401AE4 8D4C247C lea ecx, dword ptr [esp+7C]
:00401AE8 6A33 push 00000033
:00401AEA 51 push ecx
:00401AEB 68ED030000 push 000003ED
:00401AF0 8BCB mov ecx, ebx
:00401AF2 E8E7100000 Call 00402BDE ; MFC42.GetDlgItemTextA (prende username)
:00401AF7 8D542414 lea edx, dword ptr [esp+14] ; -> punta username
:00401AFB 52 push edx ; -> push username nello stack per lstrlenA
:00401AFC FF1500404000 Call dword ptr [00404000] ; KERNEL32.lstrlenA
:00401B02 8BF0 mov esi, eax ; salva lunghezza stringa in esi
:00401B04 83FE05 cmp esi, 00000005 ; lunghezza stringa < 5 ?
:00401B07 7311 jnb 00401B1A ; jump/ nome ok se lunghezza >= 5
:00401B09 6A40 push 00000040
:00401B0B 6804514000 push 00405104
:00401B10 68D8504000 push 004050D8
:00401B15 E9BA000000 jmp 00401BD4 ; jump/quit mostra end MessageBox

:00401B1A B801000000 mov eax, 00000001 ; setta eax a 1 (counter)
:00401B1F 33FF xor edi, edi ; setta edi a 0
:00401B21 3BF0 cmp esi, eax ; (esi - eax)
:00401B23 7211 jb 00401B36 ; jump se esi(lunghezza) < eax;

; [esp+14] punta a username
; eax e' il counter
:00401B25 0FBE4C0414 movsx ecx, byte ptr [esp+eax+14] ; ecx = user[eax]
:00401B2A 03CF add ecx, edi ; ecx = ecx + edi
:00401B2C 0FAFC8 imul ecx, eax ; ecx = ecx * eax
:00401B2F 40 inc eax ; eax = eax + 1
:00401B30 8BF9 mov edi, ecx ; edi = ecx
:00401B32 3BC6 cmp eax, esi ; (eax - esi) (eax e' il counter)
:00401B34 76EF jbe 00401B25 ; loop se eax <= esi(lunghezza)

:00401B36 33C9 xor ecx, ecx ; ecx = 0;
:00401B38 85F6 test esi, esi ; (esi & esi)
:00401B3A 7620 jbe 00401B5C ; jump/quit se esi(lunghezza) is 0

; [esp+14] punta a username
; [esp+48] punta alla key generata
; ecx e' il counter = 0 all'inizio
; edi contiene la key del precedente loop
:00401B3C 0FBE6C0C14 movsx ebp, byte ptr [esp+ecx+14] ; ebp = user[ecx]
:00401B41 8BC7 mov eax, edi ; eax = edi (key)
:00401B43 33D2 xor edx, edx ; edx = 0
:00401B45 F7F5 div ebp ; eax = eax/ebp, edx = eax%ebp
:00401B47 33D2 xor edx, edx ; edx = 0
:00401B49 BD0A000000 mov ebp, 0000000A ; ebp = 0xA
:00401B4E F7F5 div ebp ; eax = eax/ebp, edx = eax%ebp
:00401B50 80C230 add dl, 30 ; dl = dl + 0x30
:00401B53 88540C48 mov byte ptr [esp+ecx+48], dl ; key[ecx] = dl
:00401B57 41 inc ecx ; ecx = ecx + 1
:00401B58 3BCE cmp ecx, esi ; (ecx - esi)
:00401B5A 72E0 jb 00401B3C ; loop se ecx < esi

:00401B5C 8D542448 lea edx, dword ptr [esp+48] ; -> key generata
:00401B60 8D44247C lea eax, dword ptr [esp+7C] ; -> password inserita
:00401B64 52 push edx ; push puntatore della key nello stack
:00401B65 50 push eax ; push puntatore della password nello stack
; lstrcmpA compara le 2 stringhe nello stack
; il valore di ritorno e' messo in eax
; se le 2 stringhe sono uguali, eax = 0
:00401B66 FF1508404000 Call dword ptr [00404008] ; KERNEL32.lstrcmpA
:00401B6C 85C0 test eax, eax ; (eax & eax)
:00401B6E 7550 jne 00401BC0 ; jump se eax non e' 0

Ok! adesso per avere la stringa di registrazione basta guardare, con il
comando appropriato, nella riga di codice a :00401B5C, qual'e' il comando?
bhe se mi avete seguito fin'ora lo sapete gia'...
Comunque non e' questo il nostro intento, o per lo meno non e' il mio
Adesso senza guardare la soluzione provate a tradurre quanto sopra in uno
pseudo codice per un linguaggio di alto livello e poi confrontatelo con la mia
soluzione in fondo.
Giusto per darvi un'idea osservate bene le linee da :00401B25 a :00401B34
per esempio.
La prima cosa che salta all'occhio e' il loop per il JBE alla linea
:00401B34, questo fa un jump all'indietro alla linea :00401B25, ma quali sono
le condizioni del loop?

Ok! partiamo nell'analisi del codice:
questa e' la prima linea del loop...
:00401B25 0FBE4C0414 movsx ecx, byte ptr [esp+eax+14]
Dovresti sapere (lo spero per te!!!) che "mov" corrisponde a "=" in un
linguaggio di alto livello e "movsx" e' una variante di "mov" le cui
differenze non ci fregano granche'.
Quello che e' importante sapere di questa linea e' dove le istruzioni puntano.
Quando vedi le parentesi quadre gia' devi immaginare che si tratta di qualche
locazione di memoria, quindi analiziamo la memoria:
"d esp+eax+14" nella window dei comandi di Softice, vedremo l'username che
abbiamo inserito quindi ovviamente la linea provvede a spostare i caratteri
(byte) dell'username nel registro ECX!

andiamo ad analizzare il resto del loop:
(nota che EAX e' initializzato a 1 alla linea :00401B1A)
(nota anche che EDI e' initializzato a 0 alla linea :00401B1F)

add ecx, edi ; agiunge edi a ECX (ecx e' il byte per username)
imul ecx, eax ; moltiplica ECX per eax (eax e' il counter per questo loop)
inc eax ; aggiunge 1 a EAX
mov edi, ecx ; salva ecx in EDI (valore segreto!!!)
cmp eax, esi ; modifica gli zero & segna i flag per la comparazione
jbe 00401B25 ; loop se eax <= esi (esi e' la lunghezza dell'username)

Le ultime 2 linee ovviamente dicono che EAX e' inserito nel counter e che e'
usato per compararlo con ESI, cioe' la lunghezza dell'username. Ma come fare
a sapere cosa EDI registra nel suo valore segreto?
ok! sappiamo che non possono essere ne eax ne esi, sappiamo anche che non puo'
essere ecx perche' ecx e' cambiato alla prima linea per muoverci l'username,
e tutto evolve con delle operazioni matematiche, quindi EDI non puo' essere che
il valore risultato di questo loop!!!
Un'altra cosa e' che EAX viene incrementata, e' usata per prelevare i caratteri
della stringa inserita e' portarli al loop.

Adesso abbiamo tutto quello che ci serve per scrivere il nostro pseudo codice:

i = 1
finalvalue = 0

do
tmpvar = username(i)
tmpvar = tmpvar * i
i = i + 1
finalvalue = tmpvar
repeat if i <= lunghezza dell'username

Finito, il resto consiste nell'osservare e traslare il resto della routine di
registrazione in un linguaggio a te familiare e modificare un pochino il codice
per ottenere la registration key!

Soluzione della routine di registrazione presa dal mio sorgente C++
-------------------------------------------------------------------
register DWORD i, slen, sum;
char usrn[51] = "\0", key[51] = "\0", keystr[51] = "\0";

GetDlgItemText(IDC_USRN, usrn, 51);
GetDlgItemText(IDC_KEY, key, 51);
if ((slen = lstrlen(usrn)) < 5)
{
MessageBox("User Name must have at least 5 characters.",
"CrackMe", MB_OK | MB_ICONINFORMATION);
return;
}
for (sum = 0, i = 1; i <= slen; i++)
{
sum += usrn[i];
sum *= i;
}
for (i = 0; i < slen; i++)
keystr[i] = LOBYTE( (sum / usrn[i]) % 10 + '0' );
if (lstrcmp(key, keystr) == 0)
{
// correct registration code!
}
else
{
// incorrect registration code!
}

Il Key Generator
-----------------------
Questo e' tutto quello che ti serve per il key generator, dopo aver
traslato il codice e' necessario fare l'output a video dalla "keystr[]"
dell'utente.
Non dovrebbe essere difficile, basta mantenere il codice utile ed eliminare
quello che non ci serve cosi'...

for (sum = 0, i = 1; i <= slen; i++)
{
sum += usrn[i];
sum *= i;
}
for (i = 0; i < slen; i++)
keystr[i] = LOBYTE( (sum / usrn[i]) % 10 + '0' );
 
Top
Ruxo
view post Posted on 17/2/2010, 20:17 Quote




Cavolo bella guida (anche lunga xd) ;)
 
Top
Predator75
view post Posted on 14/11/2010, 16:45 Quote




CITAZIONE (Hacker3™ @ 17/2/2010, 18:40) 
...copiare tutto il codice assembly, fargli qualche piccola modifica e compilare il tutto con un assembler.
In questo caso e' necessario conoscere dove la routine di registrazione parte, dove finisce e quali sono le sue variabili.

Scusa se ti correggo ma questa informazione è sbagliata, non potrai mai riassemblare il codice disassemblato in questo modo.

poi, applicando le regole delle guida non ci dovrebbe essere nessun problema a keygennare questo programma:
DOWNLOAD CRACKME
image

sopratutto considerato che è scritto in asm, pertanto codice pulitissimo e fa solo 2 operazioni di keygenning
chi lo risolve, ancora meglio chi lo cracka facendo in modo che accetti qualsiasi seriale? (dato che il keygenning è semplicissimo sarebbe meglio crackarlo)
difficoltà da 1 a 5 è quasi un 2.

Predator

Edited by Predator75 - 15/11/2010, 20:23
 
Top
2 replies since 17/2/2010, 19:40
 
Reply