macOS IPC - Inter Process Communication
Last updated
Last updated
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Mach कार्य को संसाधनों को साझा करने के लिए सबसे छोटे इकाई के रूप में उपयोग करता है, और प्रत्येक कार्य में कई थ्रेड हो सकते हैं। ये कार्य और थ्रेड POSIX प्रक्रियाओं और थ्रेड्स के लिए 1:1 मैप किए जाते हैं।
कार्य के बीच संचार Mach इंटर-प्रोसेस संचार (IPC) के माध्यम से होता है, जो एकतरफा संचार चैनलों का उपयोग करता है। संदेश पोर्ट के बीच स्थानांतरित होते हैं, जो कर्नेल द्वारा प्रबंधित संदेश कतारों के रूप में कार्य करते हैं।
एक पोर्ट Mach IPC का बुनियादी तत्व है। इसका उपयोग संदेश भेजने और प्राप्त करने के लिए किया जा सकता है।
प्रत्येक प्रक्रिया में एक IPC तालिका होती है, जिसमें प्रक्रिया के mach पोर्ट मिल सकते हैं। एक mach पोर्ट का नाम वास्तव में एक संख्या है (कर्नेल ऑब्जेक्ट के लिए एक पॉइंटर)।
एक प्रक्रिया एक पोर्ट नाम कुछ अधिकारों के साथ एक अलग कार्य को भी भेज सकती है और कर्नेल इस प्रविष्टि को दूसरे कार्य की IPC तालिका में प्रदर्शित करेगा।
पोर्ट अधिकार, जो यह परिभाषित करते हैं कि एक कार्य कौन से संचालन कर सकता है, इस संचार के लिए कुंजी हैं। संभावित पोर्ट अधिकार हैं (definitions from here):
प्राप्ति अधिकार, जो पोर्ट पर भेजे गए संदेशों को प्राप्त करने की अनुमति देता है। Mach पोर्ट MPSC (multiple-producer, single-consumer) कतारें हैं, जिसका अर्थ है कि पूरे सिस्टम में प्रत्येक पोर्ट के लिए केवल एक प्राप्ति अधिकार हो सकता है (पाइप के विपरीत, जहां कई प्रक्रियाएं एक पाइप के पढ़ने के अंत के लिए फ़ाइल वर्णनकर्ता रख सकती हैं)।
एक कार्य जिसके पास प्राप्ति अधिकार है, संदेश प्राप्त कर सकता है और भेजने के अधिकार बना सकता है, जिससे इसे संदेश भेजने की अनुमति मिलती है। मूल रूप से केवल स्वयं कार्य के पास अपने पोर्ट पर प्राप्ति अधिकार होता है।
यदि प्राप्ति अधिकार का मालिक मर जाता है या इसे मारता है, तो भेजने का अधिकार बेकार हो जाता है (मृत नाम)।
भेजने का अधिकार, जो पोर्ट पर संदेश भेजने की अनुमति देता है।
भेजने का अधिकार क्लोन किया जा सकता है, इसलिए एक कार्य जो भेजने के अधिकार का मालिक है, अधिकार को क्लोन कर सकता है और इसे तीसरे कार्य को दे सकता है।
ध्यान दें कि पोर्ट अधिकार को Mac संदेशों के माध्यम से भी बीतित किया जा सकता है।
एक बार भेजने का अधिकार, जो पोर्ट पर एक संदेश भेजने की अनुमति देता है और फिर गायब हो जाता है।
यह अधिकार क्लोन नहीं किया जा सकता, लेकिन इसे स्थानांतरित किया जा सकता है।
पोर्ट सेट अधिकार, जो एक पोर्ट सेट को दर्शाता है न कि एकल पोर्ट। एक पोर्ट सेट से संदेश को डीक्यू करने से उस पोर्ट में से एक संदेश डीक्यू होता है जिसे यह शामिल करता है। पोर्ट सेट का उपयोग एक साथ कई पोर्ट पर सुनने के लिए किया जा सकता है, जैसे कि Unix में select
/poll
/epoll
/kqueue
।
मृत नाम, जो वास्तव में एक वास्तविक पोर्ट अधिकार नहीं है, बल्कि केवल एक प्लेसहोल्डर है। जब एक पोर्ट नष्ट होता है, तो पोर्ट के लिए सभी मौजूदा पोर्ट अधिकार मृत नामों में बदल जाते हैं।
कार्य SEND अधिकारों को दूसरों को स्थानांतरित कर सकते हैं, जिससे उन्हें संदेश वापस भेजने की अनुमति मिलती है। SEND अधिकारों को भी क्लोन किया जा सकता है, इसलिए एक कार्य डुप्लिकेट कर सकता है और तीसरे कार्य को अधिकार दे सकता है। यह, एक मध्यवर्ती प्रक्रिया के साथ मिलकर जिसे बूटस्ट्रैप सर्वर के रूप में जाना जाता है, कार्यों के बीच प्रभावी संचार की अनुमति देता है।
फाइल पोर्ट्स Mac पोर्ट्स में फ़ाइल वर्णनकर्ताओं को संलग्न करने की अनुमति देते हैं (Mach पोर्ट अधिकारों का उपयोग करके)। एक दिए गए FD से fileport_makeport
का उपयोग करके एक fileport
बनाना संभव है और एक fileport से FD बनाने के लिए fileport_makefd
का उपयोग करना संभव है।
जैसा कि पहले उल्लेख किया गया है, Mach संदेशों का उपयोग करके अधिकार भेजना संभव है, हालाँकि, आप एक अधिकार नहीं भेज सकते बिना पहले से एक अधिकार होने के। तो, पहला संचार कैसे स्थापित किया जाता है?
इसके लिए, बूटस्ट्रैप सर्वर (launchd in mac) शामिल है, क्योंकि कोई भी बूटस्ट्रैप सर्वर को SEND अधिकार प्राप्त कर सकता है, यह संभव है कि इसे किसी अन्य प्रक्रिया को संदेश भेजने के लिए अधिकार मांगा जाए:
कार्य A एक नया पोर्ट बनाता है, उस पर प्राप्ति अधिकार प्राप्त करता है।
कार्य A, जो प्राप्ति अधिकार का धारक है, पोर्ट के लिए एक SEND अधिकार उत्पन्न करता है।
कार्य A बूटस्ट्रैप सर्वर के साथ एक संयोग स्थापित करता है, और उसे पोर्ट के लिए SEND अधिकार भेजता है जिसे उसने शुरुआत में उत्पन्न किया था।
याद रखें कि कोई भी बूटस्ट्रैप सर्वर को SEND अधिकार प्राप्त कर सकता है।
कार्य A बूटस्ट्रैप सर्वर को एक bootstrap_register
संदेश भेजता है ताकि दिए गए पोर्ट को एक नाम से जोड़ सके जैसे com.apple.taska
कार्य B बूटस्ट्रैप सर्वर के साथ बातचीत करता है ताकि सेवा नाम के लिए बूटस्ट्रैप लुकअप कर सके (bootstrap_lookup
)। ताकि बूटस्ट्रैप सर्वर प्रतिक्रिया दे सके, कार्य B इसे एक SEND अधिकार भेजेगा जिसे उसने पहले लुकअप संदेश के भीतर बनाया था। यदि लुकअप सफल होता है, तो सर्वर SEND अधिकार को डुप्लिकेट करता है जो कार्य A से प्राप्त हुआ और इसे कार्य B को संप्रेषित करता है।
याद रखें कि कोई भी बूटस्ट्रैप सर्वर को SEND अधिकार प्राप्त कर सकता है।
इस SEND अधिकार के साथ, कार्य B कार्य A को संदेश भेजने में सक्षम है।
द्विदिशीय संचार के लिए आमतौर पर कार्य B एक प्राप्ति अधिकार और एक SEND अधिकार के साथ एक नया पोर्ट उत्पन्न करता है, और SEND अधिकार कार्य A को देता है ताकि वह कार्य B को संदेश भेज सके (द्विदिशीय संचार)।
बूटस्ट्रैप सर्वर सेवा नाम का प्रमाणीकरण नहीं कर सकता जो एक कार्य द्वारा दावा किया गया है। इसका मतलब है कि एक कार्य संभावित रूप से किसी भी सिस्टम कार्य का अनुकरण कर सकता है, जैसे कि झूठा प्राधिकरण सेवा नाम का दावा करना और फिर हर अनुरोध को मंजूरी देना।
फिर, Apple सिस्टम-प्रदान की गई सेवाओं के नाम को सुरक्षित कॉन्फ़िगरेशन फ़ाइलों में संग्रहीत करता है, जो SIP-सुरक्षित निर्देशिकाओं में स्थित हैं: /System/Library/LaunchDaemons
और /System/Library/LaunchAgents
। प्रत्येक सेवा नाम के साथ, संबंधित बाइनरी भी संग्रहीत होती है। बूटस्ट्रैप सर्वर, इन सेवा नामों के लिए एक प्राप्ति अधिकार बनाएगा और रखेगा।
इन पूर्वनिर्धारित सेवाओं के लिए, लुकअप प्रक्रिया थोड़ी भिन्न होती है। जब एक सेवा नाम की खोज की जा रही होती है, तो launchd सेवा को गतिशील रूप से शुरू करता है। नया कार्यप्रवाह इस प्रकार है:
कार्य B एक सेवा नाम के लिए बूटस्ट्रैप लुकअप शुरू करता है।
launchd जांचता है कि कार्य चल रहा है और यदि नहीं है, तो इसे शुरू करता है।
कार्य A (सेवा) एक बूटस्ट्रैप चेक-इन (bootstrap_check_in()
) करता है। यहाँ, बूटस्ट्रैप सर्वर एक SEND अधिकार बनाता है, इसे रखता है, और प्राप्ति अधिकार कार्य A को स्थानांतरित करता है।
launchd SEND अधिकार को डुप्लिकेट करता है और इसे कार्य B को भेजता है।
कार्य B एक नया पोर्ट उत्पन्न करता है जिसमें एक प्राप्ति अधिकार और एक SEND अधिकार होता है, और SEND अधिकार कार्य A (सेवा) को देता है ताकि वह कार्य B को संदेश भेज सके (द्विदिशीय संचार)।
हालांकि, यह प्रक्रिया केवल पूर्वनिर्धारित सिस्टम कार्यों पर लागू होती है। गैर-प्रणाली कार्य अभी भी मूल रूप से वर्णित तरीके से कार्य करते हैं, जो संभावित रूप से अनुकरण की अनुमति दे सकता है।
इसलिए, launchd कभी भी क्रैश नहीं होना चाहिए या पूरा सिस्टम क्रैश हो जाएगा।
mach_msg
फ़ंक्शन, जो मूल रूप से एक सिस्टम कॉल है, Mach संदेश भेजने और प्राप्त करने के लिए उपयोग किया जाता है। फ़ंक्शन को भेजे जाने वाले संदेश को प्रारंभिक तर्क के रूप में आवश्यक है। यह संदेश mach_msg_header_t
संरचना के साथ शुरू होना चाहिए, इसके बाद वास्तविक संदेश सामग्री आती है। संरचना को इस प्रकार परिभाषित किया गया है:
Processes possessing a receive right can receive messages on a Mach port. Conversely, the senders are granted a send or a send-once right. The send-once right is exclusively for sending a single message, after which it becomes invalid.
The initial field msgh_bits
is a bitmap:
First bit (most significative) is used to indicate that a message is complex (more on this below)
The 3rd and 4th are used by the kernel
The 5 least significant bits of the 2nd byte from can be used for voucher: another type of port to send key/value combinations.
The 5 least significant bits of the 3rd byte from can be used for local port
The 5 least significant bits of the 4th byte from can be used for remote port
The types that can be specified in the voucher, local and remote ports are (from mach/message.h):
उदाहरण के लिए, MACH_MSG_TYPE_MAKE_SEND_ONCE
का उपयोग यह संकेत करने के लिए किया जा सकता है कि इस पोर्ट के लिए एक send-once अधिकार निकाला और स्थानांतरित किया जाना चाहिए। इसे MACH_PORT_NULL
के रूप में भी निर्दिष्ट किया जा सकता है ताकि प्राप्तकर्ता उत्तर देने में सक्षम न हो।
एक आसान द्वि-मार्गीय संचार प्राप्त करने के लिए, एक प्रक्रिया mach पोर्ट को निर्दिष्ट कर सकती है जो mach संदेश हेडर में reply port (msgh_local_port
) कहलाता है जहाँ संदेश का प्राप्तकर्ता इस संदेश को उत्तर भेज सकता है।
ध्यान दें कि इस प्रकार का द्वि-मार्गीय संचार XPC संदेशों में उपयोग किया जाता है जो एक पुनः खेल की अपेक्षा करते हैं (xpc_connection_send_message_with_reply
और xpc_connection_send_message_with_reply_sync
)। लेकिन आमतौर पर विभिन्न पोर्ट बनाए जाते हैं जैसा कि पहले समझाया गया है ताकि द्वि-मार्गीय संचार बनाया जा सके।
संदेश हेडर के अन्य क्षेत्र हैं:
msgh_size
: पूरे पैकेट का आकार।
msgh_remote_port
: वह पोर्ट जिस पर यह संदेश भेजा गया है।
msgh_voucher_port
: mach वाउचर।
msgh_id
: इस संदेश की ID, जिसे प्राप्तकर्ता द्वारा व्याख्यायित किया जाता है।
ध्यान दें कि mach संदेश mach port
के माध्यम से भेजे जाते हैं, जो एक एकल प्राप्तकर्ता, कई प्रेषक संचार चैनल है जो mach कर्नेल में निर्मित है। कई प्रक्रियाएँ एक mach पोर्ट पर संदेश भेज सकती हैं, लेकिन किसी भी समय केवल एकल प्रक्रिया ही पढ़ सकती है।
संदेश फिर mach_msg_header_t
हेडर द्वारा निर्मित होते हैं, इसके बाद शरीर और ट्रेलर (यदि कोई हो) होता है और यह उत्तर देने की अनुमति दे सकता है। इन मामलों में, कर्नेल को केवल एक कार्य से दूसरे कार्य में संदेश पास करने की आवश्यकता होती है।
एक ट्रेलर कर्नेल द्वारा संदेश में जोड़ी गई जानकारी है (जिसे उपयोगकर्ता द्वारा सेट नहीं किया जा सकता) जिसे संदेश प्राप्ति में MACH_RCV_TRAILER_<trailer_opt>
फ्लैग के साथ अनुरोध किया जा सकता है (विभिन्न जानकारी अनुरोध की जा सकती है)।
हालांकि, अन्य अधिक जटिल संदेश हैं, जैसे अतिरिक्त पोर्ट अधिकारों को पास करने या मेमोरी साझा करने वाले, जहाँ कर्नेल को भी इन वस्तुओं को प्राप्तकर्ता को भेजने की आवश्यकता होती है। इन मामलों में हेडर msgh_bits
का सबसे महत्वपूर्ण बिट सेट किया जाता है।
पास करने के लिए संभावित वर्णनकर्ताओं को mach/message.h
में परिभाषित किया गया है:
In 32बिट्स में, सभी डिस्क्रिप्टर्स 12B होते हैं और डिस्क्रिप्टर प्रकार 11वें में होता है। 64 बिट्स में, आकार भिन्न होते हैं।
कर्नेल एक कार्य से दूसरे कार्य में डिस्क्रिप्टर्स की कॉपी करेगा लेकिन पहले कर्नेल मेमोरी में एक कॉपी बनाएगा। इस तकनीक को "फेंग शुई" के रूप में जाना जाता है, जिसका कई एक्सप्लॉइट्स में दुरुपयोग किया गया है ताकि कर्नेल अपने मेमोरी में डेटा कॉपी करे जिससे एक प्रक्रिया अपने लिए डिस्क्रिप्टर्स भेज सके। फिर प्रक्रिया संदेश प्राप्त कर सकती है (कर्नेल उन्हें मुक्त कर देगा)।
यह भी संभव है कि एक कमजोर प्रक्रिया को पोर्ट अधिकार भेजे जाएं, और पोर्ट अधिकार बस प्रक्रिया में दिखाई देंगे (भले ही वह उन्हें संभाल नहीं रही हो)।
ध्यान दें कि पोर्ट कार्य नामस्थान से जुड़े होते हैं, इसलिए एक पोर्ट बनाने या खोजने के लिए, कार्य नामस्थान को भी क्वेरी किया जाता है (अधिक जानकारी के लिए mach/mach_port.h
देखें):
mach_port_allocate
| mach_port_construct
: एक पोर्ट बनाएँ।
mach_port_allocate
एक पोर्ट सेट भी बना सकता है: पोर्ट्स के समूह पर प्राप्त अधिकार। जब भी एक संदेश प्राप्त होता है, यह इंगित करता है कि यह किस पोर्ट से था।
mach_port_allocate_name
: पोर्ट का नाम बदलें (डिफ़ॉल्ट 32बिट पूर्णांक)
mach_port_names
: एक लक्ष्य से पोर्ट नाम प्राप्त करें
mach_port_type
: एक नाम पर कार्य के अधिकार प्राप्त करें
mach_port_rename
: एक पोर्ट का नाम बदलें (जैसे FDs के लिए dup2)
mach_port_allocate
: एक नया RECEIVE, PORT_SET या DEAD_NAME आवंटित करें
mach_port_insert_right
: एक पोर्ट में एक नया अधिकार बनाएं जहां आपके पास RECEIVE है
mach_port_...
mach_msg
| mach_msg_overwrite
: माच संदेश भेजने और प्राप्त करने के लिए उपयोग की जाने वाली फ़ंक्शन। ओवरराइट संस्करण संदेश प्राप्ति के लिए एक अलग बफर निर्दिष्ट करने की अनुमति देता है (दूसरा संस्करण बस इसका पुन: उपयोग करेगा)।
चूंकि फ़ंक्शन mach_msg
और mach_msg_overwrite
का उपयोग संदेश भेजने और प्राप्त करने के लिए किया जाता है, इसलिए उन पर एक ब्रेकपॉइंट सेट करने से भेजे गए और प्राप्त किए गए संदेशों का निरीक्षण करने की अनुमति मिलेगी।
उदाहरण के लिए, किसी भी एप्लिकेशन को डिबग करना शुरू करें जिसे आप डिबग कर सकते हैं क्योंकि यह libSystem.B
लोड करेगा जो इस फ़ंक्शन का उपयोग करेगा।
mach_msg
के तर्क प्राप्त करने के लिए रजिस्टरों की जांच करें। ये तर्क हैं (से mach/message.h):
रजिस्ट्रियों से मान प्राप्त करें:
संदेश हेडर की जांच करें पहले तर्क की जांच करते हुए:
mach_msg_bits_t
प्रकार का उपयोग उत्तर की अनुमति देने के लिए बहुत सामान्य है।
The name वह डिफ़ॉल्ट नाम है जो पोर्ट को दिया गया है (चेक करें कि यह पहले 3 बाइट्स में कैसे बढ़ रहा है)। ipc-object
पोर्ट का अविकृत अद्वितीय पहचानकर्ता है।
यह भी ध्यान दें कि केवल send
अधिकार वाले पोर्ट इसके स्वामी की पहचान कर रहे हैं (पोर्ट नाम + pid)।
यह भी ध्यान दें कि +
का उपयोग एक ही पोर्ट से जुड़े अन्य कार्यों को इंगित करने के लिए किया गया है।
procesxp का उपयोग करके पंजीकृत सेवा नामों को भी देखना संभव है (SIP को com.apple.system-task-port
की आवश्यकता के कारण अक्षम किया गया है):
आप इस टूल को iOS में http://newosxbook.com/tools/binpack64-256.tar.gz से डाउनलोड करके इंस्टॉल कर सकते हैं।
ध्यान दें कि प्रेषक एक पोर्ट आवंटित करता है, नाम org.darlinghq.example
के लिए एक भेजने का अधिकार बनाता है और इसे बूटस्ट्रैप सर्वर पर भेजता है जबकि प्रेषक ने उस नाम के भेजने के अधिकार के लिए अनुरोध किया और इसका उपयोग संदेश भेजने के लिए किया।
कुछ विशेष पोर्ट हैं जो कुछ संवेदनशील क्रियाएँ करने या कुछ संवेदनशील डेटा तक पहुँचने की अनुमति देते हैं यदि किसी कार्य के पास उनके ऊपर SEND अनुमतियाँ हैं। यह इन पोर्टों को हमलावरों के दृष्टिकोण से बहुत दिलचस्प बनाता है, न केवल क्षमताओं के कारण बल्कि इसलिए कि यह कार्य के बीच SEND अनुमतियाँ साझा करना संभव है।
इन पोर्टों का प्रतिनिधित्व एक संख्या द्वारा किया जाता है।
SEND अधिकार host_get_special_port
को कॉल करके प्राप्त किए जा सकते हैं और RECEIVE अधिकार host_set_special_port
को कॉल करके। हालाँकि, दोनों कॉल के लिए host_priv
पोर्ट की आवश्यकता होती है जिसे केवल रूट ही एक्सेस कर सकता है। इसके अलावा, अतीत में रूट host_set_special_port
को कॉल करके मनमाने तरीके से हाइजैक कर सकता था, जिससे उदाहरण के लिए कोड हस्ताक्षरों को बायपास करने की अनुमति मिलती थी, जैसे कि HOST_KEXTD_PORT
को हाइजैक करके (SIP अब इसे रोकता है)।
इनका विभाजन 2 समूहों में किया गया है: पहले 7 पोर्ट कर्नेल द्वारा स्वामित्व में हैं, जिसमें 1 HOST_PORT
, 2 HOST_PRIV_PORT
, 3 HOST_IO_MASTER_PORT
और 7 HOST_MAX_SPECIAL_KERNEL_PORT
है।
संख्या 8 से शुरू होने वाले पोर्ट सिस्टम डेमन्स द्वारा स्वामित्व में हैं और इन्हें host_special_ports.h
में घोषित किया गया है।
होस्ट पोर्ट: यदि किसी प्रक्रिया के पास इस पोर्ट पर SEND विशेषाधिकार है, तो वह सूचना प्राप्त कर सकती है जैसे:
host_processor_info
: प्रोसेसर जानकारी प्राप्त करें
host_info
: होस्ट जानकारी प्राप्त करें
host_virtual_physical_table_info
: वर्चुअल/फिजिकल पेज टेबल (MACH_VMDEBUG की आवश्यकता है)
host_statistics
: होस्ट सांख्यिकी प्राप्त करें
mach_memory_info
: कर्नेल मेमोरी लेआउट प्राप्त करें
होस्ट प्रिव पोर्ट: इस पोर्ट पर SEND अधिकार वाली प्रक्रिया विशेषाधिकार प्राप्त क्रियाएँ कर सकती है जैसे बूट डेटा दिखाना या कर्नेल एक्सटेंशन लोड करने की कोशिश करना। इस अनुमति को प्राप्त करने के लिए प्रक्रिया को रूट होना चाहिए।
इसके अलावा, kext_request
API को कॉल करने के लिए अन्य अधिकारों की आवश्यकता होती है com.apple.private.kext*
जो केवल Apple बाइनरी को दिए जाते हैं।
अन्य रूटीन जो कॉल किए जा सकते हैं:
host_get_boot_info
: machine_boot_info()
प्राप्त करें
host_priv_statistics
: विशेषाधिकार प्राप्त सांख्यिकी प्राप्त करें
vm_allocate_cpm
: निरंतर भौतिक मेमोरी आवंटित करें
host_processors
: होस्ट प्रोसेसर को भेजें
mach_vm_wire
: मेमोरी को निवासित बनाएं
चूंकि रूट इस अनुमति को एक्सेस कर सकता है, यह host_set_[special/exception]_port[s]
को कॉल करके होस्ट विशेष या अपवाद पोर्ट को हाइजैक कर सकता है।
यह संभव है कि सभी होस्ट विशेष पोर्टों को चलाकर देखा जा सके:
ये पोर्ट्स प्रसिद्ध सेवाओं के लिए आरक्षित हैं। इन्हें task_[get/set]_special_port
कॉल करके प्राप्त/सेट किया जा सकता है। इन्हें task_special_ports.h
में पाया जा सकता है:
From here:
TASK_KERNEL_PORT[task-self send right]: इस कार्य को नियंत्रित करने के लिए उपयोग किया जाने वाला पोर्ट। इस कार्य को प्रभावित करने वाले संदेश भेजने के लिए उपयोग किया जाता है। यह mach_task_self (नीचे कार्य पोर्ट देखें) द्वारा लौटाया गया पोर्ट है।
TASK_BOOTSTRAP_PORT[bootstrap send right]: कार्य का बूटस्ट्रैप पोर्ट। अन्य सिस्टम सेवा पोर्ट की वापसी के लिए संदेश भेजने के लिए उपयोग किया जाता है।
TASK_HOST_NAME_PORT[host-self send right]: समाहित होस्ट की जानकारी का अनुरोध करने के लिए उपयोग किया जाने वाला पोर्ट। यह mach_host_self द्वारा लौटाया गया पोर्ट है।
TASK_WIRED_LEDGER_PORT[ledger send right]: वह पोर्ट जो इस कार्य के लिए वायर्ड कर्नेल मेमोरी का स्रोत नामित करता है।
TASK_PAGED_LEDGER_PORT[ledger send right]: वह पोर्ट जो इस कार्य के लिए डिफ़ॉल्ट मेमोरी प्रबंधित मेमोरी का स्रोत नामित करता है।
शुरुआत में Mach में "प्रक्रियाएँ" नहीं थीं, बल्कि "कार्य" थे जिन्हें धागों के कंटेनर के रूप में अधिक माना जाता था। जब Mach को BSD के साथ जोड़ा गया, तो प्रत्येक कार्य को एक BSD प्रक्रिया से संबंधित किया गया। इसलिए हर BSD प्रक्रिया के पास वह विवरण होता है जिसकी उसे एक प्रक्रिया बनने की आवश्यकता होती है और हर Mach कार्य के पास भी इसके आंतरिक कार्य होते हैं (सिवाय अस्तित्वहीन pid 0 के जो kernel_task
है)।
इससे संबंधित दो बहुत दिलचस्प कार्य हैं:
task_for_pid(target_task_port, pid, &task_port_of_pid)
: निर्दिष्ट pid
द्वारा संबंधित कार्य के कार्य पोर्ट के लिए एक SEND अधिकार प्राप्त करें और इसे निर्दिष्ट target_task_port
(जो आमतौर पर वह कॉलर कार्य होता है जिसने mach_task_self()
का उपयोग किया है, लेकिन यह एक अलग कार्य पर SEND पोर्ट भी हो सकता है) को दें।
pid_for_task(task, &pid)
: एक कार्य को SEND अधिकार दिया गया है, यह पता करें कि यह कार्य किस PID से संबंधित है।
कार्य के भीतर क्रियाएँ करने के लिए, कार्य को mach_task_self()
को कॉल करके अपने लिए एक SEND
अधिकार की आवश्यकता थी (जो task_self_trap
(28) का उपयोग करता है)। इस अनुमति के साथ, एक कार्य कई क्रियाएँ कर सकता है जैसे:
task_threads
: कार्य के धागों के सभी कार्य पोर्ट पर SEND अधिकार प्राप्त करें
task_info
: एक कार्य के बारे में जानकारी प्राप्त करें
task_suspend/resume
: एक कार्य को निलंबित या फिर से शुरू करें
task_[get/set]_special_port
thread_create
: एक धागा बनाएं
task_[get/set]_state
: कार्य की स्थिति को नियंत्रित करें
और अधिक mach/task.h में पाया जा सकता है
ध्यान दें कि एक अलग कार्य के कार्य पोर्ट पर SEND अधिकार के साथ, एक अलग कार्य पर ऐसी क्रियाएँ करना संभव है।
इसके अलावा, task_port भी vm_map
पोर्ट है जो एक कार्य के भीतर मेमोरी को पढ़ने और हेरफेर करने की अनुमति देता है जैसे कि vm_read()
और vm_write()
। इसका मूलतः मतलब है कि एक कार्य जिसके पास एक अलग कार्य के task_port पर SEND अधिकार हैं, वह उस कार्य में कोड इंजेक्ट करने में सक्षम होगा।
याद रखें कि क्योंकि कर्नेल भी एक कार्य है, यदि कोई kernel_task
पर SEND अनुमतियाँ प्राप्त करने में सफल होता है, तो वह कर्नेल को कुछ भी निष्पादित करने के लिए मजबूर कर सकता है (जेलब्रेक)।
कॉल करें mach_task_self()
इस पोर्ट के लिए नाम प्राप्त करने के लिए कॉलर कार्य के लिए। यह पोर्ट केवल exec()
के माध्यम से विरासत में लिया जाता है; fork()
के साथ बनाए गए नए कार्य को एक नया कार्य पोर्ट मिलता है (एक विशेष मामले के रूप में, एक कार्य को exec()
के बाद एक suid बाइनरी में एक नया कार्य पोर्ट भी मिलता है)। एक कार्य को उत्पन्न करने और इसके पोर्ट को प्राप्त करने का एकमात्र तरीका "पोर्ट स्वैप डांस" करना है जबकि fork()
कर रहे हैं।
ये पोर्ट तक पहुँचने के लिए प्रतिबंध हैं (बाइनरी AppleMobileFileIntegrity
से macos_task_policy
से):
यदि ऐप के पास com.apple.security.get-task-allow
अधिकार है तो समान उपयोगकर्ता की प्रक्रियाएँ कार्य पोर्ट तक पहुँच सकती हैं (जो आमतौर पर Xcode द्वारा डिबगिंग के लिए जोड़ा जाता है)। नोटरीकरण प्रक्रिया इसे उत्पादन रिलीज़ में अनुमति नहीं देगी।
com.apple.system-task-ports
अधिकार वाले ऐप किसी भी प्रक्रिया के लिए कार्य पोर्ट प्राप्त कर सकते हैं, सिवाय कर्नेल के। पुराने संस्करणों में इसे task_for_pid-allow
कहा जाता था। यह केवल Apple अनुप्रयोगों को दिया जाता है।
रूट कार्य पोर्ट्स तक पहुँच सकता है उन अनुप्रयोगों के जो एक हर्डनड रनटाइम के साथ संकलित नहीं हैं (और Apple से नहीं हैं)।
कार्य नाम पोर्ट: कार्य पोर्ट का एक अप्रिविलेज्ड संस्करण। यह कार्य को संदर्भित करता है, लेकिन इसे नियंत्रित करने की अनुमति नहीं देता। इसके माध्यम से उपलब्ध एकमात्र चीज task_info()
प्रतीत होती है।
धागों के साथ भी संबंधित पोर्ट होते हैं, जो कार्य से task_threads
को कॉल करने और प्रोसेसर से processor_set_threads
से दिखाई देते हैं। धागा पोर्ट पर SEND अधिकार thread_act
उपप्रणाली से कार्यों का उपयोग करने की अनुमति देता है, जैसे:
thread_terminate
thread_[get/set]_state
act_[get/set]_state
thread_[suspend/resume]
thread_info
...
कोई भी धागा इस पोर्ट को mach_thread_sef
को कॉल करके प्राप्त कर सकता है।
आप एक शेलकोड प्राप्त कर सकते हैं:
Introduction to ARM64v8पिछले प्रोग्राम को संकलित करें और कोड इंजेक्ट करने के लिए अधिकार जोड़ें उसी उपयोगकर्ता के साथ (यदि नहीं, तो आपको sudo का उपयोग करना होगा)।