View Full Version : File [EXE] come è fatto?
Dr Nick Riviera
23-04-2006, 18:54
Salve raga, vorrei sapere se qualcuno di voi ha qualche guida semplice o appunto o qualcosa del genere in modo che io capisca bene o male come è fatto un file exe e in maniera un po' più approfondita sulle "Import Table" e "Export Table"..
Ho cercato un po' in rete ma ho trovato solo guide non semplici in inglese.. e qualcosa in italiano ma che in linea di massima per uno che come me non ne sa niente di queste cose.. sono a dir poco incomprensibili..
Grazie anticipate per l'aiuto..
Salve raga, vorrei sapere se qualcuno di voi ha qualche guida semplice o appunto o qualcosa del genere in modo che io capisca bene o male come è fatto un file exe e in maniera un po' più approfondita sulle "Import Table" e "Export Table"..
Ho cercato un po' in rete ma ho trovato solo guide non semplici in inglese.. e qualcosa in italiano ma che in linea di massima per uno che come me non ne sa niente di queste cose.. sono a dir poco incomprensibili..
Grazie anticipate per l'aiuto..Ciao, scusa ma in questo momento ti devo rispondere un po' velocemente.
Vai su www.wotsit.org (http://www.wotsit.org) e cerca l'estensione exe. Ci troverai diversi documenti.
Salve raga, vorrei sapere se qualcuno di voi ha qualche guida semplice o appunto o qualcosa del genere in modo che io capisca bene o male come è fatto un file exe e in maniera un po' più approfondita sulle "Import Table" e "Export Table"..
Ho cercato un po' in rete ma ho trovato solo guide non semplici in inglese.. e qualcosa in italiano ma che in linea di massima per uno che come me non ne sa niente di queste cose.. sono a dir poco incomprensibili..
Grazie anticipate per l'aiuto.. sicuramente prima di imparare il formato PE/COFF dovresti avere una minima infarinatura circa la gestione della memoria virtuale. comunque sia quasi tutto lo scibile di Windows sta su MSDN, compresi formato PE/COFF e gestione della memoria virtuale su Windows; e il resto sta su Google.
Dr Nick Riviera
23-04-2006, 20:42
Grazie.. ho scaricato questo --> Portable Executable Format [Micheal J. O'Leary]
..però il mio problema è che ho dei vuoti su dei concetti di base.. ma non posso nemmeno sapere tutto sennò non ci levo le gambe.. :(
Grazie.. ho scaricato questo --> Portable Executable Format [Micheal J. O'Leary]
..però il mio problema è che ho dei vuoti su dei concetti di base.. ma non posso nemmeno sapere tutto sennò non ci levo le gambe.. :( chiedi qua no? :)
di' cos'è che non conosci e chi può ti darà un'infarinatura e qualche buon link a MSDN.
Dr Nick Riviera
24-04-2006, 11:37
Per ora ho trovato un link dove si tratta l'argomento PE in italiano.. vedo di dare una lettura a quello prima di porre altre domande in modo da vedere se alcune di esse riesco ad evitarle.. ;)
Grazie della disponibilità.. tornerò tra qualche giorno..
Dr Nick Riviera
26-04-2006, 12:21
Ho dato un po' una lettura a questo file di testo, sono arrivato alle import table e viene fatto l'esempio con notepad.exe.. Intanto l'esempio non corrisponde a quello che faccio io.. cioè, lui dice che RVA è 00006000 e invece a me viene 00007604... quindi lui dice che sono già allineati e invece non è così.. e non capisco come si faccia l'allineamento dato che non lo spiega.. inoltre poi con il debugger vengono mostrate le dword a gruppi di 5 e dice che la prima dword riguarda una unoin: IMPORT FLAGS or OriginalFirstThunk e il valore di questo punta a un indirizzo che contiene le funzioni importate.. ma io non lo trovo sul debugger..
Sapete niente in merito? :confused:
Se hai un Visual C++ puoi usare l'utility DUMPBIN. Esempio:
DUMPBIN /HEADERS NOTEPAD.EXE
Può essere molto utile per verificare i valori reali contenuti nei vari header. ;)
Ho dato un po' una lettura a questo file di testo, sono arrivato alle import table e viene fatto l'esempio con notepad.exe.. Intanto l'esempio non corrisponde a quello che faccio io.. cioè, lui dice che RVA è 00006000 e invece a me viene 00007604... si vede che hai una build diversa, nulla di strano; da me per esempio la IAT di Blocco Note si trova all'RVA 0x00001000, e la IDT all'RVA 0x00006650. tu a quale "Import Table" ti riferisci?
quindi lui dice che sono già allineati e invece non è così.. allineati in che senso? allineati al page bound? mica deve per forza essere così... non vedo che problemi ti crei se una struttura dati si trova ad un indirizzo piuttosto che un altro.
e non capisco come si faccia l'allineamento dato che non lo spiega.. tu non devi mica modificare l'exe; se la IAT o la IDT del tuo Blocco Note non è allineata al page bound chissene :)
inoltre poi con il debugger vengono mostrate le dword a gruppi di 5 e dice che la prima dword riguarda una unoin: IMPORT FLAGS or OriginalFirstThunk ok, quindi ti riferisci alla IAT, non alla IDT.
e il valore di questo punta a un indirizzo che contiene le funzioni importate.. ma io non lo trovo sul debugger.. che vuol dire non lo trovi scusa... :p
tu vai a consultare la IAT originale, ok? leggi la prima entry; leggi il primo DWORD della prima entry; quel DWORD ti da tutte le informazioni necessarie per trovare il nome oppure la hint di quella funzione (non sempre le funzioni vengono importate "by name"). dopodiché, vuoi sapere il nome o la hint dell'N-esima funzione importata? fai la stessa cosa per l'N-esima entry della IAT.
deve funzionare per forza, se non va avrai sbagliato qualcosa.
Dr Nick Riviera
26-04-2006, 13:00
Scusate raga.. ma se non ho un esempio che posso seguire per rifare i vari step col pc.. per me è arabo..
Grazie per le risposte... ma sarà dura per me capire sta roba, non mollerò, ma non sarà semplice... :mc:
Dr Nick Riviera
26-04-2006, 13:04
C'ho ripensato :D , vi riporto la parte del testo riferita alla import table, così capite ciò che voglio dirvi...
Tanto per cominciare mi serve una cavia adatta: qual'è un file con una IT semplice che abbiamo tutti?
il Notepad.exe! Andiamo nella Directory Table e per la IT troviamo:
Import table: RVA: 00006000 SIZE: 8C
quindi abbiamo indirizzo e grandezza. Ora 6000 è un RVA, quindi col FLC andiamocelo a convertire in raw
offset, ed otteniamo... 6000 (allineamento perfetto).
B0 61 00 00 - ED 6C 45 37 - FF FF FF FF - 8A 65 00 00
F0 63 00 00 - 18 61 00 00 - B3 C2 1F 37 - FF FF FF FF
9C 67 00 00 - 58 63 00 00 - CC 61 00 00 - EB 6C 45 37
FF FF FF FF - 92 6B 00 00 - 0C 64 00 00 - B8 60 00 00
72 C2 3E 35 - FF FF FF FF - F6 6C 00 00 - F8 62 00 00
C0 62 00 00 - ED 6C 45 37 - FF FF FF FF - 7A 6D 00 00
00 65 00 00 - A0 60 00 00 - EB 6C 45 37 - FF FF FF FF
DA 6D 00 00 - E0 62 00 00 - 00 00 00 00 - 00 00 00 00
00 00 00 00 - 00 00 00 00 - 00 00 00 00
questi sono i 140 (8Ch) bytes. Per ora non compaiono nomi di funzioni o dll.
Partiamo dalla Directory Table, che come al solito contiene le informazioni sulla IT stessa. Dobbiamo prendere in considerazione le prime 5 dwords, che ci identificano i seguenti valori:
_____________________________________________________________________________
VALORE: | DWORD NELLA IT DI ESEMPIO |
--------------------------------------------+-------------------------------+
Union: IMPORT FLAGS or OriginalFirstThunk | B0 61 00 00 |
TIME/DATE STAMP | ED 6C 45 37 |
FORWARDER CHAIN | FF FF FF FF |
NAME RVA | 8A 65 00 00 |
IMPORT ADDRESS TABLE RVA (FirstThunk) | F0 63 00 00 |
--------------------------------------------+-------------------------------+
anche le dword successive vanno considerate a gruppi di 5, compreso l'ultimo gruppo di 5 dwords che serve per chiudere la Directory dell'IT.
()- Import Flags
Questo dovrebbe rientrare nel campo "characteristics", ma in realtà la dword è una union tra il valore Characteristics e OriginalFirstThunk. Essendo il campo characteristics sempre a zero, la dword contiene il valore dell'OriginalFirstThunk, 000061B0, che punta alla struttura degli indirizzi ai nomi delle funzioni importate:
7A 65 00 00 - 68 65 00 00 - 20 65 00 00 - 4E 65 00 00
3C 65 00 00 - 2E 65 00 00 - 00 00 00 00
questi valori dunque puntano ai nomi delle funzioni (la NULL indica il termine della struttura), e questi indirizzi di nomi faranno parte degli OriginalFirstThunk (ne parleremo dopo).
E le Characteristics? La union è come una struttura, solo che i membri di tale struttura possono essere utilizzati solo uno alla volta. Quindi il la union in questione può contenere O le characteristics O OriginalFirstThunk. Notate che sono 6 funzioni importate, e che l'ordine dei loro nomi non coincide con l'ordine dei loro puntatori (cosa che noterete se andate a vedere l'IT dal PEditor).
In realtà questi indirizzi sono dei puntatori ad altre strutture, cioè:
Struttura IMAGE_IMPORT_BY_NAME:
word HINT
byte NAME1
infatti prendiamo ad esempio il primo puntatore, 0000657A, punta alla stringa:
0000657A 6C 00 53 68 65 6C 6C 45 78 65 63 75 74 65 41 00 l.ShellExecuteA
in cui i primi due byte sono la word HINT (006C) che rappresenta l'indice della funzione nell'ET della dll da cui stiamo importando la funzione, e poi il nome vero e proprio, ShellExecuteA in forma di array di byte terminati dallo 0.
:confused: :(
Non so se può esserti utile, io personalmente non l'ho mai usata ma so che esiste la "Image Help Library". Trovi tutta la documentazione su MSDN qui (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/debug/base/image_help_library.asp).
scusa ma sei sicuro di aver preso la entry giusta nella Import Directory Table? :|
e poi guarda che hai sicuramente fatto confusione tra la Import Address Table e la Import Directory Table: il primo dump che hai riportato hai detto che era una IAT, mentre invece è sicuramente una IDT.
Dr Nick Riviera
26-04-2006, 14:53
A me hanno detto di imparare bene le IAT... ma a sto punto non so nemmeno la differenza...
in parole povere funziona così: in teoria ci stanno tante IAT e una sola IDT; la IDT è quella che va letta per prima e nella quale ogni entry descrive una IAT. ciascuna entry della IDT (assieme alla corrispettiva IAT) descrive le importazioni da un determinato modulo (ad esempio tu in un tipico exe per Windows avrai nella IDT una entry per kernel32.dll, una per user32.dll, una per gdi32.dll, e cos' via, e avrai altrettante IAT). questa è la teoria, ma alla fine nella pratica tutte le varie IAT sono messe una appresso all'altra in modo da formare un'unica grossa IAT il cui RVA sta anche scritto in un campo dell'header opzionale (tra le Data Directories ;)). non so se sono stato molto chiaro a dire il vero... :p
Dr Nick Riviera
27-04-2006, 14:15
Grazie 71104...
In pratica ho capito che dumpando il codice si sfasano le IAT per cui è necessario fare l'allineamento per farle tornare in modo che il programma funzioni.. potete per piacere approfondirmi questo concetto?
Grazie 71104...
In pratica ho capito che dumpando il codice si sfasano le IAT per cui è necessario fare l'allineamento per farle tornare in modo che il programma funzioni.. potete per piacere approfondirmi questo concetto? ma se non l'ho capito manco io... :|
intendevi dire che l'RVA della tua IAT non corrisponde al suo offset nel file? ok, ma ribadisco che non vedo quali problemi ti creino gli RVA che non corrispondo agli offset: basta saperlo...
Dr Nick Riviera
27-04-2006, 21:55
Sinceramente devo capirlo anch'io... :doh:
vabbè.. allora andiamo per gradi sennò faccio solo confusione:
- per "offset" cosa si intende in pratica?
- per "offset" cosa si intende in pratica? in un file l'offset di un byte in esso contenuto è la distanza (in bytes) dal primo byte contenuto nel file. il primo byte di un file ha offset 0; il terzo ha offset 2; il decimo ha offset 9; e così via.
Dr Nick Riviera
28-04-2006, 02:52
;) Grazie..
Dr Nick Riviera
30-04-2006, 22:05
Scusate.. che si intende per "checksum"? :confused: :mbe:
Scusate.. che si intende per "checksum"? :confused: :mbe:Il checksum, in senso generale, indica un algoritmo per controllare l'integrità dei dati.
Il checksum più semplice è la somma. In pratica se hai la sequenza di 3 byte: 0Ah 10h 04h, il suo checksum è 1Eh.
Dr Nick Riviera
30-04-2006, 22:33
...e la sua utilità quale è?
...e la sua utilità quale è?Quella di effettuare il controllo sull'integrità dei dati.
Senza entrare troppo nei dettagli (anche perché non sono la persona più adatta ;) ) esistono tutta una serie di algoritmi che si occupano di effettuare quello che viene chiamato "Error detection" o anche "Error detection and correction" a seconda se è possibile (grazie all'algoritmo) o meno correggere l'errore.
Dato un messaggio di lunghezza N, si aggiunge al messaggio una informazione di "checksum" di lunghezza M:
<messaggio> --------> <messaggio> + <checksum>
Tale per cui sia possibile verificare, in modo più o meno sicuro, che il messaggio sia integro e non corrotto o alterato.
La caratteristica principale degli algoritmi di checksum è che dato un messaggio di lunghezza N qualunque, l'algoritmo di checksum fornisce in output un valore di checksum di lunghezza fissa M.
Di algoritmi per il checksum ce ne sono tanti, i più conosciuti sono:
- checksum (controllo somma) (a 8 bit, 16 bit, ecc...)
- CRC (Cyclic redundancy check) (CRC-8, CRC-16, CRC-32, ecc...)
- funzioni Hash (MD5, SHA-1, ecc...)
Il più semplice è il controllo della somma, che però, per via della sua semplicità, non è nemmeno molto efficace. Il motivo è semplice: è facile alterare il messaggio facendo in modo che il suo checksum resti inalterato.
Prendiamo per esempio la sequenza 0Ah 10h 04h il cui checksum a 16 bit è 001Eh.
0Bh 10h 04h --> 001Fh (alterato!!!!)
08h 12h 04h --> 001Eh (non alterato!!!!)
Si vede bene che alterando pochi bit (appena 2 bit) nel messaggio è possibile modificare il messaggio senza alterare il suo checksum. Questo è il limite del calcolo della somma, che quindi va bene quando non si hanno grosse pretese.
Dr Nick Riviera
01-05-2006, 21:44
Grazie andbin, quindi il checksum viene usato come controllo per far sì che non venga alterato il codice.. per cui se uno altera il codice (anche leggermente) e il checksum non corrisponde più, il programma non funziona?
Inoltre non ho ben chiara la differenza tra FirstThunk ed OriginalFirstThunk...
Inoltre non ho ben chiara la differenza tra FirstThunk ed OriginalFirstThunk... prima del caricamento sono uguali; dopo il caricamento la prima viene riempita con gli indirizzi virtuali delle rispettive funzioni importate.
Dr Nick Riviera
02-05-2006, 02:23
prima del caricamento sono uguali; dopo il caricamento la prima viene riempita con gli indirizzi virtuali delle rispettive funzioni importate.
..e ciò a che scopo? Perchè non può caricare direttamente quelli reali?
..e ciò a che scopo? Perchè non può caricare direttamente quelli reali? nel file non possono essere scritti gli indirizzi finali effettivi perché non sono conosciuti a priori: sono conosciuti solamente in runtime (si ricavano dalle export tables dei rispettivi moduli ;)).
Grazie andbin, quindi il checksum viene usato come controllo per far sì che non venga alterato il codice.. per cui se uno altera il codice (anche leggermente) e il checksum non corrisponde più, il programma non funziona?Il concetto è quello. Comunque il checksum, come somma di byte, è un controllo abbastanza "debole", come già detto.
Per quanto riguarda il fatto che il programma non funziona se il checksum non corrisponde, la cosa non è proprio così. Ti riferisci in particolare al campo "checksum" presente negli header dei file .exe??
Mi risulta che quel campo viene messo per default a 0 dal linker e che bisogna richiedere espressamente al linker (tramite un qualche parametro) di calcolare e inserire il checksum.
Quindi quando Windows carica un eseguibile, non controlla di certo il checksum (o almeno non credo ma non sono sicuro al 100% ;) ).
Ti riferisci in particolare al campo "checksum" presente negli header dei file .exe??
Mi risulta che quel campo viene messo per default a 0 dal linker e che bisogna richiedere espressamente al linker (tramite un qualche parametro) di calcolare e inserire il checksum. esatto
Quindi quando Windows carica un eseguibile, non controlla di certo il checksum (o almeno non credo ma non sono sicuro al 100% ;) ). penso che lo controlla solo se c'è
penso che lo controlla solo se c'èGuarda ... mi hai fatto venire un bel dubbio. Ho quindi fatto una prova pratica:
1) Ho compilato con il VC++.net 2003 una banale applicazione windows. Ho specificato al linker di calcolare/inserire il checksum (nelle proprietà del progetto nella sezione Linker/Avanzate c'è una opzione "Imposta checksum").
2) Con il tool Anywhere PE Viewer, ho esaminato l'header e ho visto che l'eseguibile ha un certo checksum (6519h).
3) Con un editor esadecimale ho modificato una delle stringhe di testo (giusto x non combinare casini) all'interno dell'eseguibile.
4) Sempre con il tool indicato sopra ho calcolato il checksum "reale" che è diventato 13409h.
5) Ho avviato l'eseguibile e Windows non si è manco accorto che il checksum non corrisponde.
Quindi non saprei cosa dirti. Credo che Windows non controlli, almeno per default, il checksum.
Dr Nick Riviera
02-05-2006, 12:13
Grazie 1000 per ora... ;)
[...] 5) Ho avviato l'eseguibile e Windows non si è manco accorto che il checksum non corrisponde.
Quindi non saprei cosa dirti. Credo che Windows non controlli, almeno per default, il checksum. in effetti spulciando i sorgenti di ReactOS vedo che non l'hanno controllato neanche loro, e stai tranquillo che chi ha scritto il loader PE è un tizio tosto: ho letto svariati suoi post su Usenet, penso che quel loader sia assolutamente identico all'originale...
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.