macOS GCD - Grand Central Dispatch
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)
ग्रैंड सेंट्रल डिस्पैच (GCD), जिसे libdispatch (libdispatch.dyld
) के नाम से भी जाना जाता है, macOS और iOS दोनों में उपलब्ध है। यह एक तकनीक है जिसे Apple ने मल्टीकोर हार्डवेयर पर समवर्ती (मल्टीथ्रेडेड) निष्पादन के लिए अनुप्रयोग समर्थन को अनुकूलित करने के लिए विकसित किया है।
GCD FIFO कतारें प्रदान करता है और प्रबंधित करता है जिनमें आपका अनुप्रयोग ब्लॉक ऑब्जेक्ट्स के रूप में कार्य प्रस्तुत कर सकता है। डिस्पैच कतारों में प्रस्तुत किए गए ब्लॉक सिस्टम द्वारा पूरी तरह से प्रबंधित थ्रेड्स के पूल पर निष्पादित होते हैं। GCD स्वचालित रूप से डिस्पैच कतारों में कार्यों को निष्पादित करने के लिए थ्रेड्स बनाता है और उन कार्यों को उपलब्ध कोर पर चलाने के लिए शेड्यूल करता है।
संक्षेप में, समानांतर में कोड निष्पादित करने के लिए, प्रक्रियाएँ GCD को कोड के ब्लॉक भेज सकती हैं, जो उनके निष्पादन का ध्यान रखेगा। इसलिए, प्रक्रियाएँ नए थ्रेड्स नहीं बनातीं; GCD दिए गए कोड को अपने स्वयं के थ्रेड्स के पूल के साथ निष्पादित करता है (जो आवश्यकतानुसार बढ़ या घट सकता है)।
यह समानांतर निष्पादन को सफलतापूर्वक प्रबंधित करने में बहुत सहायक है, प्रक्रियाओं द्वारा बनाए गए थ्रेड्स की संख्या को बहुत कम करता है और समानांतर निष्पादन का अनुकूलन करता है। यह उन कार्यों के लिए आदर्श है जिन्हें महान समानांतरता (ब्रूट-फोर्सिंग?) की आवश्यकता होती है या उन कार्यों के लिए जो मुख्य थ्रेड को अवरुद्ध नहीं करना चाहिए: उदाहरण के लिए, iOS पर मुख्य थ्रेड UI इंटरैक्शन को संभालता है, इसलिए कोई भी अन्य कार्यक्षमता जो ऐप को लटकाने का कारण बन सकती है (खोज, वेब तक पहुंच, फ़ाइल पढ़ना...) इस तरह से प्रबंधित की जाती है।
एक ब्लॉक एक स्वतंत्र कोड का खंड है (जैसे एक फ़ंक्शन जिसमें तर्क होते हैं जो एक मान लौटाता है) और यह बाउंड वेरिएबल भी निर्दिष्ट कर सकता है।
हालांकि, कंपाइलर स्तर पर ब्लॉक मौजूद नहीं होते, वे os_object
s होते हैं। इन वस्तुओं में से प्रत्येक दो संरचनाओं से बना होता है:
ब्लॉक लिटरल:
यह isa
फ़ील्ड से शुरू होता है, जो ब्लॉक की कक्षा की ओर इशारा करता है:
NSConcreteGlobalBlock
(ब्लॉक __DATA.__const
से)
NSConcreteMallocBlock
(हीप में ब्लॉक)
NSConcreateStackBlock
(स्टैक में ब्लॉक)
इसमें flags
होते हैं (जो ब्लॉक विवरण में उपस्थित फ़ील्ड को इंगित करते हैं) और कुछ आरक्षित बाइट्स
कॉल करने के लिए फ़ंक्शन पॉइंटर
ब्लॉक विवरण के लिए एक पॉइंटर
आयातित ब्लॉक वेरिएबल (यदि कोई हो)
ब्लॉक विवरण: इसका आकार उस डेटा पर निर्भर करता है जो उपस्थित है (जैसा कि पिछले फ़्लैग में संकेतित है)
इसमें कुछ आरक्षित बाइट्स होते हैं
इसका आकार
इसमें आमतौर पर एक Objective-C शैली के हस्ताक्षर के लिए एक पॉइंटर होगा ताकि यह पता चल सके कि पैरामीटर के लिए कितनी जगह की आवश्यकता है (फ्लैग BLOCK_HAS_SIGNATURE
)
यदि वेरिएबल संदर्भित हैं, तो इस ब्लॉक में एक कॉपी हेल्पर (शुरुआत में मान की कॉपी करना) और डिस्पोज़ हेल्पर (इसे मुक्त करना) के लिए पॉइंटर भी होंगे।
एक डिस्पैच कतार एक नामित वस्तु है जो निष्पादन के लिए ब्लॉकों का FIFO क्रम प्रदान करती है।
ब्लॉकों को निष्पादित करने के लिए कतारों में सेट किया जाता है, और ये 2 मोड का समर्थन करते हैं: DISPATCH_QUEUE_SERIAL
और DISPATCH_QUEUE_CONCURRENT
। बेशक, श्रृंखलाबद्ध वाला रेस कंडीशन समस्याओं का सामना नहीं करेगा क्योंकि एक ब्लॉक तब तक निष्पादित नहीं होगा जब तक कि पिछले वाला समाप्त नहीं हो गया है। लेकिन दूसरे प्रकार की कतार में यह हो सकता है।
डिफ़ॉल्ट कतारें:
.main-thread
: dispatch_get_main_queue()
से
.libdispatch-manager
: GCD का कतार प्रबंधक
.root.libdispatch-manager
: GCD का कतार प्रबंधक
.root.maintenance-qos
: सबसे कम प्राथमिकता वाले कार्य
.root.maintenance-qos.overcommit
.root.background-qos
: DISPATCH_QUEUE_PRIORITY_BACKGROUND
के रूप में उपलब्ध
.root.background-qos.overcommit
.root.utility-qos
: DISPATCH_QUEUE_PRIORITY_NON_INTERACTIVE
के रूप में उपलब्ध
.root.utility-qos.overcommit
.root.default-qos
: DISPATCH_QUEUE_PRIORITY_DEFAULT
के रूप में उपलब्ध
.root.background-qos.overcommit
.root.user-initiated-qos
: DISPATCH_QUEUE_PRIORITY_HIGH
के रूप में उपलब्ध
.root.background-qos.overcommit
.root.user-interactive-qos
: सबसे उच्च प्राथमिकता
.root.background-qos.overcommit
ध्यान दें कि यह सिस्टम होगा जो निर्धारित करेगा कि प्रत्येक समय कौन से थ्रेड्स कौन सी कतारों को संभालते हैं (कई थ्रेड्स एक ही कतार में काम कर सकते हैं या एक ही थ्रेड विभिन्न कतारों में किसी बिंदु पर काम कर सकता है)
जब dispatch_queue_create
के साथ एक कतार बनाई जाती है, तो तीसरा तर्क एक dispatch_queue_attr_t
होता है, जो आमतौर पर या तो DISPATCH_QUEUE_SERIAL
(जो वास्तव में NULL है) या DISPATCH_QUEUE_CONCURRENT
होता है, जो एक dispatch_queue_attr_t
संरचना के लिए एक पॉइंटर है जो कतार के कुछ पैरामीटर को नियंत्रित करने की अनुमति देता है।
libdispatch द्वारा उपयोग की जाने वाली कई वस्तुएँ हैं और कतारें और ब्लॉक केवल उनमें से 2 हैं। इन वस्तुओं को dispatch_object_create
के साथ बनाया जा सकता है:
block
data
: डेटा ब्लॉक
group
: ब्लॉकों का समूह
io
: Async I/O अनुरोध
mach
: Mach पोर्ट
mach_msg
: Mach संदेश
pthread_root_queue
: pthread थ्रेड पूल के साथ एक कतार और कार्य कतार नहीं
queue
semaphore
source
: इवेंट स्रोत
Objective-C में समानांतर निष्पादन के लिए एक ब्लॉक भेजने के लिए विभिन्न फ़ंक्शन हैं:
dispatch_async: एक डिस्पैच कतार पर असिंक्रोनस निष्पादन के लिए एक ब्लॉक प्रस्तुत करता है और तुरंत लौटता है।
dispatch_sync: निष्पादन के लिए एक ब्लॉक ऑब्जेक्ट प्रस्तुत करता है और उस ब्लॉक के निष्पादित होने के बाद लौटता है।
dispatch_once: एक एप्लिकेशन के जीवनकाल के लिए केवल एक बार एक ब्लॉक ऑब्जेक्ट को निष्पादित करता है।
dispatch_async_and_wait: निष्पादन के लिए एक कार्य आइटम प्रस्तुत करता है और केवल तब लौटता है जब यह निष्पादित होना समाप्त हो जाता है। dispatch_sync
के विपरीत, यह फ़ंक्शन ब्लॉक को निष्पादित करते समय कतार के सभी गुणों का सम्मान करता है।
ये फ़ंक्शन इन पैरामीटर की अपेक्षा करते हैं: dispatch_queue_t
queue,
dispatch_block_t
block
यह एक ब्लॉक का संरचना है:
और यह dispatch_async
के साथ parallelism का उपयोग करने का एक उदाहरण है:
libswiftDispatch
एक पुस्तकालय है जो Swift bindings प्रदान करता है Grand Central Dispatch (GCD) ढांचे के लिए जो मूल रूप से C में लिखा गया है।
libswiftDispatch
पुस्तकालय C GCD APIs को एक अधिक Swift-फ्रेंडली इंटरफेस में लपेटता है, जिससे Swift डेवलपर्स के लिए GCD के साथ काम करना आसान और अधिक सहज हो जाता है।
DispatchQueue.global().sync{ ... }
DispatchQueue.global().async{ ... }
let onceToken = DispatchOnce(); onceToken.perform { ... }
async await
var (data, response) = await URLSession.shared.data(from: URL(string: "https://api.example.com/getData"))
Code example:
निम्नलिखित Frida स्क्रिप्ट का उपयोग कई dispatch
फ़ंक्शंस में हुक करने और कतार का नाम, बैकट्रेस और ब्लॉक निकालने के लिए किया जा सकता है: https://github.com/seemoo-lab/frida-scripts/blob/main/scripts/libdispatch.js
वर्तमान में Ghidra न तो ObjectiveC dispatch_block_t
संरचना को समझता है, न ही swift_dispatch_block
को।
तो अगर आप इसे समझाना चाहते हैं, तो आप बस इनकी घोषणा कर सकते हैं:
फिर, कोड में एक जगह खोजें जहाँ इन्हें उपयोग किया गया है:
"block" के सभी संदर्भों को नोट करें ताकि आप समझ सकें कि संरचना का उपयोग किया जा रहा है।
वेरिएबल पर राइट-क्लिक करें -> वेरिएबल को फिर से टाइप करें और इस मामले में swift_dispatch_block
का चयन करें:
Ghidra स्वचालित रूप से सब कुछ फिर से लिख देगा:
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)