Zoom Icon

Lezione 8 File and Registry Keys

From UIC Archive

File and Registry Keys

Contents


Lezione 8 File and Registry Keys
Author: §-Death_Reaver-§
Email: [email protected]
Website:
Date: 02/11/2008 (dd/mm/yyyy)
Level: Luck and skills are required
Language: Italian Flag Italian.gif
Comments:



Introduzione

Benvenuti a tutti all'ottava lezione per newbie. In questa lezione tratteremo due tipi di protezione molto comuni: i key file (file chiave) e le registry key (chiavi di registro).

Prima di tutto spieghiamo cosa si intende:

I Key file non sono altro che file normali. La particolarità è che il programma che ne fa uso li legge traendone informazioni utili per la registrazione e cose del genere.

Le Reg Key invece sono le cosiddette "chiavi di registro". Per chi non avesse mai aperto il regedit (Start->Esegui e scrivete regedit) è il momento di farlo. Il registro di sistema è una specie di grande archivio sul quale sono memorizzate informazioni di ogni tipo, dalle impostazioni di windows a ...dati per la verifica della registrazione!.

La cavia che studieremo QUESTO piccolo crackme fatto all'occorrenza.


Tools

I programmi che andremo ad usare saranno i seguenti:

OllyDBG 1.10
Filemon 7
Regmon 7
Un qualsiasi Editor esadecimale (personalmente preferisco 010editor)
Guida API

Il primo, arrivati a questo punto dovreste conoscerlo molto bene.
Il secondo è una piccola utility in grado di monitorare l'apertura, la lettura e la scrittura di file da parte di uno o più processi.
Il terzo è uguale al secondo, solo che si occupa delle chiavi di registro.

Anche lo scopo esistenziale di un editor esadecimale dovrebbe esservi già chiaro: modificare, creare e distruggere :D

La Guida API è quasi scontato citarla...Almeno che non abbiate esperienza, dovreste sempre averla a portata di mano.


Link e Riferimenti

Questo è il Corso UIC Newbies n°7 disponibile alla pagina Corsi UIC Newbies


Essay

Cominciamo a dare un'occhiata in generale: Apriamo il programmino normalmente ed ecco cosa notiamo:

Il crackme presenta tre caselle di tipo Checkbox. Sono però disabilitate (infatti non possiamo crociarle come di solito) e in più presentano titoli sospetti: Requisito 1, Requisito 2 e Requisito 3. Infine c'è un pulsante "Check" che probabilmente farà partire i vari controlli.

Proviamo a premerlo, e ci accorgiamo che non succede nulla, se non che dopo qualche secondo si chiude tutto in automatico...

Requisito n° 1

Cominciamo quindi a utilizzare le nostre conoscenze: Apriamo Filemon e nella schermata che ci appare (filtri), mettiamo:

In "Include", il nome dei processi che vogliamo controllare, separati dal punto e virgola. Per questa lezione, scriviamo solamente "Lezione6.exe".

In "Exclude" invece, mettiamo un bell'asterisco. in questo modo, escludiamo tutti i processi (tranne quelli scritti in "Include")

In "Highlight" potete mettere quello che volete evidenziare: per comodità io di solito scrivo "NOT FOUND" in modo che evidenzi la riga solo quando un file non è trovato.

A questo punto, premete OK.

Vi si aprirà una schermata e, se avrete impostato bene i filtri, dovrebbe essere vuota. Se appaiono righe varie, fategli un click col tasto destro e scegliete "Exclude process".

Tenendo Filemon aperto, avviate Lezione6.exe e osservate: La schermata di Filemon si riempie di righe, ma non ci interessano tutte. Cominciamo col bloccare lo scroll (altrimenti si perde il segno) con CTRL+A. Analizzando le righe ci accorgiamo che fanno riferimento a file e librerie di windows (anche le righe evidenziate)..quindi niente di anomalo. Premiamo CTRL+X per fare pulizia e andiamo avanti.
Premiamo il pulsante Check e vediamo che succede: AH ecco qua! due belle righe rosse e come possiamo notare, fanno riferimento a due file: un certo "watsup.not" (nella stessa directory del crackme) e "office.cfg".

PS.
Non fatevi ingannare! Il file "office.cfg" non è un file di configurazione di Microsnorf Office! E' stato nominato così per farvi confondere!

Ora sappiamo che il crackme cerca due file. Che fare? Creiamoli!

Per prima cosa andiamo nella stessa directory del crackme e creiamo "watsup.not", poi, nella directory C:\Programmi\Microsoft Office\ creiamo "office.cfg".

Adesso CTRL+X su Filemon per ripulire la schermata e facciamo ripartire Lezione6.exe. Ripuliamo ancora la schermata e premiamo di nuovo il pulsante Check.
Ok, questa volta niente righe rosse...ma il crackme si comporta sempre alo stesso modo.

Questo significa una cosa: aver creato solamente i file non basta. C'è qualcos'altro: il contenuto. Sicuramente Non verificherà solo la presenza dei file, ma anche che contenuto!.
Per questo dobbiamo scoprire cosa scrivere destro questi file, e per farlo ci serviremo di OllyDbg.

Per prima cosa però, un pò di teoria:
La lettura e scrittura dei file in Windows avviene per lo più attraverso queste API:

_lopen, _lcreat, _lread, _lwrite

Queste sono usate molto raramente. Sono state progette per architetture a 16 bit ma mantengono la compatibilità. OpenFile, CreateFile, ReadFile, WriteFile

A differenza delle precedenti queste sono molto usate. La combinazione più comune è CreateFile+ReadFile+WriteFile.
Vediamole più in profondità: OpenFile( pNOMEFILE, pInfoBuffer, Azioni)

E' capace di creare, aprire e cancellare file. Anche questa è un pò obsoleta... Il primo parametro è un puntatore al nume del file (con relativo percorso). Il secondo è il puntatore a una struttura che conterrà le informazioni sul file una volta aperto.
Il terzo è il campo che indica l'azione da eseguire (vedere guida API per maggiori info)

CreateFile
Eccovi il prototipo di funzione: HANDLE CreateFile

(
   LPCTSTR lpFileName,	// pointer to name of the file
   DWORD dwDesiredAccess,	// access (read-write) mode
   DWORD dwShareMode,	// share mode
   LPSECURITY_ATTRIBUTES lpSecurityAttributes,	// pointer to security attributes
   DWORD dwCreationDistribution,	// how to create
   DWORD dwFlagsAndAttributes,	// file attributes
   HANDLE hTemplateFile 	// handle to file with attributes to copy
);

CreateFile è capace di aprire di tutto: dai file ai pipes, dalle directory alle console etc etc.
Il primo parametro è il classico puntatore alla stringa contenente il nome del file.
Il secondo indica la modalità di accesso: per i file ce ne sono 2:

GENERIC_READ indica un accesso in lettura
GENERIC_WRITE indica un accesso in scrittura

Tuttavia, si può ottenere lettura e scrittura semplicemente usando entrambi

GENERIC_READ + GENERIC_WRITE

Il terzo paramtro indica le regole di condivisione del file. Non è un campo molto utile ai nostri scopi, se volete comunque approfondimenti, basta sfogliare la vostra guida API.
Il quarto indica gli attributi di sicurezza. Come il precedente, di solito non serve a gran chè. Molto spesso è settato a 0.

Il quinto invece è importante: indica le modalità di apertura. Eccole elencate: CREATE_NEW indica che il file sarà creato se inesistente. Altrimenti, se il file è già presente, si avrà un errore.
CREATE_ALWAYS fa in modo che il file venga create anche se esiste già. E' chiaro che se esiste già, sarà azzerato.
OPEN_EXISTING apre il file. Se non esiste, la funzione darà errore. OPEN_ALWAYS apre il file o, se non esiste, lo crea.
TRUNCATE_EXISTING apre il file e lo azzera. Se il file non esiste, errore.

Il sesto parametro indica alcune opzioni e attributi.
il più usato è FILE_ATTRIBUTE_NORMAL. Gli altri potete leggerli direttamente sulla guida API.
Sempre in questo parametro possono essere indicati alcuni flag, che tranne in casi particolari, raramente sono usati.

L'ultimo parametro indica un handle di file dal quale prendere gli attributi...quasi sempre lasciato a zero.

Cercate di memorizzarla bene mi raccomando! :D

Adesso è venuto il momento di avviare Olly e metterlo a lavoro.
Aprite il file "cavia" (lezione6.exe) e atterrerete sull' Entry Point all'indirizzo 0040195A [Entry Point = Punto in cui il programma inizia la sua esecuzione]
Se avete poche esperienze di reversing vi si presenterà una struttura un pò anormale ma non preoccupatevi, è soltanto segno che non è un crackme scritto in assembly ma con un compilatore (avendo scritto io stesso il crackme vi dico anche che è il VS 2005 :D)
A questo punto sarebbe complicato cercare la parte di codice che ci interessa....ma basta pensare un attimo e ci accorgeremo che un indizio l'abbiamo.
Dopo l'analisi di Filemon, abbiamo osservato che il crackme cerca il file "watsup.not" e sappiamo anche che colui che ha scritto il crackme ha usato o OpenFIle o CreateFile (almeno al 90%) per l'apertura del file e che quindi il nome del file è espresso come una stringa.
Vi viene in mente niente?? Se abbiamo fortuna (classico elemento del reverse :D) la stringa contenete il nome del file (e quindi "watsup.not") potrebbe essere in chiaro (cioè visibile a prima occhiata) nel file.
Quindi abbiamo scelto un attacco: verifichiamo se va a buon termine...sulla finestra del codice di Olly clickiamo con il tasto destro e scegliamo

Search For -> All Referenced text String.


Si aprirà la finestra References di Olly (lettera R) e saranno visualizzate tutte le stringhe contenute nel file.
Quindi, cerchiamo quella che ci serve, ovvero "watsup.not"....che guarda caso è la prima ehehehe.


[P.S.]
*** Ricerca della stringa***
Nel caso le stringhe contenute nel file siano tante, è possibile effettuare una ricerca.
Basta premere il tasto destro e scegliere "Search for text". Vi si aprirà una finestrella con, oltre alla classica textbox, due opzioni, rispettivamente "Entire Scope" (ricerca totale e non solo in avanti) e "Case Sensitive" (Se volete la distinzione tra maiuscole e minuscole
[Fine PS]

Abbiamo quindi trovato ciò che volevamo. Facciamo doppio-click sulla stringa "watsup.not" e verremo catapultati nella parte di codice che la utilizza.
Come immaginato, ci troviamo su una chiamata a CreateFile. Ora, per evitare di perdersi ogni volta che riavviamo il programma, piazziamo un bel BreakPoint sul push del primo parametro di CreateFile, ovvero a 00401066.
Ora avviamo il programma sotto debug (in gergo "debuggee") con F9 e premendo il pulsante "Check" del crackme ci ritroveremo fermi sul breakpoint appena messo. Ok tutto va come dovrebbe andare!
Steppiamo con F8 fin dopo CreateFile e se abbiamo fatto tutto bene EAX conterrà il valore dell'handle del file (Che alla fine è come un n° di identificazione del file).
Appena dopo, notiamo che proprio EAX viene confrontato con -1 (o meglio 0FFFFFFFFh). Se non lo sapete (leggete bene la guida API!) il valore -1 corrisponde a INVALID_HANDLE_VALUE ed è restituito da CreateFile se non riesce ad aprire il file specificato. In poche parole il crackme controlla che il file sia presente.
Subito dopo EAX (che contienene l'handle del file) viene copiato nella DWORD all'indirizzo 004033DC.

[Consiglio: Etichette]
E' buona abitudine, ogni volta che si incontra un indirizzo che si ritiene importante, applicare un'etichetta.
Un'etichetta o "label" serve a rendere il disassemblato più leggibile. In pratica, applicando un'etichetta, si sostituisce all'indirizzo un nome, cosicché ogni ricorrenza dell'indirizzo sarà sostituita con il nome scelto.
Per "etichettare", facciamo click destro sulla riga che contiene l'indirizzo (o anche su un registro in alto a destra) e facciamo un bel "Follow in Dump" -> "Memory Address" o "Inplicit Stack address" a seconda di quello che volete visualizzare (generalmente il primo). Ora, nella finestra bassa di Olly (Data window) selezionare la prima DWORD e premere : per assegnare a questo indirizzo un'etichetta.
Usando questo procedimento per l'indirizzo di sopra, tutte le ricorrenze dell'indirizzo 004033DC saranno sostituite con il nome inserito. Bello no?
[Fine consiglio]

Continuiamo a steppare (siamo a 0040108F), EDI viene caricato con un indirizzo (abbastanza sospetto) e quindi troviamo il jmp condizionale del controllo della presenza del file.
Se avete fatto tutto bene, il jmp non sarà eseguito.
Ora viene la parte che ci interessa: siamo di fronte a ReadFile. Eccovi prima di tutto il prototipo preso dalla guida API:

BOOL ReadFile(
   HANDLE hFile,	// handle del file dal quale leggere
   LPVOID lpBuffer,	// buffer dove andranno a finire i dati letti (IMPORTANTE!)
   DWORD nNumberOfBytesToRead,	// n° di bytes da leggere
   LPDWORD lpNumberOfBytesRead,  // indirizzo dove andrà a finire il n° dei byte effettivamente letti
   LPOVERLAPPED lpOverlapped 	// indirizzo per una struttura OVERLAPPED (quasi inutile generalmente)
  );

Torniamo ad esaminare il codice: seguendo il prototipo sappiamo che:

  1. Legge dal file 18h bytes (cioè 24)
  2. I dati vengono salvati all'indirizzo contenuto in EDI

Mettiamo un etichetta all'indirizzo di EDI, piazziamo un breakpoint e ravviamo Olly (altrimenti non possiamo modificare il file watsup.not!)
Il crackme legge 24 byte, quindi per essere più credibile, il nostro watsup.not deve contenerli 24 bytes!. Detto fatto, apriamo il notepad (sarebbe meglio un hex editor) e aggiungiamo 24 bytes a caso.
Riprendiamo Olly, un bel F9 per ritornare a prima, facciamo un "Follow in Dump" su EDI e steppiamo fin dopo ReadFile e osservando la Data Window mentre viene riempita con i bytes letti dal file.
D seguito troviamo un bel controllo: viene controllato se la dword a ESP+10h è minore di 14h. Con un pò di ricerca nella stack window, ci possiamo accorgere che l'indirizzo ESP+10h è l'indirizzo passato al penultimo parametro di ReadFile, cioè il n° dei bytes effettivamente letti.
Questo quindi è un controllo che verifica che siano stati letti almeno 14h bytes dal file.
Andiamo aventi. Troviamo un altro controllo decisamente strano...confronta il primo byte di una stringa con 79h. Ma, facendo una ricerca (tasto destro -> Find references -> Immediate constant) sull'indirizzo notiamo che questo è l'unico punto in cui è utilizzato. Inoltre la destinazione del salto è la stessa del controllo precedente.
Che sia una trappola? Esatto.
Limitiamoci a steppare, poichè il controllo fallirà sempre.
Arriviamo quindi a 004010BB dove raggiungiamo un ciclo (da 004010C2 a 004010DD):

XOR ECX,ECX				;azzera ECX
MOV EAX,0040340E		;mette in eax un indirizzo (che con un pò di analisi si scoprirà essere l'indirizzo dell'ultimo byte di quelli letti dal file)

|-> MOVZX EDX,BYTE PTR [ECX+4033F8] ;prende un carattere da quelli letti dal file (004033F8 contiene i caratteri letti dal file!) | MOVZX ESI,BYTE PTR [EAX] ;mette in esi il contenuto di eax | XOR EDX,55 ;xora il contenuto di EDX con 55h | ADD ESI,6 ;aggiunge ad ESI 6 | CMP EDX,ESI | JNZ SHORT 004010ED ;verifica che siano uguali e se non lo sono....tanti saluti | INC ECX ;incrementa ECX | DEC EAX ;decrementa EAX | CMP EAX,00403404 ;è arrivata la fine? |-JG SHORT 004010C2 ;se no, ricomincia il ciclo

Eccovi la spiegazione:
Questo ciclo opera sui dati letti dal file. Prende due "indici", uno all'inizio dei dati e uno alla fine. Quindi, il dato puntato dal primo indice viene xorato per 55h mentre a quello puntato dal secondo viene aggiunto 6. Infine viene verificato che siano uguali.
Dopo ciò, il primo indice (che puntava al primo dato) viene incrementato (punta al successivo) mentre il secondo indice (che puntava all'ultimo dato) viene decrementato (punta al precedente). Questo finchè il secondo indice rimane nella seconda parte dei dati.

Quindi, per passare questo controllo, dovremo fare in modo che i dati della prima metà del file, xorati per 55h, diano come risultato valori ai quali aggiunto 6, diano il corrispondente della seconda metà.
Possiamo procedere nel seguente modo:

  1. prendiamo l'hex editor e sostituiamo al file "watsup.not" i byte che abbiamo messo prima con una serie di 20h (basta riempire i primi 12)
  2. prendiamo gli ultimi 12 bytes e sostituiamoli con una serie (20h xor 55h) - 6 = 6Fh.

Fatto ciò salvate tutto, riavviate olly e vediamo se tutto fila. Torniamo alla zona del controllo e steppiamo controllando che il salto a 004010D4 non sia mai eseguito.
Se avete agito bene, vi ritroverete a 004010DF...dove è presente un'altra stupida trappola :D
Mentre, dopo, possiamo osservare il modo in cui il crackme decide se siamo stati bravi...un bel OR di una variabile (booleana?) con 1....
Infine, notiamo un bel CloseHandle, una API usata per chiudere gli handle, compresi quelli dei file.
Possiamo quindi dire che con "watsup.not" abbiamo finito.
Inoltre, premendo F9 facendo continuare l'esecuzione normalmente, possiamo notare che abbiamo superato con successo il primo punto!!

Requisito n° 2

Ripartiamo come fatto per il requisito precedente: apriamo Filemon, vediamo se cerca altri file. Noterete che non cerca altri file...cosa potrebbe cercare dunque? Una reg key? Proviamo!

Apriamo quindi RegMon (che è praticamente uguale a Filemon, soprattutto per quanto riguarda la configurazione) e vediamo se trova qualcosa...

Se avete fatto tutto bene noterete che vengono cercate delle chiavi di registro molto strane, e più precisamente: HKCU\le_gengive\ti_fanno_tanto\male HKCU\perche\qualcuno\le_ha\colpite HKCU\quel\qualcuno\sono_io

(p.s. lo so, ho tanta fantasia ;D) (p.p.s. HKCU è l'abbreviazione di HKEY_CURRENT_USER, nota chiave di registro!)

Prima di proseguire eccovi un pò di teoria:

  1. Se non sapete nemmeno cosa sono, aprite il regedit (Start->esegui->regedit) e lo scoprirete. Dal regedit potere gestire creazione e modifica delle chiavi, dei campi e dei valori in essi contenuti.
  2. A livello di programmazione, le chiavi di registro possono essere aperte, lette o scritte mediante API apposite. Per quanto riguarda l'apertura si usa RegOpenKey o RegOpenKeyEx (quest' ultima è più usata); per la chiusura si usa RegCloseKey.

Per effettuare una query su un campo (ossia "chiedere gentilmente il suo valore") si usa RegQueryValue o RegQueryValueEx. LONG RegOpenKeyEx(

   HKEY hKey,	// handle della chiave. Potete scegliere tra HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, HKEY_USERS
   LPCTSTR lpSubKey,	// puntatore a una stringa che indica la sotto-chiave da aprire
   DWORD ulOptions,	// riservato, non ci serve
   REGSAM samDesired,	// Tipo di accesso ai dati della chiave: controllate la guida API per i possibili valori
   PHKEY phkResult 	// indirizzo dove sarà messo l'handle della chiave aperta
  );

LONG RegQueryValueEx(

   HKEY hKey,	// come in RegopenKeyEx
   LPTSTR lpValueName,	// puntatore alla stringa che contiene il nome del campo della chiave da leggere
   LPDWORD lpReserved,	// riservato
   LPDWORD lpType,	// puntatore alla variabile che conterrà il tipo (leggete la guida API per i possibili valori!)
   LPBYTE lpData,	// puntatore al buffer che riceverà i dati
   LPDWORD lpcbData 	// puntatore a una variabile indicante il n° di byte da leggere
  );

Le altre API relative alla gestione del registro non ci interessano: vi invito comunque a dare un'occhiata alla guida API per maggiori informazioni.

Torniamo al crackme. Sappiamo quindi che il crackme cerca 3 chiavi di registro. E noi dobbiamo fare in modo di fargliele avere. Aprite il regedit, espandete HKCU, un click con il tasto destro su HKCU, quindi "Nuovo->chiave" e dategli il nome della prima chiave (le_gengive). Dunque, clickate con il destro su quest'ultima e create una sotto-chiave "ti_fanno_tanto_male" e così via fino a creare tutte le chiavi e sottochiavi richieste.

Se avete fatto bene, un controllo con il regmon dovrebbe darvi ragione.

Tuttavia, nonostante le chiavi siano presenti, il crackme non spunta anche il requisito due.

Adottiamo la stessa tecnica usata in precedenza, apriamo Olly, e cerchiamo tra le stringhe se troviamo qualcosa. E in effetti qualcosa si trova...qualcosa a partire dall'indirizzo 00401113.

Qui si trova il seguente codice: 00401113 PUSH 004033D8 00401118 PUSH 20019 0040111D PUSH EBX 0040111E PUSH 00402134 00401123 MOV ESI,80000001 00401128 PUSH ESI 00401129 CALL EBP ;(RegOpenkeyEx) apertura prima chiave

0040112B TEST EAX,EAX 0040112D JNZ 00401289 ;controllo presenza

00401133 SHR BYTE PTR [EAX+40303C],1 ;(?????) CICLO STRANO 1 (?????) 00401139 INC EAX 0040113A CMP EAX,28 0040113D JL SHORT 00401133

0040113F PUSH DWORD PTR [4033D8] 00401145 CALL DWORD PTR [<&ADVAPI32.RegCloseKey>] ;chiusura chiave

0040114B PUSH 004033D8 00401150 PUSH 20019 00401155 PUSH EBX 00401156 PUSH 00402154 0040115B PUSH ESI 0040115C CALL EBP ;(RegOpenkeyEx) ;apertura seconda chiave

0040115E TEST EAX,EAX ;controllo presenza 00401160 JNZ 00401289

00401166 ADD BYTE PTR [EAX+40303C],20 (??????) CICLO STRANO 2 (?????) 0040116D INC EAX 0040116E CMP EAX,28 00401171 JL SHORT 00401166

00401173 PUSH DWORD PTR [4033D8] 00401179 CALL DWORD PTR [<&ADVAPI32.RegCloseKey>] ;chiusura chiave

0040117F PUSH 004033D8 00401184 PUSH 20019 00401189 PUSH EBX 0040118A PUSH 00402174 0040118F PUSH ESI 00401190 CALL EBP ;(RegOpenkeyEx) ;apertura terza chiave

00401192 TEST EAX,EAX ;controllo presenza 00401194 JNZ 00401289

0040119A PUSH DWORD PTR [4033D8] 004011A0 CALL DWORD PTR [<&ADVAPI32.RegCloseKey>] ;chiusura

Vediamo che questo pezzo di codice cerca le chiavi di prima, le apre (verificandone la presenza) e subito dopo le chiude. MA, tra le 3 chiamate a RegOpenKey, sono annidati 2 cicli che decrittano (riportano alla normalità) la stringa che sarà usata nella successiva chiamata a CreateFile: 004011A6 PUSH EBX 004011A7 PUSH 80 004011AC PUSH 3 004011AE PUSH EBX 004011AF PUSH EBX 004011B0 PUSH 80000000 004011B5 PUSH 0040303C ;<- ECCOLA QUI 004011BA CALL DWORD PTR [<&KERNEL32.CreateFileA>]

Per evitare di fare inutilità, limitiamoci a steppare fino al CreateFile (004011A6 o almeno fino alla fine del secondo ciclo di decript). In questo modo la stringa sarà decriptata e potremo leggere finalmente il nome del file cercato in chiaro:

C:\Programmi\Microsoft Office\office.cfg

E' strano, ma è proprio questo!

Creiamo questo file e riprendiamo subito Olly...infatti poco dopo c'è una chiamata a ReadFile PUSH EBX LEA ECX,DWORD PTR [ESP+18] PUSH ECX PUSH 8 PUSH EDI PUSH EAX CALL DWORD PTR [<&KERNEL32.ReadFile>]

che legge 8 bytes dal file appena aperto

CMP DWORD PTR [ESP+14],8 JNZ 00401271

controllando che siano effettivamente 8

MOV ECX,99 XOR EAX,EAX

/--XOR BYTE PTR [EAX+dati_dal_file],CL | SUB ECX,11 | INC EAX | CMP EAX,8 \--JL SHORT 004011F0

Ed eccoci qua ad una parte interessante: un bel ciclo. Ecco cosa fa:

0) inizializza ECX a 99h e EAX a 0

1) XORA il byte n-esimo con CL (quindi alla prima passata con 99h)

2) sottrae a ECX 11h (quindi da 99h diventa 88h

3) incrementa EAX e verifica che non superi 8

quindi non fa altro che xorare gli 8 byte letti dal file rispettivamente con 99,88,77h,66h,55h,44h,33h,22h,11h

Fatto ciò, compare questo codice: 004011FF PUSH 004033D8 00401204 PUSH 0F003F 00401209 PUSH EBX 0040120A PUSH 0040218C  ; ASCII "ma_nessuno\lo_sa" 0040120F PUSH ESI 00401210 CALL EBP  ; ADVAPI32.RegOpenKeyExA

00401212 TEST EAX,EAX 00401214 JNZ SHORT 00401271

Apre un'altra chiave ("HKCU\ma_nessuno\lo_sa"). 00401216 LEA EAX,DWORD PTR [ESP+18] 0040121A PUSH EAX  ; /pBufSize = NULL 0040121B PUSH 004034C0  ; |Buffer = Lezione6.004034C0 00401220 LEA EAX,DWORD PTR [ESP+24]  ; | 00401224 PUSH EAX  ; |pValueType = NULL 00401225 PUSH EBX  ; |Reserved = NULL 00401226 PUSH 004021A0  ; |ValueName = "ragione" 0040122B PUSH DWORD PTR [4033D8]  ; |hKey = 40 00401231 MOV DWORD PTR [ESP+30],0A  ; | 00401239 CALL DWORD PTR [<&ADVAPI32.RegQueryValueExA>] ; \RegQueryValueExA 0040123F TEST EAX,EAX 00401241 JNZ SHORT 00401271

00401243 CMP DWORD PTR [ESP+1C],3 ;controlla che il tipo del campo sia REG_BINARY (indicato dal 3) 00401248 JNZ SHORT 00401271

(PS. Se vi domandate come il 3 significhi REG_BINARY... Se avete il Visual Studio o un altro qualsiasi compilatore C, C++, basta cercare tra i file header, altrimenti basta cercare online)

Ecco che viene letto un campo dalla chiave appena aperta. Il campo si chiama "ragione" e i dati letti da questo campo sono memorizzati a 004034C0.

Come al solito, piazziamo un breakpoint qui intorno (004011FF va benissimo) , chiudete olly, aprite regedit e create chiave ("HKCU\ma_nessuno\lo_sa") e valore ("ragione").

Quindi riaprite Olly e torniamo all'analisi: 0040124A PUSH DWORD PTR [4033D8]  ; /hKey = 00000040 (window) 00401250 CALL DWORD PTR [<&ADVAPI32.RegCloseKey>]  ; \RegCloseKey

chiusura della chiave. 00401256 XOR EAX,EAX 00401258 MOV CL,BYTE PTR [EAX+dati_dal_file] 0040125E CMP CL,BYTE PTR [EAX+dati_dalla_chiave] 00401264 JNZ SHORT 00401271 00401266 INC EAX 00401267 CMP EAX,8 0040126A JL SHORT 00401258

Eheh eccoci qua ad un bel controllo: Controlla semplicemente che i dati letti dal file, xorati come precedentemente scritto siano uguali a quelli letti dalla chiave.

Per far passare questo controllo quindi, conviene fare nel seguente modo:

  1. decidiamo una stringa di 8 char
  2. la xoriamo come sopra (il primo char con 99h, il secondo con 88h etc.)
  3. Mettiamo la stringa risultante nel file C:\Programmi\Microsoft Office\office.cfg con l'hex editor


Di seguito troviamo solo il settaggio della variabile booleana usata per le checkbox e il la chiamata a CloseHandle per chiudere il file.

Se riavviate il crackme noterete che anche questo requisito è fatto.


Assegno

Ora, il requisito n°3....

Bhè io vi ho illustrato i primi due...il terzo è tutto per voi. Comunque, siccome che il terzo è un pò più ostico eccovi qualche hint:

  1. Tutto inizia a 00401297
  2. Key File e Reg Key sono usati in modo combinato
  3. Tutto finisce a 00401545
  4. Ricordate di usare sempre la vostra guida API per qualsiasi incertezza!
  5. Tutto ha un significato, alcune volte subdolo, altre decisamente utile.
  6. Ma soprattutto....preparate Daemon Tools... (e scoprirete il perchè)

In ogni caso, se avete bisogno potete servirvi del forum.
Buona fortuna

§-Death_Reaver-§


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 malevole 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.