|
|
|
![]() |
|
Strumenti |
![]() |
#1 |
Member
Iscritto dal: Jan 2005
Messaggi: 46
|
leggere eseguibile.
ciao a tutti
eventualmente giustificate la mia domanda con la mia inesperienza. ![]() scrivo un sorgente, lo compilo e genero un eseguibile. in sintesi l eseguibile e il risultato della "traduzione" del mio sorgente. l eseguibile contiene valori in binario che il processore interpreta come istruzioni. da qualche parte ho letto che il processore legge l eseguibile dal primo all ultimo indirizzo dove risiede, in ordine sequenziale. quindi faccio un programma che legge valori binario per stringhe... e leggo un eseguibile. e lecito credere che il processore legga una stringa di istruzioni per interpretarla fino a '\n' ...per poi passare alla sucessiva?? come posso interpretare anche in linea di massima, quelle stringhe?? e giusto pensare che le prime parti dell eseguibile siano il "boot"?? spero di non aver sparato troppo... ciao ![]() |
![]() |
![]() |
![]() |
#2 |
Senior Member
Iscritto dal: Jun 2002
Città:
Provincia De VaRéSe ~ § ~ Lat.: 45° 51' 7" N Long.: 8° 50' 21" E ~§~ Magica Inter ~ § ~ Detto: A Chi Più Amiamo Meno Dire Sappiamo ~ § ~ ~ § ~ Hobby: Divertimento allo Stato Puro ~ § ~ ~ § ~ You Must Go Out ~ § ~
Messaggi: 8895
|
mmm non ci ho capito un gran che.
Non penso proprio che il processore si vada a leggere tutte le istruzioni. Poi a seconda dell'implementazione dei processi si usano diversi tipi di scheduling. Se non erro quello dei processi è sotto il round robin sotto windows e linux. Poi ovvio che l'implemetazione te la puoi fare anche in sottomodi. Cmq la teoria per spiegare come un compilatore o un interprete traduce o interpreta il codice è abbastanza lunga. Cmq quando esegui un programma avrai il linker che serve a caricare le libreri esterne, poi avrai il loader che associa gli indirrizzi relativi a quelli assoluti. Poi avrai anche la paginazione se è supportata cioè te non carichi tutto l'eseguibile ma vai a caricare una pagina del codice e una pagina per lo stack. Poi a seconda di come è strutturato incomincerai ad avere un bel page fault e così caricherai la pagina che ti serve. Va be poi ci sarebbe da parlare di mmu e mucca pazza ma traslascio sta parte ![]() Adesso è detto alla carlona. Se vuoi sapere di + prenditi un libro ![]() Per il fatto delle stringhe non ho capito che chiedi ~§~ Sempre E Solo Lei ~§~
__________________
Meglio essere protagonisti della propria tragedia che spettatori della propria vita
Si dovrebbe pensare più a far bene che a stare bene: e così si finirebbe anche a star meglio. Non preoccuparti solo di essere migliore dei tuoi contemporanei o dei tuoi predecessori.Cerca solo di essere migliore di te stesso |
![]() |
![]() |
![]() |
#3 |
Member
Iscritto dal: Jan 2005
Messaggi: 46
|
ok...grazie per esserti espresso alla "carlona", gia cosi devo rileggere un po le dritte che mi dai.
provo a interpretare il tuo concetto (per me complesso). per le stringhe intendo se le operazioni (che gentilmente mi hai spiegato) sono distinte per stringhe e terminate da '\n' (in .c).. ![]() ciao |
![]() |
![]() |
![]() |
#4 |
Senior Member
Iscritto dal: Jun 2002
Città:
Provincia De VaRéSe ~ § ~ Lat.: 45° 51' 7" N Long.: 8° 50' 21" E ~§~ Magica Inter ~ § ~ Detto: A Chi Più Amiamo Meno Dire Sappiamo ~ § ~ ~ § ~ Hobby: Divertimento allo Stato Puro ~ § ~ ~ § ~ You Must Go Out ~ § ~
Messaggi: 8895
|
aspetta devi definire due cose:
- stringhe definite come costanti; - stringhe prese in input. Le prime se non erro vengono caricate immediatamente in memoria, le stringhe in input ci possono essere varie strade a seconda di come allochi la stringa. Se la allochi nel metodo char string[20]; il loader associa a string un valore di indirizzo fisico e alloca direttamente lo spazio char *string; allora qui alloca semplicemente i 32bit o 64 a seconda dell'architettura e poi quando richiamerai malloc o realloc a seconda allocherà spazio. Ovviamente se con realloc lui non ha spazio sufficiente viene spostato il contenuto in una nuova zona. Non so se mi son spiegato o ho detto delle minchiate colossali ![]() ![]() ~§~ Sempre E Solo Lei ~§~
__________________
Meglio essere protagonisti della propria tragedia che spettatori della propria vita
Si dovrebbe pensare più a far bene che a stare bene: e così si finirebbe anche a star meglio. Non preoccuparti solo di essere migliore dei tuoi contemporanei o dei tuoi predecessori.Cerca solo di essere migliore di te stesso |
![]() |
![]() |
![]() |
#5 |
Member
Iscritto dal: Jan 2005
Messaggi: 46
|
![]() aspetta fenomeno... scrivo codice megari mi spiego meglio.. in=fopen("file.exe","rb") while((c=getc(in))!=EOF&&c!='\n') per stringhe intendo quelle che leggo da file.exe...... ciao |
![]() |
![]() |
![]() |
#6 | |
Senior Member
Iscritto dal: Jun 2002
Città:
Provincia De VaRéSe ~ § ~ Lat.: 45° 51' 7" N Long.: 8° 50' 21" E ~§~ Magica Inter ~ § ~ Detto: A Chi Più Amiamo Meno Dire Sappiamo ~ § ~ ~ § ~ Hobby: Divertimento allo Stato Puro ~ § ~ ~ § ~ You Must Go Out ~ § ~
Messaggi: 8895
|
Quote:
![]() cmq non vedo come possa funzionare la lettura di un file eseguibile in quel modo. Il codice che hai non è mica un carattere. Se vuoi leggere il codice devi: disassemblarlo e capirlo (auguri e figli maschi). Poi non credo che sia possibile ritornare esattamente al codice sorgente di partenza se si fanno anche ottimizzazioni del codice. ~§~ Sempre E Solo Lei ~§~
__________________
Meglio essere protagonisti della propria tragedia che spettatori della propria vita
Si dovrebbe pensare più a far bene che a stare bene: e così si finirebbe anche a star meglio. Non preoccuparti solo di essere migliore dei tuoi contemporanei o dei tuoi predecessori.Cerca solo di essere migliore di te stesso |
|
![]() |
![]() |
![]() |
#7 |
Member
Iscritto dal: Jan 2005
Messaggi: 46
|
grazie fenomeno, pensavo si potesse spiegare facilmente......
ciao Ultima modifica di telluccio : 08-11-2005 alle 21:09. |
![]() |
![]() |
![]() |
#8 |
Senior Member
Iscritto dal: Apr 2003
Città: Genova
Messaggi: 4741
|
- dovresti avere una conoscenza dell'assembly della macchina
- dovresti sapere come far corrispondere una sequenza di 0 e 1 a una sequenza di istruzioni (cosa complicata dal fatto che ogni istruzione x86 ha un opcode di lunghezza variabile), quindi ti serve conoscere la codifica binaria di ogni istruzione - dovresti avere una conoscenza perfetta del funzionamento delle impostazioni del compilatore (tante volte a seconda delle #define nel codice o di certe flag passate nella riga di comando, viene generato codice di tipo diverso -> la sequenza in assembly ha ampi margini di variabilita') - e soprattutto dovresti conoscere come "ragiona" un compilatore per convertire blocchi di codice di alto livello in funzioni procedurali a livello HW, (che istruzioni genera in caso di if- o while- statement ad esempio ) dovresti conoscere il modo in cui si comporta con chiamate a funzione, passaggio di argomenti per stack, il funzionamento delle indirezioni ... a quel punto, con molta pazienza, puoi risalire, dato un tuo codice sorgente in linguaggio c/c++, ad una possibile sequenza binaria ![]()
__________________
Jappilas is a character created by a friend for his own comic - I feel honored he allowed me to bear his name Saber's true name belongs to myth - a Heroic Soul out of legends, fighting in our time to fullfill her only wish Let her image remind of her story, and of the emotions that flew from my heart when i assisted to her Fate
Ultima modifica di jappilas : 09-11-2005 alle 11:56. |
![]() |
![]() |
![]() |
#9 |
Member
Iscritto dal: Jan 2005
Messaggi: 46
|
sempre per curiosita...quante saranno le persone capaci di questo??
per persone intendo programmatori....o e solo una questione di tempi... ciao |
![]() |
![]() |
![]() |
#10 |
Senior Member
Iscritto dal: Nov 2005
Città: Bordeaux - France
Messaggi: 364
|
Essenzialmente, è come contare le lenticchie contenute in dozzine di camion avendo a disposizione solo un rosario: nessun folle lo farebbe, a meno che non si tratti di un programma estremamente semplice ed estremamente importante.
Come se non bastasse, può essere fattibile per programmi scritti in assembly, ben difficilmente per i linguaggi di alto livello. Nel primo caso, disassemblando ottieni qualcosa di molto simile a quanto ha scritto l'autore, e quindi interpretare quanto ha scritto è solo -incredibilmente arduo-. Nel caso dei linguaggi di alto livello, le complessità introdotte dai compilatori fan sì che il compito sia pressochè -impossibile-.
__________________
- fuocofatuo - |
![]() |
![]() |
![]() |
#11 |
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
oddiosanto quante sparate che avete fatto tutti quanti O_________O
l'unico che ha detto cose corrette è jappilas... allora, ricominciamo daccapo: telluccio, per leggere il contenuto di un exe devi conoscere il suo formato, che è il PE (scaricati il doc presente in MSDN, se non lo trovi te lo passo io). una volta scaricato il doc avrai una visione molto più chiara al di sopra delle boiate di un certo non dico chi altrimenti fenomeno si offende: scoprirai ad es. che il file inizia con degli headers per poi essere suddiviso in cosiddette sezioni. se tu vuoi disassemblare un programma, la sezione che ti interessa è quella contenente il codice dello stesso, la quale sezione spesso si chiama ".text", ma in alcuni compilatori (Borland) si chiama "CODE". disassemblare un programma C o C++ odierno per quanto mi riguarda è molto più semplice che disassemblare un programma vecchio scritto direttamente in assembly da qualcuno: le persone umane quando programmano in assembly usano ottimizzazioni e ragionamenti loro che è poi molto difficile dedurre nel disassemblaggio, mentre i compilatori usano sempre schemi fissi. ti faccio un esempio: appena vedi una sequenza di Codice:
push ebp mov ebp,esp mov ecx,N ; N è il numero di bytes occupati dalle variabili locali sub esp,ecx rep stos Codice:
pop ebp ret N ; N qui è il numero di bytes dello stack da ripulire (quelli dei parametri) ![]() inoltre, facendoti magari aiutare da un API tracer, puoi addirittura ricostruire le funzioni API chiamate dal programma ![]() anzi per aiutarti ulteriormente posso dirti che in un'altra sezioni, generalmente a sola lettura, i compilatori mettono la cosiddetta IAT, Import Address Table, la quale inizialmente (cioè quando il file è scritto su disco ma non avviato) contiene numeri che si possono interpretare in una maniera abbastanza complessa che mo non sto a spiegarti (è documentata nel doc del PE), ma quando il file è in esecuzione essa contiene (a seguito del binding effettuato dal loader) gli indirizzi delle funzioni importate da altre DLL, tra cui anche le API Win32, perciò sai che ogni istruzione CALL che preleva l'indirizzo di destinazione di uno slot dalla IAT, è un CALL che chiama la rispettiva funzione importata. aggiungendoci un po' di lavoro col Dependency Walker hai praticamente ricostruito l'aspetto originale del programma: ![]() ![]() a proposito, tante volte non lo sapessi, secondo la convenzione STDCALL (quella usata più spesso) il risultato di una funzione viene sempre restituito in EAX, e lo stack viene ripulito dalla funzione chiamata, non dal chiamante (sono cose che possono esserti utili). ciao |
![]() |
![]() |
![]() |
#12 | ||||||
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
Quote:
Quote:
Quote:
Quote:
Quote:
la situazione è più complessa: il loader di Windows mappa i files PE che carica in dei File Mapping Objects, quindi non scrive in memoria nessuna pagina; lo stack è tutt'altro discorso: viene allocato all'avvio di un thread (in genere è 1 kb di commit e 1 mega di reserve) e a noi poveri mortali non è dato sapere se viene direttamente scritto in RAM o se si procede a page faults, ma dato che si tratta di un solo kilobyte (che è meno della dimensione di una pagina) posso immagine che scriverlo direttamente in RAM non costi granché... comunque il meccanismo della paginazione è trasparente al programmatore, quindi per telluccio è inutile da sapere; gli basti sapere che processi diversi a indirizzi uguali vedono cose diverse (cosa che molti professori e studenti universitari a quanto pare non sanno). Quote:
![]() ![]() Ultima modifica di 71104 : 09-11-2005 alle 10:37. |
||||||
![]() |
![]() |
![]() |
#13 |
Member
Iscritto dal: Feb 2005
Città: Prato
Messaggi: 149
|
Ciao,
Tutto corretto finché non gli arriva sottomano un DOS exe 16bit o, peggio un NE... in tal caso è bene saper distinguere e sapere quali sono le strutture in gioco... Ogni tipo di eseguibile (eccetto i .com) ha un header determinato dalla struttura IMAGE_DOS_HEADER. La signature del campo deve essere sempre "MZ" per un eseguibile. Il campo e_lfanew può puntare ad una signature (una "firma") che può essere "PE\0\0" (4bytes) "PE" (2bytes) o "NE". Se non è presente una di queste "firme" il file non è un eseguibile standard. A partire da questo le cose cominciano a ramificarsi a seconda del formato... Il formato PE prevede una IMAGE_FILE_HEADER seguita da una IMAGE_OPTIONAL_HEADER (che, nonostante il nome NON è opzionale) e dalle informazioni sulle sezioni - IMAGE_SECTION_HEADER (indirizzo di caricamento in memoria, offset nel file, dimensioni e numerosi flags). Le tre sezioni di base (.text,.data,.rsrc) contengono rispettivamente codice, dati e risorse (come dice 71104 i nomi potrebbero essere leggermente diversi a seconda del compilatore - nell'IMAGE_OPTIONAL_HEADER è presente l'Entry Point, ovvero il punto da cui inizia l'esecuzione). Due sezioni (.idata,.edata) contengono le informazioni di import/export di funzioni da DLL esterne. Una sezione (.reloc) contiene le informazioni di rilocazione. I formati sono abbastanza ben documentati (ti consiglio di cercare "PE Format" in MSDN - su cd o sul sito http://msdn.microsoft.com nella sezione Library). L'EntryPoint di eseguibili scritti in VB o che usano MFC puntano ad una funzioncina striminzita di inizializzazione, è il framework MFC o la VM di VB che poi gestiscono l'eseguibile... gli eseguibili VC/BC contengono codice più "sequenziale". Il loader di windows carica l'eseguibile, controlla le sezioni creando un selettore (ex segmento) per le sezioni principali, si preoccupa della rilocazione del codice all'indirizzo di base (per gli eseguibili VC è di default 0x00400000 - NB:Virtuale!) e della trasformazione della idt da un insieme di numeri in un'insieme di riferimenti (indirizzi "virtuali" che corrispondono alle funzioni delle varie DLL nello spazio del processo). Fatto questo (e non è poco) inizia l'esecuzione del codice dall'Entry Point specifico. Eseguibili che si basano su un framework o su una VM passeranno alle funzioni di tale FW o VM i dati del programma (in questo caso il funzionamento può essere piuttosto complicato da rintracciare). Anche un programma semplice in VC può essere piuttosto lungo da studiare (il compilatore inserisce diverso codice per l'inizializzazione dell'applicazione)... non è mai una passeggiata ed è necessaria una buona dose di conoscenza sia per quanto riguarda il funzionamento del SO che dell'asm in sé. Per quanto riguarda il formato NE... si tratta di codice windows a 16bit... il funzionamento è totalmente diverso da quello degli eseguibili PE e decisamente più macchinoso (ogni segmento contiene in coda una serie di informazioni di rilocazione/idt di vario tipo). Il formato exe DOS/16bit è abbastanza lineare (sempre se si riesce a determinare velocemente la segmentazione del programma - un seg in questo caso sono al massimo 64k di codice/dati). Insomma, non è certo una passeggiata, neanche per i programmi più semplici... ma nemmeno una cosa infattibile quando si ha una certa esperienza ed una buona conoscenza della programmazione strutturata (non si può imparare a programmare studiando il funzionamento di un eseguibile ma è sicuramente vero il contrario)... Ciaociao ![]()
__________________
Venite a visitarci qui:http://www.bottomap.com Bottomap is a proud Masterdrive.it moderator Ultima modifica di bottomap : 09-11-2005 alle 11:15. |
![]() |
![]() |
![]() |
#14 | |||
Senior Member
Iscritto dal: Jun 2002
Città:
Provincia De VaRéSe ~ § ~ Lat.: 45° 51' 7" N Long.: 8° 50' 21" E ~§~ Magica Inter ~ § ~ Detto: A Chi Più Amiamo Meno Dire Sappiamo ~ § ~ ~ § ~ Hobby: Divertimento allo Stato Puro ~ § ~ ~ § ~ You Must Go Out ~ § ~
Messaggi: 8895
|
Quote:
![]() Quote:
![]() Quote:
cercatelo non ho voglia di spiegare quella tabella ![]() ~§~ Sempre E Solo Lei ~§~
__________________
Meglio essere protagonisti della propria tragedia che spettatori della propria vita
Si dovrebbe pensare più a far bene che a stare bene: e così si finirebbe anche a star meglio. Non preoccuparti solo di essere migliore dei tuoi contemporanei o dei tuoi predecessori.Cerca solo di essere migliore di te stesso |
|||
![]() |
![]() |
![]() |
#15 | |
Senior Member
Iscritto dal: Nov 2005
Città: Bordeaux - France
Messaggi: 364
|
Quote:
1- e` possibile sapere che compilatore e` stato adoperato e con che impostazioni? Se si`, non lo sapevo; se no, come fai? Bisognerebbe forse procedere a tentativi, perche` solo conoscendo queste informazioni puoi risalire alla struttura corretta del linguaggio ad alto livello. 2- hai detto che si arriva, piu` o meno automaticamente, ad un programma suddiviso in funzioni; ma a questo punto, come fai a interpretarlo senza avere a disposizione il nome di variabili e metodi, commenti e quant'altro? E` un lavoro assurdo, specialmente se non hai la piena conoscenza della funzione che deve svolgere... Prendo in prestito del codice da questa discussione: Codice:
int fun1(int par1){ if (par1>0) return (par1%10)+fun1(par1/100); else return 0; } int fun2(int par1){ par1/=10; if (par1>0) return (par1%10)+fun2(par1/100); else return 0; } int fun3(int par1){ return (fun3(abs(fun2(par1)-fun1(par1)))); }
__________________
- fuocofatuo - |
|
![]() |
![]() |
![]() |
#16 |
Member
Iscritto dal: Feb 2005
Città: Prato
Messaggi: 149
|
Ciao,
Provo a risponderti io: 1 - E'possibile in una buona misura sapere con che compilatore è stato creato un eseguibile... vengono in aiuto un paio di campi nell'IMAGE_FILE_HEADER e un sistema "standard" di organizzare il codice... gli exe VC (in generale quelli MS) si identificano bene dal nome delle sezioni (.text,.data,.rsrc), nell'header menzionato sopra è presente la versione (major e minor) del compilatore utilizzato. Per VB è semplice, basta osservare che le chiamate non sono quasi mai a DLL ma a funzioni linkate dalla VM (Virtual Machine). Gli eseguibili Borland si riconoscono dai nomi delle sezioni e dalle risorse tipiche (ci vanno a finire un sacco di cose inutili per un programma standard). Non abbiamo parlato ovviamente di compressori/crittatori di eseguibili (esistono ed offrono vari gradi di sicurezza) in questi casi un'analisi prevede una preventiva decompressione/decrittazione... quest'ultima può essere piuttosto impegnativa... 2 - Come ho già postato più sopra (concordo con te) è un lavoro parecchio faticoso e prevede un'ottima conoscenza di SO ed asm... il sorgente a cui si può risalire molto difficilmente sarà quello originale (si può al limite approssimare parecchio)... in pratica un lavoraccio ingrato ed in cui, in genere, il gioco non vale la candela... con un ottima conoscenza e molto tempo si può risalire al discorso della divisibilità per 11 se si sa (da una esecuzione) che il programma contiene una funzione simile... E' una cosa più che altro di intuito e che si può arrivare ad avere solo dopo aver visto diversi milioni di righe di codice scritte da altri (ovvero dopo taaaaanti anni che si programma). Ciaociao ![]()
__________________
Venite a visitarci qui:http://www.bottomap.com Bottomap is a proud Masterdrive.it moderator |
![]() |
![]() |
![]() |
#17 |
Senior Member
Iscritto dal: Nov 2005
Città: Bordeaux - France
Messaggi: 364
|
Grazie mille.
P.S. Molto... ehmmm... carini i puffi...
__________________
- fuocofatuo - |
![]() |
![]() |
![]() |
#18 |
Member
Iscritto dal: Feb 2005
Città: Prato
Messaggi: 149
|
Ehmmmm... chiedo scusa a nome del grafico Cinfa (trattasi di animale - e anche di stracanovista insensibile alla pesantezza di una pagina zeppa di immagini grandi)
![]() ![]() Ciaociao ![]()
__________________
Venite a visitarci qui:http://www.bottomap.com Bottomap is a proud Masterdrive.it moderator |
![]() |
![]() |
![]() |
#19 |
Member
Iscritto dal: Jan 2005
Messaggi: 46
|
![]() ![]() un casino grazie ...per ora coppio e incollo e rileggo i post con calma.. forse per ora e meglio che continuo a crearli gli eseguibili... ciao. |
![]() |
![]() |
![]() |
#20 | ||||||||||||||
Bannato
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
|
Quote:
![]() Quote:
![]() lì dice semplicemente che quando si legge un file PE bisogna andare all'offset 0x3C e leggere un altro offset a cui è situato l'inizio del nuovo header PE, seguito poi dall'header opzionale, da quelli delle sezioni, ed infine dalle sezioni stesse. Quote:
Quote:
![]() già telluccio non ne sa molto e la situazione è abbastanza confusa di per se', tu gli vai addirittura ad insegnare formati sconosciuti ("NE"??? O_o') che non si useranno mai... ![]() Quote:
![]() Quote:
![]() Quote:
![]() Quote:
![]() Quote:
![]() oggidì si usa solo la paginazione, e la segmentazione viene usata in maniera minimale perché non è possibile disattivarla sugli Intel; l'unica protezione che essa fornisce è tra user space e kernel space. Quote:
Quote:
![]() Quote:
Quote:
![]() Quote:
|
||||||||||||||
![]() |
![]() |
![]() |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 06:41.