2010-06-09 2 views
8

Ecco un esempio di quello che voglio dire ...C o C++: come funzionano i caricatori/wrapper?

  • utente esegue il programma LOADER.EXE
  • LOADER.EXE scarica un altro file EXE, ma mantiene tutto in memoria senza salvarlo su disco
  • Esegue il scaricato EXE proprio come se fosse eseguito da disco, ma lo fa direttamente dalla memoria

Ho visto alcune applicazioni come questa, e non ho mai visto un esempio o una spiegazione di come funziona.

Qualcuno sa?

Un altro esempio è che un EXE crittografato è incorporato in un altro. Viene estratto e decrittografato in memoria, senza mai essere salvato su disco prima che venga eseguito.

Ho visto quello utilizzato in alcune applicazioni per prevenire la pirateria.

Modifica: Come nota a margine, programmi come UPX funzionano in questo modo? Ho guardato il codice ma è difficile da decifrare per me, e lo chiedo principalmente per curiosità, non ne ho bisogno.

risposta

4

Un sacco di programmi che fanno questo basta decomprimere al% TEMP% (lo so che faccio), ma i grandi ragazzi essenzialmente re-implementare il caricatore eseguibile del sistema operativo, che deve:

  • mappa l'eseguibile in memoria. Non è così semplice come sembra, dato che l'exe contiene più "sezioni", che devono essere caricate con l'allineamento della pagina (devono iniziare con indirizzi multipli di 4K) e hanno richieste specifiche - sola lettura, copia su scrivere, azzerare inizializzato, ecc ....
  • Soddisfare le importazioni statiche, aggiornando la sezione della tabella di importazione, normalmente utilizzando LoadLibrary() e GetProcAddress().
  • Nel caso di DLL (che sono in realtà quasi identiche, la differenza importante è che hanno esportazioni e importazioni), il caricatore potrebbe anche dover rebase la DLL, se l'indirizzo di memoria che è stato compilato per caricare era già in uso (che è abbastanza comune). Questo di solito è impossibile per gli exe, perché non includono la sezione di riposizionamento che elenca i posti nel codice caricato che devono essere aggiornati, perché normalmente sono la prima cosa caricata in un processo e quindi non possono essere bloccati da qualcosa Ciò significa che un caricatore deve avere un indirizzo di caricamento insolito per il proprio file EXE che non bloccherà l'exe caricato.

In sintesi: questo è un sacco di lavoro.Se sei interessato, dai un'occhiata alle specifiche del formato PE, che descrive i file .exe e .dll e la funzione VirtualAlloc().

+0

Wow, sembra molto più complicato di quanto pensassi. Hai qualche esperienza con UPX? Funziona anche così? (Non ne so molto degli addetti al confezionamento). Speravo di riuscire a trovare un codice sorgente che dimostri ciò che sarebbe un po 'facile da seguire. –

+0

@guitar: ho appena dato un'occhiata al codice. Lo stub del caricatore è un assemblaggio piuttosto macro pesante, ma sembra che il packer stia eseguendo una pre-elaborazione molto se questo funziona, quindi lo stub può semplicemente decomprimere un file già allineato in memoria e quindi ottenere le importazioni. Questo ovviamente non è sufficiente per il tuo 2 ° e 3 ° esempio. La roba del packer in http://upx.hg.sourceforge.net/hgweb/upx/upx/file/c3853d205747/src/pefile.cpp è più vicina, ma sono sicuro che ci sono altri esempi con casing speciale altrove. –

+0

Questo sembra un buon inizio, sebbene non sia di qualità commerciale. http://code.google.com/p/egodust/source/browse/trunk/pe.c –

1

Bene se si sa dove si trova l'offset del punto di ingresso di un file eseguibile e si conoscono i parametri necessari, è sufficiente richiamare la funzione all'indirizzo "exeBase + entryPointOffset" utilizzando un puntatore di funzione.

Vale la pena notare che i sistemi operativi, almeno sui sistemi x86, tendono a non consentire l'esecuzione di memoria contrassegnata come dati. In Windows, ad esempio, è possibile modificarlo utilizzando la funzione "Virtual ProtectEx" per contrassegnare la memoria come eseguibile.

In effetti, tornando ai bei vecchi tempi, questo era un sistema comune per risparmiare memoria. Avresti "overlays" in modo da poter risparmiare memoria scambiando il codice dentro e fuori a seconda delle necessità.

+0

Potrebbe davvero funzionare? Come si può essere certi che non ci sia un salto verso un indirizzo assoluto all'interno del codice eseguibile (che verrebbe risolto al momento del caricamento)? –

+0

Le correzioni degli indirizzi assoluti sono nei dati EXE. Ecco come funziona la funzione ASLR di Vista. Tuttavia, il caricatore probabilmente sposta il suo codice di bootstrap in modo tale che l'EXE carichi al suo normale indirizzo di base. –

+0

@Hans: Sono abbastanza sicuro che gli exe non (anche se * potrebbero *) includano una sezione di rilocazione poiché l'exe è la prima cosa allocata nello spazio degli indirizzi e quindi non deve mai essere spostata (ASLR è solo per. dll). @ Goz: questo non funzionerà poiché le sezioni nei dati del file non sono allineate alla pagina: vedere le specifiche PE sulla differenza tra offset di file e RVA. –