当前位置: 技术问答>linux和unix
拦截系统调用的几个问题
来源: 互联网 发布时间:2015-01-15
本文导语: 在 Linux 下面如何截获系统调用 用Linux Kernel Module的一般目的就是扩展系统的功能,或者给某些特殊的设备提供驱动等等。其实利用Linux 内核模块我们还可以做一些比较“黑客”的事情,例如用来拦截系统调用,然后自己...
在 Linux 下面如何截获系统调用
用Linux Kernel Module的一般目的就是扩展系统的功能,或者给某些特殊的设备提供驱动等等。其实利用Linux
内核模块我们还可以做一些比较“黑客”的事情,例如用来拦截系统调用,然后自己处理。
下面给出一个简单的例子,说明了其基本的工作过程。
#define MODULE
#define __KERNEL__
#include
#include
#include
#include
#include
#include
#include
#include
#include
extern void* sys_call_table[]; /*sys_call_table is exported, so we can access it*/
int (*orig_mkdir)(const char *path); /*the original systemcall*/
int hacked_mkdir(const char *path)
{
return 0; /*everything is ok, but he new systemcall does nothing*/
}
int init_module(void) /*module setup*/
{
orig_mkdir=sys_call_table[SYS_mkdir];
sys_call_table[SYS_mkdir]=hacked_mkdir;
return 0;
}
void cleanup_module(void) /*module shutdown*/
{
sys_call_table[SYS_mkdir]=orig_mkdir; /*set mkdir syscall to the origal one*/
}
我不明白的地方是,实际上系统调用最终都是通过软中断服务int 0x80来实现的,而程序中只声明一个外部变量extern void* sys_call_table[]就能修改系统调用入口呢?它修改的是不是动态连接库的系统调用,也就是说如果在另外一个程序中使用静态连接库,就不会被拦截了,是吗?我认为更可靠的做法是直接修改int 0x80处的子功能入口地址,我的意思是用sidt指令取得中断描述符表地址,然后。。。。请问我的想法对吗?
|
软中断int 0x80发生时,在6个通用寄存器中已经保存好了关于本次系统调用的参数和系统调用号。然后通过系统调用号在sys_call_table[]中查找相应的系统调用服务例程。通过你上面的程序也可以看出,sys_call_table[]中保留的是系统调用例程的入口地址。所以,不论程序中使用的是静态连接库还是动态链接库,其系统调用的过程是一样的。
另外,通过sitd指令修改中断描述表当然可以,但是没有必要这样做。
另外,通过sitd指令修改中断描述表当然可以,但是没有必要这样做。
|
[bash]$ more /proc/ksyms | grep sys_call_table
c023e13c sys_call_table_Rdfdb18bd
内核中有一个输出符号的功能,内核模块可以不用和内核一起编译即可使用别的模块输出的符号,模块在编译的时候并没有把外部符号比如sys_call_table连接到模块中,而是在加载insmod过程中连接的,即使用符号在内核中的地址来代替符号名,内核中有一个内核符号输出表来保存各个模块、内核输出的符号地址
c023e13c sys_call_table_Rdfdb18bd
内核中有一个输出符号的功能,内核模块可以不用和内核一起编译即可使用别的模块输出的符号,模块在编译的时候并没有把外部符号比如sys_call_table连接到模块中,而是在加载insmod过程中连接的,即使用符号在内核中的地址来代替符号名,内核中有一个内核符号输出表来保存各个模块、内核输出的符号地址