通过可加载内核模块进行系统调用拦截

时间:2014-09-23 16:59:36

标签: c system-calls

为了拦截现有的系统调用,我们必须编写自己的假系统调用,然后让内核调用我们的假退出函数而不是原始的exit函数。为此,我们必须操纵系统调用表数组(sys_call_table)。使用sys_call_table数组,我们可以操纵它以使原始系统调用入口指向我们新的假系统调用。我们必须存储一个指向原始系统调用的指针,并在完成将消息打印到控制台后调用它。 interception.c包含拦截写系统调用的代码。请注意,伪写系统调用会调用原始的写系统调用。

****修改interception.c以计算调用写入系统调用的次数。

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

int counter = 0;

unsigned long **sys_call_table;

asmlinkage long (*ref_sys_write)(unsigned int fd, const char __user *buf, size_t count);

// fake write system call that calls the original write system call
asmlinkage long new_sys_write(unsigned int fd, const char __user *buf, size_t count)
{   

    return ref_sys_write(fd,buf ,count);
}

// this function returns the pointer of 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;
}

// This function disable the memory protection so that you can access any memory address
// This is done by modifying the value of the register cr0
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));
}

// This function enable the memory protection
// This is done by modifying the value of the register cr0
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));
}

// This function is executed when the module is loaded.
// 1. It gets the pointer of system call table
// 2. It disables page protection
// 3. It modifies the entry of the write system call
// 4. It enables page protection
static int __init interceptor_start(void) 
{
    if(!(sys_call_table = aquire_sys_call_table())) {
             return -1;
    }

    disable_page_protection();

    ref_sys_write = (void *)sys_call_table[__NR_write];
    sys_call_table[__NR_write] = (unsigned long *)new_sys_write;

    enable_page_protection();

    return 0;
}

// This method is executed when the module is removed/unloaded
// 1. It disables page protection
// 2. It restores the entry of the write system call
// 3. It enables page protection
static void __exit interceptor_end(void) 
{
    if(!sys_call_table)
        return;
    disable_page_protection();
    sys_call_table[__NR_write] = (unsigned long *)ref_sys_write;
    enable_page_protection();
}

module_init(interceptor_start);
module_exit(interceptor_end);

也许这很容易,但我是系统调用和模块的初学者。 感谢您的帮助。

0 个答案:

没有答案