CrackMe 1,2,3 by Cruehead / MiB | ||
Data |
by ILM©2001 |
|
Marzo 2002 |
Published by Quequero | |
Ciò che facciamo in vita... |
Grazie tante ILM i crackme erano abbastanza semplici e specie il terzo puo' dare una mano ai newbies :) |
...riecheggia nell'eternità! |
.... |
E-mail: [email protected] Nickname: ILM©2001 |
.... |
Difficoltà |
(X)NewBies ( )Intermedio ( )Avanzato ( )Master |
Introduzione |
Con questo Tutorial voglio spiegare come si
risolvono i 3 CrackMe by Cruehead / MiB presenti nella sezione CrackMe del
sito di Quequero.
Per semplicità, ma anche per una ragione estetica, i listati ASM non
contengono gli OP-CODE.
Spero di aver fatto un buon lavoro.
Auguro a tutti una buona lettura.
Tools usati |
- SoftIce 4.05
- Hex Editor
- File Mon
- Una tabella ASCII (opzionale ma molto utile)
- Calcolatrice di Windows
Essay |
CrackMe 1 by Cruehead / MiB
Studio della generazione del Serial Number
Iniziamo lo studio di questo
nostro primo CrackMe. Per prima cosa avviamo il programma e proviamo ad inserire
un nome ed un seriale a caso (tanto per vedere cosa succede) premiamo OK e, se
non abbiamo un culo sfondato,ci apparirà una MessageBox di errore.
Carichiamo il nostro beneamato Soft-Ice (SICE) premendo CTRL+D (^D) e settiamo un
BreakPoint (interruzione) sulla API "getdlgitemtexta".
Vi chiederete perché proprio su questa? La risposta è semplice, questa API si
occupa di prelevare del testo dal programma (in questo caso il nostro nome e il
nostro serial). Premete F5 per uscire da SICE ed inserite nuovamente un nome ed
un serial fittizio. Io usero' come nome "ILM" e come serial
"666111666". Premiamo ok e SICE popperà. Ora dovremo premere F12 per
uscire dalla chiamata dell'API ma siccome le chiamate sono 2, una per ogni
textbox, dovremo premere più volte F12 fino ad arrivare qui...
:00401223 cmp eax, 00000000 --->
controlla che sia stato inserito un nome
:00401226 je 004011E6 ----------> se non é stato
inserito nulla salta a 004011E6 ed esci dal programma
:00401228 push 0040218E -------> carica il nome
inserito
:0040122D call 0040137E --------> chiamata ad una
routine
:0040137E mov esi, dword ptr [esp+04] --->
sposta in ESI il valore puntato da [ESP+04]
:00401382 push esi ------------------------> carica
questo valore (ovvero il nome da noi inserito)
:00401383 mov al, byte ptr [esi] -----------> metti in
AL in primo byte di ESI ovvero il primo byte del nome
:00401385 test al, al ----------------------->
controlla che AL non sia vuoto
:00401387 je 0040139C ------------------> se é vuoto
salta a 0040139C
:00401389 cmp al, 41 ---------------------> confronta
il valore di AL con 41h (65d - "A")
:0040138B jb 004013AC -----------------> se é minore
salta a 004013AC
:0040138D cmp al, 5A --------------------> confronta AL
con 5A (90 - "Z")
:0040138F jnb 00401394 -----------------> se é
maggiore salta a 00401394 (vedi sotto)
:00401391 inc esi ------------------------->
incrementa ESI ovvero punta alla lettera successiva
:00401392 jmp 00401383 ----------------> salta a
00401383 e rifai tutto
:00401394 call 004013D2 ---> vai
all'indirizzo 004013D2
:004013D2 sub al, 20 --------------------->
sottrai ad AL il valore 20h (32d)
:004013D4 mov byte ptr [esi], al ----------> sposta il
valore modificato di AL in ESI
:004013D6 ret ----------------------------> ritorna
all'istruzione successiva alla chiamata
:00401399 inc esi ------------> punta alla
lettera successiva
:0040139A jmp 00401383 --> salta a 00401383
Dal listato ASM si intuisce subito che il programma effettua un
controllo su tutti i char del nome che abbiamo inserito.
In principio controlla che si sia effettivamente inserito un nome ed in caso
contrario carica la MessageBox di errore; poi carica in AL uno per un tutti i
char del nome controllando che esso sia composto SOLO da lettere maiuscole e non
da altri caratteri (se le lettere sono minuscole il programma le scrive in
maiuscolo in automatico). Si arriva a questa conclusione poiché il prog.
controlla che i vari char abbiano un valore compreso tra 41h e 5Ah.
Se il valore e' minore esce subito dal programma, invece se e' maggiore viene
fatta una sottrazione: chr del nome - 20h
Esempio: inserisco il nome "ILM" e non ho nessun problema in quanto le
lettere sono tutte maiuscole;
inserisco il nome "IL{" e il nome viene mutato in "IL[" in
quanto al valore del carattere "{" ,che é 123, viene sottratto
20h(32d), per dare il valore 91d che
coincide con il carattere "["
Ora che abbiamo capito come viene controllato il nome, andiamo
avanti e vediamo cosa fa il programma.
Ripartiamo da 0040139C ovvero il punto in cui si arriva quando i caratteri sono
stati tutti controllati
:0040139C pop esi -----------> togli
ESI
:0040139D call 004013C2 ---> chiamata all'indirizzo
004013C2
:004013C2 xor edi, edi ---------------> azzera
EDI
:004013C4 xor ebx, ebx --------------> azzera EBX
:004013C6 mov bl, byte ptr [esi] ------> sposta in BL
il primo char di ESI (ovvero il primo char del nome)
:004013C8 test bl, bl ----------------->
controlla che non sia vuoto
:004013CA je 004013D1 -------------> se è salta a
004013D1
:004013CC add edi, ebx --------------> somma ad EDI il
valore di EBX (ovvero di BL)
:004013CE inc esi --------------------> punta al
char successivo
:004013CF jmp 004013C6 ----------> salta a
004013C6 e ripeti tutto
:004013D1 ret -----------------------> ritorna
all'istruzione successiva alla chiamata
:004013A2 xor edi, 00005678 ----> xora il valore
di EDI con il valore 5678h
:004013A8 mov eax, edi ----------> sposta il
valore di EDI in EAX
:004013AA jmp 004013C1 -------> salta a 004013C1
:004013C1 ret
---------------------> ritorna all'istruzione successiva alla chiamata ovvero
all'indirizzo 00401232
Avete capito cosa ha fatto il programma vero? Ha sommato nel
registro EDI tutti i valori ASCII dei caratteri del nome e, successivamente, ha
xorato il risultato con il valore 5678h mettendolo poi in EAX.
Ora che sappiamo come viene trattato il nome, andiamo a vedere come viene
generato il Serial Number
:00401232 push eax -------------->
carica nello stack EAX (che è il numero calcolato dal nostro nome)
:00401233 push 0040217E ------> carica il valore
all'indirizzo 0040217E (se premete "d 0040217e" su SICE apparirà il
seriale che avrete inserito)
:00401238 call 004013D8 -------> chiamata all'indirizzo
004013D8
:004013D8 xor eax, eax ------------------->
azzera EAX
:004013DA xor edi, edi --------------------> azzera EDI
:004013DC xor ebx, ebx -------------------> azzera EBX
:004013DE mov esi, dword ptr [esp+04] --> sposta
in ESI il valore puntato da [ESP+04] (ovvero il char del nostro seriale)
:004013E2 mov al, 0A --------------------->
sposta in AL il valore 0Ah (10d)
:004013E4 mov bl, byte ptr [esi] ---------->
sposta il char il BL
:004013E6 test bl, bl ---------------------->
controlla che non sia vuoto
:004013E8 je 004013F5 ------------------> se é
vuoto salta a 004013F5
:004013EA sub bl, 30 ----------------------> sottrai a
BL il valore 30h (48d)
:004013ED imul edi, eax -------------------> moltiplica
EAX per EDI e il risultato mettilo in EDI
:004013F0 add edi, ebx -------------------> somma
EBX (BL) a EDI e metti il risultato su EDI
:004013F2 inc esi ------------------------->
punta al char successivo
:004013F3 jmp 004013E2 ----------------> salta a
004013E2 e rifai tutto il giro
:004013F5 xor edi, 00001234 ------------> xora
EDI col valore 1234h
:004013FB mov ebx, edi -----------------> sposta
EDI in EBX
:004013FD ret --------------------------->
ritorna all'istruzione successiva alla chiamata ovvero 0040123D
Il serial viene generato in questo modo: ogni char che abbiamo inserito verrà modificato,
in quanto al valore di ogni char verrà sottratto 30h.
Ogni char verrà sommato in EDI e, il registro, verrà moltiplicato di volta in
volta per il valore 0Ah (10d).
Il risultato verrà poi xorato con 1234h e messo in EBX.
:0040123D add esp, 00000004 --->
somma 04h ad ESP
:00401240 pop eax ---------------> togli EAX
:00401241 cmp eax, ebx ----------> confronta che i
valori di EAX (valore numerico calcolato dal nome) e EBX (seriale inserito
modificato) siano uguali
:00401243 je 0040124C ---------> se sono
uguali salta a 0040124C dove verra' caricata la MessageBox di complimenti
:00401245 call 00401362 ---------> se non sono uguali
vai a 00401362 e carica la MessageBox di errore
Ecco risolto il primo CrackMe.
In poche parole, per trovare un seriale corretto, basta fare una somma dei vari
char del nome (ricordarsi le regole vigenti per i char maggiori di 5Ah e minori
di 41h) e xorare il risultato prima col valore 5678h e poi con il valore
1234h.Convertire poi il risultato in decimale e il gioco e' fatto ;)
Esempio: nome "ILM"
Valore ASCII in HEX delle lettere
"I"=49h
"L"=4Ch
"M"=4Dh
Somma dei valori ASCII
49+4C+4D=E2
1° Xor
E2 xor 5678=569A
2° Xor
569A xor 1234=44AE
Conversione HEX-DEC
44AEh=17582d
Se volete potete partire dal numero 17582, fare tutte le operazioni su ogni char (sub bl,30 / imul eax,edi / xor ecc.) e vedere che il risultato sarà effettivamente 44AEh.
CrackMe 2 by Cruehead / MiB
Serial Fishing
Il CrackMe2 si presenta in modo diverso in quanto si registra
inserendo solo un seriale. Compito nostro sarà trovare quel seriale.
Avviamo il programma e andiamo nella sezione "Enter Password" (che sta
sotto "Help"). Inseriamo una Password a caso e premiamo OK. Apparirà
una MessageBox di errore. Bene! Ora apriamo SICE premendo ^D e settiamo un bel
breakpoint sull'api "getwindowtexta" (bpx getwindowtexta). Usciamo da
SICE premendo F5 e poi inseriamo un seriale a caso (io inserirò il mio solito
666111666). Premiamo OK e SICE poppera' sullo schermo. Ora premiamo un po' di
volte F12 fino a che non arriviamo in questo punto:
:00401223 cmp eax, 00000000
Come mai ho deciso di fermarmi qui? Beh semplice. Se premo nuovamente F12 esco dal prog. e appare la MessageBox di errore ;) ma ora commentiamo un po' il codice.
:00401223 cmp eax, 00000000 --------->
confronta che la lunghezza del seriale inserito col valore 0
:00401226 je 004011E6 ----------------> se é
0,ovvero se non si é inserita nessuna stringa, salta a 004011E6 ed esci dal
prog.
:00401228 push 0040217E -------------> carica i dati
all'indirizzo 0040217e (se in SICE scriviamo d 0040217E apparirà il serial da
noi inserito!)
:0040122Dcall 00401365 ---------------> chiamata ad una
routine all'indirizzo 00401365
:00401365 mov byte ptr [00402118], 00
--------> sposta il valore 0 al primo byte
dell'indirizzo 00402118
:0040136C mov esi, dword ptr [esp+04]
---------> sposta in ESI la DoubleWord puntata da
[ESP+04] (SICE: dd *(ESP+04) --> nostro serial!)
:00401370 push esi ------------------------------>
carica ESI
:00401371 mov al, byte ptr [esi] ----------------->
sposta il AL il byte puntato di ESI
:00401373 test al, al ----------------------------->
confronta che non sia vuoto
:00401375 je 00401390 ------------------------->
se é vuoto salta a 00401390
:00401377 inc byte ptr [00402118] -------------->
incrementa il byte all'indirizzo 00402118
:0040137D cmp al, 41 ---------------------------->
confronta AL col valore 41h (65d - "A")
:0040137F jb 00401385 ------------------------->
se é minore salta a 00401385
:00401381 cmp al, 5A --------------------------->
confronta AL con 5Ah (90d - "Z")
:00401383 jnb 00401388 ------------------------>
se non é minore salta a 00401388 altrimenti vai avanti (00401385)
:00401388 call 004013B2
---------> chiamata all'indirizzo 004013B2
:004013B2 sub al, 20 ------------------->
sottrai 20h (32d) a AL
:004013B4 mov byte ptr [esi], al -------->
sposta AL in ESI
:004013B6 ret -------------------------->
ritorna all'istruzione successiva alla chiamata
:0040138D inc esi
-----------------> incrementa ESI
:0040138E jmp 00401371
--------> salta a 00401371
:00401385 inc esi -------------------------------->
incrementa ESI
:00401386 jmp 00401371 ----------------------->
salta a 00401371 e rifai tutto
Fino a questo punto il CrackMe si comporta esattamente come il
suo fratello minore in quanto effettua dei controlli sui char del seriale da
noi inserito.
C'é solo una piccola differenza. Se il char da noi inserito è minore di 41h
non si fa problemi e va subito a controllare quello successivo; se è maggiore
di 5Ah viene effettuata una sottrazione --> valore del char - 20h.
Ma ora andiamo avanti nel codice....
:00401390 pop esi ---------------->
togli ESI
:00401391 call 00401399 ---------> chiamata alla
routine 00401399
:00401399 xor ebx, ebx ---------------------------->
azzera EBX
:0040139B xor edi, edi ----------------------------->
azzera EDI
:0040139D mov cl, byte ptr [edi+004021A3] ------>
muovi il byte puntato da (EDI+004021A3) in CL (SICE: d 004021A3) -->
"Messing_in_bytes")
:004013A3 mov bl, byte ptr [esi] ------------------->
muovi in BL il byte puntato da ESI (nostro serial modificato dalle routine
precedenti)
:004013A5 test bl, bl ------------------------------->
controllo se BL é vuoto
:004013A7 je 004013B1 --------------------------->
se é vuoto salta a 004013B1
:004013A9 xor bl, cl -------------------------------->
fai uno XOR tra BL e CL (risultato in BL)
:004013AB mov byte ptr [esi], bl ------------------->
sposta BL in ESI
:004013AD inc esi ---------------------------------->
incrementa ESI
:004013AE inc edi ---------------------------------->
incrementa EDI
:004013AF jmp 0040139D ------------------------->
salta a 0040139D e rifai tutto
:004013B1 ret -------------------------------------->
ritorna all'indirizzo 00401326
:00401396 jmp 00401398 --------> salta a 00401398
:00401398 ret --------------------> ritorna
all'istruzione successiva alla prima chiamata che abbiamo esaminato (00401232)
La routine all'indirizzo 00401399 e' una delle + importanti di
tutto il programma in quanto risiedo il cuore dell'algoritmo di crittazione
della password.
Il punto cruciale è all'indirizzo 0040139D dove viene spostato in CL il primo
byte presente all'indirizzo 004021A3.
Se noi con SICE andiamo a vedere cosa c'é li (db 004021A3) ci apparirà la
stringa "Messing_in_bytes".
Le istruzioni successive si occupano praticamente di effettuare uno Xor tra i
char del nostro serial con i char della stringa "Messing_in_bytes" e
di mettere il risultato di tale Xor al posto della char utilizzato. In pratica
il char del nostro seriale che viene utilizzato per lo Xor (e vengono usati
tutti uno ad uno) viene sostituito con il char risultante dal Xor.
00401232 push 0040217E ---------->
carica il valore all'indirizzo 0040217E (il nostro seriale lavorato)
:00401237 call 004013B8 -----------> chiamata
alla routine 004013B8
:004013B8 xor edi, edi ---------------------->
azzera EDI
:004013BC mov cl, byte ptr [00402118] ----->
muovi il byte all'indirizzo 00402118 in CL (lunghezza del nostro seriale)
:004013C2 mov esi, dword ptr [esp+04] ----->
sposta la DB puntata da [ESP+04] in ESI
:004013C6 mov edi, 00402150 -------------->
sposta il valore all'indirizzo 00402150 in EDI
:004013CB repz cmpsb----------------------------->
confronta CL con EDI. Se sono uguali decrementa CL e EDI e rifai il controllo.
Va avanti quando CL ed EDI sono vuoti oppure se sono diversi tra loro.
:004013CD ret ------------------------------->
ritorna all'istruzione successiva alla chiamata
:0040123C add esp, 00000004 --------> aggiungi ad ESP
il valore 4h
:0040123F test cl, cl ------------------->
controlla se CL é uguale a 0
:00401241 je 0040124A --------------> se é
uguale a 0 salta a 0040124A e carica la MessageBox di complimenti
:00401243 call 00401349 -------------> vai
all'indirizzo 00401349 e carica la MessageBox di errore
Bene!Dovreste aver capito!NO??????? Beh ora vi spiego meglio;)
Allora la routine all'indirizzo 004013B8 non fa altro che controllare i char del
nostro seriale modificato con i char alla locazione 00402118.
Se sono TUTTI uguali avete risolto il CrackMe, altrimenti no!
Dovete sapere quindi quali sono i byte con i quali si esegue il confronto;
andate in SICE e scrivete db 00402118. Annotatevi in un foglio di carta tutti i
bytes della prima riga che sono : 1F 2C 37 36 3B 3D 28 19 3D 26 1A 31 2D 3B 37
3E.
Ora vi ricordate prima che il nostro serial era stato xorato con la stringa
"Messing_in_bytes"? Allora la soluzione del CrackMe è semplice.
Basterà xorare i bytes al'indirizzo 0042118 con i char (in HEX) della stringa
"Messing_in_bytes" e si troverà il corretto seriale! Semplice no!
1F XOR 4D "M" = 52 --> R
2C XOR 65 "e" = 49 --> I
37 XOR 73 "s" = 44 --> D
36 XOR 73 "s" = 45 --> E
3B XOR 69 "i" = 52 --> R
3D XOR 6E "n" = 53 --> S
28 XOR 67 "g" = 4F --> O
19 XOR 5F "_"= 46 --> F
3D XOR 69 "i" = 54 --> T
26 XOR 6E "n" = 48 --> H
1A XOR 5F "-" = 45 --> E
31 XOR 62 "b" = 53 --> S
2D XOR 79 "y" = 54 --> T
3B XOR 74 "t" = 4F --> O
37 XOR 65 "e" = 52 --> R
3E XOR 73 "s" = 4D --> M
La password corretta sarà quindi "RIDERSOFTHESTORM".
CrackMe 3 by Cruehead / MiB
Make a KeyFile
Siamo giunti all'ultimo CrackMe,il terzo. Come leggiamo dalle
istruzioni questo prog. necessità di un KeyFile. Per prima cosa avviamo il
programma e vediamo cosa succede. Niente!!!! Solo una stringa "Uncracked"
in alto! Allora cominciamo a cracckarlo ;)
Avviamo FileMon e poi avviamo il programma. Su FileMon appariranno delle
stringhe relative al nostro CrackMe3 ed in particolare:
- CRACKME3 READ
C:\CrackMe\3\CRACKME3.EXE SUCCESS
- CRACKME3 READ
C:\CrackMe\3\CRACKME3.KEY NOTFOUND
Da questo notiamo che il KeyFile avrà nome CRACKME3.KEY e che dovrà essere
nella stessa cartella del prog.
Allora creiamone uno. Avviamo il programma e... "Uncracked".
Beh, sarebbe stato troppo semplice!!!!
Apriamo allora SICE e settiamo un BreakPoint all'API ReadFile (API che gestisce
la lettura di file); usciamo premendo F5 e poi avviamo il programma.
Dovremo premere un bel po' di volte F12 fino a che in basso a destra di SICE
apparirà il nome CRACKME3 (prima ci sono tutte le chiamate di Windows).
Arriveremo in questo punto.....
:00401066 cmp dword ptr [004021A0], 00000012 --------->
confronta la lunghezza del testo inserito nel KeyFile con il valore 12h (18d)
:0040106D jne 00401037 ----------------------------------->
se non é uguale a 12h salta a 00401037 ed esci dal programma
:0040106F push 00402008 ---------------------------------->
carica il dato all'indirizzo 00402008 (SICE: dd 00402008 ---> testo nel
KeyFile)
:00401074 call 00401311 ----------------------------------->
chiamata all'indirizzo 00401311
:00401311 xor ecx, ecx
---------------------------> azzera ECX
:00401313 xor eax, eax --------------------------->
azzera EAX
:00401315 mov esi, dword ptr [esp+04] ---------->
sposta in ESI la DoubleWord puntata da [ESP+04]
:00401319 mov bl, 41 ---------------------------->
sposta in BL il valore 41h (65d - "A")
:0040131B mov al, byte ptr [esi] ------------------>
sposta il byte di ESI il AL
:0040131D xor al, bl ------------------------------>
fai uno XOR tra AL e BL (risultato in AL)
:0040131F mov byte ptr [esi], al ------------------>
sposta AL in ESI (sostituisci il byte di ESI con quello xorato)
:00401321 inc esi --------------------------------->
incrementa ESI
:00401322 inc bl ---------------------------------->
incrementa BL
:00401324 add dword ptr [004020F9], eax ------->
somma EAX (ovvero AL) alla DoubleWord all'indirizzo 004020F9
:0040132Acmp al, 00 ----------------------------->
confronta AL con 00
:0040132C je 00401335 -------------------------->
se é uguale a 00 salta a 00401335
:0040132E inc cl ---------------------------------->
incrementa CL
:00401330 cmp bl, 4F ----------------------------->
confronta BL con 4Fh (79d - "O")
:00401333 jne 0040131B ------------------------->
se é uguale salta all'indirizzo 0040131B
:00401335 mov dword ptr [00402149], ecx ------->
sposta ECX (ovvero CL) nella DoubleWord all'indirizzo 00402149
:0040133B ret ------------------------------------->
ritorna all'indirizzo successivo alla chiamata
:00401079 xor dword ptr [004020F9], 12345678 ----------> fai uno Xor tra la DoubleWord presente all'indirizzo 004020F9 e il valore 12345678h
Analizziamo questo pezzo di codice. Allora il programma prima di
tutto controlla che la lunghezza di ciò che abbiamo inserito nel KeyFile sia
uguale a 12h ovvero 18d; in poche parole dovremmo inserire 18 char. Se ne ha
trovati 12h va avanti ed effettua uno Xor tra il char inserito da noi ed il char
presente in BL.
Come vediamo in BL all'inizio viene caricato il char "A"; poi, quando
si punto al char successivo nel nostro KeyFile, BL viene incrementato e quindi
il secondo Xor verrà effettuato con il char "B" (controllate una
tabella ASCII) e cosi via fino alla fine.Ogni risultato dello Xor viene
memorizzato in una DoubleWord all'indirzzo 004020F9. Quando BL assume il char
"O" allora si esce dal ciclo e la DoubleWord all'indirizzo 004020F9
viene Xorata col valore 12345678h.
(Ricordarsi che ogni char xorato viene poi sostituito, nel KeyFile, col
risultato dello xor)
Riassumendo: pensiamo di aver inserito la stringa
">>>ILM@2001<<<<1234" le operazioni sranno le
seguenti:
Primi 14 char del nome = ">>>ILM@2001<<<"
Chr Seriale (in HEX)
>=3E
>=3E
>=3E
I=49
L=4C
M=4D
@=40
2=32
0=30
0=30
1=31
<=3C
<=3C
<=3C
Chr (in HEX) con i quali verra' effettuato lo XOR
A=41
B=42
C=43
D=44
E=45
F=46
G=47
H=48
I=49
J=4A
K=4B
L=4C
M=4D
N=4E
Operazioni di Xor
3E xor 41 = 7F
3E xor 42 = 7C
3E xor 43 = 7D
49 xor 44 = D
4C xor 45 = 9
4D xor 46 = B
40 xor 47 = 7
32 xor 48 = 7A
30 xor 49 = 79
30 xor 4A = 7A
31 xor 4B = 7A
3C xor 4C = 70
3C xor 4D = 71
3C xor 4E = 72
Somma i risultati dello XOR
7F+7C+7D+D+9+B+7+7A+79+7A+7A+70+71+72=4DA
XORA il risultato col valore 12345678h
4DA xor 12345678=123452A2
Quindi se inseriamo la stringa ">>>ILM@2001<<<1234" la DoubleWord all'indirizzo 004020F9 assumerà il valore 123452A2
Ma ora andiamo avanti nel programma....
:00401083 add esp, 00000004 ---------->
somma ad ESP il valore 4h
:00401086 push 00402008 --------------> carica il
valore presente all'indirizzo 00402008 (il nostro testo del KeyFile modificato)
:0040108B call 0040133C --------------> chiamata alla
routine all'indirizzo 0040133C
:0040133C mov esi, dword ptr [esp+04]
--------> sposta la DoubleWord puntata da [ESP+04] in
ESI (il nostro testo modificato)
:00401340 add esi, 0000000E ------------------>
somma 0Eh (14d) ad ESI
:00401343 mov eax, dword ptr [esi] ------------>
sposta la DoubleWord puntata da ESI in EAX (ovvero gli utlimi 4 char del testo
del KeyFile)
:00401345 ret ----------------------------------->
ritorna all'istruzione successiva alla chiamata
:00401093 cmp eax, dword ptr [004020F9] ----------->
confronta la DoubleWord in 004020F9 con EAX
:00401099 setz al -------------------------------------->
non ne sono sicuro ma dovrebbe essere setta il flag Z ad AL (o almeno una cosa
del genere)
:0040109C push eax ------------------------------------>
carica EAX
:0040109D test al, al ------------------------------------>
Al é 0?
:0040109F je 00401037 -------------------------------->
SI'. Allora salta a 00401037 e carica la MessageBox di complimenti
:004010A1 push 0040210E ----------------------------->
carica la stringa "CrackMe
3.0 "
:004010A6 call 00401346 ------------------------------->
chiamata che caricherà la stringa "CrackMe 3.0 Uncracked"
L'ultimo pezzo del codice é molto semplice e ci fa capire che
gli ultimi 4 char del testo che noi abbiamo inserito nel KeyFile devono essere
uguali alla DoubleWord presente all'indirizzo 004020F9. Questo si deduce in
quanto in EAX vengono caricati gli ultimi 4 char del testo del KeyFile e poi EAX
viene comparata con la DoubleWord, Se sono uguali allora abbiamo Cracckato il
programma altrimenti no.
Per vedere quali sono questi bytes, o fate i calcoli come vi ho spiegato
precedentemente, oppure basta aprire SICE e digitare (in un qualsiasi indirizzo
purché sia successivo alle operazioni di Xor precedentemente fatte) dd
004020F9. In questo modo apparirà il valore della DoubleWord che per me é
123452A2.
Adesso basta aprire il KeyFile con un HexEditor ed inserire gli ultimi 4 bytes
del testo in modo corretto.
Bisogna inserire i bytes partendo da destra verso sinistra a coppia.
In poche parole bisognerà scrivere: A2 52 34 12. Salvate, avviate il CrackMe e...
voila'! Cracckato!!!!!!!!!
Apparirà anche una MessageBox di complimenti dove comparirà "Cracked by " ed una serie di simboli che guarda caso sono uguali al nostro testo dopo che ha subito le modifiche. Per far apparire il nome che si vuole bisogna procedere in questo modo:
Scegliere un nome da far apparire, io scelgo >>>ILM@2001<<<
Fare le operazioni di Xor con le lettere "ABCDEFGHILMN"
Scrivere i risultati dei vari Xor sul KeyFile
Calcolare gli ultimi 4 bytes da inserire nel KeyFile
Operazioni di Xor
3E xor 41 = 7F
3E xor 42 = 7C
3E xor 43 = 7D
49 xor 44 = D
4C xor 45 = 9
4D xor 46 = B
40 xor 47 = 7
32 xor 48 = 7A
30 xor 49 = 79
30 xor 4A = 7A
31 xor 4B = 7A
3C xor 4C = 70
3C xor 4D = 71
3C xor 4E = 72
Il primi 14 bytes del KeyFile saranno quindi 7F 7C 7D 0D 09
0B 07 7A 79 7A 7A 70 71 72
Calcolo gli ultimi 4 bytes e trovo: 2B 55 34 12
Quindi il mio CRACKME3.KEY sarà formato da questi bytes: 7F 7C 7D 0D 09 0B
07 7A 79 7A 7A 70 71 72 2B 55 34 12
Ricordarsi che il nome che verrà stampato dovrà essere
OBBLIGATORIAMENTE di 14 char.
ILM©2001
Note finali |
Spero di essere stato chiaro e preciso in ogni mio punto. Mi scuso per qualsiasi errore non voluto :)
Disclaimer |
Vorrei ricordare che il software va comprato e non rubato, dovete registrare il vostro prodotto dopo il periodo di valutazione. Non mi ritengo responsabile per eventuali danni causati al vostro computer determinati dall'uso improprio di questo tutorial. Questo documento è stato scritto per invogliare il consumatore a registrare legalmente i propri programmi, e non a fargli fare uso dei tantissimi file crack presenti in rete, infatti tale documento aiuta a comprendere lo sforzo immane che ogni singolo programmatore ha dovuto portare avanti per fornire ai rispettivi consumatori i migliori prodotti possibili.
Noi reversiamo al solo scopo informativo e di miglioramento del linguaggio Assembly.