понедельник, 15 июля 2013 г.

Windows RT and UEFI thoughts

As there is no jailbreak for 8.1 - I've started to look for other ways of running unsigned code on Windows RT tablets.
My main idea is the following: UEFI provides Windows several runtime services, like "SetVariable". Those services are located in RAM as their code needs to be relocated at runtime when virtual address mapping changes, and RAM can be easily patched from driver. And we can already run our own unsigned drivers under Windows RT 8.0.

So as a first investigation, I've made a Windows "complete memory" crashdump and started to look for the runtime services signature:
#define EFI_RUNTIME_SERVICES_SIGNATURE 0x56524553544e5552 
It is "RUNTSERV" in ASCII. This should give a pointer to UEFI runtime services to call them from my future driver. And I was really disappointed not to find such a sting at all. I know that the string is present in RAM, but not in a crashdump I've made. There may be two reasons - Windows crashdumps only memory that it "owns", or that memory region is not mapped at all.

So the second attempt was to make a driver that maps physical memory with MmMapIoSpace and provides an interface to read/write it from user mode. As Microsoft was kind enough to give us Windows 8.1 WDK - process was easy. Those who are interested may see the driver and test program sources here. And Windows RT precompiled binaries here. Sources are based on Microsoft's "toaster" driver, so don't wonder the device name.
Program dumps the given amount of RAM starting from a given address to disk. As we on Terga have 2 gb physical memory starting at 0x80000000 - the whole memory range could be dumped with "dumper.exe 80000000 80000000" (addr and length in hex). There is a small internal RAM on CPU at 0x40000000, but there is nothing interesting there.

What interesting can you see from a dump? there are all UEFI variables, including the ones accessible only in boot mode, obviously PK, KEK and other certificates: 

You can see the BootXXXX bootmenu entries, "SecureBoot" and "PK" keys on the screenshot. GUID is located before, the value is after a unicode variable name.
And for some reason the whole decompressed contents of firmware volumes (FV0: and FV1:) is present in RAM. So you can "extract" EFI modules to analyze them later, look after 0xFF000000 addresses for strings like "/home/cca/TF600T/Tp1201/TF600T-ASUS-1101/Build/TF600TTZ/RELEASE_ARMLINUXGCC/ARM/MdeModulePkg/Universal/Console/ConPlatformDxe/ConPlatformDxe/DEBUG/ConPlatformDxe.dll".

To test the "main" idea of patching UEFI data in RAM - I've made a small tool that patches given addresses RAM, modified "SecureBoot" and "SetupMode" variables to zero - and got nothing extraordinary. I was still unable to erase PK or KEK. Then I've modified the same tool to scan for PK or KEK and replace all their occurrences with my own certificate - even after that I was unable to add a new key to DB signed with that cert. Now I think that all UEFI variables are reread from NVRam when needed and not cached in RAM for too long.

The next step would be to reverse engineer and patch the SetVariable code, so that it would never check for a valid signature. But I'll do that later, as I've already found an interesting thing on Asus and playing with it now.

Commenting is closed for this topic, more info may be published on XDA.