Imagine
Qualcosa di diverso dal solito

Data

by CyberPK

 

20/02/2002

UIC's Home Page

Published by Quequero


Se vuoi una cosa fatta bene falla da te :P

Giuro che se mi rimandi questo tute ancora una volta...Ti termino :P (voi non lo sapete ma me l'ha fatto ripubblicare quasi sei volte :)

"Il mio potere va oltre la morte" Forse :P

....

Home page: http://CyberPK.f2g.net/ (Prossimamente)
irc.azzurranet.org, #Crack-it , #Asm

....

Difficoltà

(x)NewBies ( )Intermedio ( )Avanzato ( )Master

 

Questo crack-me di Spider è davvero grazioso. Non utilizza una delle solite routine del controllo del serial. Come dice il nome (Imagine) il check del serial è legato ai pixel :Þ. Provare x credere.


Imagine
Qualcosa di diverso dal solito
Written by CyberPK

Introduzione

Ni sto tut io cercherò di essere il + preciso possibile visto che è rivolto ad un pubblico di newbies come me che magari cerca di capirne un po di +. Visto che anchio ho avuto le tue stesse difficoltà cercherò di fare chiarezza su ogni punto ( se nn prende troppo spazio e nn vada fuori dal nostro interesse)

Tools usati

-Un cervello
-Un'api refence
-Un Hexeditor
-Un Disassemblatore
-Un Debugger

URL o FTP del programma

www.quequero.cjb.net

Notizie sul programma

Spider ci dice che "L'obiettivo del crackme è quello di trovare il seriale. Potete usare tutti i tools che volete. Il patching non è permesso." Bhè + chiaro di così!!

Essay

Ciao bimbi :P. Questo è il mio 1° tut per la UIC. Speriamo bene :Þ!!!
Questo nn è uno dei soliti crackme. Infatti nn confronta il seriale inserito con nessuna stringa. Controlla infatti che il colore dei pixel del seriale che abbiamo inserito siano uguali a quelli del vero e unico serial.
Vediamo ora come ci dobbiamo comportare... Avviamo il crack-me.Uhm... Help -->Register
Ecco la nostra finestrella. Inseriamo il solito serial ad cazzum...
 
"Il serial inserito nn è esatto. Controllare che sia stato inserito correttamente"...
 
Bene bene. Riproviamo ma con ora un bel bpx su Getdlgitemtexta e ....Cazzo! non prende. Proviamo qualche altra api... Uhm nn prende niente. Cosa facciamo allora? Risaliamo al codice di controllo dalla messageboxa. Uhm vediamo subito che il controllo avviene tramite l'api GetPixel. Uhm... e chi l'ha mai sentita! Vabbè prendiamo la nostra api reference...
 
La funzione GetPixel recupera il valore dei colori rosso, verde e blu (RGB) del pixel alla coordinata specificata.
 
COLORREF GetPixel(

HDC hdc, // handle of device context 
int XPos, // x-coordinate of pixel 
int nYPos // y-coordinate of pixel 
);
 
Come sai (e se nn lo sai lo imparerai) lo stack è LIFO (Last In First Out [Ultimo Dentro Primo Fuori]) il che vuol dire che quando pushi i valori, l'api li riceve (tramite un pop [per chiarimenti sul comando leggiti il manuale intel n°2 dove ci sono tutti i comandi]) in ordine opposto rispetto ai push(Es. io pusho 5 e 6 ad un'api quella col comando pop li prende dallo stack e li riceve il ordine opposto riceve prima il 6 e poi il 5)
Perciò quando pushi è come se fosse:
 
COLORREF GetPixel(

int nYPos // y-coordinate of pixel 
int XPos, // x-coordinate of pixel 
HDC hdc, // handle of device context
);
 
Bene piccolo chiarimento. Ora andiamo avanti...
Cazzo! Hai già chiuso l'api reference!! Aspetta, aspetta :P
Allora vediamo cosa fa...
 
.text:004011B0           cmp ax, 69h      ; Compare Two Operands
.text:004011B4           jnz 00401E6F     ; Jump if Not Zero (ZF=0)
.text:004011BA           pusha            ; Push all General Registers
.text:004011BB           push 68h         ; nIDDlgItem
.text:004011BD           push [ebp+hWnd]  ; hDlg
.text:004011C0           call GetDlgItem  ; Call Procedure
.text:004011C5           push eax         ; hWnd
.text:004011C6           call GetWindowDC ; Call Procedure

.text:004011CB           xor esi, esi     ; Logical Exclusive OR
.text:004011CD           xor edi, edi     ; Logical Exclusive OR
.text:004011CF           mov ebx, eax                             _
.text:004011D1           push 4           ; int                <-|
.text:004011D3           push 4           ; int                <-| Che vi dicevo per i push ?? :P
.text:004011D5           push ebx         ; HDC                <-|_
.text:004011D6           call GetPixel    ; Call Procedure
.text:004011DB           mov esi, eax
In questa porzione di codice prima azzera tramite uno xor esi , stessa cosa per edi. poi muove quel che c'era in eax in ebx. E che c'è in eax?? L'handle!! Ma da dove lo prende??? Lo prende tramite ad una chiamate all'api Getdlgitem che sta poco sopra.
 
La funzione GetDlgItem cerca l'handle di un controllo nella dialog box specificata. 

HWND GetDlgItem(

HWND hDlg, // handle of dialog box
int nIDDlgItem // identifier of control
);
 
C'è ancora bisogno che ti dica che vanno in senso opposto ?? ;D. Il valore di ritorno è messo in eax. Successivamente viene richaimata l'api GetWindowDc...
 
GetWindowDC assigns default attributes to the window device context each time it retrieves the device context. Previous attributes are lost. 

HDC GetWindowDC(

HWND hWnd // handle of window 
);
 
Bè l'handle delle finestra era in eax e come valore di ritorno quest'api da il device context per la finestra specificata. Ecco spiegato il mistero. Andiamo avanti.
Ora pusha i valori che richiede l'api GetPixel e porta il risultato della chiamate a GetPixel (che è in eax) in esi. Ma che se ne fa???
 
.text:004011DD           push 5           ; int
.text:004011DF           push 6           ; int
.text:004011E1           push ebx         ; HDC
.text:004011E2           call GetPixel    ; Call Procedure
.text:004011E7           cmp eax, esi     ; Compare Two Operands
.text:004011E9           jz 00401E56      ; Salta alla messagebox di errore


Ahhhhhhhh!!!Quindi prima prende il colore di     un pixel in una posizione in cui è sempre bianco (o almeno lo è il + delle volte se nn lo avete modificato voi dalle impostazioni :P). Poi utilizza questo valore per controllare il pixel x,y e se è bianco salta all'errore.   
La parte di codice che è sopra si ripete in continuazione fino alla fine della routine.
Bhè quindi prende il colore del pixel alla cordinata x,y e controlla che nn sia bianco. Se lo è salta a alla messageboxa di errore. Perciò dovremo controllare uno per uno tutti i pixel.   
Ci si prospetta un luuuuuuuuungo lavoro coronato sopratutto di pazienza... Ma noi nn abbiamo pazienza... e sopratutto è inutile logorare ulteriormente il nostro cervellino :P.
Allora. Io ho pensato che se c'è un'api GetPixel che prende il colore di un pixel ce ne sarà un'altra che setta il colore di un pixel :P... Che vuol dire questo? Che utilizziamo le stesse coordinate che ci da il programma ma al contrario in modo da visualizzare i pixel anzichè prenderne il colore. Di solito nell'api reference c'è correlata qualche api che svolge qualche funzione complementare. Se avete già chiuso l'api reference riapritela... ecco... GetPixel... maccosa c'è laggiù in basso :P. SetPixel. Vediamo cosa vuole...
 
La funzione SetPixel setta col colore specificato il pixel alle coordinate specificate.

COLORREF SetPixel(

HDC hdc, // handle of device context 
int X, // x-coordinate of pixel 
int Y, // y-coordinate of pixel 
COLORREF crColor // pixel color 
);
 
Vista la solita storia dello stack i push vanno al contrario quindi è come se l'api reference ci dasse i valori in questo ordine.
 
COLORREF SetPixel(

COLORREF crColor // pixel color 
int Y, // y-coordinate of pixel 
int X, // x-coordinate of pixel 
HDC hdc, // handle of device context 
);
 
Ora ci troviamo ad un bivio... possiamo seguire un metodo moooooolto lungo(che sotto è descritto) oppure seguirne un'altro.

1° Metodo

Eccoci arrivati. questo metodo è un po lunghetto....vi avviso ma lo metto lo stesso visto che io come uno scemo nn avevo penato ad un'altra strada :P
Vedemus cosa dobbiamo fare. Bene bene... anzi male! vuole un push in +!!!. Uhm... e da dove prendo lo spazio per questo push??? 
 
.text:004011DD  6A05         push 5           ; int
.text:004011DF 
6A0 6         push 6           ; int
.text:004011E1  53           push ebx         ; HDC
.text:004011E2  E8C10C0000    call GetPixel    ; Call Procedure
.text:004011E7  3BC6         cmp eax, esi     ; Compare Two Operands
.text:004011E9  0F84670C0000  jz 00401E56      ; Salta alla messagebox di errore

.text:004011EF  6A0 6         push 6           ; int
.text:004011F1 
6A0 6         push 6           ; int
.text:004011F3  53           push ebx         ; HDC
.text:004011F4  E8AF0C0000    call GetPixel    ; Call Procedure
.text:004011F9  3BC6         cmp eax, esi     ; Compare Two Operands
.text:004011FB  0F84550C0000  jz 00401E56      ; Salta alla messagebox di errore
Bhè al posto del jz dopo ogni cmp possiamo inserire il push e qualtaltro ci serve :P. Il push sarà un semplice push 00 (nero)
quindi al posto di jz ci mettiamo il push... ma accipicchia rende solo 2 byte e ci sono altri 4 byte che andrebbero a sputtanare il codice. Bhè esiste l'istruzione nop! Usiamola!!! (Ricordo a quelli che nn ne sanno molto che l'istruzione nop (0x90) è un'istruzione che dice al programma di nn fare nulla). Così avremo 4 nop e un push :P
Ora un lavoro di grandissima pazienza. Prendiamo l'hexeditor  ci segnamo la prima parte dell'opcode e cerchiamo tutte le eventuali corrisponze. Al posto dell'opcode del jz metteremo 90 90 90 90 6A 00. Non lo avete fatto vero? Vi capisco :P. Avete tutta la mia solidarietà se invece ci avete provato :Þ
Bhè rimane solo da cambiare la call a GetPixel in SetPixel. Come facciamo??? Bhè la call porta a una zona che richiama poi il Firstthunk della iat che ci schiaffa nell'api GetPixel. Bene bene. Ma come facciamo allora? Semplice. Lanciamo il debugger settiamo un bpx a GetPixel e seguiamo la call... arriviamo ad una zona dove c'è
 
XXXX:00401EA8 FF2500204000 Jmp dword ptr [00402000]
 
Da qui basterà digitare in softice il comando "a" eppoi invio (Quel comando sta per "assembly" (penso :P).
Bhè vi apparirà l'indirizzo e voi dovrete digitare l'istruzione che volete mettere in quella locazione. Per i nostri scopi basterà digitare :
 
Jmp SetPixel
 
Uhm... Rimane un byte inutilizzato... vabbè mentre che ci siamo digitiamo anche nop :P
Ora segnamoci il nuovo opcode da inserire nel nostro file modificato.Quindi all'indirizzo 00401EA8 (offset 0x000012A8) al posto di FF2500204000 mettiamo XXXXXXXX90. Ho messo quelle X perchè cambiano da computer a computer :P.(La sai la storiella degli OriginalFirstThunk, dei Firstthunk & c. no? Bhè se no leggiti il tut di Andreageddon :Þ[http://andreageddon.8m.com/ sezione tutorial quello sul peditor])
Se sei stato bravo nn crasherà nulla ma ci appariranno i pixel belli belli che ci delineano il serial :P. 
Eheh il serial è AD3578FZZ7
Se qualcosa crasha niente paura segnatevi l'indirizzo del crash e steppatevi il codice fino al punto dell'errore e guardate cosa avete sbagliato e correggetelo.

2° Metodo
Bhe questo metodo è notevolmente + cortoe carino e sopratutto meno invasivo...Vi starete chiedendo cosa mi sono inventato???Bene ora ve lo spiego.Questa idea mi è venuta in sogno e mi ha illuminato. Se avete letto ciò che precede e sapete qualcosa su FirstThunk & Company sapete che quando nel debugger vediamo ad esempio "call Api" in realtà "call Api" ci manda in un luogo del programma che poi ci fa saltare al vero indirizzo dell'api.
Bene ora spero che le vostre rotelle comincino a girare...3...2...1...0....Avete capito con cosa voglio andare a parare???No? bhe velo spiego sono qui per questo.
Se vediamo un "call Api" che ci manda in un luogo del programma (ad api uguale si viene mandati in un luogo uguale) che contiene un
"Jmp dword ptr [Indirizzo]" mi viene un'idea. Ma se noi anzichè fargli fare questo jmp gli mettiamo un jmp verso una sezione del prog da noi sistemata ad hoc per modificare i push e passarli all'api SetPixel???? Eheheheh non male vero?? L'idea è fattibile. Ma che istruzioni dovremmo mettere???Vediamole insieme.

pop       esi  <--Così mi salvo l'indirizzo di ritorno del ret
pop       ebx  <--Qui mi salvo l'handle. Nb. utilizzo ebx per trovarmelo disponibile anche dopo
pop       eax  <--Qui mi salvo la coordinata X del Pixel
pop       edx  <--Qui mi salvo la coordinata Y del Pixel
push      esi  <--Qui pusho l'indirizzo di ritorno della call
push      00   <--Qui mi pusho il colore del pixel da settare
push      edx  <--Qui mi pusho la coordinata Y del Pixel
push      eax  <--Qui mi pusho la coordinata X del Pixel
push      ebx  <--Qui mi pusho la l'handle
call      SetPixel
ret
Sono 16 byte. Ci basterà trovare una zona del crack-me che possa contenere queste istruzioni...prendiamo un hexeditor, un peditor. Nel peditor cerchiamo la fine delle sezioni e poi andiamo nell'hexeditor e vediamo se ci sono tanti piccoli 00 :P Ci sonoooo alla fine della sezione .text specificatamente all'offset 00001320h e sono abbastanza per contenere in nostro codice.Con un Flc ci calcoliamo il virtual addres che è 00401F20.Sapete cosa vi consiglio??? Da runtime col softice fate:

u 00401F20
a 00401F20
poi qui digitare tutte le istruzioni che abbiamo visto

successivamente

u 00401EA8
a 00401EA8
jmp 00401F20
nop
nop
nop
nop

C'è una sola pecca :PPP se guardate bene (se nn lo vedete chiamate un oculista)c'è un puntino in +a lato della "A" del codice. Ma... da dove viene???Bhè rileggete sopra dove avevamo analizzato il crack-me.Bhè ve lo dico lo stesso io :PPP. Vi ricordate che all'inizio prendeva il colore neutro che gli serviva per le comparazioni???? Bhè anche quello è diventato da GetPixel a SetPixel. Dumpatevi tutto anche col pedump (così nn dovrete andare a modificare a mano i byte :PPP) e vedrete che funzionerà a meraviglia :P e senza neanche molta fatica :PPP. Basta questo è il tute "Final" perchè nn ne posso + di sto Imagine così come del Tarantula :PP(Pubblicità occulta :PPP) Vi ho messo a disposizione 2 metodi molto graziosi anche se penso che del 1° se ne poteva anche tranquillamente fare a meno visto che il secondo è di gran lunga + di classe :PPP.Bye alla prossima
Good luck!
Bye

Note finali

Spero di essere stato chiaro in tutto quel che ho detto :P. Se nn lo sono stato dimmelo che magari cerco di migliorare qualcosa in favore della chiarezza :Þ
Comunque saluto tutti quelli che conosco inclusi tutti i frequentatori di #crack-it e #asm. Tra di questi in questo momenti ricordo Quequero (come dimenticarlo visto che l'indirizzo della uic ha il suo stesso nick :P) TheMR, Andreageddon, NikDH, SonGoten, Pbdz, lee, Dades (Si quel lamero :P[vabbè scherzo :D]), Albe, Spider (che mi sta facendo soffrire col tarantula), D31mos, Master^Shadow, True-love, Cieli, Case, x86 ecc. ecc.. ecc... Non me ne vogliate se nn vi ho nominato ma alcuni nomi si sono persi nella mia scatola cranica :P Comunque saluto tutti quelli da cui ho imparato qualcosa.

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.

Capitoooooooo????? Bhè credo di si ;))))