# Thunderstrike at 31C3

This is an annotated version of my 31C3 talk on Thunderstrike, a significant firmware vulnerability in Apple's EFI firmware that allows untrusted code to be written to the boot ROM and can resist attempts to remove it. There is also an hour long video of the talk if you prefer to watch instead of read. If you just want the tl;dr version, you can skip to the summary of the talk or check out the FAQ and media appearances.

## Overview

In the first half of the talk we’ll go on a short adventure reverse engineering Apple’s EFI boot ROM firmware to understand how it is organized, how it is validated and how to modify it. I can promise you hex dumps, x86 assembly, some pseudo-C and a little bit of Perl. I hope that this introduction will help others with their efforts to get started with reverse engineering.

The second half describes the Thunderstrike vulnerability, which allows an attacker to flash possibly malicious code to the boot ROM given a few seconds of access to the system. We’ll walk through the development of a proof of concept and demonstrate it. And the third half is some mitigation strategies, hopefully better than epoxy in the ports.

Reverse engineering is a hobby of mine. One of my more popular projects is Magic Lantern, the open source programming environment for Canon digital SLR cameras that I started in late 2009. Last year at 30C3, Michael Zoller presented a talk on the history of it.

I’m also a big fan of retrocomputing and doing things like dumping the contents of old ROMs to look for Easter Eggs. One of the fun ones that I wrote about recently at our hackerspace, NYC Resistor, was reconstructing, from a machine we found on the side of the road, these four digital photographs of the team at Apple that worked on the Mac SE in the late 1980s.

I’d like to thank my firm, Two Sigma Investments, a high-tech hedge fund in New York city, for sponsoring this research and encouraging me to present it here. I’d especially like to thank three colleagues, Thor Simon, Viktor Dukhovni and Larry Rudolph for their assistance on this project. Now, you might ask why a finance company is interested in this sort of thing, although it is quite simple. Security.

We’re concerned about security of our computer systems. A few years ago we were considering deploying Macbooks and I was asked to use my reverse engineering experience to look into the reports of rootkits on the Mac to see if it was possible to patch the firmware to be secure against them.

So I started reading papers and watching security conference presentations. Because of the significant risk that firmware-level rootkits pose, there has been some great research into boot time security. Several of these researchers are here today at the congress and I’m honored to be presenting along with them. Almost all of them, however, have focused on Wintel and the Secure/Trusted boot code.

While only a few have been looking into Apple’s EFI firmware and things like Thunderbolt security. Snare’s excellent 2012 presentation at BlackHat was the one that started me on this project, by the way.

## The Boot ROM

Step one on this journey is to open up the MacBook and get physical access the boot ROM. Opening the MacBook isn’t the easiest thing -- Apple uses a special “pentalobe” screw that requires a special bit. I was too impatient, so I went at it the old fashioned way. For a few dollars, you should just order a P5 pentalobe from ifixit and save the finish on your pretty hardware.

Once inside we can see the marvelous job on the layout and aesthetics of the components that Apple has done. They really build beautiful machines, even if they make it so hard to get inside. As a quick tour of the hardware on this MacBook Pro, the usual path that malware takes is to come in via the wifi, exploiting some sort of buffer overflow into the RAM, which can cause code to be executed on the CPU, which will write a rootkit to the SSD.

What we're interested in today, however, is the boot ROM, over here. Not all MacBooks have the ROM easily accessible, although the 15” Pro is very easy.

Zooming in on the boot ROM chip, we can read the part number MX25L6406E and find the datasheet for the Macronix 8 MB SPI flash ROM. Everyone calls it ROM, but it is really an EEPROM since we can rewrite it. SPI stands for Serial Peripheral Interface Bus, which means that it has a clock input, serial data in and out. There are other pins for enabling the device, write protecting it, etc. Because of its importance in the boot process, it is usually write-protected against software writes.

Although the software write-protection doesn't prevent external hardware from being able to write to the chip. Using an "in system programming" device allows new contents to be flashed to the chip. Something like the general purpose Dangerous Prototypes buspirate works, but it is very slow due to the overhead of its communication protocol. It literally takes hours to reflash the entire 8 MB using the flashrom program.

Since I frequently read and write to ROMs, I've designed a special-purpose [[SPI flash reader/writer using a Teensy, which is sort of like an Arduino. This device can read the chip in tens of seconds, write it in less than a minute. And in place of the fiddly test-clips, it uses an SOIC chipclip to hookup all 8 pins instantly. Sources and schematics are availabe from bitbucket.org/hudson/spiflash.

One important point if you are doing this sort of in system programming: unplug the battery from the logic board so that there aren't any other voltages on the power rails.

## ROM rewriting

Previous attempts by researchers to write new code into the ROM have failed and left the machines "bricked". There have been suspicion that there is some sort of signature check going on when the machine boots, or perhaps an auxiliary coprocessor that does the validation.

But this was all allegedly... I was very curious what was causing this, so let's replicate snare's results by flashing a firmware with a single byte changed in the ROM somewhere.. . And this is the result, possibly a \$2500 mistake. This laptop has been "bricked" due to our single byte change in the ROM -- when it is powered on there are no lights, no sounds, no indication of function. There are no outward signs of life, but what is happening on the inside?

Let's flip it over, remove the cover and power it on. We see the CPU cooling fans spin up .. and then spin down a few seconds later. So there is a brief sign of life inside.

This means that something is checking the contents of the ROM and powering down the system when it detects our modification. But is it hardware or software? One way to determine if it is software would be to try modify the code before it does the check. One idea would be to change the very first instruction the CPU executes when it boots up.

To find out where that instruction is, we go way back to the early 80s. It is funny how even the most modern x86-64 boots up as a 8088 in 16-bit real mode. This is will not be our only detour to the 1980s in this talk...

The first instruction is at the very last 16-bytes of low memory at 0xFFFF0 and is typically a direct jump instruction to the actual startup code somewhere lower in memory.

Now let's disassemble the ROM dump that we've made using our in-system programmer or flashrom. We see that it does a wbinvd to invalidate the cache, which is somewhat newer than the 1980s, followed by a jump to some more initialization code.

What if we changed the destination of that jump instruction to an infinite loop instead by making it jump to itself?

When we power on the machine after flashing this modified ROM with our infinite loop using the in-system programmer, there are two possibilities:

• If there is some sort of external hardware that checks the ROM contents, it will spin down the fans as before. That would be great for security.

• But if the fans stay on (and nothing else happens), then it is an indication that the modified ROM code is running and there is no external check of the contents, only a software check.

It is probably no surprise what happened, since I'm giving this presentation... Yes, the fans stay on and this gives us a way to get one-bit of output from the system before any of the rest of the hardware has been initialized. This is a really great reverse engineering technique that I use frequently -- drop an infinite loop into the system somewhere and the lock-up becomes a way to signal that the modified code was reached.

But more importantly, it indicates to us that there is no TPM or other hardware doing external checks on the contents of the ROM. This means that once modifications have been written to the chip, they will not be checked again. Incidentally, Apple used to have a TPM on their motherboards, but it was never used and disappeared sometime ago.

To sum up what we know now:

• We can make trivial changes to the ROM and verify that they work.
• And that there is no external hardware checking the validity of the ROM.

## Boot ROM organization

Which leads us back to the question: how is the ROM validated? In order to figure this out, we need to know how the ROM is organized. Since we know that Apple has derived their boot ROM code from the Intel EFI reference implementation, we can turn to that specification.

In the firmware volume block specification, there is a structure definition for the firmware volume header. The "signature" member sounds like it might be involved, but it is not a cryptographic signature, it is literally just the constant '_FVH'. The checksum doesn't cover the data, just the header. There is also this member ZeroVector, which is for xscale startup and doesn’t seem to have well defined real use.

So let's hexdump the first few bytes of the firmware volume at 0x7F0000, which correspond to the top 64 KB of the ROM. This would be the one that contains the boot code that we've just modified. The _FVH signature bytes are easily seen and the checksum only covers the highlighted 0x48 bytes of header.

Now the ZeroVector is interesting; while the first 8 bytes are the same in all the firmware volumes, but the last 8 bytes vary between each volume.

One nice thing about a constant string like _FVH is that we can search through the ROM for where it occurs, like here at offset 0x6fae9c. It is somewhat odd how few strings there are in this ROM, but there are some nearby, such as this very, very interesting string "RomIntegrity.c". So let's fire up Hopper, our interactive disassembler on the region that contains those strings..

Here is Hopper's disasembly of that portion of the ROM, with the address mapping fixed up to put it into 32-bit mode at 0xFF800000. First there is a comparison with the '_FVH' signature to the field at offset 0x28, which makes sense. Then there is a chunk that does some math on the length of the volume and calls a function on it.

Translating that portion into pseudo code, we get something like block. The interesting part is that the result of this function is compared to the second 8 bytes in the zero vector, which helps reinforce our idea that there is something special there.

So let's use the interactive feature of the disssembler to step into that function, 0xfff9a81f. It does a bunch of stuff in a loop over this table pointer, 32-bits at a time.

Looking at that table we find that it contains lots of "random" hex values. When faced with this sort of thing, a good choice is to toss one of them to your favorite search engine. Rudolph Marek suggested the same technique last night to track down the SMU hashing function as SHA1.

And we get a few good hits, with the first 32-bit value as well as the rest of them. We don't need to do much more reverse engineering on this function: we can declare it to be CRC32.

It is pretty straight forward to try changing a single byte and fixing up the CRC by hand, which allows our system to boot. At this point we can conclusively say that Apple has added their own CRC32 boot-time check on the contents of the firmware volume and that is why changing a single byte in the ROM makes the system shutdown.

It is important to stress that CRC32 is not a cryptographic checksum -- it is only to verify that the contents of the ROM have been correctly flashed and that they haven't been accidentally corrupted. This doesn't provide any security since computing the correct CRC and writing it into the header will allow the ROM to validate. Just be sure to fixup the EFI header checksum afterwards and everything will work fine.

You might ask why are there no cryptographic checks in the software at boot time? Other researchers have asked the same question and also found that for the most part UEFI flash components are only validated during updates. One possible conclusion is that this is a trade off for faster boot times. Although I'm not certain that this is accurate -- the crc computation takes time and requires about the same number of reads.

In actuality, any software-only validation is doomed to fail since if an attacker can get code into the ROM, they can just skip that software validation. Either by always returning true or by returning a cached value computed over the boot ROM. Without some sort of hardware cryptographic signature checks or an actual, unchangable mask ROM, this sort of software-only attempt is futile.

## Where are all the strings?

So, where are the strings? As we had discovered earlier, there aren't very many readable strings in the ROM. Using a tool like binwalk we can generate a graph of the entropy of the ROM dump. Other the NVRAM and the early boot code, most of it appears to have very high entropy, which could indicate encryption or compression.

To figure out what part of the ROM dump we should focus on, we can use flashrom to read the flash descriptor and give us a hint for where to look. The BIOS region at 0x190000 is what interests us; this includes all the way to the end of the chip that contains the early boot code.

So let's take a look at the first file in firmware volume after the header at 0x190000. Once again we return to the EFI firmware volume specification. The first three bytes are the size of the section, about 15 KB, andt he next byte is the section type, 0x01 indicates a compressed section. That's good news.

So we go to the EFI compression section specification and see that the next four bytes encode the uncompressed size of 36 KB. The next byte has the compression type is, 0x02, which according to the spec is... Not there. That's not good.

However, I observed that the next few bytes are the same in all of the compressed sections.

So let's toss those four bytes into a search engine, and we get an exact match for LZMA compressed at level 7. That's good news again. Let's test it.

Using dd we can extract the compressed bytes of data from the section, while skipping the section header, and pipe it through lzcat to attempt to decompress it.

There are no complaints from lzcat. Good. And the sizes check out with what were in the header. Also great.

And look at all those marvelous human readable strings in the uncompressed file. These printf()-style format strings are an absolute gold mine for reverse engineering. They are the sign posts that we can use to make sense of what is going on in large blocks of disassembly.

We now know how to deconstruct and re-assemble the firmware volumes in the ROM using Apple's "custom" decompression system. This is great -- there are hundreds of files in the ROM and we can finally start to make sense of them. Apple’s compression system surely has been known to other researchers, but I haven't seen it in any formal presentations and wanted to be sure to write it down where other security researchers can find it to make faster progress on their own projects..

## Why can't software write to the boot ROM?

While we can write to the boot ROM using our in-system programmer, software can't usually write changes to it. This is because in a modern system the SPI flash is not directly connected to the CPU, but instead goes through the Platform Controller Hub (PCH) and has access control by the Management Engine (ME). The ME prevents writes to the flash once it has been locked, although when the system boots the flash initially comes up in an unlocked mode.

As a result, the UEFI forum recommends that the firmware regions be locked as early as possible. Apple does appear to do this quite early in the PEI phase of their EFI boot. The locking is done via registers like FLOCKDN, which prevent changes to the permission bits on the flash and can only be unlocked by doing a full system reboot.

Which leads us to ask how does Apple update the flash? The fairly regularly releases firmware updates for their EFI firmware and SMC. They have a fancy GUI for updating the firmware that verifies the version matches the hardware you’re attempting to install it on, walks the user through the process, etc.

Under the covers, however, it is running a command line utility called bless on the SCAP file that is in the downloaded firmware update package. bless will copy the file to the EFI recovery partition and sets an EFI NVRAM variable named efi-apple-recovery that points to the SCAP file on disk.

It is important to note that bless doesn't do any validation of the SCAP file; if you bless a bad file, you get a bricked machine that will be stuck in an infinite reboot loop. Rewriting the NVRAM in the flash from an ISP seems to fix it, so only do this if you’ve successfully been able to write to the ROM with an ISP.

## What is in Apple's SCAP file?

Let's look at a dump of the first few bytes of an SCAP file to figure out what is inside of it. The _FVH signature is easily spotted, although it starts in the file at offset 0x50, which appears in the header, amongst all the zeros. We can see the firmware volume size, about 8 MB, in the fvh header, and what appears to be the total SCAP file size, 0x270 bytes larger than the firmware volume, which means there is a 0x220 byte trailer.

One thing that makes EFI reverse engineering occasionally easier is that most things have 128-bit GUIDs at the start of structs that are easy to search for.

So, we toss that GUID into the search engine and up comes yet another EFI specification document with the matching GUID. The header size and capsule file size, as we suspected, are defined here. The rest are all zero, so we can ignore them.

Since we computed that there was a 0x220 byte trailer at the end of the file, let's take a look at it. The all 0xFF's are to be expected for a region since that is the default state of a flash ROM. The rest of the trailer appears to be random with nothing human readable, so on the off chance that this is yet another GUID, let's toss it into a search. The only real hit, as of mid 2014, was this mailing list post.

The EDK II / TianoCore code is the reference UEFI implementation; Apple split their EFI firmware from this reference implementation many years ago, although they seem to have backported some number of features. This mailing list post is only a few months ago, but Apple has been using this GUID for many years.

The post defined a struct for RSA2048 SHA256 certificate blocks which will be 0x210 bytes long, which matches pretty closely to the trailer on the SCAP file.

Based on these hints, I wrote a short Perl program to test this signature scheme. It extracts the firmware volume, RSA public key and signature from the SCAP file, generates a OpenSSL key using the default RSA export and, thanks to Victor for the insight, the byte-swapped raw key bytes. Why Apple uses little-endian, while everything else uses big-endian, is another mystery.

In any event, the signature check works!

Now we know that the SCAP files are signed with RSA and that the signatures are checked sometime during a recovery mode boot before they are flashed to the ROM. Again, I’m probably not the first person to figure this out, but it doesn’t seem to have been written down anywhere.

## Where are the SCAP files' RSA signatures checked?

But this leads us to ask, where are the RSA signatures on the firmware update files checked? We know that bless doesn’t do it -- you can bless arbitrary junk and brick your machine when the signature doesn’t check out. This we’ve learned the hard way... The question is if they are being validated by some piece of harwdare like the Intel ME or SMC, or, as with the crc32 at boot, are only verified by x86 software stored in the ROM.

Let's find if there are any software functions in the now uncompressed ROM that reference the SHA hash or RSA GUIDs. If we binary grep through the ROM for those GUIDs, we find this file that contains all three of them.

Here is the code in that file that references them. It compares the two GUIDs to the ones in the SCAP file that has been read into memory, as well as does a sanity check on the file size. It also refers to the DXE services table by GUID.

Looking at the cross references for that GUID, we find this code later in the file that makes a function call, via a function pointer in the DXE services table, passing in the pointer to copy of the firmware volume in RAM.

Once again we turn to the EFI specification and, since it gives us a struct, we must count entries to find what is at offset 0x98. The function ProcessFirmwareVolume(), which will "mount" the RAM copy of the firmware volume and make it available to the other modules.

If that succeeds, it then call another function pointer in the table at offset 0x80, which again we can count to find Dispatch(). This will execute any new executable sections in the firmware volume that we just mounted.

This assembly is hard to follow, So let's translate all of this into some sort of pseudo-code. This code checks the GUIDs are checked, computes the SHA hash and checks RSA signature on it, and if both of these pass, then calls ProcessFirmwareVolume and Dispatch via the DXE services table.

We still don't know if the ME is also checking the signatures before it allows the firmware write to procede, but what we can do is generate our own ROM images to experiment. So let's NOP out the portion of the code that does the RSA signature check, write that version to the ROM with our in system programmer and attempt to update an SCAP file with a bad signature.

The trailer of the test SCAP that we'll flash looks like this. The GUIDs and public key are there (although we’ve determined experimentally that the actual public key used comes from the boot ROM, not the file). However the RSA signature is obviously not valid.

When we bless this SCAP file and reboot, if the SMC or ME are checking the signature it will brick the laptop and we'll have to recover somehow. But if there is no ME verification, then we're good to keep exploring...

I'm a little bit surprised this time -- the firmware update inside the SCAP is executed and reflashes the boot ROM, despite the invalid signature on the file. It seems to me that this is lots of trust in the correctness of the firmware code.

So we can amend this last point -- we now know that the x86 alone is responsible for verifying the signatures during a recovery mode boot.

This still required physical access to the inside of the machine to hook up the, which might be doable for certain targeted access operations, but would be tough for a normal evil-maid or border crossing. Could this sort of thing be done from the outside of the laptop?

It turns out that the Thunderbolt port gives us a way to get code running when the system boots. Thunderbolt brings the PCIe bus to the outside world and at boot time the EFI firmware asks attached devices if they have any Option ROMs to be run.

Once again we can return to the 1980s to find out what an Option ROM is. The classic IBM PC, the very first one, used an Intel 8088 with the BIOS stored in an ROM and six sockets for optional expansion ROMs, to hold things like BASIC and support for different hardware devices

ROMs could also be on the cards in the ISA bus. The BIOS was typically a mask rom and could not be changed, while the option roms were frequently UV erasable EPROMs. The BIOS would execute any code stored on the ROMs during bootup to initialize expansion cards.

Using Option ROMs offensively isn't even a new attack idea. Jon Heasman first presented the idea in 2007 at BlackHat. And snare demonstrated a pretty damn awesome OSX rootkit using a Thunderbolt Option ROM in 2012. Despite the two years and multiple Radar bugs later, this vulnerability is still present in the most recent MacBooks.

The Option ROM attacks works like this: a Thunderbolt device that has been flashed with the exploit is plugged in and the system booted. The attacker's code can hook any EFI or OS functions and do things like bypass firmware passwords, log keystrokes, install kernel backdoors, etc. This is the evil-maid attack described by Snare over two years ago, although this is not Thunderstrike: while an attacker can install a root kit to the drive, the Option ROM was loaded too late from the external device to be able to rewrite the ROM.

It is a requirement, by the way, that all EFI presentations include this graph.

In the modern EFI/UEFI era, the Option ROMs are loaded during the DXE phase and will still be executed in ring 0, although this is after the flash is locked by the early boot code running during the PEI phase. Except the flash is left unlocked when the system is performing a firmware update, and we've determined that the executable in the SCAP file that runs the firmware update is executed in the 64-bit DXE phase, the same as the Option ROMs, which leads us to the next question...

Are Option ROMs loaded during firmware updates? We can reuse the infinite loop fan trick to find out. I flashed an option ROM with this main routine, which, due to the single threaded EFI firmware, will hang the system if it is run.

I blessed a valid SCAP file, plugged in the device with the infinite loop and rebooted the machine. If the Option ROM is not loaded, the firmware update will proceed as normal and the machine is secure against this attack. Or the fans might keep spinning while the machine appears to be bricked, which means that the option ROM was loaded and we have a way to inject code into the recovery boot process.

Yes, option ROMs are loaded during the recovery mode boot.

But, it turns out that there is another check of the signature that is done before the 64-bit OptionROMs are loaded, possibly in PEI phase or 32-bit mode. This is a roadblock.

## How can the signature check be bypassed?

If we go back to the pseudo-code for the 64-bit version that actually does the flashing, - we can recall that ProcessFirmwareVolume is called by a function pointer, which is in RAM, not ROM.

This means that the Option ROM can “hook”, or replace ProcessFirmwareVolume in the DXE services table with a function pointer of its own that can modify the firmware volume after it has had its RSA signature checked, but before it is "mounted", allowing the attacker to substitute their own firmware for the official Apple one.

For an attacker with sufficient Option ROM space, the job is done: put your payload in the device’s ROM, pass a pointer to it to process firmware volume and it will be flashed for you.

Unfortunately the Broadcom in the thunderbolt adapter in our proof of concept only has a few KB, not MB of option rom. So we take a slightly different approach, which also gives us another important capability. We realized that we don't need to replace the entire ROM, just enough to allow us to use Apple's own update tools.

Also note that you don't need to disassemble the Thunderbolt adapter to rewrite its Option ROM: edk2/EfiRom will convert a PE executable to the ROM format and then the b57udiag.exe tool will compress and write it to the adapter.

The replacement ProcessFirmwareVolume() doesn't replace the entire volume, just Apple's RSA key in the image that will be flashed to the ROM. When it is called to process the firmware volume, it searches through it to find a matching GUID for Apple's RSA key ring. If this file is present, the attack copies the 256 bytes of an RSA public key that we control over Apple's public key that they use to sign firmware updates. It then fixes up the firmware file's checksums and the enclosing firmware volume crc32. And lastly it calls the original ProcessFirmwareVolume() to mount the modified volume with our key in place.

A valid SCAP file is blessed and the system is booted with the Thunderbolt device with the OptionROM exploit attached. The Option ROM could also initiate a recovery mode reboot on its own, although the proof-of-concept doesn't do this. Apple's ROM validates the signature of the SCAP file, and then calls the exploit's ProcessFirmwareVolume in place of the official one. The proof of concept is not concerned about stealth, so it prints lots of debugging messages. After the exploit replaces the RSA public key in the RAM copy of the SCAP firmware image, it then jumps into the real flasher, which will write our RSA key to the boot ROM.

And that's the Thunderstrike exploit. Since the public RSA key in the boot ROM is now one that we control, only updates that are signed by our private key can be used to update the firmware. It could be much stealthier -- this is just a POC that demonstrates the vulnerability, so we have it display a message in the ROM on the firmware lock screen to let you know that it has been installed. A weaponized version of this would not give any indication that it had taken over the boot ROM.

So this is the Thunderstrike vulnerability: Option ROMs can circumvent flash security by triggering recovery mode boots with signed firmware and causing the untrusted code to be written to the ROM. And the attacker now controls the signing keys on future firmware updates, preventing any software attempts to remove them. The Thunderstrike POC also disables Option ROMs, so it can’t be removed by a similar technique.

## How would Thunderstrike be deployed?

One way that a weaponized version of Thunderstrike could be installed is through something like NSA TAO-style operations. They could intercept hardware in shipment and replace it with ones with modified ROMs.

The classic "evil-maid" attacks also are feasible. Given a few minutes alone with your laptop, Thunderstrike allows the boot ROM firmware to be replaced, regardless of firmware passwords or disk encryption. So while you are getting breakfast at the hotel during a conference and leave the machine in your room and house-cleaning comes by to make up the bed, install the firmware backdoors, and replace the towels.

Alternatively, while you are crossing an international border they can ask to see your laptop, and they can examine it while they ask you to please step into a private room for a few questions. In the US there are no rules about the TSA searching (and perhaps secretly modifying) your laptop. In fact they consider laptops to be the most dangerous contraband to be worthy of examination.

Thunderstrike in its current form has been effective against every MacBook Pro/Air/Retina with Thunderbolt that I’ve tested, which is most models since 2011. The proof of concept is hardcoded for the 10,1 system, but the underlying vulnerability seems to be present and is independent of OS X version. Weaponization to attack all the different models is within the means of a dedicated attacker.

Pre-Thunderbolt devices are not affected by Thunderstrike, nor are Apple machines that contain mask ROMs.

Potentially it gets even worse. Remember Stuxnet? It spread via infected USB drives and was able to invade deep into the Iranian nuclear refineries, across air-gap security perimeters.

The Thunderstrike bootkit is also in a position to be able to flash new Option ROMs into attached Thunderbolt devices with its own exploit. Like Stuxnet, this capability allows it to spread virally across air-gap security perimeters through shared peripheral devices. Since so few users need the Option ROMs, the device remains fully functional, despite carrying the malicious payload. Implementing this functionality would need a minor amount of work to weaponize and port to various devices, but an attacker of modest means could easily do so.

So we now know that Thunderstrike could affect all current MacBook systems and can spread virally.

## How do we prevent Thunderstrike?

Apple has a partial fix that they have started shipping in the new Mac Mini's and iMac Retinas, and they plan to release it for older Macs soon as a firmware update. Their fix is to not load Option ROMs during firmware updates, which is effective against the current proof-of-concept.

However... it is not a complete fix. Option ROMs are still loaded on normal boots, allowing snare's 2012 attack to continue working. Older Macs are subject to downgrade attacks by "updating" to a vulnerable firmware version.

And a Thunderstrike v2 could use the new "Dark Jedi Sleep" attack.

What is the Dark Jedi attack? I just learned about it last night at Rafal and Corey’s excellent talk here at CCC. Folllowing a S3 sleep, the system restarts with the FLOCKDN register that we discussed earlier and all the other BIOS protection registers unlocked. This means that the Option ROM can arrange for arbitrary code can be run in PEI before anything is locked, allowing trivial rewrites to the flash. Thunderbolt Option ROMs can do all this without having to mess around with SCAP files and signatures or anything.

If Apple revised their hardware to include Trusted Boot hardware again -- they used to have TPM chips, but never used them and removed them in more recent models, they could at least detect this sort of error. It's not perfect, as we can tell from all of the presentations into circumventing the various forms of secure boot, but it is a good first step.

If they really need to support Option ROMs on Thunderbolt, Apple could implement the EFI architecture specific security protocol to enforce driver signing -- PCIe OptionROMs can be signed and checked before they are executed.

They do actually implement the protocol, but here's the pseudo-code for the entire implementation. However, "Proto" can never be NULL, so this always returns EFI_SUCCESS and approves all files.

If you don’t need Option ROMs, and I would wager that the vast majority of users do not, you can build your own ROM image with them disabled. This is a two byte patch to jump around the call to ProcessOptionRom. You had better believe that all of my machines have this modification and the firmware flashed by the Thunderstrike proof of concept also patches it.

Even disabling Option ROMs alone might not be sufficient since the Thunderbolt port still is subject to active DMA attacks. The ALLOYVIPER decoy VGA adapter passes through to a real VGA adapter, but also connects to a SLOTSCREAMER PCIe card that can install backdoors into a running OSX system and likely be used to springboard a Thunderstrike style firmware update. How many of you here plugged into the projector and might have fallen into an evil-conference-organizer attack?

Disabling PCIe on Thunderbolt is doable, although it would require more information and time than I had when I was doing my security research. This would be easier for Apple to do and offer as a security option, just like they disable booting from removable media when a firmware password is set.

You can also go medieval on it, as Peter Stuge suggested last year at 30c3. He showed how to hard-wire the flash to be read-only, make sure other controllers couldn’t be reprogrammed, removed devices that had DMA capabilities, etc. Likewise, epoxy in the thunderbolt port might work, for some of the attacks that we know about today (but not necessarily tomorrow’s...)

Once you've taken that sort of radical hardware modification step, you should also take Eric Michaud's advice and use glitter nail polish on the screws to detect unauthorized opening of the case; otherwise the NSA TAO might do an in-system-programming attack on your boot ROM.

## Summary

How bad could a weaponized version of the Thunderstrike bootkit be? Since it is the first OS X firmware bootkit, there is nothing currently scanning for its presence. It controls the system from the very first instruction, which allows it to log keystrokes, including disk encryption keys, place backdoors into the OS X kernel and bypass firmware passwords. It can't be removed by software since it controls the signing keys and update routines. Reinstallation of OS X won't remove it. Replacing the SSD won't remove it since there is nothing stored on the drive.

It could also be very stealthy and hide in system management mode, through virtualization or possibly in the Management Engine (although there is lots of work to be done there). It can spread virally through shared Thunderbolt devices and infect new ones that it encounters. And it can affect all current MacBooks with Thunderbolt; with minor modifications it could affect Mac Minis and iMac Retinas with Apple's fixed firmware.

And I believe it could be remotely installable by using tricks like Dark Jedi Coma or Option ROMs installed in other devices in the system.

On that cheerful summary, I'll take any questions now. You can email them to me, hudson@trmm.net, preferably encrypted with PGP. I also have written a Thunderstrike FAQ that covers many of the common questions. I look forward to seeing you all again at 32C3 next year.

Note: there was an audience Q&A session after the talk. I haven't transcribed the questions, but plan to eventually.

Last update: November 8, 2020