how to get file name safetly and compare it in windows minifilter driver

1.7k Views Asked by At

Hello i'm new at filterdriver writing so i'm apologizing for my basic question , i try to get the file name from a pre read function and check if it's equal to my file name and do some logic according to this info.

this is my function:

 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*/
 }

my problem is i getting a blue screen when i try to check if the file name is equal to my wanted file name. why the driver get here a blue screen?

Thank you pit

edit:

i updated my code to this:

 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;
}

and again i got a blue screen , this is the analized core dump:

    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
    ---------

so the crush is indead in the RtlCompareUnicodeString function (or in prefix version before) but i have no idea why it's crush there, it's look like i did every thing o.k.

2

There are 2 best solutions below

8
On

your bug not in call RtlPrefixUnicodeString( &FILE_NAME, &NameInfo->Name, TRUE )) - here all ok. your bug in previous line:

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

the %wZ format require pointer to UNICODE_STRING - so must be

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

also if FltGetFileNameInformation fail - you must not use NameInfo after that (it will be 0 or undefined). but you not do this in code

and usually swap buffers need do when and only when Data->Iopb->IrpFlags & IRP_NOCACHE - so when data readed or writed to storage

0
On

There are a lot of mistakes here.

  1. First of all don't print things that could be NULL, check them first. Go through the FLT_FILE_NAME_INFORMATION structure and make sure all the data you want to print is actually there.

  2. Fix your symbols in the debugger. Make sure your debugger has the symbol path set to the folder where your .pdb is.

  3. Don't query the name in PreRead. There are several reasons not to do this, but I will tell you what you should do:

    1. In Post IRP_MJ_CREATE query the name of the file that has been opened. Check if it is the file you are interested in. If no, just return flt postop finished processing otherwise, if it is a file you are interested in create a context for it and store the FileNameInformation there as well while you're at it.
    1. Now in PreRead, when you are called simply ask for the context of the file object. If one is present, that means it is a file you are interested in so then you do your processing, otherwise you simply skip the read.
  4. Be aware of string processing routines and IRQL. Don't use static stack strings for comparison like L"my_file.txt"

Also please show how your variable EXTENSION is initialized.