Giter Club home page Giter Club logo

foks-trot's Introduction

License Driver Test PR Issue
FOKS-TROT

FOKS-TROT

基于Minifilter框架的双缓冲透明加解密驱动

It's a minifilter used for transparent-encrypting. English

Foreword:

Foxtrot是一个实验性项目,且作者对于文件系统等的理解难免会存在偏差,因此可能会产生误导,望读者辩证的学习,并且请读者遵循相关的开源协议。且本项目5月12号以前的版本已作为毕设,如有雷同,纯属雷同((/- -)/)
经过五个月的维护,Foxtrot迎来了第一个稳定版1.0.0.2265版,项目现在是可以稳定运行在Windows 10 x64各版本上的(应该可以),建议大家重新clone一下,不过本版本不支持之前驱动加密过的文件(见第11条)。
P.S.已将项目打包成exe安装包,可以不用手动编译项目了

Description:

Foxtrot是一个使用minifilter框架的双缓冲透明加密解密过滤驱动,当进程有写入特定的文件扩展名(比如txt,docx)文件的倾向时自动加密文件。授权进程想要读取密文文件时自动解密,非授权进程不解密,显示密文,且不允许修改密文。 桌面端可以发送特权加密和特权解密命令,实现单独加密或解密文件;或者配置进程权限,机密文件夹,需加密的文件类型。

1.本项目使用双缓冲,授权进程和非授权进程分别使用明文缓冲和密文缓冲;  
2.使用StreamContext存放驱动运行时的文件信息,在文件的尾部使用4KB文件标识尾储存解密所需信息;  
3.使用AES-128 ECB模式,16个字节以内分别在SetInfo->EOF和WriteCachedIo时扩展文件大小到16字节,
  大于16个字节,使用密文挪用(Ciphertext stealing)的方法,避免明文必须分块对齐的问题;  
4.Write和Read使用SwapBuffers的方式进行透明加密解密;  
5.特权加密和特权解密使用重入(Reentry)的方式,使驱动加密解密文件;  
6.在FileRenameInformationEx和FileRenameInformation重命名操作时做处理,
  可以自动加密解密docx,doc,pptx,ppt,xlsx,xls等使用tmp文件重命名方式读写的文件;  
7.注册进程相关回调,使用链表统一管理授权与非授权进程;
  注册进程与线程对象回调,保护进程EPROCESS,ETHREAD对象;对授权进程的代码段进行完整性校验。  
8.设置机密文件夹,文件处于该文件夹下才会透明加密,
  并可以从桌面PocUser配置机密文件夹与需管控的文件扩展名 @wangzhankun  
9.PostOperation统一使用函数FltDoCompletionProcessingWhenSafed(PostRead除外),
  InstanceSetup时使用Dpc+WorkItem回调(封装为PocDoCompletionProcessingWhenSafe),
  避免在DISPATCH_LEVEL时出现IRQL_NOT_LESS_OR_EQUAL之类的蓝屏;  
10.PostClose时使用单独的线程,等待操作该文件的所有授权进程结束以后,
  再重入加密或写入文件标识尾,解决了docx类文件的死锁问题;  
11.将ULONG改成LONGLONG,原则上可以支持4GB以上文件(目前特权加密和特权解密暂不支持4GB以上文件,  
  而且在内存有限的情况下,特权解密有可能会因非分页内存的缺少而失败,不想写了,这里可以放循环里读写大文件) 
12.用WPF写了用户界面,可以配置授权进程,需管控的文件类型,机密文件夹,以及特权加密、解密文件;  
  使用InstallShield打包安装包;  
13.增加进程权限:备份权限进程,比如VMTools和explorer.exe,可以将完整的密文文件从虚拟机中拷贝出,或者  
  从机密文件夹向外拷贝密文文件,和粘贴文件到机密文件夹(未加密的自动加密,已加密的重复加密后自动解密一次)    
14.在Write加密以后,ObDereferenceObject一个之前建好的FileObject,触发Close创建线程准备写入尾或重入加密;  
15.允许驱动特权加密或解密机密文件夹以外的文件;驱动卸载时清除明文缓冲,防止明文泄露;  
16.WRITE_THROUGH时,Ntfs并不会在PagingIo之前更新Fcb->FileSize,它使用TopLevelIrpContext + 184截断  
  PagingIo的数据,在CachedIo返回时更新该FileSize,所以这里使用SC->WriteThroughFileSize暂时保存FileSize。    

Build & Installation:

1.建议在Windows 10 x64,NTFS环境运行

已测试系统及软件版本:  
Windows 10 x64 1809(17763.2928) LTSC 企业版 [WPS 11.1.0.11365]  
Windows 10 x64 1903(18362.30) 教育版 [Microsoft Office Professional Plus 2021 x64] 
                                    [WPS 11.1.0.11744] [360安全卫士 15.0.0.1061]
Windows 10 x64 1909(18363.592) 教育版  [WPS 11.1.0.11744]  
Windows Server 2019 DataCenter 1809(17763.379)  

2.系统开启测试模式,cmd以管理员身份运行,输入bcdedit /set testsigning on后重启电脑
3.驱动日志输出(可选)

找到注册表项:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Debug Print Filter  
没有Debug Print Filter就新建,在这个键下新建dword值 “default”,十六进制为0xF,然后重启电脑  
以管理员身份运行DebugView,设置`Capture->Capture Kernel`显示驱动日志  

4.下载安装包(可选)

Download
如果下载安装包,那就不需要手动编译项目了,可以直接跳到第10步
5.安装并导入CNG库

https://www.microsoft.com/en-us/download/details.aspx?id=30688  
需要在微软官网下载Cryptographic Provider Development Kit,  
项目->属性的VC++目录的包含目录,库目录设置相应的位置  
链接器的常规->附加库目录C:\Windows Kits\10\Cryptographic Provider Development Kit\Lib\x64  
输入->附加依赖项ksecdd.lib

6.在Config.c中设置目标文件扩展名,机密文件夹,以及授权进程,备份进程
7.使用Visual Studio 2019编译Debug x64 Poc驱动,UserDll(可选)和UserPanel(可选)
8.鼠标右键菜单增加特权加密和特权解密功能(可选)

这个功能可以直接用鼠标右键选择一个文件,然后点击特权加密或特权解密,不需要cmd命令行了
新建注册表项:HKEY_CLASSES_ROOT\*\shell\Encrypt,将这个键的“默认”的数据改为特权加密
新建注册表项:HKEY_CLASSES_ROOT\*\shell\Encrypt\command,
将这个键的“默认”值的数据改为 "路径\PocUserPanel.exe" 8 "%1"

新建注册表项:HKEY_CLASSES_ROOT\*\shell\Decrypt,将这个键的“默认”的数据改为特权解密
新建注册表项:HKEY_CLASSES_ROOT\*\shell\Decrypt\command,
将这个键的“默认”值的数据改为 "路径\PocUserPanel.exe" 4 "%1"

9.如果使用OsrLoader之类的加载器加载驱动,Type请选择Minifilter,也可以使用cmd加载,如下

::加载
rundll32.exe setupapi.dll,InstallHinfSection DefaultInstall 132 路径\Poc.inf
net start Poc
pause
::卸载
net stop Poc
rundll32.exe setupapi.dll,InstallHinfSection DefaultUninstall 132 路径\Poc.inf

10.驱动加载以后,测试是否正常工作(详见TestManual.md)

用notepad.exe(默认配置为授权进程)写入txt文件一些数据,
然后使用wordpad.exe(默认配置为非授权进程)打开,只能看到杂乱的数据,说明加密成功。  
P.S. 文件加密以后,加密标识尾只有在关机重启且不开驱动的情况下才能看到。  

bandicam-2022-06-07-14-17-43-706

11.使用编译好的或安装包中的PocUserPanel配置各种参数


Unfixed & Prospect:

1.授权进程"另存为"会导致明文泄露,这里可以在PreCreate判断一下是否是授权进程+有写入倾向,是,则不过滤扩展名以及路径,让文件进入驱动控制。
2.将文件标识尾改成文件标识头的方式,防止意外断电的情况。
当初写这个项目时,我对Windows内核懂得不多,所以有很多的地方从一开始架构时就有缺陷,比如密文挪用这部分,它和扩展文件大小的方法混在了一起,另外写入文件尾这一块也很笨拙,为了密文挪用这点“创新”,我妥协了很多,这导致本来可以简化的地方搞得很复杂。
我希望这个项目成为各位同僚开发时的参考,而非一个直接用的产品,双缓冲部分的实现,文件大小的扩展等等,都是值得参考的。另外我把论文和开发文档也放在了项目里,相信会有助于各位对这个项目的理解。

Credits & References:

hkx3upper:(@hkx3upper)
wangzhankun:(@wangzhankun)
MaterialDesignInXAML:(@MaterialDesignInXAML)
CSharpDesignPro:(@CSharpDesignPro)
Windows-driver-samples\filesys\fastfat:(Fastfat)
Windows-driver-samples\filesys\minifilter:(Minifilter)
Windows-Research-Kernel:(WRK)
WinNT4:(WinNT4)
基于Minifilter微框架的文件加解密系统的设计与实现 何明 2014.06
基于双缓冲过滤驱动的透明加密系统研究与实现 刘晗 2010.04
基于 IBE 和 FUSE 的双向透明文件加密系统的研究与实现 何翔 2017.04
Windows NT File System Internals - A Developer's Guide
Windows内核安全与驱动开发 谭文
Windows内核情景分析 毛德操
Windows内核原理与实现 潘爱民

License:

Foxtrot, and all its submodules and repos, unless a license is otherwise specified, are licensed under GPLv3 LICENSE.
Dependencies are licensed by their own.

foks-trot's People

Contributors

hkx3upper avatar wangzhankun avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

foks-trot's Issues

close前刷新缓冲导致程序卡死

测试程序如下:

#include <iostream>
#include <string>
#include <fstream>
#include <windows.h>

using namespace std;

const std::string root_dir("C:\\Users\\xxxx\\Desktop\\testdata\\");

void create_little_and_big_file()
{
    string file_name = root_dir + "little_and_big.txt";
    std::ofstream ofs(file_name);
    for (int i = 0; i < 5; ++i) 
    {
        ofs << "hello world\n";
        ofs.flush();
        system("pause");
    }
    for (int i = 0; i < 100; ++i) // 1.2KB
    {
        ofs << "hello world\n";
    }
    std::cout << "Press any key to close the file ..." << std::endl;
    system("pause");
    ofs.close();
}

int main(int argc, char **argv)
{
    cout << "create little and big file ..." << endl;
    create_little_and_big_file();
    return 0;
}

当测试程序执行到ofs.close()时,minifilter会转入执行刷新缓冲的操作。调用过程如下PostCloseOperation-->PocFlushOriginalCache-->FltFlushBuffers。当minifilter执行FltFlushBuffers之后会产生一个IRP_MJ_WRITE的操作并进入到minifilter的PreWritePostWrite过程。检查发现,当PreWritePostWrite正常执行成功之后,应用程序卡死,minifilter也是卡在了FltFlushBuffers。该卡死并不影响其它过程,仅仅是当前进程阻塞。

密文挪用的必要性

在文件加密时,文件大小会出现三种情况:

  1. file_size < AES_BLOCK_SIZE
  2. file_size % AES_BLOCK_SIZE == 0
  3. file_size % AES_BLOCK_SIZE != 0 && file_size > AES_BLOCK_SIZE

对于情况1,是对原始数据padding到一个AES_BLOCK_SIZE之后再进行加密的;

对于情况2,正好符合AES_ECB加密要求,不需要特殊处理

对于情况3,使用的是比较复杂的密文挪用。

请问是否有必要使用密文挪用呢?为啥情况3不能跟情况1一样都使用padding呢?情况3和情况1本质上处理起来是一样的,而现在对于情况3的处理使用密文挪用是不是设计太复杂了?是否有其必要性呢?

PocPreReadOperation逻辑问题

Read.c文件第192至195行的代码逻辑似乎有些问题。当前运行的情况是当且仅当124行、135行、145行的if判断都为false时,该代码段才会执行,这是否符合原本设计意图呢?假设,192至195行的代码成功执行了,那就表示135行的判断为false,那么,192行至195行的代码就永远不应该执行(如果被执行了,那么就与135行至142行的逻辑相互冲突。),但是事实上它是有可能被执行到的。请问正确的执行逻辑应该是什么样的呢?

内存错误Unable to get MiVisibleState

dump文件解析如下:

CORRUPTING_POOL_ADDRESS: fffff8052e8fa390: Unable to get MiVisibleState
Unable to get NonPagedPoolStart
Unable to get NonPagedPoolEnd
Unable to get PagedPoolStart
Unable to get PagedPoolEnd
unable to get nt!MmSpecialPagesInUse
 ffffc504d6d45000 

BLACKBOXBSD: 1 (!blackboxbsd)


BLACKBOXNTFS: 1 (!blackboxntfs)


BLACKBOXPNP: 1 (!blackboxpnp)


BLACKBOXWINLOGON: 1

CUSTOMER_CRASH_COUNT:  1

PROCESS_NAME:  RuntimeBroker.exe

STACK_TEXT:  
fffffe8c`204ec978 fffff805`2e18e7c8     : 00000000`0000013a 00000000`00000012 ffffc504`cea00100 ffffc504`d6d45000 : nt!KeBugCheckEx
fffffe8c`204ec980 fffff805`2e18e828     : 00000000`00000012 ffffc504`cea00280 ffffc504`cea00100 fffff805`00000080 : nt!RtlpHeapHandleError+0x40
fffffe8c`204ec9c0 fffff805`2e18e455     : ffffc504`d6e024e8 fffffe8c`204ecae4 fffffe8c`204ecae4 ffffc504`d48fa370 : nt!RtlpHpHeapHandleError+0x58
fffffe8c`204ec9f0 fffff805`2e03d98c     : 00000000`00000000 fffffe8c`204ecf50 ffff8285`de2684a8 ffffc504`d6846550 : nt!RtlpLogHeapFailure+0x45
fffffe8c`204eca20 fffff805`2de8d098     : 00000000`00000000 fffffe8c`000000c0 fffffe8c`204ecb61 00000000`000000c0 : nt!RtlpHpVsContextAllocateInternal+0x1b406c
fffffe8c`204eca80 fffff805`2e5b21c4     : ffffc504`00000000 ffffc504`d6666e50 ffff8285`63537843 fffff805`2de0715d : nt!ExAllocateHeapPool+0x888
fffffe8c`204ecbc0 fffff805`2d36b2d2     : ffffc504`d8344b20 00000000`00000008 00000000`00000000 ffffc504`00000000 : nt!ExAllocatePoolWithTag+0x64
fffffe8c`204ecc10 fffff805`2f25e17a     : ffffc504`d8344b20 fffffe8c`204ed180 00000000`00000000 00000000`00000000 : FLTMGR!FltAllocateContext+0x182
fffffe8c`204ecc50 ffffc504`d8344b20     : fffffe8c`204ed180 00000000`00000000 00000000`00000000 fffffe8c`204ecc90 : Poc+0xe17a
fffffe8c`204ecc58 fffffe8c`204ed180     : 00000000`00000000 00000000`00000000 fffffe8c`204ecc90 00000000`00000000 : 0xffffc504`d8344b20
fffffe8c`204ecc60 00000000`00000000     : 00000000`00000000 fffffe8c`204ecc90 00000000`00000000 00000000`00000000 : 0xfffffe8c`204ed180

notepad++与notepad泄露密文

测试环境

  • Windows 10
  • 最新的代码(我没有做任何修改,除了将notepad++设置为机密进程,notepad设置为非机密进程)
  • 16字节的txt文档:hello.txt,全是ascii字符
  • 机密文件夹testdata,非机密文件夹src
  • 机密进程 notepad++
  • 非机密进程notepad

bug复现

  1. 启动驱动
  2. 将hello.txt文档从非机密文件夹src拷贝到机密文件夹testdata(此时驱动会自动对该文件进行透明加密)
  3. 使用机密进程notepad++.exe打开该文档看到明文,不关闭该文档
  4. 使用非机密进程notepad打开该文档也能看到明文
  5. 关闭notepad
  6. 再次使用notepad打开该文档看到密文
  7. 如果未能复现,请关闭关闭所有进程,卸载驱动,删除机密文件夹下的hello.txt,回到第一步。这个bug还是挺好复现的,可以多试几次。

文件尾部乱码

当被修改的文件比较大时,txt超过几十W行时,此时修改保存关闭文件后,再马上打开txt
此时文件尾部会有乱码。
如果修改保存关闭文件后,等待一会儿,尾部正常无乱码。
测试环境 win10虚拟机

Write.c 非机密进程写入

在Write.c的PreWrite中,第111至121行这里的逻辑是非机密进程且NonCachedIo的情况下,由于Status被设置成FLT_PREOP_COMPLETE那么就不会再向下转发了。在这种情况下,非机密进程的非缓冲IO不是无法正常将数据写入硬盘了吗?
image

操作系统崩溃

我在依次执行以下动作后,操作系统崩溃:

  1. PocUser.exe 8 C:\Users\wangzhankun\Desktop\poc\test.txt
  2. 第一步的时候提示retval为0x1
  3. 使用notepad.exe(未授权的进程)打开该文件发现是密文
  4. 使用vscode(已授权的进程)打开该文件,系统崩溃。
  5. 重启虚拟机后(包括POC服务),使用vscode打开test.txt仍然只看得到密文,且原先可以打开test_hello.txt文件也是只能看到密文了。

死锁现象

你好,我在虚拟机测试ppt文档时,修改文档生成出.tmp会触发PocPostSetInformationOperation->FltDeleteStreamContext NewFileName = \Users\Administrator\Desktop\qd\加密流量分析功能(ETA) - 副本~0B0E52.tmp.,他然后会zwcreatefile然后走,PocReentryToEncrypt重加密,然后再运行到PocReentryToEncrypt zwcreatefile偶尔就会出现卡死现象(直接卡死到zwcreatefile函数)此时除了重启,wps无法杀掉进程重用。有没有解决方案呢?

一些其他问题

  1. 在操作word文件这块,每次编辑原文件点击保存,会创建一个.tmp文件,并将编辑内容写入到 .tmp文件,之后进行重命名。但此时写入到.tmp文件的内容并没有被加密,只有当关闭文件时,触发IRP_CLOSE等待操作进程结束才会重入加密。在编辑期间,可能会造成明文泄露,并且没有处理电源相关的IRP,在持续打开文件时,直接关机,此时文件内容也没有加密。

  2. 在IRP_CLOSE中创建的线程回调在等待相关进程结束的间隔时间可能太长,如果关闭文件后,立即快速打开文件,此时文件还处于未加密状态。

关于找不着ksecdd.lib

作者你好,我下载安装了CNG库,但是在相应的目录没有找到ksecdd.lib静态库,整台电脑中也没有找到ksecdd.lib文件,导致程序无法编译

NonCachedIo和CachedIo在双缓冲读时的区别

请问Read.c的112行和145行区分是否为缓冲IO的目的是什么呀?我看微软给出的swappedBuffer的样例里面并没有对IO是否为缓冲IO有特殊的处理。只是在对非缓冲IO需要读取的字节数做了特殊判断使其至少为一个sector的大小。

一次性读取的内存空间不足问题

PocPostReadDecrypt,和PocPreWriteOperation都是一次性分配全部的空间,但是当数据大小很大的时候不是很容易就出现内存不够的情况吗?

我看PocPostReadDecrypt的注释中说

        /*
      * 当文件大于一个块,Cache Manager将数据分多次读入缓冲,或者其他以NonCachedIo形式
     * 最后一次读的数据小于一个块的情况下,现在在倒数第二个块做一下处理
   */

似乎是分批多次读入的。但是我看实际代码还是一次性分配全部的空间哎。

因此Write.c和Read.c中的加解密是要写成分批读写的代码吧?还是说目前的代码就是分批读写的呢?

PocUserPanel项目无法成功编译

您好,我对这个工程进行编译的时候,其他三个项目都能正常编译完成,只有PocUserPanel项目编译的时候报错。
我在多方搜索下都没有办法解决,请问您有解决的方法吗?谢谢!
错误一:
MSB4018 “ResolvePackageAssets”任务意外失败。
NuGet.Frameworks.FrameworkException: Invalid framework identifier ''.

错误二:
NETSDK1013 未识别 TargetFramework 值“net5.0-windows”。可能是因为拼写错误。如果拼写正确,必须显式指定 TargetFrameworkIdentifier 和/或 TargetFrameworkVersion 属性。

对代码进行分类放置

把各个文件按照文件夹进行分类存放。在VS中,点击如下图所示的按钮即可按照文件夹视图进行编码
image

系统重启后机密进程无法正常解密

我有三个测试文件test.txt, test_vscode.txt, test_nodepad.txt。其中test.txt是在无POC驱动的情况下创建的并在启动驱动后使用PocUser.exe进行加密。test_vscode.txt是由vscode创建并写入的。test_notepad.txt是在文件夹下右键新建txt,并使用notepad打开写入的。
在最开始时,机密进程vscode可以正常打开三个文件,非机密进程notepad只能看到密文。
在重启之后,机密进程vscode只能打开test.txt文件并认为另外两个文件是二进制文件(而不是认为txt文件正常打开为密文或者明文),非机密进程notepad打开三个文件都是密文形式。
使用PocUser.exe尝试进行解密,发现RetValue为0xC0190003。(PS:需要将PocUser.exe设置为机密进程吗?)

FileObject、POC_STREAM_CONTEXT、SECTION_OBJECT_POINTERS之间的对应关系

根据SECTION_OBJECT_POINTERS structure所述:

There is a one-to-one relationship between a SECTION_OBJECT_POINTERS structure and a file stream. Multiple file objects can be associated with a particular file stream, each representing an open instance of the stream. However, only one SECTION_OBJECT_POINTERS structure can be associated with a given stream. If there are multiple file objects for a stream, the SectionObjectPointer member for all file objects must point to the same SECTION_OBJECT_POINTERS structure (that is associated with the stream).

FileObject与file stream是多对一的关系,而file stream与SECTION_OBJECT_POINTERS structure是一对一的关系。因此,对于同一份文件而言,可以有多个进程打开从而产生多个FileObject,但是该文件对应的SECTION_OBJECT_POINTERS只有一个,因此是多对一的关系。

但是在代码实现中,我们为了区分明文和密文缓冲,将OriginSectionObjectPointers供机密进程使用提供明文缓冲,ShadowSectionObjectPointers供机密进程使用提供密文缓冲。但是这两个结构体是统一封装在POC_STREAM_CONTEXT中的。

因此我的问题是设计实现中的FileObject和POC_STREAM_CONTEXT也是多对一的关系吗?

我看在代码中是通过FltGetStreamContext来获取POC_STREAM_CONTEXT的地址的,请问假设是第二次打开同一个文件,那么在此之前我们已经为同一个文件创建了POC_STREAM_CONTEXT,那么此时调用FltGetStreamContext是不是能够获取到同一个POC_STREAM_CONTEXT呢?也即是FileObject和POC_STREAM_CONTEXT也是多对一的关系,POC_STREAM_CONTEXT和file stream是一对一的关系。

请问我的理解是否正确呢?

如何进行程序打包安装

测试手册中要求要对程序进行打包和卸载的测试。请问如何对程序进行打包安装和卸载测试呀?

如何定位二进制位置

你好。我在使用windbg分析dump文件时,总是会遇到诸如poc+1790d的表示方法,请问我该如何定位到指定指令所在的源代码位置呢?

RESOURCE NOT OWNED

在复现 #40 的过程中,卸载驱动时会出现 RESOURCE NOT OWNED的蓝屏。

windbg信息如下:

3: kd> !analyze -v
*******************************************************************************
*                                                                             *
*                        Bugcheck Analysis                                    *
*                                                                             *
*******************************************************************************

RESOURCE_NOT_OWNED (e3)
A thread tried to release a resource it did not own.
Arguments:
Arg1: ffffb70d195e10c0, Address of resource
Arg2: ffffb70d10f78240, Address of thread
Arg3: 0000000000000000, Address of owner table if there is one
Arg4: 0000000000000002

Debugging Details:
------------------


KEY_VALUES_STRING: 1

    Key  : Analysis.CPU.mSec
    Value: 2733

    Key  : Analysis.DebugAnalysisManager
    Value: Create

    Key  : Analysis.Elapsed.mSec
    Value: 5484

    Key  : Analysis.Init.CPU.mSec
    Value: 4171

    Key  : Analysis.Init.Elapsed.mSec
    Value: 12499

    Key  : Analysis.Memory.CommitPeak.Mb
    Value: 87

    Key  : Bugcheck.Code.DumpHeader
    Value: 0xe3

    Key  : Bugcheck.Code.KiBugCheckData
    Value: 0xe3

    Key  : Bugcheck.Code.Register
    Value: 0xe3

    Key  : WER.OS.Branch
    Value: vb_release

    Key  : WER.OS.Timestamp
    Value: 2019-12-06T14:06:00Z

    Key  : WER.OS.Version
    Value: 10.0.19041.1


FILE_IN_CAB:  MEMORY.DMP

VIRTUAL_MACHINE:  VMware

BUGCHECK_CODE:  e3

BUGCHECK_P1: ffffb70d195e10c0

BUGCHECK_P2: ffffb70d10f78240

BUGCHECK_P3: 0

BUGCHECK_P4: 2

BLACKBOXBSD: 1 (!blackboxbsd)


BLACKBOXNTFS: 1 (!blackboxntfs)


BLACKBOXWINLOGON: 1

PROCESS_NAME:  System

STACK_TEXT:  
ffffc80a`2707d498 fffff804`6782f28d     : 00000000`000000e3 ffffb70d`195e10c0 ffffb70d`10f78240 00000000`00000000 : nt!KeBugCheckEx
ffffc80a`2707d4a0 fffff804`67650f23     : 00000000`00000000 fffff804`680db5c0 ffffb70d`10f78240 00000000`00000000 : nt!ExpReleaseResourceSharedForThreadLite+0x1de28d
ffffc80a`2707d560 fffff804`7075a430     : ffffb70d`166b33f0 ffffb70d`18aa5c70 ffffb70d`0f904780 ffffb70d`00000000 : nt!ExReleaseResourceLite+0xf3
ffffc80a`2707d5c0 fffff804`70752ef1     : ffffb70d`0f9047e0 ffffb70d`10f1fb28 00000000`00000000 ffffb70d`18b048b8 : Poc+0xa430
ffffc80a`2707d610 fffff804`66d98f22     : ffffb70d`0f9047e0 fffff804`67760008 ffffb70d`1669e010 ffffb70d`18aa5c70 : Poc+0x2ef1
ffffc80a`2707d660 fffff804`66d99b53     : ffffb70d`18aa5c68 00000000`00000000 ffffb70d`18aa5c70 ffffb70d`0f904798 : FLTMGR!DoReleaseContext+0x82
ffffc80a`2707d6a0 fffff804`66ddffb3     : ffffb70d`18aa5c50 ffffc80a`2707d799 ffffb70d`10f1fac8 fffff804`66dcc7db : FLTMGR!DeleteContextFromStreamList+0xdb
ffffc80a`2707d6e0 fffff804`66dd07a7     : 00000003`07aef2c8 ffffc80a`2707d799 00000000`00000004 00000003`07aef2c8 : FLTMGR!FltpCleanupStreamListCtrlForInstanceRemoval+0xf1a3
ffffc80a`2707d730 fffff804`66dea72a     : ffffb70d`1669e080 ffffb70d`13e77c30 ffffb70d`13e77c30 00000000`00000000 : FLTMGR!FltpFreeInstance+0x1db
ffffc80a`2707d800 fffff804`7079a08e     : fffff804`7079a1f0 00000000`00000000 00000003`00864b2a 00000000`00000000 : FLTMGR!FltUnregisterFilter+0x11a
ffffc80a`2707d8c0 fffff804`66de7ab9     : ffffc80a`00000001 ffffb70d`17f4ce30 ffffb70d`13e77c30 00000003`00864b2a : Poc+0x4a08e
ffffc80a`2707d900 fffff804`66de7d66     : ffffb70d`0fe60ba0 ffffb70d`13e77c40 ffffb70d`10a73038 ffffb70d`10a73038 : FLTMGR!FltpDoUnloadFilter+0x19d
ffffc80a`2707daf0 fffff804`67c4bc89     : ffffb70d`10f78240 fffff804`67b70380 ffffb70d`0fe60ba0 ffffc80a`276e6750 : FLTMGR!FltpMiniFilterDriverUnload+0x146
ffffc80a`2707db30 fffff804`676bfae5     : ffffb70d`00000000 00000000`00000000 ffffb70d`10f78240 fffff804`00000000 : nt!IopLoadUnloadDriver+0xdb909
ffffc80a`2707db70 fffff804`676eea75     : ffffb70d`10f78240 00000000`00000080 ffffb70d`0fe8b040 000f8067`b8bbbdff : nt!ExpWorkerThread+0x105
ffffc80a`2707dc10 fffff804`677ff428     : ffffcb00`0bc28180 ffffb70d`10f78240 fffff804`676eea20 00000000`00000000 : nt!PspSystemThreadStartup+0x55
ffffc80a`2707dc60 00000000`00000000     : ffffc80a`2707e000 ffffc80a`27078000 00000000`00000000 00000000`00000000 : nt!KiStartSystemThread+0x28


SYMBOL_NAME:  Poc+a430

MODULE_NAME: Poc

IMAGE_NAME:  Poc.sys

STACK_COMMAND:  .cxr; .ecxr ; kb

BUCKET_ID_FUNC_OFFSET:  a430

FAILURE_BUCKET_ID:  0xE3_Poc!unknown_function

OS_VERSION:  10.0.19041.1

BUILDLAB_STR:  vb_release

OSPLATFORM_TYPE:  x64

OSNAME:  Windows 10

FAILURE_ID_HASH:  {14e19972-48a8-11f4-0023-16aca111cf54}

Followup:     MachineOwner
---------

大文件右键选择打开方式导致蓝屏

我将mp4也作为了机密后缀名。在对已加密的mp4文件使用右键点击打开方式时导致电脑蓝屏,文件大小为2GB。这个右键选择打开方式的动作在大文件下会频繁导致系统宕机。而且每次dump文件都有所不同。其中一次dump文件如下:

FILE_IN_CAB:  041622-12875-01.dmp

VIRTUAL_MACHINE:  VMware

BUGCHECK_CODE:  3b

BUGCHECK_P1: c0000005

BUGCHECK_P2: fffff8073d28a280

BUGCHECK_P3: fffff80740eb6920

BUGCHECK_P4: 0

CONTEXT:  fffff80740eb6920 -- (.cxr 0xfffff80740eb6920)
rax=0073002e00740073 rbx=0073002e00740073 rcx=000000009a0c3111
rdx=0000000000020000 rsi=0000000000000023 rdi=ffffc087d4f03ae0
rip=fffff8073d28a280 rsp=ffff828db3bada50 rbp=ffff828db3badac8
 r8=70ed49994e8c7f31  r9=0000000000000000 r10=0000000000000001
r11=0000000000000001 r12=0000000000000002 r13=ffffc087d4f02000
r14=ffffc087d5000280 r15=0000000000000000
iopl=0         nv up ei pl nz na pe nc
cs=0010  ss=0018  ds=002b  es=002b  fs=0053  gs=002b             efl=00050202
nt!RtlpHpVsChunkSplit+0x590:
fffff807`3d28a280 8b4bf8          mov     ecx,dword ptr [rbx-8] ds:002b:0073002e`0074006b=????????
Resetting default scope

BLACKBOXBSD: 1 (!blackboxbsd)


BLACKBOXNTFS: 1 (!blackboxntfs)


BLACKBOXWINLOGON: 1

CUSTOMER_CRASH_COUNT:  1

PROCESS_NAME:  smartscreen.exe

STACK_TEXT:  
ffff828d`b3bada50 fffff807`3d289b1a     : 00000002`00000002 ffffc087`d4f038b0 00000000`00000002 ffff828d`00000000 : nt!RtlpHpVsChunkSplit+0x590
ffff828d`b3badb10 fffff807`3d28d098     : 00000000`00000000 00000000`00000220 ffff828d`b3badc51 00000000`00000220 : nt!RtlpHpVsContextAllocateInternal+0x1fa
ffff828d`b3badb70 fffff807`3d9b21c4     : ffff828d`00000000 00000000`00000000 ffffab88`646e6274 fffff807`3d3fb700 : nt!ExAllocateHeapPool+0x888
ffff828d`b3badcb0 fffff807`3906b4e3     : ffffab88`896b0f00 ffffc087`d54c6598 ffff828d`b3baf168 ffff828d`00000000 : nt!ExAllocatePoolWithTag+0x64
ffff828d`b3badd00 ffffab88`896b0f00     : ffffc087`d54c6598 ffff828d`b3baf168 ffff828d`00000000 00000000`00000000 : Poc+0xb4e3
ffff828d`b3badd08 ffffc087`d54c6598     : ffff828d`b3baf168 ffff828d`00000000 00000000`00000000 ffffc087`d54c65a8 : 0xffffab88`896b0f00
ffff828d`b3badd10 ffff828d`b3baf168     : ffff828d`00000000 00000000`00000000 ffffc087`d54c65a8 00000000`00000374 : 0xffffc087`d54c6598
ffff828d`b3badd18 ffff828d`00000000     : 00000000`00000000 ffffc087`d54c65a8 00000000`00000374 ffff828d`b3baf168 : 0xffff828d`b3baf168
ffff828d`b3badd20 00000000`00000000     : ffffc087`d54c65a8 00000000`00000374 ffff828d`b3baf168 00000000`00000030 : 0xffff828d`00000000


SYMBOL_NAME:  Poc+b4e3

MODULE_NAME: Poc

IMAGE_NAME:  Poc.sys

STACK_COMMAND:  .cxr 0xfffff80740eb6920 ; kb

BUCKET_ID_FUNC_OFFSET:  b4e3

FAILURE_BUCKET_ID:  AV_Poc!unknown_function

OS_VERSION:  10.0.19041.1

BUILDLAB_STR:  vb_release

OSPLATFORM_TYPE:  x64

OSNAME:  Windows 10

FAILURE_ID_HASH:  {b3630e6e-cea7-1db4-2fe3-c51d8bfb0503}

Followup:     MachineOwner
---------

手动加解密独占

手动加解密时,FltCreateFileEx似乎并不能独占打开,可能会导致潜在的数据丢失。

bug复现

  1. 用非机密进程notepad打开测试文档,写入若干字节并保存,但是不关闭
  2. 使用PocUserPannel对该文档进行特权加密,加密成功
  3. 关闭notepad。使用机密进程notepad++打开该文档,会出现两种情况,一是可能会看到乱码(小概率),二是notepad写入的数据丢失了。

补充说明

我这里只是测试了一种情况。关于对要进行特权加密和特权解密的文档可能处于各种情况,都有可能会对文件造成损坏。对于各种打开、写入等的情况的处理太过复杂。

我的建议是,PocUserPannel或者驱动首先对要进行特权加密/特权解密的文件进行扫描,如果发现该文档被某个进程持有,那么就不能进行加解密。

另外如果驱动正在对文件进行特权加解密,那么在PreCreate中就拒绝所有的尝试打开操作,直至文件加密/解密完成。

关于这个功能,你有什么建议吗?

StartingVbo是否会溢出

我在测试时拷贝了一个2G大小的文件,观察发现StartingVbo增长得很快。检查代码发现,StartingVbo是ULONG类型,那么当文件超过4G时,是会发生溢出吧?

typedef struct _POC_PAGE_TEMP_BUFFER
{
    ULONG StartingVbo;
    ULONG ByteCount;
    PCHAR Buffer;

}POC_PAGE_TEMP_BUFFER, * PPOC_PAGE_TEMP_BUFFER;

FltLockUserBuffer ERROR

实验环境:

  • Windows自带的视频播放器(非机密进程)
  • 加密后的mp4文件

在使用自带视频播放器尝试打开mp4文件时,PostRead函数的FltLockUserBuffer函数报错。主要信息如下:

INVALID_PROCESS_ATTACH_ATTEMPT (5)
Arguments:
Arg1: ffffcf8fa3b71080
Arg2: ffffcf8fa0618300
Arg3: 0000000000000000
Arg4: 0000000000000001

Debugging Details:
------------------


KEY_VALUES_STRING: 1

    Key  : Analysis.CPU.Sec
    Value: 3

    Key  : Analysis.DebugAnalysisProvider.CPP
    Value: Create: 8007007e on LAPTOP-MR01PTCV

    Key  : Analysis.DebugData
    Value: CreateObject

    Key  : Analysis.DebugModel
    Value: CreateObject

    Key  : Analysis.Elapsed.Sec
    Value: 215

    Key  : Analysis.Memory.CommitPeak.Mb
    Value: 74

    Key  : Analysis.System
    Value: CreateObject


BUGCHECK_CODE:  5

BUGCHECK_P1: ffffcf8fa3b71080

BUGCHECK_P2: ffffcf8fa0618300

BUGCHECK_P3: 0

BUGCHECK_P4: 1

PROCESS_NAME:  svchost.exe

DPC_STACK_BASE:  FFFF810BCC430FB0

PreWrite的缓冲IO处理不当

commit ID为 8f348b2f529122b6c14911052e5f553a3fa7cad0的这一次提交里面对于非缓冲IO仅考虑了FileSize < AES_BLOCK_SIZE的情况,并没有对其它情况进行处理。

image

word和WPS的写入操作

你好。我在调试word的透明加密时,无论是使用FileSpy还是Process monitor都没有发现IRP_MJ_WRITE或者WritFile的调用。请问您知道word是使用的什么系统API吗?

手动加密bug

Discussed in #32

Originally posted by wangzhankun June 13, 2022

手动加解密的部分

我在想,既然是手动加解密的功能,那就应该不考虑文件扩展名、文件是否处于机密文件夹下面。只要用户有加密需求,就应当给用户进行加密。如果是机密文件夹下的机密拓展名的文件的话,似乎也没有手动加解密的需求。

因此关于手动加解密的部分,我想把它改成无论任何文件都能加密的形式。

这个BUG是这样的:
CommPort.c->PocReentryToEncrypt->PocReentryToGetStreamContext->PocFindOrCreateStreamContext,由于是要手动加密的文档,不存在StreamContext,而在PocReentryToGetStreamContext调用PocFindOrCreateStreamContext时没有要求创建StreamContext。在PocReentryToEncrypt中将status修改为了POC_IRRELEVENT_FILE_EXTENSION,因此从外界看来是由于文件拓展名导致的。

PocPostCreateOperation->PocGetProcessName failed

image_212

在代码中Data->IoStatus.Status!=STATUS_SUCCESS,但是我打印出来的PocGetProcessName 的返回值却是STATUS_SUCCESS。我使用记事本和vscode打开一个txt文档都可以打开,但是驱动总是会跳到Data->IoStatus.Status!=STATUS_SUCCESS的处理函数。

特殊读写序列下文件无法写入,数据全部丢失

环境

  • 测试文件:机密文件夹下新写入的机密后缀名的txt文档
  • 写入进程:机密进程
  • 代码:你这边的最新的代码
  • 测试程序:TEST.exe见后文,需要将其设置为机密进程
  • 机密进程:notepad++.exe
  • 非机密进程:notepad.exe

bug复现步骤

  1. 运行驱动
  2. 运行TEST.exe向机密文件夹下写入文件,运行完毕后关闭该程序
  3. 使用机密进程notepad++.exe打开该文件,并删除全部内容,保存。关闭程序
  4. 再次运行TEST.exe向同一个文件写入数据,运行完毕后关闭该程序
  5. 使用机密进程notepad++.exe打开该文件,发现无任何数据
  6. 关闭驱动
  7. 使用notepad++.exe打开该文件,无任何数据且没有文件标识尾

日志

DESKTOP-RPF0QIQ.LOG

测试程序

#include <Windows.h>
#include <cstdio>
using namespace std;
int main(int argc, char const* argv[])
{
	// CreateFile 共享打开文件
	HANDLE hFile = CreateFileW(
		L"C:\\Users\\wangzhankun\\Desktop\\testdata\\hello.txt",
		//L"C:\\Users\\wangzhankun\\Desktop\\123src\\hello.txt",
		GENERIC_WRITE,
		FILE_SHARE_READ,
		NULL,
		OPEN_ALWAYS,
		FILE_FLAG_WRITE_THROUGH,
		NULL);

	// 判断文件是否打开成功
	if (hFile == INVALID_HANDLE_VALUE)
	{
		printf("CreateFile failed with error %d\n", GetLastError());
		goto EXIT;
	}

	// ReadFile 读取文件 
	for (int i = 0; i < 30; i++)
	{

		DWORD dwBytesWrite = 0;
		WCHAR szBuffer[100] = { L"1\n" };
		BOOL bWrite = WriteFile(hFile, szBuffer, wcslen(szBuffer) * sizeof(WCHAR), &dwBytesWrite, NULL);
		if (bWrite == FALSE)
		{
			printf("WriteFile failed with error %d\n", GetLastError());
			goto EXIT;
		}


		printf("%dth\n", i);
		Sleep(1000); // 每隔1秒读取一次
	}

EXIT:
	// CloseHandle 关闭文件
	if (hFile != INVALID_HANDLE_VALUE)
		CloseHandle(hFile);

	system("pause");

	return 0;
}

LengthReturned < 0 蓝屏

当被修改的文件比较大时,txt超过70W行左右,PocPreWriteOperation函数中的:
LengthReturned = FileSize - StartingVbo; //此时StartingVbo远远大于FileSize ,导致LengthReturned 为负数
导致蓝屏RtlMoveMemory(
StreamContext->PageNextToLastForWrite.Buffer +
StreamContext->PageNextToLastForWrite.ByteCount,
OrigBuffer, LengthReturned);

PAGED_CODE中断

驱动在运行到PocPostReadOperation时,会跳入到PAGED_CODE引发中断,导致系统崩溃。请问这个原因是什么呢?该如何解决呢?

PreWrite 写入前加密

在写入之前,会对缓冲区中的数据进行加密。根据设计,如果FileSize<AES_BLOCK_SIZE则采用流式加密,如果是最后一个块的大小不足AES_BLOCK_SIZE则会采用Steal的方式。

我的问题是,假设用户写入了10个字节,并通过刷新缓冲区的方式写入硬盘,此时FileSize是小于AES_BLOCK_SIZE的,但是过了一段时间之后,用户一次性写入10MB的数据。那么在解密的时候会不会出现问题呢?

添加机密文件夹的设计

目前的驱动设计是在全盘进行加解密,在测试阶段可能会由于驱动的错误导致某些文件被错误加密而出现无法正常打开的情况,因此我添加了机密文件夹的设计。透明加解密被限制在机密文件夹这一层级。请问原作者是否同意把这一设计引入呢?如果可以的话,我就把该设计引入进来。当然目前还是一个比较粗糙的版本。

一些其他问题

  1. 在操作word文件这块,每次编辑原文件点击保存,会创建一个.tmp文件,并将编辑内容写入到 .tmp文件,之后进行重命名。但此时写入到.tmp文件的内容并没有被加密,只有当关闭文件时,触发IRP_CLOSE等待操作进程结束才会重入加密。在编辑期间,可能会造成明文泄露,并且没有处理电源相关的IRP,在持续打开文件时,直接关机,此时文件内容也没有加密。

  2. 在IRP_CLOSE中创建的线程回调在等待相关进程结束的间隔时间可能太长,如果关闭文件后,立即快速打开文件,此时文件还处于未加密状态。

使用git提交时报短读错误

将一个加密文件(txt类型)提交时,运行git add命令时会报短读错误,猜测是git先检查的文件大小与添加时明文大小不一致引起的

如何判断是否成功加密,以及一些操作提示

1.加密解密成功后DbgView中会有成功的信息输出
2.加密成功以后,关掉驱动,仍然会看到明文(缓冲的原因),此时需要关机重启,重启后先不要开驱动,就会看到密文加标识尾
3.或者加密成功以后,使用非授权进程打开文件,看到的也是密文

编译的驱动项目是Poc,至于PocUser和Dll是额外的部分(从桌面调用特权加密,特权解密功能),不影响驱动的使用,
设置CNG库也要在Poc项目中

1.加载驱动之前,需要将电脑调成测试模式(因为驱动没有签名),然后使用OsrLoader之类的工具,或者使用cmd加载,
1)这里如果使用OsrLoader需要将Type设置为MiniFilter,
2)下面是使用cmd的例子:
rundll32.exe setupapi.dll,InstallHinfSection DefaultInstall 132 C:\Desktop\Poc.inf
net start Poc

PocNtfsFlushAndPurgeCache

FileFuncs.c->PocNtfsFlushAndPurgeCache 只对NTFS有效,针对其它文件系统有什么思路可用?

启动时报错

你好。我在成功编译后在虚拟机中尝试启动poc驱动出现如下报错:
image
请问该如何处理呢。我自己写的一个测试CNG加解密的驱动是可以正常工作的。应该不是CNG库的问题。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.