Zoom Icon

SVKP 1.3x

From UIC

SVKP 1.3x Manual Unpacking

Contents


Infos
Author: SatUrN
Email: saturn22611@yahoo.it
Website: None
Date: 25/12/2004 (dd/mm/yyyy)
Level: Major skills are required
Language: Italian Image:Flag_Italian.gif
Comments: Regalo di Natale



Introduction

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!


Tools

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'OEPOriginal Entry Point)
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)


Link e Riferimenti

h**p://www.dartpro.com


Notizie sul Programma

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!


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 diamogli 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:

0996FCA5 MOV AL,BYTE PTR DS:[EBX+ECX+1] // \ |
0996FCA9 INC ECX // | |
0996FCAA CMP ECX,0F // | primo loop |
0996FCAD NOP // | |
0996FCAE MOV BYTE PTR DS:[EBX+ECX-1],AL // | |
0996FCB2 JL SHORT 0996FCA5 // / |
0996FCB4 MOV AL,BYTE PTR DS:[ESI] // noi atterriamo qui |
0996FCB6 INC ESI // | secondo loop
0996FCB7 INC EDI // |
0996FCB8 MOV BYTE PTR DS:[EBX+F],AL // |
0996FCBB MOV AL,BYTE PTR DS:[ESI-1] // |
0996FCBE PUSH EBP // |
0996FCBF CALL 0996FCC4 // |
0996FCC4 POP EBP // |
0996FCC5 SUB EBP,470D // |
0996FCCB MOV CL,BYTE PTR SS:[EBP+350] // |
0996FCD1 POP EBP // |
0996FCD2 XOR AL,CL // |
0996FCD4 MOV BYTE PTR DS:[EDI-1],AL // |
0996FCD7 MOV EAX,EBP // |
0996FCD9 DEC EBP // |
0996FCDA TEST EAX,EAX // |
0996FCDC JNZ SHORT 0996FC82 // /
0996FCDE XOR EAX,EAX
0996FCE0 POP EBP
0996FCE1 POP EDI
0996FCE2 POP ESI
0996FCE3 POP EBX
0996FCE4 RETN 14


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:

004E7EE2 CALL DartXPPr.004E820B // Questo è l'OEP (Per ora…)
004E7EE7 CMP DWORD PTR DS:[52F110],EBX
004E7EED JNZ SHORT DartXPPr.004E7EFB
004E7EEF PUSH DartXPPr.004E8208
004E7EF4 CALL DWORD PTR DS:[4F8CAC]  ;msvcrt.__setusermatherr
004E7EFA POP ECX

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! È 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:

09966D00 MOV DWORD PTR DS:[EDI],EAX // ecco il punto di atterraggio
09966D02 JL SHORT 09966D07
09966D04 JMP SHORT 09966D09
09966D06 JMP F1F8687F

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:

09966CF6 POP EDI
09966CF7 JMP SHORT 09966CFB
09966CF9 INT 20
09966CFB POP EAX
09966CFC JMP SHORT 09966D00
09966CFE PSUBSB MM1,QWORD PTR DS:[ECX+EB037C07] // che cos'è sto schifo?!?
09966D05 ADD EBP,ECX
09966D07 JE SHORT 09966D04

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:

09966CF6 POP EDI
09966CF7 JMP SHORT 09966CFB
09966CF9 INT 20
09966CFB POP EAX
09966CFC JMP SHORT 09966D00
09966CFE <font color=blue>NOP</font>
09966CFF <font color=blue>NOP</font>
09966D00 MOV DWORD PTR DS:[EDI],EAX
09966D02 JL SHORT 09966D07

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:

09966CF6 POP EDI
09966CF7 <font color=blue>POP EAX</font>
09966CF8 <font color=blue>MOV EAX,DWORD PTR SS:[ESP+1C]</font>
09966CFC JMP SHORT 09966D00
09966CFE NOP
09966CFF NOP
09966D00 MOV DWORD PTR DS:[EDI],EAX

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:

004E7E78 PUSH EBP // \
004E7E79 MOV EBP,ESP // |
004E7E7B PUSH -1 // |
004E7E7D PUSH DartXPPr.<font style="background-color:red">004542A8</font> // |
004E7E82 PUSH DartXPPr.<font style="background-color:red">00452AD2</font> // |
004E7E87 MOV EAX,DWORD PTR FS:[0] // |
004E7E8D PUSH EAX // |
004E7E8E MOV DWORD PTR FS:[0],ESP // |
004E7E95 SUB ESP,68 // |
004E7E98 PUSH EBX // |
004E7E99 PUSH ESI // |
004E7E9A PUSH EDI // |
004E7E9B MOV DWORD PTR SS:[EBP-18],ESP // |
004E7E9E XOR EBX,EBX // | Parte copiata
004E7EA0 MOV DWORD PTR SS:[EBP-4],EBX // |
004E7EA3 PUSH 2 // |
004E7EA5 CALL DWORD PTR DS:[<font style="background-color:red">453320</font>] // |
004E7EAB POP ECX // |
004E7EAC OR DWORD PTR DS:[<font style="background-color:red">470D34</font>],FFFFFFFF // |
004E7EB3 OR DWORD PTR DS:[<font style="background-color:red">470D38</font>],FFFFFFFF // |
004E7EBA CALL DWORD PTR DS:[<font style="background-color:red">45331C</font>] // |
004E7EC0 MOV ECX,DWORD PTR DS:[<font style="background-color:red">46A748</font>] // |
004E7EC6 MOV DWORD PTR DS:[EAX],ECX // |
004E7EC8 CALL DWORD PTR DS:[<font style="background-color:red">453318</font>] // |
004E7ECE MOV ECX,DWORD PTR DS:[<font style="background-color:red">46A744</font>] // |
004E7ED4 MOV DWORD PTR DS:[EAX],ECX // |
004E7ED6 MOV EAX,DWORD PTR DS:[<font style="background-color:red">453314</font>] // |
004E7EDB MOV EAX,DWORD PTR DS:[EAX] // |
004E7EDD MOV DWORD PTR DS:[<font style="background-color:red">470D30</font>],EAX // /

004E7EE2 CALL DartXPPr.004E820B // \
004E7EE7 CMP DWORD PTR DS:[52F110],EBX // |
004E7EED JNZ SHORT DartXPPr.004E7EFB // | Parte originale
004E7EEF PUSH DartXPPr.004E8208 // |
004E7EF4 CALL DWORD PTR DS:[<&msvcrt.__setusermat> // /

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:

099CCE2F CALL DWORD PTR DS:[<font style="background-color:green">4F8C9C</font>]
099CDEA7 POP ECX
099CDEA8 OR DWORD PTR DS:[<font style="background-color:green">53581C</font>],FFFFFFFF
099CDEAF OR DWORD PTR DS:[<font style="background-color:green">535820</font>],FFFFFFFF
099CDEB6 CALL DWORD PTR DS:[<font style="background-color:green">4F8CA0</font>]
099CE24B MOV ECX,DWORD PTR DS:[<font style="background-color:green">5356D4</font>]
099CE251 MOV DWORD PTR DS:[EAX],ECX
099CE253 CALL DWORD PTR DS:[<font style="background-color:green">4F8CA4</font>]
099CE259 MOV ECX,DWORD PTR DS:[<font style="background-color:green">5356D0</font>]
099CE25F MOV DWORD PTR DS:[EAX],ECX
099CE261 MOV EAX,DWORD PTR DS:[<font style="background-color:green">4F8CA8</font>]
099CE266 MOV EAX,DWORD PTR DS:[EAX]
099CE268 MOV DWORD PTR DS:[<font style="background-color:green">535818</font>],EAX

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:

004E7EA5 CALL DWORD PTR DS:[<font style="background-color:red">453320</font>]
004E7EAB POP ECX
004E7EAC OR DWORD PTR DS:[<font style="background-color:red">470D34</font>],FFFFFFFF
004E7EB3 OR DWORD PTR DS:[<font style="background-color:red">470D38</font>],FFFFFFFF
004E7EBA CALL DWORD PTR DS:[<font style="background-color:red">45331C</font>]
004E7EC0 MOV ECX,DWORD PTR DS:[<font style="background-color:red">46A748</font>]
004E7EC6 MOV DWORD PTR DS:[EAX],ECX
004E7EC8 CALL DWORD PTR DS:[<font style="background-color:red">453318</font>]
004E7ECE MOV ECX,DWORD PTR DS:[<font style="background-color:red">46A744</font>]
004E7ED4 MOV DWORD PTR DS:[EAX],ECX
004E7ED6 MOV EAX,DWORD PTR DS:[<font style="background-color:red">453314</font>]
004E7EDB MOV EAX,DWORD PTR DS:[EAX]
004E7EDD MOV DWORD PTR DS:[<font style="background-color:red">470D30</font>],EAX

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:

CALL DWORD PTR DS:[4F83B0]

e

CALL DWORD PTR DS:[4F83CC] // (ce ne sono 2)

Metteteci dei bp e avviate il dump così breakkate subito prima che vengano eseguite.
Come vedrete la prima viene chiamata quasi subito:

004E7F9C PUSH EAX
004E7F9D PUSH ESI
004E7F9E PUSH EBX
004E7F9F PUSH EBX
004E7FA0 CALL DWORD PTR DS:[4F83B0] // <---- Eccola qua!
004E7FA6 PUSH EAX
004E7FA7 CALL DartXPPr.004E8586

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:

004E0DA3 CALL DWORD PTR DS:[4F83CC]

E adesso come facciamo a sapere che API deve venire chiamata? Beh possiamo guardare come si comporta il programma "originale" packato, quindi ricaricatelo in olly e portatevi fino all'OEP.
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ì:

004E0D90 SUB ESP,94
004E0D96 LEA EAX,DWORD PTR SS:[ESP]
004E0D9A MOV DWORD PTR SS:[ESP],94
004E0DA2 PUSH EAX
004E0DA3 CALL DWORD PTR DS:[4F83CC]
004E0DA9 MOV ECX,DWORD PTR SS:[ESP+10]
004E0DAD XOR EAX,EAX
004E0DAF CMP ECX,2
004E0DB2 SETE AL
004E0DB5 ADD ESP,94
004E0DBB RETN

Adesso è così:

004E0D90 SUB ESP,94
004E0D96 LEA EAX,DWORD PTR SS:[ESP]
004E0D9A MOV DWORD PTR SS:[ESP],94
004E0DA2 MOV EAX,1
004E0DA7 NOP
004E0DA8 NOP
004E0DA9 MOV ECX,DWORD PTR SS:[ESP+10]
004E0DAD XOR EAX,EAX
004E0DAF CMP ECX,2
004E0DB2 SETE AL
004E0DB5 ADD ESP,94
004E0DBB RETN

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!

E per finire un'interrogazione: chi sa dirmi quali sono i punti non perfetti?

SatUrN: "L'entrata di un'API non è stata risolta, ma è stato aggiustato il codice per permettere il funzionamento del programma."

Bravo e poi?

SatUrN: "Quando abbiamo copiato la struttura iniziale di Winamp non abbiamo aggiustato tutti i riferimenti (solo 9 su 11), abbiamo trascurato l'installazione del SEH lasciando l'indirizzo di Winamp."

Perfetto, promosso!

Non mi sono dato la pena di aggiustare questi 2 ultimi punti perché il prg funzia lo stesso e non mi ha dato problemi.
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

Che dire? Spero di essere stato abbastanza chiaro nelle spiegazioni visto che ho scritto tutto in fretta e furia e che soprattutto prendiate spunto dal metodo utilizzato. Ricordatevi di non usare questo tute come una ricetta di cucina, altrimenti la prossima volta che avrete a che fare con SVKP vi troverete comunque in difficoltà! Cercate soprattutto di imparare a usare i memory bp, che quando si ha a che fare con codici automodificanti sono molto importanti. Naturalmente se avete commenti o suggerimenti non esitate a contattarmi. Se ci sono lamentele contattate pure Quequero! Hihihihihi

Per finire passiamo ai saluti: Il primo saluto va alla UIC e a Captain Quequero. Gli altri saluti vanno a Zero_G che ha segnalato il prog e che è sempre pronto ad aiutare tutti. Ai moderatori della UIC in particolare a LittleLuk e Andreageddon. Per finire un saluto anche a Zara, LonelyWolf e Faina.

Ciauz


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.