Skip to content

KbTriggerCopyOnWrite BSOD immediately sample #29

@Tai7sy

Description

@Tai7sy

debug_me.exe is a simple application which call MessageBoxA when button clicked.

Now we use KbWriteProcessMemory with TriggleCoW to user32.MessageBoxA like this:

VOID BSOD_Test() {

    WdkTypes::PEPROCESS Process;
    DWORD ProcessId = GetProcessIdByName(TEXT("debug_me.exe")); // A wow64 process
    PVOID Address = (PVOID)0x76311F70; // user32.MessageBoxA

    Processes::Descriptors::KbGetEprocess(ProcessId, &Process);
    printf("MessageBoxA: VA:%p, PA:0x%I64X\n", Address, GetPhysAddr(Process, Address));
    {
        BYTE Buffer[1] = { 0 };
        BOOL Status = Processes::MemoryManagement::KbReadProcessMemory(ProcessId, (WdkTypes::PVOID)Address, Buffer, 1);
        printf("MessageBoxA: KbReadProcessMemory:  0x%02X\n", Buffer[0]);
    }

    {
        BYTE* NewBuffer = new BYTE[1];
        NewBuffer[0] = 0xC3;
        BOOL Status = Processes::MemoryManagement::KbWriteProcessMemory(ProcessId, (WdkTypes::PVOID)Address, NewBuffer, 1, TRUE);
        delete[] NewBuffer;
        printf("MessageBoxA: KbWriteProcessMemory: %d\n", Status);
        printf("MessageBoxA: PA:0x%I64X\n", GetPhysAddr(Process, Address));
    }

    Processes::Descriptors::KbDereferenceObject(Process);
}

The debug_me.exe will crash obviously because the user32.MessageBoxA is changed to 0xC3 and caused some stack error.

Then it will cause immediately BSOD.

QUOTA_UNDERFLOW (21)
This bugcheck occurs if a kernel component mishandles quota charges and
returns more quota than was previously charged to a particular quota block.
Arguments:
Arg1: ffffc9872b1ee080, The process (if any) that was initially charged.
Arg2: 0000000000000002, The quota type in question (paged pool, nonpaged pool, etc.)
Arg3: ffffffffffffffff, The initial charge amount to return.
Arg4: fffffffffffae8bd, The remaining (unreturned) charge.
------------------
os: 
Windows 10 1809

stack:
[0x4]   nt!PspReturnQuota + 0x180085   
[0x5]   nt!PsReturnProcessPageFileQuota + 0x25   
[0x6]   nt!MiReturnFullProcessCharges + 0x4b   
[0x7]   nt!MiRemoveVadCharges + 0xab   
[0x8]   nt!MiFinishVadDeletion + 0xf1   
[0x9]   nt!MiDeleteVad + 0x15f2   
[0xa]   nt!MiUnmapVad + 0x49   
[0xb]   nt!MiCleanVad + 0x30   
[0xc]   nt!MmCleanProcessAddressSpace + 0x113   
[0xd]   nt!PspRundownSingleProcess + 0x129   
[0xe]   nt!PspProcessRundownWorkerSingle + 0x32   
[0xf]   nt!ExpWorkerThread + 0x16a   
[0x10]   nt!PspSystemThreadStartup + 0x55   
[0x11]   nt!KiStartSystemThread + 0x1c   

Since the KbTriggerCopyOnWrite will still take some minnutes/hours to cause a BSOD, which meen it difficult to debug.
This maybe helpful to find the problem.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions