Zoom Icon

Imagine

From UIC

Imagine: Qualcosa di diverso dal solito

Contents


Infos
Author: CyberPK
Email: image:Cyb addr.JPG
Website:
Date: 20/02/2002 (dd/mm/yyyy)
Level: Working brain required
Language: Italian Image:Flag_Italian.gif
Comments: 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.
Que: 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 :)



Introduction

In '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

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


Link e Riferimenti

http://www.quequero.org
Crackme n°38 disponibile alla pagina Crackme 26 - 50


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<br />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 pixelanziché 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 6A06 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 6A06 push 6 //int
.text:004011F1 6A06 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 :Þ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 noianziché 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

I documenti qui pubblicati sono da considerarsi pubblici e liberamente distribuibili, a patto che se ne citi la fonte di provenienza. Tutti i documenti presenti su queste pagine sono stati scritti esclusivamente a scopo di ricerca, nessuna di queste analisi è stata fatta per fini commerciali, o dietro alcun tipo di compenso. I documenti pubblicati presentano delle analisi puramente teoriche della struttura di un programma, in nessun caso il software è stato realmente disassemblato o modificato; ogni corrispondenza presente tra i documenti pubblicati e le istruzioni del software oggetto dell'analisi, è da ritenersi puramente casuale. Tutti i documenti vengono inviati in forma anonima ed automaticamente pubblicati, i diritti di tali opere appartengono esclusivamente al firmatario del documento (se presente), in nessun caso il gestore di questo sito, o del server su cui risiede, può essere ritenuto responsabile dei contenuti qui presenti, oltretutto il gestore del sito non è in grado di risalire all'identità del mittente dei documenti. Tutti i documenti ed i file di questo sito non presentano alcun tipo di garanzia, pertanto ne è sconsigliata a tutti la lettura o l'esecuzione, lo staff non si assume alcuna responsabilità per quanto riguarda l'uso improprio di tali documenti e/o file, è doveroso aggiungere che ogni riferimento a fatti cose o persone è da considerarsi PURAMENTE casuale. Tutti coloro che potrebbero ritenersi moralmente offesi dai contenuti di queste pagine, sono tenuti ad uscire immediatamente da questo sito.

Vogliamo inoltre ricordare che il Reverse Engineering è uno strumento tecnologico di grande potenza ed importanza, senza di esso non sarebbe possibile creare antivirus, scoprire funzioni malevoli e non dichiarate all'interno di un programma di pubblico utilizzo. Non sarebbe possibile scoprire, in assenza di un sistema sicuro per il controllo dell'integrità, se il "tal" programma è realmente quello che l'utente ha scelto di installare ed eseguire, né sarebbe possibile continuare lo sviluppo di quei programmi (o l'utilizzo di quelle periferiche) ritenuti obsoleti e non più supportati dalle fonti ufficiali.