Skip to content

Implement NtQuerySystemEnvironmentValueEx, NtQuerySystemInformation SystemBootEnvironmentInformation, GetFirmwareType, GetFirmwareEnvironmentVariable*

Grigory Vasilyev requested to merge h0tc0d3/wine:firmware into master

ntdll:

  • NtQuerySystemInformation SystemBootEnvironmentInformation
  • NtQuerySystemEnvironmentValueEx

kernel32:

  • GetFirmwareType
  • GetFirmwareEnvironmentVariableExA
  • GetFirmwareEnvironmentVariableExW
  • GetFirmwareEnvironmentVariableA
  • GetFirmwareEnvironmentVariableW.

The code is needed to check SecureBoot status, security systems and for example to check the licenses of software that can use efi variables. The behavior matches the behavior of Windows 11. And the output is no different on wine and Windows 11.

Example:

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include <winnt.h>
#include <winternl.h>
#include <winbase.h>
#include <securitybaseapi.h>

/*
x86_64-w64-mingw32-gcc -O2 firmware.c -o firmware.exe -Wl,--subsystem,console
*/
#define SystemBootEnvironmentInformation 90

#define GUID_FORMAT "%08X-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX"
#define GUID_ARG(guid)                                                       \
    (unsigned int)(guid).Data1, (guid).Data2, (guid).Data3, (guid).Data4[0], \
        (guid).Data4[1], (guid).Data4[2], (guid).Data4[3], (guid).Data4[4],  \
        (guid).Data4[5], (guid).Data4[6], (guid).Data4[7]

typedef struct _SYSTEM_BOOT_ENVIRONMENT_INFORMATION
{
    GUID BootIdentifier;
    FIRMWARE_TYPE FirmwareType;
    union
    {
        ULONGLONG BootFlags;
        struct
        {
            ULONGLONG DbgMenuOsSelection : 1;
            ULONGLONG DbgHiberBoot : 1;
            ULONGLONG DbgSoftBoot : 1;
            ULONGLONG DbgMeasuredLaunch : 1;
            ULONGLONG DbgMeasuredLaunchCapable : 1;
            ULONGLONG DbgSystemHiveReplace : 1;
            ULONGLONG DbgMeasuredLaunchSmmProtections : 1;
            ULONGLONG DbgMeasuredLaunchSmmLevel : 7;
        };
    };
} SYSTEM_BOOT_ENVIRONMENT_INFORMATION, *PSYSTEM_BOOT_ENVIRONMENT_INFORMATION;

typedef NTSTATUS(NTAPI *LPFNZwInitUnicodeString)(IN OUT PUNICODE_STRING DestinationString,
                                                 IN PCWSTR SourceString);

typedef NTSTATUS(NTAPI *LPFNZwQuerySystemInformation)(
    IN SYSTEM_INFORMATION_CLASS SystemInformationClass, IN OUT PVOID SystemInformation,
    IN ULONG SystemInformationLength, OUT PULONG ReturnLength);

typedef NTSTATUS(NTAPI *LPFNZwQuerySystemEnvironmentValueEx)(
    IN PUNICODE_STRING VariableName, IN LPGUID VendorGuid, IN PVOID Value,
    IN OUT PULONG ReturnLength, OUT PULONG Attributes);

BOOL EnableTokenPrivilege(HANDLE hToken, const char *pszPrivilegesName, BOOL bEnabled)
{
    LUID luid;
    TOKEN_PRIVILEGES tp;

    if (!LookupPrivilegeValue(NULL, pszPrivilegesName, &luid))
    {
        return FALSE;
    }

    tp.PrivilegeCount = 1;
    tp.Privileges[0].Luid = luid;
    tp.Privileges[0].Attributes = bEnabled ? SE_PRIVILEGE_ENABLED : 0;

    if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL))
    {
        return FALSE;
    }

    return TRUE;
}

int main(int argc, char **argv)
{
    DWORD ret;
    ULONG ret_size;
    HANDLE hToken;
    HANDLE hProcess;
    HINSTANCE hNTdll;
    NTSTATUS status;
    DWORD attributes;
    BOOLEAN secureboot = 0;
    FIRMWARE_TYPE type = FirmwareTypeUnknown;
    char asus_license[2048] = {0};
    UNICODE_STRING asus_name;
    UNICODE_STRING dummy_name;
    UNICODE_STRING secureboot_name;

    GUID asus_guid = {
        0x02076249,
        0xa52b,
        0x420e,
        {0xbd, 0x53, 0xae, 0xd0, 0x44, 0x34, 0x93, 0x79}};
    GUID secureboot_guid = {
        0x8be4df61,
        0x93ca,
        0x11d2,
        {0xaa, 0x0d, 0x00, 0xe0, 0x98, 0x03, 0x2b, 0x8c}};
    GUID dummy_guid = {0};

    SYSTEM_BOOT_ENVIRONMENT_INFORMATION boot_info = {0};

    LPFNZwInitUnicodeString ZwInitUnicodeString;
    LPFNZwQuerySystemInformation ZwQuerySystemInformation;
    LPFNZwQuerySystemEnvironmentValueEx ZwQuerySystemEnvironmentValueEx;

    hNTdll = LoadLibraryW(L"Ntdll.dll");

    if (!hNTdll)
    {
        printf("Can't load ntdll liabrary!\n");
        return -1;
    }

    ZwInitUnicodeString = (LPFNZwInitUnicodeString)GetProcAddress(hNTdll, "RtlInitUnicodeString");
    if (!ZwInitUnicodeString)
    {
        printf("Can't get GetProcAddress RtlInitUnicodeString error: %d!\n",
               GetLastError());
        return -1;
    }

    ZwInitUnicodeString(&asus_name, L"AsusOnboardToolLicense");
    ZwInitUnicodeString(&dummy_name, L"DummyName");
    ZwInitUnicodeString(&secureboot_name, L"SecureBoot");

    ZwQuerySystemInformation = (LPFNZwQuerySystemInformation)GetProcAddress(hNTdll, "ZwQuerySystemInformation");
    if (!ZwQuerySystemInformation)
    {
        printf("Can't get GetProcAddress ZwQuerySystemInformation error: %d!\n",
               GetLastError());
        return -1;
    }

    ZwQuerySystemEnvironmentValueEx = (LPFNZwQuerySystemEnvironmentValueEx)GetProcAddress(
        hNTdll, "ZwQuerySystemEnvironmentValueEx");
    if (!ZwQuerySystemEnvironmentValueEx)
    {
        printf("Can't get GetProcAddress ZwQuerySystemEnvironmentValueEx error: %d!\n",
               GetLastError());
        return -1;
    }

    hProcess = GetCurrentProcess();
    if (!hProcess)
    {
        printf("GetCurrentProcessToken error: %d!\n", GetLastError());
        return -1;
    }

    if (!OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
    {
        printf("OpenProcessToken error: %d!\n", GetLastError());
        return -1;
    }

    if (!EnableTokenPrivilege(hToken, SE_SYSTEM_ENVIRONMENT_NAME, TRUE))
    {
        printf("EnableTokenPrivilege error: %d!\n", GetLastError());
        return -1;
    }

    if (GetFirmwareType(&type))
        printf("GetFirmwareType: %s\n\n", type == FirmwareTypeUefi ? "UEFI" : "BIOS");

    ret = GetFirmwareEnvironmentVariableA("SecureBoot",
                                          "{8be4df61-93ca-11d2-aa0d-00e098032b8c}",
                                          &secureboot, sizeof(BOOLEAN));
    if (!ret)
        printf("GetFirmwareEnvironmentVariableA error: 0x%08lx.\n\n", GetLastError());

    printf("GetFirmwareEnvironmentVariableA\nBytes: %d\nSecureBoot: %s\n\n", ret,
           secureboot ? "enabled" : "disabled");

    ret = GetFirmwareEnvironmentVariableA("DummyName",
                                          "{00000000-0000-0000-0000-000000000000}",
                                          &secureboot, sizeof(BOOLEAN));
    if (!ret)
        printf("GetFirmwareEnvironmentVariableA Dummy GUID error: 0x%08lx.\n\n", GetLastError());

    secureboot = 0;
    ret = GetFirmwareEnvironmentVariableW(L"SecureBoot",
                                          L"{8be4df61-93ca-11d2-aa0d-00e098032b8c}",
                                          &secureboot, sizeof(BOOLEAN));
    if (!ret)
        printf("GetFirmwareEnvironmentVariableW error: 0x%08lx.\n\n", GetLastError());

    printf("GetFirmwareEnvironmentVariableW\nBytes: %d\nSecureBoot: %s\n\n", ret,
           secureboot ? "enabled" : "disabled");

    attributes = 0;
    secureboot = 0;
    ret = GetFirmwareEnvironmentVariableExA("SecureBoot",
                                            "{8be4df61-93ca-11d2-aa0d-00e098032b8c}",
                                            &secureboot, sizeof(BOOLEAN), &attributes);
    if (!ret)
        printf("GetFirmwareEnvironmentVariableExA error: 0x%08lx.\n\n", GetLastError());

    printf("GetFirmwareEnvironmentVariableExA\nBytes: %d\nAttributes: 0x%08x\nSecureBoot: %s\n\n",
           ret, attributes, secureboot ? "enabled" : "disabled");

    attributes = 0;
    ret = GetFirmwareEnvironmentVariableExW(L"AsusOnboardToolLicense",
                                            L"{02076249-a52b-420e-bd53-aed044349379}",
                                            asus_license, sizeof(asus_license),
                                            &attributes);
    if (!ret)
        printf("GetFirmwareEnvironmentVariableExW error: 0x%08lx.\n\n", GetLastError());

    printf("GetFirmwareEnvironmentVariableExW\nBytes: %d\nAttributes: 0x%08x\nAsus License: \n%s\n\n",
           ret, attributes, asus_license);

    ret_size = sizeof(secureboot);
    attributes = 0;
    secureboot = 0;
    status = ZwQuerySystemEnvironmentValueEx(&secureboot_name, &secureboot_guid, &secureboot,
                                             &ret_size, &attributes);

    if (!status)
        printf("NtQuerySystemEnvironmentValueEx error: 0x%08lx.\n\n", status);

    printf("NtQuerySystemEnvironmentValueEx\nBytes: %d\nAttributes: 0x%08x\nSecureBoot: %s\n\n",
           ret_size, attributes, secureboot ? "enabled" : "disabled");

    ret_size = sizeof(secureboot);
    attributes = 0;
    secureboot = 0;
    status = ZwQuerySystemEnvironmentValueEx(&dummy_name, &dummy_guid, &secureboot,
                                             &ret_size, &attributes);

    printf("NtQuerySystemEnvironmentValueEx Dummy GUID error: 0x%08lx.\n\n", status);

    ret_size = sizeof(asus_license);
    attributes = 0;
    for (size_t i = 0; i < ret_size; i++)
    {
        asus_license[i] = '\0';
    }
    status = ZwQuerySystemEnvironmentValueEx(&asus_name, &asus_guid, asus_license, &ret_size,
                                             &attributes);
    if (status)
        printf("NtQuerySystemEnvironmentValueEx error: 0x%08lx.\n\n", status);

    printf("NtQuerySystemEnvironmentValueEx\nBytes: %d\nAttributes: 0x%08x\nAsus License: \n%s\n\n",
           ret_size, attributes, asus_license);

    status = ZwQuerySystemInformation(
        (SYSTEM_INFORMATION_CLASS)SystemBootEnvironmentInformation, &boot_info,
        sizeof(boot_info), &ret_size);
    if (status)
        printf("NtQuerySystemInformation error: 0x%08lx.\n\n", status);

    printf("SystemBootEnvironmentInformation:\nBootIdentifier: {" GUID_FORMAT "}",
           GUID_ARG(boot_info.BootIdentifier));
    printf("\nFirmwareType: %s\nBootFlags: 0x%llX\n\n",
           (boot_info.FirmwareType == FirmwareTypeUefi ? "UEFI" : "BIOS"),
           boot_info.BootFlags);

    FreeLibrary(hNTdll);

    return 0;
}

Output:

GetFirmwareType: UEFI

GetFirmwareEnvironmentVariableA
Bytes: 1
SecureBoot: enabled

GetFirmwareEnvironmentVariableW
Bytes: 1
SecureBoot: enabled

GetFirmwareEnvironmentVariableExA
Bytes: 1
Attributes: 0x00000006
SecureBoot: enabled

GetFirmwareEnvironmentVariableExW
Bytes: 1570
Attributes: 0x00000006
Asus License: 
BASE64_BIG_LICENSE_TEXT==
[LicenseID]:FED7A1
[Model]:Dummy-BaseBoard-Id
[Tools]:WAsusDmiS,LogoFlashS,ASUSFwConfigS,AsusEventLogS,AsusNvLockS
[Customer]:DummyLic
[Expire]:2022-11-24

NtQuerySystemEnvironmentValueEx
Bytes: 1
Attributes: 0x00000006
SecureBoot: enabled

NtQuerySystemEnvironmentValueEx
Bytes: 1570
Attributes: 0x00000006
Asus License: 
BASE64_BIG_LICENSE_TEXT==
[LicenseID]:FED7A1
[Model]:Dummy-BaseBoard-Id
[Tools]:WAsusDmiS,LogoFlashS,ASUSFwConfigS,AsusEventLogS,AsusNvLockS
[Customer]:DummyLic
[Expire]:2022-11-24

SystemBootEnvironmentInformation:
BootIdentifier: {8522FFCA-6A31-11EF-952A-966164983DCB}
FirmwareType: UEFI
BootFlags: 0x0
Edited by Grigory Vasilyev

Merge request reports

Loading