first commit
This commit is contained in:
19
.vscode/c_cpp_properties.json
vendored
Normal file
19
.vscode/c_cpp_properties.json
vendored
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Linux",
|
||||||
|
"includePath": [
|
||||||
|
"${workspaceFolder}/**",
|
||||||
|
"/usr/include/efi",
|
||||||
|
"/usr/include/efi/x86_64",
|
||||||
|
"/usr/include/efi/protocol"
|
||||||
|
],
|
||||||
|
"defines": [],
|
||||||
|
"compilerPath": "/usr/bin/gcc",
|
||||||
|
"cStandard": "c11",
|
||||||
|
"cppStandard": "c++17",
|
||||||
|
"intelliSenseMode": "gcc-x64"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"version": 4
|
||||||
|
}
|
||||||
42
driver/Makefile
Normal file
42
driver/Makefile
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
ARCH = $(shell uname -m | sed s,i[3456789]86,ia32,)
|
||||||
|
|
||||||
|
OBJS = main.o
|
||||||
|
TARGET = memory.efi
|
||||||
|
|
||||||
|
EFIINC = /usr/include/efi
|
||||||
|
EFIINCS = -I$(EFIINC) -I$(EFIINC)/$(ARCH) -I$(EFIINC)/protocol
|
||||||
|
LIB32 = /usr/lib32
|
||||||
|
LIB64 = /usr/lib
|
||||||
|
|
||||||
|
CFLAGS = $(EFIINCS) -fno-stack-protector -fpic \
|
||||||
|
-fshort-wchar -mno-red-zone -Wall
|
||||||
|
|
||||||
|
ifeq ($(ARCH),x86_64)
|
||||||
|
CFLAGS += -DEFI_FUNCTION_WRAPPER
|
||||||
|
LIB = $(LIB64)
|
||||||
|
EFILIB = $(LIB64)
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(ARCH),ia32)
|
||||||
|
LIB = $(LIB32)
|
||||||
|
EFILIB = $(LIB32)
|
||||||
|
endif
|
||||||
|
|
||||||
|
EFI_CRT_OBJS = $(EFILIB)/crt0-efi-$(ARCH).o
|
||||||
|
EFI_LDS = $(EFILIB)/elf_$(ARCH)_efi.lds
|
||||||
|
|
||||||
|
LDFLAGS = -nostdlib -znocombreloc -T $(EFI_LDS) -shared \
|
||||||
|
-Bsymbolic -L $(EFILIB) -L $(LIB) $(EFI_CRT_OBJS)
|
||||||
|
|
||||||
|
all: $(TARGET)
|
||||||
|
|
||||||
|
memory.so: $(OBJS)
|
||||||
|
ld $(LDFLAGS) $(OBJS) -o $@ -lefi -lgnuefi
|
||||||
|
|
||||||
|
%.efi: %.so
|
||||||
|
objcopy -j .text -j .sdata -j .data -j .dynamic \
|
||||||
|
-j .dynsym -j .rel -j .rela -j .reloc \
|
||||||
|
--target=efi-rtdrv-$(ARCH) $^ $@
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f memory.efi memory.so main.o *~
|
||||||
293
driver/main.c
Normal file
293
driver/main.c
Normal file
@@ -0,0 +1,293 @@
|
|||||||
|
// 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 <efi.h>
|
||||||
|
#include <efilib.h>
|
||||||
|
|
||||||
|
// 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 }};
|
||||||
|
|
||||||
|
// Global variable GUID (gEfiGlobalVariableGuid)
|
||||||
|
static const EFI_GUID VariableGuid
|
||||||
|
= { 0x8BE4DF61, 0x93CA, 0x11D2, { 0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C }};
|
||||||
|
|
||||||
|
// 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
|
||||||
|
EFI_SET_VARIABLE oSetVariable = NULL;
|
||||||
|
|
||||||
|
// Global declarations
|
||||||
|
EFI_EVENT NotifyEvent = NULL;
|
||||||
|
EFI_EVENT ExitEvent = NULL;
|
||||||
|
BOOLEAN Virtual = FALSE;
|
||||||
|
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 GUID is correct
|
||||||
|
if (CompareGuid(VendorGuid, &VariableGuid))
|
||||||
|
{
|
||||||
|
// 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
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// 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;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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");
|
||||||
|
}
|
||||||
BIN
driver/main.o
Normal file
BIN
driver/main.o
Normal file
Binary file not shown.
BIN
driver/memory.efi
Normal file
BIN
driver/memory.efi
Normal file
Binary file not shown.
BIN
driver/memory.so
Normal file
BIN
driver/memory.so
Normal file
Binary file not shown.
Reference in New Issue
Block a user