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) Azure हैकिंग सीखें और अभ्यास करें: HackTricks Training Azure Red Team Expert (AzRTE)

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

Code

1. Thread Hijacking

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

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

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

एक रणनीति में thread_set_exception_ports() का उपयोग करके दूरस्थ थ्रेड के लिए एक अपवाद हैंडलर पंजीकृत करना शामिल है, फ़ंक्शन कॉल से पहले lr रजिस्टर को एक अमान्य पते पर सेट करना। यह फ़ंक्शन निष्पादन के बाद एक अपवाद को ट्रिगर करता है, अपवाद पोर्ट पर एक संदेश भेजता है, थ्रेड की स्थिति की जांच करने की अनुमति देता है ताकि लौटने का मान पुनर्प्राप्त किया जा सके। वैकल्पिक रूप से, इयान बीयर के triple_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 the 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() (libobjc):
c
const char *property_getName(objc_property_t prop) {
return prop->name;
}
  1. मेमोरी लिखना — _xpc_int64_set_value() (libxpc):
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() का उपयोग करें।
  1. दूरस्थ प्रक्रिया में साझा मेमोरी बनाना
  • दूरस्थ प्रक्रिया में OS_xpc_shmem ऑब्जेक्ट के लिए मेमोरी आवंटित करें (remote_malloc)।
  • स्थानीय टेम्पलेट ऑब्जेक्ट की कॉपी करें; एम्बेडेड मच भेजने के अधिकार को 0x18 ऑफसेट पर ठीक करना अभी भी आवश्यक है।
  1. मच मेमोरी प्रविष्टि को सही करना
  • thread_set_special_port() के साथ एक भेजने का अधिकार डालें और 0x18 फ़ील्ड को दूरस्थ प्रविष्टि के नाम से ओवरराइट करें।
  1. अंतिमकरण
  • दूरस्थ ऑब्जेक्ट को मान्य करें और इसे xpc_shmem_remote() के लिए एक दूरस्थ कॉल के साथ मैप करें।

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

एक बार जब मनमाना निष्पादन और साझा-मेमोरी बैक-चैनल उपलब्ध हो जाते हैं, तो आप प्रभावी रूप से लक्षित प्रक्रिया के मालिक होते हैं:

  • मनमाना मेमोरी R/W — स्थानीय और साझा क्षेत्रों के बीच memcpy() का उपयोग करें।
  • > 8 तर्कों के साथ कार्य कॉल — अतिरिक्त तर्कों को स्टैक पर रखें जो arm64 कॉलिंग सम्मेलन का पालन करते हैं।
  • मच पोर्ट ट्रांसफर — स्थापित पोर्ट के माध्यम से मच संदेशों में अधिकार पास करें।
  • फाइल-डिस्क्रिप्टर ट्रांसफर — फाइलपोर्ट्स का लाभ उठाएं (देखें triple_fetch)।

इन सभी को threadexec पुस्तकालय में आसान पुन: उपयोग के लिए लपेटा गया है।


6. एप्पल सिलिकॉन (arm64e) की बारीकियाँ

एप्पल सिलिकॉन उपकरणों (arm64e) पर पॉइंटर ऑथेंटिकेशन कोड (PAC) सभी लौटने वाले पते और कई कार्य पॉइंटर्स की सुरक्षा करते हैं। थ्रेड-हाइजैकिंग तकनीकें जो मौजूदा कोड का पुन: उपयोग करती हैं, काम करना जारी रखती हैं क्योंकि lr/pc में मूल मान पहले से ही मान्य PAC हस्ताक्षर ले जाते हैं। समस्याएँ तब उत्पन्न होती हैं जब आप हमलावर-नियंत्रित मेमोरी पर कूदने की कोशिश करते हैं:

  1. लक्षित के अंदर निष्पादन योग्य मेमोरी आवंटित करें (दूरस्थ mach_vm_allocate + mprotect(PROT_EXEC))।
  2. अपना पेलोड कॉपी करें।
  3. दूरस्थ प्रक्रिया के अंदर पॉइंटर पर हस्ताक्षर करें:
c
uint64_t ptr = (uint64_t)payload;
ptr = ptrauth_sign_unauthenticated((void*)ptr, ptrauth_key_asia, 0);
  1. हाइजैक किए गए थ्रेड स्टेट में pc = ptr सेट करें।

वैकल्पिक रूप से, मौजूदा गैजेट्स/फंक्शंस (पारंपरिक ROP) को चेन करके PAC-अनुरूप रहें।

7. Detection & Hardening with EndpointSecurity

EndpointSecurity (ES) फ्रेमवर्क कर्नेल इवेंट्स को उजागर करता है जो रक्षकों को थ्रेड-इंजेक्शन प्रयासों को देखने या ब्लॉक करने की अनुमति देता है:

  • ES_EVENT_TYPE_AUTH_GET_TASK – तब सक्रिय होता है जब एक प्रक्रिया किसी अन्य कार्य के पोर्ट का अनुरोध करती है (जैसे task_for_pid()).
  • ES_EVENT_TYPE_NOTIFY_REMOTE_THREAD_CREATE – जब भी एक थ्रेड अलग कार्य में बनाया जाता है, तब उत्पन्न होता है।
  • ES_EVENT_TYPE_NOTIFY_THREAD_SET_STATE (macOS 14 Sonoma में जोड़ा गया) – एक मौजूदा थ्रेड के रजिस्टर हेरफेर को इंगित करता है।

रिमोट-थ्रेड इवेंट्स को प्रिंट करने वाला न्यूनतम स्विफ्ट क्लाइंट:

swift
import EndpointSecurity

let client = try! ESClient(subscriptions: [.notifyRemoteThreadCreate]) {
(_, msg) in
if let evt = msg.remoteThreadCreate {
print("[ALERT] remote thread in pid \(evt.target.pid) by pid \(evt.thread.pid)")
}
}
RunLoop.main.run()

osquery ≥ 5.8 के साथ क्वेरी करना:

sql
SELECT target_pid, source_pid, target_path
FROM es_process_events
WHERE event_type = 'REMOTE_THREAD_CREATE';

Hardened-runtime विचार

आपके एप्लिकेशन को बिना com.apple.security.get-task-allow अधिकार के वितरित करने से गैर-रूट हमलावरों को इसके टास्क-पोर्ट तक पहुँचने से रोका जाता है। सिस्टम इंटीग्रिटी प्रोटेक्शन (SIP) अभी भी कई Apple बाइनरीज़ तक पहुँच को ब्लॉक करता है, लेकिन तीसरे पक्ष के सॉफ़्टवेयर को स्पष्ट रूप से ऑप्ट-आउट करना चाहिए।

8. हालिया सार्वजनिक उपकरण (2023-2025)

उपकरणवर्षटिप्पणियाँ
task_vaccine2023कॉम्पैक्ट PoC जो Ventura/Sonoma पर PAC-सचेत थ्रेड हाईजैकिंग को प्रदर्शित करता है
remote_thread_es2024EndpointSecurity सहायक जो कई EDR विक्रेताओं द्वारा REMOTE_THREAD_CREATE घटनाओं को प्रदर्शित करने के लिए उपयोग किया जाता है

इन परियोजनाओं के स्रोत कोड को पढ़ना macOS 13/14 में पेश किए गए API परिवर्तनों को समझने और Intel ↔ Apple Silicon के बीच संगत रहने के लिए उपयोगी है।

संदर्भ

tip

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

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