x86中系统调用表中的exchange函数

x86中系统调用表中的exchange函数,c,linux-kernel,kernel,system-calls,rootkit,C,Linux Kernel,Kernel,System Calls,Rootkit,我试图重新定义sys_open的systemcall,并用它跟踪用户行为。 我使用Linux内核4.13.0-041300。 这是到目前为止我的代码 #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/syscalls.h> MODULE_LICENSE ("GPL"); //this is where the o

我试图重新定义sys_open的systemcall,并用它跟踪用户行为。 我使用Linux内核4.13.0-041300。 这是到目前为止我的代码

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/syscalls.h>

MODULE_LICENSE ("GPL");

//this is where the original sys_open call position will be saved
asmlinkage long (*original_open)(const char __user *filename, int flags, umode_t mode);

unsigned long **sys_call_table;
//this is to track how often my replaced function was called...
static int zeug = 0;

//this is my open function that i want to be replaced in the sys_call_table
asmlinkage long replaced_open(const char __user *filename, int flags, umode_t mode)
{
    printk ("replaced wurde aufgerufen...\n");
    zeug++;
    return original_open(filename, flags, mode);
}

static void enable_page_protection(void)
{
    unsigned long value;
    asm volatile("mov %%cr0, %0" : "=r" (value));

    if((value & 0x00010000))
        return;

    asm volatile("mov %0, %%cr0" : : "r" (value | 0x00010000));
}

static void disable_page_protection(void)
{
    unsigned long value;
    asm volatile("mov %%cr0, %0" : "=r" (value));

    if(!(value & 0x00010000))
        return;

    asm volatile("mov %0, %%cr0" : : "r" (value & ~0x00010000));
}

//the function to get the system_call_table
static unsigned long **aquire_sys_call_table(void)
{
    unsigned long int offset = PAGE_OFFSET;
    unsigned long **sct;

    while (offset < ULLONG_MAX) {
        sct = (unsigned long **)offset;

        if (sct[__NR_close] == (unsigned long *) sys_close)
            return sct;

        offset += sizeof(void *);
    }

    return NULL;
}

static int __init minit (void)
{
    printk ("minit: startet...\n");

    if(!(sys_call_table = aquire_sys_call_table()))
            return -1;

    printk ("minit: sys_call_table ersetzt...\n");

    disable_page_protection(); 
    {
        //here i print the function name of the current function in sys_call_table
        printk ("minit: eintrag vor ersetzen:%pF\n", sys_call_table[__NR_open]);

        //here i store the real sys_open function and change to my func
        original_open =(void * )xchg(&sys_call_table[__NR_open],(unsigned long *)replaced_open);

}
    enable_page_protection();
    return 0;
}

static void mexit (void)
{
    printk ("mexit gestartet.\n");
    printk ("Open was called %d times...\n",zeug);
    if(!sys_call_table) return;

    //here i print the stored function again
    printk ("bei exit:%pF\n", sys_call_table[__NR_open]);

    disable_page_protection();
    {
            //change back to original sys_open function
            xchg(&sys_call_table[__NR_open], (unsigned long *)original_open);
    }
    printk ("nach zurücksetzen:%pF\n", sys_call_table[__NR_open]);
    enable_page_protection();
}

module_init(minit);
module_exit(mexit);
#包括
#包括
#包括
#包括
模块许可证(“GPL”);
//这是原始系统打开呼叫位置的保存位置
asmlong(*original_open)(常量字符用户*文件名、int标志、umode_t模式);
无符号长**系统调用表;
//这是为了跟踪我被替换的函数被调用的频率。。。
静态int-zeug=0;
//这是我想要在sys\u call\u表中替换的open函数
ASMLINK long replaced_open(常量字符_用户*文件名、整型标志、umode_t模式)
{
printk(“替换为wurde aufgerufen…\n”);
zeug++;
返回原始打开状态(文件名、标志、模式);
}
静态无效启用页面保护(无效)
{
无符号长值;
asm易失性(“mov%%cr0,%0”:“=r”(值));
如果((值&0x00010000))
返回;
asm易失性(“mov%0,%%cr0”::“r”(值| 0x00010000));
}
静态无效禁用页面保护(无效)
{
无符号长值;
asm易失性(“mov%%cr0,%0”:“=r”(值));
如果(!(值&0x00010000))
返回;
asm易失性(“mov%0,%%cr0”::“r”(值&~0x00010000));
}
//获取系统调用表的函数
静态无符号长**获取系统调用表(无效)
{
无符号长整型偏移量=页码偏移量;
无符号长**sct;
同时(偏移量
我的计划: 将此模块insmod到内核后,sys\u open的每个系统调用都将“重定向”到my function replacement\u open。此函数将对其调用进行计数,然后调用原始的open函数

模块rmmod后,将再次使用原始系统调用open

看来,这种替换是可行的。所以在insmmod之后,我得到的结果被替换为open+0x0/0x40[kroot]。 也就是说,原来的函数sys_open被替换为my replaced_open,对吗? 移除模块后,我得到消息SyS_open+0x0/0x20

所以这看起来像是在替换作品

我的问题是:我看不到我的打开函数中的任何打印消息。而且似乎计数也不起作用

感觉该功能没有被正确替换


你能帮我什么忙吗?

你可能应该研究一下如何使用钩子。它的设计目的正是为了实现这一点,尽管出于安全目的,比如像SELinux那样为系统调用添加额外的检查。您需要解决的另一个问题是:内核系统调用需要是多线程安全的。你的增量
zeug++不是原子的-它实际上是“读取值,为值添加1,保存值”。这只会导致代码中的计数不正确,但对于像
inode
reference counts这样的关键值,它可能会导致严重的问题。您是否成功地找到了syscall表?这似乎是最有可能失败的。您看过这个问题了吗:也许您应该仔细检查一下,您确实找到了syscall表,例如通过检查
sys\u close
sys\u fork
等。当我运行printk(“bei exit:%pF\n”,sys\u call\u table[\uu NR\u open])时,结果是sys open+0x0/0x20。所以我认为这应该是正确的。在更改任何内容之前运行此操作时,我会得到相同的结果。sys\u fork和sys\u open等都是未知的。我只能在sys_close的情况下检查sct。您可能应该研究如何使用挂钩。它的设计目的正是为了实现这一点,尽管出于安全目的,比如像SELinux那样为系统调用添加额外的检查。您需要解决的另一个问题是:内核系统调用需要是多线程安全的。你的增量
zeug++不是原子的-它实际上是“读取值,为值添加1,保存值”。这只会导致代码中的计数不正确,但对于像
inode
reference counts这样的关键值,它可能会导致严重的问题。您是否成功地找到了syscall表?这似乎是最有可能失败的。您看过这个问题了吗:也许您应该仔细检查一下,您确实找到了syscall表,例如通过检查
sys\u close
sys\u fork
等。当我运行printk(“bei exit:%pF\n”,sys\u call\u table[\uu NR\u open])时,结果是sys open+0x0/0x20。所以我认为这应该是正确的。在更改任何内容之前运行此操作时,我会得到相同的结果。sys\u fork和sys\u open等都是未知的。我只能在系统关闭时检查sct。