驱动开发:DKOM 实现进程隐藏
DKOM 就是直接内核对象操作技术,我们所有的操作都会被系统记录在内存中,而驱动进程隐藏的做旧就是操作进程的EPROCESS结构与线程的ETHREAD结构、链表,要实现进程的隐藏我们只需要将某个进程中的信息,在系统EPROCESS链表中摘除即可实现进程隐藏。
DKOM 隐藏进程的本质是操作EPROCESS结构体,EPROCESS结构体中包含了系统中的所有进程相关信息,还有很多指向其他结构的指针,首先我们可以通过WinDBG在内核调试模式下输入dt_eprocess
即可查看到当前的EPROCESS结构体的偏移信息,结构较多,但常用的就下面这几个。
kd> dt_eprocess
nt!_EPROCESS
+0x000 Pcb : _KPROCESS
+0x160 ProcessLock : _EX_PUSH_LOCK
+0x168 CreateTime : _LARGE_INTEGER // 创建时间
+0x170 ExitTime : _LARGE_INTEGER // 退出时间
+0x180 UniqueProcessId : Ptr64 Void // 进程的PID
+0x188 ActiveProcessLinks : _LIST_ENTRY // 活动进程链表
+0x200 ObjectTable : Ptr64 _HANDLE_TABLE // 指向句柄表的指针
+0x2d8 Session : Ptr64 Void // 会话列表
+0x2e0 ImageFileName : [15] UChar // 进程的名称
+0x308 ThreadListHead : _LIST_ENTRY // 进程中的线程链表结构
+0x320 Wow64Process : Ptr64 Void // 32位进程链表
+0x328 ActiveThreads : Uint4B // 活动的线程
+0x32c ImagePathHash : Uint4B // 镜像路径的Hash值
+0x338 Peb : Ptr64 _PEB // 指向PEB结构的指针
+0x440 Flags : Uint4B // 进程标志
要实现进程的隐藏我们需要关注结构中的 ActiveProcessLinks
该指针把每个进程的EPROCESS结构体连接成了双向链表,我们可以使用 ZwQuerySystemInformation
这个函数来遍历出所有的进程信息,要实现进程的隐藏,只需要将某个进程的EPROCESS从结构体中摘除,那么通过ZwQuerySystemInformation
函数就无法遍历出被摘链的进程了,从而实现了进程的隐藏。
在实现进程隐藏之前,我们需要通过代码的方式获取到当前系统中所有进程的EPROCESS信息,我们可以通过 PsLookupProcessByProcessId
函数获取到指定进程的ID,然后通过 PsGetProcessImageFileName
函数取出结构名称,并通过 _stricmp
判断是否是我们想要隐藏的程序。
#include <ntifs.h>
NTKERNELAPI NTSTATUS PsLookupProcessByProcessId(HANDLE ProcessId, PEPROCESS *Process);
NTKERNELAPI CHAR* PsGetProcessImageFileName(PEPROCESS Process);
VOID UnDriver(PDRIVER_OBJECT driver)
{
DbgPrint(("驱动程序卸载成功! \n"));
}
PEPROCESS GetProcessObjectByName(char *name)
{
SIZE_T temp;
for (temp = 100; temp<10000; temp += 4)
{
NTSTATUS status;
PEPROCESS ep;
status = PsLookupProcessByProcessId((HANDLE)temp, &ep);
if (NT_SUCCESS(status))
{
char *pn = PsGetProcessImageFileName(ep);
if (_stricmp(pn, name) == 0)
return ep;
}
}
return NULL;
}
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
PEPROCESS PRoc = NULL;
PRoc = GetProcessObjectByName("calc.exe");
DriverObject->DriverUnload = UnDriver;
return STATUS_SUCCESS;
}
然后得到句柄以后直接摘除进程的结构即可实现隐藏,这种摘除方式比较草率,如果关闭驱动后没有手工还原的话可能会导致蓝屏,该方法只用于在Win7上使用,Win10没试过。
#include <ntifs.h>
#define PROCESS_ACTIVE_PROCESS_LINKS_OFFSET 0x188
NTKERNELAPI NTSTATUS PsLookupProcessByProcessId(HANDLE ProcessId, PEPROCESS *Process);
NTKERNELAPI CHAR* PsGetProcessImageFileName(PEPROCESS Process);
VOID UnDriver(PDRIVER_OBJECT driver)
{
DbgPrint(("驱动程序卸载成功! \n"));
}
PEPROCESS GetProcessObjectByName(char *name)
{
SIZE_T temp;
for (temp = 100; temp<10000; temp += 4)
{
NTSTATUS status;
PEPROCESS ep;
status = PsLookupProcessByProcessId((HANDLE)temp, &ep);
if (NT_SUCCESS(status))
{
char *pn = PsGetProcessImageFileName(ep);
if (_stricmp(pn, name) == 0)
return ep;
}
}
return NULL;
}
VOID RemoveListEntry(PLIST_ENTRY ListEntry)
{
KIRQL OldIrql;
OldIrql = KeRaiseIrqlToDpcLevel();
if (ListEntry->Flink != ListEntry &&ListEntry->Blink != ListEntry &&ListEntry->Blink->Flink == ListEntry &&ListEntry->Flink->Blink == ListEntry)
{
ListEntry->Flink->Blink = ListEntry->Blink;
ListEntry->Blink->Flink = ListEntry->Flink;
ListEntry->Flink = ListEntry;
ListEntry->Blink = ListEntry;
}
KeLowerIrql(OldIrql);
}
// 隐藏指定进程(会蓝屏)
BOOLEAN HideProcessB(PUCHAR pszHideProcessName)
{
PEPROCESS pFirstEProcess = NULL, pEProcess = NULL;
ULONG ulOffset = 0;
HANDLE hProcessId = NULL;
PUCHAR pszProcessName = NULL;
// 获取相应偏移大小
ulOffset = PROCESS_ACTIVE_PROCESS_LINKS_OFFSET;
if (0 == ulOffset)
{
return FALSE;
}
// 获取当前进程结构对象
pFirstEProcess = PsGetCurrentProcess();
pEProcess = pFirstEProcess;
// 开始遍历枚举进程
do
{
// 从 EPROCESS 获取进程 PID
hProcessId = PsGetProcessId(pEProcess);
// 从 EPROCESS 获取进程名称
pszProcessName = PsGetProcessImageFileName(pEProcess);
// 隐藏指定进程
if (0 == _stricmp(pszProcessName, pszHideProcessName))
{
// 摘链
RemoveEntryList((PLIST_ENTRY)((PUCHAR)pEProcess + ulOffset));
break;
}
// 根据偏移计算下一个进程的 EPROCESS
pEProcess = (PEPROCESS)((PUCHAR)(((PLIST_ENTRY)((PUCHAR)pEProcess + ulOffset))->Flink) - ulOffset);
} while (pFirstEProcess != pEProcess);
return TRUE;
}
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
PEPROCESS PRoc = NULL;
PRoc = GetProcessObjectByName("calc.exe");
// 摘除结构中的calc.exe 实现驱动隐藏计算器
RemoveListEntry((PLIST_ENTRY)((ULONG64)PRoc + PROCESS_ACTIVE_PROCESS_LINKS_OFFSET));
DriverObject->DriverUnload = UnDriver;
return STATUS_SUCCESS;
}
没什么难度,就是摘链,而这种断链隐藏,不仅操作不好会蓝屏且很容易被发现,只是能在任务管理器看不到而已。
驱动开发:DKOM 实现进程隐藏的更多相关文章
- 驱动开发:内核中实现Dump进程转储
多数ARK反内核工具中都存在驱动级别的内存转存功能,该功能可以将应用层中运行进程的内存镜像转存到特定目录下,内存转存功能在应对加壳程序的分析尤为重要,当进程在内存中解码后,我们可以很容易的将内存镜像导 ...
- 驱动开发:内核遍历进程VAD结构体
在上一篇文章<驱动开发:内核中实现Dump进程转储>中我们实现了ARK工具的转存功能,本篇文章继续以内存为出发点介绍VAD结构,该结构的全程是Virtual Address Descrip ...
- VS 2013驱动开发 + Windbg + VM双机调试(亲测+详解)
------------VS 2013驱动开发 + Windbg + VM双机调试(亲测+详解)------------- WIN10已上线,随之而来的是VS2015:微软在 "WDK760 ...
- Linux 驱动开发
linux驱动开发总结(一) 基础性总结 1, linux驱动一般分为3大类: * 字符设备 * 块设备 * 网络设备 2, 开发环境构建: * 交叉工具链构建 * NFS和tftp服务器安装 3, ...
- (57)Linux驱动开发之三Linux字符设备驱动
1.一般情况下,对每一种设备驱动都会定义一个软件模块,这个工程模块包含.h和.c文件,前者定义该设备驱动的数据结构并声明外部函数,后者进行设备驱动的具体实现. 2.典型的无操作系统下的逻辑开发程序是: ...
- Linux驱动开发概述
原文出处:http://www.cnblogs.com/jacklu/p/4722563.html Linux设备分类 设备的驱动程序也要像裸机程序那样进行一些硬件操作,不同的是驱动程序需要" ...
- Android深度探索(卷1)HAL与驱动开发
第一章 介绍Android驱动开发和移植技术 主要对android和linux做了总体的介绍,让我们有了个感性的认识. 一.Android的四层系统架构: a) Linux内核:Android是基于L ...
- 《Android深度探索HAL与驱动开发》第一章阅读心得
首先了解到Android系统架构是由四层构成:其中第一层是Linux内核,他的作用是负责Linux的驱动程序以及内存.进程.电源等管理操作:第二层是C/C++代码库,也就是Linux下.so的文件:第 ...
- 第一章 Andorid系统移植与驱动开发概述 - 读书笔记
Android驱动月考1 第一章 Andorid系统移植与驱动开发概述 - 读书笔记 1.Android系统的架构: (1)Linux内核,Android是基于Linux内核的操作系统,并且开源,所以 ...
- (转)Mac OS X内核编程,MAC驱动开发资源汇总
一.Mac OS X内核编程开发官方文档: I/O Kit Fundamentals: I/O Kit基础 - Mac OS X系统内核编程 https://developer.apple.com ...
随机推荐
- ZK--简介,部署
官网:https://zookeeper.apache.org/ 本文zk版本:3.7.0 一.简介 ZooKeeper 是一个高可用的分布式数据管理与系统协调软件,它可以为分布式应用提供状态同步.配 ...
- 淘宝flexible.js源码分析
下面三种情况都会刷新页面,都会触发load事件. 1.a标签的超链接. 2.F5或者刷新按钮(强制刷新) 3.前进后退按钮 但是火狐中,有个特点,有个"往返缓存",这个缓存中不仅保 ...
- 无向图求桥 UVA 796
***桥的概念:无向连通图中,如果删除某边后,图变 成不连通,则称该边为桥.*** ***一条边(u,v)是桥,当且仅当(u,v)为树枝边,且 满足dfn(u)<low(v)(前提是其没有重边) ...
- TOEFL | 202307 改革 · 新版题型总结
目录 Listening(36min) Reading(35min) Speaking(16min) Writing(29min) Listening(36min) 2 conversation,3 ...
- 【FreeRTOS】堆内存管理
动态内存分配及其与FreeRTOS的相关性 为了使FreeRTOS更易用,内核对象(如任务.队列.信号量.事件组)不在编译期静态分配,而是在运行时动态分配,FreeRTOS在内核对象创建时分配RAM, ...
- java - 局部变量和成员变量的区别
package class_object; /** * 局部变量和成员变量的区别 * * 1. 定义位置 * * 2. 作用域 * * 3. 默认值 => 局部变量没有默认值 * * 4. 内存 ...
- Oracle12c新增max_idle_time参数的学习与感触
Oracle12c新增max_idle_time参数的学习与感触 TLDR 其实任何软件出了新版本.readme 是很重要的. 尤其是数据库, 涉及到底层问题的. 比如这次遇到的Oracle的max_ ...
- [转帖][MySQL 8.2.0] 从参数变化解读 MySQL 8.2.0 发版说明
https://www.mryunwei.com/482476.html 日前,MySQL 8.2.0 创新版本已正式上线,并提供安装包下载,但 docker 镜像尚未更新. 在 MySQL 8.1. ...
- [转帖]如何用 30s 给面试官讲清楚什么是 Session-Cookie 认证
https://www.jianshu.com/p/e1121d4d7084 引言 由于 HTTP 协议是无状态的,完成操作关闭浏览器后,客户端和服务端的连接就断开了,所以我们必须要有一种机制来保证客 ...
- [转帖]可直接拿来用的kafka+prometheus+grafana监控告警配置
kafka配置jmx_exporter 点击:https://github.com/prometheus/jmx_exporter,选择下面的jar包下载: 将下载好的这个agent jar包上传到k ...