• Non ci sono risultati.

Per intercettare le chiamate invocate dal processo P, in esecuzione sulla Mon- VM, `e stata adottata una soluzione di tipo kernel-based, modificando il si- stema operativo della macchina tramite un modulo del kernel che effettua l’interposizione tra le invocazioni ed il codice del kernel. HiMod (Hijacking

Module) `e il componente sviluppato per compiere questa operazione. Il tipo

di soluzione basata su modifiche al kernel del sistema guest `e stata preferi- ta all’uso della chiamata ptrace principalmente per la maggiore flessibilit`a nella selezione e nella gestione delle chiamate da intercettare ed anche per la trasparenza dell’operazione di tracciamento, importante per la sicurezza del sistema.

7.2.1

Descrizione e funzionamento

La prima operazione effettuata da HiMod al caricamento in memoria `e l’hi-

jacking della system call table, operazione necessaria per poter effettuare il

tracciamento delle invocazioni. Successivamente, HiMod alloca una pagina di memoria in spazio kernel per il passaggio dei parametri alla parte di controllo. Inoltre, crea l’interfaccia di comunicazione con la parte di controllo e pubblica i parametri, numero di canale ed indirizzo della pagina, tramite l’interfaccia di XenStore.

Per la scrittura del modulo, si `e scelto il linguaggio C, che permette una migliore integrazione con le componenti del sistema operativo, in particolare per l’accesso alla system call table, dato che il kernel Linux `e scritto quasi interamente in C.

L’hijacking della system call table che avviene durante l’inizializzazione del modulo pu`o essere implementato in vari modi [22]:

a. reindirizzando i singoli puntatori a system call (Figura 7.2 a);

b. reindirizzando il puntatore all’intera system call table (Figura 7.2 b); c. sovrascrivendo il codice delle system call (Figura 7.2 c).

Nel primo caso, si modifica l’indirizzo di una chiamata nella system call table del sistema, sostituendolo con quello della nuova chiamata. Nel secondo caso, si modifica il puntatore alla system call table all’interno della IDT, all’indi- rizzo 0x80, reindirizzandolo su una nuova system call table che contiene gli indirizzi delle nuove chiamate. Infine, nel terzo caso, si sovrascrive il codi- ce di ogni singola chiamata di sistema direttamente in memoria, quindi le strutture ed i puntatori del sistema operativo rimangono inalterati.

HiMod implementa il primo dei metodi di hijacking presentati, ridichia- rando le nuove system call e reindirizzando i puntatori alle chiamate nella system call table. Ad ogni chiamata `e aggiunto del codice per implementare la copia dei parametri e la comunicazione con il lato di controllo dell’archi- tettura. La chiamata di sistema originale viene invocata dal modulo dopo aver effettuato la comunicazione con l’Analyst, in caso di esito positivo dei controlli. In questo modo, una volta individuato un comportamento non le- gale di P, l’esecuzione pu`o essere bloccata prima che la sicurezza del sistema sia compromessa.

L’indirizzo della system call table del sistema, necessario per effettuare l’hijacking, viene letto dal file System.map. Al momento della rimozione del modulo dalla memoria, sono ripristinate le entrate originali della system call table. Per questo motivo, nel codice viene mantenuta una copia degli indirizzi originali delle chiamate reindirizzate. Il modulo, al caricamento, prende come parametro il pid del processo monitorato, ad esempio:

7.2.2

Moduli del kernel

Questo paragrafo presenta i moduli del kernel Linux, la loro organizzazione nel sistema e gli strumenti disponibili per la loro gestione.

Il kernel Linux `e modulare, poich´e permette l’inserimento e la rimozione di codice dal kernel a tempo di esecuzione. Funzioni, variabili e indirizzi vengono raggruppati in un’unica immagine binaria, caricabile dal kernel detta

modulo. L’implementazione di un modulo deve rispettare alcune regole per

garantire la compatibilit`a con il sistema, infatti, devono essere definite una serie di funzioni [32]:

• module init: `e la funzione di inizializzazione eseguita al caricamento

del modulo, tipicamente `e usata per inizializzare le variabili ed allocare le strutture utilizzate dal modulo;

• module exit: analoga alla funzione precedente ma definisce l’exit point

del modulo, eseguito al momento della rimozione dal kernel. Essa viene tipicamente utilizzata per liberare quanto allocato dal modulo durante l’esecuzione;

• MODULE LICENSE: questa macro definisce il tipo di licenza del modulo.

La scelta della licenza `e importante, dato che moduli non-GPL non possono invocare simboli dichiarati con licenza GPL;

• MODULE AUTHOR: questa macro specifica l’autore del codice, quindi `e

usata unicamente per scopi informativi.

Passaggio di parametri

Il kernel Linux permette di specificare il valore di alcune variabili in fase di ca- ricamento del modulo. A questo scopo si utilizza la macro module param(),

che permette di dichiarare i parametri del modulo a cui vengono assegnati i valori trasmessi dall’utente. La macro ha tre parametri:

• name: il nome della variabile, sia internamente al modulo che esterna-

mente;

• type: il tipo del parametro definito;

• perm: i permessi sul parametro, possono essere definiti in forma ottale

oppure usando specifiche macro.

Inoltre, altre macro definite dal kernel permettono di specificare parametri con nomi diversi internamente ed esternamente dal modulo, ed `e possibile trasmettere come parametri array o stringhe.

Compilazione ed installazione

La compilazione di un modulo pu`o utilizzare due strategie principali perch´e il modulo pu`o essere inserito come parte del kernel oppure mantenuto come componente esterna. Nel caso di aggiunta del modulo al source tree del kernel, sono necessari tre passi:

a. scelta del path dove aggiungere il modulo. Di solito si usa suddividere il codice in categorie il pi`u precise possibile;

b. modifica del Makefile del path scelto per il modulo; c. aggiunta del nuovo Makefile per il modulo aggiunto.

Se un modulo `e mantenuto come componente esterna, `e necessario solo l’ultimo passo.

Il nuovo modulo creato verr`a compilato ed installato insieme al kernel tramite il comando make. L’estensione dei moduli compilati `e .ko, anche se nei Makefile occorre indicare .o.

Documenti correlati