劫持Linux系统调用
时间:2006-04-30 来源:xiaosuo
由于某些原因,我们可能需要劫持系统调用。联系系统调用的实现,根据劫持地点的不同,主要可以分为三大类:
方法1示例:
方法2示例:
方法3示例:
注意:
因为高于2.4.18的内核已经不再导出符号sys_call_table,所以要想用方法2和3首先需要导出此符号,请看下一篇文章。
- 劫持软中断,也就是int $0x80,让它首先进入我们的控制中,然后做完我们想做的事情之后,再有控制的,让它转入正常例程。
- 改变系统调用表(sys_call_table)中相应系统调用项的函数地址为我们自己定义的函数的地址。
- 通过改变某个系统调用例程(sys_xxx)的前几个字节,让它跳转到我们的例程中。
方法1示例:
#ifndef MODULE #define MODULE #endif #ifndef __KERNEL__ #define __KERNEL__ #endif #include <linux/kernel.h> #include <linux/module.h> #include <linux/unistd.h> static struct { unsigned short limit; unsigned int base; } __attribute__ ((packed)) idtr; static struct { unsigned short offset_low; unsigned short sel; unsigned char none, flags; unsigned short offset_high; } __attribute__ ((packed)) * idt; static unsigned long old_int80_handler; extern void new_int80_handler(void); static void real_int80_handler(void); static unsigned long eax, ebx, ecx, edx, esi, edi; /* * Although the inline asm code is not need to be wrapped by * the function, but if your code has some input or output * parameters, it is necessary. */ static void puppet_handle(void){ __asm__( ".section .text\n" ".align 4\n" "new_int80_handler:\n" "pusha;" "push %%es;" "push %%ds;" "push %%esi;" "push %%edi;" "push %%ebp;" "movl %%eax, %0;" "movl %%ebx, %1;" "movl %%ecx, %2;" "movl %%edx, %3;" "movl %%esi, %4;" "movl %%edi, %5;" "call real_int80_handler;" "popl %%ebp;" "popl %%edi;" "popl %%esi;" "popl %%ds;" "popl %%es;" "popa;" "jmp *old_int80_handler;" "ret;" /* this instruction will not be called */ :"=m"(eax), "=m"(ebx), "=m"(ecx), "=m"(edx), "=m"(esi), "=m"(edi) ); } static void real_int80_handler(void) { if(eax == __NR_mkdir){ printk("sys_mkdir is called by UID = %d PID = %d.\n", current->uid, current->pid); } } int init_module(void) { printk("store the new_int80_handler.\n"); __asm__("sidt %0":"=m"(idtr)); idt = (void *) (idtr.base + 8 * 0x80); old_int80_handler = (idt->offset_high << 16) | idt->offset_low; idt->offset_high = (unsigned long)new_int80_handler >> 16; idt->offset_low = (unsigned long)new_int80_handler & 0xffff; return 0; } void cleanup_module(void) { printk("restore the old_int80_handler.\n"); __asm__("sidt %0":"=m"(idtr)); idt = (void*)(idtr.base + 8 * 0x80); idt->offset_high = old_int80_handler >> 16; idt->offset_low = old_int80_handler & 0xffff; } |
#ifndef __KERNEL__ #define __KERNEL__ #endif #ifndef MODULE #define MODULE #endif #include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/unistd.h> #include <linux/linkage.h> #include <linux/syscalls.h> #include <asm/current.h> extern void* sys_call_table[]; /* * After version 2.4.18, the symbol sys_call_table is not exported, * but you can get the address from the file System.map, Just like * this `grep sys_call_table /boot/System.map'. */ //void** sys_call_table = (void **)0xc03835c0; asmlinkage long (*orig_mkdir)(const char *path, int mode); asmlinkage long hacked_mkdir(const char *path, int mode) { printk("sys_mkdir(%s, %d) is called by (uid = %d, pid = %d)\n", path, mode, current->uid, current->pid); return orig_mkdir(path, mode); } int init_module(void) { orig_mkdir=sys_call_table[__NR_mkdir]; sys_call_table[__NR_mkdir]=hacked_mkdir; return 0; } void cleanup_module(void) { sys_call_table[__NR_mkdir]=orig_mkdir; } |
#include <linux/config.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/version.h> #include <linux/utsname.h> #include <linux/string.h> #include <asm/string.h> #include <asm/unistd.h> #include <asm/linkage.h> #define SYSCALL_NR __NR_mkdir static char syscall_code[7]; static char new_syscall_code[7] = "\xbd\x00\x00\x00\x00" /* movl $0,%ebp */ "\xff\xe5" /* jmp *%ebp */ ; // void **sys_call_table = (void**)0xc03835c0; extern void *sys_call_table[]; // NOTE: DO _NOT_ forget the macro asmlinkage // If you lose the macro, the segment fault // will be occered. asmlinkage long (*orig_mkdir) (const char *, int); void *_memcpy(void *dest, const void *src, int size) { const char *p = src; char *q = dest; int i; for (i = 0; i < size; i++) *q++ = *p++; return dest; } asmlinkage long hacked_mkdir(const char *name, int mode) { long ret; _memcpy(orig_mkdir, syscall_code, sizeof(syscall_code)); printk("hacked sys_mkdir(%s, %d)\n", name, mode); ret = orig_mkdir(name, mode); _memcpy(orig_mkdir, new_syscall_code, sizeof(syscall_code)); return ret; } int init_module(void) { *(long *)&new_syscall_code[1] = (long)hacked_mkdir; orig_mkdir = sys_call_table[SYSCALL_NR]; _memcpy(syscall_code, orig_mkdir, sizeof(syscall_code)); _memcpy(orig_mkdir, new_syscall_code, sizeof(syscall_code)); return 0; } void cleanup_module(void) { _memcpy(orig_mkdir, syscall_code, sizeof(syscall_code)); } |
因为高于2.4.18的内核已经不再导出符号sys_call_table,所以要想用方法2和3首先需要导出此符号,请看下一篇文章。
相关阅读 更多 +