|
/** |
|
* Codename: GospelRoom |
|
* Technique: Data Storage in UEFI NVRAM Variables |
|
* Author: @Jackson_T |
|
* |
|
* Behaviour: Persist data in UEFI NVRAM variables. |
|
* |
|
* Benefits: |
|
* 1. Stealthy way to store secrets and other data in UEFI. |
|
* 2. Will survive a reimaging of the operating system. |
|
* 3. NVRAM variables cannot be directly enumerated with |
|
* OS-level APIs. Enumeration requires exact knowledge of |
|
* variable names and their GUIDs. |
|
* |
|
* Caveats: |
|
* 1. Computer must have UEFI enabled, legacy BIOS will not work. |
|
* 2. The user account that the app is running under must have |
|
* the SE_SYSTEM_ENVIRONMENT_NAME privilege (admin required). |
|
* 3. Buffer size is limited up to the size of the flash chip. |
|
* |
|
* Example output: |
|
* - [SET] TestVariable: Hello, NVRAM! |
|
* [GET] TestVariable: Hello, NVRAM! |
|
* |
|
* References: |
|
* - https://wikileaks.org/ciav7p1/cms/page_31227915.html |
|
* - https://wikileaks.org/ciav7p1/cms/page_26968084.html |
|
* - https://docs.microsoft.com/en-us/windows/desktop/api |
|
* /winbase/nf-winbase-getfirmwareenvironmentvariablea |
|
* - https://www.youtube.com/watch?v=q2KUufrjoRo |
|
* - https://github.com/perturbed-platypus |
|
*/ |
|
|
|
|
|
#include "stdafx.h" |
|
#include <Windows.h> |
|
|
|
// Caveat #1: Check if system supports UEFI. |
|
int IsFeatureSupported() |
|
{ |
|
int buffer; |
|
GetFirmwareEnvironmentVariable(L"", L"{00000000-0000-0000-0000-000000000000}", &buffer, sizeof(buffer)); |
|
return (GetLastError() == ERROR_INVALID_FUNCTION) ? 0 : 1; |
|
} |
|
|
|
// Caveat #2: SeSystemEnvironmentPrivilege needs to be set. |
|
int SetSystemEnvironmentPrivilege() |
|
{ |
|
typedef NTSTATUS(WINAPI* RTLADJUSTPRIVILEGE)( |
|
_In_ ULONG Privilege, |
|
_In_ BOOLEAN Enable, |
|
_In_ BOOLEAN CurrentThread, |
|
_Out_ PBOOLEAN Enabled); |
|
|
|
HMODULE hnd_module = LoadLibrary(_T("ntdll.dll")); |
|
RTLADJUSTPRIVILEGE RtlAdjustPrivilege = (RTLADJUSTPRIVILEGE)GetProcAddress(hnd_module, "RtlAdjustPrivilege"); |
|
ULONG SeSystemEnvironmentPrivilege = 22; |
|
BOOLEAN enabled = false; |
|
RtlAdjustPrivilege(SeSystemEnvironmentPrivilege, true, false, &enabled); |
|
|
|
return (int)enabled; |
|
} |
|
|
|
// Convert the variable name to GUID for convenience. |
|
// Modify this function as appropriate. |
|
wchar_t* ConvertNameToGuid(wchar_t* name) |
|
{ |
|
// Compute DJB2 hash of name. |
|
DWORD hash = 5381, c; |
|
while (c = *name++) |
|
hash = ((hash << 5) + hash) + c; |
|
|
|
wchar_t* guid = (wchar_t*)malloc(100); |
|
swprintf_s(guid, 100, L"{%08X-1337-1337-1337-1337%08X}", hash, hash); |
|
|
|
return guid; |
|
} |
|
|
|
// Persist a buffer in NVRAM. |
|
int SetVariable(wchar_t* name, void* buffer, size_t size) |
|
{ |
|
wchar_t* guid = ConvertNameToGuid(name); |
|
return SetFirmwareEnvironmentVariable(name, guid, buffer, (DWORD)size); |
|
} |
|
|
|
// Retrieve a buffer from NVRAM. |
|
size_t GetVariable(wchar_t* name, void* buffer, size_t size) |
|
{ |
|
wchar_t* guid = ConvertNameToGuid(name); |
|
return GetFirmwareEnvironmentVariable(name, guid, buffer, (DWORD)size); |
|
} |
|
|
|
int main() |
|
{ |
|
wprintf(L"GospelRoom: Data Storage in UEFI NVRAM Variables\n\n"); |
|
|
|
if (IsFeatureSupported()) |
|
{ |
|
SetSystemEnvironmentPrivilege(); |
|
|
|
wchar_t* set_buffer = L"Hello, NVRAM!"; |
|
wchar_t* get_buffer = (wchar_t*)calloc(wcslen(set_buffer), sizeof(wchar_t)); |
|
|
|
SetVariable(L"TestVariable", set_buffer, wcslen(set_buffer) * sizeof(wchar_t)); |
|
wprintf(L"[SET] TestVariable: %ls\n", set_buffer); |
|
|
|
GetVariable(L"TestVariable", get_buffer, wcslen(set_buffer) * sizeof(wchar_t)); |
|
wprintf(L"[GET] TestVariable: %ls\n", get_buffer); |
|
} else { |
|
printf("ERROR: This feature is not supported."); |
|
} |
|
|
|
return 0; |
|
} |