Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Username: Password: oppure
C/C++ - Chiarimenti sull'Entry Point e sul formato PE
Forum - C/C++ - Chiarimenti sull'Entry Point e sul formato PE

Avatar
Driverfury (Normal User)
Rookie


Messaggi: 45
Iscritto: 21/09/2011

Segnala al moderatore
Postato alle 20:20
Martedì, 13/09/2016
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 il 14/09/2016 alle 2:01
PM Quote
Avatar
pierotofy (Admin)
Guru^2


Messaggi: 6230
Iscritto: 04/12/2003

Segnala al moderatore
Postato alle 5:42
Giovedì, 15/09/2016
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: https://piero.dev
PM Quote
Avatar
Driverfury (Normal User)
Rookie


Messaggi: 45
Iscritto: 21/09/2011

Segnala al moderatore
Postato alle 13:24
Giovedì, 15/09/2016
Testo quotato

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:

Codice sorgente - presumibilmente C/C++

  1. xor eax, eax
  2. 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 il 15/09/2016 alle 13:25
PM Quote
Avatar
Driverfury (Normal User)
Rookie


Messaggi: 45
Iscritto: 21/09/2011

Segnala al moderatore
Postato alle 15:49
Giovedì, 15/09/2016
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.

PM Quote
Avatar
pierotofy (Admin)
Guru^2


Messaggi: 6230
Iscritto: 04/12/2003

Segnala al moderatore
Postato alle 16:16
Giovedì, 15/09/2016
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.

Testo quotato


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



Esatto!

Da leggere per approfondimenti: https://www.amazon.com/Windows-Internals-Part-Developer-Ref ...

Ultima modifica effettuata da pierotofy il 15/09/2016 alle 16:16


Il mio blog: https://piero.dev
PM Quote
Avatar
Driverfury (Normal User)
Rookie


Messaggi: 45
Iscritto: 21/09/2011

Segnala al moderatore
Postato alle 0:24
Venerdì, 16/09/2016
Testo quotato

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.

Testo quotato


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



Esatto!

Da leggere per approfondimenti: https://www.amazon.com/Windows-Internals-Part-Developer-Ref ...



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 il 16/09/2016 alle 0:25
PM Quote
Avatar
pierotofy (Admin)
Guru^2


Messaggi: 6230
Iscritto: 04/12/2003

Segnala al moderatore
Postato alle 14:37
Venerdì, 16/09/2016
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.


pierotofy ha allegato un file: screen.png (26698 bytes)
Clicca qui per guardare l'immagine


Il mio blog: https://piero.dev
PM Quote
Avatar
Driverfury (Normal User)
Rookie


Messaggi: 45
Iscritto: 21/09/2011

Segnala al moderatore
Postato alle 0:18
Domenica, 18/09/2016
Testo quotato

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.

PM Quote
Avatar
pierotofy (Admin)
Guru^2


Messaggi: 6230
Iscritto: 04/12/2003

Segnala al moderatore
Postato alle 1:31
Domenica, 18/09/2016
Non ho idea allora.

Se riesci ad allegare qualche file così che posso provare a replicare l'errore, posso vedere se riesco a trovare una risposta.


Il mio blog: https://piero.dev
PM Quote