热门关键字:  ubuntu  分区  Fedora  linux系统进程  函数

当前位置 :| 主页>Linux教程>内核研究>

揭示恶意的Linux内核模块是如何工作

来源: 作者: 时间:2007-03-06 Tag: 点击:

之前有一点我们没有提及,lsmod会报告装载了knark.o模块。不幸的是,入侵者能轻易的将此信息抹去。knark同时还包括了另一个LKM叫做modhide,能够隐藏自身以及上一个模块。一旦模块隐藏,如果不重启动机器就无法卸载,而且没有简单的方法检测到模块的加载,所有的相关信息都不见了。正如之前介绍的,knark的所有功能令其成为终极秘密武器。

预防方法

阻止LKM破坏显然是最佳解决方案。我们有几种方法能够提前预防LKM。可以通过保护系统调用表来预防大部分的恶毒LKM。我们可以构造一个简单的LKM,定时的或者在其他模块加载时监控系统调用表。如果它发现系统调用表改变了,可以通知系统管理员甚至将调用表修改回原来的值。下面的例子能很好的工作在Linux 2.2和2.4上。如果你的机器有超过一个处理器,可以用如下命令编译:gcc -D __SMP__ -c syscall_sentry.c。如果是单处理器,去掉-D __SMP__就行了。编译成功后,用insmod加载。具体参看下面的例子。

  /* 
  * This LKM is designed to be a tripwire for the sys_call_table. 
  */ 
  #define MODULE_NAME "syscall_sentry" 
  /* This definition is the time between periodic checks. */ 
  #define TIMEOUT_SECS 10 
  #define MODULE 
  #define __KERNEL__ 
  #include<linux/module.h> 
  #include<linux/config.h> 
  #include<linux/version.h> 
  #include<linux/kernel.h> 
  #include<linux/sys.h> 
  #include<linux/param.h> 
  #include<linux/sched.h> 
  #include<linux/timer.h> 
  #include<sys/syscall.h> 
  /* This function is a simple string comparison function */ 
  static int mystrcmp( const char *str1, const char *str2) 
  { 
  while(*str1 && *str2) 
  if (*(str1++) != *(str2++)) 
  return -1; 
  return 0; 
  } 
  /* This function builds a timer struct for versions of Linux 
  * less than Linux 2.4. It is used to set a timer 
  */ 
  #if linux_VERSION_CODE < KERNEL_VERSION(2,4,0) 
  /* Initializes a timer */ 
  void init_timer(struct timer_list * timer) 
  { 
  timer->next = NULL; 
  timer->prev = NULL; 
  } 
  #endif 
  /* This is our timer */ 
  static struct timer_list syscall_timer; 
  /* This is the system’s syscall table */ 
  extern void *sys_call_table[]; 
  /* This is the saved, valid syscall table */ 
  static void *orig_sys_call_table[ NR_syscalls ]; 
  /* This function is needed to protect yourself */ 
  static unsigned long (*orig_init_module) (const char *, struct module*); 
  /* This function checks the syscalls for changes 
  * and changes them back to the original if it has 
  * been changed. 
  */ 
  static int check_syscalls( void ) 
  { 
  int i; 
  /* Add a new timer for our next check */ 
  del_timer( &syscall_timer ); 
  init_timer( &syscall_timer ); 
  syscall_timer.function = (void *)check_syscalls; 
  syscall_timer.expires = jiffies + TIMEOUT_SECS * HZ; 
  add_timer( &syscall_timer ); 
  for ( i = 0; i < NR_syscalls - 1; i++ ) 
  { 
  if (orig_sys_call_table[i] != sys_call_table[i]) 
  { 
  printk(KERN_INFO " SysCallSentry - sys_call_table has been 
  modified in entry %d! ", i); 
  sys_call_table[i] = orig_sys_call_table[i]; 
  } 
  } 
  return 1; 
  } 
  /* Check sys_call_table anytime a new module is loaded. */ 
  static int long sys_init_module_wrapper( const char *name, struct 
  module *mod ) 
  { 
  int i; 
  int res = (*orig_init_module)(name,mod); 
  for ( i = 0; i < NR_syscalls - 1; i++ ) 
  { 
  if (orig_sys_call_table[i] != sys_call_table[i]) 
  { 
  printk( KERN_INFO " SysCallSentry - sys_call_table has been 
  modified in entry %d! ", i); 
  sys_call_table[i] = orig_sys_call_table[i]; 
  } 
  } 
  return res; 
  } 
  /* Module Init Code */ 
  static int init_module (void) 
  { 
  int i; 
  printk(KERN_INFO " SysCallSentry Inserted "); 
  /* Initiate the periodic timer */ 
  init_timer( &syscall_timer ); 
  /* Save the old values of the sys_call_table */ 
  orig_init_module = sys_call_table[SYS_init_module]; 
  /* Wrap the init_module syscall. This will check to see 
  * if any calls have been altered when a new module loads. 
  */ 
  sys_call_table[SYS_init_module] = sys_init_module_wrapper; 
  for ( i=0; i < NR_syscalls - 1; i++ ) 
  { 
  orig_sys_call_table[i] = sys_call_table[i]; 
  } 
  /* Start our first check */ 
  check_syscalls(); 
  return(0); 
  } 
  /* Module Cleanup Code */ 
  static void cleanup_module (void) 
  { 
  /* Return system status to the original */ 
  sys_call_table[SYS_init_module] = orig_init_mo


相关文章:
精通initramfs构建step by step
Linux利用kexec迅速切换内核
进程上下文VS中断上下文
内核通知链 学习笔记
linux spi子系统驱动分析
menuconfig 配置选项
《Linux操作系统内核实习》之练习一
udev详解
什么叫微内核,宏内核?
Linux 信号signal处理机制
开发简单的 Linux2.6 内核模块
删除内核的perl脚本
Linux2.6内核usb gadget驱动移植
GCC hacks in the Linux kernel
iomem
kernel学习的想法
让自己的驱动支持udev
linux内核编译步骤
内核的等待队列
Linux内核wait_queue深入分析
升级和删除内核
SD卡驱动分析2
Linux Kernel VDSO本地权限提升漏洞
内核中的TCP的追踪分析-15-TCP(IPV4)的客户端与
linux 2.6内核可加载模块的编译
内核模块HelloWorld
在环回接口上发送一个数据报
ARP初始化
1分钟编译FreeBSD内核
linux设备模型之uart驱动架构分析