Android Chromium 全链路漏洞利用,结合 CVE-2026-11057 信息泄露与 CVE-2026-5281 释放后使用(use-after-free),实现 vtable 劫持与任意代码执行。
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 释放后使用)组合成一条完整利用链。所有修改均在渲染器侧;GPU 进程代码保持不变:
信息泄露(CVE-2026-11057) — 通过 canvas 文本渲染触发未初始化的字形图像缓冲区,从 GPU 进程堆中读回指针,通过算术运算校验这些指针,推导出 PartitionAlloc 池基址,并计算出伪造 Server 目标 M = POOL + 0x202A08000(经校准的偏移)。
CC 喷射 — createBuffer(label="CCM:<m>:<n>") 触发注入 3000 个不完整的 ChunkedCommands(10KB 桶,remainingSize=1,在 wire 服务器的 mChunkedCommands 中保持存活)。载荷在 M 周围区域填充一个为 Android arm64 布局的伪造 Server:MutexProtected vptr 位于 +0xB20,ChunkedCommandSerializer 位于 +0xB50/+0xB58,伪造的 CommandSerializer/vtable 位于 +0xC00/+0xD00。
5281 触发 + 占位 — queue.writeBuffer(buffer, 0x414141, ...) 首先调用 Unregister(Device) 释放 16 字节的 DeviceInfo,然后注入一个 16 字节的占位 ChunkedCommand 以回收该槽位并将 info->server 覆盖为 M,最后通过越界偏移触发验证错误。
悬空回调 → vtable 劫持 — 未捕获错误回调解引用 info->server = M(伪造 Server):清零的互斥锁通过检查,执行流到达 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 载荷,并注入 N 个在 GPU 进程中保持存活的不完整 ChunkedCommands。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