【问题标题】:System call interception in linux-kernel module (kernel 3.5)linux-kernel模块中的系统调用拦截(内核3.5)
【发布时间】:2012-12-02 07:38:10
【问题描述】:

我需要用我自己的实现替换标准系统调用(例如 SYS_mkdir)。

正如我在一些资料中看到的,包括 Stackoverflow 上的 this question,自内核版本 2.6 以来,sys_call_table 未导出符号。

我尝试了以下代码:

    #include <linux/module.h> 
    #include <linux/kernel.h> 
    #include <linux/unistd.h> 
    #include <asm/syscall.h> 

    int (*orig_mkdir)(const char *path); 

    ....

    int init_module(void) 
    { 
            orig_mkdir=sys_call_table[__NR_mkdir]; 
            sys_call_table[__NR_mkdir]=own_mkdir;  
            printk("sys_mkdir replaced\n"); 
            return(0); 
    } 

    ....

很遗憾我收到编译器错误:

 error: assignment of read-only location ‘sys_call_table[83]’

如何替换系统调用?

编辑:有没有不打内核补丁的解决方案?

【问题讨论】:

  • 尝试将类型转换为 char* 然后分配
  • 可能是thisthis对你有帮助
  • 没有不打补丁的通用解决方案。

标签: c module linux-kernel kernel-module


【解决方案1】:

这对我有用。

Linux Kernel: System call hooking examplehttps://bbs.archlinux.org/viewtopic.php?id=139406

asmlinkage long (*ref_sys_open)(const char __user *filename, int flags, umode_t mode);
asmlinkage long new_sys_open(const char __user *filename, int flags, umode_t mode)
{
  return ref_sys_open(filename, flags, mode);
}

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 *);
  }
  print("Getting syscall table failed. :(");
  return NULL;
}


// Crazy copypasted asm stuff. Could use linux function as well...
// but this works and will work in the future they say.
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));
}

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 int __init rootkit_start(void) 
{

  //Hide me

  print("loaded");

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

  disable_page_protection(); 
  {
    ref_sys_open = (void *)sys_call_table[__NR_open];
    sys_call_table[__NR_open] = (unsigned long *)new_sys_open;
  }
  enable_page_protection();
  return 0;
}

static void __exit rootkit_end(void) 
{
  print("exiting");

  if(!sys_call_table) {
    return;
  }

  disable_page_protection();
  {
    sys_call_table[__NR_open] = (unsigned long *)ref_sys_open;
  }
  enable_page_protection();
}

【讨论】:

    【解决方案2】:

    是的,有一个无需修补/重建内核的解决方案。使用Kprobes 基础架构(或 SystemTap)。

    这将允许您使用内核模块在内核中的任何点放置“探针”(函数)。

    现在可以防止通过修改 sys_call_table 来做类似的事情(它是只读的)并且被认为是一种肮脏的黑客攻击! Kprobes/Jprobes/etc 是一种“干净”的方式。此外,内核源代码树中提供的文档和samples 非常好(查看内核源代码树下的Documentation/kprobes.txt)。

    【讨论】:

    • kprobes/systemtap 不会让您替换系统调用处理程序,但可以补充它/在它之前。
    • 嘿,kprobes 使用补丁 :)
    • @fche:是的,我同意。关键是效果是相似的。。@IlyaMatveychikov:AFAIK,不,kprobes 是一个内核特性;你不需要应用任何补丁。此外,大多数发行版都启用了 kprobes..
    【解决方案3】:

    问题是由于 sys_call_table 是只读的。为了避免该错误,在操作 sys_call_table 之前,您还必须使其可写。内核提供了一个函数来实现它。该函数以 set_mem_rw() 的形式给出。

    只需在操作 sys_call_table 之前添加以下代码 sn-p

    set_mem_rw((long unsigned int)sys_call_table,1);
    

    在内核模块的退出函数中,请不要忘记将sys_call_table恢复为只读。可以如下实现。

    set_mem_ro((long unsigned int)sys_call_table,1);    
    

    【讨论】:

      【解决方案4】:

      首先,您需要确定 sys_call_table 的位置。见here

      在写入刚刚定位的系统表之前,您必须使其内存页可写。检查here,如果这不起作用,请尝试this

      【讨论】:

        【解决方案5】:

        使用 LSM 基础架构。

        查看 LSM 挂钩 path_mkdirinode_mkdir 了解详情。需要解决的一个问题是如何在系统不允许的情况下注册自己的 LSM 模块。在此处查看答案以获取详细信息:

        How can I implement my own hook function with LSM?

        【讨论】:

          猜你喜欢
          • 2019-05-16
          • 2012-09-18
          • 1970-01-01
          • 2014-10-01
          • 2015-01-13
          • 2010-09-09
          • 1970-01-01
          • 2011-01-24
          • 2020-04-08
          相关资源
          最近更新 更多