macOS Thread Injection via Task port

Reading time: 9 minutes

tip

AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE)

HackTricks का समर्थन करें

Code

1. Thread Hijacking

शुरुआत में, task_threads() फ़ंक्शन को कार्य पोर्ट पर दूरस्थ कार्य से थ्रेड सूची प्राप्त करने के लिए लागू किया जाता है। एक थ्रेड को हाईजैक करने के लिए चुना जाता है। यह दृष्टिकोण पारंपरिक कोड इंजेक्शन विधियों से भिन्न है क्योंकि नए दूरस्थ थ्रेड को बनाने की अनुमति नहीं है क्योंकि नई रोकथाम thread_create_running() को अवरुद्ध करती है।

थ्रेड को नियंत्रित करने के लिए, thread_suspend() को कॉल किया जाता है, जिससे इसकी निष्पादन रुक जाती है।

दूरस्थ थ्रेड पर केवल रोकना और शुरू करना, पंजीकरण मानों को प्राप्त करना और संशोधित करना की अनुमति है। दूरस्थ फ़ंक्शन कॉल को पंजीकरण x0 से x7 को आर्गुमेंट्स पर सेट करके, pc को लक्षित फ़ंक्शन पर कॉन्फ़िगर करके, और थ्रेड को सक्रिय करके आरंभ किया जाता है। यह सुनिश्चित करना कि थ्रेड लौटने के बाद क्रैश न हो, लौटने का पता लगाने की आवश्यकता होती है।

एक रणनीति में दूरस्थ थ्रेड के लिए एक्सेप्शन हैंडलर को thread_set_exception_ports() का उपयोग करके पंजीकृत करना शामिल है, फ़ंक्शन कॉल से पहले lr पंजीकरण को एक अमान्य पते पर सेट करना। यह फ़ंक्शन निष्पादन के बाद एक अपवाद को ट्रिगर करता है, अपवाद पोर्ट पर एक संदेश भेजता है, थ्रेड की स्थिति की जांच करने की अनुमति देता है ताकि लौटने का मान पुनर्प्राप्त किया जा सके। वैकल्पिक रूप से, इयान बीयर के ट्रिपल_fetch एक्सप्लॉइट से अपनाई गई विधि में, lr को अनंत लूप में सेट किया जाता है। थ्रेड के पंजीकरण को तब लगातार मॉनिटर किया जाता है जब तक pc उस निर्देश की ओर इशारा नहीं करता

2. Mach ports for communication

अगले चरण में दूरस्थ थ्रेड के साथ संचार को सुविधाजनक बनाने के लिए Mach पोर्ट स्थापित करना शामिल है। ये पोर्ट कार्यों के बीच मनमाने भेजने और प्राप्त करने के अधिकारों को स्थानांतरित करने में महत्वपूर्ण हैं।

द्विदिशीय संचार के लिए, दो Mach प्राप्त करने के अधिकार बनाए जाते हैं: एक स्थानीय में और दूसरा दूरस्थ कार्य में। इसके बाद, प्रत्येक पोर्ट के लिए एक भेजने का अधिकार समकक्ष कार्य में स्थानांतरित किया जाता है, जिससे संदेशों का आदान-प्रदान संभव होता है।

स्थानीय पोर्ट पर ध्यान केंद्रित करते हुए, प्राप्त करने का अधिकार स्थानीय कार्य द्वारा रखा जाता है। पोर्ट को mach_port_allocate() के साथ बनाया जाता है। चुनौती इस पोर्ट के लिए एक भेजने के अधिकार को दूरस्थ कार्य में स्थानांतरित करने में है।

एक रणनीति में thread_set_special_port() का उपयोग करके दूरस्थ थ्रेड के THREAD_KERNEL_PORT में स्थानीय पोर्ट के लिए एक भेजने का अधिकार रखना शामिल है। फिर, दूरस्थ थ्रेड को mach_thread_self() को कॉल करने के लिए निर्देशित किया जाता है ताकि भेजने का अधिकार प्राप्त किया जा सके।

दूरस्थ पोर्ट के लिए, प्रक्रिया मूल रूप से उलट होती है। दूरस्थ थ्रेड को mach_reply_port() के माध्यम से एक Mach पोर्ट उत्पन्न करने के लिए निर्देशित किया जाता है (क्योंकि mach_port_allocate() इसकी वापसी तंत्र के कारण अनुपयुक्त है)। पोर्ट निर्माण के बाद, mach_port_insert_right() को दूरस्थ थ्रेड में एक भेजने का अधिकार स्थापित करने के लिए लागू किया जाता है। इस अधिकार को फिर thread_set_special_port() का उपयोग करके कर्नेल में रखा जाता है। स्थानीय कार्य में वापस, thread_get_special_port() का उपयोग दूरस्थ कार्य में नए आवंटित Mach पोर्ट के लिए भेजने के अधिकार को प्राप्त करने के लिए किया जाता है।

इन चरणों के पूरा होने से Mach पोर्ट स्थापित होते हैं, जो द्विदिशीय संचार के लिए आधार तैयार करते हैं।

3. Basic Memory Read/Write Primitives

इस अनुभाग में, बुनियादी मेमोरी पढ़ने और लिखने की प्राइमिटिव स्थापित करने के लिए निष्पादित प्राइमिटिव का उपयोग करने पर ध्यान केंद्रित किया गया है। ये प्रारंभिक कदम दूरस्थ प्रक्रिया पर अधिक नियंत्रण प्राप्त करने के लिए महत्वपूर्ण हैं, हालांकि इस चरण में प्राइमिटिव का अधिक उपयोग नहीं होगा। जल्द ही, उन्हें अधिक उन्नत संस्करणों में अपग्रेड किया जाएगा।

Memory Reading and Writing Using Execute Primitive

उद्देश्य विशिष्ट फ़ंक्शंस का उपयोग करके मेमोरी पढ़ने और लिखने का प्रदर्शन करना है। मेमोरी पढ़ने के लिए, निम्नलिखित संरचना के समान फ़ंक्शंस का उपयोग किया जाता है:

c
uint64_t read_func(uint64_t *address) {
return *address;
}

और मेमोरी में लिखने के लिए, इस संरचना के समान फ़ंक्शन का उपयोग किया जाता है:

c
void write_func(uint64_t *address, uint64_t value) {
*address = value;
}

ये फ़ंक्शन दिए गए असेंबली निर्देशों के अनुरूप हैं:

_read_func:
ldr x0, [x0]
ret
_write_func:
str x1, [x0]
ret

उपयुक्त फ़ंक्शनों की पहचान

सामान्य पुस्तकालयों का स्कैन इन ऑपरेशनों के लिए उपयुक्त उम्मीदवारों का खुलासा करता है:

  1. मेमोरी पढ़ना: property_getName() फ़ंक्शन Objective-C runtime library से मेमोरी पढ़ने के लिए एक उपयुक्त फ़ंक्शन के रूप में पहचाना गया है। फ़ंक्शन नीचे वर्णित है:
c
const char *property_getName(objc_property_t prop) {
return prop->name;
}

यह फ़ंक्शन प्रभावी रूप से read_func की तरह कार्य करता है, जो objc_property_t के पहले फ़ील्ड को लौटाता है।

  1. मेमोरी लिखना: मेमोरी लिखने के लिए एक पूर्व-निर्मित फ़ंक्शन खोजना अधिक चुनौतीपूर्ण है। हालाँकि, libxpc से _xpc_int64_set_value() फ़ंक्शन एक उपयुक्त उम्मीदवार है, जिसमें निम्नलिखित डिस्सेम्बली है:
c
__xpc_int64_set_value:
str x1, [x0, #0x18]
ret

एक विशिष्ट पते पर 64-बिट लिखने के लिए, दूरस्थ कॉल को इस प्रकार संरचित किया जाता है:

c
_xpc_int64_set_value(address - 0x18, value)

इन प्राइमिटिव्स की स्थापना के साथ, साझा मेमोरी बनाने के लिए मंच तैयार है, जो दूरस्थ प्रक्रिया को नियंत्रित करने में एक महत्वपूर्ण प्रगति है।

4. साझा मेमोरी सेटअप

उद्देश्य स्थानीय और दूरस्थ कार्यों के बीच साझा मेमोरी स्थापित करना है, डेटा ट्रांसफर को सरल बनाना और कई तर्कों के साथ कार्यों को कॉल करने की सुविधा प्रदान करना है। यह दृष्टिकोण libxpc और इसके OS_xpc_shmem ऑब्जेक्ट प्रकार का लाभ उठाने में शामिल है, जो मच मेमोरी प्रविष्टियों पर आधारित है।

प्रक्रिया अवलोकन:

  1. मेमोरी आवंटन:
  • साझा करने के लिए मेमोरी आवंटित करें mach_vm_allocate() का उपयोग करके।
  • आवंटित मेमोरी क्षेत्र के लिए OS_xpc_shmem ऑब्जेक्ट बनाने के लिए xpc_shmem_create() का उपयोग करें। यह फ़ंक्शन मच मेमोरी प्रविष्टि के निर्माण का प्रबंधन करेगा और OS_xpc_shmem ऑब्जेक्ट के ऑफसेट 0x18 पर मच भेजने का अधिकार संग्रहीत करेगा।
  1. दूरस्थ प्रक्रिया में साझा मेमोरी बनाना:
  • दूरस्थ प्रक्रिया में malloc() के लिए एक दूरस्थ कॉल के साथ OS_xpc_shmem ऑब्जेक्ट के लिए मेमोरी आवंटित करें।
  • स्थानीय OS_xpc_shmem ऑब्जेक्ट की सामग्री को दूरस्थ प्रक्रिया में कॉपी करें। हालाँकि, यह प्रारंभिक कॉपी ऑफसेट 0x18 पर गलत मच मेमोरी प्रविष्टि नामों के साथ होगी।
  1. मच मेमोरी प्रविष्टि को सही करना:
  • दूरस्थ कार्य में मच मेमोरी प्रविष्टि के लिए एक भेजने के अधिकार को सम्मिलित करने के लिए thread_set_special_port() विधि का उपयोग करें।
  • दूरस्थ मेमोरी प्रविष्टि के नाम के साथ इसे ओवरराइट करके ऑफसेट 0x18 पर मच मेमोरी प्रविष्टि फ़ील्ड को सही करें।
  1. साझा मेमोरी सेटअप को अंतिम रूप देना:
  • दूरस्थ OS_xpc_shmem ऑब्जेक्ट को मान्य करें।
  • xpc_shmem_remote() के लिए एक दूरस्थ कॉल के साथ साझा मेमोरी मैपिंग स्थापित करें।

इन चरणों का पालन करके, स्थानीय और दूरस्थ कार्यों के बीच साझा मेमोरी को प्रभावी ढंग से सेट किया जाएगा, जिससे सरल डेटा ट्रांसफर और कई तर्कों की आवश्यकता वाले कार्यों के निष्पादन की अनुमति मिलेगी।

अतिरिक्त कोड स्निपेट्स

मेमोरी आवंटन और साझा मेमोरी ऑब्जेक्ट निर्माण के लिए:

c
mach_vm_allocate();
xpc_shmem_create();

दूरस्थ प्रक्रिया में साझा मेमोरी ऑब्जेक्ट बनाने और सुधारने के लिए:

c
malloc(); // for allocating memory remotely
thread_set_special_port(); // for inserting send right

याद रखें कि Mach पोर्ट और मेमोरी एंट्री नामों के विवरण को सही तरीके से संभालना आवश्यक है ताकि साझा मेमोरी सेटअप सही तरीके से कार्य करे।

5. पूर्ण नियंत्रण प्राप्त करना

साझा मेमोरी स्थापित करने और मनमाने निष्पादन क्षमताओं को प्राप्त करने में सफल होने पर, हमने मूल रूप से लक्षित प्रक्रिया पर पूर्ण नियंत्रण प्राप्त कर लिया है। इस नियंत्रण को सक्षम करने वाली मुख्य कार्यक्षमताएँ हैं:

  1. मनमानी मेमोरी संचालन:
  • साझा क्षेत्र से डेटा कॉपी करने के लिए memcpy() को कॉल करके मनमानी मेमोरी पढ़ें।
  • साझा क्षेत्र में डेटा स्थानांतरित करने के लिए memcpy() का उपयोग करके मनमानी मेमोरी लिखें।
  1. कई तर्कों के साथ फ़ंक्शन कॉल को संभालना:
  • उन फ़ंक्शनों के लिए जो 8 से अधिक तर्कों की आवश्यकता होती है, कॉलिंग कन्वेंशन के अनुसार अतिरिक्त तर्कों को स्टैक पर व्यवस्थित करें।
  1. Mach पोर्ट ट्रांसफर:
  • पहले से स्थापित पोर्ट के माध्यम से Mach संदेशों के माध्यम से कार्यों के बीच Mach पोर्ट स्थानांतरित करें।
  1. फाइल डिस्क्रिप्टर ट्रांसफर:
  • triple_fetch में Ian Beer द्वारा उजागर की गई तकनीक का उपयोग करके प्रक्रियाओं के बीच फाइल डिस्क्रिप्टर्स स्थानांतरित करें।

यह व्यापक नियंत्रण threadexec पुस्तकालय के भीतर संकुचित है, जो पीड़ित प्रक्रिया के साथ बातचीत के लिए एक विस्तृत कार्यान्वयन और उपयोगकर्ता के अनुकूल API प्रदान करता है।

महत्वपूर्ण विचार:

  • सिस्टम स्थिरता और डेटा अखंडता बनाए रखने के लिए मेमोरी पढ़ने/लिखने के संचालन के लिए memcpy() का उचित उपयोग सुनिश्चित करें।
  • Mach पोर्ट या फाइल डिस्क्रिप्टर्स को स्थानांतरित करते समय, उचित प्रोटोकॉल का पालन करें और रिसोर्सेस को जिम्मेदारी से संभालें ताकि लीक या अनपेक्षित पहुंच से बचा जा सके।

इन दिशानिर्देशों का पालन करके और threadexec पुस्तकालय का उपयोग करके, कोई भी प्रक्रियाओं का कुशलतापूर्वक प्रबंधन और बातचीत कर सकता है, लक्षित प्रक्रिया पर पूर्ण नियंत्रण प्राप्त कर सकता है।

संदर्भ

tip

AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE)

HackTricks का समर्थन करें