Defcon-17-Bosse Eriksson-Kernel Patching On Osx
Defcon-17-Bosse Eriksson-Kernel Patching On Osx
Defcon-17-Bosse Eriksson-Kernel Patching On Osx
Who am I?
Bosse Eriksson Security Consultant / Researcher at Bitsec Unhealthy fetish for breaking stuff Recently been looking into Mac OS X rootkit
techniques
Agenda
Intro What is a rootkit? OS X? BSD? XNU? Runtime kernel patching Runtime kernel patching on OS X PoC runtime kernel patching rootkit for OS X Rootkit detection References Q&A
What is a rootkit?
Program for access retention Local / remote backdoors Typically requires root access NOT an exploit or a trojan horse Stealth Hides files/processes/sockets Types of rootkits Userspace
Easy to implement Easy to discover
Kernelspace
Hard(er) to implement Much harder to detect if done properly
Rootkit examples
Userspace
Kernelspace
Phalanx by rebel
Runtime kernel patching rootkit for Linux 2.6 Uses /dev/mem to patch kernel memory and hook syscalls
SucKIT by sd
Runtime kernel patching rootkit for Linux 2.4 (SucKIT 2 for Linux 2.6) Uses /dev/kmem to patch kernel memory and hook syscalls
Knark by Creed
WeaponX by nemo
Kernel module (KEXT) for OS X < 10.3 First public OS X kernel rootkit
OS X? BSD? XNU?
XNU is the kernel of the OS X operating system Built on both BSD and Mach technology BSD layer Networking Processes POSIX API and BSD syscalls Mach layer Kernel threads Interrupts Memory management Scheduling
OS X? BSD? XNU?
XNU support modules, Kernel Extensions (KEXT) Most common way of subverting the XNU kernel But thats old, we want something (somewhat) new, right?
modules (LKM / KLD / KEXT) Hooking system calls to stay hidden and implement various backdoors in the running OS Also able to manipulate various kernel structures in memory
result to function A
Function A Function B
Evil Hook
void * read_mem(unsigned int addr, size_t len) { mach_port_t port; pointer_t buf; unsigned int sz; if (task_for_pid(mach_task_self(), 0, &port)) fail("cannot get port"); if (vm_read(port, (vm_address_t)addr, (vm_size_t)len, &buf, &sz) != KERN_SUCCESS) fail("cannot read memory"); return (void *)buf; }
void write_mem(unsigned int addr, unsigned int val) { mach_port_t port; if (task_for_pid(mach_task_self(), 0, &port)) fail("cannot get port"); if (vm_write(port, (vm_address_t)addr, (vm_address_t)&val, sizeof(val))) fail("cannot write to addr"); }
void * alloc_mem(size_t len) { vm_address_t buf; mach_port_t port; if (task_for_pid(mach_task_self(), 0, &port)) fail("cannot get port"); if (vm_allocate(port, &buf, len, TRUE)) fail("cannot allocate memory"); return (void *)buf; }
1
SYS_exit
2
SYS_fork
struct sysent { /* system call table */ int16_t sy_narg; /* number of args */ int8_t sy_resv; /* reserved */ int8_t sy_flags; /* flags */ sy_call_t *sy_call; /* implementing function */ ... }
427
SYS_MAXSYSCALL
system call handlers Landon Fuller developed a nice method of doing this with a KEXT
system, /mach_kernel The kernel image is just a universal Mach-O binary with two architectures, i386 and PPC
4
SYS_write
5
SYS_open
asmlinkage int open_hook(struct proc *p, struct open_args *uap, register_t *retval) { ... sys_open = (void *) 0x001e425c;
5
SYS_close struct sysent {
...
sy_call = 0xdeadc0de;
...
}
DEMO
memory to a known state In reality its not that easy, but anyway
that position
DEMO
References
Various articles
Abusing Mach on Mac OS X by nemo, Uninformed vol 4 Mac OS X Wars a XNU hope by nemo, Phrack 64 Developing Mac OS X Kernel Rootkits by wowie & ghalen, Phrack 66
http://kmem.se
A big thanks to
wowie and the rest of #hack.se, rebel, nemo and the people at Bitsec
Q&A
Any questions?
Thank you!
Thanks for listening, Ill be in the nearest bar getting
a beer