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:
```C #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 <shlwapi.h> #include <securitybaseapi.h>
/* x86_64-w64-mingw32-gcc -O2 firmware.c -o firmware.exe -Wl,--subsystem,console -lole32 */ #define SystemBootEnvironmentInformation 90
#define GUID_FORMAT "%08lX-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX" #define GUID_ARG(guid) \ (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, LPCTSTR 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; DWORD attributes; BOOLEAN secureboot = 0; FIRMWARE_TYPE type = FirmwareTypeUnknown;
UNICODE_STRING asus_name; char asus_license[2048] = {0};
UNICODE_STRING secureboot_name;
GUID asus_guid; GUID secureboot_guid;
SYSTEM_BOOT_ENVIRONMENT_INFORMATION boot_info = {0};
LPFNZwInitUnicodeString ZwInitUnicodeString; LPFNZwQuerySystemInformation ZwQuerySystemInformation; LPFNZwQuerySystemEnvironmentValueEx ZwQuerySystemEnvironmentValueEx;
if (CLSIDFromString(L"{02076249-a52b-420e-bd53-aed044349379}", &asus_guid) != NOERROR) { printf("CLSIDFromString error: %d!\n", GetLastError()); return -1; }
if (CLSIDFromString(L"{8be4df61-93ca-11d2-aa0d-00e098032b8c}", &secureboot_guid) != NOERROR) { printf("CLSIDFromString error: %d!\n", GetLastError()); return -1; }
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(&secureboot_name, L"SecureBoot"); ZwInitUnicodeString(&asus_name, L"AsusOnboardToolLicense");
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: % d!\n\n", GetLastError()); return -1; } printf("GetFirmwareEnvironmentVariableA\nBytes: %d\nSecureBoot: %s\n\n", ret, secureboot ? "enabled" : "disabled");
secureboot = 0; ret = GetFirmwareEnvironmentVariableW( L"SecureBoot", L"{8be4df61-93ca-11d2-aa0d-00e098032b8c}", &secureboot, sizeof(BOOLEAN) ); if (!ret) { printf("GetFirmwareEnvironmentVariableW error: % d!\n\n", GetLastError()); return -1; } 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: % d!\n\n", GetLastError()); return -1; } 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: % d!\n\n", GetLastError()); return -1; } 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; if (ZwQuerySystemEnvironmentValueEx(&secureboot_name, &secureboot_guid, &secureboot, &ret_size, &attributes) != NOERROR) { printf("ZwQuerySystemEnvironmentValueEx error: % d!\n\n", GetLastError()); FreeLibrary(hNTdll); return -1; } printf( "NtQuerySystemEnvironmentValueEx\nBytes: %d\nAttributes: 0x%08x\nSecureBoot: %s\n\n", ret_size, attributes, secureboot ? "enabled" : "disabled" );
ret_size = sizeof(asus_license); attributes = 0; for (size_t i = 0; i < ret_size; i++) { asus_license[i] = '\0'; } if (ZwQuerySystemEnvironmentValueEx(&asus_name, &asus_guid, asus_license, &ret_size, &attributes) != NOERROR) { printf("ZwQuerySystemEnvironmentValueEx error: % d!\n\n", GetLastError()); FreeLibrary(hNTdll); return -1; } printf( "NtQuerySystemEnvironmentValueEx\nBytes: %d\nAttributes: 0x%08x\nAsus License: \n%s\n\n", ret_size, attributes, asus_license );
if (ZwQuerySystemInformation( (SYSTEM_INFORMATION_CLASS) SystemBootEnvironmentInformation, &boot_info, sizeof(boot_info), &ret_size ) != NOERROR) { printf("ZwQuerySystemInformation error: % d!\n\n", GetLastError()); FreeLibrary(hNTdll); return -1; }
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 ```
-- v25: kernel32: Implement GetFirmwareEnvironmentVariableExA, GetFirmwareEnvironmentVariableExW, GetFirmwareEnvironmentVariableA, GetFirmwareEnvironmentVariableW.