1

I'm coding a UEFI Runtime Driver for Windows which hooks gRT->SetVariable(...)

Hooking seems to work fine but whenever I startup a user-mode application and call SetFirmwareEnvironmentVariable(...) it reults in a Bluescreen saying UNEXCEPTED_KERNEL_MODE_TRAP.

I cannot find any solution for this. Here are a few things iam aware of:

  • I'm raising TPL
  • I recalculate and set CRC32
  • On SetVirtualAddressMap(...) i convert all my pointer

Google didn't help at all. So i really wonder what causes this Bluescreen and how i may proceed to resolve this issue.

What am i missing? Am i doing something wrong?

Here is my code:

ExchangePointerInServiceTable((VOID**)&gST->RuntimeServices->SetVariable,
        (VOID*)HookedSetVariable,
        (VOID**)&gOriginalSetVariable);
static
EFI_STATUS
ExchangePointerInServiceTable(
    IN OUT VOID** AddressToUpdate,
    IN VOID* NewPointer,
    OUT VOID** OriginalPointer OPTIONAL
)
{
    EFI_STATUS status;
    EFI_TPL tpl;

    ASSERT(*AddressToUpdate != NewPointer);

    tpl = gBS->RaiseTPL(TPL_HIGH_LEVEL);

    if (OriginalPointer != NULL)
    {
        *OriginalPointer = *AddressToUpdate;
    }
    *AddressToUpdate = NewPointer;

    gST->Hdr.CRC32 = 0;
    status = gBS->CalculateCrc32(&gST->Hdr, gST->Hdr.HeaderSize, &gST->Hdr.CRC32);
    ASSERT_EFI_ERROR(status);

    gBS->RestoreTPL(tpl);
    return status;
}
EFI_STATUS
EFIAPI
HookedSetVariable(
    IN CHAR16* VariableName,
    IN EFI_GUID* VendorGuid,
    IN UINT32 Attributes,
    IN UINTN DataSize,
    IN VOID* Data
) {
    if (StrCmp(VariableName, gStrComVarName) == 0) {
        COMMUNICATION_PROTOCOL * comVarPtr = (COMMUNICATION_PROTOCOL*)Data;
        switch (comVarPtr->i8OperationId) {
        case COMMUNICATION_PROTOCOL_OPERATION_PING:
            comVarPtr->i8OperationId = COMMUNICATION_PROTOCOL_PONG;
        }
        CopyMem(Data, comVarPtr, DataSize);
    }
    
    return gOriginalSetVariable(VariableName, VendorGuid, Attributes, DataSize, Data);
}

Edit: While in UEFI, other UEFI Applications correctly call the hooked SetVariable(...) without any further problems. This may bring it down to the problem only existing after VirtualAddressSpace has been created from the OS.

s0T7x
  • 69
  • 1
  • 9
  • Does the error message indicate what fault occurred, and at what address? Is it in your hook function, or before it is called, or after it returns? – prl Aug 29 '20 at 17:51
  • Are you sure your UEFI runtime driver is still loaded and accessible at the same virtual address? – prl Aug 29 '20 at 17:55
  • Isn’t CopyMem in boot services, not runtime services? In any case, the call to CopyMem is unnecessary; the source and destination are the same. – prl Aug 29 '20 at 18:00
  • Where is gStrComVarName stored? Is it still accessible at the time your hook function is called? – prl Aug 29 '20 at 18:02
  • If you haven’t already, I suggest you test this with a UEFI program before trying it with a Windows program, to concentrate on one set of problems at a time. – prl Aug 29 '20 at 18:04
  • @prl regarding the error message: i cannot find anymore information to this. Error log only gives me error code: `0x0000007f (0x0000000000000008, 0xfffff80654280e50, 0xffffa68e94898ee0, 0xfffff80650c5844a).` I think it should still be loaded but how may i find out? I removed CopyMem call. Still BSOD. With another UEFI application i can easily call the hooked SetVariable. gStrComVarName in stored in global scope. But i saw that i did not convert its pointer. I do that now. Still BSOD. – s0T7x Aug 30 '20 at 12:02
  • Searching for UNEXPECTED_KERNEL_MODE_TRAP finds some useful information. For example, https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/bug-check-0x7f--unexpected-kernel-mode-trap and https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/bug-check-code-reference2. – prl Aug 30 '20 at 21:07
  • 0x7f means UNEXPECTED_KERNEL_MODE_TRAP; 8 means double fault. The addresses indicate that it is not in your driver (because they would be less than 0x100000000) but other than that I don't know how to interpret them. You probably need a Windows debugger (windbg). – prl Aug 30 '20 at 21:07
  • Can you figure out a way to tell when your hook function is called (trace, for example), so you can tell if the error occurs before it is called or after it returns? – prl Aug 30 '20 at 21:08

0 Answers0