Closed wangzhankun closed 2 years ago
可是日志里显示,你并没有把Test.exe设置为授权进程,所以之后用notepad++删除以后,非授权进程Test无法写入文件。 不过我还是更新了一下,文件的EOF==0,默认它是明文了。
可是日志里显示,你并没有把Test.exe设置为授权进程,所以之后用notepad++删除以后,非授权进程Test无法写入文件。 不过我还是更新了一下,文件的EOF==0,默认它是明文了。
问题还是没解决。可能是文档上传错了。你那边可以调试一下。
而且比较奇怪的是,在打开文件时,将FILE_FLAG_WRITE_THROUGH
用0替换,缓冲写的时候,也是有问题。而且我在驱动里面看是确确实实有数据被写入的:
可是打开文件数据就是不对。
现在打开的数据是怎么不对?只有4个字节? 我没有复现出来,不过我改了俩地方,你再试试?把完整的日志传上来吧,我看看。
最新的代码仍然有问题。录屏和日志见百度网盘。(你有阿里云盘吗?百度的你那边下载的时候太慢了) 链接:https://pan.baidu.com/s/1u9d2q6wqoHjElE96e4fadw 提取码:s5ql
视频里对应的Test.exe也发给我,没事,我还有一个周的百度网盘会员
另外用这个程序做测试的时候还会有一个bug。我在录屏里面运行了两次TEST.exe。两次运行之间把生成的hello.txt文件删除了,如果这个文件不删除,连续运行两次TEST.exe,也会导致文件损坏。
只能解决一部分问题,现在更新了CurrentByteOffset,不会有一块乱码了。但还是会有丢掉最后一块数据的情况。 不知为什么,这个WRITE_THROUGH,并没有在CacheManager写入文件之前更新Fcb里面的FileSize,这就导致Write中取到的FileSize是个过时的值,所以最后一块数据并没有正常加密写入。反而在PagingIo写完,返回FSD,然后FSD返回CachedIo时更新了FileSize。 我没找到原因......这可能取决于ntfs对于FileSize的更新方式。 不改了不改了,就这样吧。
只能解决一部分问题,现在更新了CurrentByteOffset,不会有一块乱码了。但还是会有丢掉最后一块数据的情况。 不知为什么,这个WRITE_THROUGH,并没有在CacheManager写入文件之前更新Fcb里面的FileSize,这就导致Write中取到的FileSize是个过时的值,所以最后一块数据并没有正常加密写入。反而在PagingIo写完,返回FSD,然后FSD返回CachedIo时更新了FileSize。 我没找到原因......这可能取决于ntfs对于FileSize的更新方式。 不改了不改了,就这样吧。
我这边测试好像没有数据丢失的情况了。但是连续两次运行TEST.exe导致文件损坏的问题还是存在。
(如果在2、3步之间使用机密进程打开该文件,或者删除hello.txt,第二次运行TEST.EXE并不会导致文件损坏)
bug日志: DESKTOP-RPF0QIQ.LOG
另外用这个程序做测试的时候还会有一个bug。我在录屏里面运行了两次TEST.exe。两次运行之间把生成的hello.txt文件删除了,如果这个文件不删除,连续运行两次TEST.exe,也会导致文件损坏。
感觉是文件标识尾写入太慢的问题。
我建议是把这一行的代码Status = KeDelayExecutionThread(KernelMode, FALSE, &Interval);
放到下面去。就是先判断是否有进程正在读写。把代码放到下面就没问题了。
再试试吧,问题处在了Write中的LengthReturned值不准确上,因为WRITE_THROUGH的原因。 设置标识WRITE_THROUGH,ntfs并不会在PagingIo之前更新Fcb->FileSize,这导致我们的Write中LengthReturned取了一个过时的值。 它使用TopLevelIrpContext+184截断PagingIo的,如下图 这个数据就是TopLevelIrpContext+184的值,0x10是个准确的值 我在StreamContext中加了一个变量WriteThroughFileSize,用来在这种情况下替代Fcb->FileSize做判断。
数据丢失是指写入5次 1th\n 2th\n ......5th\n 第五次的5th\n丢失了
我用beyond compare做了对比,丢失的数据还挺多的。
有没有可能是valid_data_length的问题呢?
我发现即使是不指定FILE_FLAG_WRITE_THROUGH
,也是会出现数据丢失的问题。而且比指定了FILE_FLAG_WRITE_THROUGH
要丢失的数据更多。指定了FILE_FLAG_WRITE_THROUGH
之后,丢失的数据是最后一次写入的数据,而不指定该标志,丢失的数据是随机的。
HANDLE hFile = CreateFileA(
file_path.c_str(),
GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
OPEN_ALWAYS,
//FILE_FLAG_WRITE_THROUGH,
0,
NULL);
我发现即使是不指定
FILE_FLAG_WRITE_THROUGH
,也是会出现数据丢失的问题。而且比指定了FILE_FLAG_WRITE_THROUGH
要丢失的数据更多。指定了FILE_FLAG_WRITE_THROUGH
之后,丢失的数据是最后一次写入的数据,而不指定该标志,丢失的数据是随机的。HANDLE hFile = CreateFileA( file_path.c_str(), GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, //FILE_FLAG_WRITE_THROUGH, 0, NULL);
对于这个问题,在PreWrite
中添加以下代码就能解决了。
ok,加上了,虽然我没太搞懂这么做的原因。
wangzhankun同学,我开了一个分支"wangzhankun",并且重新把你加上了Co,你可以把之前PR的代码提交到该分支。 最近有点忙,你自己提交或修改即可。 @wangzhankun
除了修复目前还存在的各种bug之外,(可以参考Readme中的Unfixed), 如果你感兴趣,想添加一些新的功能, 可以做一下权限的细分,比如增加用户权限,用户组权限的控制,这里要注意用户组>用户>进程的权限顺序, 做一下驱动的保护,比如防止别的调试软件获取明文,以及防止其他恶意minifilter驱动加载, 做驱动对进程的注入,实现防截屏之类的功能等等, 这些都是可以参考的方向。 另外,我写代码很大程度参考Windows-driver-samples\filesys\fastfat的源码实现,以及Windows内核情景分析、Windows内核原理与实现和Windows NT File System Internals - A Developer's 三本书,再就是Winnt4和WRK泄露的Windows源码,你要是觉得有用可以看看。
环境
bug复现步骤
日志
DESKTOP-RPF0QIQ.LOG
测试程序