SVKP 1.3x |
||
Data |
by "SatUrN" |
|
25/12/2004 |
Published by Quequero |
|
Quando dormo poco sono più allegro... |
Bravissimo saturn hai fatto un tute davvero curato e approfondito! |
Quando dormo tanto sono più bello! (V. Rossi) |
.... |
E-mail: [email protected] |
.... |
Difficoltà |
( )NewBies ( )Intermedio (X)Avanzato ( )Master |
Introduzione |
In questo tutorial vedremo di unpackare manualmente uno dei
tanti packers in commercio.
La metodologia utilizzata sarà sicuramente molto utile per altri packers, benché sia abbastanza “grezza”.
Sottolineo che il tute riguarderà soltanto la decompressione
e la ricostruzione e non l’analisi della protezione, per quello dovete pensarci
voi!
Il programma utilizzato è Dart XP Pro e serve a restaurare il suono di registrazioni. Vi riporto la loro descrizione:
“DART XP Pro (Digital Audio Restoration Technology) is a sophisticated program for the restoration of archived audio recordings. It is capable of removing impulsive disturbances (such as clicks, pops and record scratches), wide-band noise (such as tape hiss or record surface noise) and harmonic disturbances (such as power line hum) - and does it in a fast and efficient way.”
La versione usata è la 1.1.5p ed è l’ultima disponibile attualmente.Il target è stato segnalato
da Zero_G nel forum della UIC
perché è compresso con SVKP (Slovak Protector) del nostro amico Pavol
Cerven. Visto che sto scrivendo sotto natale vediamo
di fare un regalino anche a lui :-)
Inoltre non mi risulta ci siano tutorials in italiano
su questo packer, perciò ho deciso di sacrificare
un po’ del mio tempo e di scriverne uno io. Fatene buon uso!
Tools usati |
OllyDbg 1.10 (+plugin OllyDump)
PeID
0.92 (Per identificare il packer)
ImpREC v1.6 Final
PEditor 1.7 (un qualsiasi PE editor va bene, servirà
solo per cambiare l’OEP)
Winamp 5.08 (Per ascoltare MP3 durante l’unpacking, ma anche per… SORPRESA!)
Chi avesse problemi a recuperare qualche programma (specie ollydump) può chiedere alla UIC, c’è sicuramente qualcuno disposto a spedirli! (Il sottoscritto per primo)
URL o FTP del programma |
www.dartpro.com
Essay |
Cominciamo!
La prima cosa da fare è identificare il packer. Sapete
già qual’è? E grazie al caxxo,
l’avete letto nel titolo!
Prendete comunque PeID
e andate a cercare l’exe da analizzare.
“SVKP 1.3x -> Pavol Cerven”
Bene, bene adesso ci pensiamo noi!
Apriamo il nostro fido OllyDbg e diamogl i in
pasto Dart XP. Naturalmente ci
viene segnalato che l’EP non è nella sezione di codice. L’EP attuale
fa parte della sezione .svkp ed è all’offset 700000
(300000+image base).
Evitiamo pure di far eseguire l’analisi a
olly che risparmiamo tempo.
Vi anticipo che non ci sono controlli debugger, quindi
possiamo lavorare più tranquilli.
Facciamo gestire tutte le eccezioni a
olly e avviamo il prog.
Si incontrano 4 eccezioni, passiamole di volta in volta al programma
(SHIFT+F9). Quando passiamo l’ultima, il prog
parte (ci mette un po’ ma parte).
Bene ricominciamo (abituatevi), ma stavolta fermiamoci alla quarta eccezione
che è un INT1.
A questo punto mettiamo un bel memory breakpoint
on access sulla sezione code (401000-4F8000).
Se non sapete come fare leggetevi il tutorial di
Bender0 su olly, disponibile naturalmente alla UIC.
Continuiamo l’esecuzione (SHIFT+F9) e aspettiamo che il debugger
riprenda il controllo. A questo momento ci troviamo qui:
|
Il punto dove si brekka (0996FCB4)
non è certo l’OEP come ci poteva aspettare.
Se continuiamo l’esecuzione, vediamo che continuiamo
a breakkare su 3 istruzioni. Cosa
sta succedendo? Questo è il loop che si occupa di
riscrivere tutti gli opcodes dell’eseguibile, praticamente la decriptazione.
Il nostro memory bp ci ha fatto fermare troppo presto!
Fa niente, perché dando uno sguardo più sotto vediamo un RET, allora possiamo
togliere il memory bp
e metterne uno “normale” sul RET all’offset 0996FCE4.
Vi ricordo che difficilmente gli offset saranno uguali ai miei, questo succede
perché la memoria viene allocata diversamente su
ogni pc.
Vabbè perlomeno le istruzioni sono uguali, perciò
un bel RUN e aspettiamo di breakkare sul RET.
A questo punto rimettiamo il memory bp
sulla sezione code come in precedenza e togliamo quello sul RET.
Se vi dimenticate di togliere il bp
non c’è problema, olly breakkerà
ancora 3 volte nello stesso punto perché per la decriptazione
delle altre sezioni viene usata la stessa routine.
Continuando da dove ci siamo fermati e se avete fatto le cose in ordine vi
bloccate qui:
|
Date un occhio all’offset, sembra proprio
che ci siamo. Eh sì questo è l’OEP, ma solo per qualche nanosecondo. Provate
a guardare le istruzioni precedenti alla prima call. Cosa vedete? Una sfilza di
NOP! Questi sono gli stolen bytes
che dovremo riscrivere, quindi l’OEP verrà cambiato.
Ce ne occupiamo dopo perché sarà la cosa più difficile.
A questo punto cominciamo a pensare alla IT che è
stata manomessa. Visto che dovremo riniziare da
capo (e questo ve lo anticipo io) evitiamo di dumpare.
Apriamo invece ImpREC e vediamo quante entrate non
sono risolte.
Carichiamo dartxppro.exe, inseriamo il nostro OEP (4E7EE2-image base=E7EE2)
e facciamo cercare la IAT a ImpREC.
La trova all’RVA F8000. Sarà giusto? Beh possiamo
verificarlo con olly.
Dobbiamo visualizzare la memoria a partire da 4F8000
(image base + RVA IAT)
Che fortuna è già visualizzata nella finestra del dump!
E’ la sezione data, che si estende da 4F8000 a 527000.
Guardate all’inizio (4F8000) e vedrete una struttura che potrebbe essere quella
della IAT. Per essere veramente sicuri che ImpREC
non si sia sbagliato basta guardare la grandezza della IAT, ImpREC
ci dice 157C perciò:
4F8000+157C=4F957C
e qui la IAT deve essere finita.
Si è proprio così, bravo ImpREC!
A questo punto possiamo premere su “Get Imports” e far risolvere le entrate. 190 invalide!!!!!!!!!!
Non disperatevi perché le possiamo ridurre. Come?
Premiamo su “Show Invalid” e poi pulsante destro
su una qualsiasi entrata invalida. Facciamo un “Trace
Level1 (Disasm)” e vediamo che le invalide scendono
a 31. Ancora troppe e io di tracciarle ad una ad una a mano, rischiando oltretutto
di sbagliare, proprio non ne ho voglia.
Visto che adesso sappiamo dove viene scritta la IAT,
vediamo di intercettare il punto quando viene scritta.
Ripartiamo dall’inizio e mettiamo un memory bp on write sul primo byte della
IAT (4F8000).
Volendo potete passare tutte le eccezioni direttamente al programma, così
evitate di dover premere ogni volta SHIFT+F9.
Bene, facciamo ripartire il programma e aspettiamo
di breakkare. Dove ci si ferma? Naturalmente nello stesso loop di prima perché, prima della scrittura della IAT, la
sezione deve essere decriptata. Ve l’ho detto che
viene usata sempre la stessa routine.
Quindi il primo break non ci interessa, perciò premiamo
ancora F9.
Aspettiamo un attimo e ci troviamo qua:
|
Se steppiamo vediamo che effettivamente viene
messo il contenuto di EAX nella dword puntata da EDI!
Il problema è che in EAX c’è l’entrata errata.
Guardiamo le istruzioni precedenti per capire cosa fa il prog.
Ma porc… cosa succede?
Eh sì, olly fa confusione a causa di bytes
di interferenza, perciò vediamo questo:
|
Guardate gli offset rispetto a prima,
sono tutti sballati! Però, con un po’ di ingegno, possiamo aggiustare 2-3 righe per semplificare
la lettura.
Osservate il flusso: c’è il POP EDI, un JMP a 09966CFB,
un POP EAX e un JMP a 09966D00. A questo offset c’è
l’istruzione che scrive la IAT (MOV DWORD PTR DS:[EDI],EAX), quindi i 2 bytes prima (09966CFE, 09966CFF) non servono a niente perché
vengono saltati, noppiamoli e otteniamo questo:
|
Un po’ più leggibile no?
Adesso quello che ci serve è che venga scritto in
EAX l’EP esatto. Dove lo prendiamo? E che ne so, pensateci voi, non posso
mica fare tutto io!
No sto scherzando, non abbandonate la lettura e lo
scoprirete!
Date un occhio allo stack e vedrete l’API “ADVAPI32.RegSetValueExA”
all’indirizzo 0012FF90 (da me). Inutile dire che è quella che viene
sostituita con un fake EP riferito alla memoria
allocata da SVKP.
Noi dobbiamo riuscire a mettere l’EP originale in EAX e farlo scrivere nella
IAT al posto di quello falso.
Ok, adesso ci pensiamo noi ad aggiustare il codice.
Trasformatelo come segue:
|
Avete capito cosa ho fatto? Il POP EAX viene eseguito
come in precedenza per evitare di sballare lo stack,
ma subito dopo in EAX ci scriviamo l’EP corretto che, come avete capito, si
trova sullo stack a 0012FF90.
Ora ESP è 0012FF74 quindi l’indirizzo che serve a noi (0012FF90) si trova
a ESP+1C.
Bene, adesso sappiamo come cambiare il codice. Però dobbiamo ricominciare
perché alcune entrate erano già state scritte.
Mettete un hardware breakpoint a 09966CF6 sul “POP
EDI” e riavviate. Quando breakkate sul POP EDI (ci
si mette un attimino) cambiate il codice come abbiamo
appena visto.
Ok, adesso potete togliere l’hardware bp e mettere un memory bp sulla sezione code come in precedenza.
Fate continuare il prog e aspettate di breakkare all’OEP.
In questo caso non dobbiamo preoccuparci di rimettere a posto il codice perché
non ci sono controlli, ma tenete presente che possono esistere (Arma, ASPR,...) e di solito portano alla chiusura del programma.
Visto che fortunatamente non è un nostro problema andiamo avanti.
Siamo fermi all’OEP con la IAT valida, quindi possiamo dumpare
facendo uso del plugin olly
dump e disattivando l’opzione
“Rebuild Import”.
Potete usare qualsiasi altro tool (lordPE, PEditor,...), ma visto che non li ho testati non vi assicuro
niente.
Ora aprite ImpREC e caricate dartxppro.exe, inserite
l’OEP, premete su “IAT Auto Search” e poi su “Get
Imports”.
Solo 2 entrate invalide! Molto meglio di prima ma non ci siamo ancora. Vabbè chi se ne
frega, fixiamo lo stesso, ma ricordandoci che dobbiamo
fixarle dopo a mano.
Un dump quasi a posto, ma non dimentichiamoci degli
stolen bytes!
Arriva la parte più bella e interessante: gli stolen
sono 106 e conoscendo il packer non saranno facili
da scovare.
Ho provato a breakkare prima di raggiungere l’OEP
e steppare con cura, ma trovare gli stolen
in mezzo a un mare di istruzioni che non c’entrano
niente è praticamente impossibile.
Che si può fare? Ci ho pensato giusto un attimo e
mi si è accesa una lampadina: la struttura iniziale è sempre ripetitiva quindi
basta trovare un programma simile per farsi un’idea delle istruzioni mancanti.
Indovinate che programma ho trovato...
Bravi, proprio Winamp!
Caricatelo in olly e vedrete la somiglianza col
nostro dump (stolen a
parte).
Ecco come vi si presentano i due file in olly:
La prima cosa che dobbiamo fare è copiare tutta la struttura di Winamp
e incollarla nel nostro dump.
Selezionate dall’OEP di Winamp fino all’istruzione
“MOV DWORD PTR DS:[470D30],EAX” compresa. Pulsante
destro --> Binary -->
Binary Copy.
Adesso selezionate tutta la serie di NOP nel dump
e fate un bel Binary Paste. Ci sta tutto a puntino!
Ed ecco il risultato:
|
Naturalmente nella parte copiata dobbiamo mettere a posto alcuni indirizzi (evidenziati
in rosso) perché sono riferiti a Winamp e non a Dart XP.
Dove li troviamo quelli corretti? Nel programma compresso, e dove se no? Adesso
però, a differenza di prima, sappiamo che istruzioni cercare!
Tenete aperto olly con
il file dumpato, chiudete olly
con Winamp perchè non
ci serve più, aprite un’altra finestra di olly e
caricateci Dart XP compresso.
Adesso dobbiamo riuscire ad breakkare
il più possibile vicini all’OEP per poter steppare
e beccare ciò che ci serve.
Partendo da un punto che già conosciamo, e cioè la
scrittura della IAT, vediamo di trovare qual’è l’ultima
entrata scritta. Da quel punto l’OEP non dovrebbe essere troppo distante.
E sarà così in effetti!
Rimettete un memory bp
on write sul byte 4F8000 e avviate. Si breakka
2 volte, la seconda, se ben ricordate, sull’istruzione “MOV DWORD PTR DS:[EDI],EAX”. Metteteci sopra un bp
“normale” e continuate con F9 tenendo d’occhio il registro EDI, che è quello
che contiene l’indirizzo per scriverci l’entrata processata.
L’ultima entrata scritta è all’indirizzo 004F8DBC. Tenetelo a mente e riavviate
(e che palle!).
Stavolta il nostro memory bp
on write lo metteremo all’indirizzo appena trovato
(004F8DBC). 2 break e ci troviamo al punto di prima
col packer pronto a scrivere l’ultima entrata della
IAT.
Rimettete un memory bp
sulla sezione code e stavolta continuate premendo CTRL+F11 che non è altro
che uno Step Into, con
la differenza che viene fatto un log.
Dopo un paio di secondi vi troverete all’OEP ma con
tutte le istruzioni eseguite loggate.
Apriamo il log (è l’iconcina azzurra in alto con
i 3 puntini) e diamogli uno sguardo attento.
Le istruzioni loggate dovrebbero essere 8842, ma
partiamo dal presupposto che gli stolen verranno passati subito prima di raggiungere l’OEP. Quindi
possiamo andare in fondo al log dove ci sono le ultime istruzioni eseguite
prima del break all’OEP e fare un po’ di “Back Tracing
visuale”.
Io la prima volta ho fatto esattamente come vi ho descritto, poi ho preferito
far scrivere il log in un file per poter cancellare quello che non mi interessava e evidenziare gli stolen.
La prima istruzione che dobbiamo cercare partendo dal basso
sarà di questa forma:
MOV DWORD PTR DS:[XXXXXX],EAX
La troverete subito, è la 16-17esima partendo dal basso, e le istruzioni precedenti,
a parte un paio di interferenza che servono al packer
per poter chiamare le API __set_app_type, __p__fmode e __p__commode, sono
le altre che ci servono.
Ecco cosa ho trovato dal log:
|
Adesso vi basta sostituire gli indirizzi in verde a quelli in rosso trovati
prima. Ve li riporto per comodità e come vedete tutto coincide a meraviglia:
|
Per gli indirizzi 53581C e 535820 potreste avere
problemi a cambiarli direttamente nel disassemblato
di olly. Se ottenete l’errore
“Unknown Identifier” dovete
sostituire l’FFFFFFFF nell’istruzione con un –1,
ci penserà poi olly a rimettere tutto a posto!
Abbiamo finito? Certo che no! Dobbiamo ancora cambiare l’OEP, visto che abbiamo aggiunto gli stolen,
e fixare le 2 entrate che non sono ancora risolte.
Per l’OEP lo so che sapete come si fa, ma lo scrivo lo stesso.
Prendere un PE editor (io ho usato PEditor
1.7) e caricate il dump. Ora cambiate
l’Entry Point da E7EE2 a E7E78, salvate e uscite.
E adesso ci occupiamo delle 2 entrate non risolte.
Si trovano rispettivamente a 4F83B0 e a 4F83CC nella IAT, ma dobbiamo trovare
dove vengono chiamate. Potete fare un “search for command” (CTRL+F)
nel disassemblato di olly e cercare:
|
Metteteci dei bp e avviate il dump così breakkate subito prima che vengano
eseguite.
|
Visto che l’OEP è 4E7E78 siamo proprio una manciata
di istruzioni più sotto. Per questa entrata possiamo ancora appoggiarci a Winamp.
Aprite un altro olly e ricaricate Winamp,
confrontate ancora la struttura e in corrispondenza della nostra call [4F83B0] troverete un bel call
“GetModuleHandleA”, è questa l’API non risolta!
Se vi mettete sopra con il mouse e scegliete Follow
In Dump --> Memory
Address vi troverete alla DWORD con l’EP dell’API, pronto
per essere copiato e incollato a 4F83B0 nella IAT del nostro dump. Facile no?
E la prima è a posto. Ricordatevi di salvare il tutto e poi ricaricate il
nuovo file.
Ricercate di nuovo la seconda entrata “CALL DWORD PTR DS:[4F83CC]”
e rimettete i bp. Avviate e aspettate di breakkare, arriverete qui:
Se non vi ricordate come fare vuol dire che avete una memoria di merda! Ritornate all’inizio e ricominciate a leggere dal principio!
Se al contrario avete una buona memoria
siete già fermi come me all’OEP.
Togliete il memory bp,
mettetene uno all’offset 004E0DA3 e continuate l’esecuzione.
A questo punto la tentazione è di fare uno Step
Into e tracciarsi la call per vedere
cosa fa. Fatelo pure, io non ne ho ricavato niente.
Quindi ho preso un’altra strada.
Ho notato che il registro EAX, che viene pushato prima della call, entra
con 94 ed esce con 1.
Va bene, togliamo la call e facciamo mettere 1 in
EAX.
Ecco la trasformazione, se prima era così:
|
Adesso è così:
|
Ricordatevi che la call [4F83CC] viene richiamata 2
volte quindi dovete ripetere l’operazione anche per l’altro offset (004E0D73)
che si trova poco più sopra.
E ricordatevi anche di salvare il file dopo la modifica.
Bene, abbiamo direi che proprio finito!
Ci sono un paio di punti che non sono esattamente perfetti, ma chi se ne frega,
il programma funziona!
Se dovessero essercene basta andare un po’ più a
fondo e mettere tutto a posto.
Adesso potete divertirvi con la protezione interna del prg!
SatUrN
Note finali |
Per finire passiamo ai saluti
Ciauz
Disclaimer |
Non mi ritengo
responsabile per eventuali anni causati al vostro computer determinati dall'uso
improprio di questo
Noi