Files
ave27/scripts/gen_icon.py
T
JBJF bc019e2b6c AVE27 — standalone POC app for CVE-2026-112705 (AppleAVE2 NTL OOB write)
- All stages ported from MchinaMd57764/AVETemporalPoC (orig. Calif/Chollima):
  stage1-12, 20, 21, fuzz, SBE — launch-arg parity kept
- New: stage13 NTL threshold sweep, stage14 usage×rc acceptance matrix,
  stage15 private-key entitlement audit (23 keys)
- Panic journal: kern.boottime-based in-app panic evidence after reboot
- Interactive SwiftUI console + NTL field + report share; header shows
  PANIC-CAPABLE on iOS 27.0-27.1, FIXED BUILD on 27.2+
- App icon: temporal-layer stack, top layer displaced past the stack edge
- scripts/build-device.sh → unsigned arm64 IPA (iOS 17.0+)
2026-10-30 19:13:13 +08:00

174 lines
5.7 KiB
Python

#!/usr/bin/env python3
"""
gen_icon.py — the AVE27 app icon, drawn with a signed-distance renderer and
written as a raw PNG (no image library).
The mark: a stack of five temporal layers — an SVC pyramid, widest at the base.
The top layer is displaced up and out past the stack's bounding edge: the layer
count that walks past what the driver sized. Deep slate field, steel layers,
the escaping layer in hot ember with the halo of the write landing somewhere
it was never allocated.
"""
import math
import os
import struct
import zlib
OUT = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "Resources", "Assets.xcassets", "AppIcon.appiconset")
os.makedirs(OUT, exist_ok=True)
SIZE = 1024
def srgb(c):
return max(0, min(255, int(round(c))))
def mix(a, b, t):
return tuple(a[i] + (b[i] - a[i]) * t for i in range(3))
def smoothstep(e0, e1, x):
t = max(0.0, min(1.0, (x - e0) / (e1 - e0)))
return t * t * (3 - 2 * t)
def sd_round_rect(px, py, cx, cy, hw, hh, r):
qx = abs(px - cx) - (hw - r)
qy = abs(py - cy) - (hh - r)
outside = math.hypot(max(qx, 0.0), max(qy, 0.0))
inside = min(max(qx, qy), 0.0)
return outside + inside - r
# ---------------------------------------------------------------- palette
BG_TOP = (0.086, 0.094, 0.118)
BG_BOT = (0.024, 0.026, 0.038)
LAYER_COLD = (0.36, 0.44, 0.58)
LAYER_WARM = (0.52, 0.62, 0.78)
EMBER = (1.00, 0.44, 0.14)
EMBER_HOT = (1.00, 0.76, 0.38)
# stack geometry: five layers, widths grow downward, top one escapes
STACK_CY = SIZE * 0.555
LAYER_H = SIZE * 0.082
LAYER_GAP = SIZE * 0.028
BASE_HALF = SIZE * 0.30
TOP_HALF = SIZE * 0.115
LAYERS = 5
# the escape: top layer displaced up-right, past the stack's right edge
ESC_DX = SIZE * 0.145
ESC_DY = -SIZE * 0.085
def render():
out = bytearray()
half = SIZE / 2
radius = SIZE * 0.2237
tau = math.tau
cos, sin, hypot = math.cos, math.sin, math.hypot
# precompute layer rects: index 0 = base .. LAYERS-1 = top
step = LAYER_H + LAYER_GAP
total = LAYERS * LAYER_H + (LAYERS - 1) * LAYER_GAP
rects = []
for i in range(LAYERS):
t = i / (LAYERS - 1)
hw = BASE_HALF + (TOP_HALF - BASE_HALF) * t
cy = STACK_CY + total / 2 - LAYER_H / 2 - i * step
cx = half
r = LAYER_H * 0.32
rects.append((cx, cy, hw, LAYER_H / 2, r, t))
esc_rect = None
if LAYERS >= 1:
cx, cy, hw, hh, r, t = rects[-1]
esc_rect = (cx + ESC_DX, cy + ESC_DY, hw, hh, r, t)
esc_cx, esc_cy = esc_rect[0], esc_rect[1]
halo_r = SIZE * 0.20
for y in range(SIZE):
out.append(0)
py = y + 0.5
for x in range(SIZE):
px = x + 0.5
# background
g = py / SIZE
col = mix(BG_TOP, BG_BOT, g)
d = hypot(px - half, py - SIZE * 0.47)
lift = 1.0 - smoothstep(0.0, SIZE * 0.66, d)
col = tuple(min(1.0, col[i] + 0.05 * lift) for i in range(3))
# faint baseline under the stack
sd_base = abs(py - (STACK_CY + LAYER_H * 2.6)) - SIZE * 0.004
if abs(px - half) < BASE_HALF * 1.25:
cov = 1.0 - smoothstep(-1.0, 1.0, sd_base)
col = mix(col, LAYER_COLD, cov * 0.22)
# the stack: steel gradient, cold at base, warmer toward the top
for (cx, cy, hw, hh, r, t) in rects[:-1]:
sd = sd_round_rect(px, py, cx, cy, hw, hh, r)
if sd < 1.2:
cov = 1.0 - smoothstep(-1.2, 1.2, sd)
layer_col = mix(LAYER_COLD, LAYER_WARM, t)
col = mix(col, layer_col, cov * 0.9)
# the escaping layer: ember, halo behind it
d_esc = hypot(px - esc_cx, py - esc_cy)
if d_esc < halo_r:
halo = 1.0 - smoothstep(0.0, halo_r, d_esc)
hk = 0.22 * halo * halo
col = tuple(min(1.0, col[i] + EMBER[i] * hk) for i in range(3))
(cx, cy, hw, hh, r, t) = esc_rect
sd = sd_round_rect(px, py, cx, cy, hw, hh, r)
if sd < 1.2:
cov = 1.0 - smoothstep(-1.2, 1.2, sd)
# hot edge on the leading (upper-right) side
heat = smoothstep(0.0, 1.0, (px - cx + hw) / (2 * hw)) * 0.7
col = mix(col, mix(EMBER, EMBER_HOT, heat), cov)
# the trail: where the escaping layer used to sit — an ember outline
(cx, cy, hw, hh, r, t) = rects[-1]
sd_trail = abs(sd_round_rect(px, py, cx, cy, hw, hh, r)) - SIZE * 0.006
if sd_trail < 1.2:
cov = (1.0 - smoothstep(-1.2, 1.2, sd_trail)) * 0.8
col = mix(col, EMBER, cov)
# rounded-rect alpha
sd_r = sd_round_rect(px, py, half, half, half - 0.5, half - 0.5, radius)
a = 1.0 - smoothstep(-0.75, 0.75, sd_r)
out += bytes([srgb(min(1.0, col[0]) * 255), srgb(min(1.0, col[1]) * 255),
srgb(min(1.0, col[2]) * 255), srgb(a * 255)])
return bytes(out)
def write_png(path, width, height, rgba):
def chunk(tag, data):
c = struct.pack(">I", len(data)) + tag + data
c += struct.pack(">I", zlib.crc32(tag + data) & 0xFFFFFFFF)
return c
ihdr = struct.pack(">IIBBBBB", width, height, 8, 6, 0, 0, 0)
raw = zlib.compress(rgba, 9)
png = (b"\x89PNG\r\n\x1a\n"
+ chunk(b"IHDR", ihdr)
+ chunk(b"IDAT", raw)
+ chunk(b"IEND", b""))
with open(path, "wb") as f:
f.write(png)
def main():
data = render()
icon = os.path.join(OUT, "AppIcon-1024.png")
write_png(icon, SIZE, SIZE, data)
print("wrote", icon, os.path.getsize(icon), "bytes")
if __name__ == "__main__":
main()