CrackMe #1 di Cruehead

Data

by "Gbyte"

 

03/07/2001

UIC's Home Page

Published by Quequero


It's better to burn out than to fade away

Beh, che dire se non: un'ottima lezione di xoring :)

It's better to burn out than to fade away

....

E-mail: s_[email protected]
Gbyte su IRC/#crack.it

....

Difficoltà

(x)Ok,adesso so cos'è il cracking ! ( )Intermedio 

( )Avanzato ( )Master

 

Questa volta proveremo a risolvere un bell'esercizio di Cruehead,lui stesso ci dice esclusivamente di trovare il seriale, senza alcuna modifica al crackme e noi faremo proprio così.


CrackMe #1 di Cruehead
No comment
Written by Gbyte
 

Introduzione

Eccomi al mio secondo tute,dopo quello su Winamp Skin Maker (spero l'abbiate gradito) mi ripropongo con una nuova sfida,ancora facile però! Proverò ad esplorare bit x bit questo CrackMe ... ehhh,non proprio bit x bit...li risolverò e cercherò di spiegarvi nel miglior modo possibile la generazione del seriale con qualche accenno allo xoring! Questa volta il culo non ci servirà per niente,è talmente semplice...

Tools usati

SoftIce 

URL o FTP del programma

Su questo sito, alla sezione CrackMe...è il n°1

Notizie sul programma

Questo non è un programma vero e proprio, ma un semplice CrackMe.Sapete cosa sono i CrackMe? No...CrackMe = Crackami... Sono dei programmini scritti da cracker come esercizio per gli altri.Di solito presentano solo un box per la registrazione, altre volte una schermata principale dalla quale si accede al box,altre volte non c'è per niente il box. Questo preso in esame fa parte del secondo gruppo. Non appena lo avviate vedete la schermata principale e in alto i menu File ed Help,proprio da Help si accede al box di registrazione per inserire i nostri dati.

Essay

 

Il primo CrackMe di Cruehead richiede un seriale generato a partire dal nick inserito.Quindi per brekare nel programma useremo le solite funzioni:prima proviamo GetWindowTextA,ma non funziona,allora con GetDlgItemTextA e...bingo,ecco che Sice appare.Premiamo F11 per uscire dalla funzione e diamo un'occhiata alle righe di codice che precedono la barra bianca del Sice:

 

:004012B5    PUSH    0B

:004012B7    PUSH    0040218E <- proprio qui viene salvato il nome che abbiamo inserito

:004012BC    PUSH    000003EB

:004012C1    CALL    DWORD PTR [EBP+10]

:004012C4    CALL    User32!GetDlgItemTextA <- ecco la funzione su cui abbiamo brekato

. . . . . . .

:004012D5    PUSH    0B

:004012D7    PUSH    0040417E <- qui invece viene salvato il seriale che abbiamo inserito

:004012DC    PUSH    000003E9

:004012E1    PUSH    DWORD PTR [EBP+08]

:004012E4    CALL    User32!GetDlgItemTextA <- di nuovo la stessa funzione di prima,spero almeno sappiate cosa fa...

 

Qui in pratica possiamo vedere dove vengono salvati i due dati inseriti:nome a 0040417E e seriale a 0040418E.Adesso però ci troviamo in una serie di chiamate quindi premiamo una prima volta F12 una seconda e poi di nuovo fino a quando non vedremo nella barra in basso a destro il nome del nostro programma. Ecco cosa abbiamo:

 

:00401223    CMP     EAX,00

:00401226    JZ      004011E6 <- hai inserito il nome?

:00401228    PUSH    0040218E <- vi ricordate cosa c'è qui?

:0040122D    CALL    0040137E <- generazione seriale 

:00401232    PUSH    EAX      <- EAX viene salvato perché servirà nella call dopo per effettuare altri calcoli

:00401233    PUSH    0040217E <- e qui che c'è?

:00401238    CALL    004013D8 <- acquisizione seriale inserito

:0040123D    ADD     ESP,04

:00401240    POP     EAX <- viene ristabilito il valore di EAX

:00401241    CMP     EAX,EBX  <- controllo dei due seriali (attenzione non sono confrontati direttamente)

:00401243    JZ      0040124C <- salta se uguali

:00401245    CALL    00401362  <- come dicono i cinesi ELLOLE!

:0040124A    JMP     004011E6

:0040124C    CALL    0040134D <- WELL DONE!

 

Beh,più evidente di così! Abbiamo uno dei controlli più semplici: nella prima chiamata viene acquisito il nome,ci vengono fatti sopra dei calcoli,il risultato viene poi crittato (xorato) e messo da parte (PUSH EAX) poi abbiamo una seconda chiamata,questa volta viene acquisito il nostro seriale e anche questo viene crittato e messo da parte in EBX;alla fine i due valori vengono confrontati e c'è il salto se sono uguali. Niente di più semplice! Ora noi potremmo forzare il JZ del controllo (quello dopo il CMP EAX, EBX) ma visto che dobbiamo trovare il seriale siamo costretti ad entrare nelle due call e vedere cosa succede. Bene,F8 ed entriamo.Questo è il codice:

 

:0040137E    MOV     ESI,DWORD PTR [ESP+04]

:00401382    PUSH    ESI

:00401383    MOV     AL,BYTE PTR [ESI]<- sposta un char del nome in AL

:00401385    TEST    AL,AL    

:00401387    JZ      0040139C <- queste due istruzioni controllano se i char del nome sono finiti

:00401389    CMP     AL,41 <- da qui...

:0040138B    JB      004013AC

:0040138D    CMP     AL,5A

:0040138F    JAE     00401394 <- a qui,controlla se il char è compreso tra A e Z cioè se è una lettera maiuscola

:00401391    INC     ESI <- esi+1

:00401392    JMP     00401383 <- c'è bisogno del commento anche qui?

:00401394    CALL    004013D2 

 

*** dentro la call a 00401394 ***

 

:004013D2    SUB     AL,20 <- trasforma i char minuscoli in maiuscoli (es:a=61h,61-20=41h,41h=A)

:004013D4    MOV     [ESI],AL <- sposta AL nel byte puntato da ESI 

:004013D6    RET

 

queste tre righe fanno in modo che alla fine in [EDI] ci sia il nome composto da sole lettere maiuscole (es:prima Gbyte, dopo GBYTE),quindi in questa prima parte non è stato ancora acquisito il nome.

 

*** exit ***

 

:00401399    INC     ESI <- ESI+1

:0040139A    JMP     00401383

:0040139C    POP     ESI <-ripristiana il valore di ESI che era stato salvato a 401382 per poter di nouvo acquisire i char del nome

:0040139D    CALL    004013C2

 

*** dentro la call 0040139D ***

      

:004013C2    XOR     EDI,EDI

:004013C4    XOR     EBX,EBX

:004013C6    MOV     BL,[ESI] <- un char in BL 

:004013C8    TEST    BL,BL <- è zero?

:004013CA    JZ      004013D1 <- se è 0 salta,se no continua

:004013CC    ADD     EDI,EBX <- in EDI vengono accumulati i valori hex dei char

:004013CE    INC     ESI <- passa al prossimo char di [ESI]

:004013CF    JMP     004013C6 <- ripete fino a quando i char non finiscono

:004013D1    RET

 

*** exit ***

 

:004013A2    XOR     EDI,00005678 <- xora EDI con 5678

:004013A8    MOV     EAX,EDI <- sposta EDI nel definitivo registro EAX

:004013AA    JMP     004013C1 <- salta al return ->

    ...

    ...

    ...

:004013C1    RET <- ritorna alla parte principale

 

Qui abbiamo visto come viene acquisito il nome char per char , i valori hex corrispondenti ai caratteri ASCII del nome vengono sommati e accumulati in EDI poi quest'ultimo viene xorato con un valore fisso e messo in EAX dove aspetterà di essere confrontato con l'altro valore, quello elaborato nella chiamata successiva. Annotiamoci i valori di EDI prima dello xor,5678 e il valore di EAX alla fine.

Passiamo ora  al codice della seconda chiamata:

 

:004013D8    XOR     EAX,EAX <-

:004013DA    XOR     EDI,EDI <- 

:004013DC    XOR     EBX,EBX <- i tre registri vengono azzerati  

:004013DE    MOV     ESI,DWORD PTR [ESP+04] <-sposta in ESI i byte 7E 21 40 00 (che sono puntati proprio da ESP+04,cioè a partire dal quarto byte dopo esp,con d esp avremmo : xx xx xx xx 7E 21 40 00) * vedi la nota a fine listato *

:004013E2    MOV     AL,0A <- sposta in AL AOh=10d   

:004013E4    MOV     BL,BYTE PTR [ESI] <- sposta in BL la prima cifra del seriale (ricordate che BL è = alla metà bassa di EBX mentre BH a quella alta)  

:004013E6    TEST    BL,BL <-  

:004013E8    JZ      004013F5 <- controlla che BL non sia zero  

:004013EA    SUB     BL,30 <- sottrae a BL 30 (questo serve perché il primo char del seriale viene acquisito sotto forma di carattere ASCII,proprio come per il nome,non come numero decimale,quindi con - 30h otteniamo la conversione in decimale.Teniamo conto di aver inserito nel box il numero 6: 

valore hex    dec    ascii

          36     54      6

facendo - 30h otteniamo

           6      6    *un simbolo simile alle picche delle carte 

                        da poker*

questo naturalmente si ripete per tutte le cifre del seriale.

 

:004013ED    IMUL    EDI,EAX <- moltiplica EDI x EAX (EDIx0A)  

:004013F0    ADD     EDI,EBX <- aggiunge ad EDI EBX 

:004013F2    INC     ESI <- ESI+1

:004013F3    JMP     0004013E2 <-ripete il ciclo fino a quando non terminano le cifre e il JZ di sopra salta questo salto(che bel gioco di parole eheheh...)  

:004013F5    XOR     EDI,00001234 <- xora EDI (il nostro seriale)per 1234

:004013FB    MOV     EBX,EDI <- sposta EDI in EBX  

:004013FD    RET    

 

Voi vi chiederete:"Ma come fa il programma ad avere in EDI alla fine della routine il seriale che abbiamo inserito?" Niente di più semplice! Non mi rimetto a spiegare cosa avviene con le singole cifre.Allora i comandi da tenere in considerazione sono MOV BL,BYTE PTR [ESI], IMUL EDI,EAX ed ADD EDI,EAX. In EAX abbiamo sempre il valore 0Ah (10d),in EBX le singole cifre del nostro seriale,che quindi cambiano ogni volta mentre EDI è il registro accumulatore. Per spiegarmi meglio faccio l'esempio del seriale 166 (in questo caso i calcoli li farò in decimali): l'1 viene acquisito,voi sapete già come (prima sotto forma di char ASCII e poi convertito in dec), poi abbiamo EDIxEAX cioè 0x10=0 a questo risultato viene aggiunto la cifra del seriale cioè 1. Per la seconda cifra abbiamo EBX=6,EDI=1 e EAX=10 quindi 1x10+6=16.Per la terza cifra è la stessa cosa EBX=6,EDI=16 ed EAX è sempre 10 ->16x10+6=166 ed ecco il nostro seriale!     

In questo modo se dopo l'acquisizione dell'ultima cifra e prima di oltrepassare l'indirizzo 004013F5 facciamo ? EDI possiamo vedere il seriale che abbiamo inserito sotto forma di valore hex,decimale ed ASCII (naturalmente lo riconosciamo vedendo il valore decimale).Adesso annotatevi il valore di EDI prima dello xor, il valore 1234 ed il valore finale che sta in EBX,ci serviranno dopo per calcolare il seriale corretto.

Ci terrei a chiarire una cosa riguardo ai puntatori * per un discorso più generale sui puntatori potete vedere gli altri tute che sono presenti in questa stessa sezione *.Abbiamo un bell'esempio all'indirizzo 004013DE (ricordate che BYTE PTR [...] corrisponde ad un singolo byte es: 06 h ,mentre DWORD PTR[...] corrisponde a quattro byte es: 06 07 FD 65).

In questo caso i 4 byte puntati da ESP+04 ,che possiamo vedere con il comando d ESP+04  e sono 7E 21 40 00 vengono spostati in un registro (ESI), quindi in ESI con il comando ? ESI apparirà il valore 0040217Eh (h sta per esadecimale).

Due comandi dopo ESI diventa un puntatore,quindi vedetelo con d ESI e fate caso sulla sinistra a che indirizzo si trova, 0040217E, ma va! La vedete la relazione? E' evidente! E pensare che a sta cosa ci ho fatto caso solo adesso!

L'ultimo sforzo dai! Riprendete tutti i valori che vi ho fatto annotare,prendete una calcolatrice esadecimale (quella che trovate con HexWorkshop va benissimo) che abbia anche la funzione xor e fate questo:

 

EAX xor 1234 = seriale esatto

 

Ora vi spiego: EAX e EBX devono essere uguali per registrare il programma, EAX = EDI1 xor 5678 mentre EBX = EDI2 xor 1234 (ATTENZIONE:i due EDI hanno valori diversi),quindi dobbiamo trovare il valore di EDI2 per cui EDI2 xor 1234 = EDI1 xor 5678 (cioè i EAX = EBX). Per avere EDI2 (seriale da inserire) dobbiamo fare: 

 

EDI2 = (EDI1 xor 5678) xor 1234  

 

ma dato che EDI1 xor 5678 = EAX sostituendo abbiamo EDI2 = EAX xor 1234 ed ecco il seriale esatto!

 

                                     by Gbyte

 

Note finali

Come avete visto in questo CrackMe è impossibile trovare il seriale esatto semplicemente controllando nei vari registri. I calcoli sono necessari quando nella protezione viene usata la tecnica dello Xoring, una delle più diffuse per la crittazione dei dati (per saperne di più vedete il tutorial di Quequero). Eh...cazzo...ho scritto un bel pò e poi...che casino ho fatto nella parte finale, spero sia stato chiaro! Beh...ringrazio Quequero nel caso dovesse riservare un pò di spazio sull'UIC Store per questo tute e poi ... basta! Potrei tornare sull'argomento dei CrackMe con la versione 2 di Cruehead nel caso nessuno ci abbia ancora scritto sopra un tute. Io già l'ho crackato e devo ammettere che è anche più semplice di questo! Ciao e a presto!

Disclaimer

Vorrei ricordare che il software va comprato e  non fregato, dovete registrare il vostro prodotto dopo il periodo di (s)valutazione. Non mi ritengo responsabile per eventuali danni causati al vostro computer determinati dall'uso di questo tutorial come arma impropria (se volete usarla come miccia per della dinamite sono caxxi vostri). Questo documento è stato scritto per invogliare i programmatori a non fare più programmi perché tanto noi glieli crackiamo e il consumatore a registrarsi legalmente , 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 (e le mille dosi di creatina che si è sparato) per fornire ai rispettivi consumatori i migliori prodotti possibili.

Noi reversiamo al solo scopo informativo e di miglioramento del linguaggio Assembly.