Jacob_linux 发表于 2015-12-07 14:45

32位中hook sys_execve 为什么导致crash,求指点!

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fdtable.h>
#include <linux/binfmts.h>
#include <linux/syscalls.h>
#include <linux/dirent.h>
#include <linux/dcache.h>
#include <linux/mount.h>
#include <linux/fs_struct.h>
#include <asm/unistd_32.h>


static unsigned longsys_call_tab   =0x0000000000000000;
module_param(sys_call_tab,ulong, S_IRUGO);


typedef asmlinkage long (*SYS_EXECVE)(const char __user *filename,
                           const char __user *const __user *argv,
                           const char __user *const __user *envp,
                           struct pt_regs *regs);

SYS_EXECVE old_sys_execve;

static long clear_and_return_cr0(void)
{
      unsigned long cr0 = 0;
      unsigned long ret = 0;

      asm volatile ("movl %%cr0, %%eax":"=a"(cr0));
      ret = cr0;
      cr0 &=0xfffeffff;
      asm volatile ("movl %%eax, %%cr0"
                :
                : "a"(cr0));
      return ret;
}

void setback_cr0(unsigned int val)
{
      asm volatile ("movl %%eax, %%cr0"
                :
                : "a"(val));
}

asmlinkage long new_sys_execve(const char __user *filename,
                           const char __user *const __user *argv,
                           const char __user *const __user *envp,
                           struct pt_regs *regs)
{       
        return old_sys_execve(filename , argv, envp, regs);
}
int __init monitor_init(void)
{
        unsigned int   orig_cr0 = 0;
        unsigned long* sys_call_table = sys_call_tab;

        old_sys_execve = (SYS_EXECVE)sys_call_table;
       
       
        orig_cr0 = clear_and_return_cr0();
        sys_call_table = new_sys_execve;
        setback_cr0(orig_cr0);

        printk("sys_execve : %p , syscall : %p __NR_execve : %d\n", old_sys_execve, sys_call_table, __NR_execve);
        return 0;
}

void __exit monitor_exit(void)
{
        unsigned int orig_cr0 = 0;
        unsigned long* sys_call_table = sys_call_tab;

        orig_cr0 = clear_and_return_cr0();
        sys_call_table = old_sys_execve;
        setback_cr0(orig_cr0);
       
        return;
}

module_init(monitor_init);
module_exit(monitor_exit);

MODULE_LICENSE("GPL");

Jacob_linux 发表于 2015-12-07 15:08

那位大神帮看看,   系统调用表地址,我是直接传进去的 ,打印出的old_sys_execve地址, 其实是符号表中的ptregs_execve,   我在钩子函数new_sys_execve中return 0 ;就不会crash ,但是什么都做不了了,如果我像上面那么返回,就会出crash。什么问题呢

macwe 发表于 2015-12-31 13:39

把crash信息贴出来。。。

shiweixingcn 发表于 2016-01-02 18:12

sys_call_table在很早以前就是只读属性了吧,所以如果你这么做的话可能需要把它变为可写,然后再做,不过为什么会出现这个现象需要看crash的log才能确认。

macwe 发表于 2016-01-11 12:19

execute系统调用的调用路径是stub_execve(entry_64.S)->sys_execve, stub_execve函数不符合gcc的调用约定,你的hook函数会导致栈不平衡。
页: [1]
查看完整版本: 32位中hook sys_execve 为什么导致crash,求指点!