微过滤(minifilter)驱动实现文件隐藏增强版

微过滤驱动主要用于安全隔离盒累产品,通过收集资料,和各位高手的文章,具有参考意义的的文章主要输入下

看雪论套:https://bbs.pediy.com/thread-226174.htm

是一篇很有质量的文章,基本逻辑已经实现,入门级的如何新建工程,编译,签名与安装,可以参考其他教程,这里只把实践重遇到的问题进行总结与给出解决方案。现在先总结问题:

问题1:设置为保护,仍然可以删除文件和目录;

问题2、保护状态仍然可以通过鼠标右键新建文件夹与其他文件,只是内容为空,0字节大小;

问题3、发现目录重第一个文件无法隐藏;

解决方法:

问题1、对IRP_MJ_SET_INFORMATION与IRP_MJ_CREATE 的pre过程监听,参考了如下文章

https://www.cnblogs.com/lsh123/archive/2004/01/13/10405002.html

但需要坐下改进代码如:


FLT_PREOP_CALLBACK_STATUS SafeUsbFilterPreDelete(_Inout_ PFLT_CALLBACK_DATA Data,
	_In_ PCFLT_RELATED_OBJECTS FltObjects,
	_Flt_CompletionContext_Outptr_ PVOID *CompletionContext)
{
	UNREFERENCED_PARAMETER(FltObjects);
	UNREFERENCED_PARAMETER(CompletionContext);
	PAGED_CODE();//PreCallback的IRQL应当<= APC_LEVEL
	FILE_DISPOSITION_INFORMATION  fdi;
	FLT_PREOP_CALLBACK_STATUS Status = FLT_PREOP_SUCCESS_NO_CALLBACK;//不再调用postoperation callback routine,

	ULONG ulDisposition = 0;
	BOOLEAN IsDirectory = FALSE;//目录操作跳过,不管
	NTSTATUS status = FltIsDirectory(FltObjects->FileObject, FltObjects->Instance, &IsDirectory);
	if (NT_SUCCESS(status)) {
		if (IsDirectory == TRUE) {
			//return Status;
		}
	}
	
	if (Data->Iopb->MajorFunction == IRP_MJ_CREATE) {
		if (!FlagOn(Data->Iopb->Parameters.Create.Options, FILE_DELETE_ON_CLOSE)) {

			
			ulDisposition = (Data->Iopb->Parameters.Create.Options >> 24) & 0xFF;
			if (ulDisposition == FILE_CREATE || ulDisposition == FILE_OVERWRITE || ulDisposition == FILE_OVERWRITE_IF)
			{
				fdi.DeleteFile = TRUE;
				//FltSetInformationFile(FltObjects->Instance, FltObjects->FileObject, &fdi, sizeof(FILE_DISPOSITION_INFORMATION), FileDispositionInformation);

				//FltCancelFileOpen(FltObjects->Instance, FltObjects->FileObject);
				if (gReadOnly == TRUE)
				{
					Data->IoStatus.Status = STATUS_ACCESS_DENIED;
					Data->IoStatus.Information = 0;

					Status = FLT_PREOP_COMPLETE;
				}
			}
			return Status;
		}
	}

	if (Data->Iopb->MajorFunction == IRP_MJ_SET_INFORMATION) {
		switch (Data->Iopb->Parameters.SetFileInformation.FileInformationClass) {
		case FileRenameInformation:
		case FileRenameInformationEx:
		case FileDispositionInformation:
		case FileDispositionInformationEx:
		case FileRenameInformationBypassAccessCheck:
		case FileRenameInformationExBypassAccessCheck:
		case FileShortNameInformation:
			break;
		default:
			return Status;
		}
	}


	PFLT_FILE_NAME_INFORMATION FileNameInfo = NULL;
	if (FltObjects->FileObject != NULL) {
		status = FltGetFileNameInformation(Data, FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_DEFAULT, &FileNameInfo);
		if (NT_SUCCESS(status)) {
			FltParseFileNameInformation(FileNameInfo);
			//if (RtlCompareUnicodeString(&FileNameInfo->Name, &Protected, TRUE) == 0) {
			//if (RtlCompareUnicodeString(&FileNameInfo->Extension, &Protected, TRUE) == 0)
			if (gReadOnly == TRUE)
			{
				DbgPrint("===========Protecting file deletion/rename! filenamelength ==========");
				DbgPrint("%wZ\n", &(FileNameInfo->Name));

				Data->IoStatus.Status = STATUS_ACCESS_DENIED;
				Data->IoStatus.Information = 0;
				Status = FLT_PREOP_COMPLETE;
			}
			// Clean up file name information.
			FltReleaseFileNameInformation(FileNameInfo);
		}
	}

	return Status;

问题2

参考http://bbs3.driverdevelop.com/read.php?tid=90996

但是需要改进,不是处理Post,仍然是Pre代码已经在问题1重,对if (ulDisposition == FILE_CREATE || ulDisposition == FILE_OVERWRITE || ulDisposition == FILE_OVERWRITE_IF)进行拦截;

问题3:参考https://www.oschina.net/code/piece_full?code=43729

改问题比较特殊,网上只找对对目录隐藏的处理方式,但不足以满足需求,且在时间过程中发现 IRP_MJ_CREATE 的Post函数始终未执行,还是IRP_MJ_DIRECTORY_CONTROL中隐藏逻辑代码中做特殊处理,根据看雪轮胎网友代码中previousFileInfo = currentFileInfo;//保存下来是有问题的,始终无法处理第一个文件隐藏问题,最后参考了该链接方式,把该因此的文件类型强制改为系统不显示的类型,问题解决。

解决以上三个问题后,一个完整的存储过滤器安全防护类产品通过微软的微滤器完美实现。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
很抱歉,我无法为您提供完整的代码。但是,我可以为您提供一个简单的示例,以说明如何使用minifilter双缓存机制实现透明加解密处理。 在此示例中,我们将使用minifilter驱动程序来拦截文件访问,并使用双缓存机制对文件进行加解密处理。我们将使用AES算法进行加解密,并使用Windows CryptoAPI来实现加解密过程。 以下是示例代码的主要部分: ```c // 定义双缓存结构体 typedef struct _DOUBLE_BUFFER { PVOID DataBuffer; // 数据缓存 ULONG DataLength; // 数据长度 PVOID AuxBuffer; // 辅助缓存 ULONG AuxLength; // 辅助缓存长度 ULONG TotalLength; // 数据总长度 CRITICAL_SECTION Lock; // 互斥锁 } DOUBLE_BUFFER, *PDOUBLE_BUFFER; // 初始化双缓存 NTSTATUS InitializeDoubleBuffer(PDOUBLE_BUFFER pBuffer, ULONG TotalLength) { NTSTATUS status = STATUS_SUCCESS; pBuffer->DataBuffer = ExAllocatePoolWithTag(NonPagedPool, TotalLength, 'Tag1'); if (pBuffer->DataBuffer == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; goto Exit; } pBuffer->DataLength = 0; pBuffer->AuxBuffer = ExAllocatePoolWithTag(NonPagedPool, TotalLength, 'Tag2'); if (pBuffer->AuxBuffer == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; goto Exit; } pBuffer->AuxLength = 0; pBuffer->TotalLength = TotalLength; InitializeCriticalSection(&pBuffer->Lock); Exit: if (!NT_SUCCESS(status)) { if (pBuffer->DataBuffer != NULL) { ExFreePoolWithTag(pBuffer->DataBuffer, 'Tag1'); } if (pBuffer->AuxBuffer != NULL) { ExFreePoolWithTag(pBuffer->AuxBuffer, 'Tag2'); } } return status; } // 销毁双缓存 VOID DestroyDoubleBuffer(PDOUBLE_BUFFER pBuffer) { if (pBuffer->DataBuffer != NULL) { ExFreePoolWithTag(pBuffer->DataBuffer, 'Tag1'); } if (pBuffer->AuxBuffer != NULL) { ExFreePoolWithTag(pBuffer->AuxBuffer, 'Tag2'); } DeleteCriticalSection(&pBuffer->Lock); } // 读取文件到缓存 NTSTATUS ReadFileToBuffer(PFLT_CALLBACK_DATA Data, PFLT_RELATED_OBJECTS FltObjects, PVOID* pBuffer, PULONG pLength) { NTSTATUS status = STATUS_SUCCESS; HANDLE hFile = NULL; OBJECT_ATTRIBUTES objAttr; IO_STATUS_BLOCK ioStatus; FILE_STANDARD_INFORMATION fileInfo; LARGE_INTEGER byteOffset; ULONG length = 0; ULONG bytesRead = 0; InitializeObjectAttributes(&objAttr, &Data->Iopb->TargetFileObject->FileName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); status = FltCreateFile(FltObjects->Instance, FltObjects->FileObject, &hFile, FILE_READ_DATA, &objAttr, &ioStatus, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN, FILE_NON_DIRECTORY_FILE, NULL, 0, IO_IGNORE_SHARE_ACCESS_CHECK); if (!NT_SUCCESS(status)) { goto Exit; } status = ZwQueryInformationFile(hFile, &ioStatus, &fileInfo, sizeof(fileInfo), FileStandardInformation); if (!NT_SUCCESS(status)) { goto Exit; } length = (ULONG)fileInfo.EndOfFile.QuadPart; *pBuffer = ExAllocatePoolWithTag(NonPagedPool, length, 'Tag3'); if (*pBuffer == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; goto Exit; } byteOffset.QuadPart = 0; status = ZwReadFile(hFile, NULL, NULL, NULL, &ioStatus, *pBuffer, length, &byteOffset, NULL); if (!NT_SUCCESS(status)) { goto Exit; } bytesRead = (ULONG)ioStatus.Information; if (bytesRead != length) { status = STATUS_FILE_CORRUPT_ERROR; goto Exit; } *pLength = length; Exit: if (hFile != NULL) { ZwClose(hFile); } if (!NT_SUCCESS(status) && *pBuffer != NULL) { ExFreePoolWithTag(*pBuffer, 'Tag3'); *pBuffer = NULL; *pLength = 0; } return status; } // 写入缓存到文件 NTSTATUS WriteBufferToFile(PFLT_CALLBACK_DATA Data, PFLT_RELATED_OBJECTS FltObjects, PVOID pBuffer, ULONG Length) { NTSTATUS status = STATUS_SUCCESS; HANDLE hFile = NULL; OBJECT_ATTRIBUTES objAttr; IO_STATUS_BLOCK ioStatus; LARGE_INTEGER byteOffset; InitializeObjectAttributes(&objAttr, &Data->Iopb->TargetFileObject->FileName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); status = FltCreateFile(FltObjects->Instance, FltObjects->FileObject, &hFile, FILE_WRITE_DATA, &objAttr, &ioStatus, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN_IF, FILE_NON_DIRECTORY_FILE, NULL, 0, IO_IGNORE_SHARE_ACCESS_CHECK); if (!NT_SUCCESS(status)) { goto Exit; } byteOffset.QuadPart = 0; status = ZwWriteFile(hFile, NULL, NULL, NULL, &ioStatus, pBuffer, Length, &byteOffset, NULL); if (!NT_SUCCESS(status)) { goto Exit; } Exit: if (hFile != NULL) { ZwClose(hFile); } return status; } // AES加密 NTSTATUS EncryptData(PVOID pData, ULONG Length, PVOID pKey, ULONG KeyLength) { NTSTATUS status = STATUS_SUCCESS; HCRYPTPROV hProv = 0; HCRYPTKEY hKey = 0; ULONG blockSize = 0; ULONG bufferLength = 0; PVOID pBuffer = NULL; // 获取加密算法的块大小 if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) { status = STATUS_INTERNAL_ERROR; goto Exit; } if (!CryptCreateHash(hProv, CALG_SHA_256, 0, 0, NULL, NULL)) { status = STATUS_INTERNAL_ERROR; goto Exit; } if (!CryptDeriveKey(hProv, CALG_AES_256, NULL, 0, &hKey)) { status = STATUS_INTERNAL_ERROR; goto Exit; } if (!CryptGetKeyParam(hKey, KP_BLOCKLEN, (PBYTE)&blockSize, &bufferLength, 0)) { status = STATUS_INTERNAL_ERROR; goto Exit; } // 分配缓存 bufferLength = ROUND_UP(Length, blockSize); pBuffer = ExAllocatePoolWithTag(NonPagedPool, bufferLength, 'Tag4'); if (pBuffer == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; goto Exit; } RtlZeroMemory(pBuffer, bufferLength); RtlCopyMemory(pBuffer, pData, Length); // 加密数据 if (!CryptEncrypt(hKey, NULL, TRUE, 0, (PBYTE)pBuffer, &Length, bufferLength)) { status = STATUS_INTERNAL_ERROR; goto Exit; } RtlCopyMemory(pData, pBuffer, Length); Exit: if (hKey != 0) { CryptDestroyKey(hKey); } if (hProv != 0) { CryptReleaseContext(hProv, 0); } if (pBuffer != NULL) { ExFreePoolWithTag(pBuffer, 'Tag4'); } return status; } // AES解密 NTSTATUS DecryptData(PVOID pData, ULONG Length, PVOID pKey, ULONG KeyLength) { NTSTATUS status = STATUS_SUCCESS; HCRYPTPROV hProv = 0; HCRYPTKEY hKey = 0; ULONG blockSize = 0; ULONG bufferLength = 0; PVOID pBuffer = NULL; // 获取解密算法的块大小 if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) { status = STATUS_INTERNAL_ERROR; goto Exit; } if (!CryptCreateHash(hProv, CALG_SHA_256, 0, 0, NULL, NULL)) { status = STATUS_INTERNAL_ERROR; goto Exit; } if (!CryptDeriveKey(hProv, CALG_AES_256, NULL, 0, &hKey)) { status = STATUS_INTERNAL_ERROR; goto Exit; } if (!CryptGetKeyParam(hKey, KP_BLOCKLEN, (PBYTE)&blockSize, &bufferLength, 0)) { status = STATUS_INTERNAL_ERROR; goto Exit; } // 分配缓存 bufferLength = ROUND_UP(Length, blockSize); pBuffer = ExAllocatePoolWithTag(NonPagedPool, bufferLength, 'Tag5'); if (pBuffer == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; goto Exit; } RtlZeroMemory(pBuffer, bufferLength); RtlCopyMemory(pBuffer, pData, Length); // 解密数据 if (!CryptDecrypt(hKey, NULL, TRUE, 0, (PBYTE)pBuffer, &Length)) { status = STATUS_INTERNAL_ERROR; goto Exit; } RtlCopyMemory(pData, pBuffer, Length); Exit: if (hKey != 0) { CryptDestroyKey(hKey); } if (hProv != 0) { CryptReleaseContext(hProv, 0); } if (pBuffer != NULL) { ExFreePoolWithTag(pBuffer, 'Tag5'); } return status; } // 处理文件读取操作 FLT_PREOP_CALLBACK_STATUS PreReadCallback(PFLT_CALLBACK_DATA Data, PCFLT_RELATED_OBJECTS FltObjects, PVOID* CompletionContext) { NTSTATUS status = STATUS_SUCCESS; PFILE_OBJECT pFileObject = FltObjects->FileObject; PVOID pBuffer = NULL; ULONG length = 0; PDOUBLE_BUFFER pDoubleBuffer = NULL; // 检查文件对象是否是普通文件 if ((pFileObject->Flags & FO_STREAM_FILE) != 0) { goto Exit; } // 检查文件大小是否超过双缓存的总长度 if (pFileObject->SectionObjectPointer->FileSize.QuadPart > MAX_DOUBLE_BUFFER_LENGTH) { goto Exit; } // 创建双缓存 pDoubleBuffer = ExAllocatePoolWithTag(NonPagedPool, sizeof(DOUBLE_BUFFER), 'Tag6'); if (pDoubleBuffer == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; goto Exit; } status = InitializeDoubleBuffer(pDoubleBuffer, (ULONG)pFileObject->SectionObjectPointer->FileSize.QuadPart); if (!NT_SUCCESS(status)) { goto Exit; } // 读取文件到缓存 status = ReadFileToBuffer(Data, FltObjects, &pDoubleBuffer->DataBuffer, &pDoubleBuffer->DataLength); if (!NT_SUCCESS(status)) { goto Exit; } // 复制数据到辅助缓存 EnterCriticalSection(&pDoubleBuffer->Lock); RtlCopyMemory(pDoubleBuffer->AuxBuffer, pDoubleBuffer->DataBuffer, pDoubleBuffer->DataLength); pDoubleBuffer->AuxLength = pDoubleBuffer->DataLength; LeaveCriticalSection(&pDoubleBuffer->Lock); // 加密缓存中的数据 status = EncryptData(pDoubleBuffer->DataBuffer, pDoubleBuffer->DataLength, g_Key, g_KeyLength); if (!NT_SUCCESS(status)) { goto Exit; } // 将双缓存设置为完成上下文 *CompletionContext = pDoubleBuffer; Exit: if (!NT_SUCCESS(status)) { if (pDoubleBuffer != NULL) { DestroyDoubleBuffer(pDoubleBuffer); ExFreePoolWithTag(pDoubleBuffer, 'Tag6'); } Data->IoStatus.Status = status; return FLT_PREOP_COMPLETE; } return FLT_PREOP_SYNCHRONIZE; } // 处理文件写入操作 FLT_POSTOP_CALLBACK_STATUS PostWriteCallback(PFLT_CALLBACK_DATA Data, PCFLT_RELATED_OBJECTS FltObjects, PVOID CompletionContext, FLT_POST_OPERATION_FLAGS Flags) { NTSTATUS status = STATUS_SUCCESS; PFILE_OBJECT pFileObject = FltObjects->FileObject; PDOUBLE_BUFFER pDoubleBuffer = (PDOUBLE_BUFFER)CompletionContext; // 检查文件对象是否是普通文件 if ((pFileObject->Flags & FO_STREAM_FILE) != 0) { goto Exit; } // 复制数据到辅助缓存 EnterCriticalSection(&pDoubleBuffer->Lock); RtlCopyMemory(pDoubleBuffer->AuxBuffer, pDoubleBuffer->DataBuffer, pDoubleBuffer->DataLength); pDoubleBuffer->AuxLength = pDoubleBuffer->DataLength; LeaveCriticalSection(&pDoubleBuffer->Lock); // 解密辅助缓存中的数据 status = DecryptData(pDoubleBuffer->AuxBuffer, pDoubleBuffer->AuxLength, g_Key, g_KeyLength); if (!NT_SUCCESS(status)) { goto Exit; } // 写入缓存到文件 status = WriteBufferToFile(Data, FltObjects, pDoubleBuffer->AuxBuffer, pDoubleBuffer->AuxLength); if (!NT_SUCCESS(status)) { goto Exit; } Exit: if (pDoubleBuffer != NULL) { DestroyDoubleBuffer(pDoubleBuffer); ExFreePoolWithTag(pDoubleBuffer, 'Tag6'); } Data->IoStatus.Status = status; return FLT_POSTOP_FINISHED_PROCESSING; } // 注册minifilter回调 FLT_PREOP_CALLBACK_STATUS PreOperationCallback(PFLT_CALLBACK_DATA Data, PCFLT_RELATED_OBJECTS FltObjects, PVOID* CompletionContext) { switch (Data->Iopb->MajorFunction) { case IRP_MJ_READ: return PreReadCallback(Data, FltObjects, CompletionContext); default: return FLT_PREOP_SUCCESS_WITH_CALLBACK; } } FLT_POSTOP_CALLBACK_STATUS PostOperationCallback(PFLT_CALLBACK_DATA Data, PCFLT_RELATED_OBJECTS FltObjects, PVOID CompletionContext, FLT_POST_OPERATION_FLAGS Flags) { switch (Data->Iopb->MajorFunction) { case IRP_MJ_WRITE: return PostWriteCallback(Data, FltObjects, CompletionContext, Flags); default: return FLT_POSTOP_FINISHED_PROCESSING; } } // 注册minifilter驱动程序 NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) { NTSTATUS status = STATUS_SUCCESS; PFLT_FILTER pFilter = NULL; OBJECT_ATTRIBUTES objAttr; UNICODE_STRING uniString; // 初始化互斥锁 InitializeCriticalSection(&g_Lock); // 初始化加密密钥 RtlInitUnicodeString(&uniString, L"Password"); status = BCryptGenerateSymmetricKey(&g_hKey, &g_Algorithm, NULL, 0, (PUCHAR)uniString.Buffer, uniString.Length, 0); if (!NT_SUCCESS(status)) { goto Exit; } // 创建过滤器 RtlInitUnicodeString(&uniString, L"FileEncryptionFilter"); InitializeObjectAttributes(&objAttr, NULL, OBJ_KERNEL_HANDLE, NULL, NULL); status = FltCreateFilter(&g_FilterHandle, FLT_REGISTRATION_VERSION, &g_FilterRegistration, &g_FilterContext, &pFilter); if (!NT_SUCCESS(status)) { goto Exit; } // 注册回调函数 status = FltRegisterFilter(pFilter, DriverObject, &uniString, &g_FilterHandle); if (!NT_SUCCESS(status)) { goto Exit; } status = FltStartFiltering(pFilter); if (!NT_SUCCESS(status)) { goto Exit; } Exit: if (!NT_SUCCESS(status)) { if (g_hKey != NULL) { BCryptDestroyKey(g_hKey); g_hKey = NULL; } if (pFilter != NULL) { FltUnregisterFilter(pFilter); } if (g_FilterHandle != NULL) { FltClose(g_FilterHandle); } DeleteCriticalSection(&g_Lock); } return status; } // 卸载minifilter驱动程序 VOID DriverUnload(PDRIVER_OBJECT DriverObject) { PFLT_FILTER pFilter = NULL; if (g_FilterHandle != NULL) { FltGetFilterFromInstance(g_FilterHandle, &pFilter); FltStopFiltering(pFilter); FltUnregisterFilter(pFilter); FltClose(g_FilterHandle); } if (g_hKey != NULL) { BCryptDestroyKey(g_hKey); g_hKey = NULL; } DeleteCriticalSection(&g_Lock); } ``` 这只是一个简单的示例,实际实现中可能需要更多的代码来处理各种情况和错误。此外,请注意,此示例仅用于演示目的,并且未经过完整测试或优化,因此可能存在问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值