CrackMe #1 di Cruehead | ||
Data |
by "Gbyte" |
|
03/07/2001 |
Published by Quequero | |
|
Beh, che dire se non: un'ottima lezione di xoring :) |
It's
better to burn out than to fade away |
.... |
|
.... |
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ì.
Introduzione |
Tools usati |
URL o FTP del programma |
Notizie sul programma |
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]
: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.