WINDOWS文件过滤系统驱动开发,可用于硬盘还原,防病毒,文件安全防护,文件加密 等诸多领域。而掌握核心层的理论及实践,对于成为一名优秀的开发人员不可或缺。
WINDOWS文件过滤系统驱动开发的两个经典例子,Filemon与SFilter,初学者在经 过一定的理论积累后,对此两个例子代码的研究分析,会是步入驱动开发殿堂的重要一步 ,相信一定的理论积累以及贯穿剖析理解此两个例程后,就有能力开始进行文件过滤系统 驱动开发的实际工作了。
对于SFilter例子的讲解,楚狂人的教程已经比较流行, 而Filemon例子也许因框架结构相对明晰,易于剖析理解,无人贴出教程,本人在剖析 Filemon的过程中积累的一些笔记资料,陆续贴出希望对初学者有所帮助,并通过和大家 的交流而互相提高。
Filemon学习笔记 第一篇:
Filemon的大致架构为, 在此驱动程序中,创建了两类设备对象。
一类设备对象用于和Filemon对应的exe 程序通信,以接收用户输入信息,比如挂接或监控哪个分区,是否要挂接,是否要监控, 监控何种操作等。此设备对象只创建了一个,在驱动程序的入口函数DriverEntry中。此 类设备对象一般称为控制设备对象,并有名字,以方便应用层与其通信操作。
第 二类设备对象用于挂接到所须监控的分区,比如c:,d:或e:,f:,以便拦截到引应用 层对该分区所执行的读,写等操作。此类设备对象为安全起见,一般不予命名,可根据须 监控多少分区而创建一个或多个。
驱动入口函数大致如下:
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
//此设备对象用来和用户交互信息
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();//为了得到当前进程名字
//
// 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;
}