读源码笔记--文件过滤驱动FileSpy第1篇 -- DriverEntry

2024-09-07 15:08

本文主要是介绍读源码笔记--文件过滤驱动FileSpy第1篇 -- DriverEntry,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

今天只读FileSpy的DriverEntry,位于源文件:filespy.c。

//
// 全局变量.
//

ULONG gFileSpyDebugLevel = DEFAULT_FILESPY_DEBUG_LEVEL;
#if WINVER >= 0x0501
ULONG gFileSpyAttachMode = FILESPY_ATTACH_ALL_VOLUMES;
#else
ULONG gFileSpyAttachMode = FILESPY_ATTACH_ON_DEMAND;
#endif

 

NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegPath)

{

    UNICODE_STRING nameString;
    NTSTATUS status;
    PFAST_IO_DISPATCH fastIoDispatch;
    ULONG i;
    UNICODE_STRING linkString;

 

#if WINVER >= 0x0501

//第一步,获取动态函数。

 

//目的只有一个,兼容Windows的之前的版本。原因是:有些Windows后面版本出现的函数,在出现之前的Windows操作系统中是没有。

//如果直接使用该函数,在该函数出现之前的Windows操作系统中,将直接导致驱动加载失败。

 

//这里面包括如下动态加载的函数:

// 1.FsRtlRegisterFileSystemFilterCallbacks:注册一些通知回调函数,当下层文件驱动执行某些操作的时候调用。2K SP4和XP以后可用。

// 2.IoAttachDeviceToDeviceStackSafe:绑定目标设备对象。2K SP4和XP以后可用。

// 3.IoEnumerateDeviceObjectList:枚举驱动的设备对象链。2K SP4和XP以后可用。

// 4.IoGetLowerDeviceObject:获取当前驱动的下一层的设备对象。2K SP4和XP以后可用。

// 5.IoGetDeviceAttachmentBaseRef:获取文件系统驱动或设备驱动栈底的设备对象。2K SP4和XP以后可用。

// 6.IoGetDiskDeviceObject:获取与给定文件系统卷设备相关的磁盘设备对象。2K SP4和XP以后可用。

// 7.IoGetAttachedDeviceReference:获取驱动栈顶的设备对象,并将该设备对象的引用计数增1。2K 和XP以后可用。

// 8.RtlGetVersion:获取操作系统版本。

SpyLoadDynamicFunctions();

 

// 获取操作系统版本,调用的是RtlGetVersion或PsGetVersion。

SpyGetCurrentVersion();

#endif

 

// 从注册表中获取FileSpy指定的参数。

// 根据RegistryPath在注册表中的路径,

// 1.查询“MaxRecords”

//                数据结构体为:KEY_VALUE_PARTIAL_INFORMATION,其下的Data成员的内容放于全局变量:gMaxRecordsToAllocate中

// 2.查询“MaxNames”

//                 数据结构体为:KEY_VALUE_PARTIAL_INFORMATION,其下的Data成员的内容放于全局变量:gMaxNamesToAllocate中

// 3.查询“DebugFlags”

//                 数据结构体为:KEY_VALUE_PARTIAL_INFORMATION,其下的Data成员的内容放于全局变量:gFileSpyDebugLevel中

// 4.查询“AttachMode”

//                 数据结构体为:KEY_VALUE_PARTIAL_INFORMATION,其下的Data成员的内容放于全局变量:gFileSpyAttachMode中

SpyReadDriverParameters( RegistryPath );

 

// #ifndef FlagOn
// #define FlagOn(_F,_SF)        ((_F) & (_SF))
// #endif

if (FlagOn(gFileSpyDebugLevel,   SPYDEBUG_BREAK_ON_DRIVER_ENTRY)) {

        DbgBreakPoint();
    }

 

//

// 将DriverEntry的参数:DriverObject,保存到全局变量:gFileSpyDriverObject

//

gFileSpyDriverObject = DriverObject;

 

//

// 初始化一个Lookaside的内存池。

//

ExInitializePagedLookasideList( &gFileSpyNameBufferLookasideList,
                                    NULL,
                                    NULL,
                                    0,
                                    FILESPY_LOOKASIDE_SIZE,
                                    FILESPY_NAME_BUFFER_TAG,
                                    0 );

 

 

#if DBG && WINVER >= 0x0501

//

// 判断操作系统版本,设置卸载例程。

//

    if (IS_WINDOWSXP_OR_LATER()) {

        ASSERT( NULL != gSpyDynamicFunctions.EnumerateDeviceObjectList );

        gFileSpyDriverObject->DriverUnload = DriverUnload;
    }
#endif

//

// 初始化名称,并调用IoCreateDevice创建设备。

// 这里的#define                  FILESPY_FULLDEVICE_NAME1                L"\\FileSystem\\Filters\\FileSpy"

// 因为是CDO,所以不需要设备拓展。

//

RtlInitUnicodeString( &nameString, FILESPY_FULLDEVICE_NAME1 );

status = IoCreateDevice( DriverObject,
                             0,                 //  has no device extension
                             &nameString,
                             FILE_DEVICE_DISK_FILE_SYSTEM,
                             FILE_DEVICE_SECURE_OPEN,
                             FALSE,
                             &gControlDeviceObject);

    if (STATUS_OBJECT_PATH_NOT_FOUND == status) {

        //

        // 如果第一次创建失败,错误代码为:STATUS_OBJECT_PATH_NOT_FOUND,说明不存在这个路径。再次创建,路径为:

        // #define           FILESPY_FULLDEVICE_NAME2        L"\\FileSystem\\FileSpyCDO"

        // 因为这是一个我们自己使用的CDO,所以不需要设备拓展。该设备,主要用来与我们自己的应用层通信使用 和

        // 修改整个驱动的内部配置的。

        //

        RtlInitUnicodeString( &nameString, FILESPY_FULLDEVICE_NAME2 );

        status = IoCreateDevice( DriverObject,
                                 0,             //  has no device extension
                                 &nameString,
                                 FILE_DEVICE_DISK_FILE_SYSTEM,
                                 FILE_DEVICE_SECURE_OPEN,
                                 FALSE,
                                 &gControlDeviceObject);

        if (!NT_SUCCESS( status )) {

            SPY_LOG_PRINT( SPYDEBUG_ERROR,
                           ("FileSpy!DriverEntry: Error creating FileSpy control device \"%wZ\", error: %x\n",
                           &nameString,
                           status) );

            return status;
        }

    } else if (!NT_SUCCESS( status )) {

        //

       // 调用失败,直接返回。

       //

        SPY_LOG_PRINT( SPYDEBUG_ERROR,
                       ("FileSpy!DriverEntry: Error creating FileSpy control device \"%wZ\", error: %x\n",
                       &nameString,
                       status) );

        return status;

    }

//

// 创建符号链接,如果失败,删除符号链接,再创建一次,如果再次失败,删除设备,返回。

//

RtlInitUnicodeString( &linkString, FILESPY_DOSDEVICE_NAME );
    status = IoCreateSymbolicLink( &linkString, &nameString );

    if (!NT_SUCCESS(status)) {

        //
        //  Remove the existing symbol link and try and create it again.
        //  If this fails then quit.
        //

        IoDeleteSymbolicLink( &linkString );
        status = IoCreateSymbolicLink( &linkString, &nameString );

        if (!NT_SUCCESS(status)) {

            SPY_LOG_PRINT( SPYDEBUG_ERROR,
                       ("FileSpy!DriverEntry: IoCreateSymbolicLink failed\n") );

            IoDeleteDevice(gControlDeviceObject);
            return status;
        }
    }

//

// 初始化派遣例程,这里只设置IRP_MJ_CREATE、IRP_MJ_CLOSE、IRP_MJ_FILE_SYSTEM_CONTROL。

// IRP_MJ_FILE_SYSTEM_CONTROL,是文件系统控制设备对象(CDO),在一个新的存储介质被系统发现并在文件系统中生成一个卷的

// 这个过程开始时,收到的一个IRP,这个时候的次功能号为IRP_MN_MOUNT。只要过滤驱动生成了一个设备,并且绑定了文件系统的控制

// 设备对象(CDO),过滤驱动就一定能得到这样一个IRP。

//

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

        DriverObject->MajorFunction[i] = SpyDispatch;
    }

    DriverObject->MajorFunction[IRP_MJ_CREATE] = SpyCreate;
    DriverObject->MajorFunction[IRP_MJ_CLOSE] = SpyClose;
    DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = SpyFsControl;

//

// 设置FAST I/O的派遣例程。每个驱动对象都有FAST I/O派遣例程,只是多数设备驱动是不调用这写快速I/O分发函数的。但是文件系统必须

// 要设置,如果不设置上层依然会调用FAST I/O这些例程,而且会导致蓝屏。它是独立于普通IRP的另外的接口。

// 最简单的FAST I/O分发函数的写法是:直接返回FALSE就可以了。

//

// FLAST I/O 的例程空间需要自己开辟。该空间的释放,在DriverUnload里面。

//

fastIoDispatch = ExAllocatePoolWithTag( NonPagedPool,
                                            sizeof( FAST_IO_DISPATCH ),
                                            FILESPY_POOL_TAG );

    if (!fastIoDispatch) {

        IoDeleteDevice( gControlDeviceObject );
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    RtlZeroMemory( fastIoDispatch, sizeof( FAST_IO_DISPATCH ) );
    fastIoDispatch->SizeOfFastIoDispatch = sizeof( FAST_IO_DISPATCH );
    fastIoDispatch->FastIoCheckIfPossible = SpyFastIoCheckIfPossible;
    fastIoDispatch->FastIoRead = SpyFastIoRead;
    fastIoDispatch->FastIoWrite = SpyFastIoWrite;
    fastIoDispatch->FastIoQueryBasicInfo = SpyFastIoQueryBasicInfo;
    fastIoDispatch->FastIoQueryStandardInfo = SpyFastIoQueryStandardInfo;
    fastIoDispatch->FastIoLock = SpyFastIoLock;
    fastIoDispatch->FastIoUnlockSingle = SpyFastIoUnlockSingle;
    fastIoDispatch->FastIoUnlockAll = SpyFastIoUnlockAll;
    fastIoDispatch->FastIoUnlockAllByKey = SpyFastIoUnlockAllByKey;
    fastIoDispatch->FastIoDeviceControl = SpyFastIoDeviceControl;
    fastIoDispatch->FastIoDetachDevice = SpyFastIoDetachDevice;
    fastIoDispatch->FastIoQueryNetworkOpenInfo = SpyFastIoQueryNetworkOpenInfo;
    fastIoDispatch->MdlRead = SpyFastIoMdlRead;
    fastIoDispatch->MdlReadComplete = SpyFastIoMdlReadComplete;
    fastIoDispatch->PrepareMdlWrite = SpyFastIoPrepareMdlWrite;
    fastIoDispatch->MdlWriteComplete = SpyFastIoMdlWriteComplete;
    fastIoDispatch->FastIoReadCompressed = SpyFastIoReadCompressed;
    fastIoDispatch->FastIoWriteCompressed = SpyFastIoWriteCompressed;
    fastIoDispatch->MdlReadCompleteCompressed = SpyFastIoMdlReadCompleteCompressed;
    fastIoDispatch->MdlWriteCompleteCompressed = SpyFastIoMdlWriteCompleteCompressed;
    fastIoDispatch->FastIoQueryOpen = SpyFastIoQueryOpen;

    DriverObject->FastIoDispatch = fastIoDispatch;

//

// 设置通知回调。FsRtlRegisterFileSystemFilterCallbacks函数注册需通知回调函数,这些回调函数将在文件系统的相关操作之前被调用

//

#if WINVER >= 0x0501

    {
        FS_FILTER_CALLBACKS fsFilterCallbacks;

        if (IS_WINDOWSXP_OR_LATER()) {

            ASSERT( NULL != gSpyDynamicFunctions.RegisterFileSystemFilterCallbacks );

            //
            //  This version of the OS exports
            //  FsRtlRegisterFileSystemFilterCallbacks, therefore it must
            //  support the FsFilter callbacks interface.  We will register to
            //  receive callbacks for these operations.
            //

            //
            //  Setup the callbacks for the operations we receive through
            //  the FsFilter interface.
            //

            fsFilterCallbacks.SizeOfFsFilterCallbacks = sizeof( FS_FILTER_CALLBACKS );
            fsFilterCallbacks.PreAcquireForSectionSynchronization = SpyPreFsFilterOperation;
            fsFilterCallbacks.PostAcquireForSectionSynchronization = SpyPostFsFilterOperation;
            fsFilterCallbacks.PreReleaseForSectionSynchronization = SpyPreFsFilterOperation;
            fsFilterCallbacks.PostReleaseForSectionSynchronization = SpyPostFsFilterOperation;
            fsFilterCallbacks.PreAcquireForCcFlush = SpyPreFsFilterOperation;
            fsFilterCallbacks.PostAcquireForCcFlush = SpyPostFsFilterOperation;
            fsFilterCallbacks.PreReleaseForCcFlush = SpyPreFsFilterOperation;
            fsFilterCallbacks.PostReleaseForCcFlush = SpyPostFsFilterOperation;
            fsFilterCallbacks.PreAcquireForModifiedPageWriter = SpyPreFsFilterOperation;
            fsFilterCallbacks.PostAcquireForModifiedPageWriter = SpyPostFsFilterOperation;
            fsFilterCallbacks.PreReleaseForModifiedPageWriter = SpyPreFsFilterOperation;
            fsFilterCallbacks.PostReleaseForModifiedPageWriter = SpyPostFsFilterOperation;

            status = (gSpyDynamicFunctions.RegisterFileSystemFilterCallbacks)( DriverObject,
                                                                              &fsFilterCallbacks );

            if (!NT_SUCCESS( status )) {

                DriverObject->FastIoDispatch = NULL;
                ExFreePoolWithTag( fastIoDispatch, FILESPY_POOL_TAG );
                IoDeleteDevice( gControlDeviceObject );
                return status;
            }
        }
    }
#endif

//

// 初始化全局变量。链表,锁等

//

 ExInitializeFastMutex( &gSpyDeviceExtensionListLock );
    InitializeListHead( &gSpyDeviceExtensionList );

    KeInitializeSpinLock( &gControlDeviceStateLock );

    InitializeListHead( &gOutputBufferList );

    KeInitializeSpinLock( &gOutputBufferLock );
    KeInitializeSpinLock( &gLogSequenceLock );

    ExInitializeFastMutex( &gSpyAttachLock );

#ifndef MEMORY_DBG

    //
    //  When we aren't debugging our memory usage, we want to allocate
    //  memory from a look-aside list for better performance.  Unfortunately,
    //  we cannot benefit from the memory debugging help of the Driver
    //  Verifier if we allocate memory from a look-aside list.
    //

    ExInitializeNPagedLookasideList( &gFreeBufferList,
                                     NULL/*ExAllocatePoolWithTag*/,
                                     NULL/*ExFreePool*/,
                                     0,
                                     RECORD_SIZE,
                                     FILESPY_LOGRECORD_TAG,
                                     100 );
#endif

//

// 初始化名称环境。SpyInitNamingEnvironment位于:fspyHash.c中。初始化:gHashTable和gHashLockTable这2个全局变量。

// 初始化内部字符串,存于全局变量:gVolumeString、gOverrunString、gPagingIoString

//

SpyInitNamingEnvironment();

RtlInitUnicodeString(&gVolumeString, L"VOLUME");
RtlInitUnicodeString(&gOverrunString, L"......");
RtlInitUnicodeString(&gPagingIoString, L"Paging IO");

//

// IoRegisterFsRegistrationChange 注册文件系统变动回调。当系统中有任何文件系统被激活或被注销时,注册过的回调函数就会被调用。

//

// 注:这里的文件系统激活和卷的挂载是2回事。文件系统,比如NTFS、FAT32等,如果系统中一个NTFS的磁盘卷都没有采用这种文件

// 系统,那么这时的操作系统时没有加载NTFS文件系统的驱动,换言之,NTFS处于未激活状态。当任何一个卷采用了NTFS这种文件

// 系统,则NTFS被加载了,此时就叫NTFS被激活,以后再有卷采用NTFS文件系统挂载时,都不能说是文件系统的激活。

//

// 2K SP4和XP及以后的OS,会枚举所有已经存在的文件系统(除了RAM文件系统)。而2K SP4以前的,不会枚举已经在过滤驱动加载之前

// 就已经挂载上了的文件系统。

//

if (gFileSpyAttachMode == FILESPY_ATTACH_ALL_VOLUMES) {

        status = IoRegisterFsRegistrationChange( DriverObject,  SpyFsNotification );

        if (!NT_SUCCESS( status )) {

            SPY_LOG_PRINT( SPYDEBUG_ERROR,
                           ("FileSpy!DriverEntry: Error registering FS change notification, status=%08x\n",
                            status) );

            DriverObject->FastIoDispatch = NULL;
            ExFreePoolWithTag( fastIoDispatch, FILESPY_POOL_TAG );
            IoDeleteDevice( gControlDeviceObject );
            return status;
        }
    }

 

#if WINVER >= 0x0600

//

// 根据filespy创建资源管理器。SpyCreateKtmResourceManager位于:fspyTx.c中

//

status = SpyCreateKtmResourceManager();

if (!NT_SUCCESS( status )) {

        SPY_LOG_PRINT( SPYDEBUG_ERROR,
                       ("FileSpy!DriverEntry: Error creating Ktm resource manager, status=%08x\n",
                        status) );

        return status;
    }

//

// 下面就比较简单了,就不提了。

//

    //
    //  Initialize the lookaside list for the transaction context data.
    //  We will create a transaction context for each enlistment we create.
    //  The context data will be freed when the KTM callback routine
    //  receives appropriate notifications.
    //

    ExInitializeNPagedLookasideList( &gTransactionList,
                                     NULL,
                                     NULL,
                                     0,
                                     sizeof( FILESPY_TRANSACTION_CONTEXT ),
                                     FILESPY_TRANSACTION_TAG,
                                     0 );

#endif


    //
    //  Clear the initializing flag on the control device object since we
    //  have now successfully initialized everything.
    //

    ClearFlag( gControlDeviceObject->Flags, DO_DEVICE_INITIALIZING );

    return STATUS_SUCCESS;

 

 

}

这篇关于读源码笔记--文件过滤驱动FileSpy第1篇 -- DriverEntry的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1145398

相关文章

深入探索协同过滤:从原理到推荐模块案例

文章目录 前言一、协同过滤1. 基于用户的协同过滤(UserCF)2. 基于物品的协同过滤(ItemCF)3. 相似度计算方法 二、相似度计算方法1. 欧氏距离2. 皮尔逊相关系数3. 杰卡德相似系数4. 余弦相似度 三、推荐模块案例1.基于文章的协同过滤推荐功能2.基于用户的协同过滤推荐功能 前言     在信息过载的时代,推荐系统成为连接用户与内容的桥梁。本文聚焦于

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学

pandas数据过滤

Pandas 数据过滤方法 Pandas 提供了多种方法来过滤数据,可以根据不同的条件进行筛选。以下是一些常见的 Pandas 数据过滤方法,结合实例进行讲解,希望能帮你快速理解。 1. 基于条件筛选行 可以使用布尔索引来根据条件过滤行。 import pandas as pd# 创建示例数据data = {'Name': ['Alice', 'Bob', 'Charlie', 'Dav

Java ArrayList扩容机制 (源码解读)

结论:初始长度为10,若所需长度小于1.5倍原长度,则按照1.5倍扩容。若不够用则按照所需长度扩容。 一. 明确类内部重要变量含义         1:数组默认长度         2:这是一个共享的空数组实例,用于明确创建长度为0时的ArrayList ,比如通过 new ArrayList<>(0),ArrayList 内部的数组 elementData 会指向这个 EMPTY_EL

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

如何在Visual Studio中调试.NET源码

今天偶然在看别人代码时,发现在他的代码里使用了Any判断List<T>是否为空。 我一般的做法是先判断是否为null,再判断Count。 看了一下Count的源码如下: 1 [__DynamicallyInvokable]2 public int Count3 {4 [__DynamicallyInvokable]5 get

Linux_kernel驱动开发11

一、改回nfs方式挂载根文件系统         在产品将要上线之前,需要制作不同类型格式的根文件系统         在产品研发阶段,我们还是需要使用nfs的方式挂载根文件系统         优点:可以直接在上位机中修改文件系统内容,延长EMMC的寿命         【1】重启上位机nfs服务         sudo service nfs-kernel-server resta

工厂ERP管理系统实现源码(JAVA)

工厂进销存管理系统是一个集采购管理、仓库管理、生产管理和销售管理于一体的综合解决方案。该系统旨在帮助企业优化流程、提高效率、降低成本,并实时掌握各环节的运营状况。 在采购管理方面,系统能够处理采购订单、供应商管理和采购入库等流程,确保采购过程的透明和高效。仓库管理方面,实现库存的精准管理,包括入库、出库、盘点等操作,确保库存数据的准确性和实时性。 生产管理模块则涵盖了生产计划制定、物料需求计划、

论文阅读笔记: Segment Anything

文章目录 Segment Anything摘要引言任务模型数据引擎数据集负责任的人工智能 Segment Anything Model图像编码器提示编码器mask解码器解决歧义损失和训练 Segment Anything 论文地址: https://arxiv.org/abs/2304.02643 代码地址:https://github.com/facebookresear