Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
工具/GitHubGitHub/soralis0912/cve-2026-43499-warhol-root
Android安全权限提升漏洞分析漏洞利用二进制利用
GitHubsoralis0912/cve-2026-43499-warhol-root

CVE-2026-43499-warhol-root

针对 CVE-2026-43499 的本地权限提升漏洞利用程序,适用于运行 Android 16、搭载 MediaTek MT6993 SoC 的 Xiaomi 17T Pro(warhol)。

查看仓库

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享
11451个月前尚未审核

warhol-root

CVE-2026-43499(IonStack)本地权限提升漏洞,已移植到 小米 17T Pro(warhol) —— 联发科 MT6993,Android 16。

仅限 GKI 6.12 / android16。 waiter 覆盖区、pselect 栈布局以及所有结构体偏移量都固定在该分支上,因此这里的内容无法迁移到 6.6、6.1 或 5.10 —— 那些分支需要为它们专门构建的基础。generate_target.py 会拒绝任何其他 banner,而不是生成一个会在设备上出错的头文件。

状态:可用。 于 2026-07-26 在设备上从干净启动验证通过,覆盖 两种 preloader 变体 —— uid=0(root) context=u:r:kernel:s0,SELinux 宽容模式,su 已安装。Root 并非持久:每次启动后需重新执行 LD_PRELOAD 那一行。pselect 竞态并非 100% 成功:一次失败的运行可能导致手机内核 panic,重启后重试是正常的。完整记录见 WARHOL_PORT.md。

此设备需要内核 MTE 修复。 上游原版 popsicle 无法在此设备上获得 root —— 它会永远卡在 kernel page retry N/12。参见 内核 MTE。

构建分为两种 preloader 变体:PRELOADER=retail(默认)和 PRELOADER=eng。它们选择不同的目标目录,因此任何一方都不会覆盖另一方的地址 —— 参见 Preloader 变体。


目标设备

以下事实来自零售版完整 OTA 包 —— 元数据、A/B payload 清单,以及从 payload.bin 中提取的 boot/vendor_boot/dtbo 镜像。

在这里,内核比 SoC 更重要:warhol 与上游 popsicle 位于同一条 GKI 分支(android16-5,4K 页),仅差一个补丁级别 —— 6.12.38 对比 popsicle 已验证的 6.12.23。结构体偏移量仍须针对每次构建重新生成;只有漏洞利用的整体形态得以沿用。不同的 OS3.0.x 构建需要自己的 target.h。


为什么选择这个基础

漏洞利用链是版本锁定于 GKI 分支的,而不是 SoC。rt_mutex waiter 布局、pselect 栈覆盖以及 pipe_buffer 结构体偏移量全都跟随内核,因此基于 6.12/android16 的方案胜过基于同厂商较旧分支的方案。

x-spy/CVE-2026-43499-popsicle 是唯一在 6.12/android16 GKI 系列(小米 17 / Pro / Ultra,内核 6.12.23-android16-5)上验证过的公开实现,因此 source/ 取自该仓库并尽可能保持与上游一致 —— 仅两行例外(参见 内核 MTE,此设备必须依赖它才能工作)。

MediaTek 的大部分差异集中在构建时的目标生成上,分为两部分:

  • 上游从高通的 xbl_config 分区读取 p0_phys_offset 和 p0_kernel_phys_load,而 warhol 没有该分区。generate_target.py --dtb 改从 vendor_boot FDT 的 /memory 节点读取 DRAM 基址,并采用与 arm64_memblock_init 相同的方式向下取整。内核物理加载地址通过 --preloader 从 preloader 的 mb_kernel 预留区读取;对于此设备,差值算出来为 0,而 lk 拒绝启动放在任何其他位置的内核。
  • MediaTek 将内核以 LZ4-legacy 压缩形式放在 boot.img 内,而非裸露的 arm64 Image,因此生成器在分析前会先将其解压。

WARHOL_PORT.md §2 包含完整推导过程。


Preloader 变体

MediaTek 的 lk 并非将内核加载到编译期常量地址 —— 它会查找名为 mb_kernel 的 DRAM 预留区,并断言内核恰好落在其上。该预留区由 preloader 创建,这正是手机当前运行的 preloader 构建被视为此处构建输入的原因:它是 boot.img 之外唯一能改变 P0_KERNEL_PHYS_LOAD 的东西,那里的值一旦出错,就意味着线性映射别名错误、手机变砖,而不是单纯的利用失败。

因此存在两种变体,分别存放于独立的目标目录中:

root@kitploit:~
make preload                  # PRELOADER=retail -> out/preload-<device>.so
make PRELOADER=eng preload    #                  -> out/preload-<device>-eng.so
make both                     # both of the above, and print their sha256

两个产物以不同的名称并排存放。在这套固件上,它们产出逐字节一致的结果 —— 这是下述分析的结果,而非绕开它的捷径,因此两者仍然分开构建并命名。

你可以自行读取两个 preloader 的内存布局表:

root@kitploit:~
python3 tools/preloader_memlayout.py <preloader.bin> --diff <preloader_eng.bin>

在这套固件上,两张表完全相同,两者的 mb_kernel.start = 0x80000000,因此 eng 版的 target.h 与零售版逐字节一致,两个构建也会产出相同的 preload.so。

真正进入漏洞利用的是差值 P0_KERNEL_PHYS_LOAD − P0_PHYS_OFFSET,而它的两个项并非建立在同等强度的证据之上:

  • P0_KERNEL_PHYS_LOAD —— 从 eng 镜像中实测得出,即上面的 mb_kernel.start。
  • P0_PHYS_OFFSET —— 是论证得出而非实测,因为它是 memstart_addr,内核在运行时从 lk 依据 preloader 在 DRAM 初始化后报告的内容所生成的 /memory 节点获取该值,而非从生成器读取的静态 FDT 获取。当时的论证是:两个构建共享整套 DRAM 路径 —— 相同的 dramc/emi/mblock/memory_layout 源码,eng 独有的字符串中没有内存布局相关代码 —— 并且 eng preloader 多出的那个预留区(一个带 mapping=1 的 3 MiB 动态 security_fe_rsv)既无法挤占固定地址条目,也无法在 DRAM 底部挖出空洞。设备实测了结此事:线性映射别名在 eng 下正确落地,因此该项是对的。

完整推导见 targets/warhol-OS3.0.304.0.WPSJPXM-eng/NOTES.md。

来自设备实测的说明:

  • BootROM 接受这个 eng preloader —— 它正常启动到了 Android,ro.boot.verifiedbootstate=green 和 flash.locked=1 均未改变。在亲自尝试之前,这曾是一个悬而未决的问题;它由 efuse 烧录的根密钥哈希决定,而且此构建与零售版使用相同的密钥签名。
  • eng preloader 保持 META / 工厂下载模式可用:%s META DIS 是零售版独有的字符串,而 eng 带有零售版所没有的完整 META 实现(Enable fastmeta.、FAST META GPIO: %d、META_COM PORT: %d、read_meta_proinfo 等)。在这里它直接启动到了 Android,但如果刷了 eng 的手机将来落入其他状态,这很可能就是原因,且与任何 target.h 的值无关。
  • 如果以后的固件移动了 mb_kernel,两个目标就会分道扬镳 —— 将它们作为独立目录分开存放,正是为了避免这种变化被悄然忽略。

内核 MTE

该内核运行 KASAN_HW_TAGS —— /proc/cmdline 带有 kasan.stack_ring_size=524288 —— 因此 slab 指针在第 59:56 位携带分配标签。上游 popsicle 假定指针不带标签,因此完全无法让此设备获得 root:它会无限循环于 [-] kernel page retry N/12 mode=1,日志中没有任何内容说明原因。

source/ 中的两行代码修复了这个问题,二者都在 warhol-mte-fix.patch 中:

只有检查操作会去除标签。指针本身保持带标签,因为其标签正是它们所指向内存的正确标签 —— 这正是内核解引用它们时所需要的。

不要为此去读 arm64.memtag.bootctl:该属性是用户空间的 MTE 控制项,与内核是否标记自身分配毫无关系。


上游 / 参考资料

本仓库是一个移植。漏洞利用链的功劳归于上游。


目录结构

root@kitploit:~
source/          exploit core (upstream popsicle + the kernel-MTE fix; see warhol-mte-fix.patch)
  src/           main.c slide.c fops.c pipe.c util.c preload.c su_daemon.c + kernelsnitch/
targets/         per-build generated target.h, one dir per fingerprint x preloader variant
  warhol-OS3.0.304.0.WPSJPXM/       PRELOADER=retail
  warhol-OS3.0.304.0.WPSJPXM-eng/   PRELOADER=eng
tools/
  payload_dump.py          extract partitions from an A/B payload.bin (verifies size+sha256)
  kernel_banner.py         read the Linux banner out of a boot.img
  bootinfo.py              dump boot / vendor_boot header fields
  generate_target.py       target.h generator; upstream's, MediaTek-only, plus kernel decompression
  preloader_memlayout.py   dump/diff a MediaTek preloader's static DRAM reservation table
  lz4legacy.py             LZ4 legacy-frame decompressor (kernel images)
out/             build artifacts (gitignored)

构建

在 target.h 存在之前不会构建任何东西 —— Makefile 会明确报错失败,而不是针对错误的内核产出二进制文件。

root@kitploit:~
# 1. extract boot.img straight out of the OTA zip (payload.bin is stored uncompressed,
#    so --base seeks into the zip; no need to unpack 7.6 GB first)
python3 tools/payload_dump.py <ota.zip> --base 5081 -p boot,vendor_boot,dtbo -o <dir>

# 2. confirm the kernel banner — every offset downstream is pinned to it
python3 tools/kernel_banner.py <dir>/boot.img
python3 tools/bootinfo.py <dir>/boot.img

# 3. generate the target header. --preloader reads the kernel's physical load address
#    out of the preloader's mb_kernel reservation; pass the preloader the phone runs.
python3 tools/generate_target.py \
  --boot <dir>/boot.img --dtb <dir>/vendor_boot.img --preloader <preloader.bin> \
  -o targets/warhol-OS3.0.304.0.WPSJPXM/target.h

# 4. build
make preload            # DEVICE=warhol-OS3.0.304.0.WPSJPXM, PRELOADER=retail by default

手头没有 preloader 镜像时,--kernel-phys-delta 0 是较旧的用法,对本固件会生成相同的头文件 —— 但它是一种断言而非实测读取,因此优先使用 --preloader。两者都传时,生成器会对它们进行交叉校验,不一致则报错。

--base 5081 是此特定 OTA 的 payload.bin 本地头偏移量;对于其他任何软件包,请从 META-INF/com/android/metadata 中的 ota-property-files 读取该值。

需要 Android NDK(NDK_ROOT / ANDROID_NDK_HOME)和 llvm-objdump。

运行

root@kitploit:~
# <device> is the target name: <fingerprint> for PRELOADER=retail, <fingerprint>-eng for eng
adb push out/preload-<device>.so /data/local/tmp/preload.so
adb shell chmod 0644 /data/local/tmp/preload.so
adb shell "LD_PRELOAD=/data/local/tmp/preload.so /system/bin/true"
adb shell "/data/local/tmp/su -c id"

cred 与 SELinux 状态是在内存中修补的,因此每次启动后都必须重复此操作。无需解锁 bootloader。


免责声明

仅供在您自有的硬件上进行研究。运行此程序可能导致设备反复重启(bootloop)或变砖,并使保修失效。不提供任何形式的担保。

上游项目由其各自作者授予许可;本移植沿用其条款。

下载工具
项目值来源
代号warholpre-device=warhol
构建指纹Xiaomi/warhol_global/warhol:16/BP2A.250605.031.A3/OS3.0.304.0.WPSJPXM:user/release-keyspost-build
增量版本OS3.0.304.0.WPSJPXM(JP 全球版)post-build-incremental
Android16,SDK 36post-sdk-level=36
安全补丁2026-05-01post-security-patch-level
OTA 类型A/B(payload.bin,CrAU,39 个分区)ota-type=AB
SoC联发科 MT6993(天玑 9500)vendor_boot DTB 中的 mediatek,mt6993-* 兼容项;cmdline bootopt=64S3,32N2,64N2
内核6.12.38-android16-5-g1d46253471dd-ab15048002-4k,clang 19.0.1从提取的 boot.img 中读取的 banner
启动镜像header v4,内核 18,898,125 字节,LZ4-legacy 压缩,无 ramdisktools/bootinfo.py
PRELOADER=手机上的 preloader目标目录状态
retail(默认)随设备出货的 preloader_<device>.bin,与 fastboot ROM 中的 preloader_raw.img 逐字节相同targets/warhol-OS3.0.304.0.WPSJPXM/✅ 2026-07-26 已在设备上验证
eng工程构建版 preloader_<device>_eng.bintargets/warhol-OS3.0.304.0.WPSJPXM-eng/✅ 2026-07-26 已在设备上验证
文件更改原因
src/util.ckernelsnitch_setup(..., mte_enabled=1)设为 0 时,mm_struct 搜索只会尝试无标签的候选,永远无法触及带标签的指针 —— 这是结构性失配,而非运气不佳
src/util.cis_kernel_ptr() / is_direct_ptr() 在范围检查前先去除标签否则,从内核内存读出的带标签指针会因“不在线性映射中”而被拒绝(direct-entry-fatal reason=bad-task-or-cpu)
src/kernelsnitch/kernelsnitch.h标签扫描 < 15 → < 16标签 0xf 就是无标签/匹配所有指针的标签,因此该扫描现在也覆盖没有 MTE 的内核 —— mte_enabled=1 两种情况下都安全
仓库在本项目中的角色
https://github.com/MobiusM/CVE-2026-43499原始 CVE-2026-43499 PoC / 崩溃触发程序
https://github.com/x-spy/CVE-2026-43499-popsicle本移植的基础。 小米 17 Pro Max(popsicle),内核 6.12.23-android16-5;source/ 和 tools/generate_target.py 来自此仓库
https://github.com/Kananosa/CVE-2026-43499-For-Xiaomi-17T-chagall最接近的姊妹设备(小米 17T,chagall,同为 MediaTek)。源自 popsicle,附带预构建的 preload.so —— 其编译期常量确认了物理加载偏移
https://github.com/MiCode/Xiaomi_Kernel_OpenSource小米内核源码,用于交叉核对结构体布局