// Since some retard decided to use M$ ABI in EFI standard // instead of SysV ABI, we now have to do transitions // GNU-EFI has a functionality for this (thanks god) #define GNU_EFI_USE_MS_ABI 1 // Mandatory defines #include #include // Our protocol GUID (should be different for every driver) static const EFI_GUID ProtocolGuid = { 0x2b479eea, 0x0ecf, 0x4a46, {0x96, 0x84, 0x8f, 0x14, 0xed, 0x92, 0xd9, 0xec} }; // VirtualAddressMap GUID (gEfiEventVirtualAddressChangeGuid) static const EFI_GUID VirtualGuid = { 0x13FA7698, 0xC831, 0x49C7, { 0x87, 0xEA, 0x8F, 0x43, 0xFC, 0xC2, 0x51, 0x96 }}; // ExitBootServices GUID (gEfiEventExitBootServicesGuid) static const EFI_GUID ExitGuid = { 0x27ABF055, 0xB1B8, 0x4C26, { 0x80, 0x48, 0x74, 0x8F, 0x37, 0xBA, 0xA2, 0xDF }}; // Dummy protocol struct typedef struct _DummyProtocalData{ UINTN blank; } DummyProtocalData; // Pointers to original functions static EFI_SET_VARIABLE oSetVariable = NULL; // Global declarations static EFI_EVENT NotifyEvent = NULL; static EFI_EVENT ExitEvent = NULL; static BOOLEAN Virtual = FALSE; static BOOLEAN Runtime = FALSE; // Defines used to check if call is really coming from client #define VARIABLE_NAME L"yromeMifE" // EfiMemory #define COMMAND_MAGIC 0xDEAD // Struct containing data used to communicate with the client typedef struct _MemoryCommand { int magic; int operation; unsigned long long data1; unsigned long long data2; int size; } MemoryCommand; // Function that actually performs the r/w EFI_STATUS RunCommand(MemoryCommand* cmd) { // Check if the command has right magic // (just to be sure again) if (cmd->magic != COMMAND_MAGIC) { return EFI_ACCESS_DENIED; } // Copy operation if (cmd->operation == 0) { // Same as memcpy function CopyMem(cmd->data1, cmd->data2, cmd->size); return EFI_SUCCESS; } // Invalid command return EFI_UNSUPPORTED; } // Hooked EFI function SetVariable() // Can be called from Windows with NtSetSystemEnvironmentValueEx EFI_STATUS EFIAPI HookedSetVariable( IN CHAR16 *VariableName, IN EFI_GUID *VendorGuid, IN UINT32 Attributes, IN UINTN DataSize, IN VOID *Data ) { // Use our hook only after we are in virtual address-space if (Virtual && Runtime) { // Check of input is not null if (VariableName != NULL && VariableName[0] != CHAR_NULL && VendorGuid != NULL) { // Check if variable name is same as our declared one // this is used to check if call is really from our program // running in the OS (client) if (StrnCmp(VariableName, VARIABLE_NAME, (sizeof(VARIABLE_NAME) / sizeof(CHAR16)) - 1) == 0) { if (DataSize == 0 && Data == NULL) { // Skip no data return EFI_SUCCESS; } // Check if the data size is correct if (DataSize == sizeof(MemoryCommand)) { // We did it! // Now we can call the magic function return RunCommand((MemoryCommand*)Data); } } } } // Call the original SetVariable() function return oSetVariable(VariableName, VendorGuid, Attributes, DataSize, Data); } // Event callback when SetVitualAddressMap() is called by OS VOID EFIAPI SetVirtualAddressMapEvent( IN EFI_EVENT Event, IN VOID* Context ) { // Convert orignal SetVariable address RT->ConvertPointer(0, &oSetVariable); // Convert runtime services pointer RtLibEnableVirtualMappings(); // Null and close the event so it does not get called again NotifyEvent = NULL; // We are now working in virtual address-space Virtual = TRUE; } // Event callback after boot process is started VOID EFIAPI ExitBootServicesEvent( IN EFI_EVENT Event, IN VOID* Context ) { // This event is called only once so close it BS->CloseEvent(ExitEvent); ExitEvent = NULL; // Boot services are now not avaible BS = NULL; // We are booting the OS now Runtime = TRUE; // Print some text so we know it works (300iq) ST->ConOut->SetAttribute(ST->ConOut, EFI_WHITE | EFI_BACKGROUND_BLUE); ST->ConOut->ClearScreen(ST->ConOut); Print(L"Driver seems to be working as expected! Windows is booting now...\n"); } // Replaces service table pointer with desired one // returns original VOID* SetServicePointer( IN OUT EFI_TABLE_HEADER *ServiceTableHeader, IN OUT VOID **ServiceTableFunction, IN VOID *NewFunction ) { // We don't want to fuck up the system if (ServiceTableFunction == NULL || NewFunction == NULL) return NULL; // Make sure boot services pointers are not null ASSERT(BS != NULL); ASSERT(BS->CalculateCrc32 != NULL); // Raise task priority level CONST EFI_TPL Tpl = BS->RaiseTPL(TPL_HIGH_LEVEL); // Swap the pointers // GNU-EFI and InterlockedCompareExchangePointer // are not friends VOID* OriginalFunction = *ServiceTableFunction; *ServiceTableFunction = NewFunction; // Change the table CRC32 signature ServiceTableHeader->CRC32 = 0; BS->CalculateCrc32((UINT8*)ServiceTableHeader, ServiceTableHeader->HeaderSize, &ServiceTableHeader->CRC32); // Restore task priority level BS->RestoreTPL(Tpl); return OriginalFunction; } // EFI driver unload routine static EFI_STATUS EFI_FUNCTION efi_unload(IN EFI_HANDLE ImageHandle) { // We don't want our driver to be unloaded // until complete reboot return EFI_ACCESS_DENIED; } // EFI entry point EFI_STATUS efi_main(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable) { // Initialize internal GNU-EFI functions InitializeLib(ImageHandle, SystemTable); // Get handle to this image EFI_LOADED_IMAGE *LoadedImage = NULL; EFI_STATUS status = BS->OpenProtocol(ImageHandle, &LoadedImageProtocol, (void**)&LoadedImage, ImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); // Return if protocol failed to open if (EFI_ERROR(status)) { Print(L"Can't open protocol: %d\n", status); return status; } // Install our protocol interface // This is needed to keep our driver loaded DummyProtocalData dummy = { 0 }; status = LibInstallProtocolInterfaces( &ImageHandle, &ProtocolGuid, &dummy, NULL); // Return if interface failed to register if (EFI_ERROR(status)) { Print(L"Can't register interface: %d\n", status); return status; } // Set our image unload routine LoadedImage->Unload = (EFI_IMAGE_UNLOAD)efi_unload; // Create global event for VirtualAddressMap status = BS->CreateEventEx(EVT_NOTIFY_SIGNAL, TPL_NOTIFY, SetVirtualAddressMapEvent, NULL, VirtualGuid, &NotifyEvent); // Return if event create failed if (EFI_ERROR(status)) { Print(L"Can't create event (SetVirtualAddressMapEvent): %d\n", status); return status; } // Create global event for ExitBootServices status = BS->CreateEventEx(EVT_NOTIFY_SIGNAL, TPL_NOTIFY, ExitBootServicesEvent, NULL, ExitGuid, &ExitEvent); // Return if event create failed (yet again) if (EFI_ERROR(status)) { Print(L"Can't create event (ExitBootServicesEvent): %d\n", status); return status; } // Hook SetVariable (should not fail) oSetVariable = (EFI_SET_VARIABLE)SetServicePointer(&RT->Hdr, (VOID**)&RT->SetVariable, (VOID**)&HookedSetVariable); // Print confirmation text Print(L"\n"); Print(L" __ _ \n"); Print(L" ___ / _(_)___ _ __ ___ _ __ ___ _ _ _ _ \n"); Print(L" / -_) _| |___| ' \\/ -_) ' \\/ _ \\ '_| || |\n"); Print(L" \\___|_| |_| |_|_|_\\___|_|_|_\\___/_| \\_, |\n"); Print(L" |__/ \n"); Print(L"Made by: Samuel Tulach\n"); Print(L"Thanks to: @Mattiwatti (EfiGuard), Roderick W. Smith (rodsbooks.com)\n\n"); Print(L"Driver has been loaded successfully. You can now boot to the OS.\n"); return EFI_SUCCESS; }