Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2026-43499-warhol-root — Android 16과 MediaTek MT6993 SoC를 탑재한 Xiaomi 17T Pro(warhol)의 CVE-2026-43499를 대상으로 하는 로컬 권한 상승 익스플로잇. | Kitploit
도구/GitHubGitHub/soralis0912/cve-2026-43499-warhol-root
Android SecurityPrivilege EscalationVulnerability AnalysisExploitationBinary Exploitation
GitHubsoralis0912/cve-2026-43499-warhol-root

CVE-2026-43499-warhol-root

Android 16과 MediaTek MT6993 SoC를 탑재한 Xiaomi 17T Pro(warhol)의 CVE-2026-43499를 대상으로 하는 로컬 권한 상승 익스플로잇.

저장소 보기

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유
1126일 전아직 검토되지 않음

warhol-root

CVE-2026-43499 (IonStack) 로컬 권한 상승 — Xiaomi 17T Pro (warhol) — MediaTek MT6993, Android 16용으로 포팅됨.

GKI 6.12 / android16 전용. waiter 오버레이, pselect 스택 레이아웃 및 모든 struct 오프셋은 해당 브랜치에 고정되어 있으므로 여기의 어떤 것도 6.6, 6.1 또는 5.10으로 이전되지 않습니다 — 해당 커널에는 전용으로 빌드된 베이스가 필요합니다. generate_target.py는 기기에서 fault를 일으킬 헤더를 생성하는 대신 다른 배너를 거부합니다.

상태: 동작 확인. 클린 부팅 후 2026-07-26에 기기에서 두 preloader 변형 모두로 검증됨 — uid=0(root) context=u:r:kernel:s0, SELinux permissive, su 설치됨. 루트는 영구적이지 않습니다: 부팅할 때마다 LD_PRELOAD 라인을 다시 실행하세요. pselect 레이스는 100%가 아닙니다: 실패한 실행은 폰을 패닉시킬 수 있으며, 재부팅 후 재시도하는 것은 정상입니다. 전체 기록은 WARHOL_PORT.md를 참조하세요.

이 기기는 kernel-MTE 수정이 필요합니다. 스톡 업스트림 popsicle은 이 기기를 루팅할 수 없습니다 — kernel page retry N/12에서 영원히 회전합니다. Kernel MTE를 참조하세요.

빌드는 PRELOADER=retail(기본값)과 PRELOADER=eng 두 가지 preloader 변형으로 제공됩니다. 둘은 서로 다른 대상 디렉터리를 선택하므로 어느 쪽도 다른 쪽의 주소를 덮어쓸 수 없습니다 — Preloader variant를 참조하세요.


대상 기기

아래 팩트는 리테일 전체 OTA 패키지에서 읽어낸 것입니다 — 메타데이터, A/B payload 매니페스트, 그리고 payload.bin에서 추출한 boot/vendor_boot/dtbo 이미지.

여기서는 SoC보다 커널이 더 중요합니다: warhol은 업스트림 popsicle과 동일한 GKI 브랜치 (android16-5, 4K 페이지)에 있으며, 패치레벨 하나 차이입니다 — 6.12.38 vs popsicle의 검증된 6.12.23. struct 오프셋은 여전히 빌드마다 재생성해야 합니다; exploit의 형태만 그대로 이어집니다. 다른 OS3.0.x 빌드는 자체 target.h가 필요합니다.


이 베이스를 사용하는 이유

exploit 체인은 SoC가 아닌 GKI 브랜치에 버전이 고정되어 있습니다. rt_mutex waiter 레이아웃, pselect 스택 오버레이 및 pipe_buffer struct 오프셋은 모두 커널을 따르므로, 6.12/android16 베이스가 이전 브랜치의 동일 벤더 베이스보다 낫습니다.

x-spy/CVE-2026-43499-popsicle는 6.12/android16 GKI 라인(Xiaomi 17 / Pro / Ultra, 커널 6.12.23-android16-5)에서 검증된 유일한 공개 구현체이므로, source/는 여기서 가져와 업스트림과 최대한 가깝게 유지합니다 — 두 줄만 제외하고 (이 기기가 전혀 작동하려면 반드시 필요한 Kernel MTE 참조).

MediaTek 델타의 대부분은 빌드 타임 대상 생성에 국한되며, 두 부분으로 나뉩니다:

  • 업스트림은 Qualcomm 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은 boot.img 안에 커널을 bare arm64 Image가 아닌 LZ4-legacy 압축 형태로 제공하므로, 생성기는 분석 전에 이를 압축 해제합니다.

WARHOL_PORT.md §2에 전체 유도 과정이 있습니다.


Preloader variant

MediaTek lk는 커널을 컴파일 타임 상수로 로드하지 않습니다 — mb_kernel이라는 DRAM 예약을 조회하고 정확히 그 위치에 도달했는지 확인합니다. 이 예약은 preloader가 만듭니다. 그래서 폰에서 실행 중인 preloader 빌드가 여기서 빌드 입력이 되는 것입니다: boot.img 외부에서 P0_KERNEL_PHYS_LOAD를 움직일 수 있는 유일한 요소이며, 그 값이 틀리면 exploit 실패가 아니라 잘못된 linear-map 별칭과 죽은 폰을 의미합니다.

따라서 두 가지 변형이 있으며, 별도의 대상 디렉터리로 유지됩니다:

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는 retail과 바이트 단위로 동일하게 나오고 두 빌드는 동일한 preload.so를 생성합니다.

실제로 exploit에 도달하는 것은 차이값 P0_KERNEL_PHYS_LOAD − P0_PHYS_OFFSET이며, 그 두 항은 동일하게 확실한 근거에 기반하지 않습니다:

  • P0_KERNEL_PHYS_LOAD — 위의 mb_kernel.start처럼 eng 이미지에서 측정된 값.
  • P0_PHYS_OFFSET — 측정이 아닌 논증으로 결정됨. 이는 memstart_addr이기 때문인데, 커널은 DRAM 초기화 후 preloader가 보고하는 내용을 lk가 런타임에 출력하는 /memory 노드에서 가져오며, 생성기가 읽는 정적 FDT가 아닙니다. 논증은 다음과 같았습니다: 두 빌드는 전체 DRAM 경로를 공유하며 — 동일한 dramc/emi/mblock/memory_layout 소스, eng 전용 문자열 중 메모리 레이아웃 코드 없음 — 그리고 eng preloader의 추가 예약 하나(3 MiB 동적 security_fe_rsv, mapping=1)는 고정 주소 항목을 옮기지도 DRAM 하단에 구멍을 내지도 못합니다. 기기 실행으로 결판이 났습니다: linear-map 별칭이 eng에서 정확히 맞아떨어졌으므로 이 항은 올바릅니다.

전체 유도 과정은 targets/warhol-OS3.0.304.0.WPSJPXM-eng/NOTES.md에 있습니다.

기기 실행에서 얻은 참고 사항:

  • BootROM은 이 eng preloader를 수용합니다 — ro.boot.verifiedbootstate=green과 flash.locked=1이 변경되지 않은 채 정상적으로 Android로 부팅되었습니다. 이는 직접 시도하기 전까지 미해결 질문이었습니다. efuse에 각인된 루트 키 해시로 결정되며, 이 빌드는 retail과 동일한 키로 서명되었습니다.
  • eng preloader는 META / 팩토리 다운로드 모드를 활성 상태로 유지합니다: %s META DIS는 retail 전용 문자열인 반면, eng는 retail에는 없는 전체 META 구현(Enable fastmeta., FAST META GPIO: %d, META_COM PORT: %d, read_meta_proinfo, …)을 포함합니다. 여기서는 Android로 바로 부팅되었지만, eng가 플래시된 폰이 다른 곳으로 떨어진다면 그것이 유력한 원인이며 어떤 target.h 값도 연루되지 않습니다.
  • 이후 펌웨어가 mb_kernel을 옮기면 두 대상은 갈라집니다 — 별도 디렉터리로 유지하는 것이 이를 조용히 지나치지 않게 막는 방법입니다.

Kernel MTE

이 커널은 KASAN_HW_TAGS로 실행됩니다 — /proc/cmdline에 kasan.stack_ring_size=524288이 포함됨 — 따라서 slab 포인터는 비트 59:56에 할당 태그를 지닙니다. 업스트림 popsicle은 태그 없는 포인터를 가정하므로 이 기기를 전혀 루팅할 수 없습니다: [-] kernel page retry N/12 mode=1에서 무한히 반복되며, 로그에는 이유가 나타나지 않습니다.

source/의 두 줄이 이를 수정하며, 둘 다 warhol-mte-fix.patch에 있습니다:

검사만 태그를 제거합니다. 포인터 자체는 태그된 상태로 유지됩니다. 태그가 가리키는 메모리에 대해 올바른 태그이기 때문입니다 — 커널이 이를 역참조할 때 정확히 필요한 것입니다.

이 용도로 arm64.memtag.bootctl을 읽지 마십시오: 이 속성은 사용자 공간 MTE 제어이며 커널이 자체 할당에 태그를 지정하는지 여부를 알려주지 않습니다.


업스트림 / 참조

이 저장소는 포팅입니다. exploit 체인의 공로는 업스트림에 있습니다.


레이아웃

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 상태는 메모리에서 패치되므로 부팅할 때마다 이 작업을 반복해야 합니다. 부트로더 잠금 해제는 필요하지 않습니다.


면책 조항

소유한 하드웨어에 대한 연구용입니다. 실행하면 기기가 부팅 루프에 빠지거나 벽돌이 될 수 있으며 보증이 무효화됩니다. 어떠한 종류의 보증도 제공되지 않습니다.

업스트림 프로젝트는 각 저자의 라이선스를 따릅니다; 이 포팅은 그 조건을 계승합니다.

도구 다운로드
항목값출처
코드네임warholpre-device=warhol
빌드 핑거프린트Xiaomi/warhol_global/warhol:16/BP2A.250605.031.A3/OS3.0.304.0.WPSJPXM:user/release-keyspost-build
IncrementalOS3.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
SoCMediaTek MT6993 (Dimensity 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에서 읽은 배너
boot 이미지header v4, 커널 18,898,125 B, LZ4-legacy 압축, ramdisk 없음tools/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() 범위 검사 전 태그 제거커널 메모리에서 읽은 태그된 포인터는 그렇지 않으면 linear-map에 없는 것으로 거부됨 (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이 포팅의 베이스. Xiaomi 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가장 가까운 자매 기기(Xiaomi 17T, chagall, 역시 MediaTek). popsicle 기반, 사전 빌드된 preload.so 포함 — 포함된 컴파일 상수가 물리 로드 오프셋을 확인해 줌
https://github.com/MiCode/Xiaomi_Kernel_OpenSourceXiaomi 커널 소스, struct 레이아웃 교차 확인용