Eurytus CrackMe Reversing and KeyMaker Coding

Data

by Misanthropic

 

17/11/2004

UIC's Home Page

Published by Quequero

Just lay down for me, naked for me to see...

Che pazienza che hai misa :) grazie del tute!

...It's just one kiss that's all I need. (A Kiss To Remember - My Dying Bride)

....

Home page: http://korn88.altervista.org/
E-mail: korn -at- mytux -dot- org
Misanthropic, #crack-it@AzzurraNET

....

Difficoltà

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

 

 

 

Introduzione

Benvenuti. In questo tutorial verrà analizzato il crackme Eurytus di Novice. Il crackme analizzato dal punto di vista informatico è molto semplice, infatti non vi è nessun trick anti debugger et similia... invece dal punto di vista matematico è un po' un casino, come vedremo, perché dovremmo svolgere qualche equazioncina (o quasi... ihihihih :)

Tools usati

IDA
Visual Studio 6

URL o FTP del programma

http://pmode.impazz.it/crackme/Eurytus.zip

Essay

Cominciamo col dire che a questo tutorial c'è un allegato che contiene il codice sorgente del keymaker.
Bene, apriamo il crackme, notiamo subito che appare una finestra con due pulsanti, info e check... bene bene... adesso apriamo il nostro fido IDA e cerchiamo la Window Procedure della finestra principale. Scrolliamo un po' fin quando non arriviamo alla procedura handler dei pulsanti, soffermiamoci in questo punto:

.text:00401174             loc_401174:                 ; CODE XREF: DialogFunc+168 j
.text:00401174             lea eax, [esp+64h+var_5C]   ; file name
.text:00401178             lea ecx, [esp+64h+var_58]   ; method
.text:0040117C             push eax                    ; pusha il nome (\Key)
.text:0040117D             push ecx                    ; e il metodo (rb)
.text:0040117E             call _fopen                 ; chiama _fopen per aprire il file
.text:00401183             mov esi, eax                ; mette l'handle in esi
.text:00401185             add esp, 8
.text:00401188             test esi, esi               ; controlla se è zero
.text:0040118A             mov [esp+64h+arg_4], esi    ; lo memorizza in una locazione
.text:0040118E             jnz short loc_4011B0        ; salta se non è zero
.text:00401190             push 10h                 ; uType
.text:00401192             lea edx, [esp+68h+Text]
.text:00401196             push offset aEurytus     ; lpCaption
.text:0040119B             push edx                 ; lpText
.text:0040119C             push eax                 ; hWnd
.text:0040119D             call ds:MessageBoxA
.text:004011A3             pop esi
.text:004011A4             mov eax, 1
.text:004011A9             pop ebx
.text:004011AA             add esp, 5Ch
.text:004011AD             retn
10h                    ; esci dalla procedura

Come possiamo notare, vengono pushati nello stack due parametri (nome file e modo di lettura si suppone..) e viene chiamata la funzione _fopen. se il return value è l'handle al file allora lo memorizza in [esp+64h+arg_4] e salta a loc_4011B0 (che ora analizzeremo) altrimenti se che c'è stato un errore in apertura... per esempio se il file non esiste :)  mostra una MessageBox dicendo che il crackme non è registrato. A questo punto, quali sono il nome del file e il metodo di lettura? Apriamo il tutto con un debugger e mettiamo un breakpoint su 00401174 a questo punto ci leggiamo il tutto con un bel data dump :P (d'ora in poi darò per scontato che userete il debugger per leggere le stringhe...). Ora tocca a:


.text:004011B0             loc_4011B0:         ; CODE XREF: DialogFunc+18E j
.text:004011B0             push 2              ; pusha 2
.text:004011B2             push 0              ; pusha 0
.text:004011B4             push esi            ; pusha l'handle al file
.text:004011B5             call _fseek         ; chiama fseek
.text:004011BA             push esi            ; pusha l'handle al file
.text:004011BB             call _ftell         ; chiama _ftell (ritorna in eax la lunghezza del file)
.text:004011C0             add esp, 10h
.text:004011C3             cmp al, 14h         ; controlla se la lunghezza è 20 (14 in esadecimale)
.text:004011C5             jz short loc_4011F1 ; se si salta a loc_4011F1
.text:004011C7             push 10h ; uType
.text:004011C9             lea eax, [esp+68h+Text]
.text:004011CD             push offset aEurytus ; lpCaption
.text:004011D2             push eax ; lpText
.text:004011D3             push 0 ; hWnd
.text:004011D5             call ds:MessageBoxA ; dii che il crackme non è registrato
.text:004011DB             push esi
.text:004011DC             call _fclose        ; chiudi il file
.text:004011E1             add esp, 4
.text:004011E4             mov eax, 1
.text:004011E9             pop esi
.text:004011EA             pop ebx
.text:004011EB             add esp, 5Ch
.text:004011EE             retn 10h            ; esci

Un semplice controllo della lunghezza...


.text:004011F1             loc_4011F1:         ; CODE XREF: DialogFunc+1C5 j
.text:004011F1             push 0              ; pusha 0
.text:004011F3             push 0              ; pusha 0
.text:004011F5             push esi            ; pusha l'handle al file
.text:004011F6             call _fseek         ; chiama _fseek
.text:004011FB             add esp, 0Ch
.text:004011FE             mov byte ptr [esp+64h+hDlg], 0
.text:00401203             mov ebx, 1
.text:00401208
.text:00401208             loc_401208:         ; CODE XREF: DialogFunc+236 j
.text:00401208                                 ; DialogFunc+254 j ...
.text:00401208             push esi            ; pusha l'handle al file
.text:00401209             call _getc          ; chiama _getc

Fin qui non fa altro che mettere il file pointer a 0 e chiamare _getc per leggere un solo carattere dal file.

 
.text:0040120E             add esp, 4
.text:00401211             cmp al, 0FFh
.text:00401213             jz loc_401387
.text:00401219             cmp al, 30h
.text:0040121B             jnz short loc_401238
.text:0040121D             mov ecx, [esp+64h+hDlg]
.text:00401221             mov al, byte ptr [esp+64h+hDlg]
.text:00401225             and ecx, 0FFh
.text:0040122B             inc al
.text:0040122D             mov byte ptr [esp+64h+hDlg], al
.text:00401231             mov byte ptr [esp+ecx+64h+var_50], 0
.text:00401236             jmp short loc_401208
.text:00401238             ; ---------------------------------------------------------------------------
.text:00401238            
.text:00401238             loc_401238: ; CODE XREF: DialogFunc+21B j
.text:00401238             cmp al, 31h
.text:0040123A             jnz short loc_401256
.text:0040123C             mov edx, [esp+64h+hDlg]
.text:00401240             mov al, byte ptr [esp+64h+hDlg]
.text:00401244             and edx, 0FFh
.text:0040124A             inc al
.text:0040124C             mov byte ptr [esp+64h+hDlg], al
.text:00401250             mov byte ptr [esp+edx+64h+var_50], bl
.text:00401254             jmp short loc_401208
.text:00401256             ; ---------------------------------------------------------------------------
.text:00401256
.text:00401256             loc_401256: ; CODE XREF: DialogFunc+23A j
.text:00401256             cmp al, 32h
.text:00401258             jnz short loc_401274
.text:0040125A             mov eax, [esp+64h+hDlg]
.text:0040125E             and eax, 0FFh
.text:00401263             mov byte ptr [esp+eax+64h+var_50], 2
.text:00401268             mov al, byte ptr [esp+64h+hDlg]
.text:0040126C             inc al
.text:0040126E             mov byte ptr [esp+64h+hDlg], al
.text:00401272             jmp short loc_401208
.text:00401274             ; ---------------------------------------------------------------------------
.text:00401274
.text:00401274             loc_401274: ; CODE XREF: DialogFunc+258 j
.text:00401274             cmp al, 33h
.text:00401276             jnz short loc_401296
.text:00401278             mov ecx, [esp+64h+hDlg]
.text:0040127C             mov al, byte ptr [esp+64h+hDlg]
.text:00401280             and ecx, 0FFh
.text:00401286             inc al
.text:00401288             mov byte ptr [esp+64h+hDlg], al
.text:0040128C             mov byte ptr [esp+ecx+64h+var_50], 3
.text:00401291             jmp loc_401208
.text:00401296             ; ---------------------------------------------------------------------------
.text:00401296
.text:00401296             loc_401296: ; CODE XREF: DialogFunc+276 j
.text:00401296             cmp al, 34h
.text:00401298             jnz short loc_4012B8
.text:0040129A             mov edx, [esp+64h+hDlg]
.text:0040129E             mov al, byte ptr [esp+64h+hDlg]
.text:004012A2             and edx, 0FFh
.text:004012A8             inc al
.text:004012AA             mov byte ptr [esp+64h+hDlg], al
.text:004012AE             mov byte ptr [esp+edx+64h+var_50], 4
.text:004012B3             jmp loc_401208
.text:004012B8             ; ---------------------------------------------------------------------------
.text:004012B8
.text:004012B8             loc_4012B8: ; CODE XREF: DialogFunc+298 j
.text:004012B8             cmp al, 35h
.text:004012BA             jnz short loc_4012D9
.text:004012BC             mov eax, [esp+64h+hDlg]
.text:004012C0             and eax, 0FFh
.text:004012C5             mov byte ptr [esp+eax+64h+var_50], 5
.text:004012CA             mov al, byte ptr [esp+64h+hDlg]
.text:004012CE             inc al
.text:004012D0             mov byte ptr [esp+64h+hDlg], al
.text:004012D4             jmp loc_401208
.text:004012D9             ; ---------------------------------------------------------------------------
.text:004012D9
.text:004012D9             loc_4012D9: ; CODE XREF: DialogFunc+2BA j
.text:004012D9             cmp al, 36h
.text:004012DB             jnz short loc_4012FB
.text:004012DD             mov ecx, [esp+64h+hDlg]
.text:004012E1             mov al, byte ptr [esp+64h+hDlg]
.text:004012E5             and ecx, 0FFh
.text:004012EB             inc al
.text:004012ED             mov byte ptr [esp+64h+hDlg], al
.text:004012F1             mov byte ptr [esp+ecx+64h+var_50], 6
.text:004012F6             jmp loc_401208
.text:004012FB             ; ---------------------------------------------------------------------------
.text:004012FB
.text:004012FB             loc_4012FB: ; CODE XREF: DialogFunc+2DB j
.text:004012FB             cmp al, 37h
.text:004012FD             jnz short loc_40131D
.text:004012FF             mov edx, [esp+64h+hDlg]
.text:00401303             mov al, byte ptr [esp+64h+hDlg]
.text:00401307             and edx, 0FFh
.text:0040130D             inc al
.text:0040130F             mov byte ptr [esp+64h+hDlg], al
.text:00401313             mov byte ptr [esp+edx+64h+var_50], 7
.text:00401318             jmp loc_401208
.text:0040131D             ; ---------------------------------------------------------------------------
.text:0040131D
.text:0040131D             loc_40131D: ; CODE XREF: DialogFunc+2FD j
.text:0040131D             cmp al, 38h
.text:0040131F             jnz short loc_40133E
.text:00401321             mov eax, [esp+64h+hDlg]
.text:00401325             and eax, 0FFh
.text:0040132A             mov byte ptr [esp+eax+64h+var_50], 8
.text:0040132F             mov al, byte ptr [esp+64h+hDlg]
.text:00401333             inc al
.text:00401335             mov byte ptr [esp+64h+hDlg], al
.text:00401339             jmp loc_401208
.text:0040133E ; ---------------------------------------------------------------------------
.text:0040133E
.text:0040133E             loc_40133E: ; CODE XREF: DialogFunc+31F j
.text:0040133E             cmp al, 39h
.text:00401340             jnz short loc_401360
.text:00401342             mov ecx, [esp+64h+hDlg]
.text:00401346             mov al, byte ptr [esp+64h+hDlg]
.text:0040134A             and ecx, 0FFh
.text:00401350             inc al
.text:00401352             mov byte ptr [esp+64h+hDlg], al
.text:00401356             mov byte ptr [esp+ecx+64h+var_50], 9
.text:0040135B             jmp loc_401208
.text:00401360             ; ---------------------------------------------------------------------------
.text:00401360
.text:00401360             loc_401360: ; CODE XREF: DialogFunc+340 j
.text:00401360             push 10h ; uType
.text:00401362             lea edx, [esp+68h+Text]
.text:00401366             push offset aEurytus ; lpCaption
.text:0040136B             push edx ; lpText
.text:0040136C             push 0 ; hWnd
.text:0040136E             call ds:MessageBoxA
.text:00401374             push esi
.text:00401375             call _fclose
.text:0040137A             add esp, 4
.text:0040137D             mov eax, ebx
.text:0040137F             pop esi
.text:00401380             pop ebx
.text:00401381             add esp, 5Ch
.text:00401384             retn 10h

Tutto questo casino di codice è un loop che legge un carattere alla volta dal file, controlla se è da "0" a "9" (ma non bastava una sottrazione invece che un check del genere!?) e lo memorizza, altrimenti da una MessageBox, arrivato a 20 caratteri letti dal file salta a una locazione (loc_401387), il check vero e proprio.


.text:00401387             loc_401387: ; CODE XREF: DialogFunc+213 j Eccoci qua...
.text:00401387             push ebp                        ; preserva i registri
.text:00401388             push edi                        ; preserva i registri
.text:00401389             push esi                        ; pusha l'handle al file
.text:0040138A             call _fclose                    ; lo chiude
.text:0040138F             mov esi, [esp+70h+var_50]       ; mette in esi il primo numero letto dal file
.text:00401393             mov edi, [esp+70h+var_50+3]     ; in edi il quarto
.text:00401397             mov ebp, [esp+70h+var_50+2]     ; in ebp il terzo
.text:0040139B             mov edx, [esp+70h+var_50+1]     ; in edx il secondo
.text:0040139F             add esp, 4
.text:004013A2             xor eax, eax
.text:004013A4             and esi, 0FFh                   ; lascia in esi solo il primo byte
.text:004013AA             and edi, 0FFh                   ; uguale a prima però in edi
.text:004013B0             and ebp, 0FFh                   ; inutile continuare a scrivere
.text:004013B6             and edx, 0FFh                   ; ma io commento ugualmente
.text:004013BC             lea ecx, [esp+6Ch+var_50]       ; carica l'indirizzo dell'aray delle chiavi in ecx
.text:004013C0             mov [esp+6Ch+hDlg], 14h         ; memorizza 20 in una locazione di memoria
.text:004013C8
.text:004013C8             loc_4013C8: ; CODE XREF: DialogFunc+3E3 j Ecco il loop
.text:004013C8             xor ebx, ebx                    ; azzera ebx
.text:004013CA             mov bl, [ecx]                   ; muove l'elemento puntato da ecx in bl
.text:004013CC             add ebx, eax                    ; somma eax a ebx
.text:004013CE             imul ebx, esi                   ; moltiplica ebx per la prima chiave
.text:004013D1             add ebx, edx                    ; aggiunge la prima chiave
.text:004013D3             add ebx, ebp                    ; aggiunge la seconda
.text:004013D5             add ebx, edi                    ; e aggiunge la prima
.text:004013D7             inc ecx                         ; incrementa il puntatore al vettore di chiavi
.text:004013D8             mov eax, ebx                    ; mette ebx in eax
.text:004013DA             mov ebx, [esp+6Ch+hDlg]         ; mette in ebx il numero che avevamo memorizzato prima (è un contatore)
.text:004013DE             dec ebx                         ; lo decrementa
.text:004013DF             mov [esp+6Ch+hDlg], ebx         ; lo memorizza di nuovo
.text:004013E3             jnz short loc_4013C8            ; se l'ultima operazione non ha dato zero come risultato allora salta a short loc_4013C8
.text:004013E5             pop edi                         ; eccoci fuori, ristora edi
.text:004013E6             cmp eax, 40h                    ; controlla se il risultato del check precedente è 64d
.text:004013E9             pop ebp                         ; ristora ebp
.text:004013EA             jz short loc_40141A             ; se si salta congratulati
.text:004013EC             push 10h ; uType
.text:004013EE             lea eax, [esp+68h+Text]
.text:004013F2             push offset aEurytus ; lpCaption
.text:004013F7             push eax ; lpText
.text:004013F8             push 0 ; hWnd
.text:004013FA             call ds:MessageBoxA             ; altrimenti fanculo
.text:00401400             mov ecx, [esp+64h+arg_4]
.text:00401404             push ecx
.text:00401405             call _fclose                    ; chiudi il file
.text:0040140A             add esp, 4
.text:0040140D             mov eax, 1
.text:00401412             pop esi
.text:00401413             pop ebx
.text:00401414             add esp, 5Ch
.text:00401417             retn 10h                        ; esci

Benissimo... a quanto pare questa funzione prende le nostre 20 chiavi dal keyfile e fa alcune operazioni su di esse... se il risultato di queste operazioni è 64 (in decimale) allora le 20 chiavi sono esatte... trasformiamo la nostra funzione in una equazione:

(c1 + c2 + c3 + c0 ((c1 + c19 + c2 + c3 + c0 ((c1 + c18 + c2 + c3 + c0 ((c1 + c17 + c2 + c3 + c0 ((c1 + c16 + c2 + c3 + c0 ((c1 + c15 + c2 + c3 + c0 ((c1 + c14 + c2 + c3 + c0 ((c1 + c13 + c2 + c3 + c0 ((c1 + c12 + c2 + c3 + c0 ((c1 + c11 + c2 + c3 + c0 ((c1 + c10 + c2 + c3 + c0 ((c1 + c2 + c3 + c0 ((c1 + c2 + c3 + c0 ((c1 + c2 + c3 + c0 ((c1 + c2 + c3 + c0 ((c1 + c2 + c3 + c0 ((c1 + c2 + c3 + c0 ((c1 + c2 + 2 c3 + c0 ((c1 + 2 c2 + c3 + c0 ((c0^2 + 2 c1 + c2 + c3)))))) + c4)) + c5)) + c6)) + c7)) + c8)) + c9))))))))))))))))))))))) = 64

Dove c0, c1, c2...c17, c18, c19 stanno per le nostre venti chiavi. Non lasciamoci confondere dalla lunghezza della nostra equazione perché non ne vale la pena... :) prima di cominciare a risolverla... vorrei farvi notare una cosa... analizziamo la funzione per calcolare:

for (contatore = 0; contatore>20;contatore--)
    valore = (keys[contatore] + valore) * keys[0] + keys[1] + keys[2] + keys[3];

 
Notiamo subito che l'unica operazione di moltiplicazione che svolgiamo è quella con keys[0] ovvero la prima chiave... ma... wow! questo ci facilita un po' tutto!!! perché se noi come prima chiave mettiamo 1 la moltiplicazione avverrà sempre col numero uno! e poi se impostiamo le chiavi dalla seconda alla quarta a 0... riduciamo la nostra funzione a una funzione sommatoria, nella quale si sommano le chiavi :)))))) e grazie a questa debolezza di questa funzione riusciamo a non impazzire nel risolvere un'equazione a 20 parametri :)
Dunque per trovare una soluzione valida ci basta impostare la prima chiave a 1, la seconda, la terza e la quarta a 0 e le restanti le imposteremo in modo che la loro somma mi dia 63 (la prima chiave è a 1) :) (ricordiamoci che ogni chiave può essere da 0 a 9).
Molto bene, cominciamo col scrivere il keymaker!!!

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void seed();
int randomize(int);

void main() {
    int i, indice, ok=0;
    unsigned int keygen_keys[20] = {0};

    keygen_keys[0]=1;
    keygen_keys[1]=0;
    keygen_keys[2]=0;
    keygen_keys[3]=0;

    seed();

    for (i=0;i<63;i++) {
        while (!ok) {
            indice=randomize(16)+4;
            if (keygen_keys[indice]<9) {
            keygen_keys[indice]++;
            ok=1;
        } // end if
    } // end while
    ok=0;
    } // end for

    for (i=0;i<20;i++)
        printf("%i", keygen_keys[i]);

    return;

}

void seed() {
    srand(time(NULL));
}

int randomize(int bound) {
    return rand()%bound;
}

 

                                                                                                                 Misanthropic

Note finali e ringraziamenti

Come vedete il keymaker risulta facilissimo :)
Con questo è tutto vi ringrazio per aver letto tutto il tutorial ;p

In prima posizione ringrazio pirloz ché senza di lui non avrei potuto scrivere questo tutorial.... :) grazie tante! Poi ringrazio dionis` per avermi dato una mano sull'estetica del keymaker (intendo quello da scaricare, il link in alto) ringrazio il papero per l'hosting, inoltre saluto Ntoskrnl perché è un genio (spero si accontenti...ahahah). Ovviamente ringrazio Novice per questo crackme. Dulcis in fundo saluto Evilcry... buona fortuna evil :) azz... quasi quasi dimenticavo.. la gentaglia di #crack-it, #cryptorev e #pmode :)

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. 

Arrestatemi perché ho reversato un crackme :)