积木首页 | 500多种网页特效 | 函数手册 | 广播电台 | 高清晰图片素材 | 服务器合租 | 万年历 | 网友最新浏览记录
程序开发 网页设计 搜索引擎 特效代码 操作系统 防范病毒 黑客技术 图形图象 电脑硬件 网络技术 服 务 器 数 据 库 网文精粹
您的位置:积木首页 >> 网络技术频道 >> Web服务器 >> 正文:
标题:Linux环境下的高级隐藏技术(2)
时间:2005-8-24 来源:不详 浏览数:
  2.2 隐藏模块


  上面分析了如何修改系统调用以隐藏特定名字的文件,在实际的处理中,经常会用模块来达到修改系统调用的目的,但是当插入一个模块时,若不采取任何隐藏措施,很容易被对方发现,一旦对方发现并卸载了所插入的模块,那么所有利用该模块来隐藏的文件就暴露了,所以应继续分析如何来隐藏特定名字的模块。Linux中用来查询模块信息的系统调用是sys_query_module,所以可以通过修改该系统调用达到隐藏特定模块的目的。首先解释一下原来的系统调用,原来系统调用的原型为:
int sys_query_module(const char *name, int which, void *buf, size_t bufsize , size_t *ret)
如果参数name不空,则访问特定的模块,否则访问的是内核模块,参数which说明查询的类型,当which=QM_MODULES时,返回所有当前已插入的模块名称,存入buff, 并且在ret中存放模块的个数,buffsize是buf缓冲区的大小。在模块隐藏的过程中只需要对which=QM_MODULES的情况进行处理就可以达到目的。修改后的系统调用工作过程如下:

  1)调用原来的系统调用,出错则返回错误代码;
  2)如果which不等于QM_MODULES,则不需要处理,直接返回。
  3)从buf的开始位置进行处理,如果存在特定的名字,则将后面的模块名称向前覆盖该名字。
  4)重复3),直到处理处理完所有的名字,正确返回。

  2.3 隐藏进程

  在Linux中不存在直接查询进程信息的系统调用,类似于ps这样查询进程信息的命令是通过查询proc文件系统来实现的,在背景知识中已经介绍过proc文件系统,由于它应用文件系统的接口实现,因此同样可以用隐藏文件的方法来隐藏proc文件系统中的文件,只需要在上面的hacked_getdents中加入对于proc文件系统的判断即可。由于proc是特殊的文件系统,只存在于内存之中,不存在于任何实际设备之上,所以Linux内核分配给它一个特定的主设备号0以及一个特定的次设备号1,除此之外,由于在外存上没有与之对应的i节点,所以系统也分配给它一个特殊的节点号PROC_ROOT_INO(值为1),而设备上的1号索引节点是保留不用的。通过上面的分析,可以得出判断一个文件是否属于proc文件系统的方法:

  1)得到该文件对应的inode结构dinode;
  2)if (dinode->i_ino == PROC_ROOT_INO && !MAJOR(dinode->i_dev) && MINOR(dinode->i _dev) == 1) {该文件属于proc文件系统}

  通过上面的分析,给出隐藏特定进程的伪代码表示:

  hacket_getdents(unsigned int fd, struct dirent *dirp, unsigned int count)
  {

  调用原来的系统调用;

  得到fd所对应的节点;

  if(该文件属于proc文件系统&&该文件名需要隐藏)
    {从dirp中去掉该文件相关信息}
}


 2.4 修改系统调用的方法


  现在已经解决了如何修改系统调用来达到隐藏的目的,那么如何用修改后的系统调用来替换原来的呢?这个问题在实际应用中往往是最关键的,下面将讨论在不同的情况下如何做到这一点。

  (1)当系统导出sys_call_table,并且支持动态的插入模块的情况下:

  在Linux内核2.4.18版以前,这种内核配置是非常普遍的。这种情况下修改系统调用非常容易,只需要修改相应的sys_call_table表项,使其指向新的系统调用即可。下面是相应的代码:

  int orig_getdents(unsigned int fd, struct dirent *dirp, unsigned int count)
  int init_module(void) 
  /*初始化模块*/
  {
  orig_getdents=sys_call_table[SYS_getdents];    //保存原来的系统调用
  orig_query_module=sys_call_table[SYS_query_module]
  sys_call_table[SYS_getdents]=hacked_getdents;  //设置新的系统调用
  sys_call_table[SYS_query_module]=hacked_query_module;
  return 0; //返回0表示成功
  }
  void cleanup_module(void)
  /*卸载模块*/
  {
  sys_call_table[SYS_getdents]=orig_getdents;    //恢复原来的系统调用
  sys_call_table[SYS_query_module]=orig_query_module;
  }

  (2)在系统并不导出sys_call_table的情况下:

  linux内核在2.4.18以后为了安全起见不再导出sys_call_table符号,从而无法直接获得系统调用表的地址,那么就必须找到其他的办法来得到这个地址。在背景知识中提到了/dev/kmem是系统主存的映像,可以通过查询该文件来找到sys_call_table的地址,并对其进行修改,来使用新的系统调用。那么如何在系统映像中找到sys_call_table的地址呢?让我们先看看system_call的源代码是如何来实现系统调用的(代码见/arch/i386/kernel/entry.S):

ENTRY(system_call)
  pushl %eax      # save orig_eax
  SAVE_ALL
  GET_CURRENT(%ebx)
  cmpl $(NR_syscalls),%eax
  jae badsys
  testb $0x02,tsk_ptrace(%ebx)  # PT_TRACESYS
  jne tracesys
  call *SYMBOL_NAME(sys_call_table)(,%eax,4)
  movl %eax,EAX(%esp)    # save the return value
ENTRY(ret_from_sys_call)


(责任编辑:欣欣裴)
关于本站 | 广告服务 | 联系我们 | 版权申明 | 强强联盟 | 投稿热线 | 网站地图 | 申请链接
Copyright ©2005-2006 Gimoo.net All rights reserved. 积木网 版权所有
E-mail:gimoohr@gmail.com 京ICP备05050695号