一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

SFilter框架理解

 夢醉千秋 2021-04-20
                     控制設(shè)備(接受我們自己的客服端)----過濾設(shè)備(接受別的進程的IRP) IRP棧每層對應(yīng)的設(shè)備不同  
綁定后返回的:最頂層的設(shè)備 看圖 為什么返回最頂層,當(dāng)我們的設(shè)備處理好后要發(fā)給下面的 而下面的第一個就是最頂層的設(shè)備 看圖理解






過濾
分層驅(qū)動中再加一層而不影響它的上下層,以過濾它們之間的數(shù)據(jù),對數(shù)據(jù)或行為進行安全控制。過濾是通過設(shè)備綁定實現(xiàn)的。
圖:



綁定
設(shè)備棧綁定的形式。驅(qū)動自己生成一個設(shè)備(過濾設(shè)備),調(diào)用系統(tǒng)提供的綁定API,綁定到目標(biāo)設(shè)備上。并返回一個在未綁定之前目標(biāo)設(shè)備所在設(shè)備棧的最頂層設(shè)備。這樣發(fā)往下層的IRP或者發(fā)往上層的數(shù)據(jù)都會被過濾設(shè)備截獲。
  1. PDEVICE_OBJECT
  2. IoAttachDeviceToDeviceStack(
  3. IN PDEVICE_OBJECT SourceDevice,
  4. IN PDEVICE_OBJECT TargetDevice );


AttachedDevice需要記錄,以便調(diào)用IoCallDriver()繼續(xù)下發(fā)IRP
為什么要返回一個DEVICE_OBJECT呢?
"并返回一個在未綁定之前目標(biāo)設(shè)備所在設(shè)備棧的最頂層設(shè)備"


一個系統(tǒng)中可能存在多個過濾設(shè)備
  1. ------------
  2. SourceDevice
  3. ------------<-----AttachedDevice
  4. Filter2Device
  5. ------------
  6. Filter1Device
  7. ------------
  8. TargetDevice



此時最頂層的對象為Filter2Device 返回這個以便IRP下發(fā) 比如放行
圖:






綁定API:
  1. IoAttachDevice()
  2. IoAttachDeviceToDeviceStackSafe(2000 SP4以及XP以上)
  3. IoAttachDeviceToDeviceStack()

windbg 查看相關(guān)信息:
  1. !devobj 查看設(shè)備對象信息
  2. !drvobj 查看驅(qū)動對象信息
  3. !devstack 查看設(shè)備棧
  4. !devnode 0 1 系統(tǒng)設(shè)備樹



文件系統(tǒng)過濾框架
  1. Filemon //不常見 不能動態(tài)監(jiān)控移動設(shè)備
  2. Sfilter //走在被淘汰的路上
  3. Minifilter //未來主流
  4. Filespy //不常見


Sfilter總體流程:

創(chuàng)建控制設(shè)備
創(chuàng)建控制設(shè)備符號鏈接
過濾分發(fā)函數(shù)
Fastio
過濾與綁定
生成一個過濾設(shè)備
IoRegisterFsRegistrationChange( 
DriverObject,
SfFsNotification ); (文件系統(tǒng)設(shè)備綁定)
SfFsControl (卷設(shè)備綁定)
一個驅(qū)動,看見幾個文件系統(tǒng)設(shè)備,看見幾個卷設(shè)備,對應(yīng)每一個設(shè)備就生成相應(yīng)設(shè)備附載上去,然后進行相應(yīng)處理。 


綁定文件系統(tǒng)是在回調(diào)中(也就是上面的SfFsNotification),綁定卷設(shè)備在分發(fā)函數(shù)中 在綁定文件系統(tǒng)后 在FILR_SYSTEM_COMTEL中就會收到卷設(shè)備創(chuàng)建的信息 就可以綁定卷設(shè)備了 在分發(fā)函數(shù)中創(chuàng)建過濾設(shè)備對象


比如一個U盤插入電腦 ,它第一步需要創(chuàng)建一個文件對象,然后再創(chuàng)建一個卷設(shè)備
我們要動態(tài)Attach到這上面,我們需要Hook這個過程,而這個HOOK過程,我們用回調(diào)的方法
這個回調(diào)的作用是監(jiān)視創(chuàng)建文件設(shè)備行為和綁定文件設(shè)備,綁定文件設(shè)備后,當(dāng)這個U盤要創(chuàng)建卷設(shè)備的時候就會被我攔截到,這個時候我們就可以生成過濾設(shè)備綁定上去了
動態(tài)監(jiān)控卷的掛載(VolumeMounting)概述: 一個新的存儲介質(zhì)被系統(tǒng)發(fā)現(xiàn)并在文件系統(tǒng)中創(chuàng)建一個新的卷Volume的過程被稱為Mounting。其過程是: 文件系統(tǒng)的控制設(shè)備對象(FSCDO)將得到一個IRP,其主功能碼(MajorFunctionCode)為IRP_MJ_FILE_SYSTEM_CONTRO。副功能碼(MinorFunctionCode)為IRP_MN_MOUNT,呵呵,仔細(xì)想一下,不要死板,如果我們創(chuàng)建一個設(shè)備對象,并將其綁定到文件系統(tǒng)控制設(shè)備對象的設(shè)備對象棧上,那么我們的設(shè)備對象不就能接受到這個IRP了嗎!這樣,我們就能時刻的知道新卷的產(chǎn)生了。解決了上面的問題。


這里說說FileMon過濾
FileMon里的方法:
枚舉26個盤符,打開文件,獲得FileObject?DeviceObject.
然后通過自己驅(qū)動生成一個過濾設(shè)備,Attach過濾設(shè)備到DeviceObject上
無法監(jiān)控類似U盤等動態(tài)加載上去的


而IoRegisterFsRegistrationChange是動態(tài)獲取的


Fastio
文件系統(tǒng)除了處理正常的IRP之外,還要處理所謂的FastIo.
FastIo是Cache Manager調(diào)用所引發(fā)的一種沒有irp的請求。換句話說,除了正常的Dispatch Functions之外,你還得為DriverObject撰寫另一組Fast Io Functions.
這組函數(shù)的指針在 driver->FastIoDispatch 
代碼:

  1. fastIoDispatch = ExAllocatePoolWithTag( NonPagedPool,
  2. sizeof( FAST_IO_DISPATCH ),
  3. SFLT_POOL_TAG_FASTIO );
  4. if (!fastIoDispatch) {
  5. IoDeleteDevice( gSFilterControlDeviceObject );
  6. return STATUS_INSUFFICIENT_RESOURCES;
  7. }
  8. RtlZeroMemory( fastIoDispatch, sizeof( FAST_IO_DISPATCH ) );
  9. fastIoDispatch->SizeOfFastIoDispatch = sizeof( FAST_IO_DISPATCH );
  10. fastIoDispatch->FastIoCheckIfPossible = SfFastIoCheckIfPossible;
  11. fastIoDispatch->FastIoRead = SfFastIoRead;
  12. fastIoDispatch->FastIoWrite = SfFastIoWrite;
  13. fastIoDispatch->FastIoQueryBasicInfo = SfFastIoQueryBasicInfo;
  14. fastIoDispatch->FastIoQueryStandardInfo = SfFastIoQueryStandardInfo;
  15. fastIoDispatch->FastIoLock = SfFastIoLock;
  16. fastIoDispatch->FastIoUnlockSingle = SfFastIoUnlockSingle;
  17. fastIoDispatch->FastIoUnlockAll = SfFastIoUnlockAll;
  18. fastIoDispatch->FastIoUnlockAllByKey = SfFastIoUnlockAllByKey;
  19. fastIoDispatch->FastIoDeviceControl = SfFastIoDeviceControl;
  20. fastIoDispatch->FastIoDetachDevice = SfFastIoDetachDevice;
  21. fastIoDispatch->FastIoQueryNetworkOpenInfo = SfFastIoQueryNetworkOpenInfo;
  22. fastIoDispatch->MdlRead = SfFastIoMdlRead;
  23. fastIoDispatch->MdlReadComplete = SfFastIoMdlReadComplete;
  24. fastIoDispatch->PrepareMdlWrite = SfFastIoPrepareMdlWrite;
  25. fastIoDispatch->MdlWriteComplete = SfFastIoMdlWriteComplete;
  26. fastIoDispatch->FastIoReadCompressed = SfFastIoReadCompressed;
  27. fastIoDispatch->FastIoWriteCompressed = SfFastIoWriteCompressed;
  28. fastIoDispatch->MdlReadCompleteCompressed = SfFastIoMdlReadCompleteCompressed;
  29. fastIoDispatch->MdlWriteCompleteCompressed = SfFastIoMdlWriteCompleteCompressed;
  30. fastIoDispatch->FastIoQueryOpen = SfFastIoQueryOpen;
  31. DriverObject->FastIoDispatch = fastIoDispatch;

看看我們的分發(fā)函數(shù):
  1. for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) {
  2. DriverObject->MajorFunction[i] = SfPassThrough;//通用分發(fā)函數(shù) 下發(fā)IRP 私用IoSkip 和 IoCallDriver
  3. }
  4. //
  5. // We will use SfCreate for all the create operations
  6. //
  7. DriverObject->MajorFunction[IRP_MJ_CREATE] = SfCreate;
  8. //DriverObject->MajorFunction[IRP_MJ_CREATE_NAMED_PIPE] = SfCreate;
  9. //DriverObject->MajorFunction[IRP_MJ_CREATE_MAILSLOT] = SfCreate;
  10. DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = SfFsControl;//注意這個 當(dāng)我們下面綁定了文件系統(tǒng)設(shè)備,我們就會收到這個IRP 在這個IRP處理函數(shù)中 我們就可以//綁定了卷設(shè)備對象了
  11. DriverObject->MajorFunction[IRP_MJ_CLEANUP] = SfCleanupClose;
  12. DriverObject->MajorFunction[IRP_MJ_CLOSE] = SfCleanupClose;


Sfilter代碼通讀分析



將我們驅(qū)動的對象保存起來---等會綁定文件系統(tǒng)設(shè)備的時候要用到
 gSFilterDriverObject = DriverObject;

首先我們初始化一個鏈表,這個鏈表用來內(nèi)存管理,防止碎片,等會再SfCreate中有很多數(shù)據(jù),可能需要頻繁的申請內(nèi)存,這樣不便于管理
我們在開頭就初始化這個一個鏈表,當(dāng)需要用到內(nèi)存的時候就到這面來拿

  1. ExInitializeFastMutex( &gSfilterAttachLock );
  2. //
  3. // Initialize the lookaside list for name buffering. This is used in
  4. // several places to avoid having a large name buffer on the stack. It is
  5. // also needed by the name lookup routines (NLxxx).
  6. //
  7. ExInitializePagedLookasideList( &gSfNameBufferLookasideList,
  8. NULL,
  9. NULL,
  10. 0,
  11. SFILTER_LOOKASIDE_SIZE,
  12. SFLT_POOL_TAG_NAME_BUFFER,
  13. 0 );

接下來就是創(chuàng)建設(shè)備對象
首先在
"\\FileSystem\\Filters\\SFilterDrv"

中創(chuàng)建,如果創(chuàng)建失敗就在

"\\FileSystem\\SFilterDrv"

中創(chuàng)建

與NTMod不同的是 NTmodel中我們創(chuàng)建對象的時候?qū)ο笫荱NKNOW_DEVICE 這里我們創(chuàng)建的是磁盤文件系統(tǒng)設(shè)備

  1. RtlInitUnicodeString( &nameString, L"\\FileSystem\\Filters\\SFilterDrv" );
  2. status = IoCreateDevice( DriverObject,
  3. 0, //has no device extension
  4. &nameString,
  5. FILE_DEVICE_DISK_FILE_SYSTEM,
  6. FILE_DEVICE_SECURE_OPEN,
  7. FALSE,
  8. &gSFilterControlDeviceObject );//保存下來 后面判斷是發(fā)給我們的驅(qū)動的還是發(fā)給文件系統(tǒng)的
  9. if (status == STATUS_OBJECT_PATH_NOT_FOUND) {
  10. //
  11. // This must be a version of the OS that doesn't have the Filters
  12. // path in its namespace. This was added in Windows XP.
  13. //
  14. // We will try just putting our control device object in the
  15. // \FileSystem portion of the object name space.
  16. //
  17. RtlInitUnicodeString( &nameString, L"\\FileSystem\\SFilterDrv" );
  18. status = IoCreateDevice( DriverObject,
  19. 0, //has no device extension
  20. &nameString,
  21. FILE_DEVICE_DISK_FILE_SYSTEM,
  22. FILE_DEVICE_SECURE_OPEN,
  23. FALSE,
  24. &gSFilterControlDeviceObject );
  25. if (!NT_SUCCESS( status )) {
  26. KdPrint( ("SFilter!DriverEntry: Error creating control device object \"%wZ\", status=%08x\n",
  27. &nameString,
  28. status ));
  29. return status;
  30. }
  31. } else if (!NT_SUCCESS( status )) {
  32. KdPrint(( "SFilter!DriverEntry: Error creating control device object \"%wZ\", status=%08x\n",
  33. &nameString, status ));
  34. return status;
  35. }


    然后就是設(shè)置我們的通信模式了
    默認(rèn)是BUFFIO
   
 gSFilterControlDeviceObject->Flags |= DO_BUFFERED_IO; //gSFilterControlDeviceObject是我們保存的我們驅(qū)動的對象



    接下去就是初始化分發(fā)函數(shù)了
    
  
  1. for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) {
  2. DriverObject->MajorFunction[i] = SfPassThrough;
  3. }
  4. //
  5. // We will use SfCreate for all the create operations
  6. //
  7. //還有其他的 比如讀寫 改 刪
  8. /*
  9. FilterCreate(創(chuàng)建)
  10. FilterRead(一般不攔,加解密處理)
  11. FilterWrite(修改,加解密處理)
  12. FilterSetInfo(刪,重命名)
  13. FilterClose(一般不攔)
  14. FilterClean(寫關(guān)閉等)
  15. */
  16. DriverObject->MajorFunction[IRP_MJ_CREATE] = SfCreate;
  17. //DriverObject->MajorFunction[IRP_MJ_CREATE_NAMED_PIPE] = SfCreate;
  18. //DriverObject->MajorFunction[IRP_MJ_CREATE_MAILSLOT] = SfCreate;
  19. 注意這個 當(dāng)我們下面綁定了文件系統(tǒng)設(shè)備,我們就會收到這個IRP 在這個IRP處理函數(shù)中 我們就可以//綁定了卷設(shè)備對象了
  20. DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = SfFsControl;//卷設(shè)備綁定
  21. DriverObject->MajorFunction[IRP_MJ_CLEANUP] = SfCleanupClose;
  22. DriverObject->MajorFunction[IRP_MJ_CLOSE] = SfCleanupClose;


前面說過了,不但有Dispatch分發(fā)函數(shù) 也有 fastIoDispatch
  1. fastIoDispatch = ExAllocatePoolWithTag( NonPagedPool,
  2. sizeof( FAST_IO_DISPATCH ),
  3. SFLT_POOL_TAG_FASTIO );
  4. if (!fastIoDispatch) {
  5. IoDeleteDevice( gSFilterControlDeviceObject );
  6. return STATUS_INSUFFICIENT_RESOURCES;
  7. }
  8. RtlZeroMemory( fastIoDispatch, sizeof( FAST_IO_DISPATCH ) );
  9. fastIoDispatch->SizeOfFastIoDispatch = sizeof( FAST_IO_DISPATCH );
  10. fastIoDispatch->FastIoCheckIfPossible = SfFastIoCheckIfPossible;
  11. fastIoDispatch->FastIoRead = SfFastIoRead;
  12. fastIoDispatch->FastIoWrite = SfFastIoWrite;
  13. fastIoDispatch->FastIoQueryBasicInfo = SfFastIoQueryBasicInfo;
  14. fastIoDispatch->FastIoQueryStandardInfo = SfFastIoQueryStandardInfo;
  15. fastIoDispatch->FastIoLock = SfFastIoLock;
  16. fastIoDispatch->FastIoUnlockSingle = SfFastIoUnlockSingle;
  17. fastIoDispatch->FastIoUnlockAll = SfFastIoUnlockAll;
  18. fastIoDispatch->FastIoUnlockAllByKey = SfFastIoUnlockAllByKey;
  19. fastIoDispatch->FastIoDeviceControl = SfFastIoDeviceControl;
  20. fastIoDispatch->FastIoDetachDevice = SfFastIoDetachDevice;
  21. fastIoDispatch->FastIoQueryNetworkOpenInfo = SfFastIoQueryNetworkOpenInfo;
  22. fastIoDispatch->MdlRead = SfFastIoMdlRead;
  23. fastIoDispatch->MdlReadComplete = SfFastIoMdlReadComplete;
  24. fastIoDispatch->PrepareMdlWrite = SfFastIoPrepareMdlWrite;
  25. fastIoDispatch->MdlWriteComplete = SfFastIoMdlWriteComplete;
  26. fastIoDispatch->FastIoReadCompressed = SfFastIoReadCompressed;
  27. fastIoDispatch->FastIoWriteCompressed = SfFastIoWriteCompressed;
  28. fastIoDispatch->MdlReadCompleteCompressed = SfFastIoMdlReadCompleteCompressed;
  29. fastIoDispatch->MdlWriteCompleteCompressed = SfFastIoMdlWriteCompleteCompressed;
  30. fastIoDispatch->FastIoQueryOpen = SfFastIoQueryOpen;
  31. DriverObject->FastIoDispatch = fastIoDispatch;


然后就是初始化一些回調(diào)函數(shù)被設(shè)置在我們的驅(qū)動對象上 也就是注冊回調(diào)函數(shù)
  1. FS_FILTER_CALLBACKS fsFilterCallbacks;
  2. if (NULL != gSfDynamicFunctions.RegisterFileSystemFilterCallbacks) {
  3. //
  4. // Setup the callbacks for the operations we receive through
  5. // the FsFilter interface.
  6. //
  7. // NOTE: You only need to register for those routines you really
  8. // need to handle. SFilter is registering for all routines
  9. // simply to give an example of how it is done.
  10. //
  11. fsFilterCallbacks.SizeOfFsFilterCallbacks = sizeof( FS_FILTER_CALLBACKS );
  12. fsFilterCallbacks.PreAcquireForSectionSynchronization = SfPreFsFilterPassThrough;
  13. fsFilterCallbacks.PostAcquireForSectionSynchronization = SfPostFsFilterPassThrough;
  14. fsFilterCallbacks.PreReleaseForSectionSynchronization = SfPreFsFilterPassThrough;
  15. fsFilterCallbacks.PostReleaseForSectionSynchronization = SfPostFsFilterPassThrough;
  16. fsFilterCallbacks.PreAcquireForCcFlush = SfPreFsFilterPassThrough;
  17. fsFilterCallbacks.PostAcquireForCcFlush = SfPostFsFilterPassThrough;
  18. fsFilterCallbacks.PreReleaseForCcFlush = SfPreFsFilterPassThrough;
  19. fsFilterCallbacks.PostReleaseForCcFlush = SfPostFsFilterPassThrough;
  20. fsFilterCallbacks.PreAcquireForModifiedPageWriter = SfPreFsFilterPassThrough;
  21. fsFilterCallbacks.PostAcquireForModifiedPageWriter = SfPostFsFilterPassThrough;
  22. fsFilterCallbacks.PreReleaseForModifiedPageWriter = SfPreFsFilterPassThrough;
  23. fsFilterCallbacks.PostReleaseForModifiedPageWriter = SfPostFsFilterPassThrough;
  24. status = (gSfDynamicFunctions.RegisterFileSystemFilterCallbacks)( DriverObject,
  25. &fsFilterCallbacks );
  26. if (!NT_SUCCESS( status )) {
  27. DriverObject->FastIoDispatch = NULL;
  28. ExFreePoolWithTag( fastIoDispatch, SFLT_POOL_TAG_FASTIO );
  29. IoDeleteDevice( gSFilterControlDeviceObject );
  30. return status;
  31. }
  32. }


接下去就是創(chuàng)建一個回調(diào),監(jiān)視文件系統(tǒng)設(shè)備創(chuàng)建, 在這個回調(diào)中,我們可以監(jiān)控文件系統(tǒng)創(chuàng)建和綁定文件系統(tǒng)設(shè)備
  1. status = IoRegisterFsRegistrationChange( DriverObject, SfFsNotification );//在里面綁定文件系統(tǒng)設(shè)備,也是卷設(shè)備綁定的前提條件
  2. if (!NT_SUCCESS( status )) {
  3. KdPrint(( "SFilter!DriverEntry: Error registering FS change notification, status=%08x\n",
  4. status ));
  5. DriverObject->FastIoDispatch = NULL;
  6. ExFreePoolWithTag( fastIoDispatch, SFLT_POOL_TAG_FASTIO );
  7. IoDeleteDevice( gSFilterControlDeviceObject );
  8. return status;
  9. }


然后就是對文件計數(shù)引用
  1. /*
  2. IoGetDeviceObjectPointer函數(shù)的功能是:
  3. 它從下層的設(shè)備對象名稱來獲得下層設(shè)備指針。該函數(shù)造成了對下層設(shè)備對象以及下層設(shè)備對象所對應(yīng)的文件對象的引用。
  4. 如果本層驅(qū)動在卸載之前對下層的設(shè)備對象的引用還沒有消除,則下層驅(qū)動的卸載會被停止。因此必須要消除對下層設(shè)備對象的引用。
  5. 但是程序一般不會直接對下層設(shè)備對象的引用減少。因此只要減少對文件對象的引用就可以減少文件對象和設(shè)備對象兩個對象的引用。
  6. 事實上,IoGetDeviceObjectPointer返回的并不是下層設(shè)備對象的指針,而是該設(shè)備堆棧中頂層的設(shè)備對象的指針。
  7. IoGetDeviceObjectPointer函數(shù)的調(diào)用必須在 IRQL=PASSIVE_LEVEL的級別上運行。
  8. */
  9. {
  10. PDEVICE_OBJECT rawDeviceObject;
  11. PFILE_OBJECT fileObject;
  12. //
  13. // Attach to RawDisk device
  14. //
  15. RtlInitUnicodeString( &nameString, L"\\Device\\RawDisk" );
  16. status = IoGetDeviceObjectPointer(
  17. &nameString,
  18. FILE_READ_ATTRIBUTES,
  19. &fileObject,
  20. &rawDeviceObject );
  21. if (NT_SUCCESS( status )) {
  22. SfFsNotification( rawDeviceObject, TRUE );//綁定RawDisk 激活這個設(shè)備 然后被我們捕捉到,綁定過濾設(shè)備
  23. ObDereferenceObject( fileObject );
  24. }
  25. //
  26. // Attach to the RawCdRom device
  27. //
  28. RtlInitUnicodeString( &nameString, L"\\Device\\RawCdRom" );
  29. status = IoGetDeviceObjectPointer(
  30. &nameString,
  31. FILE_READ_ATTRIBUTES,
  32. &fileObject,
  33. &rawDeviceObject );
  34. if (NT_SUCCESS( status )) {
  35. SfFsNotification( rawDeviceObject, TRUE );//同上
  36. ObDereferenceObject( fileObject );
  37. }
  38. }
  39. //
  40. // Clear the initializing flag on the control device object since we
  41. // have now successfully initialized everything.
  42. //
  43. ClearFlag( gSFilterControlDeviceObject->Flags, DO_DEVICE_INITIALIZING );
  44. DbgPrint("Sfilter installed\n");
  45. return STATUS_SUCCESS;
  46. }

去看看SfFsNotification
//回調(diào)例程,當(dāng)文件系統(tǒng)被激活或者撤銷時調(diào)用//在該例程中,完成對文件系統(tǒng)控制設(shè)備對象的綁定.
綁定文件系統(tǒng): 首先,我們需要知道當(dāng)前系統(tǒng)中都有那些文件系統(tǒng),例如:NTFS,F(xiàn)AT32,CDFS。因為,卷設(shè)備對象是由文件系統(tǒng)創(chuàng)建的。 其次,我們要知道什么時候去綁定文件系統(tǒng)。當(dāng)一個卷設(shè)備對象動態(tài)產(chǎn)生的時候,其對應(yīng)的文件系統(tǒng)就被激活。例如,如果一個FAT32的U盤被插入到電腦上,則對應(yīng)的FAT32文件系統(tǒng)就會被激活,并創(chuàng)建一個“J:”的卷設(shè)備對象。 IoRegisterFsRegistrationChange是一個非常有用的系統(tǒng)調(diào)用。這個調(diào)用注冊一個回調(diào)函數(shù),當(dāng)系統(tǒng)中有文件系統(tǒng)被激活或者撤銷時,該回調(diào)函數(shù)就被調(diào)用。OhGood,那么我們就可以在這個回調(diào)函數(shù)中去綁定文件系統(tǒng)的控制設(shè)備對象。 這里要注意:文件系統(tǒng)的加載和卷的掛載是兩碼事,卷的掛載是建立在文件系統(tǒng)被激活的基礎(chǔ)上。當(dāng)一個文件系統(tǒng)被激活后,才能創(chuàng)建卷設(shè)備對象
SfFsNotification是我們要注冊的回調(diào)函數(shù),它調(diào)用SfAttachToFileSystemDevice完成真正的設(shè)備綁定。當(dāng)然,它還有其他功能,代碼說明問題。 SfAttachToFileSystemDevice創(chuàng)建過濾設(shè)備對象,并調(diào)用我們設(shè)備綁定外包函數(shù):SfAttachDeviceToDeviceStack來將過濾設(shè)備對象綁定到文件系統(tǒng)控制設(shè)備對象的設(shè)備棧上。 這樣,我們的過濾設(shè)備對象就能接受到發(fā)送到FSCDO的IRP_MJ_FILE_SYSTEM_CONTRO的請求,動態(tài)監(jiān)控卷的掛載。那么以后的工作就是完成對卷的監(jiān)控綁定了。
回調(diào)例程,當(dāng)文件系統(tǒng)被激活或者撤銷時調(diào)用
 //在該例程中,完成對文件系統(tǒng)控制設(shè)備對象的綁定.// 
 //例程描述:
 這個例程在文件系統(tǒng)激活或者銷毀的時被調(diào)用
 這個例程創(chuàng)建一個設(shè)備對象將它附加到指定的文件系統(tǒng)控制設(shè)備對象
 //的對象棧上,這就允許這個設(shè)備對象過濾所有發(fā)送給文件系統(tǒng)的請求.
 //這樣,我們就能獲得一個掛載卷的請求,就可以附加到這個新的卷設(shè)備對象
 //的設(shè)備對象棧上//
  //參數(shù):
  DeviceObject:指向被激活或者撤銷的文件系統(tǒng)的控制設(shè)備對象
  FsActive:激活或者撤銷標(biāo)志
  1. {
  2. PNAME_CONTROL devName;
  3. PAGED_CODE();
  4. //
  5. // Display the names of all the file system we are notified of
  6. //
  7. devName = NLGetAndAllocateObjectName( DeviceObject,
  8. &gSfNameBufferLookasideList );
  9. if (devName == NULL) {
  10. SF_LOG_PRINT( SFDEBUG_DISPLAY_ATTACHMENT_NAMES,
  11. ("SFilter!SfFsNotification: Not attaching to %p, insufficient resources.\n",
  12. DeviceObject) );
  13. return;
  14. }
  15. SF_LOG_PRINT( SFDEBUG_DISPLAY_ATTACHMENT_NAMES,
  16. ("SFilter!SfFsNotification: %s %p \"%wZ\" (%s)\n",
  17. (FsActive) ? "Activating file system " : "Deactivating file system",
  18. DeviceObject,
  19. &devName->Name,
  20. GET_DEVICE_TYPE_NAME(DeviceObject->DeviceType)) );
  21. //
  22. // Handle attaching/detaching from the given file system.
  23. //
  24. if (FsActive) {
  25. SfAttachToFileSystemDevice( DeviceObject, devName );
  26. } else {
  27. SfDetachFromFileSystemDevice( DeviceObject );
  28. }
  29. //
  30. // We're done with name (SfAttachToFileSystemDevice copies the name to
  31. // the device extension) so free it.
  32. //
  33. NLFreeNameControl( devName, &gSfNameBufferLookasideList );
  34. }


這個綁定了文件設(shè)備對象,這時我們就可以收到IRP_MJ_FILE_SYSTEM_CONTROL IRP 在這個例程里我們就可以實現(xiàn)對卷的綁定

(注意 這里必須綁定了文件設(shè)備后才能收到哦)

看下IRP_MJ_FILE_SYSTEM_CONTROL的例程

  1. switch (irpSp->MinorFunction) {
  2. case IRP_MN_MOUNT_VOLUME://設(shè)備在Mount的時候,我們就要進行綁定了
  3. return SfFsControlMountVolume( DeviceObject, Irp );
  4. case IRP_MN_LOAD_FILE_SYSTEM:
  5. return SfFsControlLoadFileSystem( DeviceObject, Irp );
  6. case IRP_MN_USER_FS_REQUEST:
  7. {
  8. switch (irpSp->Parameters.FileSystemControl.FsControlCode) {
  9. case FSCTL_DISMOUNT_VOLUME:
  10. {
  11. PSFILTER_DEVICE_EXTENSION devExt = DeviceObject->DeviceExtension;
  12. SF_LOG_PRINT( SFDEBUG_DISPLAY_ATTACHMENT_NAMES,
  13. ("SFilter!SfFsControl: Dismounting volume %p \"%wZ\"\n",
  14. devExt->NLExtHeader.AttachedToDeviceObject,
  15. &devExt->NLExtHeader.DeviceName) );
  16. break;
  17. }
  18. }
  19. break;
  20. }
  21. }
  22. //
  23. // Pass all other file system control requests through.
  24. //
  25. IoSkipCurrentIrpStackLocation( Irp );
  26. return IoCallDriver( ((PSFILTER_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->NLExtHeader.AttachedToDeviceObject,
  27. Irp );
  28. }


差不多就是這樣,我們來看看其它分發(fā)函數(shù)
比如SfCreate
我們要做的工作就是在分發(fā)函數(shù)里寫代碼
  1. NTSTATUS
  2. SfCreate (
  3. IN PDEVICE_OBJECT DeviceObject,
  4. IN PIRP Irp
  5. )
  6. /*++
  7. Routine Description:
  8. This function filters create/open operations. It simply establishes an
  9. I/O completion routine to be invoked if the operation was successful.
  10. Arguments:
  11. DeviceObject - Pointer to the target device object of the create/open.
  12. Irp - Pointer to the I/O Request Packet that represents the operation.
  13. Return Value:
  14. The function value is the status of the call to the file system's entry
  15. point.
  16. --*/
  17. {
  18. NTSTATUS status;
  19. PNAME_CONTROL fileName = NULL;
  20. PSFILTER_DEVICE_EXTENSION devExt = (PSFILTER_DEVICE_EXTENSION)(DeviceObject->DeviceExtension);
  21. PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( Irp );
  22. BOOLEAN cacheName;
  23. PAGED_CODE();
  24. //
  25. // If this is for our control device object, don't allow it to be opened.
  26. //
  27. //如果是我們的設(shè)備 返回成功 這個宏判斷設(shè)備對象是不是我們保存那個和是不是我們的驅(qū)動對象
  28. if (IS_MY_CONTROL_DEVICE_OBJECT(DeviceObject)) {
  29. //
  30. // Sfilter doesn't allow for any communication through its control
  31. // device object, therefore it fails all requests to open a handle
  32. // to its control device object.
  33. //
  34. // See the FileSpy sample for an example of how to allow creates to
  35. // the filter's control device object and manage communication via
  36. // that handle.
  37. //
  38. //Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
  39. Irp->IoStatus.Status = STATUS_SUCCESS;
  40. Irp->IoStatus.Information = 0;
  41. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  42. return STATUS_INVALID_DEVICE_REQUEST;
  43. //return STATUS_SUCCESS;
  44. }
  45. ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
  46. //
  47. // If debugging is enabled, do the processing required to see the packet
  48. // upon its completion. Otherwise, let the request go with no further
  49. // processing.
  50. //
  51. if (!FlagOn( SfDebug, SFDEBUG_DO_CREATE_COMPLETION |
  52. SFDEBUG_GET_CREATE_NAMES|
  53. SFDEBUG_DISPLAY_CREATE_NAMES )) {
  54. //
  55. // We don't want to get filenames, display filenames, or
  56. // call our completion routine. Don't put us on the stack
  57. // and call the next driver.
  58. //
  59. //如果是Deug 就不顯示 直接下發(fā)
  60. IoSkipCurrentIrpStackLocation( Irp );
  61. return IoCallDriver( ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->NLExtHeader.AttachedToDeviceObject,
  62. Irp );
  63. }
  64. //如果要顯示一下信息
  65. if (FlagOn( SfDebug, SFDEBUG_GET_CREATE_NAMES |
  66. SFDEBUG_DISPLAY_CREATE_NAMES ) &&
  67. !FlagOn(devExt->Flags,SFDEVFL_DISABLE_VOLUME)) {
  68. //
  69. // Debugging specifies that we need to get the filename
  70. //
  71. NAME_LOOKUP_FLAGS LookupFlags = 0x00000000;
  72. //
  73. // If DosName has been set, indicate via flags that we
  74. // want to use it when getting the full file name.
  75. //
  76. if (devExt->NLExtHeader.DosName.Length != 0) {
  77. SetFlag( LookupFlags, NLFL_USE_DOS_DEVICE_NAME );
  78. }
  79. //
  80. // Indicate we are in pre-create
  81. //
  82. SetFlag( LookupFlags, NLFL_IN_CREATE );
  83. if (FlagOn( irpSp->Parameters.Create.Options, FILE_OPEN_BY_FILE_ID )) {
  84. //
  85. // The file is being opened by ID, not file name.
  86. //
  87. SetFlag( LookupFlags, NLFL_OPEN_BY_ID );
  88. }
  89. if (FlagOn( irpSp->Flags, SL_OPEN_TARGET_DIRECTORY )) {
  90. //
  91. // The file's parent directory should be opened
  92. //
  93. SetFlag( LookupFlags, NLFL_OPEN_TARGET_DIR );
  94. }
  95. //
  96. // Retrieve the file name. Note that in SFilter we don't do any name
  97. // caching.
  98. //
  99. //申請存儲數(shù)據(jù)的空間
  100. status = NLAllocateNameControl( &fileName, &gSfNameBufferLookasideList );
  101. if (NT_SUCCESS( status )) {
  102. //
  103. // We are okay not checking the return value here because
  104. // the GetFullPathName function will set the Unicode String
  105. // length to 0. So either way, in an error it will print an empty string
  106. //
  107. //拿到文件的全路徑
  108. status = NLGetFullPathName( irpSp->FileObject,
  109. fileName,
  110. &devExt->NLExtHeader,
  111. LookupFlags,
  112. &gSfNameBufferLookasideList,
  113. &cacheName );
  114. }
  115. }
  116. //往下發(fā)
  117. if (FlagOn( SfDebug, SFDEBUG_DISPLAY_CREATE_NAMES |
  118. SFDEBUG_DO_CREATE_COMPLETION ) &&
  119. !FlagOn(devExt->Flags,SFDEVFL_DISABLE_VOLUME)) {
  120. //
  121. // Debugging flags indicate we must do completion.
  122. // Note that to display file names we must do completion
  123. // because we don't know IoStatus.Status and IoStatus.Information
  124. // until post-create.
  125. //
  126. KEVENT waitEvent;
  127. //
  128. // Initialize an event to wait for the completion routine to occur
  129. //
  130. KeInitializeEvent( &waitEvent, NotificationEvent, FALSE );
  131. //
  132. // Copy the stack and set our Completion routine
  133. //
  134. 設(shè)置完成例程
  135. IoCopyCurrentIrpStackLocationToNext( Irp );
  136. IoSetCompletionRoutine(
  137. Irp,
  138. SfCreateCompletion,
  139. &waitEvent,
  140. TRUE,
  141. TRUE,
  142. TRUE );
  143. //
  144. // Call the next driver in the stack.
  145. //
  146. status = IoCallDriver( devExt->NLExtHeader.AttachedToDeviceObject, Irp );
  147. //
  148. // Wait for the completion routine to be called
  149. //
  150. if (STATUS_PENDING == status) {
  151. NTSTATUS localStatus = KeWaitForSingleObject( &waitEvent,
  152. Executive,
  153. KernelMode,
  154. FALSE,
  155. NULL );
  156. ASSERT(STATUS_SUCCESS == localStatus);
  157. }
  158. //
  159. // Verify the IoCompleteRequest was called
  160. //
  161. ASSERT(KeReadStateEvent(&waitEvent) ||
  162. !NT_SUCCESS(Irp->IoStatus.Status));
  163. //
  164. // If debugging indicates we should display file names, do it.
  165. //
  166. //打印信息
  167. if (irpSp->Parameters.Create.Options & FILE_OPEN_BY_FILE_ID) {
  168. SF_LOG_PRINT( SFDEBUG_DISPLAY_CREATE_NAMES,
  169. ("SFilter!SfCreate: OPENED fo=%p %08x:%08x %wZ (FID)\n",
  170. irpSp->FileObject,
  171. Irp->IoStatus.Status,
  172. Irp->IoStatus.Information,
  173. &fileName->Name) );
  174. } else {
  175. SF_LOG_PRINT( SFDEBUG_DISPLAY_CREATE_NAMES,
  176. ("SFilter!SfCreate: OPENED fo=%p st=%08x:%08x %wZ\n",
  177. irpSp->FileObject,
  178. Irp->IoStatus.Status,
  179. Irp->IoStatus.Information,
  180. &fileName->Name) );
  181. }
  182. //
  183. // Release the name control structure if we have
  184. //
  185. if (fileName != NULL) {
  186. NLFreeNameControl( fileName, &gSfNameBufferLookasideList );
  187. }
  188. //
  189. // Save the status and continue processing the IRP
  190. //
  191. status = Irp->IoStatus.Status;
  192. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  193. return status;
  194. } else {
  195. //
  196. // Free the name control if we have one
  197. //
  198. if (fileName != NULL) {
  199. NLFreeNameControl( fileName, &gSfNameBufferLookasideList );
  200. }
  201. //
  202. // Debugging flags indicate we did not want to display the file name
  203. // or call completion routine.
  204. // (ie SFDEBUG_GET_CREATE_NAMES && !SFDEBUG_DO_CREATE_COMPLETION)
  205. //
  206. IoSkipCurrentIrpStackLocation( Irp );
  207. return IoCallDriver( ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->NLExtHeader.AttachedToDeviceObject,
  208. Irp );
  209. }
  210. }


再來看看分發(fā)函數(shù)
非過濾驅(qū)動中的默CommonDispatch

  1. NTSTATUS CommonDispatch(
  2. PDEVICE_OBJECT DeviceObject,
  3. PIRP Irp)
  4. {
  5. Irp->IoStatus.Status = STATUS_SUCCESS;
  6. IoCompleteRequest(Irp,IO_NO_INCREMENT);
  7. return STATUS_SUCCESS;
  8. }



過濾驅(qū)動中CommonDispatch寫法


  1. NTSTATUS SfPassThrough (
  2. IN PDEVICE_OBJECT DeviceObject,
  3. IN PIRP Irp
  4. )
  5. {
  6. PIO_STACK_LOCATION pIrp = IoGetCurrentIrpStackLocation( Irp );
  7. ASSERT(!IS_MY_CONTROL_DEVICE_OBJECT( DeviceObject ));
  8. ASSERT(IS_MY_DEVICE_OBJECT( DeviceObject ));
  9. if (!IS_MY_DEVICE_OBJECT(DeviceObject) ||
  10. IS_MY_CONTROL_DEVICE_OBJECT(DeviceObject))
  11. {
  12. NTSTATUS status = Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
  13. IoCompleteRequest( Irp, IO_NO_INCREMENT );
  14. return status;
  15. }
  16. IoSkipCurrentIrpStackLocation( Irp );
  17. return IoCallDriver( ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->NLExtHeader.AttachedToDeviceObject,
  18. Irp );
  19. }

一個是結(jié)束IRP 一個是判斷是不是發(fā)給我們驅(qū)動的 如果是就返回?zé)o效的參數(shù),(這里是返回失敗,但在攔截的分發(fā)函數(shù)中是需要放行的這個放行是返回success)

對一個主防來說:
  1. FilterCreate(創(chuàng)建)
  2. FilterRead(一般不攔,加解密處理)
  3. FilterWrite(修改,加解密處理)
  4. FilterSetInfo(刪,重命名)
  5. FilterClose(一般不攔)
  6. FilterClean(寫關(guān)閉等)

對于一個主防來說 一般是攔截創(chuàng)建 和 關(guān)閉  為什么要攔截關(guān)閉呢 一個人現(xiàn)在是好人,但他不一定一輩子都是好人
創(chuàng)建文件 我們放了,然后它寫入了一個shellcode 如果我們攔截寫的話 一個一個的攔截 效果并不好 在關(guān)閉的時候我們就可以一次性知道


深入理解下設(shè)備對象
設(shè)備對象類別


Sfilter自己的設(shè)備
控制設(shè)備
過濾設(shè)備
其它設(shè)備
文件系統(tǒng)設(shè)備
卷設(shè)備
設(shè)備類別
FILE_DEVICE_DISK_FILE_SYSTEM


  1. #define IS_MY_DEVICE_OBJECT(_devObj) \
  2. (((_devObj) != NULL) && \
  3. ((_devObj)->DriverObject == gSFilterDriverObject) && \
  4. ((_devObj)->DeviceExtension != NULL))
  5. #define IS_MY_CONTROL_DEVICE_OBJECT(_devObj) \
  6. (((_devObj) == gSFilterControlDeviceObject) ? \
  7. (ASSERT(((_devObj)->DriverObject == gSFilterDriverObject) && \
  8. ((_devObj)->DeviceExtension == NULL)), TRUE) : \
  9. FALSE)
  10. #define IS_DESIRED_DEVICE_TYPE(_type) \
  11. (((_type) == FILE_DEVICE_DISK_FILE_SYSTEM) || \
  12. ((_type) == FILE_DEVICE_CD_ROM_FILE_SYSTEM) || \
  13. ((_type) == FILE_DEVICE_NETWORK_FILE_SYSTEM))


三種類型的設(shè)備處理
  1. NTSTATUS FilterXXX(PDEVICE_OBJECT DeviceObject, PIRP pIrp)//過濾設(shè)備
  2. {
  3. NTSTATUS Status = STATUS_SUCCESS;
  4. ULONG ulInfomation = 0;
  5. IO_STACK_LOCATION* lpIrpStack = IoGetCurrentIrpStackLocation(pIrp);
  6. if (IS_MY_CONTROL_DEVICE_OBJECT(DeviceObject))//控制設(shè)備
  7. {
  8. //如果需要與R3交互,這里必須返回成功
  9. pIrp->IoStatus.Status = Status;
  10. pIrp->IoStatus.Information = ulInfomation;
  11. IoCompleteRequest(lpIrp, IO_NO_INCREMENT);
  12. }
  13. else if (!IS_MY_DEVICE_OBJECT(DeviceObject))
  14. {
  15. //非法參數(shù)
  16. pIrp->IoStatus.Status = Status = STATUS_INVALID_PARAMETER;
  17. pIrp->IoStatus.Information = 0;
  18. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  19. }
  20. else
  21. {
  22. //這里才是我們要過濾的操作
  23. IoSkipCurrentIrpStackLocation( pIrp );
  24. Status = IoCallDriver(((PSFILTER_DEVICE_EXTENSION)->DeviceExtension)DeviceObject->NLExtHeader.AttachedToDeviceObject, pIrp);
  25. }
  26. return Status;
  27. }



重要問題:文件路徑的解析與保存
Namelookup.c(構(gòu)造IRP,不能用 ObQueryNameString)
NLGetFullPathName()?
NLPQueryFileSystemForFileName()?IRP查詢
在SfCreate里查詢名字,通過FILE_OBJECT與Name保存起來。供其它過濾函數(shù)中查詢使用。
保存在哪里?
List_Entry
HASH
TREE


Sfilter安裝測試
原始的Sfilter框架,不支持通信
sfCreate中對自己的控制設(shè)備,返回成功
符號鏈接的創(chuàng)建(框架中沒有)
  1. GroupOrder:"FSFilter Activity Monitor“
  2. L\\FileSystem\\SFilterDrv
  3. DeviceObject?Flags |= DO_BUFFERED_IO

不要在release版本使用DriverUnload。BSOD




既然是過濾 那么就有放和禁
FilterCreate:
放:
內(nèi)核過來的
Irp->RequestorMode == KernelMode 
本進程的
FilterDeviceIoctrl中 PsGetCurrentProcessId()
系統(tǒng)進程的
DriverEntry里:PsGetCurrentProcessId()
文件夾
  1. ulOptions = IrpStack->Parameters.Create.Options ;
  2. FlagOn(IrpStack->FileObject->Flags, FO_VOLUME_OPEN) ||
  3. FlagOn(ulOptions, FILE_DIRECTORY_FILE) ||
  4. FlagOn(IrpStack->Flags, SL_OPEN_PAGING_FILE)
分頁IO
  1. (Irp->Flags & IRP_PAGING_IO) ||
  2. (Irp->Flags & IRP_SYNCHRONOUS_PAGING_IO)
  3. KeGetCurrentIrql() > APC_LEVEL
如何放?
  1. IoSkipCurrentIrpStackLocation( lpIrp );
  2. IoCallDriver();

禁:自定義啦 比如禁止在driver目錄寫入sys文件




拿文件名/長短名轉(zhuǎn)化 短文轉(zhuǎn)長名
匹配規(guī)則
FsRtlIsNameInExpression 
彈框

STATUS_ACCESS_DENIED

Pending完成例程
加入表中,供其它Filter函數(shù)使用




FilterWrite:
放:
本進程
系統(tǒng)進程
分頁IO
從表中根據(jù)file_object沒有找到的
匹配規(guī)則
彈框
攔截

效率
多次寫?




FilterSetInfo:攔截刪除,重命名等

IrpStack->Parameters.SetFile.FileInformationClass
FileRenameInformation//重命名
如何拿重命名之后的文件名?
IrpSp->Parameters.SetFile.FileObject//測試無效
IrpSp->FileObject//測試無效

Irp->AssociatedIrp.SystemBuffer;//有效

  1. //R3UserResult = hipsGetResultFromUser(szOper, lpNameControl->Name.Buffer, ((PFILE_RENAME_INFORMATION)(lpIrp->AssociatedIrp.SystemBuffer))->FileName, User_DefaultNon);
  2. if(R3UserResult == User_Block)
  3. <span style="white-space:pre"></span>goto Ex;
  4. DbgPrint("%ws\n",((PFILE_RENAME_INFORMATION)(lpIrp->AssociatedIrp.SystemBuffer))->FileName);
fileObject->DeviceObject
RtlVolumeDeviceToDosName
ObQueryNameString
IoQueryFileDosDeviceName
FileDispositionInformation//刪除
刪除
例子: 這個例子中還沒拿到重命名后的文件名 和將重命名后的文件名傳給R3 (hipsGetResultFromUser的第三個參數(shù))
  1. NTSTATUS
  2. sfSetInformation(PDEVICE_OBJECT lpDevice, PIRP lpIrp)
  3. {
  4. NTSTATUSStatus= STATUS_SUCCESS;
  5. ULONGulInfomation= 0;
  6. UNICODE_STRINGustrRule= {0};
  7. PLIST_ENTRYCurrentList= NULL;
  8. USER_RESULTR3UserResult= User_Pass;
  9. PNAME_CONTROLlpNameControl= NULL;
  10. BOOLEANbSkipped= FALSE;
  11. BOOLEANbNeedPostOp= FALSE;
  12. BOOLEANbRename= FALSE;
  13. IO_STACK_LOCATION*lpIrpStack= IoGetCurrentIrpStackLocation(lpIrp);
  14. PFILE_OBJECTlpFileObject= lpIrpStack->FileObject;
  15. PTWOWAYpTwoWay= NULL;
  16. WCHAR*szOper= NULL;
  17. if (IS_MY_CONTROL_DEVICE_OBJECT(lpDevice))
  18. {
  19. lpIrp->IoStatus.Status = Status;
  20. lpIrp->IoStatus.Information = ulInfomation;
  21. IoCompleteRequest(lpIrp, IO_NO_INCREMENT);
  22. return Status;
  23. }
  24. else if (!IS_MY_DEVICE_OBJECT(lpDevice))
  25. {
  26. lpIrp->IoStatus.Status = Status = STATUS_INVALID_PARAMETER;
  27. lpIrp->IoStatus.Information = 0;
  28. IoCompleteRequest(lpIrp, IO_NO_INCREMENT);
  29. return Status;
  30. }
  31. else
  32. {
  33. PSFILTER_DEVICE_EXTENSION lpDevExt = (PSFILTER_DEVICE_EXTENSION)(lpDevice->DeviceExtension);
  34. if (PsGetCurrentProcessId() == g_hSystemProcID)
  35. {
  36. bSkipped = TRUE;
  37. goto _EXIT;
  38. }
  39. //從HASH表中獲得文件名
  40. pTwoWay = Find((DWORD)lpFileObject, g_pHashTable);
  41. if (pTwoWay == NULL)
  42. {
  43. bSkipped = TRUE;
  44. goto _EXIT;
  45. }
  46. lpNameControl = pTwoWay->data.lpNameControl;
  47. if (lpIrpStack->Parameters.SetFile.FileInformationClass == FileRenameInformation ||
  48. lpIrpStack->Parameters.SetFile.FileInformationClass == FileBasicInformation ||
  49. lpIrpStack->Parameters.SetFile.FileInformationClass == FileAllocationInformation ||
  50. lpIrpStack->Parameters.SetFile.FileInformationClass == FileEndOfFileInformation ||
  51. lpIrpStack->Parameters.SetFile.FileInformationClass == FileDispositionInformation)
  52. {
  53. switch (lpIrpStack->Parameters.SetFile.FileInformationClass)
  54. {
  55. case FileAllocationInformation:
  56. case FileEndOfFileInformation:
  57. szOper = L"設(shè)置大小";
  58. bSkipped = TRUE;
  59. goto _EXIT;
  60. // break;
  61. case FileRenameInformation:
  62. szOper = L"重命名";
  63. break;
  64. case FileBasicInformation:
  65. szOper = L"設(shè)置基礎(chǔ)信息";
  66. bSkipped = TRUE;
  67. goto _EXIT;
  68. //break;
  69. case FileDispositionInformation:
  70. bNeedPostOp = TRUE;
  71. szOper = L"刪除";
  72. break;
  73. }
  74. }
  75. else
  76. {
  77. // 允許
  78. bSkipped = TRUE;
  79. goto _EXIT;
  80. }
  81. RtlInitUnicodeString(&ustrRule, L"C:\\WINDOWS\\SYSTEM32\\*\\*.SYS");
  82. if (!IsPatternMatch(&ustrRule, &lpNameControl->Name, TRUE))
  83. {
  84. bSkipped = TRUE;
  85. goto _EXIT;
  86. }
  87. if (lpIrpStack->Parameters.SetFile.FileInformationClass == FileRenameInformation)
  88. {
  89. //重命名的目標(biāo)路徑?
  90. }
  91. R3UserResult = hipsGetResultFromUser(szOper, lpNameControl->Name.Buffer, NULL, User_DefaultNon);
  92. if (R3UserResult == User_Block)
  93. {
  94. // 禁止
  95. lpIrp->IoStatus.Information = 0;
  96. lpIrp->IoStatus.Status = STATUS_ACCESS_DENIED;
  97. IoCompleteRequest(lpIrp, IO_NO_INCREMENT);
  98. Status = STATUS_ACCESS_DENIED;
  99. bSkipped = FALSE;
  100. goto _EXIT;
  101. }
  102. bSkipped = TRUE;
  103. }
  104. _EXIT:
  105. if (bSkipped)
  106. {
  107. KEVENT waitEvent;
  108. IoCopyCurrentIrpStackLocationToNext(lpIrp);
  109. KeInitializeEvent(&waitEvent,
  110. NotificationEvent,
  111. FALSE);
  112. IoSetCompletionRoutine(lpIrp,
  113. SetFilterCompletion,
  114. &waitEvent,
  115. TRUE,
  116. TRUE,
  117. TRUE);
  118. Status = IoCallDriver(
  119. ((PSFILTER_DEVICE_EXTENSION)lpDevice->DeviceExtension)->NLExtHeader.AttachedToDeviceObject,
  120. lpIrp);
  121. if (Status == STATUS_PENDING)
  122. {
  123. Status = KeWaitForSingleObject(&waitEvent,
  124. Executive,
  125. KernelMode,
  126. FALSE,
  127. NULL);
  128. }
  129. Status = lpIrp->IoStatus.Status;
  130. IoCompleteRequest(lpIrp, IO_NO_INCREMENT);
  131. }
  132. return Status;
  133. }



參考:
http://blog.csdn.net/cosmoslife/article/details/7727688
http://bbs./archive/index.php?t-152338.html                 

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    熟妇久久人妻中文字幕| 国产亚洲午夜高清国产拍精品| 国产精品不卡一区二区三区四区| 婷婷开心五月亚洲综合| 大香伊蕉欧美一区二区三区| 国产毛片对白精品看片| 日韩精品综合免费视频| av一区二区三区天堂| 91欧美日韩国产在线观看| 欧美成人精品一区二区久久| 欧美激情区一区二区三区| 国产精品欧美激情在线| 欧美精品在线观看国产| 91人妻人澡人人爽人人精品| 精品日韩av一区二区三区| 欧美不卡一区二区在线视频| 日本免费一级黄色录像| 伊人久久五月天综合网| 日韩在线欧美一区二区| 日本精品理论在线观看| 国产又粗又猛又爽色噜噜| 欧美亚洲另类久久久精品| 中文字幕高清不卡一区| 尹人大香蕉中文在线播放| 国产精品伦一区二区三区四季| 欧美亚洲另类久久久精品| 国内尹人香蕉综合在线| 微拍一区二区三区福利| 中文字幕亚洲人妻在线视频| 亚洲视频一区二区久久久| 国产精品涩涩成人一区二区三区| 一区中文字幕人妻少妇| 好吊色欧美一区二区三区顽频 | 男人和女人黄 色大片| 可以在线看的欧美黄片| 中文字幕五月婷婷免费| 最新69国产精品视频| 欧美特色特黄一级大黄片| 懂色一区二区三区四区| 国产av熟女一区二区三区四区| 亚洲一区二区三区四区性色av|