 So we're getting ready to start. Welcome to a presentation on runtime kernel patching on Mac OS X. My name is Bosa Ericsson. It's kind of hard to pronounce for you Americans and non-Swedish people. I'm a security consultant at Swedish company Bitsec. And I break stuff for a living. And recently I've been looking into Mac OS X root kitten techniques. So that's short about me. We only have 20 minutes, so I'm going to speed this up. But the basic talk is going to look like this. Short intro about rootkits, OS X, BSD and the X new kernel. Runtime kernel patching in general. What makes runtime kernel patching specific for OS X? And I'm going to demonstrate our proof of concept rootkit for OS X. Also some basic detection technique for this. And we'll take a question if we have time. I'm going to start off. So I'm pretty sure most of you guys know what a rootkit is. Well, basically it's a program for access retention. It's like not an exploit or a trojan horse. Like it doesn't grant you access to a box. You don't own something with it. Also you don't send it to a person and have them run it. It's something you run on a box you own to retain access to it. Typically it requires root access. And it provides stealth techniques like hides files, processes, sockets, and so on. Basic types of rootkits are user space rootkits and kernel space rootkits. Those are the main categories. The user space rootkits are kind of easy to implement or therefore easy to detect. The kernel ones are a bit harder to implement and much harder to detect if they are done properly. Since you are at the kernel level of the OS and you can manipulate pretty much anything you want. This is a simple demonstration. Just so you get this right. This is when you get owned. That's the exploit right there. And the bottom line, that's when you stay owned. That's the rootkits. So just to get this straight, it's to require root access. Example of rootkits. Well, user space, like various evil patches to PS, Netstat, LS, and you can also binary patching like SSH demons and stuff. Pretty basic stuff. The kernel ones, there are a few out there, public, private. We have FATNICS by Rebel, which is a kernel patching rootkit for Linux 2.4. Uses DevMem device to patch these calls. Suckit by SD, which are classic. One of the first public rootkits who used this runtime kernel patching. It's for Linux 2.4. Also, it's a later version of Suckit 2 for 2.6. We are Knotic by Switch Gundam Creed, which is a Linux kernel module for Linux 2.2. It hooks these calls by patching the kernel via an LKM. And also we have Weapon X by Nemo, which is, I believe, the first public OSX kernel rootkit. But unfortunately, it stopped working at OSX 10.3, and there hasn't been any public OSX rootkits since then, I believe. So, short intro on OSX and the XNU kernel. The XNU kernel is the kernel of the OSX operating system, and it's built on both BSD and Mach technology. Mach is the micro kernel which runs in the bottom of the OS, and you also have a kind of BSD layer in there, and they're both responsible for different stuff. This is very abstracted, but the BSD layer is responsible for networking, processors, and POSIX 8.5, and the BSD CIS calls. So, you can basically do any POSIX stuff on OSX without touching the Mac layer at all. And the Mac layer handles like kernel threads, interrupts, memory management, scheduling, and so forth. We don't have the time, I want to dig into this, but this is the basic of it. The XNU, like any modern operating system, supports modules. On Linux, you have LKMs, BSD has KLDs, and OSX has kicks, like kernel extensions for device drivers and so on. So, you can extend the kernel at runtime and adding new code to it. And this has been the primary way to subvert the XNU kernel, like the Rootkit I mentioned, WebNX uses kernel extensions to patch it. But I think that's kind of all that's been done. It was talked last year on Black Hat by Jesse, I can pronounce his last name. He did the same thing with kicks that works for every new release of OSX. But we're going to skip the kicks part and we're going to runtime patch the kernel. So, runtime kernel patching is basically subvert in the kernel without use of kernel modules. Because that's the basic entry point in the kernel for normal Rootkits, like WebNX. And we're going to do hooking system calls to stay hidden and implement various backdoors in the running OS by just patching the kernel directly in memory. And you can also manipulate various kernel structures to do all kinds of crazy stuff if you want to. But I'm going to show you some basic examples. This is basically function hooking for those of you who doesn't know it. It's kind of a man in the middle attack between two functions. Let's say function A calls function B. But instead of function B getting executed, the evil hook function get executed and then executes function B and passes on the return value back to function A. So it's like a transparent man in the middle attack. Function A sees the result from function B, but various other code can also be executed in the hook. So that's the basic idea of function hooking. Runtime kernel patching is nothing new. Like I said, it's been done. I think the first occurrence was what was the Suckit Rootkit back in like 99, which it is on Linux. And the basic idea is you allocate kernel memory from user land. You put your evil code in the allocated space. And you redirect a system call or any other function to this memory area, and then you get profit. Cause you can do like whatever you want. So normal way to do this, this is for Linux. You find a suitable system call handler like set hostname that is rarely used. You back up the system call handler. You redirect the handler to Kmalloc, the function in the kernel to allocate memory. And then you execute the system call and Kmalloc will be executed from user space and you have your memory. And then you restore the system call handler. But that's kind of a lot of work. So we're gonna do this a bit easier. OSX is very hacker friendly by the way. Since it provides an API for this. You can use various function exported by the mock layer to do this evil stuff and all you need is root. So there's a couple of function here. VM read, VM write, and VM allocate. I'm not gonna go into this like too deep, but basic the read, write, and allocate memory in a process. So you're gonna see where this is going. This is some basic analogy of the mock kernel. The mock part of the kernel of XNU has tasks which is a logical representation of an execution environment. Fancy speaking, it contains one or more threads. And a thread has its own register and scheduling policies. So we're not gonna go into deep entries because we don't have time, but you have ports. Ports is like a message communication channel. It's used to send messages between processes. That's basically all you need to know for this. So here we have a simple function using this for reading memory. I don't know if you can read that, but you just call task for PID and you could specify PID zero, which is the XNU kernel running in the OSX operating system. And what you get there is a port to the kernel, the communication channel. And all you need to do is use this function, VM read, VM write, and VM allocate, and you can manipulate the kernel's memory space. It's that easy. It's literally like 10 lines of code to read kernel memory as root. It's pretty awesome if you wanna root get a machine. Here's the same function, but for writing kernel memory. Same thing, task for PID, VM write, you're good to go. Also for allocating, it's just a one line change. So OSX has a global SYS entry array which holds a structure for each system call available in the kernel. It's maximum is 427. Goes from zero up to there. Each entry has this structure which contains the system call arguments and also a pointer to the system call handler, which is the function that gets executed when the system call is called. So that's our main target when you're patched. So to do this, we need to locate the SYS entry table and patch the system call handlers. This guy Landon Fowler, he developed a really nice method of doing this with a kernel extension to enable P trace for certain Apple applications. His method was like this. Since the number of system calls is an exported function in the kernel, you like call nsysent, number of SYS entries, you can calculate from that an offset to the system call type, SYS entry table. And that's static. It's 28 plus four on I 386. So you just add to that and you get to the SYS entry table. I can mention before 10.3, the SYS entry table, what was in self and exported. So you could access it directly from a kernel extension, but it's not anymore. So you can't patch it directly. You need to locate it in memory. And that works pretty good for cakes, but as I said, we don't want to use cakes. So to do this from user land, we just need to locate the number of SYS entries in memory. And on OSX, the kernel image is on the file system called Mach kernel in slash. And it contains the nsysentry symbol, which can be resolved by parsing the Mach O binary. And you take that symbol plus 32 and there you have it, the SYS entry table. So you don't need a kernel extension to do this. And yes, as I said, I was thinking we could do some Mach O parsing here, but we don't have time, so I'm gonna skip it. The kernel is a universal Mach O binary with two architectures, I-386 and PPC. So just read up on how the file format is and you can parse it pretty easy. I even have some tools to do that I'll give to you later. So basically the modified function looks like this. It's S2A, resolve. It's a library I threw together to resolve symbols from the kernel. So we don't change anything, we just resolve it from the kernel on the disk, so. So now we have located the SYS entry table, which holds all the system calls in the OS. We can read, write and allocate kernel memory, which is good. So now we're just gonna get down to the dirty business. So it looks basically like this. We have the SYS entry table, which contains all the system calls. Normally it points to like 001E425C, I think that's for one version back of the XNU kernel. It points to open for the open SYS call. What we're gonna do is we're gonna modify that structure and point it to our address of our choosing. Not necessarily a dead code, but another is where we have this function here. Where we then have a function pointer, which we will execute and return. So we can do evil stuff in between transparent. So I'm gonna show you like a proof of concept rootkit I threw together for this. It's called Mirage. It's a cheesy name, I know it, but it results symbols from the XNU kernel and hook system calls using the named functions. It's not detected by check rootkit, but I don't know any serious rootkit, which is detected by check rootkit. So demo time. And I'm not gonna do this live. I have videos, since I'm a chicken. So basically we compile the rootkit. We patch the kernel with the install. As you see, p11 here is visible. It's the directory service. We install the rootkit, patch some SYS calls, and p11 is gone. We uninstall the rootkit, and p11 is visible again. So that's basically process hiding. Thank you. There's more. We have an open back door here. It's kind of messy. I'll take it later if we have time. This is the TCP input hook. The basic idea of this is you send the infected host a trigger packet, and it looks for patterns in the TCP packet, and then execute stuff you want. So on the top here is the infected host, and the lower window is the attacker. We build a rootkit, we install it, hook some SYS calls, and the TCP input handler. That's a client for a connect back shell. This is the same host, but it could be a remote host. And I just send a packet to port 1337, and there you have it. Root prompt. And as you see, we're root. You don't need to connect to the port, actually. I just used a nutcat because it was easy. You can do that with any kind of trigger like in the TCP header. Really easy. You just need to modify it. So detection, well, how do you detect these things like if you've been infected? It turns out it's pretty easy. You just compare the SYS Entertable in memory to a known state, right? But I think everyone in here knows that that's just not the case every time because there's like a million ways to bypass this comparison, but I'm gonna show you it anyway because it works, but any serious attacker would not make this work, so. Yeah, it's not that easy. But remember, the number of SYS Entertables available is 427, and that was zero X, one AB in Higgs. And the original SYS Entertable is that number of SYS Entertables plus 32. So we can look at the mark kernel image and you see our highlight there. We have the number of SYS Entertables and 32 bytes ahead. We have the start of the SYS Entertable. So all we need to do is we copy the kernel image into a buffer. We find the offset to the ansys and symbol and we add 32 bytes to that offset and return a pointer to that position and there we have our SYS Entertable from disk, which is sort of a known state. It can be modified. A attacker could hook open call to the kernel image and whatnot to make you read another SYS Entertable, but it's simple and it works. So here's the code for it. Just open the kernel image and do a for loop basically with a pointer and look for patterns. So if you're on that you should find it. Demo time. Fingers crossed. So we build the rootkit and the detector. So we patch the kernel and you see PD11 is invisible again. We run the detector as two modes, scan and restore. First we scan, detects two hooked system calls and we run restore, two restored system calls successfully and PD11 is visible again. So that's basically it about detection. But as I said, this is not reality, it works in a lab, but you shouldn't rely on this. We could go back and do the other demos later. This is basically an open hook for the open SYS call which will take a path and a flag and if you specify a magic flag, the file won't be open but it will be executed as root. So now we patch the kernel. In temp there's a file called run me and we're just a regular user. And the run me file cats the master password file to temp.pone. The test program here just calls open temp run me with one, three, three, seven as the flag. Nothing special and then exits. So we run it and check the file and we have the password file. Not that OS10 stores shadows or something in there but it's read only for root. It's an easy way for a local backdoor to be implemented. And there's the other slides. Oh yeah, here. Articles on this sub if you want to read up to it you have abusing mock on mock by Nemo which talks about this a lot deeper and the whole mock ex new technology is a great paper. Mac OSX wars, a new hope by Nemo, frag 64 is also a good paper on Mac OSX stuff and developing Mac OSX kernel rootkits by myself and Huawei. We talk a little bit about runtime kernel patching but mostly about kernel extensions. So Mac Hacker's handbook by Dino and Miller it's great Mac book if you love OSX and hacking Macs. Update the slides will be available on Kmem.se perhaps some code, there's also, there are already some code there, simple resolving code and some other I can't remember but it's there. So that's all I have to say. You know where to find me if you have any questions I don't have any Q and A so thank you.