Oppure

Loading
13/09/16 18:20
Driverfury
Premessa: se questa non è la sezione adatta, chiedo ai moderatori gentilmente di spostare questo thread.

Salve a tutti,

da poco sto studiando il formato PE (Portable Executable) che, come sapete, è il formato standard di Windows per gli eseguibili e le DLL.

Ho scritto un semplice programmino Hello World in C e l'ho aperto con CFF Explorer per vedere i vari header, le sezioni ecc...

Ho notato che nell'Optional Header c'è anche l'Entry Point che è, appunto, l'indirizzo della prima istruzione che sarà eseguita del programma.

Provo a debuggare il programmino Hello World (che si chiama prova.exe) con OllyDBG e noto, con mia grande sorpresa, che prima dell'istruzione dell'entry point vengono eseguite tantissime altre istruzioni, la prima in assoluto è quella del modulo ntdll, dopodichè si passa al modulo KERNEL32 ed infine al modulo principale del mio programma (cioè modulo prova). Tra l'altro vengono eseguite varie istruzioni nel modulo prova prima di passare all'entry point.

Qualcuno sa darmi dei chiarimenti a riguardo?

Perché ho bisogno di chiarimenti?

In pratica, ho provato a scrivere un programma (in C) che:
1. prende in input il mio programma Hello World (prova.exe) e lo carica in memoria
2. inietta un codice binario puro (chiamiamolo codice1.bin) in un code cave alla fine della text section di prova.exe
3. setta l'Entry Point all'indirizzo della prima istruzione del codice iniettato
4. aumenta la virtual size della text section (perché ora c'è da considerare anche il codice iniettato)
5. cripta la text section tranne il codice iniettato

Cosa fa il codice1.bin?
1. decripta la text section
2. salta al vecchio entry point con una JMP [indirizzo vecchio entry point]

In pratica è una sorta di scantime crypter. Il problema, però, è proprio il seguente (che è il motivo per cui ho scritto questo thread):
la prima istruzione ad essere eseguita non è quella del codice iniettato, ma devono essere eseguite prima altre istruzioni della text section che però sono criptate e quindi non riconosciute come istruzioni.

Chiedo aiuto a voi utenti più esperti.
Ultima modifica effettuata da Driverfury 14/09/16 0:01
aaa
15/09/16 3:42
pierotofy
Mm, per sapere per certo, faciliterebbe molto se allegassi un pò di codice sorgente (con istruzioni su come li compili) e i risultanti binari.

Probabilmente non stai impostando correttamente l'optional header.

Ma perchè cambiare l'entry point? Potresti semplicemente scambiare l'ordine dei due codici...

Invece di avere la sezione .text organizzata come |codice cryptato|codice1.bin| metti |codice1.bin|codice cryptato|.



Il mio blog: piero.dev
15/09/16 11:24
Driverfury
Postato originariamente da pierotofy:

Mm, per sapere per certo, faciliterebbe molto se allegassi un pò di codice sorgente (con istruzioni su come li compili) e i risultanti binari.

Probabilmente non stai impostando correttamente l'optional header.

Ma perchè cambiare l'entry point? Potresti semplicemente scambiare l'ordine dei due codici...

Invece di avere la sezione .text organizzata come |codice cryptato|codice1.bin| metti |codice1.bin|codice cryptato|.





Forse non mi sono spiegato bene.

Il programma funziona se inietto un codice qualunque ad esempio il codice:

xor eax, eax
jmp vecchio_entry_point


ovviamente sostituendo vecchio_entry_point con l'indirizzo del vecchio entry point.

Se provo a debuggare con OllyDBG l'exe in cui ho iniettato il codice succede questo:
1. vengono eseguite delle istruzioni del modulo ntdll
2. vengono eseguite altre istruzioni del modulo prova
3. si passa finalmente all'entry point (quello settato nell'optional header)
3.1 xor eax, eax
3.2 salta al vecchio entry point
4. il programma continua la sua normale esecuzione

Il fatto è che questo accade con qualsiasi exe. Ho provato a debuggare PuTTY.exe (sia con OllyDBG che con altri debugger) e accade sempre lo stesso:
1. vengono eseguite delle istruzioni del modulo ntdll
2. vengono eseguite altre istruzioni del modulo putty
3. si passa finalmente all'entry point (quello settato nell'optional header)

Voglio sapere perché vengono eseguite tutte quelle istruzioni prima dell'entry point.

Siccome vengono eseguite delle istruzioni del modulo principale del mio programma prima di passare all'esecuzione dell'entry point, non posso criptare la text section. Perché altrimenti le istruzioni sarebbero criptate e quindi "non riconoscibili".

Spero di essere stato chiaro.
Ultima modifica effettuata da Driverfury 15/09/16 11:25
aaa
15/09/16 13:49
Driverfury
UPDATE:

Ho risolto.

In pratica ntdll viene richiamato prima di eseguire il processo, ha il compito di inizializzare diverse variabili (da quello che ho capito) e di chiamare appunto l'entry point del processo.

Inoltre: prima dell'entry point non viene eseguita alcuna istruzione del modulo principale, è stato un mio grossolano errore.
aaa
15/09/16 14:16
pierotofy
ntdll viene richiamata durante la fase di initializzazione del processo, l'image loader legge la lista di dipendenze riportate nella sezione imports, una volta caricate le dipendenze viene fatto il jump all'entry point.

prima dell'entry point non viene eseguita alcuna istruzione del modulo principale


Esatto!

Da leggere per approfondimenti: amazon.com/Windows-Internals-Part-Developer-Reference/dp/…
Ultima modifica effettuata da pierotofy 15/09/16 14:16
Il mio blog: piero.dev
15/09/16 22:24
Driverfury
Postato originariamente da pierotofy:

ntdll viene richiamata durante la fase di initializzazione del processo, l'image loader legge la lista di dipendenze riportate nella sezione imports, una volta caricate le dipendenze viene fatto il jump all'entry point.

prima dell'entry point non viene eseguita alcuna istruzione del modulo principale


Esatto!

Da leggere per approfondimenti: amazon.com/Windows-Internals-Part-Developer-Reference/dp/…


Ti ringrazio per il link.

In effetti il mio crypter funziona.

Il problema è il debugger (problema riscontrato sia con OllyDBG che con Immunity Debugger): quando eseguo il programma criptato con il debugger ho un errore di "Access violation when writing [...]" ad una istruzione che ancora non è stata eseguita (l'entry point è al codice che decripta).

Esempio: il mio entry point è all'indirizzo 0x401C64. Appena avvio il programma nel debugger ho l'errore all'indirizzo 0x4013C0. Ma questo indirizzo non è stato ancora eseguito, dovrebbero essere eseguite prima varie istruzioni della ntdll e poi il mio entry point! Nel debugger le istruzioni della ntdll non vengono proprio eseguite, parte direttamente con l'errore all'indirizzo 0x4013C0.

Se invece eseguo il programma normalmente (doppio click o esecuzione dal cmd) funziona tutto alla perfezione.

Non so per quale arcano motivo accade ciò. Forse i debugger fanno vari controlli prima di avviare il programma (non so se può c'entrare anche il fatto che aggiungo la flag writable alla sezione .text).

Se sapreste chiarirmi le idee ve ne sarei grato.
Ultima modifica effettuata da Driverfury 15/09/16 22:25
aaa
16/09/16 12:37
pierotofy
Mm, ci dovrebbe essere un'impostazione in OllyDbg dal menu Options -- Options -- Debugging -- Exceptions -- metti il segno di spunta su "Ignore also the following custom exceptions or ranges" -- Add current e aggiungi C00000005 ACCESS_VIOLATION.

Vedi screenshot.

Penso il problema accade perchè la sezione .text cambia durante l'esecuzione, e il debugger non è notificato del cambiamento, quindi al momento del jump, cerca di referenziare una parte di codice che (per il debugger) non esiste.
Il mio blog: piero.dev
17/09/16 22:18
Driverfury
Postato originariamente da pierotofy:

Mm, ci dovrebbe essere un'impostazione in OllyDbg dal menu Options -- Options -- Debugging -- Exceptions -- metti il segno di spunta su "Ignore also the following custom exceptions or ranges" -- Add current e aggiungi C00000005 ACCESS_VIOLATION.

Vedi screenshot.

Penso il problema accade perchè la sezione .text cambia durante l'esecuzione, e il debugger non è notificato del cambiamento, quindi al momento del jump, cerca di referenziare una parte di codice che (per il debugger) non esiste.


Nada. Stesso errore.
aaa