青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

S.l.e!ep.¢%

像打了激速一樣,以四倍的速度運(yùn)轉(zhuǎn),開心的工作
簡(jiǎn)單、開放、平等的公司文化;尊重個(gè)性、自由與個(gè)人價(jià)值;
posts - 1098, comments - 335, trackbacks - 0, articles - 1
  C++博客 :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

? 文件過(guò)濾系統(tǒng)驅(qū)動(dòng)開發(fā) Filemon 學(xué)習(xí)筆記

? ??????????????????????????

?

WINDOWS 文件過(guò)濾系統(tǒng)驅(qū)動(dòng)開發(fā),可用于硬盤還原,防病毒,文件安全防護(hù),文件加密等諸多領(lǐng)域。而掌握核心層的理論及實(shí)踐,對(duì)于成為一名優(yōu)秀的開發(fā)人員不可或缺。

?

WINDOWS 文件過(guò)濾系統(tǒng)驅(qū)動(dòng)開發(fā)的兩個(gè)經(jīng)典例子, Filemon SFilter ,初學(xué)者在經(jīng)過(guò)一定的理論積累后,對(duì)此兩個(gè)例子代碼的研究分析,會(huì)是步入驅(qū)動(dòng)開發(fā)殿堂的重要一步,相信一定的理論積累以及貫穿剖析理解此兩個(gè)例程后,就有能力開始進(jìn)行文件過(guò)濾系統(tǒng)驅(qū)動(dòng)開發(fā)的實(shí)際工作了。

對(duì)于 SFilter 例子的講解,楚狂人的教程已經(jīng)比較流行,而 Filemon 例子也許因框架結(jié)構(gòu)相對(duì)明晰,易于剖析理解,無(wú)人貼出教程,本人在剖析 Filemon 的過(guò)程中積累的一些筆記資料,陸續(xù)貼出希望對(duì)初學(xué)者有所幫助,并通過(guò)和大家的交流而互相提高。

?

???????????????????? Filemon 學(xué)習(xí)筆記 第一篇:

?

?

Filemon 的大致架構(gòu)為,在此驅(qū)動(dòng)程序中,創(chuàng)建了兩類設(shè)備對(duì)象。

一類設(shè)備對(duì)象用于和 Filemon 對(duì)應(yīng)的 exe 程序通信,以接收用戶輸入信息,比如掛接或監(jiān)控哪個(gè)分區(qū),是否要掛接,是否要監(jiān)控,監(jiān)控何種操作等。此設(shè)備對(duì)象只創(chuàng)建了一個(gè),在驅(qū)動(dòng)程序的入口函數(shù) DriverEntry 中。此類設(shè)備對(duì)象一般稱為控制設(shè)備對(duì)象,并有名字,以方便應(yīng)用層與其通信操作。

第二類設(shè)備對(duì)象用于掛接到所須監(jiān)控的分區(qū),比如 c :, d :或 e :, f :,以便攔截到引應(yīng)用層對(duì)該分區(qū)所執(zhí)行的讀,寫等操作。此類設(shè)備對(duì)象為安全起見(jiàn),一般不予命名,可根據(jù)須監(jiān)控多少分區(qū)而創(chuàng)建一個(gè)或多個(gè)。

?

驅(qū)動(dòng)入口函數(shù)大致如下

?

NTSTATUS

DriverEntry(

??? IN PDRIVER_OBJECT DriverObject,

??? IN PUNICODE_STRING RegistryPath

??? )

{

??? NTSTATUS??????????????? ntStatus;

??? PDEVICE_OBJECT????????? guiDevice;

??? WCHAR?????????????????? deviceNameBuffer[]? = L"\\Device\\Filemon";

??? UNICODE_STRING????????? deviceNameUnicodeString;

??? WCHAR?????????????????? deviceLinkBuffer[]? = L"\\DosDevices\\Filemon";

??? UNICODE_STRING????????? deviceLinkUnicodeString;

??? ULONG?????????????????? i;

?

??? DbgPrint (("Filemon.SYS: entering DriverEntry\n"));

??? FilemonDriver = DriverObject;

?

??? //???

??? // Setup the device name

??? //???

??? RtlInitUnicodeString (&deviceNameUnicodeString,

????????????????????????? deviceNameBuffer );

?

??? //

??? // Create the device used for GUI communications

??? // 此設(shè)備對(duì)象用來(lái)和用戶交互信息

??? ntStatus = IoCreateDevice ( DriverObject,

??????????????????????????????? sizeof(HOOK_EXTENSION),

??????????????????????????????? &deviceNameUnicodeString,

??????????????????????????????? FILE_DEVICE_FILEMON,

??????????????????????????????? 0,

?????????????????? ?????????????TRUE,

??????????????????????????????? &guiDevice );

?

??? //

??? // If successful, make a symbolic link that allows for the device

??? // object's access from Win32 programs

??? //

??? if(NT_SUCCESS(ntStatus)) {

?

??????? //

??????? // Mark this as our GUI device

??????? //

??????? ((PHOOK_EXTENSION) guiDevice->DeviceExtension)->Type = GUIINTERFACE;

?

??????? //

??????? // Create a symbolic link that the GUI can specify to gain access

??????? // to this driver/device

??????? //

??????? RtlInitUnicodeString (&deviceLinkUnicodeString,

????????????????????????????? deviceLinkBuffer );

??????? ntStatus = IoCreateSymbolicLink (&deviceLinkUnicodeString,

???????????????????????????????????????? &deviceNameUnicodeString );

??????? if(!NT_SUCCESS(ntStatus)) {

?

??????????? DbgPrint (("Filemon.SYS: IoCreateSymbolicLink failed\n"));

??????????? IoDeleteDevice( guiDevice );

??????????? return ntStatus;???????????

??????? }

?

??????? //

??????? // Create dispatch points for all routines that must be handled.

?? ?????// All entry points are registered since we might filter a

??????? // file system that processes all of them.

??????? //

??????? for( i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++ ) {

?

??????????? DriverObject->MajorFunction[i] = FilemonDispatch;

??????? }

#if DBG???????

??????? //

??????? // Driver unload is only set if we are debugging Filemon. This is

??????? // because unloading a filter is not really safe - threads could

??????? // be in our fastio routines (or about to enter them), for example,

?? ?????// and there is no way to tell. When debugging, we can risk the

??????? // occasional unload crash as a trade-off for not having to

??????? // reboot as often.

??????? //

??????? // DriverObject->DriverUnload = FilemonUnload;

#endif // DBG

?

??????? //

??????? // Set up the Fast I/O dispatch table

??????? //

??????? DriverObject->FastIoDispatch = &FastIOHook;

?

??? } else {

?

??????? //

??????? // If something went wrong, cleanup the device object and don't load

??????? //

??????? DbgPrint(("Filemon: Failed to create our device!\n"));

??????? return ntStatus;

??? }

?

??? //

??? // Initialize the name hash table

??? //

??? for(i = 0; i < NUMHASH; i++ ) HashTable[i] = NULL;

?

??? //

??? // Find the process name offset

??? //

??? ProcessNameOffset = FilemonGetProcessNameOffset();// 為了得到當(dāng)前進(jìn)程名字

?

??? //

??? // Initialize the synchronization objects

??? //

#if DBG

??? KeInitializeSpinLock( &CountMutex );

#endif

??? ExInitializeFastMutex( &LogMutex );

??? ExInitializeResourceLite( &FilterResource );

??? ExInitializeResourceLite( &HashResource );

?

??? //

??? // Initialize a lookaside for file names

??? //

??? ExInitializeNPagedLookasideList( &FullPathLookaside, NULL, NULL,

??????????????????????????? ???? 0, MAXPATHLEN, 'mliF', 256 );

?

??? //

??? // Allocate the first output buffer

??? //

? ??CurrentLog = ExAllocatePool( NonPagedPool, sizeof(*CurrentLog) );

??? if( !CurrentLog ) {

?

??????? //

??????? // Oops - we can't do anything without at least one buffer

??????? //

??????? IoDeleteSymbolicLink( &deviceLinkUnicodeString );

??????? IoDeleteDevice( guiDevice );

??????? return STATUS_INSUFFICIENT_RESOURCES;

??? }

?

??? //

??? // Set the buffer pointer to the start of the buffer just allocated

??? //

??? CurrentLog->Len? = 0;

??? CurrentLog->Next = NULL;

??? NumLog = 1;

?

??? return STATUS_SUCCESS;

}

?

在此驅(qū)動(dòng)入口點(diǎn)函數(shù)中,主要做了生成新的設(shè)備對(duì)象,此設(shè)備對(duì)象用來(lái)和應(yīng)用層信息交互,比如應(yīng)用層向驅(qū)動(dòng)傳遞需要掛接或者監(jiān)控的分區(qū)盤符,或者是否掛接盤符,是否監(jiān)控操作等。

上面創(chuàng)建設(shè)備對(duì)象的代碼為:

ntStatus = IoCreateDevice ( DriverObject,

??????????????????????????????? sizeof(HOOK_EXTENSION),

??????????????????????????????? &deviceNameUnicodeString,

??? ????????????????????????????FILE_DEVICE_FILEMON,

??????????????????????????????? 0,

??????????????????????????????? TRUE,

??????????????????????????????? &guiDevice );

?

??? //

??? // If successful, make a symbolic link that allows for the device

??? // object's access from Win32 programs

??? //

??? if(NT_SUCCESS(ntStatus)) {

?

??????? //

??????? // Mark this as our GUI device

??????? //

??????? ((PHOOK_EXTENSION) guiDevice->DeviceExtension)->Type = GUIINTERFACE;

?

??????? //

??????? // Create a symbolic link that the GUI can specify to gain access

??????? // to this driver/device

??????? //

??????? RtlInitUnicodeString (&deviceLinkUnicodeString,

????????????????????????????? deviceLinkBuffer );

??????? ntStatus = IoCreateSymbolicLink (&deviceLinkUnicodeString,

???????????????????????????????????????? &deviceNameUnicodeString );

??????? if(!NT_SUCCESS(ntStatus)) {

?

??????????? DbgPrint (("Filemon.SYS: IoCreateSymbolicLink failed\n"));

??????????? IoDeleteDevice( guiDevice );

??????????? return ntStatus;???????? ???

??????? }

上面代碼完成的功能為創(chuàng)建了用于與應(yīng)用層交互的控制設(shè)備對(duì)象,名字在參數(shù) &deviceNameUnicodeString, 中。設(shè)備對(duì)象創(chuàng)建成功后又調(diào)用 IoCreateSymbolicLink 創(chuàng)建了一個(gè)符號(hào)連接,以便于應(yīng)用層交互。

?

在入口點(diǎn)函數(shù) DriverEntry 代碼中,還有一處代碼:

ProcessNameOffset = FilemonGetProcessNameOffset();// 為了得到當(dāng)前進(jìn)程名字。

此函數(shù)體如下:

ULONG

FilemonGetProcessNameOffset(

??? VOID

??? )

{

??? PEPROCESS?????? curproc;

??? int???????????? i;

?

??? curproc = PsGetCurrentProcess();// 調(diào)用 PsGetCurrentProcess 取得 KPEB 基址

?

??? // 然后搜索 KPEB ,得到 ProcessName 相對(duì) KPEB 的偏移量

??? // Scan for 12KB, hoping the KPEB never grows that big!

??? //

? ??for( i = 0; i < 3*PAGE_SIZE; i++ ) {

????

??????? if( !strncmp( SYSNAME, (PCHAR) curproc + i, strlen(SYSNAME) )) {

?

??????????? return i;

??????? }

??? }

?

??? //

??? // Name not found - oh, well

??? //

??? return 0;

?

這個(gè)函數(shù)通過(guò)查找 KPEB (Kernel?Process?Environment?Block) ,取得進(jìn)程名, GetProcessNameOffset 主要是調(diào)用 PsGetCurrentProcess 取得 KPEB 基址,然后搜索 KPEB ,得到 ProcessName 相對(duì) KPEB 的偏移量,存放在全局變量 ProcessNameOffset 中,得到此偏移量的作用是:無(wú)論當(dāng)前進(jìn)程為哪個(gè),其名字在 KPEB 中的偏移量不變,所以都可以通過(guò)此偏移量得到。而在入口點(diǎn)函數(shù) DriverEntry 執(zhí)行時(shí),當(dāng)前進(jìn)程必為系統(tǒng)進(jìn)程,所以在此函數(shù)中方便地根據(jù)系統(tǒng)進(jìn)程名 SYSNAME #define SYSNAME? ??"System" )得到此偏移量。

?

分發(fā)函數(shù)剖析:

在入口點(diǎn)函數(shù)中,通過(guò)代碼:

for( i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++ ) {

?

??????????? DriverObject->MajorFunction[i] = FilemonDispatch;

??????? }

簡(jiǎn)單地把各個(gè)分發(fā)例程設(shè)置成了 FilemonDispatch; 然后我們追蹤其函數(shù)體:

?

NTSTATUS

FilemonDispatch(

??? IN PDEVICE_OBJECT DeviceObject,

??? IN PIRP Irp

??? )

{

??? //

??? // Determine if its a request from the GUI to us, or one that is

??? // directed at a file system driver that we've hooked

??? //

??? if( ((PHOOK_EXTENSION) DeviceObject->DeviceExtension)->Type == GUIINTERFACE ) {

?

??????? return FilemonDeviceRoutine( DeviceObject, Irp );

?

??? } else {

?

??????? return FilemonHookRoutine( DeviceObject, Irp );

??? }

}

?

函數(shù)體先判斷需要處理 IRP 包的設(shè)備對(duì)象的類型,看是屬于控制設(shè)備對(duì)象,還是屬于用于掛接并監(jiān)控文件讀寫操作的過(guò)濾設(shè)備對(duì)象。如果是屬于后者 則進(jìn)入: FilemonHookRoutine( DeviceObject, Irp )

此函數(shù)是攔截文件操作的中心,在其中獲得了被操作的文件名字,并且根據(jù)操作類型,在

switch( currentIrpStack->MajorFunction ) {

}

中針對(duì)不同的 MajorFunction ,打印出相關(guān)操作信息。

因此函數(shù)體太長(zhǎng) 不再全部列出。

其函數(shù)體總體框架為:得到被操作的文件名字,打印相關(guān)操作信息,然后下發(fā) IRP 到底層驅(qū)動(dòng)。

在下發(fā) IRP 到底層驅(qū)動(dòng)處理前,本層驅(qū)動(dòng)必須負(fù)責(zé)設(shè)置下層 IO 堆棧的內(nèi)容。這樣下一層驅(qū)動(dòng)調(diào)用 IoGetCurrentIrpStackLocation() 時(shí)能得到相應(yīng)的數(shù)據(jù)。

設(shè)置下層 IO 堆棧的內(nèi)容,一般用兩個(gè)函數(shù)來(lái)實(shí)現(xiàn):

IoCopyCurrentIrpStackLocationToNext( Irp )

此函數(shù)一般用在本驅(qū)動(dòng)設(shè)置了完成例程時(shí)調(diào)用,把本層 IO _STACK_LOCATION 中的參數(shù) copy 到下層,但與完成例程相關(guān)的參數(shù)信息例外。因?yàn)楸掘?qū)動(dòng)設(shè)置的完成例程只對(duì)本層驅(qū)動(dòng)有效。

IoSkipCurrentIrpStackLocationToNext(Irp)

此函數(shù)的作用是:直接把本層驅(qū)動(dòng) IO 堆棧的內(nèi)容設(shè)置為下層驅(qū)動(dòng) IO 堆棧指針的指向。因兩層驅(qū)動(dòng) IO 堆棧的內(nèi)容完全一致,省卻 copy 過(guò)程。

?

而在 Filemon 的處理中,它用了一個(gè)特別的辦法,沒(méi)有調(diào)用此兩個(gè)函數(shù), FilemonHookRoutine 函數(shù)體里面有三句代碼:

?

??? PIO_STACK_LOCATION? currentIrpStack = IoGetCurrentIrpStackLocation(Irp);

PIO_STACK_LOCATION? nextIrpStack??? = IoGetNextIrpStackLocation(Irp);

?

*nextIrpStack = *currentIrpStack;// 此步設(shè)置了下層驅(qū)動(dòng)的 IO_STACK_LOCATION

直接設(shè)置了下層驅(qū)動(dòng) IO 堆棧的值。

?

FilemonHookRoutine 函數(shù)里,用一個(gè)宏實(shí)現(xiàn)了復(fù)雜的獲得攔截到的被操作文件的名字:

?

if( FilterOn && hookExt->Hooked ) {

?

? ??????GETPATHNAME( createPath );

}

?

GETPATHNAME( createPath ) 宏展開為:

?

#define GETPATHNAME(_IsCreate)????????????????????????????????????????????????? \

??????? fullPathName = ExAllocateFromNPagedLookasideList( &FullPathLookaside ); \

??????? if( fullPathName ) {??????????????????????????????????????????????????? \

??????????? FilemonGetFullPath( _IsCreate, FileObject, hookExt, fullPathName ); \

??????? } else {??????????????????????????????????????????????????????????????? \

??????????? fullPathName = InsufficientResources;?????????????????????????????? \

??????? }?????

?

在函數(shù): FilemonGetFullPath( _IsCreate, FileObject, hookExt, fullPathName ) 中實(shí)現(xiàn)了獲得被操作的文件名字,此函數(shù)代碼較多,判斷條件復(fù)雜,理解起來(lái)比較麻煩,下面重點(diǎn)講解。

對(duì)函數(shù) FilemonGetFullPath 的理解關(guān)鍵在于理順結(jié)構(gòu),

此函數(shù)的功能就是獲得文件名字,獲得文件名字一般在三種狀態(tài)下:

一:在打開文件請(qǐng)求中,但在打開文件前。

二:在打開文件請(qǐng)求中,但在打開文件后,通過(guò)在本層驅(qū)動(dòng)中設(shè)置完成例程。在完成例程中獲得。

三:在過(guò)濾到讀寫等操作時(shí)。

而在此函數(shù)中,它包含了第一種和第三種方法,通過(guò)一些煩瑣的條件判斷,先判斷出目前是處于什么狀態(tài)中,然后根據(jù)不同狀態(tài)采取不同方法。

先分析當(dāng)在第一種條件下,此函數(shù)的處理方法,可以精煉為如下:

?

?

VOID

FilemonGetFullPath(

??? BOOLEAN createPath,

??? PFILE_OBJECT fileObject,

??? PHOOK_EXTENSION hookExt,

??? PCHAR fullPathName

??? )

{

?????? ULONG????? ?????????pathLen, prefixLen, slashes;

??? PCHAR?????????????? pathOffset, ptr;

??? BOOLEAN???????????? gotPath;

??? PFILE_OBJECT??????? relatedFileObject;

???

??? ANSI_STRING???????? fileName;

??? ANSI_STRING???????? relatedName;

???

??? UNICODE_STRING? ????fullUniName;

?

?

?????? prefixLen = 2; // "C:"

?

?????? if( !fileObject ) {

?

??????? sprintf( fullPathName, "%C:", hookExt->LogicalDrive );

??????? return;

??? }

?

??????

??? //

??? // Initialize variables

??? //

??? fileName.Buffer = NULL;

??? relatedName.Buffer = NULL;

??? gotPath = FALSE;

?

?????? if( !fileObject->FileName.Buffer)

?????? {

????????????? sprintf( fullPathName, "%C:", hookExt->LogicalDrive);

????????????? return;

?????? }else

????????????? DbgPrint("fileOjec->FileName:%s",fileObject->FileName);

?

?????? ?if( !NT_SUCCESS( RtlUnicodeStringToAnsiString( &fileName, &fileObject->FileName, TRUE ))) {

?

??????????? sprintf( fullPathName, "%C: <Out of Memory>", hookExt->LogicalDrive );

??????????? return;

??????? }

?

?????? ?

??????? pathLen = fileName.Length + prefixLen;

??????? relatedFileObject = fileObject->RelatedFileObject;

?

????????????? ? //

??????? // Only look at related file object if this is a relative name

??????? //

??????? if( fileObject->FileName.Buffer[0] != L'\\' &&

??????????? relatedFileObject && relatedFileObject->FileName.Length ) {

???????????????????? DbgPrint("relatedFileObject filename : %s",relatedFileObject->FileName);

?????? ???????

???????????????????? if( !NT_SUCCESS( RtlUnicodeStringToAnsiString( &relatedName, &relatedFileObject->FileName, TRUE ))) {

?

??????????????

??????????????? sprintf( fullPathName, "%C: <Out of Memory>", hookExt->LogicalDrive );

??????????????? RtlFreeAnsiString( &fileName );

??????????????? return;

??????????? }

??????????? pathLen += relatedName.Length+1;

??????? }

?

????????????? if( fileObject->DeviceObject->DeviceType != FILE_DEVICE_NETWORK_FILE_SYSTEM ) {

?

??????????? sprintf( fullPathName, "%C:", hookExt->LogicalDrive );

??????? }

?

????????????? ?if( pathLen >= MAXPATHLEN ) {

???????????

??????????? strcat( fullPathName, " <Name Too Long>" );

?

??????? } else {

???

??????????? //

??????????? // Now we can build the path name

??????????? //

?????? ?????fullPathName[ pathLen ] = 0;

???????????

??????????? pathOffset = fullPathName + pathLen - fileName.Length;

??????????? memcpy( pathOffset, fileName.Buffer, fileName.Length + 1 );

???

??????????? if( fileObject->FileName.Buffer[0] != L'\\' &&

???? ???????????relatedFileObject && relatedFileObject->FileName.Length ) {

?

??????????????? //

??????????????? // Copy the component, adding a slash separator

??????????????? //

??????????????? *(pathOffset - 1) = '\\';

??????????????? pathOffset -= relatedName.Length + 1;

???????????????????

??????????????? memcpy( pathOffset, relatedName.Buffer, relatedName.Length );

?

??????????????? //

??????????????? // If we've got to slashes at the front zap one

??????????????? //

??????????????? if( pathLen > 3 && fullPathName[2] == '\\' && fullPathName[3] == '\\' )? {

???????????????????

??????????????????? strcpy( fullPathName + 2, fullPathName + 3 );

??????????????? }

??????????? }

??????? }?

??????

?

}

上面的精簡(jiǎn)后的函數(shù)代碼為只考慮目前處于第一種情況,即打開文件請(qǐng)求中,但文件尚未打開時(shí)。

在此時(shí),文件的名字信息存儲(chǔ)在文件對(duì)象 fileObject->FileName, fileObject->RelatedFileObject->FileName, FileObject->FileName RelatedObject 的相對(duì)路徑, 通過(guò)對(duì)兩者的解析組合出文件名字。

?

?

而在 FilemonGetFullPath 函數(shù)體中的另一段代碼:

?

?

FilemonGetFullPath

{

…………………..

…………………..

…………………..

if( !gotPath && !createPath ) {

?

???????

??????? fileNameInfo = (PFILE_NAME_INFORMATION) ExAllocatePool( NonPagedPool,

??????????????????????????????????????????????????????????????? MAXPATHLEN*sizeof(WCHAR) );

?

??????? if( fileNameInfo &&

??????????? FilemonQueryFile(hookExt->FileSystem, fileObject, FileNameInformation,

???????????????????????????? fileNameInfo, (MAXPATHLEN - prefixLen - 1)*sizeof(WCHAR) )) {

?

??????????? fullUniName.Length = (SHORT) fileNameInfo->FileNameLength;

????? ??????fullUniName.Buffer = fileNameInfo->FileName;

??????????? if( NT_SUCCESS( RtlUnicodeStringToAnsiString( &fileName, &fullUniName, TRUE ))) {

?

??????????????? fullPathName[ fileName.Length + prefixLen ] = 0;

?

??????????????? if( hookExt->Type == NPFS ) {

???????????????????

??????????????????? strcpy( fullPathName, NAMED_PIPE_PREFIX );

?

??????????????? } else if( hookExt->Type == MSFS ) {

?

??????????????????? strcpy( fullPathName, MAIL_SLOT_PREFIX );

?

??????????????? } else if( fileObject->DeviceObject->DeviceType != FILE_DEVICE_NETWORK_FILE_SYSTEM ) {

?

??????????????????? sprintf( fullPathName, "%C:", hookExt->LogicalDrive );

?

??????????????? } else {

???????????????

??????????????????? //

??????????????????? // No prefix for network devices

???????? ???????????//

??????????????? }

?

??????????????? memcpy( &fullPathName[prefixLen], fileName.Buffer, fileName.Length );

??????????????? gotPath = TRUE;

??????????????? RtlFreeAnsiString( &fileName );

??????????????? fileName.Buffer = NULL;

??????????? }

?? ?????}

??????? if( fileNameInfo ) ExFreePool( fileNameInfo );

}

………………….

…………………..

………………………

}

?

上面這段代碼是處理另外一種情況,即是在其他讀寫請(qǐng)求中,自己根據(jù)攔截到的 fileObject 構(gòu)建 IRP ,下發(fā)到底層,以此來(lái)查詢文件名信息。整個(gè)過(guò)程還是易于理解的。

?

在理清這兩種脈絡(luò)后,再剖析此整個(gè)函數(shù),就很容易理解整個(gè)函數(shù)代碼了。

代碼中對(duì) MajorFunction == IRP_MJ_CREATE_NAMED_PIPE

??????? ?MajorFunction == IRP_MJ_CREATE_MAILSLOT ? 的判斷是為了辨別對(duì)攔截到的進(jìn)程間的兩種通信方式:命名管道與郵槽的處理。

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲国产精品t66y| 99综合精品| 欧美精品在欧美一区二区少妇| 中文欧美日韩| 亚洲人成网在线播放| 欧美成人精精品一区二区频| 美女视频黄免费的久久| 免费亚洲一区二区| 欧美激情2020午夜免费观看| 欧美激情第3页| 亚洲高清久久久| 日韩午夜激情| 亚洲欧美国产视频| 久久久久久亚洲精品不卡4k岛国| 狂野欧美一区| 欧美日韩不卡在线| 国产精品人人爽人人做我的可爱 | 亚洲午夜免费福利视频| 亚洲综合精品一区二区| 欧美在线高清| 亚洲成色777777女色窝| 99re66热这里只有精品3直播| 亚洲一区二区三区视频播放| 亚洲欧美日韩另类精品一区二区三区| 亚洲一区二区三区涩| 欧美自拍偷拍| 欧美黄色免费网站| 亚洲天堂av在线免费| 久久久久88色偷偷免费| 欧美日韩视频第一区| 国产在线视频欧美| 在线视频精品一区| 欧美成人69av| 亚洲综合精品| 欧美激情一区二区三区四区| 国产乱码精品一区二区三| 亚洲精品中文字幕在线| 久久国产精品一区二区三区| 亚洲激情电影在线| 久久久国产一区二区三区| 国产精品高潮呻吟视频| 亚洲精品中文在线| 欧美成人免费播放| 欧美影院精品一区| 国产精品视频免费| 亚洲一区二区免费在线| 亚洲国产一区二区三区a毛片| 欧美亚洲在线观看| 欧美性猛交xxxx乱大交蜜桃| 在线视频国产日韩| 久久久久九九视频| 午夜精品久久久久久久久久久久| 欧美日本不卡高清| 91久久国产精品91久久性色| 蜜臀av性久久久久蜜臀aⅴ| 久久精品日韩欧美| 亚洲一区二区毛片| 亚洲人成网在线播放| 久久一区二区三区四区| 影音先锋亚洲视频| 免费观看亚洲视频大全| 久久精品综合一区| 激情六月综合| 老鸭窝91久久精品色噜噜导演| 亚洲专区在线视频| 国产精品美女久久久久久久| 在线视频亚洲欧美| 亚洲天堂偷拍| 国产欧美91| 久久婷婷麻豆| 老司机免费视频一区二区三区| 影音先锋成人资源站| 欧美国产日韩一区二区在线观看 | 亚洲无毛电影| 一区二区欧美亚洲| 国产精品久久久久久久久免费桃花 | 亚洲国产黄色| 欧美精品91| 亚洲欧美亚洲| 久久精品国语| 美女久久一区| 亚洲人成人一区二区三区| 亚洲黄色视屏| 国产精品国产一区二区 | 亚洲午夜在线观看视频在线| 夜夜爽www精品| 国产日本欧美视频| 欧美成人四级电影| 欧美日韩精品综合| 久久精品成人一区二区三区蜜臀| 久久久亚洲高清| 夜夜嗨一区二区三区| 亚洲免费在线视频一区 二区| 狠狠色丁香久久婷婷综合丁香| 欧美黄色片免费观看| 国产精品福利网| 久久综合伊人| 欧美日韩免费看| 久久久久综合| 欧美日本精品| 麻豆精品网站| 欧美性猛交99久久久久99按摩| 久久精品国产96久久久香蕉| 免费高清在线一区| 欧美亚洲色图校园春色| 欧美3dxxxxhd| 久久久亚洲成人| 欧美视频在线免费| 免费看av成人| 国产欧美激情| 亚洲人精品午夜在线观看| 韩国精品久久久999| 激情成人综合网| 免费在线日韩av| 欧美色图天堂网| 欧美大片在线观看一区二区| 国产精品久久一区二区三区| 亚洲第一黄色| 精品成人在线观看| 亚洲免费一区二区| 在线视频一区二区| 免费观看成人鲁鲁鲁鲁鲁视频| 欧美一区二区三区在线看| 欧美久久电影| 亚洲电影在线免费观看| 国产一区二区三区丝袜| 99精品免费网| 99re在线精品| 另类国产ts人妖高潮视频| 久久精品欧美日韩| 国产日韩精品一区二区三区| 一区二区三区精品国产| 一区二区欧美日韩| 欧美精品三级日韩久久| 亚洲成色www8888| 国产在线观看一区| 亚洲欧美综合国产精品一区| 亚洲欧美日韩中文视频| 欧美视频一区| 中文精品视频一区二区在线观看| 一区二区欧美国产| 国产精品igao视频网网址不卡日韩| 亚洲国产乱码最新视频| 亚洲国产日韩欧美在线99 | 国产精品中文字幕欧美| 亚洲视频免费在线| 午夜久久tv| 国产精品手机视频| 午夜视频一区在线观看| 久久视频精品在线| 伊人成人在线视频| 美女精品在线观看| 亚洲乱码国产乱码精品精98午夜| 一本色道久久综合亚洲精品婷婷| 欧美国产免费| 99国产精品久久久久老师| 亚洲一区综合| 国产欧美短视频| 久久久久久自在自线| 亚洲第一页自拍| 中文在线资源观看视频网站免费不卡| 欧美色精品天天在线观看视频| 亚洲一区二区网站| 久久网站免费| 日韩一二三区视频| 国产美女精品一区二区三区| 久久激情视频| 亚洲精品在线二区| 欧美在线免费观看视频| 欲色影视综合吧| 国产精品va在线| 久久久久国产免费免费| 亚洲国产欧美一区二区三区久久| 亚洲一区在线免费| 亚洲大胆人体在线| 国产精品日日摸夜夜摸av| 久久久综合精品| 亚洲最新在线视频| 国产主播一区二区三区| 欧美国内亚洲| 亚洲欧美日韩精品综合在线观看| 免费av成人在线| 亚洲欧美国产高清va在线播| 一区二区三区在线免费视频| 欧美另类69精品久久久久9999| 午夜精品久久久久久久99黑人| 亚洲国产精品va在线看黑人| 欧美一区二区三区播放老司机| 亚洲精品国产精品国产自| 国产手机视频精品| 欧美吻胸吃奶大尺度电影| 久久精品免费观看| 亚洲永久免费av| 亚洲精品视频一区| 欧美大片在线看| 久久婷婷丁香| 久久国产成人| 亚洲欧洲av一区二区三区久久| 亚洲精品一区二区三区在线观看| 国外视频精品毛片|