▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
█                                                                                      █
▓                         [x] ringZ3r0  Proudly Presents [x]                           ▓
▓                                                                                      ▓
▒            ┌──────────────────────────────────────────────────────────┌              ▒
▒                                                                                      ▒
                 │ PE-Packers/Crypters : Manual unpacking - parte 2 │

                                       Kill3xx
   
                                   04 Agosto,1999

--==[  PREMESSA  ]==--------------------------------------------------------------------

LE INFORMAZIONI CHE TROVATE ALL'INTERNO DI QUESTO FILE SONO PER PURO SCOPO DIDATTICO.
L'AUTORE NON INCORAGGIA CHI VOLESSE UTILIZZARLE PER SCOPI ILLEGALI.

--==[ DIFFICOLTA' ]==-------------------------------------------------------------------

scala : *=Novizio, **=Apprendista, ***=Esperto, ****=Guru
target: ***

--==[ TOOLS USATI ]==-------------------------------------------------------------------
 
* SoftIce 3.25
* PROCDUMP 1.5
* ULTRAEDIT 6.10
* MASM 6.14

--==[ LETTERATURA ]==-------------------------------------------------------------------

"Peering Inside the PE: A Tour of the Win32 Portable Executable File Format" 
(M. Pietrek),  Microsoft Systems Journal 3/1994

"The Portable Executable File Format from Top to Bottom" (Randy Kath), MSDN

"The PE file format" (B. Luevelsmeyer), reperibile sulla rete

"Windows 95 Programming Secrets" (M. Pietrek), IDG BOOKS, 1995

"Window Advanced Programming" (J. Ritcher), Microsoft Press, 1997

"Win32 Exception handling for assembler programmers" (Jeremy Gordon), 1998,
reperibile sulla rete

"Intel Architecture Software DeveloperÆs Manual Volume 3: System Programming Guide",1997,
reperibile sulla rete

--==[ INTRODUZIONE ]==------------------------------------------------------------------

yeah sono in vacanzaaa ;))

Prima  di iniziare voglio pero' essere esplicito con voi: 
non ho nessuna intenzione di replicare il manuale di Procdump per cui mi limitero' 
a descrivere i comandi e le opzioni piu' importanti e tralasciero' cose come 
descrivere il process monitor, o il significato di ciascun campo/listview/dialog...
credo che se state leggendo questo tutorial siate gia' piu' che autosufficienti per 
queste cose ;)


--==[ PROCDUMP INTERNALS ]==------------------------------------------------------------

Procdump puo' essere scomposto in vari moduli / modalita' operative:
process monitor, dumper, pe editor, pe rebuilder, unpacker, bhrama server.
Come vi ho gia' anticipato analizzeremo solamente l'unpacker e il bhrama server, questo
xche' ritengo che ormai sappiate come utilizzare il dumper, l'editor, il process 
monitor, ecc. Quello che mi preme piuttosto e' chiarire il contesto in cui vanno 
utilizzate le varie opzioni di unpacking e soprattutto, il xche' di si debba utilizzare
l'una invece dell'altra, ragionando anche sull'implementatazione stessa di ProcDump.
Innanzitutto va detto che Procdump opera x il 90% del tempo a ring3 questo xche' le
fondamenta su cui poggia sono , se escludiamo l'opzione del tracer a ring0, l'API di 
debug: sia le funzioni di dumping che l'engine principale sono realizzati servendosi 
della ToolHelp32/PSPAPI o di funzioni come ReadProcessMemory, SetThreadContext, 
WaitDebugEvent,ecc.. Le implicazioni di questo modo di operare sono molto importanti 
visto che ,come vedremo, determinano i limiti stessi di Procdump.
Ma procediamo con ordine e analizziamo la modalita' piu' importante, l'unpacker:
in questa modalita' Procdump opera come un vero e proprio debugger a ring3.. il processo
viene creato con il flag DEBUG_PROCESS.. quindi viene attivato loop WaitForDebugEvent
ContinueDebugEvent.. questo permette di trappare tutte le exception che il processo
child genera prima che vengano gestite da eventuali filtri di eccezione / terminazione 
locali. Immagino che quelli piu' attenti fra di voi abbiano gia' collegato quest'ultima
affermazione con l'opzione Ignore Faults: esatto .. se si verifica un'eccezzione in un
processo sottoposto a debug, la prima azione che Windows compie e' notificare il debugger
segnalando un debug event... e' responsabilita' del debugger decidere se gestire 
quest'eccezzione, nota come first chance, o restituire immediatamente il controllo 
all'applicazione. Se "Ignore Faults" e' ON, Procdump trappa solo le eccezzioni di tipo
EXCEPTION_BREAKPOINT (Int03) che sono state generate in seguito ai comandi bp* dello
script attivo. Questo avviene verificando se l'EIP dell'eccezzione corrisponde 
all'indirizzo del breakpoint attivo. Ma quando e' necessario attivare quest'opzione ? 
semplice quando il loader utilizza meccanismi come la SEH per traferire il controllo 
all'interno del codice,o per verificare la presenza di sIce (exp. classico l'interfaccia
int03 "BHCK") o in generale di debuggers / tracers. Se non lasciassimo al programma la
possibilita' di gestire queste situazioni attraverso i suoi exception filters locali 
quest'ultimo con ogni probabilita' andrebbe incontro a morte prematura dato che Procdump
non saprebbe certo come gestirli.
Un'altra importante conseguenza di utilizzare la debug API x l'unpacker engine e' che
Procdump necessita di un cosidetto "predump" per poter ricostruire la IT...mi spiego 
meglio : in Windows 9x, quando ad un processo e' attaccato un debugger, se utilizziamo
GetProcAddress per ritrovare l'entry point di una funzione da una DLL shared di sistema,
al posto di ottenere l'indirizzo effettivo otteniamo invece quello di uno stub creato
da WinZoz in un'area shared (>0x80000000). La ragione di questo assurdo comportamento 
dipende dal fatto che alla M$ hanno pensato bene che essendo kernel32,user32,ecc. 
condivisi x tutti processi non era carino che un debugger a r3 potesse steppare nel 
codice o cmq pokicchiarci (che bel termine vero? ;). Dato che il 99% dei packers/cryters
utilizza GetProcAddress quando risolve le imports e' chiaro che se l'IT rebuiler utilizza
la IAT durante l'unpacking senza opportuni accorgimenti non sara' in grado di ricostuire 
una IT valida (sull'engine Phoenix ne parleramo piu' in dettaglio tra un po'). Il predump
puo' poi essere statico (= "external predump") o dinamico ("predump after X"):
- per statico si intende che dobbiamo fornire al rebilder un dump che contenga una IAT 
corretta, anche se gia' fixata, in modo che questo possa attraversare i vari 
image_thunk_data e ricostruire gli array first_thunk... sostanzialmente e' lo stesso
modo di operare di makePE. 
- per dinamico invece significa che procdump lancera' il programmma in modalita'
non debug e attendera' X msec prima di sospendere il thread principale ed eseguire
lo scan della IAT: X ovviamente deve essere tarato in modo che nel momento in cui
si sospende il thread la IT o la IAT siano 1) raggiungibili 2) non trashate..
nel caso X == 0 Procdump attendera' che siamo noi a confermare l'inizio del rebuild.
Il maggior problema  di questa implementazione e' che durante la fase di predump non 
e' possibile utilizzare gli scripts e quindi neutralizzare quei packers/ crypters che 
contengano codice anti-rebuild (inserimento di stubs,ecc.), la qual cosa, come vedremo
nel caso clinico che vi sottoporro' ;) [petite 2.1] , si rivela molto limitativa.
Le opzioni "EIP confirmation" e "Multiple layer confirmation" servono invece ad offrire
un'ulterirore occasione x decidere, una volta entrati in STEP mode, quale EIP utilizzare 
come EP ,ma IMHO sono ormai obsoleti considerato che ora il linguaggio script disponde 
dei comandi OBJ e EIP. Ultima opzione che si presenta nel group box dedicato all'unpacker
e' "Trace API" : se selezionamo quest'opzione Procdump utilizzera' la versione a Ring0 
del tracer (VXDBODY.VXD x w9x e VXDBODY.KMD x NT), tracer che nelle intenzioni dovrebbe 
consentire di neutralizzare i metodi ADT piu' classici (EFLAGS->TF, int1 / int3 traps,
ecc.). Ho utilizzato il condizionale non a caso: il fatto e' che in realta' il codice 
non e' esattamente stabile e/o completo, il che purtroppo ne rende l'impiego 
sostanzialmente inutile (senza contare che i crash sono praticamente garantiti). 

[ nota a margine : Procdump maschera la sua presenza quale debugger attraverso 
l'azzeramento del campo DebugContext nel TIB (Thread Information Block), il classico 
FS:[20h] per farla breve. Benche' questo sistema funzioni per la maggior parte dei 
crypters classici,non e' che un pagliativo... purtroppo e' la natura stessa di Procdump
quale debugger a r3 ad esporlo pesantemente ai detectors (FindWindow,IsDebuggerPresent,
pushfd pop eax test ah,01, parent PDB check,ecc.) quindi tenenete conto x evitare 
sorprese.]

Passiamo ora alle opzioni del rebuiler: 
le opzioni "Recompute ObjectSize" e "Optimize PE structure" mi paiono chiare e sono
del resto spiegate esaurientemente nel "manuale"... qualke parolina in piu' merita 
"Check Header Sections": attivando questa opzione Procdump verifica che le pagine 
presenti nel range occupato dall'immagine (cosi' come riportato nella section table) 
siano tutte presenti e leggibili.. immagino vi starete chiedendo: "xche' mai non 
dovrebbero esserlo?" dunque quest'opzione e'nata per contrastare quei crypter (mi 
risulta lo faccesse solo la prima ver del crypter dei PC e PEShield.. but who know..)
che giocando sul fatto che ProcDump utilizza ReadProcessMemory, modificavano il PE
alterando SizeOfImage o la VSize delle sections in modo che fosse maggiore o minore 
dello spazio fisicamente okkupato, cosa che si traduceva in una lettura errata di 
ReadProcessMemory nel caso in cui di quelle pagine non fosse ancora stato fatto il 
commit o non fossero proprio allocate. Dato che questo trick non e' decisamente gradito
a WinNT :) per via del differente funzionamento del VMM (vi ricordate ne abbiamo gia' 
parlato...), e' difficile che dobbiate incontrare ancora appz che ne fanno uso. 
L'opzione "Rebuild header" e' stata introdotta solo di recente: lo scopo e' di forzare 
Procdump a ripristinare i campi vitali del PE header che potrebbero essere stati 
cancellati (NumberOfSection,SizeOfHeaders,ecc) invece di limitarsi ad un dump passivo 
dell'header.. ovviamente quest'operazione  si basa su criteri euristici, assumendo 
valori come standard in ogni PE, analizzando la section table e la DataDirectory (in 
verita' non ho ancora analizzato bene il codice relativo, ma cmq non ho trovato chiamate
a VirtualQueryEx che potrebbero far pensare ad un'analisi dell'address space nel
tentativo di ricostuire il layout dell'image...) x cui non e' affatto scontato che 
l'header cosi' ricostruito sia effettivamente corretto... controllatelo cmq.
Ok, veniamo adesso alla parte piu' importante: l'IT rebuilder (Phoenix). Il significato 
delle prime due opzioni mi pare auto-eplicativo.. passiamo oltre : come gia' saprete i
packers/crypters piu' recenti ridirigono DataDir->IT_RVA xche' punti alla propria 
mini-IT in modo da importare staticamente le funzioni di cui necessitano e gestendo 
poi, con un proprio imports loader, la IT table originaria.. sappiamo anche che si 
possono verificare due ipotesi:

1) la IT (intesa come comprensiva di image_imports_descriptors,ecc.) dopo l'unpack e'
ancora presente in memoria anche se non "raggiungibile" attraverso il PEHeader
2) la IT originale e'compattata in una struttura gestita internamene dal crypter o
cmq copiata in un buffer separato e distrutta una volta fixata la IAT

in entrambi i casi pero' una cosa e' sicura (almeno fin'ora ;) la IAT non e' stata
rilocata e si trova nella posizione originale.. questo xche', in caso contrario, sarebbe
necessario rilocare tutte le chiamate alle func importate presenti nel codice dell'appz.
Ancora, cosa ci impedisce di utilizzare la IT del caso 1) ? semplice i vari FirstThunk
sono stati fixati e non contengono piu' gli rva x gli image_import_by_name e/o ordinals.
Bene l'opzione "Rebuild import table" cerca di porre rimedio al caso 1).. come?
semplice Procdump tenta euristicamente di trovare la IAT scannando il codice alla ricerca
di un jump [dword] (opcode FF25) ,quindi legge dword.. se questa contiene un address 
valido x uno di moduli caricati (usa ToolHelp32/PSAPI) lo confronta in successione
con quelli restituiti da GetProcAddress x ogni funzione di ogni modulo... se corrisponde
sa di aver trovato un array FirstThunk.. quindi percorre i vari thunks a ritroso 
compiendo le stesse operazioni e costruendo una mappa interna FirsThunk_rva:Modulo:API
che poi utilizza x ricostuire gli elementi di ogni FirsThunk->image_thunk_data.. 
Procdump provvedera' anche ad aggiornare la DataDirectory... semplice no? =)

[ nota a margine: l'uso di GetProcAddress e' stato introdotto nella v. 1.5 (prima era
utilizzato uno scan Modulo->ET->AddressOfFunctions) ed e' simile a quello utilizzato da 
Virogen/PC e Titti/Blizzard nel loro PERebuilder.. date un'occhiata ai sorgenti di questo..
e' una buona lettura.. ( btw io avrei suggerito un'altro sistema con VirtualQueryEx.. se 
avete visto i miei srcs di PESpy sapete cosa voglio dire) ]

ovviamente il rebuild puo' funzionare solo se gli image_import_descriptors non sono stati 
trashati. Nel caso in cui non sia cosi', come nel 2), abbiamo la possibilita' di 
specificare un "Full Import rebuild".. ovvero ProcDump utilizzera' lo stesso procedimento
ma questa volta ricreara' anche gli image_import_descriptors,ecc. in una IT nuova che sara'
aggiunta in fondo all'exe dumpato.

Uhmm.. se siete arrivati a leggere fino qui' (lo so' avete pazienza da vendere ;) vi 
starete sicuramente chiedendo a che pro questa lunga parentesi tecnofila su come
e' implementato Procdump... dunque... nel 90% dei casi a nulla =) visto che potete anche
limitarvi ad utilizzare script / plugin che altri hanno scritto.. tuttavia nell'altro 10% 
dei casi potreste incontrare un crypter non ancora supportato da Procdump , che, nemmeno
a farlo apposta, contiene codice anti-trace/dump.. beh in questo 10% credo vi torni utile
conoscere come funziona Procdump e quali punti deboli possono esser stati sfruttati.


--==[ PROCDUMP : SCRIPTS ]==------------------------------------------------------------

Gli script sono senz'altro una delle caratteristiche piu' importanti di Procdump. Senza 
di essi Procdump non potrebbe gestire l'unpacking automatico x tutta la moltitudine di 
packers/crypters che supporta. Ma qual'e' lo scopo degli script e sopratutto il loro 
funzionamento? lo scopo e' semplice: guidare Procudump attraverso il codice del loader 
fino a fargli raggiungere indenne l'OEP.. cio' significa' gestire secondo necessita' 
eventuale codice anti-trace/dump, encryption, layers, e quant'altro possa impedire a 
Procdump di fare il suo sporco lavoro =)
Il funzionamento com'e' ormai assodato si basa sulla DebugApi.. e piu' precisamente
sull'uso di R/W*ProcessMemory e sopratutto Set/GetThreadContext. In pratica ogni 
istruzione BPxx si traduce in un int3 (questo spiega l'avvertenza di settare I3HERE = OFF
in sICE) inserito nel codice del appz... questo che genera un'eccezzione, che viene 
trappata dal loop WaitDebugEvent che decodifica la prossima istruzione dello script, 
la quale a sua volta puo' tradursi in un'alterazione del codice o del context del thread
(MOVE,REPL) oppure nell'impostazione di un'altro breakpoint.. cosi' finche' non si entra
in STEP mode, al che' si passa definitivamente il controllo al tracer e da questo al 
dumper. Per esaminare le potenzialita' (e i limiti) ho deciso di utilizzare come target
il classico notepad.exe compresso con Petite 2.1. 
Iniziamo coll'esaminare il codice del loader di Petite 2.1 nelle sue parti essenziali 
(i dead listings completi li trovate in allegato):

B800C04000          MOV     EAX,0040C000              ; hardcoded entrypoint EIP 
6A00                PUSH    00                        
6812624000          PUSH    00406212                  ; use SEH to transfer control 
64FF3500000000      PUSH    DWORD PTR FS:[00000000]   ; to the next layer (2)
64892500000000      MOV     FS:[00000000],ESP
 
vi ricordate che tutorial precedente  vi dicevo che l'installazione di un exception frame
e' da considerarsi sospetta.. eccone un riprova... petite 2.1 utilizza proprio la SEH per 
trasferire il controllo al layer successivo una volta che tutta l'immagine e' stata 
decompressa. La cosa avviene piu' o meno in questo modo: Petite decomprime l'immagine per 
blocco / sezioni successivi, compresi il blocco con i layer successivi.. quindi esegue 
un'ulteriore invocazione della funzione di unpacking ma con parametri nulli in modo da 
generare una violazione di accesso... quando questa si verifica l'esecuzione e' trasferita
da WinZoz all'exception handler, EIP = 0x00406212 in questo caso, dove al momento 
dell'eccezzione si trova la seguente call:

E84F000000          CALL    00406266                  ; xHandler gateway

che a sua volta trasferisce il controllo al terzo layer quello in cui vengono gestite
imports, base relocations, TLS, ecc. ok ora se volessimo scrivere la prima parte dello
script ci troveremmo di fronte ad alcuni piccoli problemi:

1) l'address 00406212 non e' caricato in alcun registro e il linguaggio script di 
   Procdump non offre la possibilita di leggere un address dal codice/stack
2) l'address dell'handler e' dipendente dal target quindi BPX non e' utilizzabile
3) il codice a quell'indirizzo non e' in chiaro sin dal caricamento ma viene decompresso
   dal primo layer, quindi se mettiamo un BP prima che cio' avvenga questo sara' 
   sovrascritto..
   
problemi insormontabili? naaa.. ci vuole solo quel po' di malizia nel pensare che,
se anche il codice non prevede una determina azione, possiamo sempre pensarci noi ;) 
inserendo il codice seguente possimo caricare in eax l'address del primo handler nella
exception chain:

mov  eax,fs:[00]
mov  eax,[eax+4]

tradotto in script:

; cerchiamo il pattern corrispondente al codice da sovrascrivere, ovvero:
; 85C0                TEST    EAX,EAX
; 0F8420FFFFFF        JZ      0040C0CE

L1=LOOK 85,C0,0F,84,20,FF,FF,FF 

; rimpiazziamolo con il nostro

L2=REPL 67,64,A1,00,00,8B,40,04

; e quindi mettimo un breakpoint dopo 3 esecuzioni di fnDecrypt 
; ovvero quando in genere viene decompressa la "call xHandler"

L3=ADD 8
L4=BPC 3

; ed infine un BP all'address contenuto in EAX = xHandler

L5=BPR EAX

et voila'.. a questo punto siamo in grado far raggiungere a Procdump il layer2...
bastera' quindi :

L6=WALK

e ci troveremo all'inizio del layer3... good! 
Ora quello che ci preme e' impedire che il loader nel risolvere le imports crei
i suoi stubs: osservando il codice ci rendiamo subito conto che il modo migliore
e' patchare questo snippet: 

FF4C2428            DEC     DWORD PTR [ESP+28]   ; stub randomizer
7D25                JGE     00406467
8B542424            MOV     EDX,[ESP+24]

L7=OBJR                  
L8=LOOK 7D,25,8B
L9=REPL EB

perfetto ora il codice dovrebbe sempre saltare la creazione degli stubs. Se osservate
i dead listings noterete come Petite 2.1 si premuri anche di cancellare i nomi delle 
funzioni importate (quelli dei moduli sono gia' stati rimossi e copiati in una table 
saparata dal packer) e i fields FirstThunk x ogni image_import_descritor.. e' evidente
che i programmatori hanno voluto cautelarsi contro Procdump e il suo import rebuilder.
Poco sotto il codice che gestisce le imports c'e' quello x l'handling della base 
relocation.. tutto assolutamente familiare se avete letto i precedenti tutorial =) , 
va solo notato che anche qui troviamo un semplice stratagemma x complicare il rebuild: 
ogni record della relocation directory e' wipato dopo l'uso.
So fa so good...  ora quello che ci interessa e' raggiungere il quarto layer:
anche qui pero' abbiamo lo stesso problema del secondo layer2.. il codice presente
nel layer4 e' decrittato dal seguente codice:

3119                XOR     [ECX],EBX          ; use crc as decryption key 
315904              XOR     [ECX+04],EBX       ; for the 4th layer's code
315908              XOR     [ECX+08],EBX
31590C              XOR     [ECX+0C],EBX
59                  POP     ECX
315C1101            XOR     [EDX+ECX+01],EBX   ; and "goto layer4" call

vabbeh poko male.. il nostro breakpoint precedente ci assicura che il codice sia
gia' decrittato nel momento in cui Procdump esegue la line L9.. possiamo allora
semplicemente impostare un'altro BP e precisamente su questo snippet:

33C0                XOR     EAX,EAX
B960030000          MOV     ECX,00000360           ; sizeof loader layers (2-3)

LA=LOOK FD,33,C0,B9
LB=ADD 8
LC=BP

e quindi eseguire la call che ci porta al layer4:

E8915B0000          CALL    0040C102            

LD=WALK

ora non resta che ottenere l'OEP e passare il controllo al tracer... che ragionando
sul codice di petite:

61                  POPAD
669D                POPF                           ; restore register & flags
83C40C              ADD     ESP,0C                 ; stack cleanup
E9F04EFFFF          JMP     00401000               ; jmp to OEP

ci porta a scrivere le seguenti linee dello script:

LE=OBJR
LF=LOOK 83,C4,0C,E9
L10=ADD 3
L11=BP
L12=WALK                                           ; esegui jmp EOP
L13=EIP                                            ; assumi l'EIP corrente (dopo il jmp)
L14=STEP                                           ; come entry point x il dump

non ci resta che impostare le options,aggiungerlo nel file script.ini e il nostro primo
script puo' dirsi completo:

Recompute object size = ON             
Optimize PE structure = ON
Full Import rebuild   = ON
Predump After         = ON = 0ms
Ignore Faults         = ON

tutto assolutamente lineare non vi sembra ? =)
immagino starete esclamando "yeah, il mio primo script.. proviamolo subito..."... ok! 
lanciamo Procdump... target il nostro notepad.exe, click su UNPACK, selezioniamo il 
nostro script, confermiamo il predump... lo script si esegue perfettamente... good...
ci appare la dialog di save.. very good... salviamo ed esaminiamo velocemente il file 
nel PE editor: EP = 1000, ecc...ottimo.. lo lanciamo baldanzosi e...... si pianta!! 
"o kill3xx chettufai?" tranquilli =) era preventivato. Siete stati cosi' fortunati che
il vostro primo script, apparentemente perfetto,e' anche un esempio dei limiti di 
Procdump... che culo vero? ;). La ragione e' semplice e gia'la conoscete: Procdump 
ricostruisce la IT in fase di predump ma come sappiamo in fase di predump gli script 
non sono attivi, ne consegue che, se anche il nostro script preveda la neutralizzazione
degli stubs, in realta' questo avviene quando oramai Procdump ha gia' ricostruito 
internamente la IT. Soluzioni ? nessuna, o meglio, nessuna che utilizzi gli script. 
Potremmo usare sIce durante il predump e fixare a mano il "jg" nel  codice del loader 
ma non mi pare una soluzione elegante. =)


--==[ PROCDUMP : BHRAMA SERVER ]==------------------------------------------------------

Dalla versione .1.4, data la sempre maggiore ostilita' verso Procdump dei crypters e
packers, e visti i limiti degli script, Procdump mette a disposizione un nuovo modo di 
operare il Bhrama Server e i plugin/client. Un plugin altro non e' che un loader in cui
gestiamo con nostro codice quello che in Procdump avremmo realizzato con uno script, 
ovvero:
 1) eliminare eventuali tricks anti-dump (i.e x petite2.1 gli stubs)
 2) attendere che il codice si totalmente decrittato
 3) raggiungere l'OEP e comunicarlo a Prodump in modo che lo utilizzi come EP x il 
rebuild. Una volta che abbiamo raggiunto l'OEP possiamo sospendere il main thread del 
programma target e comunicare con Procdump attraverso il Bhrama server: questo e' un 
Dialog che funge da server esponendo un protocollo di IPC ben definito e basato su 
WM_COPYDATA. I servizi che ci mette a disposizione il Bhrama server sono gli stessi che
potremmo utilizzare dal Process Monitor di Procdump.. ovvero FULL e PARTIAL DUMP.
Le strutture utilizzate x i vari service sono ben ducumentate nel file Bhrama.txt e 
nella directory omonima trovate anche due esempi (w32asm e c) dello skeletro di un 
plugin. Detto questo passo ad illustrarvi l'idea alla base del plugin x Petite 2.1
che ho realizzato. L'obiettivo e' ovvio: neutralizzare gli stubs: il sistema un po meno
visto che l'esecuzione del loader e' multilayer e il passaggio fra questi avviene 
attraverso la SEH. Qualcuno potrebbe essere tentato di usare la DebugAPI visto che le 
exception vengono notificate prima al debugger che all'appz.. ma in tal caso ci 
ritroveremmo con il probelma degli stubs che crea WinZoz. L'intuizione che ho avuto e' 
la seguente: se sostituiamo l'indirizzo dell'exception handler originale con un nostro
handler, il cui codice e' stato iniettato nell'address space del processo, saremmo noi
ad avere il controllo quando si verifichera' l'eccezzione, e di consegueza avremmo 
accesso ai layer2 e al layer3.. da questo punto in poi possiamo utilizzare un mini 
tracer attraverso l'installazione di un final exception handler (che vi ricordo e' 
process wide.. SetUnhandledExceptionFilter) e sfuttando l'accesso al CONTEXT del thread
settare i seguenti bp:
- int3 x raggiungere il layer3
- HW bp sul "jg" dello stub randomizer
- HW bp sulla "call _layer4"
- EFlags.TF in modo eseguire la call _layer4 (equivalente al WALK di Procdump)
gli HW breakpoint sono realizzati utilizzando la copia locale dei debug registers che 
viene mantenuta x ogni Thread Context.
Quando i BP genereranno altrettante exception, queste, non essendo gestite da Petite,
dovranno necessariamente essere notificate al nostro handler e noi , in tal modo, 
avremmo il totale controllo sull'esecuzione/codice del loader di Petite. Ancora: quando
ci troveremo nel layer4 calcoleremo l'EIP dell'OEP e lo notificheremo alla nostra IPC 
server window che provvedera' a sospendere il main thread del programma e ad invocare 
il service FULL DUMP del Bhrama server. Per quel che riguarda l'iniezione del codice ho
optato x modificare il codice dell'EP del target inserendovi uno stub x mappare un memory
mapped. Questo MMF contiene tutto il codice da iniettare, compreso quello che si occupa 
ripristinare il codice originale e riprende l'esecuzione di questo. Non mi dilungo oltre
a commentare ogni singola linea xche' ci vorrebbe troppo spazio e questo tute e' gia 
lungo di per se'... voglio pero' sottolinere come la combinazione di exceptions e 
manipolazione del context (specialmente EIP, ESP, Dr0..3, Dr7) sia davvero uno strumento
flessibile e potente (eheh probabilmente oltre la stessa volonta' dell M$ ;): la potete
utilizzare x andare a r0 (in w9x),x anti-debug,x un tracer, SMC code,ecc.. 
Il resto del codice (che troverete in allegato) riguarda il setup del MMF e codice di 
contorno che credo sia autoesplicativo.


--==[ NOTE FINALI]==--------------------------------------------------------------------

Bene siamo finalmente giunti alla fine: spero che questi tutorial sul PE abbiano 
contribuito a farvi interessare a questa intrigante materia. Vi annuncio fin'ora che
non credo che ne scrivero' ancora, almeno finche' non ci sara' qualkosa di nuovo sotto 
il sole. Prima di congedarmi pero' i soliti saluti di rito =) :

Along3x,Alor,Deamon (dove minkia sei finito ??? =),Genius,GuyBrush,Little-John,Insanity,
Kry0,+Malattia,Neural_Noise,MoonShadow,Pe-WoW,Pusillus,T3X,Quequero,xAONINO,Yan-orel,
War-lock e a tutti quelli che frequentano #crack-it e chi mi sono dimenticato.. 
tnx *.* =)

byz Kill3xx

Allegati