ROMPIAMO IL CODICE (LEONARDO v1.2) DA VINCI

Data

by DaGoN

 

23/04/2005

UIC's Home Page

Published by Quequero

"Se in un primo momento l'idea non è assurda,
allora non c'è nessuna speranza che si realizzi"

Albert Einstein

Grazie tante dago!

Ogni drago genera un S. Giorgio che lo uccide

Kahlil Gibran

...

E-mail: dagon AT xxx.it

....

Difficolt�

( )NewBies ()Intermedio (X)Avanzato ( )Master

 

 

Introduzione

Cosa dicono gli autori:

Leonardo è un programma per computer che offre la possibilità di effettuare ricerche statistiche avanzate, e consente di ricavare dati preziosi per la formulazione di pronostici ad alta attendibilità. E' uno strumento versatile e potente, indispensabile al ricercatore che desidera analizzare e  valutare tutti quei dati che la statistica rende disponibili.

Insomma, un comunissimo programma per il Lotto. Ma...

 

Tools usati

I tools utilizzati sono:
OllyDgb 1.10 (un ottimo debugger)

W32Dasm v8.93 (un buon disassemblatore)

PEid (solo per prassi)

WinHex (non necessario.. ma l'ho usato)

Borland C++ (Usato per trovare la chiave di decrypting e per il keygen)

Masm 8.2 (usato per fare il keygen)

Keygen + sorgenti

URL o FTP del programma

www.camelott.it

Essay

1. Leonardo

Installiamo leonardo e lanciamo il file leonardo.exe. Ecco ciò che vedremo:

A colpo d'occhio il codice utente sembrerebbe interessante; inseriamo nel nome "DaGoN", nel cognome "DgN", nel seriale "11223344" e premiamo il pulsante "Registrami". Il programma parte ma subito dopo si chiude. Gulp!
Se riapriamo leonardo noteremo che il prog riparte ma si richiude immediatamente dopo. Da qualche parte il programma ha memorizzato i nostri dati. Qui sono stato fortunato: ho cercato nella cartella di leonardo il nome "DaGoN" e l'ho trovato nel file Etc/tabelr.lot insieme a "DgN" e al mio fake serial "11223344". Cancelliamo il file tabelr.lot dalla cartella Etc e leonardo ritornerà come nuovo.

Per prassi diamo un'occhiata a cosa stiamo cercando di reversare:

Bene, niente packers o crypters in giro :D. Ora usiamo il vecchio ma sempre utile w32Dasm per disassemblare il leonardino. Qui la fortuna ci ha provato ancora, bella topona! Intuito o culo, c'è da dire che ho trovato quasi subito il codice che controlla la chiusura della form.

Mi sono detto: "Se il programma si chiude, da qualche parte dovrà pur chiamare il metodo close della Form."

Premendo sul pulsante [imp fn] (Import function) notiamo il metodo vcl40::Form::TCustomForm:Close(void()), cioè il metodo che viene richiamato quando si chiude una form. Ma quale sarà il nostro? Quello buono? Io ho puntato su quello della Form1, nonchè la form principale. Questo è il codice disassemblato:

* Reference To: Camelottprj._Form1
|
:0040DBF4 8B0D687E4800 mov ecx, dword ptr [00487E68]
:0040DBFA 8B81E0020000 mov eax, dword ptr [ecx+000002E0]
:0040DC00 8B80EC010000 mov eax, dword ptr [eax+000001EC]
:0040DC06 BA01000000 mov edx, 00000001
:0040DC0B E810E90500 call 0046C520
:0040DC10 5A pop edx
:0040DC11 E810E90500 call 0046C526
:0040DC16 FF4DF4 dec [ebp-0C]
:0040DC19 8D45FC lea eax, dword ptr [ebp-04]
:0040DC1C BA02000000 mov edx, 00000002
:0040DC21 E89ADF0500 call 0046BBC0
:0040DC26 A0ACD44600 mov al, byte ptr [0046D4AC] // Muovi in al il byte all'indirizzo 0046D4AC
:0040DC2B 84C0 test al, al //<--- se è 00 salta, altrimenti chiudi la form
:0040DC2D 740A je 0040DC39
:0040DC2F A1687E4800 mov eax, dword ptr [00487E68]

* Reference To: Vcl40.Forms::TCustomForm::Close(void()), Ord:0000h
|
:0040DC34 E839E60500 Call 0046C272

Sembrerebbe che tutto dipenda dal flag all'indirizzo 0046D4AC, apriamo Ollydbg e carichiamo Leonardo.exe; nella finestra Hex dump (quella sotto la finestra codice) premiamo Ctrl+g (Go to) e digitiamo 0046D4AC nella form di Olly:

Andremo a finire proprio all'indirizzo del flag, qui metteremo un bel breakpoint memory, on write. Quando qualsiasi istruzione cerca di scrivere al nostro indirizzo olly breakerà. Selezioniamo il primo byte e con il tasto destro applichiamo il breakpoint memory, on write come in figura:

Premiamo F9 e ridigitiamo nel nome "DaGoN", nel cognome "DgN" e nel seriale "11223344". Premiamo il pulsante "Registrami" e questa volta olly breakerà nel punto dove leonardo cercherà di settare a 1 il flag, come in figura:

Mucho interessante:

0040E30C /$ 55 PUSH EBP
0040E30D |. 8BEC MOV EBP,ESP
0040E30F |. 68 F1E84600 PUSH Leonardo.0046E8F1 ; /s2 = "LEONARDO"
0040E314 |. 68 7C7E4800 PUSH Leonardo.00487E7C ; |s1 = "_+]/W!@‚B..... " // ho tagliato...
0040E319 |. E8 1AE50500 CALL <JMP.&cp3245mt._strcmp> ; \_strcmp
0040E31E |. 83C4 08 ADD ESP,8
0040E321 |. 85C0 TEST EAX,EAX //sono uguali(EAX=0)? se si salta...
0040E323 |. 74 07 JE SHORT Leonardo.0040E32C
0040E325 |. C605 ACD44600 >MOV BYTE PTR DS:[46D4AC],1
0040E32C |> 68 FAE84600 PUSH Leonardo.0046E8FA ; /s2 = "1.0"
0040E331 |. 68 9A7E4800 PUSH Leonardo.00487E9A ; |s1 = ""@p9 ... " // ho tagliato
0040E336 |. E8 FDE40500 CALL <JMP.&cp3245mt._strcmp> ; \_strcmp
0040E33B |. 83C4 08 ADD ESP,8
0040E33E |. 85C0 TEST EAX,EAX //sono uguali(EAX=0)? se si salta...
0040E340 |. 74 07 JE SHORT Leonardo.0040E349
0040E342 |. C605 ACD44600 >MOV BYTE PTR DS:[46D4AC],1
0040E349 |> 68 FEE84600 PUSH Leonardo.0046E8FE ; /s2 = "WIZARD 1999"
0040E34E |. 68 9E7E4800 PUSH Leonardo.00487E9E ; |s1 = "9 I/....." // ho tagliato
0040E353 |. E8 E0E40500 CALL <JMP.&cp3245mt._strcmp> ; \_strcmp
0040E358 |. 83C4 08 ADD ESP,8
0040E35B |. 85C0 TEST EAX,EAX //sono uguali(EAX=0)? se si salta...
0040E35D |. 74 07 JE SHORT Leonardo.0040E366
0040E35F |. C605 ACD44600 >MOV BYTE PTR DS:[46D4AC],1
0040E366 |> D905 BC7E4800 FLD DWORD PTR DS:[487EBC] //prende la dword all'indirizzo 487EBC e la confronta
0040E36C |. D81D 80E34000 FCOMP DWORD PTR DS:[40E380] //con la dword 0000803F all'indirizzo 40E380

0040E372 |. DFE0 FSTSW AX // http://webster.cs.ucr.edu/AoA/DOS/ch14/CH14-5.html
0040E374 |. 9E SAHF // per chi volesse approffondire queste istruzioni
0040E375 |. 74 07 JE SHORT Leonardo.0040E37E // se sono uguali salta...
0040E377 |. C605 ACD44600 >MOV BYTE PTR DS:[46D4AC],1
0040E37E |> 5D POP EBP
0040E37F \. C3 RETN

La _strcmp non fa altro che confrontare 2 stringhe, s2 =LEONARDO con la s1, s2 =1.0 con s1 e s2 = WIZARD 1999 con s1. Voi direte: "Chi se ne frega? Ormai è fatta! Basta invertire i je in jne e il prog funziona". Questo è il risultato che ho raggiunto 2 anni fa, è un grande flop... apparentemente tutto fila liscio, finchè non apriamo
Statistiche->Estratto->Tabellone Estratti: qui i dati sono completamente sballati! Niente donne e champagne, per noi solo seghe e gazzosa! Vediamo di guadagnarci almeno un bichierino di tevernello... L'analisi è tutto, ricordatelo sempre! Cosa abbiamo in mano finora?(una gazzosa?) Sappiamo che alla riga 0040E314, il push 00487E7C (controllate quale indirizzo di memoria c'è nella vostra macchina) deve essere uguale a LEONARDO, altrimenti il prog si chiude; mmm... usiamo la stessa tecnica del flag! Riavviamo il debug per leonardo, nella finestra Hex dump (quella sotto la finestra codice) premiamo Ctrl+g (Go to) e digitiamo 00487E7C nella form di Olly. Mettiamoci un bel breakpoint memory, on write e vediamo chi va a scrivere quella serie di byte che dovrebbero essere uguali a LEONARDO. Premete f9 e vi ritroverete nel modulo cp3245mt, steppate con f8 fino a ritornare su Leonardo.

00401C63 |> 68 A4D74600 PUSH Leonardo.0046D7A4 ; /mode = "rb"
00401C68 |. 68 8BD74600 PUSH Leonardo.0046D78B ; |path = ".\indirect\tabelcinq.lot" // Questo è il file!
00401C6D |. E8 5AAB0600 CALL <JMP.&cp3245mt._fopen> ; \_fopen
00401C72 |. 83C4 08     ADD ESP,8
00401C75 |. 8945 D4     MOV DWORD PTR SS:[EBP-2C],EAX
00401C78 |. 8B4D D4     MOV ECX,DWORD PTR SS:[EBP-2C]
00401C7B |. 85C9        TEST ECX,ECX
00401C7D |. 75 29       JNZ SHORT Leonardo.00401CA8
00401C7F |. 6A 10       PUSH 10
00401C81 |. B9 34D84600 MOV ECX,Leonardo.0046D834 ; ASCII "Componenti Mancanti"
00401C86 |. BA A7D74600 MOV EDX,Leonardo.0046D7A7 ; ASCII "Non tutte le componenti di Leonardo sono installate correttamente.
Si prega di reinstallare il software o di contattare il servizio clienti."
00401C8B |. A1 5829E000 MOV EAX,DWORD PTR DS:[<&Vcl40.@Forms@App>
00401C90 |. 8B00        MOV EAX,DWORD PTR DS:[EAX]
00401C92 |. E8 A59D0600 CALL Leonardo.0046BA3C
00401C97 |. 33C0        XOR EAX,EAX
00401C99 |. 8B55 D8     MOV EDX,DWORD PTR SS:[EBP-28]
00401C9C |. 64:8915     MOV DWORD PTR FS:[0],EDX
00401CA3 |. E9 FF100000 JMP Leonardo.00402DA7
00401CA8 |> FF75 D4     PUSH DWORD PTR SS:[EBP-2C] ; /stream
00401CAB |. 6A 01       PUSH 1 ; |n = 1
00401CAD |. 6A 44       PUSH 44 ; |size = 44 (68.)
00401CAF |. 68 7C7E4800 PUSH Leonardo.00487E7C ; |ptr = Leonardo.00487E7C
00401CB4 |. E8 1FAB0600 CALL <JMP.&cp3245mt._fread> ; \_fread // <-- legge il file tabelcinq.lot
00401CB9 |. 83C4 10     ADD ESP,10 // <--- se tutto è andato bene noi spunteremo qui
00401CBC |. 6A 44       PUSH 44 ; /Arg2 = 00000044
00401CBE |. 68 7C7E4800 PUSH Leonardo.00487E7C ; |Arg1 = 00487E7C
00401CC3 |. E8 3CB60000 CALL Leonardo.0040D304 ; \Leonardo.0040D304

Dovremmo spuntare alla 401CB9. Verifichiamo che i primi byte del file tabelcinq.lot siano uguali a quello che vediamo su olly.

Parliamo dei byte alla 00487E7C -> DD 69 06 DF e così via... bene se aprite il file .\indirect\tabelcinq.lot con winhex vi accorgerete che i byte sono uguali. Già dovreste sapere che cosa succederà se premiamo f9. Vi ricordate? Noi dovremmo aspettarci la stringa "LEONARDO", ma nel file non c'è, questo significa che il file è criptato. Allora, se premiamo f9 finiremo nel punto dove il programma cercherà di decriptarlo (questo ve lo anticipo hehehe). Questa è la chiave di tutto, il punto dove le mura di Jerico crolleranno al nostro passo...

Premete F9:

2. Il Cryptex

Ecco la routine di decrypting:

55           PUSH EBP
8BEC         MOV EBP,ESP
83C4F0       ADD ESP,-10
33C0         XOR EAX,EAX
8945F8       MOV DWORD PTR SS:[EBP-8],EAX
33D2         XOR EDX,EDX
8955FC       MOV DWORD PTR SS:[EBP-4],EDX
8B4DFC       MOV ECX,DWORD PTR SS:[EBP-4]
8B450C       MOV EAX,DWORD PTR SS:[EBP+C]
3BC8         CMP ECX,EAX
7D56         JGE SHORT Leonardo.0040D374
C645F300     MOV BYTE PTR SS:[EBP-D],0                    \
33D2         XOR EDX,EDX                                   |
8955F4       MOV DWORD PTR SS:[EBP-C],EDX                  |
8B4DF8       MOV ECX,DWORD PTR SS:[EBP-8]          \       |
8D0C49       LEA ECX,DWORD PTR DS:[ECX+ECX*2]       |      |
8D817C9A4800 LEA EAX,DWORD PTR DS:[ECX+488690] // carica in EAX l'indirizzo della chiave
8B55F4       MOV EDX,DWORD PTR SS:[EBP-C] // indice ciclo  |
8A0C10       MOV CL,BYTE PTR DS:[EAX+EDX] // mette in cl il primo byte della chiave
B001         MOV AL,1     // AL = 1                 |      |
D2E0         SHL AL,CL    // Shifta a sinistra AL con CL (valore n della chiave * 2)
0845F3       OR BYTE PTR SS:[EBP-D],AL // fa un or con il valore n della chiave
FF45F4       INC DWORD PTR SS:[EBP-C] // index +1   |      |
8B55F4       MOV EDX,DWORD PTR SS:[EBP-C] //indice in edx  |
83FA03       CMP EDX,3 // index è uguale a 3? Se si esci dal ciclo
7CDCJL       JL SHORT Leonardo.0040D327            /       |
8B4D08       MOV ECX,DWORD PTR SS:[EBP+8]                  |
8B45FC       MOV EAX,DWORD PTR SS:[EBP-4]                  |
8A55F3       MOV DL,BYTE PTR SS:[EBP-D] // mette in DL il valore che sarà utilizzato per il decrypting alla riga successiva
301401       XOR BYTE PTR DS:[ECX+EAX],DL // questo è il punto in cui siamo atterrati (XORA il primo byte del file caricato in memoria e così via)
FF45F8       INC DWORD PTR SS:[EBP-8]                      |
8B4DF8       MOV ECX,DWORD PTR SS:[EBP-8]                  |
83F903       CMP ECX,3                                     |
7C05         JL SHORT Leonardo.0040D367                    |
33C0         XOR EAX,EAX                                   |
8945F8       MOV DWORD PTR SS:[EBP-8],EAX                  |
FF45FC       INC DWORD PTR SS:[EBP-4]                      |
8B55FC       MOV EDX,DWORD PTR SS:[EBP-4]                  |
8B4D0C       MOV ECX,DWORD PTR SS:[EBP+C]                  |
3BD1         CMP EDX,ECX                                   |
7CAA         JL SHORT Leonardo.0040D31E                   /
8BE5         MOV ESP,EBP
5D           POP EBP
C3           RETN

Tutto il decrypting è gestito dal valore in DL (XOR BYTE PTR DS:[ECX+EAX],DL). Qui mi scuso con LittleLuk e con tutti quelli che hanno letto il mio post. Ho teorizzato sul crypting/decrypting a base di XOR e poi l'ho escluso, sostenedo che era solo un esempio, che la routine di crypting/decrypting non era a base di XOR, ma realizzata con un'altro algoritmo. Ebbene, dopo averlo reversato per benino sono arrivato a questo: avevo teorizzato bene e praticato MALE!

LEA EAX,DWORD PTR DS:[ECX+488690] a questo indirizzo troviamo i byte [01 05 06, 07 03 05, 02 06 08]. Questi byte dipendono dal seriale e dal codice utente(lo dico in anticipo... poi ci arriveremo), quindi non state a controllare se sono uguali ai quelli che avete sulla vostra macchina. Noterete che il ciclo prende i primi 3 byte della chiave, elabora i byte e mette in DL il risultato, poi xora.

index = 0 -> Byte(01) , index = 1 -> Byte(05) , index = 2 -> Byte(06) , elabora con lo shl 1,CL == (CL * 2), esce dal ciclo e valorizza DL, poi decrypta il primo byte del file tabelcinq.lot con il valore in DL. Questi sono i byte che dobbiamo xorare, vi ricordate? Sono i primi byte del file tabelcinq.lot -> DD 69 06 DF 6D 1B D5 63.

XOR DD,DL = L
XOR 69,DL = E
XOR 06,DL = O
XOR DF,DL = N
XOR 6D,DL = A
XOR 1B,DL = R
XOR D5,DL = D
XOR 63,DL = O

Quale valore dovrà assumere DL perchè il byte DD xorato diventi 4C (L in esadecimale) e così via? Io ho risolto così: ho aperto Visual C++ 6 e ho dato inizio a un progetto Console. Voglio fare le cose semplici, quindi niente codice da professionista! L è uguale a 4C in esadecimale.

Quindi ho scritto questo codice:

#include "stdafx.h"

int main(int argc, char* argv[])
{

int byteDD = 0xDD; // Primo byte DD criptato
int byte4C = 0x4C; // La L di Leonardo espressa in esadecimale
int brutalNumber = 255; // Prova tutti i numeri da 0 a 255

for(int DL=0; DL < brutalNumber; DL++ )
{

int xorValue = byte4C ^ DL; // xora 4C con 0, con 1 , con 2... 255 fino a trovare il valore
                                           // per il quale 4C xor DL = DD. Dove DL è la nostra incognita

 
   
if(xorValue == byteDD){ // controlla se il valore i xorato con 4C è uguale al byte Cryptato
        printf( "Valore di DL perchè 4C(L) xorato sia uguale a DD: %x esadecimale\n", DL ); // Visualizza il valore di DL
   }
}


return 0;
}

 

In allegato trovate il codice ottimizzato in Visual C++ che fa un brutalforce su i primi 8 byte (LEONARDO). Si nota immediatamente una cosa molto curiosa:

XOR DD, DL = L  <----- DL = 91
XOR 69,DL = E    <----- DL = 2C
XOR 06,DL = O   <----- DL = 49
XOR DF,DL = N  <----- DL = 91
XOR 6D,DL = A   <----- DL = 2C
XOR 1B,DL = R   <----- DL = 49
XOR D5,DL = D   <----- DL = 91
XOR 63,DL = O    <----- DL = 2C

Noterete che abbiamo a che fare con una tabellina di XOR: I byte 91,2C,49 si ripetono fino alla fine del file. La routine di decrypting non fa altro che prendere i primi tre byte della chiave, giocarci un po', ottenendo così il primo valore di DL = 91 e decriptare, prendere gli altri tre, giocarci un po' e decriptare con DL = 2C e poi prendere gli ultimi 3 byte, giocarci un po' e decryptare con DL = 49, fino alla fine del file. Ricordate il LEA EAX,DWORD PTR DS:[ECX+489A7C], a questo indirizzo troviamo questi byte, [01 05 06, 07 03 05, 02 06 08].

Ora sappiamo che combina il primo cicletto: 01 05 06 07 03 05 02 06 08
  DL=91 DL=2C DL=49

8B4DF8       MOV ECX,DWORD PTR SS:[EBP-8]          \       |
8D0C49       LEA ECX,DWORD PTR DS:[ECX+ECX*2]       |      |
8D817C9A4800 LEA EAX,DWORD PTR DS:[ECX+488690] //l'indirizzo della chiave [01 05 06, 07 03 05, 02 06 08]
8B55F4       MOV EDX,DWORD PTR SS:[EBP-C] // indice ciclo  |
8A0C10       MOV CL,BYTE PTR DS:[EAX+EDX] // in cl il primo byte della chiave (prima 01, poi 05, poi 06)
B001         MOV AL,1     // AL = 1                 |      |
D2E0         SHL AL,CL    // Shifta a sinistra AL con CL (valore n della chiave * 2)
0845F3       OR BYTE PTR SS:[EBP-D],AL // fa un or con il valore n della chiave
FF45F4       INC DWORD PTR SS:[EBP-C] // index +1   |      |
8B55F4       MOV EDX,DWORD PTR SS:[EBP-C] //indice in edx  |
83FA03       CMP EDX,3 // index è uguale a 3? Se si esci dal ciclo
7CDCJL       JL SHORT Leonardo.0040D327            /       |

La domanda è questa: Quale valore dovranno avere i primi tre byte(01, 05, 06) della chiave perchè DL sia uguale a 91?

All'uscita di questo ciclo noi SAPPIAMO che in [EBP-D],AL (andrà poi a finire in DL) ci deve essere 91. Bene, qui io non ho assolutamente reversato , ho semplicemente cambiato i valori dei primi tre byte 01,05,06 fino a che non ho ottenuto 91 in DL. Non è una cosa complessa, ricordate gli enigmi di Resident Evil? Poi l'ho fatto fino ad ottenere 2C e poi fino ad ottenere 49. Alla fine ecco la famigerata chiave: (91 = 00,07,04) (2C = 02,03,05) (49 = 00,03,06). Questa è la chiave di decrypting che dovrebbe essere scritta all'indirizzo [ECX+488690] .

Qui ragazzi ci meritiamo una serata con Eva Henger... o con Rocco Siffredi, dipende dai gusti hehehe. Le cose buttano bene, ma siamo solo alla fine della prima parte!

Capitolo 2

Ora sappiamo che abbiamo a che fare con una tabellina Xor con valori 91,2C,49. A loro volta questi tre valori vengono ottenuti da una chiave a nove cifre all'indirizzo [ECX+488690] [01 05 06, 07 03 05, 02 06 08]. Ma chi diavolo andrà mai a scrivere questi nove bytes? Squadra vincente non si cambia... Mettiamo un breakpoint memory, on write all'indirizzo 489A7C. Ricarichiamo Leonardo su Olly, nella finestra hex dump premiamo Ctrl+g(Go to) e inseriamo nella form di Olly l'indirizzo della nostra chiave tricolore(489A7C). Mettiamonici un bel breakpoint memory, on write e facciamo partire Leonardo con F9.

Dovremmo vedere questo:

Usciamo dal ciclo cliccando sul RETN e premiamo f4 e poi f8. Dovremo vedere questo:

Osservate bene dove siamo atterrati: questo è il cuore della battaglia, l'occhio del ciclone. Ho colorato le Call con il colore delle frecce.

Analizziamo un po' di codice:

E830AA0000    CALL Leonardo.0040DA84 ; Call che serivirà per generare il nostro codice utente
59            POP ECX
68859D4800    PUSH Leonardo.00489D85 ; // Indirizzo dove sarà scritto il nostro codice utente
8D95E4FDFFFF  LEA EDX,DWORD PTR SS:[EBP-21C] ;
52            PUSH EDX ;
E81AA70000    CALL Leonardo.0040D780 ; Call che genera il nostro codice utente
83C408        ADD ESP,8
8945AC        MOV DWORD PTR SS:[EBP-54],EAX // .\indirect\tabels.lot
68859C4800    PUSH Leonardo.00489C85 ; Il seriale da noi inserito
FF75AC        PUSH DWORD PTR SS:[EBP-54] ; // .\indirect\tabels.lot
E8B7A50000    CALL Leonardo.0040D630 ; Call che genera la chiave di decrypting

Per non rendere molto complesso, e di lunghezza biblica questo tutorial, commenterò sono le funzioni necessarie alla realizzazione del keygen. Le call CALL Leonardo.0040DA84 e CALL Leonardo.0040D780 saranno sostituite da una semplice editbox dove noi andremo a inserire il codice utente che leggeremo dalla form di Leonardo, quella di registrazione insomma. In Pratica il Codice Utente lo lasceremo calcolare a leonardo, il mio è abc7c(Vedi immagine inizio tutorial).

Ora non ci resta che analizzare la Call CALL Leonardo.0040D630; questa call creerà la nostra chiave tricolore. Voglio ricordarvi che la chiave per cui l'algoritmo genera i valori giusti di decrypting è 00,07,04, 02,03,05, 00,03,06. Verde per 91, bianca per 2C e rossa per 49

Ecco la famigerata Call:

55              PUSH EBP
8BEC            MOV EBP,ESP
81C4 78F7FFFF   ADD ESP,-888
33C0            XOR EAX,EAX
8945 F8         MOV DWORD PTR SS:[EBP-8],EAX
33D2            XOR EDX,EDX
8955 FC         MOV DWORD PTR SS:[EBP-4],EDX
8B4D F8        /MOV ECX,DWORD PTR SS:[EBP-8] // Counter ECX = 0
C6840D F0FBFFF>|MOV BYTE PTR SS:[EBP+ECX-410],30 // 30 sta per 0 ASCII
8B4D FC        |MOV ECX,DWORD PTR SS:[EBP-4] // ECX = 0
B8 01000000    |MOV EAX,1 ; 1 in eax
D3E0           |SHL EAX,CL ; sposta a sinistra eax,cl eax=1 cl=0
8B55 08        |MOV EDX,DWORD PTR SS:[EBP+8] // Codice Utente (abc7c) in EDX
23C2           |AND EAX,EDX ; EAX = 0 + EDX = abc7c
74 0B          |JE SHORT Leonardo.0040D66A
8B45 F8        |MOV EAX,DWORD PTR SS:[EBP-8] EAX =0;
C68405 F0FBFFF>|MOV BYTE PTR SS:[EBP+EAX-410],31 // 31 sta per 1 ASCII
FF45 F8        |INC DWORD PTR SS:[EBP-8] // incrementa di 1
8B55 F8        |MOV EDX,DWORD PTR SS:[EBP-8] EDX = 1;
81FA E8030000  |CMP EDX,3E8 Confronta EDX con 3E8
7C 07          |JL SHORT Leonardo.0040D67F se edx è più piccolo salta (EDX = 1)
C745 F8 E70300>|MOV DWORD PTR SS:[EBP-8],3E7 sposta 3E7 (sta chiudento la serie)
FF45 FC        |INC DWORD PTR SS:[EBP-4] incrementa indice ciclo
8B4D FC        |MOV ECX,DWORD PTR SS:[EBP-4] index in ECX
83F9 20        |CMP ECX,20 controlla se ha ciclato 20 volte
7C B9          \JL SHORT Leonardo.0040D643 ripeti il ciclo finchè ECX = 20
////////////////////////////// FINE PRIMO CICLO IMPORTANTE /////////////////////////////////////
8B45 F8         MOV EAX,DWORD PTR SS:[EBP-8]
C68405 F0FBFFF  MOV BYTE PTR SS:[EBP+EAX-410],0
33D2            XOR EDX,EDX
8955 E0         MOV DWORD PTR SS:[EBP-20],EDX
33C9            XOR ECX,ECX
894D FC         MOV DWORD PTR SS:[EBP-4],ECX
/////////////////////////// INIZIO SECONDO CICLO IMPORTANTE ////////////////////////////////////
33C0          /XOR EAX,EAX
8945 EC       |MOV DWORD PTR SS:[EBP-14],EAX
8B55 0C       |/MOV EDX,DWORD PTR SS:[EBP+C] ; Seriale IN EDX (11223344)
8B4D E0       ||MOV ECX,DWORD PTR SS:[EBP-20] ; counter
8A040A        ||MOV AL,BYTE PTR DS:[EDX+ECX] ; primo numero seriale in AL
04 D0         ||ADD AL,0D0 ; aggiunge ad al 0D0
8845 DB       ||MOV BYTE PTR SS:[EBP-25],AL ; copia il al qui
0FBE55 DB     ||MOVSX EDX,BYTE PTR SS:[EBP-25] ; EDX = AL
8D0C52        ||LEA ECX,DWORD PTR DS:[EDX+EDX*2] ; (EDX + (EDX * 2))
884D DB       ||MOV BYTE PTR SS:[EBP-25],CL ; copia cl (1 byte) qui
33C0          ||XOR EAX,EAX ; EAX = 0
8985 98F7FFFF ||MOV DWORD PTR SS:[EBP-868],EAX
33D2          ||XOR EDX,EDX
8995 9CF7FFFF ||MOV DWORD PTR SS:[EBP-864],EDX
33C9          ||XOR ECX,ECX
898D A0F7FFFF ||MOV DWORD PTR SS:[EBP-860],ECX
0FBE45 DB     ||MOVSX EAX,BYTE PTR SS:[EBP-25]
0FBE9405 F0FBF||MOVSX EDX,BYTE PTR SS:[EBP+EAX-410]
83FA 31       ||CMP EDX,31
75 0A         ||JNZ SHORT Leonardo.0040D6EF
C785 98F7FFFF ||MOV DWORD PTR SS:[EBP-868],1
0FBE4D DB     ||MOVSX ECX,BYTE PTR SS:[EBP-25]
0FBE840D F1FBF||MOVSX EAX,BYTE PTR SS:[EBP+ECX-40F]
83F8 31       ||CMP EAX,31
75 0A         ||JNZ SHORT Leonardo.0040D70A
C785 9CF7FFFF ||MOV DWORD PTR SS:[EBP-864],1
0FBE55 DB     ||MOVSX EDX,BYTE PTR SS:[EBP-25]
0FBE8C15 F2FBF||MOVSX ECX,BYTE PTR SS:[EBP+EDX-40E]
83F9 31       ||CMP ECX,31
75 0A         ||JNZ SHORT Leonardo.0040D725
C785 A0F7FFFF ||MOV DWORD PTR SS:[EBP-860],1
8B85 9CF7FFFF ||MOV EAX,DWORD PTR SS:[EBP-864]
03C0          ||ADD EAX,EAX
8B95 98F7FFFF ||MOV EDX,DWORD PTR SS:[EBP-868]
03C2          ||ADD EAX,EDX
8B8D A0F7FFFF ||MOV ECX,DWORD PTR SS:[EBP-860]
C1E1 02       ||SHL ECX,2
03C1          ||ADD EAX,ECX
8945 DC       ||MOV DWORD PTR SS:[EBP-24],EAX
8A45 DC       ||MOV AL,BYTE PTR SS:[EBP-24]
8B55 FC       ||MOV EDX,DWORD PTR SS:[EBP-4]
8D1452        ||LEA EDX,DWORD PTR DS:[EDX+EDX*2]
8D8A 7C9A4800 ||LEA ECX,DWORD PTR DS:[EDX+489A7C]
8B55 EC       ||MOV EDX,DWORD PTR SS:[EBP-14]
880411        ||MOV BYTE PTR DS:[ECX+EDX],AL ; scrive la nostra chiave(1 byte a ciclo), segnateveli
FF45 E0       ||INC DWORD PTR SS:[EBP-20]
FF45 EC       ||INC DWORD PTR SS:[EBP-14]
8B45 EC       ||MOV EAX,DWORD PTR SS:[EBP-14]
83F8 03       ||CMP EAX,3
0F8C 3AFFFFFF |\JL Leonardo.0040D6A4
FF45 FC       |INC DWORD PTR SS:[EBP-4]
8B4D FC       |MOV ECX,DWORD PTR SS:[EBP-4]
83F9 03       |CMP ECX,3
0F8C 26FFFFFF \JL Leonardo.0040D69F
8BE5           MOV ESP,EBP
5D             POP EBP
C3             RETN

Vi fuma il cervello? Perchè non ho più commentato il secondo Ciclo? Perchè non ho capito un cavolo, oppure perchè ho gia scoperto chi è l'assassino? So chi è l'assassino naturalmente...

Il primo ciclo non fa altro che scrivere alla locazione di memoria EBP+EAX-410 (+1 ad ogni ciclo) una serie di 11111000111101010100000000000001 che saranno poi uzilizzati dal ciclo numero 2(Giallo). Qui io mi sono rotto e mi sono posizionato su MOV BYTE PTR DS:[ECX+EDX],AL e ho premuto F4 per ogni numero del seriale(11223344) e ho notato questo: prende il primo numero del seriale, lo elabora e mette il risultato in AL, che è il primo byte della chiave tricolore. Ecco i vari valori in AL ad ogni ciclo:

Seriale          = 11223344

Valori in AL = 77116633

La nostra chiave tricolore

00,07,04 02,03,05 00,03,06

la chiave generata con il seriale 11223344

07,07,01 01,06,06 03,03
  1, 1, 2 2, 3, 3  4, 4

Ora anche voi SAPETE chi è l'assassino... abbiamo reversato abbastanza, è ora di aprire il Cryptex. Ma come?

Ci manca un numero, quindi il seriale è di 9 lettere, ho notato però che con le lettere non genera valori validi, ma solo numeri pari a 0! Quindi il seriale è di soli numeri.

Cancelliamo il file tabelr.lot e reinseriamo il seriale così: 112233445

Ecco la chiave generata:

07,07,01 01,06,06 03,03,06

Qui mi sono fermato e ho ascoltato Welcome to Dying dei Blind Guardian, solo per riflettere un po'...

Il nostro Obiettivo è trovare quei numeri che elaborati dai 2 cicli diano la chiave tricolore... facciamo un tentativo per capire meglio l'enigma:

Chiave di decrypting

00,07,04 02,03,05 00,03,06

Valori ottenuti con il seriale 112233445

07,07,01 01,06,06 03,03,05
  1, 1, 2 2, 3, 3  4, 4, 5

 

Seguite i colori e lo spostamento delle cifre della chiave ottenuta dal seriale 112233445

00 07 04, 02 03 05, 00 03 06

Dannazione, ci mancano i numeri 00, 04, 02, e 06!

X, 1, X,  X, 4, 5 , X , 4 ,X

Quali saranno? Qui la soluzione è banalissima... cancelliamo nuovamente il file tabelr.lot e lanciamo ancora leonardo.exe, inseriamo al posto del seriale 112233445 il seriale 012345678 e segnamoci i valori in AL:

Valori ottenuti con il seriale 012345678

04 07 01, 06 03 05, 02 00 00

 

0, 1, 2,  3, 4, 5,  6, 7, 8

 

Chiave di decrypting

00 07 04, 02 03 05, 00 03 06

Seriale Valido per il decrypting con codice utente abc7c

7, 1, 0,  6, 4, 5,  7, 4, 3

E' incredibile... proprio quando stavo per scrivere: "E' ora di donne e champagne!", mi ha fatto uno squillo una ragazza che non sentivo da mesi... So che non ci crederete mai! Sono le 20 e 10 del 3 marzo 2005, sono in pigiama e vorrei giocare a Call of Duty, per quale stramaledetta ragione dovrei scrivere che mi ha chiamato LEI?

Se mi avete seguito fin qui siete sbroccati come la Regina di Cuori in Alice nel Paese delle Meraviglie! E una volta arrivati fin qui, perchè non dare un'occhiata a come assemblare un keygen... in assembly?

Aprite il masm e caricateci dentro il sorgente keygen.asm... io vi aspetto lì.

Grazie per aver scelto Leonardo ed "in bocca al lupo".
                                     Lo Staff di Leonardo

Un saluto a Valentino EUGENI e Mauro DONATI... siete stati originali!

DaGoN                                                                                                           

Note finali

Ringrazio mio padre, che all'età di 8 anni mi comprò il mio primo computer: un mitico Commodore 64! Ringrazio mia madre, che ascoltò il mio pianto e all'età di 16 anni mi comprò l'Amiga 500. Ringrazio entrambi, che all'età di 20 anni esaudirono il mio desiderio comprandomi un PC. Ringrazio me stesso, che all'età di 28 anni ascoltai i miei capricci e mi comprai un altro PC. Ringrazio Eleonora per aver letto la prima stesura del tutorial correggendo errori di ortografia e di punteggiatura. Ringrazio TUTTA la UIC e Quequero per avermi dato modo di arrivare un giorno a scrivere questo tutorial. Spero inoltre di non avervi annoiato. Alla Prossima,

DaGoN

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 che ogni sviluppatore ha dovuto portare avanti per fornire ai rispettivi consumatori i migliori prodotti possibili.

Reversiamo al solo scopo informativo e per migliorare la nostra conoscenza del linguaggio Assembly.