-
Notifications
You must be signed in to change notification settings - Fork 148
双缓冲部分的设计
如下图,缓冲管理器管理着一块内存形式的文件,应用程序大部分的读写操作都是直接和这块内存交互的。
下图是一次缓冲读操作,如果这块缓冲没有建立,那么在缓冲管理器建立以后,由System发起一次NonCachedIo、PagingIo的读操作请求,去磁盘中将数据读入缓冲之中。
单一缓冲时,授权进程读操作后,缓冲内是明文,此时非授权进程再读缓冲,也会读到明文,这样会导致数据泄露。
所以本课题使用双缓冲,授权进程和非授权进程分别使用明文缓冲和密文缓冲,两个缓冲之间互不干扰,相对独立。
双缓冲即使用原来的缓冲作为明文缓冲,新建的缓冲作为密文缓冲。主要涉及到密文缓冲的创建与销毁,以及密文缓冲与明文缓冲的同步问题。密文缓冲不允许下发非缓冲写请求到文件系统驱动,它的非缓冲读请求不解密,因而应用程序会显示密文。如图
缓冲是建立在FileObject->SectionObjectPointer结构体指针上的,如下图所示。
本课题在minifilter内的私有密文缓冲指针ShadowSectionObjectPointer的基础上建立密文缓冲,替换掉非授权进程原始的SectionObjectPointer指针;而授权进程仍使用文件系统的原始明文缓冲。
至于为什么使用这种实现方式,可以参考开发文档这一节。
非授权进程原始的SectionObjectPointer指针的替换在PostCreate中。
FileObject.c->PocInitShadowSectionObjectPointers
ExEnterCriticalRegionAndAcquireResourceExclusive(StreamContext->Resource);
StreamContext->OriginSectionObjectPointers = FileObject->SectionObjectPointer;
ExReleaseResourceAndLeaveCriticalRegion(StreamContext->Resource);
FileObject->SectionObjectPointer = StreamContext->ShadowSectionObjectPointers;
Status = FltReadFileEx(FltObjects->Instance, FileObject, &ByteOffset, //密文缓冲的创建
sizeof(Buffer), &Buffer, 0, NULL, NULL, NULL, NULL, NULL);
if (!NT_SUCCESS(Status) && STATUS_END_OF_FILE != Status)
{
PT_DBG_PRINT(PTDBG_TRACE_ROUTINES,
("PocInitShadowSectionObjectPointers->FltReadFileEx init ciphertext cache failed. Status = 0x%x\n", Status));
goto EXIT;
}
if (!CcIsFileCached(FileObject)) //判断是否创建成功
{
PT_DBG_PRINT(PTDBG_TRACE_ROUTINES, ("PocInitShadowSectionObjectPointers->after FltReadFileEx file doesn't have cache.\n"));
Status = STATUS_UNSUCCESSFUL;
goto EXIT;
}
Status = STATUS_SUCCESS;
if (FltObjects->FileObject->SectionObjectPointer
== StreamContext->ShadowSectionObjectPointers)
{
PT_DBG_PRINT(PTDBG_TRACE_ROUTINES, ("PocPostReadOperation->Don't decrypt ciphertext cache map.\n"));
Status = FLT_POSTOP_FINISHED_PROCESSING;
/*
* 如果想单独验证双缓冲是否建立,这里的读操作也要不执行,直接返回,
* 如果能看到乱码和空白,说明双缓冲建立成功。
* Data->IoStatus.Status = STATUS_SUCCESS;
* Data->IoStatus.Information = Data->Iopb->Parameters.Read.Length;
* Status = FLT_PREOP_COMPLETE;
*/
goto EXIT;
}
if (FltObjects->FileObject->SectionObjectPointer == StreamContext->ShadowSectionObjectPointers
&& NonCachedIo)
{
PT_DBG_PRINT(PTDBG_TRACE_ROUTINES,
("PocPreWriteOperation->Block StartingVbo = %d ProcessName = %ws File = %ws.\n",
Data->Iopb->Parameters.Write.ByteOffset.LowPart, ProcessName, StreamContext->FileName));
Data->IoStatus.Status = STATUS_SUCCESS;
Data->IoStatus.Information = Data->Iopb->Parameters.Write.Length;
Status = FLT_PREOP_COMPLETE;
goto ERROR;
}
如果读者打算写一个双缓冲透明加解密驱动,从这里开始就可以创建项目了,首先在PreCreate中过滤一下想要处理的文件类型,比如txt之类的,这里不区分进程为授权还是非授权进程,然后把双缓冲实现一下。
正常情况下,用记事本打开txt文件,看到的只有乱码和空白,没有正常的数据;写入一些数据,关机重启后,不启动驱动打开文件,数据实际上并没有写入磁盘里,说明双缓冲建立成功了。