Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
mt6985-CVE-2026-43499 — CVE-2026-43499 exploit adapter for MT6985 MediaTek Dimensity 9300 (vivo PD2241) | Kitploit
Tools/GitHubGitHub/233laoliu/mt6985-cve-2026-43499
Exploit FrameworksVulnerability AnalysisExploitationReverse EngineeringForensicsMobile SecurityFirmware AnalysisBinary Exploitation
GitHub233laoliu/mt6985-cve-2026-43499

mt6985-CVE-2026-43499

CVE-2026-43499 exploit adapter for MT6985 MediaTek Dimensity 9300 (vivo PD2241)

View Repository
1121 month agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2026-43499 Failure Log: MT6985 Adaptation Attempt

Conclusion: Spent 68M tokens, no root obtained.
Reason: KernelSnitch timing attack is unreliable on MTK Dimensity 9200, and CONFIG_PANIC_ON_OOPS=y leaves no room for trial and error.
This article documents the complete troubleshooting process for future reference.


Background

ItemValue
Devicevivo PD2241 (Dimensity 9200 / MT6985), Android 15
FirmwarePD2241_A_15.2.10.2.W10.V000L1
Kernel5.15.178-android13-8-gfb31f5bdd612-dirty
BootloaderLocked (ro.boot.flash.locked=1)
SELinuxEnforcing
panic_on_oopsEnabled → any kernel OOPS = instant reboot
ExploitCyberMeowfia — CVE-2026-43499 (IonStack)
Source treeandroid_15.0_kernel_MT6985 (5.15.178) — does not match device version (source is android15 GKI, device runs android13 GKI)

What Was Done

1. Source Analysis → Extracting Struct Offsets

Extracted from arch/arm64/include/asm/memory.h + include/linux/fs.h + android/abi_gki_aarch64.xml:

  • Memory layout: KIMAGE_TEXT_BASE = 0xffffffc008000000, VA_BITS=39, DIRECT_MAP=256GB
  • task_struct: 36864 bits, fully parsed (ABI XML layout-offset-in-bits)
  • file_operations: no iopoll (android13 GKI), IOCTL=0x48, open=0x68
  • cred: atomic_t usage = 4 bytes, uid=0x04
  • struct page: 64 bytes, slab_cache=0x18

Key finding: Source is android15 GKI, device is android13 GKI — task_struct offsets differ by 0x40~0x88 bytes, cannot blindly copy from source.

2. Firmware Unpacking → Extracting Symbols

root@kitploit:~
OTA zip (8.3GB)
  → payload.bin (8.2GB)
    → payload_dumper → boot.img (96MB, v4 header)
      → LZ4 decompress → Image (50MB ARM64)
        → kallsyms-finder → 187810 symbols

Extracted symbols from two firmware versions (15.2.7.6 / 15.2.10.2) — the same symbol differs by 10KB~200KB between versions, must use the correct version.

3. Disassembly Verification → capstone Confirms Key Offsets

root@kitploit:~
# In rt_mutex_adjust_pi:
LDR x21, [x19, #0x8b0]  → pi_blocked_on = 0x8b0 (android15 value, not frankel)

This confirmed the task_struct layout is the android15 branch, not frankel's android13.

4. Compilation → Passes

NDK r29, make PROJECT=android_15.0_kernel_MT6985 → preload.so (150KB).

5. Execution → Repeated Crashes

root@kitploit:~
[+] preload starting pid=25414
[+] p0 profile ... all symbols loaded correctly
[-] KernelSnitch mm_struct leak failed     ← sometimes absent (occasional success)
[+] slide child context route=pselect      ← slide KASLR leak child process started
[kernel panic]                                ← rt_mutex_adjust_prio_chain+0x1b0

Crash instruction (capstone):

root@kitploit:~
ldar w8, [x27]    ; x27 = waiter->lock (loaded from [x28, #0x38])
                  ; x27 value is garbage → no page table mapping → translation fault
                  ; → die() → panic → reboot

Why It Failed

Root Cause 1: KernelSnitch Unreliable on MTK

KernelSnitch is the entry point of the entire exploit — it leaks the mm_struct address through timing differences in the futex hash bucket:

  1. Collision detection succeeds — 5 collisions found at low threshold
  2. Bruteforce matching almost always fails — the core problem is:
root@kitploit:~
MT6985 has CONFIG_KASAN_HW_TAGS=y → kernel tags slab allocations with MTE tags
mm_struct pointers carry KASAN tags → futex_hash computed on tagged pointer

But bruteforce scans the direct map (untagged addresses) → computed hash doesn't match
Even with MTE tag iteration (0-14, 15 total), on VA_BITS=39 systems
tag bits (bit56-59) overlap with sign-extension bits → some tag combinations produce invalid addresses → missed detections

Pixel devices don't have KASAN_HW_TAGS, so this mechanism works there. MTK doesn't.

Root Cause 2: CONFIG_PANIC_ON_OOPS Is the Killer

root@kitploit:~
Pixel:  kernel OOPS → dump_stack → keeps running → exploit can retry
MT6985: kernel OOPS → die() → panic() → instant reboot → no room for trial and error
A slight deviation in the π chain corruption causes total collapse; on Pixel a deviation just means "this attempt failed, try another set of addresses."

And the bootloader is locked (flash.locked=1) → cannot flash a custom kernel to remove this option.

Root Cause 3: Kernel Version Drift

root@kitploit:~
Source tree: 5.15.178 android15 GKI
Device:      5.15.178-android13 (vivo vendor)

Although the major version is 5.15.178 for both, the GKI branches differ (android13 vs android15), so key struct layouts like task_struct/cred are inconsistent. After repeatedly switching between frankel/android15 offset sets, disassembly was ultimately required to lock it down.


Adjustments Attempted (All Useless)

ChangePurposeResult
THRESHOLD_MULT 10→5→3Lower collision detection threshold<5 too many false positives
APPENDED_FUTEXES 4096→8192Increase hash chain differenceNo effect
REPEAT_MEASUREMENT/AVERAGEIncrease sampling precisionNo effect
MTE=1Make bruteforce iterate tagsSlower, actually fewer crashes
MM_STRUCT_SZ 0x500→0x400Fix mm_struct strideNecessary, ABI is actually 992 bytes
IDENTITY_END 64GB→256GBExpand scan rangeToo slow (MTE iteration), still no match
TASK offsets: android15↔frankelLock down correct offsetsDisassembly confirms android15
FOPS offsets: android15↔frankelandroid13 has no iopollUsed frankel

Current State of target.h

In exploit/targets/android_15.0_kernel_MT6985/target.h:

CategoryConfidenceVerification Method
Memory layoutCorrectmemory.h calculation + kallsyms _text verification
Symbol offsets (22)CorrectExtracted from 15.2.10.2 boot.img
task_struct offsetsCorrectABI XML + capstone disassembly (pi_blocked_on=0x8b0)
FOPS offsetsIncorrect (fixed 2026-07-31)Original values copied from frankel (android13 has no iopoll); source tree ABI actually has iopoll@0x30, ioctl=0x50, open=0x70 — see VERIFICATION.md
CRED offsetsCorrect (verified)ABI XML: uid=0x04, securebits=0x24, caps=0x28, security=0x78

Assembly compiles, it runs, but loses at the last mile.


If You Want to Continue

Prerequisites (All Required)

  1. Remove CONFIG_PANIC_ON_OOPS — either flash a custom kernel (requires unlocking the bootloader), or find an MT6985 device where this option is disabled by default
  2. Fix KernelSnitch — requires cache timing calibration for MTK Dimensity 9200, or completely replace KernelSnitch with another mm_struct leak method in the exploit

Possible Alternative Approaches

  • /proc/self/pagemap — restricted on this device (returns all zeros)
  • MTK-specific debug interfaces (/proc/mtk_*) — exist but require further analysis
  • MTK camera/GPU driver ioctl vulnerabilities — simpler privilege escalation path
  • Wait for community adaptation of an MTK variant

Residual Value of This Repository

  • symbols/kallsyms_PD2241_15.2.10.2.txt — complete 15.2.10.2 symbol table, directly usable by others
  • device_config.txt — actual device kernel config, shows what the vendor changed
  • exploit/targets/android_15.0_kernel_MT6985/target.h — struct offsets verified
  • scripts/server_compile.py — automated compilation, fast rebuild after parameter changes

Pitfall Checklist (For Future Reference)

  1. Extracting files on Windows: tar -xf may fail on large zips, use Python zipfile or manually extract first
  2. payload_dumper protobuf version conflict: The generated update_metadata_pb2.py requires protobuf 5.x, need to manually remove the runtime_version import line
  3. Running ./preload.so directly segfaults: Must use /system/bin/linker64 /data/local/tmp/preload.so
  4. ABI XML is more accurate than source code: layout-offset-in-bits is computed by the compiler, 100x more accurate than manually counting 5000 bytes
  5. GKI branch affects layout: task_struct differs between android13/14/15, cannot copy offsets across branches
  6. Different firmware versions have different symbol offsets: 15.2.7.6 and 15.2.10.2 differ by 10KB~200KB
  7. vivo vendor adds many OEM fields: CONFIG_ANDROID_VENDOR_OEM_DATA=y, CONFIG_SCHED_INFO=y, CONFIG_RSC_* → deviates from standard GKI
  8. Front-to-back symbol extraction toolchain: boot.img → kernel.bin → LZ4 decompress → Image → kallsyms-finder → symbol table

Timeline

root@kitploit:~
07/28  Downloaded CyberMeowfia repository + MT6985 source
07/29  Source analysis (memory.h, fs.h, ABI XML, various structs)
       Firmware unpacking (payload.bin → boot.img → Image)
       Symbol extraction (kallsyms-finder → 187810 symbols)
       Multiple compilation rounds + multiple crashes + disassembly verification
       5 automatic retries → all failed
       Wrote this article
-------------------------------------------
Total: ~68M tokens, 0 root shells

2026-07-29, lived to tell the tale


2026-07-31 Follow-up: Verification and Corrections After Source Arrived

After obtaining android_15.0_kernel_MT6985.tar.gz (5.15.178 source tree + ABI XML), performed full cross-verification, see VERIFICATION.md for details. Summary:

  1. MT6985 = Dimensity 9200 (MT6989 is the 9300), corrected in the text above.
  2. Symbol offsets 23/23 correct (kallsyms verified), task_struct / cred / waiter / page / pipe / configfs offsets all match the source tree ABI.
  3. FOPS offsets were wrong: original values copied from frankel (android13 GKI, no iopoll, ioctl=0x48); but the device's task_struct layout (pi_blocked_on=0x8b0, confirmed via runtime disassembly) matches this source tree, so the same kernel's file_operations should have iopoll@0x30, ioctl=0x50, open=0x70, etc. — target.h has been corrected, with the exploit's built-in leak_kernel_base() real-device self-check as a fallback.
  4. KernelSnitch MTK compatibility patch (patches/kernelsnitch_mtk_fixes.patch):
    • Userspace futex hash table size changed to match the kernel (possible CPU + 2 rounded to a power of 2), avoiding guaranteed bruteforce failure when possible≠online;
    • MTE tag iteration now includes 0xf (untagged), and KSNITCH_MTE_ENABLED=1 actually takes effect (original util.c hardcoded mte=0);
    • Does not affect non-MTK targets.
  5. The crash point rt_mutex_adjust_prio_chain+0x1b0 is in the pselect/pi chain stage, earlier than the FOPS self-check; after the above fixes, it's worth re-testing on real hardware.

2026-07-31 Real-Device Testing: KernelSnitch Works Now, Slide Stage Is Still the Wall

Device (PD2241, compiler251203103903) 8+ rounds of real-device testing:

  • KernelSnitch fixed and verified: MM_STRUCT_SZ=0x400 (original 0x500 caused scan grid misalignment, producing only false positives) + MTE tag 0..15 iteration (device mm pointer tags change) + untagging forged addresses. Now reliably finds the real mm_struct.
  • Still crashes at rt_mutex_adjust_prio_chain+0x1b0 every round: pselect/pi chain timing race (forged waiter doesn't land at the correct offset on the kernel stack). vivo's RSC scheduler modified the futex/pi path, potentially breaking this race fundamentally. Slide stack alignment has been parameterized as the SLIDE_SHIFT environment variable, scan not completed.
  • FOPS/pipe/cred stages not yet reached, real-device verification to be continued.

Final decision: downgraded to paid bootloader unlock (no longer relying on this path).

Download Tool