
# एडीबी-संचालित KernelSU लोडर स्टॉक Google Pixel के लिए: CVE-2026-43499 (GhostLock) के माध्यम से अस्थायी कर्नेल R/W, फिर चल रहे KMI के लिए हस्ताक्षर-मिलान वाले kernelsu.ko को लेट-लोड करता है। मैनेजर-अज्ञेयवादी।
एक adb-संचालित टूल जो स्टॉक, लॉक्ड-बूटलोडर Google Pixel को बूटलोडर अनलॉक किए बिना या बूट इमेज को संशोधित किए बिना KernelSU-रूटेड डिवाइस में बदल देता है। होस्ट से यह डिवाइस पर एक अनप्रिविलेज्ड यूज़रस्पेस कर्नेल एक्सप्लॉइट चलाकर अस्थायी कर्नेल रीड/राइट प्राप्त करता है, उस प्रिमिटिव का उपयोग करके रूट क्रेडेंशियल पैच करता है, और फिर चालू GKI कर्नेल में एक KernelSU लोडेबल कर्नेल मॉड्यूल (kernelsu.ko) लेट-लोड करता है और नियंत्रण उस KernelSU मैनेजर (KernelSU, KernelSU-Next, SukiSU, या कोई अन्य वैरिएंट) को सौंप देता है जो पहले से इंस्टॉल है। यह GKI 6.1 और 6.6 कर्नेल पर Android 17 Pixels को लक्षित करता है और निर्धारित अनुक्रमण और टाइमस्टैम्प्ड लॉग के लिए पूरे फ्लो को adb shell पर चलाता है।
डिवाइस-साइड पेलोड CVE-2026-43499 ("GhostLock") के लिए वेंडर किया गया फुल-चेन LPE है, जो kernel/locking/rtmutex.c में एक futex/rtmutex प्रायोरिटी-इनहेरिटेंस स्टैक use-after-free है। requeue-PI रोलबैक पथ पर, remove_waiter() वास्तविक वेटर के बजाय requeuer (current) पर pi_blocked_on को साफ़ करता है, जिससे एक डैंगलिंग पॉइंटर एक फ्री किए गए कर्नेल-स्टैक स्लॉट में रह जाता है जिसमें rt_mutex_waiter था। यह बग एक साधारण अनप्रिविलेज्ड प्रोसेस से पहुंच योग्य है:
owner, waiter, consumer) एक PI चेन बनाते हैं; waiter FUTEX_WAIT_REQUEUE_PI पर पार्क करता है, मुख्य थ्रेड FUTEX_CMP_REQUEUE_PI फायर करता है, और consumer से एक sched_setattr रोलबैक को चलाता है।pselect()/select() (या कुछ 6.1 टारगेट पर एक TCP_ZEROCOPY_RECEIVE रूट) द्वारा पुनः प्राप्त किया जाता है जिसके fd_set शब्द waiter स्ट्रक्चर पर आते हैं, एक जाली फ्लैट rt_mutex_waiter लिखते हैं ताकि डैंगलिंग पॉइंटर हमलावर-नियंत्रित rb-tree और lock फ़ील्ड्स पर चले — एक एकल नियंत्रित पॉइंटर-राइट प्रिमिटिव।mm_struct/sk_buff/ ऑब्जेक्ट्स को रखने वाले slab पेज को खोजने के लिए एक कर्नेल-हीप/डायरेक्ट-मैप पता प्राप्त करता है।रूट और SELinux स्थिति फिर पाइप प्रिमिटिव के माध्यम से पैच की जाती है: रूट-चाइल्ड टास्क का cred पूर्ण क्षमता सेट के साथ uid/gid 0 पर शून्य किया जाता है, इसका SELinux osid/sid SECINITSID_KERNEL पर सेट किया जाता है, seccomp साफ़ किया जाता है, और selinux_state.enforcing 0 पर सेट किया जाता है।
एक्सप्लॉइट चेन, KASLR ओरेकल, और KernelSnitch साइड चैनल NebuSec के IonStack Part II — GhostLock शोध ( NebuSec/CyberMeowfia PoC, Apache-2.0) से उत्पन्न होते हैं, जिन्हें यहाँ Pixel/aarch64 के लिए अनुकूलित किया गया है। देखें Attribution & License।
चेन का ठीक एक चरण कर्नेल को पैनिक कर सकता है: KASLR स्लाइड व्युत्पत्ति, जो एक पेज के साथ रेस करता है जिसे वह पुनः प्राप्त करने की आशा करता है। हर दूसरा चरण रीट्राई-सुरक्षित है, और कर्नेल-टेक्स्ट बेस एक एकल बूट के जीवनकाल के लिए निश्चित है। होस्ट फ्लो इस गुण पर विभाजित होता है:
KASLR_BASE के चलता है। जाली-वेटर राइट random_table sysctl ctl_table.data को एक ज्ञात कर्नेल-टेक्स्ट पॉइंटर पर पुनः इंगित करता है; /proc/sys/kernel/random/boot_id पढ़ना इसे proc_do_uuid() के माध्यम से लीक करता है, और इमेज ऑफसेट घटाने पर _stext/KASLR बेस मिलता है। restore_slide_boot_id() दूषित ctl_table.data की मरम्मत करता है। क्योंकि एक खोई हुई रेस डिवाइस को रीबूट करती है, हर प्रयास से पहले एक वेट-फॉर-बूट होता है और एक लाइवनेस जांच एक गायब होने को पैनिक के रूप में वर्गीकृत करती है। सफलता पर डिवाइस लॉग slide-kaslr-ok pid=<pid> base=<hex> उत्सर्जित करता है, और बेस वर्तमान बूट के लिए पिन किया जाता है।KASLR_BASE=0x<base> निर्यात के साथ फिर से चलता है। यह पथ कभी पैनिक नहीं करता और तब तक लूप किया जाता है जब तक id अस्थायी su के माध्यम से रिपोर्ट नहीं करता।कनेक्टेड डिवाइस को रनटाइम पर data/targets.json के विरुद्ध हल किया जाता है; कुछ भी डिवाइस-हार्डकोडेड नहीं है। दो स्वतंत्र समाधान होते हैं:
uname -r) से लिया जाता है, या तो मिलान किए गए टारगेट प्रविष्टि से या रिलीज़ स्ट्रिंग से व्युत्पन्न (जैसे android14-6.1)।कई डिवाइसों में एक पेलोड का पुन: उपयोग GKI/KMI संरचना से होता है। एक ही GKI बिल्ड पर हर डिवाइस बाइट-दर-बाइट समान vmlinux चलाता है, और स्ट्रक्चर-फ़ील्ड ऑफसेट (task_struct->cred, cred->uid, …) KMI प्रकार अनुबंध और MODVERSIONS CRC प्रवर्तन द्वारा एक KMI शाखा के जीवन के लिए स्थिर होते हैं। इसके विपरीत, पूर्ण कर्नेल प्रतीक पते लिंकर द्वारा प्रति ab<NNN> बिल्ड तय किए जाते हैं, इसलिए एक्सप्लॉइट के निश्चित ऑफसेट एक विशिष्ट vmlinux से संबंधित होते हैं; इसलिए अलग-अलग कर्नेल इमेजों को अलग-अलग पेलोड की आवश्यकता होती है भले ही उनका KMI मेल खाता हो। data/targets.json ठीक यही एन्कोड करता है: कई डिवाइस कर्नेल इमेज द्वारा कुंजीबद्ध एक पेलोड पर डीडुप्लिकेट होते हैं, जबकि एक अलग कर्नेल इमेज को अपना खुद का मिलता है।
LKM लेट-लोड के लिए लोडेबल-मॉड्यूल समर्थन और KMI-मिलान .ko के साथ एक GKI कर्नेल (5.10+) की आवश्यकता होती है। KernelSU कर्नेल मॉड्यूल अपने मैनेजर को कर्नेल में मैनेजर APK के v2 सिग्नेचर ब्लॉक को सत्यापित करके और साइनिंग सर्टिफिकेट के SHA-256 की तुलना .ko में संकलित KSU_EXPECTED_SIZE/KSU_EXPECTED_HASH जोड़ी के विरुद्ध करके प्रमाणित करता है। इसलिए एक मैनेजर रिलीज़ के अंदर भेजा गया kernelsu.ko और उस मैनेजर का APK एक साइनिंग पहचान साझा करते हैं; एक बेमेल ksud ड्राइवर को लोड करता है लेकिन मैनेजर-प्राधिकरण बिट कभी सेट नहीं करता, जिससे डिवाइस बिना उपयोग योग्य रूट के रह जाता है।
फ्लो इस बंधन का सम्मान करता है: यह इंस्टॉल किए गए मैनेजर के APK पथ को हल करता है (pm path <manager package>), APK खींचता है, ksud बाइनरी के रूप में lib/arm64-v8a/libksud.so निकालता है, और यदि कोई मैनेजर इंस्टॉल नहीं है तो रुक जाता है। अस्थायी रूट धारण करते हुए, वह ksud रूट-स्वामित्व वाले निष्पादन योग्य के रूप में स्टेज किया जाता है और ksud late-load --kmi <kmi> --package-name <manager package> के रूप में आमंत्रित किया जाता है। लेट-लोड वर्तमान KMI का पता लगाता है, अपनी एम्बेडेड एसेट्स से "{kmi}_kernelsu.ko" खींचता है, मैनुअल प्रतीक पुनर्वासन करता है (प्रत्येक SHN_UNDEF प्रतीक को /proc/kallsyms के विरुद्ध हल करता है, प्रविष्टियों को SHN_ABS में फिर से लिखता है), और पैच किए गए बफर पर init_module(2) कहता है। फिर यह शेष बूट पाइपलाइन चलाता है जो init करेगा (ksud इंस्टॉल करें, restorecon, sepolicy.rule और रूट प्रोफाइल लोड करें, post-fs-data/स्टेज स्क्रिप्ट चलाएं, मॉड्यूल ओवरले माउंट करें)।
लेट-लोड डेमोनाइज़ करता है और अपने फोर्क किए गए चाइल्ड में SELinux को फिर से लागू करता है, जो एक्सप्लॉइट के अस्थायी-su डेमॉन को तोड़ देता है; इसलिए सत्यापन su के माध्यम से नहीं जाना चाहिए। इसके बजाय लोड किया गया ड्राइवर सीधे उसके सिस्कॉल सतह के माध्यम से क्वेरी किया जाता है, जो बिना रूट के एक सादे शेल से पहुंच योग्य है: ksud debug version को पोल किया जाता है और रिपोर्ट किया गया कर्नेल संस्करण पार्स किया जाता है। एक गैर-खाली, गैर-शून्य संस्करण पुष्टि करता है कि ड्राइवर निवासी है और उत्तर दे रहा है। ड्राइवर इंस्टॉल पथ reboot(2) मैजिक → इंस्टॉल-fd → KSU_IOCTL_GET_INFO तंत्र है (reboot(0xDEADBEEF, 0xCAFEBABE, 0, &fd) एक अनाम [ksu_driver] fd स्थापित करता है; GET_INFO {version, flags, features, uapi_version} लौटाता है), फॉलबैक के रूप में विरासत prctl(0xDEADBEEF, …) चैनल की जांच की जाती है। स्टार्टअप पर चलाया गया वही प्रोब पूरे फ्लो को शॉर्ट-सर्किट करता है जब मॉड्यूल वर्तमान बूट के लिए पहले से निवासी होता है।
एक्सप्लॉइट अपने अस्थायी su को /apex/com.android.virt/bin/su पर स्टेज करता है, adbd के माउंट नेमस्पेस के अंदर उस apex bin निर्देशिका पर माउंट किए गए tmpfs पर, क्योंकि वह निर्देशिका शेल PATH में /system/bin से पहले आती है — इसलिए फ्लो चलते समय adb shell में एक नंगा su अस्थायी तक पहुंचता है। लेट-लोड फिर टेम्प-su डेमॉन को तोड़ देता है (देखें (e)) शैडो को हटाए बिना, जो एक नंगा adb shell su छोड़ देता है जो एक अनाथ क्लाइंट चलाता है जो su: connect daemon: Permission denied के साथ विफल होता है भले ही रूट काम कर रहा हो, और apex के वास्तविक बाइनरी (crosvm, virtmgr, vm, …) छिपे रहते हैं। एक बार सत्यापन एक लाइव ड्राइवर की रिपोर्ट करता है, फ्लो स्टेजिंग tmpfs को अनमाउंट करता है — KernelSU के अपने /system/bin/su के माध्यम से, क्योंकि एक्सप्लॉइट का डेमॉन पहले ही जा चुका है — टेम्प-su क्लाइंट, सॉकेट और लॉग को हटाता है, और रिपोर्ट करता है कि एक सादा adb shell अब कौन सा हल करता है। यह बेस्ट-एफर्ट है: विफलता पर यह रन को विफल करने के बजाय मैनुअल कमांड के साथ चेतावनी देता है, और एक रीबूट माउंट को वैसे भी साफ़ कर देता है।
adb, डिवाइस अधिकृत हो (USB डिबगिंग सक्षम)।kernelsu.ko का स्रोत है।artifacts/exploits/ में प्रीबिल्ट एक्सप्लॉइट पेलोड (देखें Building payloads)।# adb पर एक डिवाइस; मैनेजर इंस्टॉल; पेलोड बिल्ट।
bin/pixel-ksu-root
ड्राइवर डिवाइस को data/targets.json के विरुद्ध हल करता है, दो-चरण KASLR फ्लो चलाता है, मैनेजर-व्युत्पन्न ksud के माध्यम से मॉड्यूल लेट-लोड करता है, और ड्राइवर सिस्कॉल के माध्यम से सत्यापित करता है। यह गैर-शून्य के साथ बाहर निकलता है यदि डिवाइस के लिए कोई पेलोड हल नहीं होता है, यदि कोई मैनेजर इंस्टॉल नहीं है, या यदि सत्यापन कभी लाइव ड्राइवर की रिपोर्ट नहीं करता है।
KASLR_BASE=0x<hex> — चरण B के दौरान डिवाइस पेलोड को पास किया जाता है ताकि एक निश्चित, पहले से व्युत्पन्न प्रति-बूट बेस के विरुद्ध रीप्ले किया जा सके। चरण A के दौरान अनसेट ताकि पेलोड बेस स्वयं व्युत्पन्न करे।ANDROID_NDK_HOME — Android NDK का पथ, केवल पेलोड बनाते समय आवश्यक।API — पेलोड बनाते समय NDK टूलचेन के लिए Android API स्तर (डिफ़ॉल्ट 35)।pixel-ksu-root/
├── bin/ होस्ट ड्राइवर प्रवेश बिंदु (adb-संचालित फ्लो)
├── data/
│ └── targets.json डिवाइस→पेलोड और डिवाइस→KMI समाधान तालिका
├── exploit/ वेंडर किया गया CVE-2026-43499 पेलोड स्रोत
│ ├── Makefile प्रति-टारगेट aarch64 NDK बिल्ड
│ ├── src/ android15-6.6 बेसलाइन स्रोत सेट
│ │ ├── main.c slide.c fops.c pipe.c root.c preload.c util.c
│ │ ├── su_daemon.c चेन द्वारा उत्पन्न अस्थायी-su सहायक
│ │ ├── kernelsnitch/ Futex-हैश अधिभोग साइड चैनल हेडर
│ │ └── targets/ प्रति डिवाइस+बिल्ड target.h (कर्नेल ऑफसेट)
│ └── src/61/ android14-6.1 स्रोत सेट (slide61.c, TCP रूट)
├── lib/ होस्ट-साइड साझा शेल/सहायक फ़ंक्शन
├── scripts/
│ └── build-payloads.sh पेलोड सेट बनाता और डीडुप्लिकेट करता है
├── artifacts/
│ └── exploits/ बिल्ट, डीडुप्लिकेटेड पेलोड .so फ़ाइलें
└── docs/ डिज़ाइन और विश्लेषण नोट्स
scripts/build-payloads.sh प्रति-टारगेट exploit/Makefile को लपेटता है और data/targets.json में नामित डीडुप्लिकेटेड पेलोड सेट को artifacts/exploits/ में उत्सर्जित करता है। यह प्रति डिवाइस के बजाय प्रति अद्वितीय ऑफसेट समूह (उस समूह के build_from टारगेट से) एक .so बनाता है।
export ANDROID_NDK_HOME=/path/to/android-ndk # इसमें aarch64 NDK टूलचेन होना चाहिए
scripts/build-payloads.sh # data/targets.json में हर पेलोड बनाता है
Makefile ANDROID_NDK_HOME से aarch64 NDK Clang टूलचेन का चयन करता है और एक समय में एक टारगेट संकलित करता है; API (डिफ़ॉल्ट 35) aarch64-linux-android<API>-clang ड्राइवर चुनता है। स्रोत सेट कर्नेल परिवार द्वारा चुना जाता है — android15-6.6 टारगेट src/ बेसलाइन संकलित करते हैं, android14-6.1 टारगेट src/61/ संकलित करते हैं — और प्रत्येक टारगेट के पूर्ण कर्नेल ऑफसेट src/targets/<codename>-<build>/target.h से आते हैं। एक टारगेट सीधे बनाने के लिए:
make -C exploit TARGET=husky-CP2A.260705.006
data/targets.json 18 Pixel मॉडलों को कवर करने वाली 19 डिवाइस/बिल्ड प्रविष्टियाँ सूचीबद्ध करता है (bluejay दो फर्मवेयर बिल्ड पर दिखाई देता है), जिन्हें 5 कर्नेल-ऑफसेट पेलोड में समूहीकृत किया गया है। चयन कर्नेल इमेज द्वारा होता है, इसलिए एक vmlinux साझा करने वाले डिवाइस एक पेलोड पर डीडुप्लिकेट होते हैं; एक अलग कर्नेल इमेज को अपना खुद का मिलता है।
साझा android14-6.1-a कर्नेल इमेज (6.1.157-android14-11-gbd23337e42e7-ab14791245) पर डिवाइस Pixel 6/6 Pro/6a, 7/7 Pro/7a, 8/8 Pro, और 9/9 Pro/9 Pro XL/9 Pro Fold परिवारों में फैले हैं; android14-6.1-b और android14-6.1-akita उसी KMI पर मॉडलों को अलग करते हैं जिनका कर्नेल बिल्ड या ऑफसेट भिन्न होता है; android15-6.6 Pixel 10 परिवार को कवर करता है।
NebuSec/CyberMeowfia रिपॉजिटरी में Apache-2.0 के तहत जारी; खोज का श्रेय NebuSec के VEGA टूलिंग को, 2026-07-07 को प्रकट किया गया।exploit/ ट्री NebuSec एक्सप्लॉइट के ऊपर android14-6.1 और android15-6.6 टारगेट ऑफसेट और एक KernelSU लेट-लोड डेमॉन जोड़ता है; यह कोई अलग लाइसेंस नहीं रखता और अपस्ट्रीम Apache-2.0 शर्तों को विरासत में लेता है।ksud, और मैनेजर-प्राधिकरण मॉडल प्रदान करते हैं जिसे यह टूल लेट-लोड करता है।exploit/ के अंतर्गत वेंडर किया गया स्रोत अपना अपस्ट्रीम लाइसेंस बनाए रखता है (NebuSec-व्युत्पन्न एक्सप्लॉइट के लिए Apache-2.0)। यह प्रोजेक्ट मैनेजर-अज्ञेयवादी है: यह जो भी KernelSU वैरिएंट का मैनेजर इंस्टॉल है उसे लेट-लोड करता है और किसी विशिष्ट फोर्क को लक्षित या बंडल नहीं करता है।
pipe_bufferashmem_miscs[0].fops को एक जाली file_operations के साथ अधिलेखित करता है जिसका हर स्लॉट एक वास्तविक, प्रोटोटाइप-संगत कर्नेल फ़ंक्शन (configfs_bin_write_iter, configfs_read_iter, copy_splice_read, ashmem_ioctl, noop_llseek, …) पर इंगित करता है, इसलिए फॉरवर्ड-एज CFI संतुष्ट होता है जबकि ashmem fd पर read/write/splice एक सीमित कर्नेल R/W देते हैं।pipe_buffer स्ट्रक्चर जाली बनाता है (page vmemmap↔डायरेक्ट-मैप रूपांतरण के माध्यम से किसी भी लक्ष्य पर इंगित, ops = anon_pipe_buf_ops, PIPE_BUF_FLAG_CAN_MERGE), इसलिए पाइप पर सादा read()/write() मनमाने कर्नेल पतों से और तक बाइट्स स्थानांतरित करता है — एक स्थिर मनमाना कर्नेल R/W।uid=0/proc/sys/kernel/random/boot_id की तुलना कैप्चर समय पर दर्ज बूट से करता है; कोई भी परिवर्तन बेस को त्याग देता है और चरण A पर लौटता है। एक बाहरी लूप रीबूटों में व्युत्पन्न→रीप्ले दोहराता है।suumount| पेलोड | KMI | किससे बनाया गया | डिवाइस |
|---|
android14-6.1-a | android14-6.1 | bluejay-CP2A.260705.006 | oriole, raven, bluejay (CP2A), panther, cheetah, comet, shiba, husky, lynx, caiman |
android14-6.1-b | android14-6.1 | komodo-CP2A.260705.006 | komodo, tegu, tokay |
android14-6.1-akita | android14-6.1 | akita-CP2A.260805.005 | akita |
android14-6.1-cp1a | android14-6.1 | bluejay-CP1A.260405.005 | bluejay (CP1A) |
android15-6.6 | android15-6.6 | blazer-CP2A.260705.006 | frankel, blazer, mustang, rango |