如何在windows minifilter驱动程序中安全地获取文件名并进行比较

如何在windows minifilter驱动程序中安全地获取文件名并进行比较,windows,driver,minifilter,filter-driver,Windows,Driver,Minifilter,Filter Driver,您好,我是filterdriver写作新手,所以我为我的基本问题道歉,我尝试从预读函数获取文件名,检查它是否等于我的文件名,并根据此信息执行一些逻辑 这是我的职责: FLT_PREOP_CALLBACK_STATUS SwapPreReadBuffers( _Inout_ PFLT_CALLBACK_DATA Data, _In_ PCFLT_RELATED_OBJECTS FltObjects, _Flt_CompletionContext_Outptr_ PVOID *C

您好,我是filterdriver写作新手,所以我为我的基本问题道歉,我尝试从预读函数获取文件名,检查它是否等于我的文件名,并根据此信息执行一些逻辑

这是我的职责:

 FLT_PREOP_CALLBACK_STATUS SwapPreReadBuffers(    _Inout_ PFLT_CALLBACK_DATA Data,    _In_ PCFLT_RELATED_OBJECTS FltObjects,    _Flt_CompletionContext_Outptr_ PVOID *CompletionContext   )
{
    PFLT_IO_PARAMETER_BLOCK iopb = Data->Iopb;
    FLT_PREOP_CALLBACK_STATUS retValue = FLT_PREOP_SUCCESS_NO_CALLBACK;
    PVOID newBuf = NULL;
    PMDL newMdl = NULL;
    PVOLUME_CONTEXT volCtx = NULL;
    PPRE_2_POST_CONTEXT p2pCtx;
    NTSTATUS status;
    ULONG readLen = iopb->Parameters.Read.Length;
    PFLT_FILE_NAME_INFORMATION NameInfo = NULL;
    UNICODE_STRING FILE_NAME;

 //
 //  Skip IRP_PAGING_IO, IRP_SYNCHRONOUS_PAGING_IO and
 //  TopLevelIrp.
 //

    if ((Data->Iopb->IrpFlags & IRP_PAGING_IO) ||     (Data->Iopb->IrpFlags & IRP_SYNCHRONOUS_PAGING_IO) ||      IoGetTopLevelIrp())
    {
         return FLT_PREOP_SUCCESS_NO_CALLBACK;
    }

    RtlInitUnicodeString( & FILE_NAME, L"my_file.txt" );

    status = FltGetFileNameInformation( Data,  FLT_FILE_NAME_NORMALIZED | 
    FLT_FILE_NAME_QUERY_DEFAULT, &NameInfo );
    if (!NT_SUCCESS( status )) 
    {
         DbgPrint("[-] SwapPreReadBuffers we couldn't extract %wZ info\n",  Data->Iopb->TargetFileObject->FileName);
    }


     status = FltParseFileNameInformation( NameInfo );
    if (!NT_SUCCESS( status )) 
     {
        DbgPrint("[-] SwapPreReadBuffers we couldn't pars %wZ info\n",  Data->Iopb->TargetFileObject->FileName);            
     }


     DbgPrint("[+] pars gets me Name: %wZ extention:  %wZ  perentDir: %wZ volume: %wZ \n",  NameInfo->Name, NameInfo->Extension, NameInfo->ParentDir, NameInfo->Volume);


    if (RtlPrefixUnicodeString( &FILE_NAME, &NameInfo->Name, TRUE ))        /* here i'm getting the blue screen*/
     {
         DbgPrint("[***] SwapPreReadBuffers we are at calles thats related to our file %wZ \n",  Data->Iopb->TargetFileObject->FileName);                
     }
    /* continue of the code*/
 }
我的问题是,当我试图检查文件名是否等于我想要的文件名时,会出现蓝屏。 为什么司机会在这里看到蓝屏

多谢各位 坑

编辑:

我将代码更新为:

 FLT_PREOP_CALLBACK_STATUS SwapPreReadBuffers(    _Inout_ PFLT_CALLBACK_DATA Data,    _In_ PCFLT_RELATED_OBJECTS FltObjects,    _Flt_CompletionContext_Outptr_ PVOID *CompletionContext   )
{
    PFLT_IO_PARAMETER_BLOCK iopb = Data->Iopb;
    FLT_PREOP_CALLBACK_STATUS retValue = FLT_PREOP_SUCCESS_NO_CALLBACK;
    PVOID newBuf = NULL;
    PMDL newMdl = NULL;
    PVOLUME_CONTEXT volCtx = NULL;
    NTSTATUS CbStatus = FLT_PREOP_SUCCESS_NO_CALLBACK;
    PPRE_2_POST_CONTEXT p2pCtx;
    NTSTATUS status;
    ULONG readLen = iopb->Parameters.Read.Length;
    PFLT_FILE_NAME_INFORMATION NameInfo = NULL;
    UNICODE_STRING FILE_NAME;

 //
 //  Skip IRP_PAGING_IO, IRP_SYNCHRONOUS_PAGING_IO and
 //  TopLevelIrp.
 //

     if ((Data->Iopb->IrpFlags & IRP_PAGING_IO) ||
    (Data->Iopb->IrpFlags & IRP_SYNCHRONOUS_PAGING_IO) ||
    IoGetTopLevelIrp()) {

    DbgPrint("[-] SwapPreReadBuffers we out , this call not for us\n");
    return FLT_PREOP_SUCCESS_NO_CALLBACK;
}


status = FltGetFileNameInformation( Data,
                                    FLT_FILE_NAME_NORMALIZED
                                      | FLT_FILE_NAME_QUERY_DEFAULT,
                                    &NameInfo );
if (!NT_SUCCESS( status )) 
{
    DbgPrint("[-] SwapPreReadBuffers we couldn't extract info\n");
     goto PreReadCleanup;
}

status = FltParseFileNameInformation( NameInfo );
if (!NT_SUCCESS( status )) 
{
    DbgPrint("[-] SwapPreReadBuffers we couldn't pars info\n");
     goto PreReadCleanup;
}


if (NULL == NameInfo)
{
    DbgPrint("[---] name info is actally 0\n");
}
else
{
    DbgPrint("[*] address of name is %x:%x and address of extansion is %x:%x  -> buffers are: name %x  , extension: %x \nsize of info %d size of extension %d\n",NameInfo->Extension , &NameInfo->Extension, EXTENTION, &EXTENTION, NameInfo->Extension.Buffer , EXTENTION.Buffer ,NameInfo->Extension.Length , EXTENTION.Length);
}

if ((0 == RtlCompareUnicodeString( &EXTENTION, &NameInfo->Extension, TRUE ))) { 
    DbgPrint("[***] SwapPreReadBuffers we are at calles thats related to our file %wZ \n",  &Data->Iopb->TargetFileObject->FileName);  
    DbgPrint("[+] pass parse\n"); 
    DbgPrint("[+] pars gets me Name: %wZ\n extention:  %wZ\n  perentDir: %wZ\n volume: %wZ\n",  &NameInfo->Name, &NameInfo->Extension, &NameInfo->ParentDir, &NameInfo->Volume);
}
else{

    DbgPrint("[*] we pass compration check\n");
      goto PreReadCleanup;
}
 //
 //  Clean up
 //
 PreReadCleanup:
    if (NameInfo) {

        FltReleaseFileNameInformation( NameInfo );
    }
    return retValue;
}
我又看到了一个蓝屏,这是经过分析的堆芯转储:

    kd>  !analyze -v
    *******************************************************************************
    *                                                                             *
    *                        Bugcheck Analysis                                    *
    *                                                                             *
    *******************************************************************************

    PAGE_FAULT_IN_NONPAGED_AREA (50)
    Invalid system memory was referenced.  This cannot be protected by try-except,
    it must be protected by a Probe.  Typically the address is just plain bad or it
    is pointing at freed memory.
    Arguments:
    Arg1: 994af2a4, memory referenced.
    Arg2: 00000000, value 0 = read operation, 1 = write operation.
    Arg3: 82a72a17, If non-zero, the instruction address which referenced the bad memory
        address.
    Arg4: 00000000, (reserved)

    Debugging Details:
    ------------------


    READ_ADDRESS: GetPointerFromAddress: unable to read from 829a5718
    Unable to read MiSystemVaType memory at 829851a0
     994af2a4 

    FAULTING_IP: 
    nt!RtlCompareUnicodeStrings+3c
    82a72a17 0fb706          movzx   eax,word ptr [esi]

    MM_INTERNAL_CODE:  0

    CUSTOMER_CRASH_COUNT:  1

    DEFAULT_BUCKET_ID:  WIN7_DRIVER_FAULT

    BUGCHECK_STR:  0x50

    PROCESS_NAME:  cmd.exe

    CURRENT_IRQL:  0

    TRAP_FRAME:  a72b7974 -- (.trap 0xffffffffa72b7974)
    ErrCode = 00000000
    eax=00000003 ebx=994af2aa ecx=8da2064c edx=000000bf esi=994af2a4 edi=137f5b5e
    eip=82a72a17 esp=a72b79e8 ebp=a72b79f4 iopl=0         nv up ei pl nz ac po nc
    cs=0008  ss=0010  ds=0023  es=0023  fs=0030  gs=0000             efl=00010212
    nt!RtlCompareUnicodeStrings+0x3c:
    82a72a17 0fb706          movzx   eax,word ptr [esi]       ds:0023:994af2a4=????
    Resetting default scope

    LAST_CONTROL_TRANSFER:  from 8287c3d8 to 828c941b

    STACK_TEXT:  
    a72b795c 8287c3d8 00000000 994af2a4 00000000 nt!MmAccessFault+0x106
    a72b795c 82a72a17 00000000 994af2a4 00000000 nt!KiTrap0E+0xdc
    a72b79f4 82a72b0f 994af2aa 00000003 acca4e02 nt!RtlCompareUnicodeStrings+0x3c
    a72b7a10 994a9105 994ad090 acca4d6c 00000001 nt!RtlCompareUnicodeString+0x25
    WARNING: Stack unwind information not available. Following frames may be wrong.
    a72b7a6c 8b756aeb 87587068 a72b7a8c a72b7ab8 MyDriver2+0x1105
    a72b7ad8 8b7599f0 a72b7b2c 87435e48 00000000 fltmgr!FltpPerformPreCallbacks+0x34d
    a72b7af0 8b759f01 a72b7b2c 00000000 862ff240 fltmgr!FltpPassThroughInternal+0x40
    a72b7b14 8b75a3ba 032b7b00 862ff240 00000000 fltmgr!FltpPassThrough+0x203
    a72b7b44 82872593 862ff240 87435e48 87435e48 fltmgr!FltpDispatch+0xb4
    a72b7b5c 82a6699f 87435e48 87435fd8 87590d98 nt!IofCallDriver+0x63
    a72b7b7c 82a9f2da 862ff240 87590d98 00000001 nt!IopSynchronousServiceTail+0x1f8
    a72b7c08 828791ea 862ff240 87435e48 00000000 nt!NtReadFile+0x644
    a72b7c08 773e70b4 862ff240 87435e48 00000000 nt!KiFastCallEntry+0x12a
    0013f014 00000000 00000000 00000000 00000000 0x773e70b4


    STACK_COMMAND:  kb

    FOLLOWUP_IP: 
    MyDriver2+1105
    994a9105 ??              ???

    SYMBOL_STACK_INDEX:  4

    SYMBOL_NAME:  MyDriver2+1105

    FOLLOWUP_NAME:  MachineOwner

    MODULE_NAME: MyDriver2

    IMAGE_NAME:  MyDriver2.sys

    DEBUG_FLR_IMAGE_TIMESTAMP:  597b0358

    FAILURE_BUCKET_ID:  0x50_MyDriver2+1105

    BUCKET_ID:  0x50_MyDriver2+1105

    Followup: MachineOwner
    ---------

因此,crush在RtlCompareUnicodeString函数中是独立的(或者在以前的前缀版本中),但我不知道为什么会在那里出现crush,看起来我做的每件事都很好。

你的bug不在调用中
rtlprefexonicodestring(&FILE\u NAME,&NameInfo->NAME,TRUE))
-这里一切正常。上一行中的错误:

DbgPrint("[+] pars gets me Name: %wZ extention:  %wZ  perentDir: %wZ volume: %wZ \n",  
NameInfo->Name, 
NameInfo->Extension, 
NameInfo->ParentDir, 
NameInfo->Volume);
%wZ
格式需要指向
UNICODE\u字符串的指针,因此必须

DbgPrint("[+] pars gets me Name: %wZ extention:  %wZ  perentDir: %wZ volume: %wZ \n",  
&NameInfo->Name, 
&NameInfo->Extension, 
&NameInfo->ParentDir, 
&NameInfo->Volume);
此外,如果
FltGetFileNameInformation
失败,则在此之后不得使用
NameInfo
(它将为0或未定义)。但你不能在代码中这样做


通常交换缓冲区需要在且仅在
数据->Iopb->IrpFlags&IRP_NOCACHE
时进行-因此,当数据读写到存储器时,这里有很多错误

  • 首先,不要打印可能为空的内容,请先检查它们。 检查FLT文件名信息结构,确保所有要打印的数据都在那里

  • 在调试器中修复符号。确保调试器将符号路径设置为.pdb所在的文件夹

  • 不要在PreRead中查询名称。有几个理由不这样做,但我将告诉您应该做什么:

  • 在PostIRP\U MJ\U CREATE中,查询已打开的文件的名称。检查是否是您感兴趣的文件。如果没有,只需返回flt postop finished processing,否则,如果它是一个您感兴趣的文件,请为它创建一个上下文,并在处理时将filename信息存储在那里
  • 现在在PreRead中,调用时只需询问file对象的上下文即可。如果存在一个文件,这意味着它是您感兴趣的文件,那么您需要进行处理,否则您只需跳过读取
  • 注意字符串处理例程和IRQL。不要使用静态堆栈字符串进行比较,如L“my_file.txt”


  • 另外,请说明您的变量扩展名是如何初始化的。

    谢谢您,因为muchi更改了我的代码,但当RTLPRefexInocDestring出现时,我仍然会出现蓝屏(我在注释时没有看到蓝屏,所以我相信这是问题的根源)@pit-您需要分析崩溃转储以查看问题的确切来源<当您传递
    UNICODE\u字符串而不是
    UNICODE\u字符串*
    时,code>DbgPrint
    当然是错误的。在
    RtlPrefixUnicodeString(&FILE\u NAME,&NameInfo->NAME,TRUE)
    如果
    NameInfo!=0
    。但在这种情况下,您将在(我怎么说你需要正确处理
    FltGetFileNameInformation
    @pit失败-以及你所有
    DbgPrint
    中的
    %wZ
    都是错误的。你每次通过
    UNICODE\u STRING
    而不是
    UNICODE\u STRING*
    -
    数据->Iopb->TargetFileObject->FileName
    ,例如,我将DbgPrint修复为
    &nameinform->Name
    所以现在它们都是指针,我在每个
    !NT_SUCCESS(status)
    案例中都添加了return,当我只注释掉
    rtlprefixunocodestring(&FILE\u Name,&NameInfo->Name,TRUE)
    我很好,但是当有这个主持人时,我会看到一个蓝屏,所以我认为这与新代码版本中的no?有关:
    RtlCompareUnicodeString(&EXTENTION,&NameInfo->Extension,TRUE)
    -其中
    Extension
    被初始化,以及如何初始化?错误检查显示
    缓冲区
    0x994af2a4
    )无效。这可能是在
    扩展名
    (我猜)或
    &NameInfo>扩展名
    中。并且您的dbgprint(新版本)无论如何都是错误的
    扩展名
    是一个全局变量,它在驱动程序条目中初始化(初始化进行得很顺利,初始化后我在驱动程序条目中打印了Extension的值,以使舒尔知道它进行得很顺利。(我还尝试原样使用microsoft提供的cancelSafe迷你过滤器,但没有任何更改,而且它在同一个功能中也向我发送了命令,但出现了相同的错误(某些地址未验证))(cencel安全代码可以在这里找到)您的错误检查分析清楚地表明
    NameInfo->Extension
    Extension
    中的
    Buffer
    无效。或者。或者。如果您更深入地查找崩溃转储-这很容易准确查看。
    NameInfo->Extension
    由fltmgr初始化,我怀疑它是否无效(如果您按原样显示所有代码,并且未在未显示的代码中损坏代码).
    扩展在驱动程序条目中初始化
    -不是使用本地字符串?不是很晚才覆盖它?并在和dbgprint处修复-几乎所有错误。当您将
    UNICODE_字符串作为参数传递时,我从驱动程序条目中初始化它,如下所示`RtlInitUnicodeString(&EXTENTION,L“txt”)`