edk2 + OVMF boot and runtime hook toolkit
This repository has been archived on 2020-12-23. You can view files and clone it, but you cannot make any changes to its state, such as pushing and creating new issues, pull requests or comments.
  • C 79.3%
  • Shell 19.1%
  • Makefile 1.6%
Find a file
2020-12-23 09:36:00 +00:00
edk2/NineLivesPkg fix: virtual address conversion returned success when a hook failed 2020-12-14 19:05:00 +00:00
runtime/linux fix: kernel module reported stale state after a failed refresh 2020-12-17 10:58:00 +00:00
scripts update(build): verify every host tool built during setup 2020-11-29 11:33:00 +00:00
tools fix: configuration tool ignored ioctl unlink and parse failures 2020-12-20 15:12:00 +00:00
.gitignore update: initial ninelives dxe runtime driver with entry point and serial logging 2019-03-12 09:30:00 +00:00
LICENSE update: initial ninelives dxe runtime driver with entry point and serial logging 2019-03-12 09:30:00 +00:00
Makefile update(build): clean the runtime module from the top level makefile 2020-12-23 09:36:00 +00:00
README.txt update(build): clean the runtime module from the top level makefile 2020-12-23 09:36:00 +00:00

    _   _ _       _      _ _
   | \ | (_)_ __ (_) ___| (_)_   _____  ___
   |  \| | | '_ \| |/ _ \ | \ \ / / _ \/ __|
   | |\  | | | | | |  __/ | |\ V /  __/\__ \
   |_| \_|_|_| |_|_|\___|_|_| \_/ \___||___/

                boot and runtime control flow interception
                          for edk2 firmware


ninelives is a small research framework for establishing and measuring
control flow interception primitives inside EDK II firmware. it starts at
DXE, survives ExitBootServices and SetVirtualAddressMap and keeps a piece
of itself alive into the running OS without writing to disk

the point is not the payload. the point is measuring which interception
primitive survives which phase and how many independent indicators each
one leaves behind. every primitive is selectable, the hooks can be removed,
and the whole thing is built against edk2-stable201908


<================================================================================>
what it does

five primitives, one bit each:

    P0  table    replace the LoadImage pointer in the boot services table
    P1  inline   patch the LoadImage prologue with a relocated trampoline
    P2  window   hook StartImage and ExitBootServices
    P3  runtime  hook GetVariable and SetVariable, survive into the OS
    P4  persist  keep the selected mask in NVRAM across power cycles

the default mask is 0x1d, which is table + window + runtime + persist.
inline is opt in because it is the only primitive that touches code bytes

P0 and P1 both target LoadImage. if both bits are set P1 is used and the
loader falls back to P0 when the prologue cannot be relocated

<================================================================================>
detection

nlscan reads a physical memory image, finds the EFI system table signature,
prints the boot and runtime service entry points, and diffs them against a
golden capture:

    scripts/golden.sh
    tools/nlscan out/matrix/p0_table/dump.bin --base 0x70000000 \
        --golden out/golden/dump.bin

a clean run reports indicator_count 0. a run with the default mask reports
five moved entry points:

    load_image, start_image, exit_boot_services, get_variable, set_variable

the inline primitive moves none of those and is only visible by comparing the
prologue bytes of the original function, which nlscan does as a separate
indicator


<================================================================================>
runtime observer

the state variable is readable from Linux through efivarfs:

    tools/nlcfg get
    tools/nlcfg set 0x09

kernel module:

    make -C runtime/linux
    insmod runtime/linux/ninelives_rt.ko
    cat /proc/ninelives

<================================================================================>
references

[1] UEFI specification 2.7 and 2.8, runtime services and SetVirtualAddressMap
[2] PI specification 1.6, DXE dispatch
[3] edk2-stable201908, MdeModulePkg/Core/Dxe/Image/Image.c
[4] edk2-stable201908, MdeModulePkg/Core/RuntimeDxe
[5] CHIPSEC, platform security assessment framework
[6] LoJax, ESET, 2018
[7] Beyond BIOS, second edition

<================================================================================>
credits

built on edk2 and OVMF. thanks to the people who publish bootchain research
and keep the tools open :)