最刺激的添加内核系统调用的方法就是hack sys_call_table 了 ^_^
它的基本思想就是
1 找到 sys_call_table 的地址;
2 保存其中某项内容,比如 sys_call_table[__NR_mkdir] 以便hack后恢复; 3 修改 sys_call_table[__NR_mkdir] 使其指向自己实现的系统调用函数这样做之后,系统调用mkdir就被你hack了 呵呵 是不是很爽
来来来 咱们实现一下代码
hack_sys_call.c#include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> #include <linux/sched.h> #include <asm/unistd.h>
MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Different from others, this module automatically locate the entry of sys_call_table !");
unsigned long *sys_call_table=NULL; asmlinkage int (*orig_mkdir)(const char *,int);
struct _idt { unsigned short offset_low; unsigned short segment_sel; unsigned char reserved; unsigned char flags; unsigned short offset_high; };
unsigned long *getscTable() { unsigned char idtr[6],*shell,*sort; struct _idt *idt; unsigned long system_call,sct; unsigned short offset_low,offset_high; char *p; int i; /* get the interrupt descriptor table */ __asm__("sidt %0" : "=m" (idtr)); /* get the address of system_call */ idt=(struct _idt*)(*(unsigned long*)&idtr[2]+8*0x80); offset_low = idt->offset_low; offset_high = idt->offset_high; system_call=(offset_high<<16)|offset_low; shell=(char *)system_call; sort="/xff/x14/x85"; /* get the address of sys_call_table */ for(i=0;i<(100-2);i++) if(shell[i]==sort[0]&&shell[i+1]==sort[1]&&shell[i+2]==sort[2]) break;
p=&shell[i]; p+=3; sct=*(unsigned long*)p; return (unsigned long*)(sct); }
asmlinkage int hacked_mkdir(const char * pathname, int mode) { printk("PID %d called sys_mkdir !/n",current->pid); return orig_mkdir(pathname,mode); }
static int __init find_init(void) { sys_call_table = getscTable(); orig_mkdir=(int(*)(const char*,int))sys_call_table[__NR_mkdir]; sys_call_table[__NR_mkdir]=(unsigned long)hacked_mkdir; return 0; }
static void __exit find_cleanup(void) { sys_call_table[__NR_mkdir]=(unsigned long)orig_mkdir; }
module_init(find_init); module_exit(find_cleanup);
MakefileCC=gcc INCLUDEDIR = /usr/src/linux-2.4/include MODCFLAGS :=-Wall -O -DMODULE -D__KERNEL__ -DLINUX -I$(INCLUDEDIR) hack_sys_call.o: hack_sys_call.c $(CC) $(MODCFLAGS) -c hack_sys_call.c
getscTable()是在内存中查找sys_call_table地址的函数。 每一个系统调用都是通过int 0x80中断进入核心,中断描 述符表把中断服务程序和中断向量对应起来。对于系统调 用来说,操作系统会调用system_call中断服务程序。 system_call函数在系统调用表中根据系统调用号找到并 调用相应的系统调用服务例程。idtr寄存器指向中断描述 符表的起始地址,用sidt[asm ("sidt %0" : "=m" (idtr));] 指令得到中断描述符表起始地址,从这条指令中得到的指针 可以获得int 0x80中断服描述符所在位置,然后计算出 system_call函数的地址。反编译一下system_call函数可以 看到在system_call函数内,是用call sys_call_table指令 来调用系统调用函数的。因此,只要找到system_call里 的call sys_call_table(,eax,4)指令的机器指令就可以获得 系统调用表的入口地址了 在2.4和2.6之前的内核中,sys_call_table是可以直接导出的 挺危险的 ^_^