Linux下隐藏文件的一种新方法
来源:优易学  2011-12-22 19:57:45   【优易学:中国教育考试门户网】   资料下载   IT书店

  源代码在同一文件中:
  int vfs_readdir(struct file *file, filldir_t filler, void *buf)
  {
  struct inode *inode = file->f_path.dentry->d_inode;
  int res = -ENOTDIR;
  if (!file->f_op || !file->f_op->readdir)
  goto out;
  res = security_file_permission(file, MAY_READ);
  if (res)
  goto out;
  res = mutex_lock_killable(&inode->i_mutex);
  if (res)
  goto out;
  res = -ENOENT;
  if (!IS_DEADDIR(inode)) {
  res = file->f_op->readdir(file, buf, filler);
  file_accessed(file);
  }
  mutex_unlock(&inode->i_mutex);
  out:
  return res;
  }
  EXPORT_SYMBOL(vfs_readdir);它有3个参数,第一个是通过fget得到的file结构指针, 第2个通过结合上下文可得知,这是一个回调函数用来填充第3个参数开始的用户空间的指针。 接着看看它具体是怎么实现的。
  通过security_file_permission()验证后, 在用mutex_lock_killable()对inode结构加了锁。然后调用ile->f_op->readdir(file, buf, filler);通过进一步的底层函数来对buf进行填充。这个buf就是用户空间strcut dirent64结构的开始地址。
  所以到这里我们可以断定通过hook vfs_readdir函数对buf做过滤还是可以完成隐藏文件的功能。而且vfs_readdir的地址是导出的, 这样就不用复杂的方法找它的地址了。
  但是还有没有更进一步的方法呢? 前面不是提到过有个filldir64函数吗, 它用来填充buf结构的。也许通过hook它来做更隐蔽的隐藏文件方法。 继续跟踪filldir64,看看它是怎么实现的。
  static int filldir64(void * __buf, const char * name, int namlen, loff_t offset,
  u64 ino, unsigned int d_type)
  {
  struct linux_dirent64 __user *dirent;
  struct getdents_callback64 * buf = (struct getdents_callback64 *) __buf;
  int reclen = ALIGN(NAME_OFFSET(dirent) + namlen + 1, sizeof(u64));
  buf->error = -EINVAL;
  if (reclen > buf->count)
  return -EINVAL;
  dirent = buf->previous;
  if (dirent) {
  if (__put_user(offset, &dirent->d_off))
  goto efault;
  }
  dirent = buf->current_dir;
  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;
  }先把参数buf转换成struct getdents_callback64的结构指针。
  struct getdents_callback64 {
  struct linux_dirent64 __user * current_dir;
  struct linux_dirent64 __user * previous;
  int count;
  int error;
  };current_dir始终指向当前的struct dirent64结构,filldir64每次只填充一个dirent64结构。
  它是被file->f_op->readdir循环调用的。 通过代码可以看出是把dirent64结构的相关项拷贝到用户空间的dirent64结构中, 然后更新相应的指针。
  所以通过分析filldir64代码, 可以判定通过判断参数name,看它是否是我们想隐藏的文件,是的话,return 0就好了。
  三. 扩展
  通过分析sys_getdents64代码的实现,我们可以了解到通过hook内核函数的方法,来完成rootkit的功能是很简单和方便的。 关键你能了解它的实现逻辑。 对linux平台来说,阅读内核源代码是开发rootkit的根本。 如何hook? 最简单的就是修改函数的前几个字节,jmp到我们的新函数中去, 在新函数完成类似函数的功能。 根本不必在跳回原函数了, 有了内核源代码在手,原函数怎么实现,我们就怎么copy过去给它在实现一次。 所在linux实现rk也有很方便的一点,就是它的内核源代码是公开的, 好好阅读源代码吧, 你会有更多的收获。

上一页  [1] [2] 

责任编辑:小草

文章搜索:
 相关文章
热点资讯
热门课程培训