【Linux、进程隐藏】在Linux环境下添加系统调用实现进程隐藏

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

进程隐藏的应用

进程隐藏,也就在用户不知情的情况下,悄悄执行自己的代码。是病毒、木马等恶意软件能不被发现的重要技术。因此了解进程隐藏的技术就可以在防治病毒的方面起到积极的作用,提高电脑的安全性。

一、环境设置:

我采用的是Ubuntu15.0.0,linux内核是5.4.0。网上有很多安装方法,要是不会的话可以私信问我。

二、实现方法步骤:

1.思路图

基于内核态的进程隐藏

2.利用strace命令追踪ps

Strace命令常用来跟踪进程执行时的系统调用和所接收的信号。 在Linux世界,进程不能直接访问硬件设备,当进程需要访问硬件设备(比如读取磁盘文件,接收网络数据等等)时,必须由用户态模式切换至内核态模式,通过系统调用访问硬件设备。strace可以跟踪到一个进程产生的系统调用,包括参数,返回值,执行消耗的时间。
在linux终端输入strace ps 命令(以ps命令为例,top命令操作一样):

在这里插入图片描述
可以发现ps的命令是通过readdir函数来访问/proc/pid(进程号id)的状态来显示所有的进程号。既然如此,那我们可以通过cat /proc/pid/stat 的方式来查看一下想查看的进程信息:
在这里插入图片描述
想了解具体参数信息的可以自己去CSDN查一下这里就不多说了。

3.基于内核态下的隐藏进程:(添加系统调用+修改内核代码)

3.1 原理:

首先进入内核源码(我的版本:/usr/src/linux-source-5.4.0),在PCB增加一个hide字段,用来表示是否要隐藏进程(1表示隐藏,0表示不隐藏),在相关联的函数增加一个判断条件,若是hide字段为1就不做将信息复制到/proc目录下的操作,在fork函数添加一个hide初始化内容,之后添加两个系统调用,用来实现将进程隐藏和显示。

3.2 实现步骤

1、在include/linux/sched.h的系统代码中,寻找到task_struct结构体(具体位置会根据使用的系统内核版本不同而有所变化),找到task_struct结构体后,在结构体中找到randomized_struct_fields_end字段。这个字段是linux内核源码提供给用户自定义变量的地方。其余地方是内核代码固定好的不能随便放。
在这里插入图片描述修改的地方
2、修改fs/proc/base.c文件,找到里面proc_pid_readdir() 函数,找到对应的for循环,这个for循环的作用是根据系统内进程动态添加子进程号目录,我们要做的就是在这个循环里增加一个判断当hide字段为0,即不隐藏的状态下是才进行添加操作,否则不进行添加操作。
在这里插入图片描述
在这里插入图片描述
3、在kernel/fork.c文件中,在task_struct *copy_proccess函数里,在p=dup_task_struct(current,node)字段之下,增加对hide字段的初始化。
在这里插入图片描述
4、在kernel/sys.c文件中,添加两个系统调用sys_hide和sys_unhide,这两个系统调用的作用就是将hide字段置为0或者1。(隐藏时为0,不隐藏时为1)。只要将两个系统调用添加在sys.c文件的最底端就可以。
在这里插入图片描述
代码如下:

asmlinkage long sys_hide(void)
{
    
    
    current->hide=1;
    return 0;
}
asmlinkage long sys_unhide(void)
{
    
    
    current->hide=0;
    return 0;
}

5、在include/uapi/asm-generic/unistd.h文件中,找到__NR_syscalls字段,在其之上添加所需要的系统调用号(sys_hide为436,sys_unhide为437),并且修改系统调用号的总数(系统调用总数+2,例如此时我的系统调用为436,要修改成438)。
在这里插入图片描述
添加内容如下:

#define __NR_hide 436
__SYSCALL(__NR_hide,sys_hide)
#define __NR_unhide 437
__SYSCALL(__NR_unhide,sys_unhide)
//切记一定将低下系统调用总数+2

6、在include/linux/syscalls.h文件中,找到kernel/sys.c字段,声明刚才添加的两个系统调用函数(sys_hide和sys_unhide)
在这里插入图片描述
添加内容如下:

asmlinkage long sys_hide();                        //my system call
asmlinkage long sys_unhide();  //my system call

7、在系统调用表arch/x86/entry/syscalls/syscall_64.tbl中,在系统调用号为436和437(前面定义的系统调用号)的位置添加对应项
在这里插入图片描述
添加内容如下:

436 64      hide       sys_hide
437 64      unhide  sys_unhide

8、至此所有东西都已经配置好了。开始重新编译内核、重启虚拟机。步骤如下:

sudo make gconfig
sudo make clean 
sudo make -j4	//编译内核,可以去打几把游戏,挺久的
sudo make modules_install        //安装内核模块
sudo make install      //安装内核
reboot	//重启

三、测试

在用户目录下创建一个hide.c文件。
代码如下:

#include <stdio.h>
#include <sys/types.h>
#include <linux/unistd.h>
#define __NR_hide 436  
#define __NR_unhide 437  
int main()
{
    
    
        printf("Before hide:\n");
        system("ps");
        syscall(__NR_hide);//调用系统号为436的系统调用  
        printf("After hide:\n");
        system("ps");
        syscall(__NR_unhide);
        printf("After unhide:\n");
        system("ps");
        return 0;
}

之后gcc编译.c文件,并运行

编译命令:gcc hide.c -o hide,执行命令:./hide

在这里插入图片描述
至此,所有工作都已完成,且测试隐藏进程成功。


总结

其实我介绍的隐藏进程的方法比较简单,最折磨人的还是编译内核的各种报错,每次都得等好几个小时,网上还有许多其他隐藏进程的方法,例如在用户态下劫持readdir()函数,让他无法读取/proc/pid的目录、在内核态下直接修改系统自带的proc_pid_lookup函数实现进程隐藏等等。其实万变不离其宗,只要理解了ps的原理,怎么实现看的是个人的理解和能力。
最后,这是我发布的第一篇博客,有逻辑问题的地方希望各位看官多担待!

放一些我参考的内容:(要是不会的可以跟着这几篇走)
安装编译内核:内核编译最新教程+常见问题总结
实现隐藏进程的其余方法:(十分详细,这个博主写的非常好,哪怕不去实现去看看也好。)(渗透测试后期)Linux进程隐藏详解

猜你喜欢

转载自blog.csdn.net/qq_51720181/article/details/125458127
今日推荐