|
>
CraCk Me n.1 Di xyzero:SoLuTiOn <
Realizzato da NoRpiUs ToOLz
uTiLiZzATi:
- Debugger ( Olly Dbg ) SpiEgaZiOnE:
Eccoci qua, questo e' il solito crack me con user
e pass con scopo di creare un keygen. Questo crack me lavora abbastanza con le
zone di memoria, per cui quando ne incontreremo di importanti ve le segnalero'
scrivendoci affianco IMPORTANTE. Ok, iniziamo. Mettiamo un breakpoint su
GetWindowTextA e ollydbg ci poppa qua: CALL ESI
; qua prende il serial
LEA EAX,DWORD PTR SS:[EBP-2C]
; carica in eax l'indirizzo del nome :)
PUSH EAX
; pusha eax sullo stack
CALL <JMP.&MSVCRT.strlen>
; calla strlen per sapere la lunghezza del nome
CMP EAX,4
; confronta la lunghezza del nome con 4
POP ECX
; ecx = indirizzo della stringa con il nome
JNB SHORT keygenme.004011AC
; se la lunghezza e' maggiore di 4 salta
MOV ESI,DWORD PTR DS:[<&USER32.SetDlgIte>] ;
se no il programma esegue queste istruzioni
PUSH 0
; che consistono nel resettare il campo delle
PUSH EDI
; informazioni ...
PUSH DWORD PTR SS:[EBP+8]
; ...
CALL ESI
; ...
PUSH keygenme.00403164
; ...
PUSH EBX
; ...
PUSH DWORD PTR SS:[EBP+8]
; ...
CALL ESI
; ...
JMP keygenme.00401281
; ... e dopo esce dalla nostra routine
Beh, da queste istruzioni si capisce che il nome
di cui ha bisogno deve essere per forza maggiore di 4 caratteri. Andiamo avanti
:) LEA EAX,DWORD PTR SS:[EBP-2C]
; carica in eax l'indirizzo della stringa con il nome
PUSH EAX
; lo pusha sullo stack
CALL <JMP.&MSVCRT.strlen>
; richiama strlen per sapere la lunghezza e ritorna in eax
POP ECX
; ecx = indirizzo della stringa con il nome
AND DWORD PTR SS:[EBP-8],0
; azzera la zona di memoria SS:[EBP-8]
MOV ECX,EAX
; mette in ecx la lunghezza dell'user
IMUL ECX,ECX,2D
; moltiplica la lunghezza per 0x2D (45 decimale)
TEST EAX,EAX
; controlla se eax = 0
LEA EDX,DWORD PTR DS:[ECX+ECX]
; carica in edx l'indirizzo di memoria ecx * 2
LEA ESI,DWORD PTR DS:[EDX+EDX*2]
; carica in esi l'indirizzo di memoria edx + edx * 2
MOV DWORD PTR SS:[EBP-4],ESI
; salva il valore di esi in SS:[EBP-4] - RICORDARE!
JBE SHORT keygenme.004011F5
; salto inutile
MOV ESI,EAX
; mette in esi la lunghezza del nome
IMUL ESI,DWORD PTR SS:[EBP-4]
; moltiplica esi per SS:[EBP-4] salvato prima
ADD DWORD PTR SS:[EBP-4],EAX
; adda eax alla zona di memoria [EBP-4] (servirà +
tardi)
Qua si fa qualche calcolino prima di entrane nel
primo dei 3 cicli che farà, il keygen fin qua e' cosi: #include
<stdio.h>
#include <string.h>
int main(void)
{
char user[512];
long ecx, edx, esi, eax, var, edi;
do {
printf("Scrivi
un user di minimo 4 caratteri: ");
scanf("%s", user);
} while ( strlen(user) < 4);
eax = strlen(user);
ecx = eax * 0x2D;
edx = ecx * 2;
var = edx + edx * 2;
// var sarebbe la zona di memoria
SS:[EBP-4] :)
esi = eax * var;
var += eax; } Ok,
reversiamo il primo ciclo :) CICLO:
; inizio ciclo MOV
EDI,DWORD PTR SS:[EBP-8]
; mette in edi il valore di
[EBP-4], che e' 0 al primo ciclo
ADD ESI,EAX
; somma eax a esi
MOVSX EDI,BYTE PTR SS:[EBP+EDI-2C] ;
mette in esi la ECX-esima lettera dell'user
IMUL EDI,ECX
; moltiplica edi per ecx
ADD EDI,EDX
; somma ad edi, edx
ADD DWORD PTR SS:[EBP-14],EDI
; somma edi all'indirizzo di
memoria [EBP-14] - IMPORTANTE!
INC ECX
; incrementa ecx (ecx =
contatore dei cicli)
LEA EDI,DWORD PTR DS:[ESI+ECX]
; carica in edi l'indirizzo di
memoria esi + ecx
ADD EDX,EDI
; somma edi a edx
INC DWORD PTR SS:[EBP-8]
; incrementa la zona di memoria
SS:[EBP-8]
CMP DWORD PTR SS:[EBP-8],EAX
; confronta il contatore con la lunghezza del nome
JB CICLO
; se e' minore torna a inizio
ciclo
Questo e' il primo dei 3 cicli che farà. I cicli
hanno come particolarità che hanno tutti e 3 una zona di memoria in cui vanno a
sommare il valore di un registro, che
servirà successivamente per la creazione del serial finale. In questo primo
ciclo questa zona di memoria e' SS:[EBP-14] e ci somma dentro il valore di edi a
ogni ciclo. Il ciclo si può riassumere cosi:
for ( int i = 0; i < eax; i++ )
{
esi += eax;
edi = user[i];
edi *= ecx;
edi += edx;
finale += edi;
ecx++;
edi = esi + ecx;
edx += edi;
}
Tra il 1 e il 2 ciclo
fa queste piccole istruzioni:
XOR EDI,EDI
; azzera edi
TEST EAX,EAX
; controlla se eax = 0
JBE SHORT keygenme.0040121A
; non
saltera' mai
MOV ESI,EDX
; mette edx in esi
IMUL ESI,ESI,2D
; moltiplica esi per 0x2D (45
decimale)
ADD ESI,ECX
; somma ecx a esi
Ora andiamo a spulciare il secondo ciclo:
CICLO:
MOVSX ECX,BYTE PTR SS:[EBP+EDI-2C]
; mette in ecx la EDI-esima lettera del nome
INC ECX
; incrementa ecx
ADD ESI,2D
; somma a esi 0x2D (45 decimale)
IMUL ECX,EDX
; moltiplica ecx per edx
ADD DWORD PTR SS:[EBP-10],ECX
; somma ecx in SS:[EBP-10] - IMPORTANTE!
ADD DWORD PTR SS:[EBP-4],ESI
; somma esi in SS:[EBP-4] - ve la ricordate? :)
INC EDX
; edx = edx + 1
INC EDI
; incrementa edi
CMP EDI,EAX
; confronta edi con eax
JB
CICLO
; se edi < eax torna a inizio ciclo
Fa i soliti calcoli e questa volta la zona di
memoria da tenere d'occhio e' SS:[EBP-10], a cui somma ecx. Un altra zona di
memoria da tenere d'occhio e' SS:[EBP-4], ma non servira' per la creazione del
seriale alla fine, bensi' verrà usata nel 3 ciclo. Pasto il for del 2 ciclo:
esi = edx;
esi *= 0x2D;
esi += ecx;
for ( int i = 0; i < eax; i++ )
{
ecx = user[i];
ecx++;
esi += 0x2D;
ecx *= edx;
finale2 += ecx;
var += esi;
edx++;
}
Tra il 2 e il 3 ciclo fa queste istruzioni: XOR ECX,ECX
; azzera ecx
TEST EAX,EAX
; controlla se eax = 0
JBE SHORT keygenme.00401234
;
e non salterà mai :)
Ora ci resta l'ultimo dei 3 cicli: CICLO:
; inizio ciclo MOVSX ESI,BYTE PTR SS:[EBP+ECX-2C]
; mette in esi la ECX-esima lettera del nome
IMUL ESI,DWORD PTR SS:[EBP-4]
; moltiplica esi per il valore di [EBP-4]
ADD ESI,EDX
; somma edx a esi
ADD DWORD PTR SS:[EBP-C],ESI
; somma esi in [EBP-C] - IMPORTANTE!
INC EDX
; incrementa edx
INC ECX
; incrementa ecx
CMP ECX,EAX
; confronta ecx con eax
JB
CICLO
; se ecx < eax salta a inizio ciclo
Altri calcoli, altro keygen :)
ecx = 0;
for ( int i = 0; i < eax; i++ )
{
esi = user[i];
esi *= var;
esi += edx;
finale3 += esi;
edx++;
}
Siamo
quasi arrivati alla fine. Subito dopo il 3 ciclo fa queste istruzioni: LEA ECX,DWORD PTR DS:[EAX+2]
; carica in ecx l'indirizzo eax + 2
MOV EDX,DWORD PTR SS:[EBP-10]
; mette in edx il valore di [EBP-10]
IMUL ECX,DWORD PTR SS:[EBP-C]
; moltiplica ecx per il valore in [EBP-C]
PUSH ECX
; pusha ecx sullo stack
MOV ECX,DWORD PTR SS:[EBP-14]
; mette in ecx il valore in [EBP-14]
IMUL EAX,ECX
; moltiplica eax per ecx
ADD EDX,ECX
; somma ecx a edx
PUSH EDX
; pusha edx
PUSH EAX
; pusha eax
LEA EAX,DWORD PTR SS:[EBP-50]
; carica in eax l'indirizzo di sprintf
PUSH keygenme.00403150 - Format = "%u-%u-%u" ;
pusha il formato di sprintfazione :D
PUSH EAX
; pusha eax sullo stack
CALL DWORD PTR DS:[<&USER32.wsprintfA>]
; e calla sprintf
Ed eccoci qua alla fine del crack me. Ogni zona di
memoria dei 3 cicli e' servita per creare una parte del serial. Il serial e'
formato cosi: EAX-EDX-ECX. Finalmente posso pastare il keygen finale: #include <stdio.h>
#include <string.h>
int main(void)
{
char user[512];
long ecx, edx, esi, eax, var, edi, finale = 0, finale2 = 0,
finale3 = 0;
do {
printf("Scrivi un user di minimo 4 caratteri: ");
scanf("%s", user);
} while ( strlen(user) < 4);
eax = strlen(user);
ecx = eax * 0x2D;
edx = ecx * 2;
var = edx + edx * 2;
// var sarebbe la zona di memoria SS:[EBP-4] :)
esi = eax * var;
var += eax;
for ( int i = 0; i < eax; i++ )
{
esi += eax;
edi = user[i];
edi *= ecx;
edi += edx;
finale += edi;
ecx++;
edi = esi + ecx;
edx += edi;
}
esi = edx;
esi *= 0x2D;
esi += ecx;
for ( int i = 0; i < eax; i++ )
{
ecx = user[i];
ecx++;
esi += 0x2D;
ecx *= edx;
finale2 += ecx;
var += esi;
edx++;
}
ecx = 0;
for ( int i = 0; i < eax; i++ )
{
esi = user[i];
esi *= var;
esi += edx;
finale3 += esi;
edx++;
}
ecx = eax + 2;
edx = finale2;
ecx *= finale3;
eax *= finale;
edx += finale;
printf("%u-%u-%u", eax, edx, ecx);
return 0;
} E finalmente siamo giunti alla fine di
questo bel crack me di xyzero. Byez :) |