Zoom Icon

Corso UIC Newbies 01 Tactus

From UIC

Deskey 1.03.010 - Registrazione

Contents


Infos
Author: tactus
Email: tactus_2001@yahoo.com
Website:
Date: 24/01/2001 (dd/mm/yyyy)
Level: Working brain required
Language: Italian Image:Flag_Italian.gif
Comments: Grazie tactus per il tutorial, sono felice che come NewBies hai scelto di usare IDA (a proposito, la versione 3.8x full la trovate liberamente sul sito datarescue) sono contento anche dell'impegno che ci hai messo, vai avanti così



Introduzione

Sostanzialmente voglio affrontare diversi problemi presentati negli altri tutorial ma che non hanno avuto abbastanza spazio, vale per tutti l'intento di registrare effettivamente il programma (facendoglielo credere). In piu', per questo lavoro ho utilizzato IDA che un disassembler molto potente.

Tools usati


Tools


Link e Riferimenti

Questo è la soluzione del Corso UIC Newbies n°01 disponibile alla pagina Corso UIC Newbies 01


Essay

Innanzitutto lo strumento: IDA è un disassemblatore dalle grandi possibilita', io ho iniziato con W32Dasm ma da quando ho provato IDA me ne sono innamorato. Cerchero', durante il tutorial, di indicare pregi e difetti aiutando chi è ancora in dubbio a fare la scelta che più conviene. Dunque iniziamo proprio dal disassemblato. Indicate ad IDA quale exe volete aprire, date OK alle videate di conferma (chiedono una serie di opzioni decisamente complesse da spiegare qui) e parte la giostra.
Qui si vede subito la prima pecca: il processo è lentissimo: il lavoro su un EXE di 1 mega può occupare anche 15 minuti (naturalmente sul mio PII 350). Alla fine IDA ci posiziona all'inizio del programma.
Ora facciamo il punto: come tutti hanno detto, scattando la protezione entro un'ora, c'è puzza di SetTimer. Diamo Ctrl-PgUp per andare in cima al sorgente, Alt-T per avere la maschera di ricerca stringa e scriviamo "SetTimer" (ovviamente senza le virgolette :))) Giusto per vedere qualcosa, ecco cosa dovreste avere a video:

.text:00402FBF jnz short loc_0_40300A
.text:00402FC1 cmp dword_0_409010, 0
.text:00402FC8 jz short loc_0_402FE9
.text:00402FCA push 0 ; lpTimerFunc WM_TIMER all'applicazione
.text:00402FCC mov eax, dword_0_409028
.text:00402FD1 push 3E8h ; uElapse = 1 secondo
.text:00402FD6 push 2468h ; nIDEvent
.text:00402FDB push eax ; HWND
.text:00402FDC call ds:SetTimer
.text:00402FE2 xor eax, eax
.text:00402FE4 jmp loc_0_4039E3

Ecco che possiamo vedere qualche opzione di IDA: essendo su una riga, dando ":" possiamo inserire un commento sulla stessa proprio come se fossimo in assembler. Se il commento è di più righe, IDA abbassa il sorgente in modo che il commento rimanga sempre riferito alla stessa riga (e' molto più facile vederlo che non spiegarlo).
I commenti sono ovviamente miei e sono presi dal manuale Win32 (il formato hlp si trova ovunque).
Alla 420FDC c'è la vera e propria chiamata a SetTimer che accetta 4 parametri: l'identificatore della finestra che riceverà i messaggi (HWND), un identificativo del messaggio (nIDEvent), il tempo tra un messaggio e l'atro in millisecondi (uElapsed), la funzione da richiamare quando si attiva il timer (lpTimerFunc).
Nel nostro caso lo zero nel puntatore alla funzione significa che il messaggio WM_TIMER (che scatta ad ogni intervallo di tempo), finirà con tutti gli altri messaggi, all'interno dell'applicazione.
3E8h vale 1000 in decimale e quindi indica un secondo.
L'identificativo dell'evento è abbastanza interessante: supponiamo di avere diversi Timer, come faccio a sapere un WM_TIMER a quale orologio si riferisce? Proprio grazie all'identificatore; nel messaggio WM_TIMER è riportato proprio il codice.
Un'ultima cosa: notate l'ordine con cui i parametri sono inseriti (PUSH) nello stack; sono inseriti nell'ordine inverso a quello in cui li vuole la funzione. Questo è un dettaglio da tenere sempre a mente quando cerchiamo nei parametri delle funzioni.
Dopo tutta questa storia, si vede che il timer scatta ogni secondo e non può essere quello fatidico dei 60 minuti (questo ovviamente non lo possiamo sapere prima! Ho sperato che fosse così ed ho cercato altri SetTimer, sfortunatamente altre volte le cose non vanno in maniera tanto liscia).
Con un Ctrl-T cerchiamo l'occorrenza successiva e troviamo un altro Timer di un secondo con codice 1234h.
Ancora una volta Ctrl-T e troviamo questa roba:

.text:0040397F loc_0_40397F: ; CODE XREF: .text:00403755.j
.text:0040397F cmp Flag_1, 0
.text:00403986 jz short loc_0_403991
.text:00403988 cmp dword_0_40901C, 0
.text:0040398F jz short loc_0_4039B2
.text:00403991 loc_0_403991: ; CODE XREF: .text:00403986.j
.text:00403991 push 0
.text:00403993 mov eax, dword_0_409028
.text:00403998 push 3600000 ; = 3600 secondi = 1 ora
.text:0040399D push 1234h
.text:004039A2 push eax
.text:004039A3 call ds:SetTimer
.text:004039A9 mov edi, [esp+6ACh]
.text:004039B0 jmp short loc_0_4039C4 ; default

Un'altra caratteristica di IDA è che potete rinominare praticamente ogni identificatore: la linea 40397F probabilmente vi appare come:

.text:0040397F cmp dword_0_409018, 0

Ora posizionatevi sul simbolo "dword_0_409018" e date Enter. Verrete proiettati nel segmento dati proprio alla locazione 409018 dove è stata creata una doubleword (guarda caso!). Sempre posizionandosi sul simbolo "dword_0_409018" e dando "N", IDA ci invita a cambiare il nome del simbolo stesso. Ovviamente IDA lo cambiera', per noi, in tutto il sorgente.
Rinominato il campo torniamo dove eravamo con "ESC".
Torniamo a noi: il tempo per questo timer è 36EE80h (ma andandoci sopra e premendo "H", IDA ce lo mette in decimale) cioe' 3600000 che è proprio un'ora. Giusto per provare ho cambiato il valore a 3A98h (=15000 = 15 secondi) ed effettivamente la protezione scatta dopo pochissimo.
Quindi questo è il punto da saltare, ma cerchiamo di capire meglio: se Flag_1 vale 0 scatta la protezione, quindi deve valere 1. L'altra locazione non ci interessa (anche questo ovviamente ORA non lo sappiamo! Per il nostro obiettivo vedremo che l'impostazione del secondo valore è ininfluente ma in realtà solo seguendo tutte le strade aperte possiamo scoprire che non servono!!!).
Ora mettiamoci sul simbolo Flag_1 e diamo "X". Otterremo una finestra che ci mostra tutte le istruzioni che utilizzano Flag_1. Potremmo andare a vederle tutte ma la prima è proprio quella che ci interessa di piu': date ENTER e si giunge qui:

.text:00402786 cmp Flag_1, 0
.text:0040278D jz ThankForEval
.text:00402793 push offset Name_3
.text:00402798 push offset Name_2
.text:0040279D call ds:lstrlenA
.text:004027A3 mov ecx, ds:wsprintfA
.text:004027A9 test eax, eax
.text:004027AB mov eax, offset Name_2
.text:004027B0 jnz short loc_0_4027B7
.text:004027B2 mov eax, offset aNoRegisteredOrganization
.text:004027B7
.text:004027B7 loc_0_4027B7: ; CODE XREF: .text:004027B0.j
.text:004027B7 push eax
.text:004027B8 push offset Name_1
.text:004027BD lea eax, [esp+328h]
.text:004027C4 push offset aRegisteredToSSS
.text:004027C9 push eax
.text:004027CA call ecx
.text:004027CC add esp, 14h
.text:004027CF cmp word_0_409578, 0
.text:004027D7 jnz short TempRegistration
.text:004027D9 cmp word_0_40957A, 0
.text:004027E1 jnz short TempRegistration
.text:004027E3 cmp word_0_40957E, 0
.text:004027EB jnz short TempRegistration
.text:004027ED lea eax, [esp+31Ch]
.text:004027F4 push offset aThankYouForRegistering
.text:004027F9 push eax
.text:004027FA call edi
.text:004027FC jmp short loc_0_402876

Il pezzo è piuttosto lungo ma vale la pena.
Proprio all'inizio c'è la cmp su Flag_1 (ricordiamoci che per 0 viene attivata la protezione, quindi se il programma fosse registrato NON dovrebbe essere 0!).
Subito sotto, alla 40278D, c'è un jz ad una label che ho rinominato ThankForEval infatti ecco la piccola parte relativa a quella label:

.text:00402863 ThankForEval: ; CODE XREF: .text:0040278D.j
.text:00402863 lea eax, [esp+31Ch]
.text:0040286A push offset aThankYouForChoosingToEvaluate
.text:0040286F push eax
.text:00402870 call ds:lstrcpyA

Il riferimento che viene inserito nello stack poco prima della lstrcpy è il testo che compare nel dialogo di About. Ovviamente questo testo non dovrebbe comparire per una edizione acquistata, infatti se il Flag_1 non vale zero, la jz non salta.
I simboli Name_3, Name_2 e Name_1 che ho dato, rappresentano soltanto dei buffer di stringhe e, per ora, non ci interessano. Piuttosto vediamo ancora più sotto cosa succede. A nessuno sarà sfuggito il simbolo aThankYouForRegistering che compare in fondo: quello è il riferimento che cercavamo! Ma notiamo anche il simbolo aRegisteredToSSS che corrisponde ad una stringa di formato per wsprintf che indica i nomi dei registrati.

Tiriamo le somme: Flag_1 deve valere NON zero (poniamo 1), in tal modo la protezione non si attiva e ci mettiamo nella strada giusta per essere registrati.
Ora è il momento di eseguire la modifica: questo è quello che ho modificato:

.0040397F: C7051890400001000000 mov d,[000409018],000000001 ;"
.00403989: EB27 jmps .0004039B2 -------- (1)

Siamo alla fine: lanciate il programma, cliccate sulla piccola icona e scegliete "About Deskey". I dati che compaiono sono stati impostati all'installazione di Windows, ma ciò che più conta è che siamo stati a tutti gli effetti registrati.

Non ho volutamente nominato la variabili Name_1 ecc. perché sono semplici buffer che contengono i dati da presentare nel dialogo ma si può giocare anche con questi!
Notate che alla 4027A3 l'offset della wsprintf viene caricato in ecx, il suo richiamo avverrà alla 4027CA. La stringa di formato è inserita alla 4027C4 e quindi Name_1, Name_2 e Name_3 compariranno in questo ordine (infatti sono "pushate" nell'ordine inverso).
Consideriamo Name_1: posizionandoci sopra e dando Ctrl-N ci si apre una maschera che dà alcune informazioni fra cui l'indirizzo effettivo: 409260.
Scorrendo il sorgente, poco sotto, troviamo il riferimento a duie stringhe ora inutili:

.text:00402814 mov eax, offset aExpired
.text:00402819 jnz short loc_0_402820
.text:0040281B mov eax, offset aWillExpire

Due generiche stringhe che dicono che il software ha terminato il periodo di prova. Ovviamente queste non servono più (!) e le possiamo riutilizzare. Andando sui due simboli e dando Ctrl-N troviamo i seguenti indirizzi:

aExpired 4098FC
aWillExpire 4098F0

Se andiamo a vedere nel file le cose si presentano cosi':

.004098F0: 77 69 6C 6C-20 65 78 70-69 72 65 00-65 78 70 69 will expire expi
.00409900: 72 65 64 00-54 65 6D 70-6F 72 61 72-79 20 72 65 red Temporary re

Ora possiamo modificarlo cosi':

.004098F0: 43 72 61 63-6B 65 72 00-69 72 65 00-54 61 63 74 Cracker ire Tact
.00409900: 75 73 00 00-54 65 6D 70-6F 72 61 72-79 20 72 65 us Temporary re

Mettete i nomi che volete ma ovviamente le stringhe non possono essere più lunghe delle vecchie (non è strettamente detto ma è meglio cosi', piuttosto scegliete stringhe inutili più lunghe) e ricordate di terminarle sempre con 0 (valore, non carattere!). Ritorniamo alla 4027B8 dove si referenzia Name_1; cambiamo la

.004027B8: 6860924000 push 000409260 ;" @Æ`"
nella
.004027B8: 68FC984000 push 0004098FC ;" @ÿ³"

In questo modo abbiamo cambiato il riferimento per le stringhe della wsprintf. Fate una cosa simile alle 2 (attenzione a farle tutte e due!) occorrenze di Name_2 usando l'indirizzo 4098F0. Alla fine il programma è completamente personalizzato.


Note Finali

Voglio ringraziare chi ha messo tanti tutorial a disposizione di tutti ed in particolare a +Sandman che è stato il primo sito che ho trovato sul R.E.


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.