截獲linux系統調用

方法1:修改系統調用表(適用於linux-2.4內核)node

內核使用sys_call_table數組來存儲系統調用表,將系統調用號與系統調用處理函數對應起來,經過修改sys_call_table數組的某一個元素,便可實現截獲系統調用的功能,在2.4內核中,sys_call_table符號是被導出的,外部模塊能夠使用,故能簡單的實現截獲系統調用,在加載模塊時,修改sys_call_table的處理函數,並保存其原來的值,在卸載模塊時,還原其處理函數。linux

在2.6內核中,因爲sys_call_table符號不可見,網上有介紹在內存中查找sys_call_table地址的方法,不過比較複雜,還沒有弄清其原理。數組

方法2:經過修改VFS操做表函數

該方法只能截獲vfs相關的系統調用,經過修改file_operations,inode_operations的成員操做函數來實現,代碼以下所示:內存

#include <linux/sched.h>it

#include <linux/module.h>io

#include <linux/kernel.h>編譯

#include <linux/init.h>table

#include <linux/fs.h>變量

#include <linux/file.h>


MODULE_LICENSE("GPL");


char *root_fs="/";


typedef int (*readdir_t)(struct file *,void *,filldir_t);

readdir_t orig_root_readdir=NULL;


int myreaddir(struct file *fp,void *buf,filldir_t filldir)

{

       int r;

       printk("<1>You got me partner!\n");

       r=orig_root_readdir(fp,buf,filldir);

       return r;

}


int patch_vfs(const char *p,readdir_t *orig_readdir,readdir_t new_readdir)

{

       struct file *filep;

       filep=filp_open(p,O_RDONLY,0);

       if(IS_ERR(filep))

            return -1;

       if(orig_readdir)

            *orig_readdir=filep->f_op->readdir;


       filep->f_op->readdir=new_readdir;

       struct file_operations *fop = filep->f_op;

       fop->readdir = new_readdir;

       filep->f_op = fop;

       filp_close(filep,0);

       return 0;

}


int unpatch_vfs(const char *p,readdir_t orig_readdir)

{

       struct file *filep;

       filep=filp_open(p,O_RDONLY,0);

       if(IS_ERR(filep))

            return -1;

       filep->f_op->readdir=orig_readdir;

       struct file_operations *fop = filep->f_op;

       fop->readdir = orig_readdir;

       filep->f_op = fop;

       filp_close(filep,0);

       return 0;

}


static int patch_init(void)

{

       patch_vfs(root_fs,&orig_root_readdir,myreaddir);

       printk("<1>VFS is patched!\n");

       return 0;

}

static void patch_cleanup(void)

{

       unpatch_vfs(root_fs,orig_root_readdir);

       printk("<1>VFS is unpatched!\n");

}

module_init(patch_init);

module_exit(patch_cleanup);


以上模塊在linux-2.6.19內核上編譯不能經過,提示錯誤消息爲:readdir成員爲只讀的,不能對其賦值(紅色部分)。因而,我引入一箇中間變量,來達到修改操做表的目的(將紅色部分修改成藍色部分)。

相關文章
相關標籤/搜索