
# Android Chromium 전체 체인 익스플로잇 CVE-2026-11057 정보 유출과 CVE-2026-5281 use-after-free를 결합하여 vtable 하이재킹 및 임의 코드 실행을 달성하는 Android Chromium용 전체 체인 익스플로잇입니다.
Pixel 7 Android 16 ARM64
commit 994c846bbd7a35241ba7c08158c13d66412a6993 (HEAD -> 146.0.7680.111, tag: 146.0.7680.111)
Author: Roger McFarlane <[email protected]>
Date: Mon Mar 9 12:48:07 2026 -0700
이 저장소는 CVE-2026-11057(Skia 초기화되지 않은 글리프 이미지 메모리)과 CVE-2026-5281(Dawn wire 서버 DeviceInfo use-after-free)을 결합하여 전체 체인을 구성합니다. 모든 수정은 렌더러 측에서 이루어지며, GPU 프로세스 코드는 변경되지 않습니다:
정보 유출 (CVE-2026-11057) — 캔버스 텍스트 렌더링을 통해 초기화되지 않은 글리프 이미지 버퍼를 트리거하고, GPU 프로세스 힙에서 포인터를 다시 읽어 산술 연산으로 검증한 뒤, PartitionAlloc 풀 베이스를 도출하고, 가짜 Server 대상 M = POOL + 0x202A08000(보정된 오프셋)을 계산합니다.
CC 스프레이 — createBuffer(label="CCM:<m>:<n>")는 3000개의 불완전한 ChunkedCommand(10KB 버킷, remainingSize=1, wire 서버의 mChunkedCommands에 유지됨) 주입을 트리거합니다. 페이로드는 Android arm64용으로 배치된 가짜 Server로 M 주변 영역을 채웁니다: +0xB20에 MutexProtected vptr, +0xB50/+0xB58에 ChunkedCommandSerializer, +0xC00/+0xD00에 가짜 CommandSerializer/vtable.
5281 트리거 + 점유 — queue.writeBuffer(buffer, 0x414141, ...)는 먼저 Unregister(Device)를 호출하여 16바이트 DeviceInfo를 해제한 다음, 16바이트 점유 ChunkedCommand를 주입하여 해당 슬롯을 재점유하고 info->server를 M으로 덮어쓰며, 마지막으로 범위를 벗어난 오프셋으로 검증 오류를 트리거합니다.
댕글링 콜백 → vtable 하이재킹 — 캡처되지 않은 오류 콜백이 info->server = M(가짜 Server)을 역참조합니다: 0으로 초기화된 뮤텍스를 통과하고, 실행이 OnUncapturedError → SerializeCommand에 도달하며, 상대 vtable 간접 호출이 우리의 가짜 vtable에 도달하여 pc = fake_vtable + 제어된 int32 오프셋이 되며, 이는 pc = 0x7641414141로 시연됩니다.
참고: Android arm64 Chromium은 상대 vtable(
-fexperimental-relative-c++-abi-vtables)을 사용합니다. vtable 항목은 절대 함수 포인터가 아닌 32비트 상대 오프셋이므로, PoC는 vtable 하이재킹 지점에서 제어된 int32 오프셋을 마커로 사용합니다.
테스트 기기에서 전체 체인은 거의 100%의 성공률로 vtable 하이재킹 크래시에 도달합니다. 유출 단계는 성공하기 전에 때때로 여러 번의 자동 재로드가 필요할 수 있습니다.
SkStrike.cpp.patch — CVE-2026-11057 유출 트리거. FlattenGlyphsByType()은 strike 페이로드를 다시 작성하여 GPU 프로세스가 fImage == nullptr인 SkGlyph를 생성하게 하고, 결국 초기화되지 않은 이미지 버퍼를 읽어 힙 포인터를 유출합니다.Device.cpp.patch — Dawn wire 클라이언트 CC 스프레이. APICreateBuffer()는 CCM: 레이블을 파싱하고, Android arm64 가짜 Server 페이로드를 구성하며, GPU 프로세스에 유지되는 N개의 불완전한 ChunkedCommand를 주입합니다.ApiProcs.cpp.patch — CVE-2026-5281 트리거 + 점유. QueueWriteBuffer 매직 오프셋 0x414141에서 Unregister(Device)를 호출하여 DeviceInfo를 해제하고, 16바이트 ChunkedCommand를 주입하여 슬롯을 재점유하고 info->server = M을 설정한 다음, 범위를 벗어난 오프셋으로 진행하여 댕글링 콜백을 발동합니다.exploit.html — 페이지 오케스트레이션: 유출 프리미티브(groom/draw/readCell/verifyRuns/derivePoolBase), CC 스프레이, 그리고 독립 실행형 exploit5281() 트리거. 실패 시 스프레이 상태를 정리하고 재로드하여 단계들이 서로 간섭하지 않도록 합니다.이 ExP는 vtable 하이재킹 단계(제어된 간접 호출 대상, pc = base+0x41414141)까지만 공개됩니다. 제어된 점프 이후의 단계와 RCE 구현은 기밀로 유지되며 이 저장소에 포함되지 않습니다.
제 익스플로잇은 원래 보고자의 접근 방식과 핵심적인 점에서 다릅니다. 원본 익스플로잇은 GPU 프로세스의 PartitionAlloc 소스 코드를 수정하여 주소 무작위화를 비활성화함으로써 달성되었습니다. 이 접근 방식은 개념 증명 목적에만 적합합니다. 반면, 제 익스플로잇은 정보 유출 취약점을 결합하여 주소 무작위화를 우회함으로써 실제 환경에서 작동하는 완전한 기능의 익스플로잇을 가능하게 합니다.
# Set build arguments here. See `gn help buildargs`.
is_official_build = true
is_debug = false
symbol_level = 0
v8_symbol_level = 0
blink_symbol_level = 0
is_component_build = false
proprietary_codecs = true
ffmpeg_branding = "Chrome"
dcheck_always_on =false
optimize_webui = true
android_static_analysis = "off"
target_os = "android"
target_cpu = "arm64"
# Disable PartitionAllocEventuallyZeroFreedMemory
disable_fieldtrial_testing_config = true
treat_warnings_as_errors = false
adb logcat | grep DEBUG 실행