SVKP 1.3x
(Manual Unpacking)

Data

by "SatUrN"

 

25/12/2004

UIC's Home Page

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]
oppure P.M. a SatUrN sul forum UIC

....

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:


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


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 
NOP
09966CFF  NOP
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 
POP EAX
09966CF8  MOV EAX,DWORD PTR SS:[ESP+1C]
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’opzioneRebuild 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.004542A8                     |
004E7E82  PUSH DartXPPr.00452AD2                     |
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:[453320]                 |
004E7EAB  POP ECX                                    |
004E7EAC  OR DWORD PTR DS:[470D34],FFFFFFFF          |
004E7EB3  OR DWORD PTR DS:[470D38],FFFFFFFF          |
004E7EBA  CALL DWORD PTR DS:[45331C]                 |
004E7EC0  MOV ECX,DWORD PTR DS:[46A748]              |
004E7EC6  MOV DWORD PTR DS:[EAX],ECX                 |
004E7EC8  CALL DWORD PTR DS:[453318]                 |
004E7ECE  MOV ECX,DWORD PTR DS:[46A744]              |
004E7ED4  MOV DWORD PTR DS:[EAX],ECX                 |
004E7ED6  MOV EAX,DWORD PTR DS:[453314]              |
004E7EDB  MOV EAX,DWORD PTR DS:[EAX]                 |
004E7EDD  MOV DWORD PTR DS:[470D30],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:[4F8C9C]
099CDEA7  POP ECX
099CDEA8  OR DWORD PTR DS:[53581C],FFFFFFFF
099CDEAF  OR DWORD PTR DS:[535820],FFFFFFFF
099CDEB6  CALL DWORD PTR DS:[4F8CA0]
099CE24B  MOV ECX,DWORD PTR DS:[5356D4]
099CE251  MOV DWORD PTR DS:[EAX],ECX
099CE253  CALL DWORD PTR DS:[4F8CA4]
099CE259  MOV ECX,DWORD PTR DS:[5356D0]
099CE25F  MOV DWORD PTR DS:[EAX],ECX
099CE261  MOV EAX,DWORD PTR DS:[4F8CA8]
099CE266  MOV EAX,DWORD PTR DS:[EAX]
099CE268  MOV DWORD PTR DS:[535818],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:[453320]
004E7EAB  POP ECX
004E7EAC  OR DWORD PTR DS:[470D34],FFFFFFFF
004E7EB3  OR DWORD PTR DS:[470D38],FFFFFFFF
004E7EBA  CALL DWORD PTR DS:[45331C]
004E7EC0  MOV ECX,DWORD PTR DS:[46A748]
004E7EC6  MOV DWORD PTR DS:[EAX],ECX
004E7EC8  CALL DWORD PTR DS:[453318]
004E7ECE  MOV ECX,DWORD PTR DS:[46A744]
004E7ED4  MOV DWORD PTR DS:[EAX],ECX
004E7ED6  MOV EAX,DWORD PTR DS:[453314]
004E7EDB  MOV EAX,DWORD PTR DS:[EAX]
004E7EDD  MOV DWORD PTR DS:[470D30],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

Vorrei ricordare che il software va comprato e non rubato, dovete registrare il vostro prodotto dopo il periodo di valutazione o anche prima (non con i seriali di astalavista lameri!)

Non mi ritengo responsabile per eventuali anni causati al vostro computer determinati dall'uso improprio di questo tutorial. Questo documento è stato scritto per far diminuire le ore di sonno al sottoscritto e per invogliare il consumatore a registrare legalmente i propri programmi, infatti tale documento aiuta a comprendere lo sforzo immane che ogni singolo programmatore di packers ha dovuto portare avanti per fornire ai programmatori ignoranti una protezione decente.

Noi reversiamo al solo scopo informativo e di miglioramento del linguaggio Assembly.