1. Foundational Resources
- VisualUefi from Alex Ionescu
- DreamBoot bootkit
- UEFI-Bootkit
- MoonBounce bootkit
- MoonBounce Technical Writeup
- Hook ExitBootServices
- NCC Group - Deploying Rootkits from EFI
- EDK II Module Writers Guide
2. Setting Up a Development Environment
While the EDK is a massive project with a difficult and complex set up process, Alex Ionescu has released a repository with everything one needs to get set up quickly in Visual Studio. Link: VisualUefi).
git clone https://github.com/ionescu007/VisualUefi.git
git submodules init
git submodule update --init --recursive
# then build in EDK II solution
3. Moonbounce Synposis (UEFI Component)
Notes from kaspersky writeup linked above.
DriverMapping Shellcode Hook
- Restore function prologue bytes of
AllocatePool
- Call
AllocatePool
and writeDriver Mapping Shellcode
to the buffer - Restore original arguments and pass to
AllocatePool
Main Algorithm
- Load driver during
DXE
phase - Hook first five bytes
AllocatePool
to allocate and assign buffer for/withDriver Mapping Shellcod
- Hook
ExitBootServices
to hookOslArchTransferToKernel
- Allow execution up to
OslArchTransferToKernel
hook - Locate
ntoskrnl.exe
by readingIDENTRY64
interrupt service routineIdtBase
(Interrupt Descriptor Table) field fromKPCR
. This handler is in thentosrknl
address space and can be used to search backward in memory for the DOS MZ header, and then resolve the addresses of its exportExRegisterCallback
,ExAllocatePool
, andMmMapIoSpace
- Hook
ExAllocatePool
to call a shellcode buffer copied intontoskrnl.exe
’s relocation directory - Allow execution to first call of
ExAllocatePool
hook, which callsMmMapIoSpace
to allocate space for mapping driver mapping shellcode contained by the buffer created in step to by theAllocatePool
hook and execute this shellcode
Driver Loader
passed:
- Pointer to buffer with original
ExAllocatePool
bytes - Base of
ntoskrnl.exe
- Pointer to
ExAllocatePool
algorithm:
- unhooks
ExAllocatePool
- resolves
RtlInitAnsiString
,RtlAnsiStringToUnicodeString
, andMmGetSystemRoutineAddress
- Allocates pool space for the driver
- Maps and copies headers and sections
- Performs relocations
- Resolves imports
- Passes control to driver
Remainder of Attack Chain
From there, the driver registers a callback to PsSetLoadImageNotifyRoutine
to faciliate injection of usermode malware into the a Windows service.
4. Synopsis of ExitBootServices
From Vault7
ExitBootServices
is the point where UEFI boot services phase ends and control is transferred to the operating system- Terminates boot services
- Reclaims boot service memory
ExitBootServices
pointer is found inEFI_BOOT_SERVICES
table- UEFI driver can simply store this pointer and replace it with the hook
- Must call
GetMemoryMap
before calling realExitBootServices
Exmaple code:
extern EFI_BOOT_SERVICES *gBS;
EFI_EXIT_BOOT_SERVICES gOrigExitBootServices;
EFI_STATUS
EFIAPI
ExitBootServicesHook(IN EFI_HANDLE ImageHandle, IN UINTN MapKey){
/* <hook related fun> */
/* Do fun hook-related stuff here */
/* </hook-related fun> */
/* Fix the pointer in the boot services table */
/* If you don't do this, sometimes your hook method will be called repeatedly, which you don't want */
gBS->ExitBootServices = gOrigExitBootServices;
/* Get the memory map */
UINTN MemoryMapSize;
EFI_MEMORY_DESCRIPTOR *MemoryMap;
UINTN LocalMapKey;
UINTN DescriptorSize;
UINT32 DescriptorVersion;
MemoryMap = NULL;
MemoryMapSize = 0;
do {
Status = gBS->GetMemoryMap(&MemoryMapSize, MemoryMap, &LocalMapKey, &DescriptorSize,&DescriptorVersion);
if (Status == EFI_BUFFER_TOO_SMALL){
MemoryMap = AllocatePool(MemoryMapSize + 1);
Status = gBS->GetMemoryMap(&MemoryMapSize, MemoryMap, &LocalMapKey, &DescriptorSize,&DescriptorVersion);
} else {
/* Status is likely success - let the while() statement check success */
}
DbgPrint(L"This time through the memory map loop, status = %r\n",Status);
} while (Status != EFI_SUCCESS);
return gOrigExitBootServices(ImageHandle,LocalMapKey);
}
EFI_STATUS
EFIAPI
HookDriverMain(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable){
/* Store off the original pointer and replace it with your own */
gOrigExitBootServices = gBS->ExitBootServices;
gBS->ExitBootServices = ExitBootServicesHook;
/* It's hooked! Return EFI_SUCCESS so your driver stays in memory */
return EFI_SUCCESS;
}
5. NCC Group - Deploying Rootkits from EFI
- First phase of EFI framework
- Handling platform restart, creating temporary memory store, act as root-of-trust, pass control to PEI (pre EFI)
- Pre EFI
- Low basic low-level hardware related modules
- Invokes DXE phase
- Other ways to subvery loading of the Operating System - DreamBoot hooks/shims a boot service, but other possibilities include:
Modifying ACPI tables
Loading and SMM driver (x86-64) (god mode)
- SMM drivers remain available after
ExitBootServices
- SMM stands for
System Management Mode
aka ring -2 - SMM is a “key to defending the (Windows) hypervisor” - microsoft
- Hardware breakpoints not useable in SMM
- SMM locked at end of DXE?
- See this blog post for more
- SMM drivers remain available after
Hooking other boot/runtime services
- ATA Passthrough
6. More on SMM
- SMM phase is supported by DXE drivers implementing UEFI protocols (
EFI_SMM_ACCESS2_PROTOCL
,EFI_SMM_CONTROL2_PROTOCOL
,EFI_SMM_BASE2_PROTOCOL
,EFI_SMM_COMMUNICATION_PROTOCOL
, etc.) - Of note
EFI_SMM_CPU_IO2_PROTOCOL
‘provides CPU I/O and memory access for SMM Code.EFI_SMM_PCI_ROOT_BRIDGE_IO_PROTOCOL
‘provides basic memory, I/O, PCI configuration and DMA interfaces that are used to abstract accesses to PCI controllers...’. In System Management System Table
SMM Related Resources
Tools
UEFITool - extracting, modifying UEFI firmware images
Malware
- DeityBounce - amazing SMM
Vulnerabilities
Blog Posts
Papers and Technical Documentation
7. Source for Driver Manual Mapper from EFI
https://github.com/btbd/umap/blob/master/boot/main.c
- Hooks Windows Loader
- Hooks ImgArchStartBootApplication
- Hooks BlImgAllocateImageBuffer
- OslFwpKernelSetupPhase1
8. Key Defenses and Detection Vectors
<code>EFI_BOOT_SERVICES</code> Hooks
Unsigned EFI Allocated Kernel Drivers
Malicious SMM Drivers
SMM Isolation is a three part policy for protecting SMM and is OEM dependent. The chip is resonsible for reporting compliance to the isolation policy to the OS. On AMD, a UEFI driver `SMM Sup