Here is something to hate me…

I had a meeting yesterday evening with some organisation and these people offered me $50,000 – in a bag – to take over computers running Mavericks, Yosemite and El Capitan. All legally of course. Right. Man that is insane! Do I look like a drug dealer or something?

Update: For clarity. I won’t help this unnamed organisation, but not that it matters because I was informed earlier today that somebody else (some company) in the hack scene stepped in. Good for them. Not that I case, because I don’t have time for this kind of stuff anymore.

Pike signing off… I have work to do

Advertisement

Apple’s kext signing bypassed…

I have found a very simple way to bypass Apple’s kext signing in El Capitan, like I did before in Yosemite and Mavericks before that. This time I did it differently, and this blog post is a short and simple POC (proof of concept) to show you that bypassing Apple’s rather strict kext signing restrictions still works. Even in El Capitan DP5. This means that I run my hack with maximum System Integrity Protection (SIP) activated (no rootless=0 boot argument/runtime/NVRAM variables to bypass the code signing restrictions) with the following unsigned kexts:

/Extra/Extensions/AppleHDA892.kext
/Extra/Extensions/AppleIntelE1000e.kext
/Extra/Extensions/AppleEmulator.kext (your FakeSMC.kext)

I use /Extra/Extensions for unsigned kexts, so that the /Library/Extensions and /System/Library/Extensions directories can be kept vanilla/untouched. This way unsigned kexts won’t show up in System Information/Software/Extensions, which in my view makes it somewhat harder to detect. Sure. Running kextstat does shows all loaded kexts, so it’s not that hidden, but cleaner anyway. We could add another hack to hide kexts in kextstat, and that makes it even worse.

A Little Background Info
OS X won’t load/execute unsigned kexts, unless you use kext-dev-mode=1 in Mavericks and Yosemite for /Library/Extensions, but this setting is obsolete in El Capitan so you either have to use rootless=0 (now also obsolete in El Capitan) or all unsigned kexts will fail to load. Another option is to use the Security Configurator utility to toggle a checkbox, or run csrutil [enable/disable] from the Recovery OS.

Screenshot of the SecurityConfiguration App

Apple already said that rootless=0 will be absolute, in due time, and then we have to use the Security Configurator… or use a boot loader that sets boot flag CSR_ALLOW_UNTRUSTED_KEXTS to allow unsigned kexts 😉

#ifndef CSR_VALID_FLAGS
	/* Rootless configuration flags */
	#define CSR_ALLOW_UNTRUSTED_KEXTS		(1 << 0)	// 1
	#define CSR_ALLOW_UNRESTRICTED_FS		(1 << 1)	// 2
	#define CSR_ALLOW_TASK_FOR_PID			(1 << 2)	// 4
	#define CSR_ALLOW_KERNEL_DEBUGGER		(1 << 3)	// 8
	#define CSR_ALLOW_APPLE_INTERNAL		(1 << 4)	// 16
	#define CSR_ALLOW_UNRESTRICTED_DTRACE	(1 << 5)	// 32
	#define CSR_ALLOW_UNRESTRICTED_NVRAM	(1 << 6)	// 64

	#define CSR_VALID_FLAGS (CSR_ALLOW_UNTRUSTED_KEXTS | \
			CSR_ALLOW_UNRESTRICTED_FS | \
			CSR_ALLOW_TASK_FOR_PID | \
			CSR_ALLOW_KERNEL_DEBUGGER | \
			CSR_ALLOW_APPLE_INTERNAL | \
			CSR_ALLOW_UNRESTRICTED_DTRACE | \
			CSR_ALLOW_UNRESTRICTED_NVRAM)
#endif

This is also what I use for the third Developer Preview of El Capitan in RevoBoot and the Enoch branch of Chameleon. Slice, the Clover project owner and main developer, also recently implemented a Clover option to set the NVRAM key csr-active-config (see nvram -xp).

Kext Injection
Some boot loaders can inject kexts, like FakeSMC.kext, but RevoBoot is not one of them. That will certainly change now that I have seen the use of it. Anyway. Clover kext injection used to work, but works differently than what I envision, and now also fails in DP4. This was why I looked into it, to see if I could find a workaround, so that the Clover developers can solve this issue. A group of Clover users even offered me to pay a 1800 Euro bounty (2000 Dollar), but I declined their offer.

Prelinkedkernel
The prelinkedkernel is located in /System/Library/prelinkedkernels and is loaded by boot.efi, or in case of a legacy boot loader.. the boot loader. Not that it really matters for this POC but anyway. The prelinkedkernel replaces the old /System/Library/Caches/com.apple.kext.caches/Startup/kernelcache and is compressed with LZSS. The former with LZVN – I blogged about changing the compression type and the new, at that time, LZVN compression here OS X 10.10 Yosemite DP1 kernel(cache).

Tools
I use a self written command line tool called LZVN to unpack and repack the prelinkedkernel, but the current version needs a few small changes to automate the process of unpacking, repacking, calculating the adler32, fixing the offset and size of the (un)compressed file.

Bootloader
I use RevoBoot as my primary boot loader of choice for my Hack, but it can’t inject kexts. Not yet that it, but adding support for it would have been a lot of work, and that is why I chose to modify the prelinkedkernel instead. For this to work I added a “Kernel Cache” property in /Library/Preferences/com.apple.Boot.plist with a string value pointing to the modified prelinkedkernel. This way RevoBoot loads that instead of the normal prelinkedkernel. And it does that just like any other booter would do, including boot.efi

Sure. What you want is a boot loader that can inject the required kext for you. Something that Clover and Chameleon can do for quite some time already, so please keep using the boot loader of your choice. I don’t care. Really. I only shared my view on this matter, and used RevoBoot because that makes things easier for me. Thing is. Since this works with a modified copy of a prelinkedkernel, then it will work with my type of kext injection. Someone just need to write/patch the code for it.

Kext Injection
Like I said earlier; RevoBoot cannot inject kext and the main reason for this is twofold.
1) I had no need for it.
2) I like to write my own code.

Nope. Nobody learns anything from a simple copy/paste action, and thus that won’t happen. I also want to do things differently. The reason for this is simple. I found out – the hard way for the macosxbootloader project – that boot.efi was changed in Yosemite, and it is likely going to be changed in the near future as well, so we need to do things a bit differently, so please note that we are not going to create a prelinkedkernel from scratch. I can, but it takes too much time to explain/write it all up!

Ok. Let’s get cracking (still a work-in-progress) but only start doing this when you know what you are doing. Be aware that mistakes can render your Mac/Hack unbootable!

1) cp /System/Library/Prelinkedkernels/prelinkedkernel ~/prelinkedkernel_el_capitan

Note: The unsigned kexts must already be included in your prelinkedkernel, for this POC, but only to make things simpler and easier to understand.

2) Move all unsigned kexts out of /Library/Extensions and /System/Library/Extensions into /Extra/Extensions

Note: Don’t skip this step, or it won’t work!

3) Run ./lzvn -d [path]prelinkedkernel_el_capitan [path]prelinkedkernel_el_capitan_unpacked

4) Change the _PrelinkBundlePath of all unsigned kexts into /Extra/Extensions/[kext-name].kext

Note: Don’t skip this step, or it won’t work!

5) Run ./lzvn [path]prelinkedkernel_el_capitan_unpacked [path]prelinkedkernel_el_capitan_repacked

6) Load prelinkedkernel_el_capitan in a hex editor and copy the first 412/0x19c bytes. It looks like this:

CA FE BA BE 00 00 00 01 01 00 00 07 00 00 00 03
00 00 00 1C 01 19 15 09 00 00 00 00 63 6F 6D 70
6C 7A 76 6E D1 E2 8A C2 02 EF 40 00 01 19 13 89
00 00 00 01 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00

The red value 01 19 15 09 is the file size minus 28/0x1c. The purple value D1 E2 8A C2 is the checksum (adler32). The brown value 02 EF 40 00 is the size of the uncompressed file. The blue value 01 19 13 89 is the size of the compressed file. Nothing new, and the required values can be found in the output of LZVN. I myself kept the length the same (added a couple of zero’s).

Note: Please wait for me to update my LZVN repository if you don’t want to mess with this.

7) Fix the coloured values and insert the 412/0x19c bytes at the top of [path]prelinkedkernel_el_capitan_repacked

8) Save the file and copy it to: /Extra/Prelinkedkernels/Prelinked_El_Capitan_Patched, or use any other location that allows you to write the file to.

Edit: Oops. I changed the path from /System/Library/Prelinkedkernels to /Extra/Prelinkedkernels because that is what I use.

9) Open /Library/Preferences/SystemC*/com.apple.Boot.plist with nano (example) and add a “Kernel Cache” key property. Below that you add a string property with the value pointing to your copy of the prelinkedkernel. In my case: /Extra/Prelinkedkernels/Prelinked_El_Capitan_Patched

Edit: Path to El_Capitan_Patched added.

10) Reboot and run cat /var/log/system.log | grep kext to see if everything is OK.

Why patch a prelinkedkernel?
Well. For starters. The idea was to simply demonstrate a weakness in Apple’s kext signing protection in El Capitan. I also want it to work on my Mac as well. Yes. I could have added code to the macosxbootloader project, and compiled a new version of boot.efi to inject the (unsigned) kexts into the prelinkedkernel, but like I said earlier… that would have taken too much time. Not to mention that this is only a simple POC.

And sure. OS X recreates prelinkedkernel files automatically, so normally there is no need to do this manually, but this route opens the door of loading unsigned kexts on a system with SIP in place. And with El Capitan being the first version of OS X full SIP in place, which should make it way more restrictive than all previous versions of OS X… this hack is definitely new(s) – though Apple may close the door before the El Capitan GM is released.

The fact that you can set kext-dev-mode=1 in Mavericks and Yosemite, and let it update the kernel cache and prelinkedkernel with unsigned kexts, and then remove the setting afterwards, not only makes me wonder why nobody implemented proper kext injection – as in injecting kexts in the prelinkedkernel – in Clover and/or Chameleon. To me this shows us that this weakness wasn’t so well known as some people want you to believe. I mean saying something like that after a POC is published for El Capitan, is dead easy, but also a bit unfair. Why else is kext injection still broken? Nobody told slice this, or any of the other Clover developers? Really? Not to mention that I do all this with SIP fully enabled in El Capitan, without the need of kext-dev-mode, rootless=0 or any of the CSR flags… and that makes it a totally different.

Note: RevoBoot was the first boot loader to add the following CSR boot flags:

	#define CSR_ALLOW_UNTRUSTED_KEXTS	(1 << 0)	// 1
	#define CSR_ALLOW_UNRESTRICTED_FS	(1 << 1)	// 2
	#define CSR_ALLOW_TASK_FOR_PID		(1 << 2)	// 4
	#define CSR_ALLOW_KERNEL_DEBUGGER	(1 << 3)	// 8
	#define CSR_ALLOW_APPLE_INTERNAL	(1 << 4)	// 16
	#define CSR_ALLOW_UNRESTRICTED_DTRACE	(1 << 5)	// 32
	#define CSR_ALLOW_UNRESTRICTED_NVRAM	(1 << 6)	// 64

This was picked up a little later by the Enoch branch of Chameleon, with my help, and now Clover can also configure the CSR settings (runtime variable). And adding CSR_ALLOW_UNTRUSTED_KEXTS is similar to kext-dev-mode and thus enables you to add unsigned kexts to the prelinkedkernel in El Capitan. Just like using kext-dev-mode in Mavericks and Yosemite, but my POC is about injection kexts in the prelinkedkernel with SIP already fully enabled. A different kind of story.

The Problem
The main issue for me is that Apple told us that:

Valid code signatures will eventually be mandatory for all kexts

And that since Mavericks already. Now the release note of El Capitan add this:

A new security policy that applies to every running process, including privileged code and code that runs out of the sandbox. The policy extends additional protections to components on disk and at run-time, only allowing system binaries to be modified by the system installer and software updates. Code injection and runtime attachments to system binaries are no longer permitted.

But I can still inject code in the prelinkedkernel. That is not OK. I don’t like that. Another thing is that /Library/Preferences/com.apple.Boot.plist is (still) was unprotected up untill DP8, and thus anyone who liked to use a patched prelinkedkernel with unsigned kexts in it… could do that. Easily. You just need to know how.

A more serious problem is that Apple allows unsigned kext to execute from anywhere. In this POC we load them from /Extra/Extensions but other locations can be used as well. Plus. If you hide the directory including the unsigned kexts, then the average joe user won’t even notice it, since it won’t show up the finder. Plus that it will be undetectable in System Information/Software/Extensions so you won’t even know what kext is loaded from where. To me this is due to some lazy coding.

A possible oversight on Apple’s side, and that is why I expect this to change in a next Developer Preview. Well. So I hope, otherwise the first security exploit can take over your Mac/Hack. Like Hackinteam et all. Shrug.

Kext Whitelisting
If all you need is kext whitelisting, with SIP in place, then you can change/add one or more entries under OSKextSigExceptionHashList (see AppleKextExcludeList.kext/Content/Info.plist) in the prelinkedkernel, like we have been doing in Mavericks and Yosemite.

Update: Woohoo. I found another more serious way to bypass Apple’s kext signing restrictions, but this time I go for the bounty money (have a meeting tomorrow evening).

Note: Hang in tight folks. Sure. I am still very busy with my – non hack related – work, and I still suffer pain from my accident, but I will do my utmost best to finish this work. Promised!

Update-2: LZVN with support to extract the kernel, dictionary and kexts from the prelinkedkernel, is now available from my LZVN Github repository. See also LZVN command line tool updated and LZVN with kexts/dictionary extraction.

Update-3: I don’t know when, but something changed recently, as in: /L*/P*/SystemC*/com.apple.Boot.plist is now protected by SIP. How did I miss this change?

Edit: Apple fixed this bug in DP8. Fabulous!

El Capitan should not be booted with rootless=0

First. I believe that Hacking Team (currently offline ROFL) was hacked in late 2014 already, by the Dream Team, and that using rootless=0 as NVRAM/boot-arg is utterly stupid. I mean. Nobody should open ‘a backdoor in OS X’ and rootless=0 helps to protect your filesystem – among others – and so please do not use it with installations that are connected to the Internet. That is all I can say here.

Yes. I can replace your boot.efi with a modified copy of mine and give myself access to all of your files. Trust me. I would never do this, and that is why I urge you to listen to me: Please do NOT boot with rootless=0 Period!!!

Okay. Your hack won’t boot without rootless=0 but hang on. I hear you. This is why I am/will be working with boot loaders developers so that they can fix this. To let your modified kexts load without the need of rootless=0. Without the need of opening a back door. Promised.

Note: You don’t need to replace boot.efi with a legacy boot loader – think Chameleon, Chimera and RevoBoot – to be vulnerable, because boot.efi isn’t used by legacy boot loaders. Not that it really matters, because all* legacy boot loaders are still vulnerable.

Update: RevoBoot and the Enoch branch of Chameleon are no longer vulnerable and can now boot El Capitan without rootless=0 (the ‘all or nothing’ setting.. going away in a next DP).

Update-2: I have not yet been contacted by Clover developers, but then again they might not care about (your) security/privacy.

Update-3: Clover is recently changed and now sets csr-active-config by default similar to rootless=0. Which is, again, utterly stupid.

// CsrActiveConfig
Prop = GetProperty (DictPointer, "CsrActiveConfig");
gSettings.CsrActiveConfig = (UINT32)GetPropertyInteger (Prop, 0x67); //the value 0xFFFF means not set

Note: If Clover has changed, but I missed it, then please let me know so that I can update it here. Thanks!

People who set the NVRAM variable csr-data and/or csr-active-config in a way that it basically disables the System Integrity Protection, that is not in your best interest. What I mean here is that it is better to change as little as possible. Keeping as much protection up and running. Possibly only let unsigned kexts load and let the rest for what it is since that isn't required, and may open a door for exploits.