|
|
|
![]() |
|
Strumenti |
![]() |
#1 |
Senior Member
Iscritto dal: May 2001
Messaggi: 12822
|
[Linux - C] Intercettare chiamate di sistema
Ok, come da titolo, a scopo didattico vorrei intercettare le chiamate di sistema (ad esempio sys_open che consente l'apertura di un file).
L'idea è quella di usare un Linux Kernel Module e sostituire la voce corrispondente della sys_call_table con la mia nuova funzione. Tuttavia facendo così il modulo mi crasha, presumo che ci sia una qualche protezione che impedisce la modifica della sys_call_table. Ho cercato a lungo su Google, ma tutti gli esempi conducono a questo risultato. Per altro a quanto ho letto dal kernel 2.6 in poi non è più esportata la sys_call_table, quindi ho dovuto leggere il valore della locazione di memoria dal file System.map. Questo è il codice: Codice:
#include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/syscalls.h> unsigned long* sys_call_table = (unsigned long*)0xc0592150; asmlinkage long (*def_sys_open)(const char *filename, int flags, int mode); asmlinkage long mod_sys_open(const char *filename, int flags, int mode) { printk(KERN_INFO "[HELLO MODULE] Intercepted system call! Filename: %s\n", filename); return def_sys_open(filename, flags, mode); } static int __init hello(void) { printk(KERN_INFO "[HELLO MODULE] Init, sys_call_table open @ %lx\n", sys_call_table[__NR_open]); def_sys_open = (void*)sys_call_table[__NR_open]; printk(KERN_INFO "[HELLO MODULE] default_sys_open @ %lx\n", (unsigned long)def_sys_open); printk(KERN_INFO "[HELLO MODULE] mod_sys_open @ %lx\n", (unsigned long)mod_sys_open); sys_call_table[__NR_open] = (unsigned long)mod_sys_open; // default_sys_open =(void * )xchg(&sys_call_table[__NR_open], mod_sys_open); return 0; } static void __exit bye(void) { sys_call_table[__NR_open] = (unsigned long)def_sys_open; printk(KERN_INFO "[HELLO MODULE] Goodbye world.\n"); } module_init(hello); module_exit(bye); ![]() Edit: fantastico ho appena scoperto che la sys_call_table è diventata read-only... trovato su un forum nascosto nei meandri della rete... :-( a questo punto? Ultima modifica di WarDuck : 03-05-2010 alle 18:40. |
![]() |
![]() |
![]() |
#2 |
Senior Member
Iscritto dal: Oct 2005
Messaggi: 3306
|
Usare LD_PRELOAD?
|
![]() |
![]() |
![]() |
#3 |
Senior Member
Iscritto dal: Nov 2002
Messaggi: 5845
|
Probabilmente il comando strace fa al caso tuo:
strace <tuoprogramma> |
![]() |
![]() |
![]() |
#4 |
Senior Member
Iscritto dal: Jun 2002
Città: Dublin
Messaggi: 5989
|
Personalmente non me ne intendo così tanto, ma so che nella mia università è stato portato avanti un progetto che usa una tecnica simile. I sorgenti li si può leggere, quindi ti linko:
ciao ![]() EDIT: la parte "interessante" è /module/remus_intercept.c.
__________________
C'ho certi cazzi Mafa' che manco tu che sei pratica li hai visti mai! Ultima modifica di DanieleC88 : 04-05-2010 alle 10:51. |
![]() |
![]() |
![]() |
#5 | |
Senior Member
Iscritto dal: Jun 2002
Città: Dublin
Messaggi: 5989
|
Quote:
Anzi: questo tipo risolve il problema patchando il kernel... http://kerneltrap.org/node/16668 L'alternativa sarebbe una libreria+LD_PRELOAD, ma non funzionerebbe sui programmi compilati staticamente.
__________________
C'ho certi cazzi Mafa' che manco tu che sei pratica li hai visti mai! |
|
![]() |
![]() |
![]() |
#6 |
Senior Member
Iscritto dal: May 2001
Messaggi: 12822
|
Innanzitutto grazie per le risposte, gli ho dato uno sguardo veloce:
@tommino: appena ho tempo provo, ma se come ho letto è una environment variabile credo che sarebbe abbastanza facile eludere l'hook. Quello che vorrei fare è limitare di default l'azione degli eseguibili sul file system, possibilmente rendendo difficile la vita a chi vorrebbe agirare il sistema ![]() @unrue: strace dovrebbe servire a vedere quali chiamate di sistema usa un dato eseguibile, un comando molto utile ma purtroppo non aiuta a risolvere il problema (che in questo caso è intercettare le chiamate e "modificare" il loro comportamento). @daniele: anche qui da quanto vedo si basa tutto sul kernel 2.4, purtroppo dal kernel 2.6 (in particolare le ultime versioni) molti trucchi non funzionano più. Ho comunque continuato a cercare e ho letto che sarebbe possibile modificare la page table in maniera tale da rendere scrivibile l'area di memoria della sys_call_table (che di default è read-only). In questo caso si potrebbe rendere l'area rw, modificare la tabella e rimetterla read-only. Ci sono cmq modi di agire a più basso livello (tipo intercettare direttamente l'interrupt e modificare i registri relativi), ma prima dovrei studiarmi l'assembly intel ![]() Grazie a tutti per le risposte, appena ho un po' di tempo rileggo tutto con calma. |
![]() |
![]() |
![]() |
#7 | |
Senior Member
Iscritto dal: Nov 2001
Città: Bastia Umbra (PG)
Messaggi: 6394
|
Non mi intendo in profondità di Linux, ma in Windows la modifica del System Service Descriptor Table (conosciuto anche come KiServiceTable) - che è esattamente quello che vuoi fare tu su linux - richiede la disabilitazione del flag Write Protect al fine di poter scrivere in zone di memoria del kernel marcate come read only.
Il flag Write Protect è il bit 16 del registro CR0 (uno dei Control Register) nella CPU x86. Quote:
Un codice simile è spesso utilizzato per modificare la KiServiceTable in Windows: Codice:
cli mov eax,cr0 and eax,0xFFFEFFFF mov cr0,eax sti Codice:
cli mov eax,cr0 or eax,10000h mov cr0,eax sti ![]()
__________________
:: Il miglior argomento contro la democrazia è una conversazione di cinque minuti con l'elettore medio :: Ultima modifica di eraser : 04-05-2010 alle 12:11. |
|
![]() |
![]() |
![]() |
#8 |
Senior Member
Iscritto dal: Nov 2001
Città: Bastia Umbra (PG)
Messaggi: 6394
|
Ovviamente, ma questo era scontato, il codice sopra evidenziato deve essere eseguito con privilegi equivalenti o maggiori del codice necessario per interagire con il kernel e i registri della CPU.
(Nel caso in questione, in Windows, il codice deve essere eseguito almeno in ring 0)
__________________
:: Il miglior argomento contro la democrazia è una conversazione di cinque minuti con l'elettore medio :: |
![]() |
![]() |
![]() |
#9 | |
Senior Member
Iscritto dal: Dec 2005
Città: Istanbul
Messaggi: 1817
|
Quote:
__________________
One of the conclusions that we reached was that the "object" need not be a primitive notion in a programming language; one can build objects and their behaviour from little more than assignable value cells and good old lambda expressions. —Guy Steele |
|
![]() |
![]() |
![]() |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 05:33.