/* sequestra.c * * Kernel module que intercepta uma chamada de sistema (system call) * * Para compreender melhor este modulo voce precisa ter uma rapida visao * de como funciona system calls no linux. * No linux as system calls sao chamadas executando a instrucao em assembler * int $0x80, o qual e uma execucao programada (interrupcao de software) * Como o kernel implementa muitas system calls, o processo deve passar * um parametro chamado "system call number" para identificar a system * call desejada. O registrador eax e usado para este proposito. * Assim o kernel usa um numero para identificar cada system call. Em ordem * de associar cada numero com cada system call o kernel usa uma * "system call dispatch table". Esta tabela e armazenada * no vetor sys_call_table, e tem NR_syscalls entrada (normalmente 256). * Mas nem todas as entradas sao definidas. * NR_syscalls e o limite estatico do numero maximo de system calls implemetaveis. * Isto nao indica que o numero atual de system calls implementada seja este. * As entradas na sys_call_table que nao contem uma system call associada, contem * sys_ni_syscall, que e uma funcao que retorna o erro -ENOSYS * Deste modo a entrada numero n na sys_call_table contem o endereco da rotina da * system call tendo como numero n. * * Para mais detalhes de uma olhada nestes arquivos : * * /usr/src/linux/arch/i386/kernel/entry.S * /usr/src/linux/include/asm-i386/unistd.h * /usr/src/linux/include/linux/sys.h * * Qualquer duvida, sugestao, ou algum erro: mail thobias@cos.ufrj.br * 19/10/2001 */ #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> #include <linux/unistd.h> #include <linux/sched.h> asmlinkage int (*original_call)(const char *, int, int); asmlinkage int my_sys_open(const char *filename, int flags, int mode) { int ret; MOD_INC_USE_COUNT; /* Tenha cuidado ou seu systema sera inundado de msgs * Um programa de usuário chama esta syscall muitas vezes em uma execução * rode strace <programa> <argumentos> para ver quais syscall um determinado programa chama * Para mais detalhes man strace */ // Use algum tipo de filtro aqui if ( current->gid == 500) printk(KERN_ALERT "Call the syscall open gid=500 \n"); // chama a sys_open original, senão seu sistema nao conseguira abrir nenhum arquivo ret = original_call(filename, flags, mode); MOD_DEC_USE_COUNT; return ret; } int seq_init_module(void) { extern long sys_call_table[]; printk(KERN_ALERT "Hello !\n"); /* * Salva o endereco da rotina original da chamada sys_open * __NR_open e o index na syscall table * lista completa em /usr/src/linux/include/asm-i386/unistd.h */ original_call = (int (*)(const char *, int, int))(sys_call_table[__NR_open]); /* * Subistitui a entrada da syscall table para o nosso codigo */ sys_call_table[__NR_open] = (unsigned long)my_sys_open; printk(KERN_ALERT "syscall sys_open interceptada \n"); return 0; } void seq_cleanup_module(void) { extern long sys_call_table[]; printk(KERN_ALERT "Goodbye !\n"); /* * retorna o endereco original */ sys_call_table[__NR_open] = (unsigned long)original_call; printk(KERN_ALERT "sys_open voltou\n"); } module_init(seq_init_module); module_exit(seq_cleanup_module); MODULE_DESCRIPTION("Exemplo de como interceptar uma system call"); MODULE_AUTHOR("Thobias Salazar Trevisan"); MODULE_LICENSE("GPL"); EXPORT_NO_SYMBOLS;