Windows System Software -- Consulting, Training, Development -- Unique Expertise, Guaranteed Results

Sept/Oct 2019 Issue of The NT Insider available


Download PDF here: http://insider.osr.com/2019/ntinsider_2019_01.pdf

It’s a particularly BIG issue, too: 40 pages of technical goodness, ranging from WDF to Minifilters. Check it out.
Before Posting...
Please check out the Community Guidelines in the Announcements and Administration Category.

minifilter caused BSOD in Win7 bug check with 0xF7

Alex_C3Alex_C3 Member Posts: 9

Hi,all.

I use the minifilter to intercept operation with file/folder.But BSOD always happened 1-2 days after I start it,I can't figure out why.Could someone help? Any words are appreciated.

The relative source code and the debug info catched by windbg is attached.

Microsoft (R) Windows Debugger Version 6.12.0002.633 X86
Copyright (c) Microsoft Corporation. All rights reserved.

0: kd> !analyze -v


  • *
  • Bugcheck Analysis *
  • *

DRIVER_OVERRAN_STACK_BUFFER (f7)
A driver has overrun a stack-based buffer. This overrun could potentially
allow a malicious user to gain control of this machine.
DESCRIPTION
A driver overran a stack-based buffer (or local variable) in a way that would
have overwritten the function's return address and jumped back to an arbitrary
address when the function returned. This is the classic "buffer overrun"
hacking attack and the system has been brought down to prevent a malicious user
from gaining complete control of it.
Do a kb to get a stack backtrace -- the last routine on the stack before the
buffer overrun handlers and bugcheck call is the one that overran its local
variable(s).
Arguments:
Arg1: 90d93ce4, Actual security check cookie from the stack
Arg2: d4eaac15, Expected security check cookie
Arg3: 2b1553ea, Complement of the expected security check cookie
Arg4: 00000000, zero

Debugging Details:

*** WARNING: Unable to verify timestamp for qutmdrv.sys
*** ERROR: Module load completed but symbols could not be loaded for qutmdrv.sys
*** WARNING: Unable to verify timestamp for TsQBDrv.sys
*** ERROR: Module load completed but symbols could not be loaded for TsQBDrv.sys
*** WARNING: Unable to verify timestamp for QQFrmMgr.sys
*** ERROR: Module load completed but symbols could not be loaded for QQFrmMgr.sys
*** WARNING: Unable to verify timestamp for Hookport.sys
*** ERROR: Module load completed but symbols could not be loaded for Hookport.sys

DEFAULT_BUCKET_ID: GS_FALSE_POSITIVE_MISSING_GSFRAME

SECURITY_COOKIE: Expected d4eaac15 found 90d93ce4

CUSTOMER_CRASH_COUNT: 1

BUGCHECK_STR: 0xF7

PROCESS_NAME: svchost.exe

CURRENT_IRQL: 0

LAST_CONTROL_TRANSFER: from 9bdf5825 to 8432ecc4

STACK_TEXT:
c48a7398 9bdf5825 000000f7 90d93ce4 d4eaac15 nt!KeBugCheckEx+0x1e
WARNING: Stack unwind information not available. Following frames may be wrong.
c48a73b8 9bdf50b7 00000000 87480000 00000800 folderprotect+0x2825
c48a75a8 85771aeb 9f25a148 c48a75c8 c48a75f4 folderprotect+0x20b7
c48a7614 857749f0 c48a7658 87e4f2b8 00000000 FLTMGR!FltpPerformPreCallbacks+0x34d
c48a762c 857881fe c48a7658 8578bf3c 00000000 FLTMGR!FltpPassThroughInternal+0x40
c48a7640 857888b7 c48a7658 87e4f4fc 00000000 FLTMGR!FltpCreateInternal+0x24
c48a7684 84285f87 8a746230 8a7b5318 87e4f2b8 FLTMGR!FltpCreate+0x2c9
c48a769c 95172cd0 00000000 8abf8698 c585f848 nt!IofCallDriver+0x63
c48a7730 84285f87 8abf8698 87e4f2b8 87e4f2b8 qutmdrv+0x12cd0
c48a7748 8577520c 87e4f2b8 00000000 87e4f520 nt!IofCallDriver+0x63
c48a776c 857888c9 c48a778c 9f331768 00000000 FLTMGR!FltpLegacyProcessingAfterPreCallbacksCompleted+0x2aa
c48a77b8 84285f87 9f331768 9f3395b8 a08ac2c4 FLTMGR!FltpCreate+0x2db
c48a77d0 8449fdab e87780bb 87a80328 8af4fd20 nt!IofCallDriver+0x63
c48a78b0 844db58a 9f331768 85537900 8781ca18 nt!IopParseDevice+0xf08
c48a78f0 8447eff8 87a80328 87537900 8781ca18 nt!IopParseFile+0x51
c48a796c 8448f674 0000019c c48a79c0 00000040 nt!ObpLookupObjectName+0x510
c48a79cc 94a6714d 00ecf320 87537900 00ecf301 nt!ObOpenObjectByName+0x165
c48a7a48 84485f6b 00ecf320 87537900 00ecf301 TsQBDrv+0xc14d
c48a7ac4 8448c2f4 00ecf348 00100080 00ecf320 nt!IopCreateFile+0x6c3
c48a7b0c 94d52310 00ecf348 00100080 00ecf320 nt!NtOpenFile+0x2a
c48a7b4c 8d531e6c 00ecf348 00100080 00ecf320 QQFrmMgr+0x6310
c48a7c14 8428ca6a 00ecf348 00100080 00ecf320 Hookport+0xe6c
c48a7c14 77936c04 00ecf348 00100080 00ecf320 nt!KiSystemServicePostCall
00ecf34c 00000000 00000000 00000000 00000000 0x77936c04

STACK_COMMAND: kb

FOLLOWUP_IP:
folderprotect+2825
9bdf5825 ?? ???

SYMBOL_STACK_INDEX: 1

SYMBOL_NAME: folderprotect+2825

FOLLOWUP_NAME: MachineOwner

MODULE_NAME: folderprotect

IMAGE_NAME: folderprotect.sys

DEBUG_FLR_IMAGE_TIMESTAMP: 5d6cc8a4

FAILURE_BUCKET_ID: 0xF7_MISSING_GSFRAME_folderprotect+2825

BUCKET_ID: 0xF7_MISSING_GSFRAME_folderprotect+2825

Followup: MachineOwner

0: kd> kb
ChildEBP RetAddr Args to Child
c48a7398 9bdf5825 000000f7 90d93ce4 d4eaac15 nt!KeBugCheckEx+0x1e
WARNING: Stack unwind information not available. Following frames may be wrong.
c48a73b8 9bdf50b7 00000000 87480000 00000800 folderprotect+0x2825
c48a75a8 85771aeb 9f25a148 c48a75c8 c48a75f4 folderprotect+0x20b7
c48a7614 857749f0 c48a7658 87e4f2b8 00000000 FLTMGR!FltpPerformPreCallbacks+0x34d
c48a762c 857881fe c48a7658 8578bf3c 00000000 FLTMGR!FltpPassThroughInternal+0x40
c48a7640 857888b7 c48a7658 87e4f4fc 00000000 FLTMGR!FltpCreateInternal+0x24
c48a7684 84285f87 8a746230 8a7b5318 87e4f2b8 FLTMGR!FltpCreate+0x2c9
c48a769c 95172cd0 00000000 8abf8698 c585f848 nt!IofCallDriver+0x63
c48a7730 84285f87 8abf8698 87e4f2b8 87e4f2b8 qutmdrv+0x12cd0
c48a7748 8577520c 87e4f2b8 00000000 87e4f520 nt!IofCallDriver+0x63
c48a776c 857888c9 c48a778c 9f331768 00000000 FLTMGR!FltpLegacyProcessingAfterPreCallbacksCompleted+0x2aa
c48a77b8 84285f87 9f331768 9f3395b8 a08ac2c4 FLTMGR!FltpCreate+0x2db
c48a77d0 8449fdab e87780bb 87a80328 8af4fd20 nt!IofCallDriver+0x63
c48a78b0 844db58a 9f331768 85537900 8781ca18 nt!IopParseDevice+0xf08
c48a78f0 8447eff8 87a80328 87537900 8781ca18 nt!IopParseFile+0x51
c48a796c 8448f674 0000019c c48a79c0 00000040 nt!ObpLookupObjectName+0x510
c48a79cc 94a6714d 00ecf320 87537900 00ecf301 nt!ObOpenObjectByName+0x165
c48a7a48 84485f6b 00ecf320 87537900 00ecf301 TsQBDrv+0xc14d
c48a7ac4 8448c2f4 00ecf348 00100080 00ecf320 nt!IopCreateFile+0x6c3
c48a7b0c 94d52310 00ecf348 00100080 00ecf320 nt!NtOpenFile+0x2a
c48a7b4c 8d531e6c 00ecf348 00100080 00ecf320 QQFrmMgr+0x6310
c48a7c14 8428ca6a 00ecf348 00100080 00ecf320 Hookport+0xe6c
c48a7c14 77936c04 00ecf348 00100080 00ecf320 nt!KiSystemServicePostCall
00ecf34c 00000000 00000000 00000000 00000000 0x77936c04
0: kd> lmvm folderprotect
start end module name
9bdf3000 9bdfc000 folderprotect T (no symbols)
Loaded symbol image file: folderprotect.sys
Image path: folderprotect.sys
Image name: folderprotect.sys
Timestamp: Mon Sep 02 15:45:40 2019 (5D6CC8A4)
CheckSum: 0000F0CA
ImageSize: 00009000
Translations: 0000.04b0 0000.04e4 0409.04b0 0409.04e4

Comments

  • Alex_C3Alex_C3 Member Posts: 9

    relative source code,work on preoperation of IRP_MJ_CREATE:
    FLT_PREOP_CALLBACK_STATUS
    NPPreCreate(
    __inout PFLT_CALLBACK_DATA Data,
    __in PCFLT_RELATED_OBJECTS FltObjects,
    __deref_out_opt PVOID *CompletionContext
    )
    {
    NTSTATUS status;
    PFLT_FILE_NAME_INFORMATION nameInfo;
    UNREFERENCED_PARAMETER(FltObjects);
    UNREFERENCED_PARAMETER(CompletionContext);
    PAGED_CODE();
    __try
    {
    status = FltGetFileNameInformation(
    Data,
    FLT_FILE_NAME_NORMALIZED |
    FLT_FILE_NAME_QUERY_DEFAULT,
    &nameInfo
    );
    if (!NT_SUCCESS(status))
    {
    DbgPrint("folderprotect!Get file name fail");
    return FLT_PREOP_SUCCESS_WITH_CALLBACK;
    }
    char fileName[NAME_PATH_LENGTH] = "";
    FltParseFileNameInformation(nameInfo);
    if (!KStrUniToChar(&nameInfo->Name, fileName))
    {
    DbgPrint("folderprotect!Unicode string to char fail");
    FltReleaseFileNameInformation(nameInfo);
    return FLT_PREOP_SUCCESS_WITH_CALLBACK;
    }
    else
    {
    if (fileName == NULL)
    {
    DbgPrint("folderprotect!fileName is NULL");
    FltReleaseFileNameInformation(nameInfo);
    return FLT_PREOP_SUCCESS_WITH_CALLBACK;
    }
    }

        SHORT pos = 0;
        TIME_FIELDS time;
        UNICODE_STRING timeStr;
        UNICODE_STRING operStr;
        UNICODE_STRING totalStr;
        KStrInitUni(&timeStr, MAX_PATH_FOL, FOLDER_POOL_TAG);
        KStrInitUni(&operStr, MAX_PATH_FOL, FOLDER_POOL_TAG);
        KStrInitUni(&totalStr, MAX_PATH_FOL, FOLDER_POOL_TAG);
    
        for (int i = 0; i < pathCount; i++)
        {
            UNICODE_STRING indexStr;
            KStrInitUni(&indexStr, MAX_PATH_FOL, FOLDER_POOL_TAG);
            RtlUpcaseUnicodeString(&indexStr, &folprotect[i], FALSE);
            RtlAppendUnicodeToString(&indexStr, L"\\");
            if (RtlEqualUnicodeString(&folprotect[i], &nameInfo->Name, TRUE) ||
                KStrStartWith(&nameInfo->Name, &indexStr,TRUE, FOLDER_POOL_TAG))
            {
                if (Data->Iopb->MajorFunction == IRP_MJ_SET_INFORMATION)
                {
                    switch (Data->Iopb->Parameters.SetFileInformation.FileInformationClass)
                    {
                    case FileRenameInformation:
                    case FileDispositionInformation:
                    case FileRenameInformationBypassAccessCheck:
                    case FileShortNameInformation:
                        break;
                    default:
                        KStrFreeUni(&indexStr, FOLDER_POOL_TAG);
                        KStrFreeUni(&timeStr, FOLDER_POOL_TAG);
                        KStrFreeUni(&operStr, FOLDER_POOL_TAG);
                        KStrFreeUni(&totalStr, FOLDER_POOL_TAG);
                        return FLT_PREOP_SUCCESS_NO_CALLBACK;
                    }
                    time = GetTime();
                    timmm(FOLDER_POOL_TAG, &timeStr);
                    RtlAppendUnicodeToString(&operStr, L"filedelete|");
                    KStrUniAddThree(&timeStr, &operStr, &nameInfo->Name, &totalStr);
                    AddFile(totalStr, time);
                    Data->IoStatus.Status = STATUS_ACCESS_DENIED;
                    Data->IoStatus.Information = 0;
                    FltReleaseFileNameInformation(nameInfo);
                    KStrFreeUni(&indexStr, FOLDER_POOL_TAG);
                    KStrFreeUni(&timeStr, FOLDER_POOL_TAG);
                    KStrFreeUni(&operStr, FOLDER_POOL_TAG);
                    KStrFreeUni(&totalStr, FOLDER_POOL_TAG);
                    return FLT_PREOP_COMPLETE;
                }
                if (Data->Iopb->MajorFunction == IRP_MJ_WRITE)
                {
                    time = GetTime();
                    timmm(FOLDER_POOL_TAG, &timeStr);
                    RtlAppendUnicodeToString(&operStr, L"file write|");
                    KStrUniAddThree(&timeStr, &operStr, &nameInfo->Name, &totalStr);
                    AddFile(totalStr, time);
                    Data->IoStatus.Status = STATUS_ACCESS_DENIED;
                    Data->IoStatus.Information = 0;
                    FltReleaseFileNameInformation(nameInfo);
                    KStrFreeUni(&indexStr, FOLDER_POOL_TAG);
                    KStrFreeUni(&timeStr, FOLDER_POOL_TAG);
                    KStrFreeUni(&operStr, FOLDER_POOL_TAG);
                    KStrFreeUni(&totalStr, FOLDER_POOL_TAG);
                    return FLT_PREOP_COMPLETE;
                }
                if (Data->Iopb->MajorFunction == IRP_MJ_CREATE)
                {
                    if (((Data->Iopb->Parameters.Create.Options >> 24) & 0x000000ff) == FILE_CREATE ||
                        ((Data->Iopb->Parameters.Create.Options >> 24) & 0x000000ff) == FILE_OPEN_IF ||
                        ((Data->Iopb->Parameters.Create.Options >> 24) & 0x000000ff) == FILE_OVERWRITE_IF)
                    {
                        time = GetTime();
                        timmm(FOLDER_POOL_TAG, &timeStr);
                        RtlAppendUnicodeToString(&operStr, L"file create|");
                        KStrUniAddThree(&timeStr, &operStr, &nameInfo->Name, &totalStr);
                        AddFile(totalStr, time);
                        Data->IoStatus.Status = STATUS_ACCESS_DENIED;
                        Data->IoStatus.Information = 0;
                        FltReleaseFileNameInformation(nameInfo);
                        KStrFreeUni(&indexStr, FOLDER_POOL_TAG);
                        KStrFreeUni(&timeStr, FOLDER_POOL_TAG);
                        KStrFreeUni(&operStr, FOLDER_POOL_TAG);
                        KStrFreeUni(&totalStr, FOLDER_POOL_TAG);
                        return FLT_PREOP_COMPLETE;
                    }
                    if (Data->Iopb->OperationFlags == '\x05')
                    {
                        time = GetTime();
                        timmm(FOLDER_POOL_TAG, &timeStr);
                        RtlAppendUnicodeToString(&operStr, L"file rename|");
                        KStrUniAddThree(&timeStr, &operStr, &nameInfo->Name, &totalStr);
                        AddFile(totalStr, time);
                        Data->IoStatus.Status = STATUS_ACCESS_DENIED;
                        Data->IoStatus.Information = 0;
                        FltReleaseFileNameInformation(nameInfo);
                        KStrFreeUni(&indexStr, FOLDER_POOL_TAG);
                        KStrFreeUni(&timeStr, FOLDER_POOL_TAG);
                        KStrFreeUni(&operStr, FOLDER_POOL_TAG);
                        KStrFreeUni(&totalStr, FOLDER_POOL_TAG);
                        return FLT_PREOP_COMPLETE;
                    }
                    if (Data->Iopb->Parameters.Create.Options == FILE_DELETE_ON_CLOSE)
                    {
                        time = GetTime();
                        timmm(FOLDER_POOL_TAG, &timeStr);
                        RtlAppendUnicodeToString(&operStr, L"other operation|");
                        KStrUniAddThree(&timeStr, &operStr, &nameInfo->Name, &totalStr);
                        AddFile(totalStr, time);
                        Data->IoStatus.Status = STATUS_ACCESS_DENIED;
                        Data->IoStatus.Information = 0;
                        FltReleaseFileNameInformation(nameInfo);
                        KStrFreeUni(&indexStr, FOLDER_POOL_TAG);
                        KStrFreeUni(&timeStr, FOLDER_POOL_TAG);
                        KStrFreeUni(&operStr, FOLDER_POOL_TAG);
                        KStrFreeUni(&totalStr, FOLDER_POOL_TAG);
                        return FLT_PREOP_COMPLETE;
                    }
                }
                KStrFreeUni(&indexStr, FOLDER_POOL_TAG);
                break;
            }
            KStrFreeUni(&indexStr, FOLDER_POOL_TAG);
        }
        KStrFreeUni(&timeStr, FOLDER_POOL_TAG);
        KStrFreeUni(&operStr, FOLDER_POOL_TAG);
        KStrFreeUni(&totalStr, FOLDER_POOL_TAG);
        FltReleaseFileNameInformation(nameInfo);
    
        return FLT_PREOP_SUCCESS_WITH_CALLBACK;
    }
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
        return FLT_PREOP_SUCCESS_WITH_CALLBACK;
    }
    

    }

  • MichaelKMichaelK Member Posts: 6

    First, you need to fix your symbol path, symbols look wrong.
    Second, what is the value of NAME_PATH_LENGTH and what does KStrUniToChar do? I have a feeling that stack corruption happens here.

  • Alex_C3Alex_C3 Member Posts: 9

    @MichaelK said:
    First, you need to fix your symbol path, symbols look wrong.
    Second, what is the value of NAME_PATH_LENGTH and what does KStrUniToChar do? I have a feeling that stack corruption happens here.

    NAME_PATH_LENGTH is the is a constant representing the maximum length of a file path,I set it and MAX_PATH_FOL to 2^10=1024;
    KStrUniToChar converts wide strings to char arrays,the code is as follows:

    BOOLEAN KStrUniToChar(PUNICODE_STRING uniName, char Name[])
    {
    ANSI_STRING ansiName;
    NTSTATUS ntstatus;
    char* nameptr;
    __try {
    ntstatus = RtlUnicodeStringToAnsiString(&ansiName, uniName, TRUE);
    nameptr = (PCHAR)ansiName.Buffer;
    strcpy(Name, _strupr(nameptr));
    RtlFreeAnsiString(&ansiName);
    }
    __except (EXCEPTION_EXECUTE_HANDLER) {
    return FALSE;
    }
    return TRUE;
    }

  • MichaelKMichaelK Member Posts: 6

    How do you know that uniName is not longer than 1024 bytes?
    You need at least to add a check of the string length.
    Also, consider using Ntstrsafe to prevent stack and heap overflows.

  • Tim_RobertsTim_Roberts Member - All Emails Posts: 13,066

    Your KStrUniToChar is inherently unsafe, and is EXACTLY the reason why ANSI_STRING exists. You should be using ANSI_STRING. I don't see where you're using fileName, anyway. Also, this line:
    if (fileName == NULL)
    is totally silly. It's an array. It CAN'T be NULL.

    Tim Roberts, [email protected]
    Providenza & Boekelheide, Inc.

  • Alex_C3Alex_C3 Member Posts: 9

    @MichaelK said:
    How do you know that uniName is not longer than 1024 bytes?
    You need at least to add a check of the string length.
    Also, consider using Ntstrsafe to prevent stack and heap overflows.

    This driver works on Windows7 32bit,the maximum length of the file path is defined as 260 characters,so 1024 bytes is long enough to accommodate file paths.
    I tried to use Ntstrsafe and it worked well. Thanks a lot.

  • Alex_C3Alex_C3 Member Posts: 9

    @Tim_Roberts said:
    Your KStrUniToChar is inherently unsafe, and is EXACTLY the reason why ANSI_STRING exists. You should be using ANSI_STRING. I don't see where you're using fileName, anyway. Also, this line:
    if (fileName == NULL)
    is totally silly. It's an array. It CAN'T be NULL.

    You are true. I didn't use fileName. I forgot to delete this code when I am modifying it. Thanks for your reminder. BTW, is there anything else could lead to error?

  • MichaelKMichaelK Member Posts: 6

    @Alex_C3 said:
    This driver works on Windows7 32bit,the maximum length of the file path is defined as 260 characters,so 1024 bytes is long enough to accommodate file paths.

    This is not that straightforward, path names can be longer:

    The Windows API has many functions that also have Unicode versions to permit an extended-length path for a maximum total path length of 32,767 characters. This type of path is composed of components separated by backslashes, each up to the value returned in the lpMaximumComponentLength parameter of the GetVolumeInformation function (this value is commonly 255 characters).

    (Source)

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Upcoming OSR Seminars
Writing WDF Drivers 21 Oct 2019 OSR Seminar Space & ONLINE
Internals & Software Drivers 18 Nov 2019 Dulles, VA
Kernel Debugging 30 Mar 2020 OSR Seminar Space
Developing Minifilters 27 Apr 2020 OSR Seminar Space & ONLINE