Abusing EFI Variables and the AMT

Speculation on How EFI was Modified:

By simply having Ring 0 (kernel mode) one can place EFI variables into NVRAM via EFI runtime services. If one of these variables is scanned as a valid FFV, that gives execute at level of Ring -1, from there modifying the SPI contents of the flash chip to re-write the Intel ME / Intel Gigabit Ethernet is possible. By flashing an old version of the Intel ME (orbetter the Intel AMT) one can take advantage of known CVEs in the Intel ME giving Ring -3. From here one can inject any SMBios of their choosing and maintain Ring -2 every boot. This allows for a evil actor to run their own stack during any OS load or reinstall. By using AMT ramdisks, EFI drivers, and modifying the ACPI tables they can then live in Ring 0 cooperatively with any OS that is installed.

Booting Into a Decent Shell

After some working around various issues I finally got into a decent EFI v2.2 shell. The first five entries in the handle table were what are known as “FFV” or flash-firmware-volume entries. This implies that the lion share of this is happening one of two ways: the flash chip has been somehow updated to a version of EFI that it should not contain, or two that something is persisting to disk and performing a restore in a way that it is not possible to reset with only pulling the power cable out of the device. It is clearly running vPro and the AMT stack, and has created an entry of a ramdisk entry (shows in the table) as well as loading a number of drivers and Dxe’s that are to say the least, unexpected. From a running linux view the following EFI vars were observed, not matching in any way what was pulled from the shell: https://gist.githubusercontent.com/rickmark/21059379ab65c11bfcb2f3b339bdbea1/raw/7a0d2a60f38cdc1bf7887df1e7e461474dced25c/refi_var_list.txt

Asking the device for the listing of devices shows

     
Seg:Bus:Dev:Func Ven:Dev Description
00:00:00:00 8086:3ED0 Bridge Device - Host/PCI bridge
00:00:02:00 8086:3EA5 Display Controller - VGA/8514
00:00:08:00 8086:1911 Other System Peripheral (Gaussian Mixture Model?)
00:00:12:00 8086:9DF9 Other DAQ & SP controllers
00:00:14:00 8086:9DED USB Controller
00:00:14:02 8086:9DED RAM Memory Controller (Interface 30)
00:00:16:00 8086:9DE0 Simple Communications Controller
00:00:17:00 8086:9DD3 Mass Storage SATA (interface 1)
00:00:1D:00 8086:9DB0 Bridge Device PCI/PCI
00:00:1F:00 8086:9D84 Bridge Device PCI/ISA bridge
00:00:1F:04 8086:9DA3 SMBus Controller
00:00:1F:05 8086:9DA4 Serial Bus Controllers
00:00:1F:06 8086:15BE Network Controller
00:01:00:00 144D:A808 Mass Storage Controller - NV memory subsystem

The following does skip some entries as there’s no good way to copy and paste this, and UDIDs are hard…

Open Questions:

Useful non-Network Control Channels

Using accessibility systems like brltty over bluetooth can give terminal access without need of a reliable network (WiFior ethernet).

Early Injection using Firewire Serial

Messing with the ACPI Tables

People often forget that operating systems will happily collect data from ACPI including AML code. This is usually executed during power events like suspend and resume and has been abused in the past in the form of “dark wake” attacks.

Hiding from Root Using the Linux BFP LSM

One of the more recent advancements in the Linux tree is reusing eBPF (yes of note because it has been used for network firewalls for many years) to become a policy agent. eBPF was selected because it is a Turing complete language that we already compile and execute in-kernel by way of ip_tables/x_tables and the like. When auditing is enabled, loading and unloading of these BPF programs will become part of the kernel debug output so they can be observed. You can actually “mount” this to see the BPF entries by executing mount bpffs /mnt/bpffs/ -t bpf which will provide maps.debug and progs.debug. Another useful tool to get more information about this is bpftool prog show

Xen Para-virtualization is Still a Thing

Even without using Intel’s VT, it is still very possible for an attacker to kexec into a Xen based kernel providing themselves a way to control non-virtual ring-0 even while still letting an arbitrary linux guest OS execute thinking it is the kernel of the system. Even without kexec one can do about exactly the same thing using kgdb after transferring an image to memory.

Tampering During Compile