阅读:4409回复:24
关于透明为文件增加文件头的问题
我现在正在写一个过滤驱动,需要为文件增加一个文件头,并且向应用程序屏蔽增加了文件头这个事实。
我尝试了在IRP_MJ_CREATE例程完成后,将文件头写入到文件中的方法,但是存在一些问题。我使用的代码如下: BOOLEAN SetFileHeader( IN PDEVICE_OBJECT DeviceObject, IN PFILE_OBJECT FileObject, IN PVOID FileHeader ){ HANDLE hFile = NULL; NTSTATUS status; LONGLONG CurrentByteOffset; IO_STATUS_BLOCK IoStatus; LARGE_INTEGER ByteOffset; FILE_END_OF_FILE_INFORMATION EndOfFileInfo; //获得文件句柄 status = ObOpenObjectByPointer( FileObject, OBJ_KERNEL_HANDLE, NULL, 0, NULL, KernelMode, &hFile ); if( !NT_SUCCESS( status ) ){ return FALSE; } ByteOffset.QuadPart = 0; status = ZwWriteFile( hFile, NULL, NULL, NULL, &IoStatus, FileHeader, PAGE_SIZE, &ByteOffset, NULL ); if( !NT_SUCCESS( status ) ){ ZwClose( hFile ); return FALSE; } ZwClose( hFile ); return TRUE; } 这段代码导致的结果是在cmd.exe中执行copy con 1.txt时,如果文件不存在时,文件头和内容均无法被写入,跟踪之后,发现问题出在ObOpenObjectByPointer和ZwClose上。 我现在有两个问题: 1)在IRP_MJ_CREATE例程中手工构造IRP来写入文件头是否可行? 2)还有没有更合适的写入文件头的时机? |
|
最新喜欢:![]() |
沙发#
发布于:2007-05-11 08:26
1. 根据我先前的测试来看,IRP_MJ_CREATE例程成功完成时应该是最好的时机;
2. 既然有FILE_OBJECT了为何还要再获取句柄呢? |
|
|
板凳#
发布于:2007-05-11 10:04
这个是技巧问题~
头读写最好直接给真实的那个啥~ 其他数据则走你的那个啥处理~ |
|
|
地板#
发布于:2007-05-11 19:19
谢谢大家的支持。 我现在已经通过构建IRP_MJ_WRITE的方式来解决了写入文件头的问题。
但是现在又遇到了新的问题:当使用wordpad来创建和打开文件时完全OK;但是使用notepad来创建和打开文件时,则结果异常。出现这个问题的原因应该是因为内存映射文件的缘故,现在不知道该如何解决,请大牛们指点迷津,谢谢! |
|
地下室#
发布于:2007-05-11 19:20
本人抱着学习与研究的态度与大家沟通问题,下面把我编写的新的SetFileHeader函数附在这里,与大家一起学习。
BOOLEAN SetFileHeader( IN PDEVICE_OBJECT DeviceObject, IN PFILE_OBJECT FileObject, IN PVOID FileHeader ){ HANDLE hFile = NULL; NTSTATUS status; LONGLONG CurrentByteOffset; IO_STATUS_BLOCK IoStatus; LARGE_INTEGER ByteOffset; KEVENT event; PIRP Irp; PIO_STACK_LOCATION IrpSp; PDEVICE_OBJECT TargetDeviceObject; KeInitializeEvent(&event, SynchronizationEvent, FALSE); TargetDeviceObject = ((PHOOK_EXTENSION)DeviceObject->DeviceExtension)->FileSystem; ByteOffset.QuadPart = 0; Irp = IoBuildSynchronousFsdRequest( IRP_MJ_WRITE, TargetDeviceObject, FileHeader, PAGE_SIZE, &ByteOffset, &event, &IoStatus ); if( Irp == NULL ){ return FALSE; } IrpSp = IoGetNextIrpStackLocation(Irp); IrpSp->FileObject = FileObject; (void)IoCallDriver( TargetDeviceObject,Irp ); KeWaitForSingleObject(&event, Executive, KernelMode, TRUE, 0); return TRUE; } |
|
5楼#
发布于:2007-05-11 22:28
这个问题,你可以看看楚大侠的文章,活着参考这个版的帖子,不过你想的话必须自己处理FastIo。
|
|
|
6楼#
发布于:2007-05-14 09:28
你说的自己来处理FastIo是什么意思?是不是自己来执行从缓存中拷贝数据的动作,如果不在缓存中,需要自己来构造IRP来执行PAGE IO?
本论坛的关于这方面的文章我都读过了,也看了本版版主的文章,说是把加密标志放在文件头很困难,所以他放在了文件的尾部。 但是我在想,如果放在尾部,Allocation Size, EndOfFile还有ValidDataLength是否该按如下方式进行调整: AllocationSize += TAG_SIZE; EndOfFile += TAG_SIZE; ValidDataLength保持不变? 如果标志放在文件尾部,如果在过滤驱动未被加载的时候,将文件拷贝其他的地方,譬如FTP到服务器上,是否文件加密标志就丢失了?? 这些问题请版主和各位大牛明示,谢谢! |
|
7楼#
发布于:2007-05-15 11:12
放在文件首部,内存映射文件的问题太难解决了
尝试着放在文件尾部吧.... |
|
8楼#
发布于:2007-05-16 09:22
引用第7楼stephenlv于2007-05-15 11:12发表的 : 放在文件尾部,要处理CLOSE问题,更痛苦~ 不如放在头部,放在头部主要是处理文件的映射问题, 挺困难,搞成了就好了~ |
|
|
9楼#
发布于:2007-05-16 09:41
处理映射文件太难了
我试过Hook ZwMapViewOfSection函数的方法,试图通过改变其中的offset来改变映射方式,但是在hook函数中,通过SectionHandle获取FileObject时遇到了问题,无法正常获取,所以没有办法了 我觉得要出力映射文件除了在这个地方做之外,再没有更合适的地方了,因为一旦这个函数调用结束,返回的BaseAddress就已经和文件的起始位置关联起来了 继续处理解决放在尾部的问题...... 呜呼哀哉。。。。。 |
|
10楼#
发布于:2007-05-16 11:52
继续努力,我在这个问题上卡了两个月~
|
|
|
11楼#
发布于:2007-05-16 11:52
才处理掉,嘿嘿~
|
|
|
12楼#
发布于:2007-05-17 09:39
天哪~~~~~~~~~~~~~~~
![]() |
|
13楼#
发布于:2007-05-17 09:40
我现在也有阅读devia提供的2003的部分源代码,希望能够对实现这个功能有所帮助~~~~~~
|
|
14楼#
发布于:2007-05-17 17:28
在处理IRP_MJ_CLOSE的CloseRoutine中使用传进来的FileObject构建IRP来执行写入操作,报STATUS_FILE_CLOSED错误。
我在网上查找STATUS_FILE_CLOSED时,只能找到很少的资料,不知道什么情况下会报这个异常?引起这个异常的原因是不是因为FileObject的某个标志引起的? 请版主、killvxk 和各位大牛们明示..... |
|
15楼#
发布于:2007-05-18 22:44
没有找到STATUS_FILE_CLOSED的解决办法:(
使用隐藏设备来写入文件扩展信息,在CloseRoutine中调用IoCallDriver之后,使用独占的方式打开文件然后将文件扩展信息写入到文件中。使用这个办法担心如果在CloseRoutine完成之前,其他程序去打开这个文件该怎么办?独占模式能否解决这个问题? 但是使用隐藏设备时使用独占模式打开文件时出现了无法打开的问题,总是出现 STATUS_SHARE_VIOLATION错误:( 不知道到底在CloseRoutine中写入文件尾到底该怎么做? |
|
16楼#
发布于:2007-05-18 22:46
现在设置文件扩展信息的代码变成了如下的样子:
BOOLEAN SetFileHeader( IN PDEVICE_OBJECT DeviceObject, IN PFILE_OBJECT FileObject, IN PWCHAR FullFileName, IN PVOID FileHeader ){ PWCHAR FileNameBuffer = FullFileName; HANDLE hFile = NULL; PWCHAR FileName = NULL; UNICODE_STRING UniFileName; OBJECT_ATTRIBUTES Attributes; NTSTATUS Status; IO_STATUS_BLOCK StatusBlock; PHOOK_EXTENSION hookExt = (PHOOK_EXTENSION)DeviceObject->DeviceExtension; CHAR Drive = (CHAR)hookExt->LogicalDrive; BOOLEAN retVal = FALSE; LARGE_INTEGER ByteOffset; PFILE_OBJECT objFile; PIPPS_FILE_XINFO XInfo = (PIPPS_FILE_XINFO)FileHeader; FILE_STANDARD_INFORMATION StandardInfo; FileName = (PWCHAR)ExAllocatePoolWithTag( NonPagedPool, MAXPATHLEN*sizeof(WCHAR), IO_POOL_TAG_FILENAME ); memset( FileName,0,MAXPATHLEN*sizeof(WCHAR) ); wcsncpy( FileName,SHADOW_DEVICE_PREFIX,wcslen(SHADOW_DEVICE_PREFIX) ); if( FileNameBuffer[0] != L'\\' ){ wcsncat( FileName,L"\\",1 ); } wcsncat( FileName,FileNameBuffer,MAXPATHLEN-wcslen( FileNameBuffer ) ); FileName[20] = Drive; RtlInitUnicodeString( &UniFileName,FileName ); InitializeObjectAttributes( &Attributes, &UniFileName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL ); memset( &StatusBlock,0,sizeof(IO_STATUS_BLOCK) ); Status = ZwCreateFile( &hFile, FILE_GENERIC_WRITE, &Attributes, &StatusBlock, NULL, FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_TEMPORARY, FILE_SHARE_READ, FILE_OPEN, FILE_NON_DIRECTORY_FILE | FILE_NO_INTERMEDIATE_BUFFERING, NULL, 0 ); if( !NT_SUCCESS( Status ) ){ retVal = FALSE; goto exit0; } // // Set shadow file object's Vpb // Status = ObReferenceObjectByHandle( hFile, FILE_ALL_ACCESS, NULL, KernelMode, &objFile, NULL); if( NT_SUCCESS( Status ) ){ if( ((PHOOK_EXTENSION)objFile->DeviceObject->DeviceExtension)->Type==SHADOW ){ IoDbgPrint( ("The file object is on a shadow device\n") ); } objFile->Vpb = NULL; ObDereferenceObject( &objFile ); } // // Query file size // Status = ZwQueryInformationFile( hFile, &StatusBlock, &StandardInfo, sizeof(StandardInfo), FileStandardInformation ); if( !NT_SUCCESS( Status ) ){ retVal = FALSE; goto exit0; } // // Set the LastPageFreeBytes of the extend information object // XInfo->LastPageFreeBytes = PAGE_SIZE - StandardInfo.EndOfFile.LowPart % PAGE_SIZE; DbgPrint( "LastPageFreeBytes: %d\n",XInfo->LastPageFreeBytes ); if( XInfo->LastPageFreeBytes == PAGE_SIZE ){ XInfo->LastPageFreeBytes = 0; } // // Write the extend information to the file // ByteOffset.QuadPart = StandardInfo.EndOfFile.QuadPart + XInfo->LastPageFreeBytes; DbgPrint( "ByteOffset: %d\n",ByteOffset.LowPart ); Status = ZwWriteFile( hFile, NULL, NULL, NULL, &StatusBlock, FileHeader, PAGE_SIZE, &ByteOffset, NULL ); // // Read extend information failure // if( !NT_SUCCESS( Status ) ){ retVal = FALSE; goto exit0; } // // Set the return values // retVal = TRUE; exit0: if( hFile != NULL ){ ZwClose( hFile ); } if( FileName != NULL ){ ExFreePool( FileName ); } return retVal; } |
|
17楼#
发布于:2007-05-19 10:30
根据你的代码和你的描述~~
1.千万不要用ZW*的api来操作文件,用irp来工作。 2.重入打开文件的函数好像不对吧~ 3.另外就是一定得在Close完成後(pending的话,你得等啊~),再打开~ 4.可以通过改fileobject的几项来实现直接用close时的fileobject来写——请自己记录一下Close时的fileobject和READ/WRITE等时的Fileobject的区别~ 哈哈~ |
|
|
18楼#
发布于:2007-05-19 18:21
大哥,能不能告诉小弟需要修改哪几个标志可以直接使用close时的fileobject来执行写操作?
难道打开文件也要自己构建IRP来做?这样真的可以解决问题吗? 我现在是在closeroutine中执行了iocalldriver之后才调用写函数的,并且当pending时也进行了等待。 |
|
19楼#
发布于:2007-05-19 18:22
兄台,有没有什么联系方式,我们单独交流一下?
|
|
上一页
下一页