यह LD_PRELOAD on Linux के समान है। यह एक प्रक्रिया को इंगित करने की अनुमति देता है जो चलने वाली है कि एक विशेष लाइब्रेरी को एक पथ से लोड किया जाए (यदि env var सक्षम है)
यह तकनीक ASEP तकनीक के रूप में भी उपयोग की जा सकती है क्योंकि हर स्थापित एप्लिकेशन में "Info.plist" नामक एक plist होती है जो एक कुंजी LSEnvironmental का उपयोग करके पर्यावरणीय चर असाइन करने की अनुमति देती है।
2012 से Apple ने DYLD_INSERT_LIBRARIES की शक्ति को नाटकीय रूप से कम कर दिया है।
कोड पर जाएं और src/dyld.cpp की जांच करें। फ़ंक्शन pruneEnvironmentVariables में आप देख सकते हैं कि DYLD_* चर हटा दिए गए हैं।
फ़ंक्शन processRestricted में प्रतिबंध का कारण सेट किया गया है। उस कोड की जांच करते समय आप देख सकते हैं कि कारण हैं:
बाइनरी setuid/setgid है
macho बाइनरी में __RESTRICT/__restrict अनुभाग का अस्तित्व।
बाइनरी के अधिकार की जांच करें: codesign -dv --entitlements :- </path/to/bin>
अधिक अपडेटेड संस्करणों में आप इस तर्क को फ़ंक्शन configureProcessRestrictions के दूसरे भाग में पा सकते हैं। हालाँकि, जो नए संस्करणों में निष्पादित होता है वह फ़ंक्शन के शुरुआती जांच हैं (आप iOS या सिमुलेशन से संबंधित ifs को हटा सकते हैं क्योंकि वे macOS में उपयोग नहीं किए जाएंगे)।
लाइब्रेरी मान्यता
यहां तक कि यदि बाइनरी DYLD_INSERT_LIBRARIES env चर का उपयोग करने की अनुमति देती है, यदि बाइनरी लोड करने के लिए लाइब्रेरी के हस्ताक्षर की जांच करती है, तो यह एक कस्टम को लोड नहीं करेगी।
एक कस्टम लाइब्रेरी लोड करने के लिए, बाइनरी को निम्नलिखित अधिकारों में से एक होना चाहिए:
या बाइनरी को हर्डनड रनटाइम फ्लैग या लाइब्रेरी मान्यता फ्लैग नहीं होना चाहिए।
आप यह जांच सकते हैं कि क्या बाइनरी में हर्डनड रनटाइम है codesign --display --verbose <bin> के साथ CodeDirectory में रनटाइम फ्लैग की जांच करते हुए जैसे: CodeDirectory v=20500 size=767 flags=0x10000(runtime) hashes=13+7 location=embedded
आप एक लाइब्रेरी को भी लोड कर सकते हैं यदि यह बाइनरी के समान प्रमाणपत्र के साथ हस्ताक्षरित है।
इसका (ab) उपयोग करने का एक उदाहरण खोजें और प्रतिबंधों की जांच करें:
याद रखें कि पिछले लाइब्रेरी मान्यता प्रतिबंध भी लागू होते हैं Dylib हाइजैकिंग हमलों को करने के लिए।
Windows की तरह, MacOS में आप भी dylibs को हाइजैक कर सकते हैं ताकि एप्लिकेशनमनमानेकोड को निष्पादित कर सकें (ठीक है, वास्तव में एक सामान्य उपयोगकर्ता के लिए यह संभव नहीं हो सकता क्योंकि आपको एक TCC अनुमति की आवश्यकता हो सकती है ताकि आप एक .app बंडल के अंदर लिख सकें और एक लाइब्रेरी को हाइजैक कर सकें)।
हालांकि, MacOS एप्लिकेशन लाइब्रेरी को लोड करने का तरीका Windows की तुलना में अधिक प्रतिबंधित है। इसका मतलब है कि मैलवेयर डेवलपर्स अभी भी स्टेल्थ के लिए इस तकनीक का उपयोग कर सकते हैं, लेकिन अधिकार बढ़ाने के लिए इसका दुरुपयोग करने की संभावना बहुत कम है।
सबसे पहले, यह अधिक सामान्य है कि MacOS बाइनरी लाइब्रेरी को लोड करने के लिए पूर्ण पथ इंगित करती हैं। और दूसरा, **MacOS कभी भी लाइब्रेरी के लिए $PATH के फ़ोल्डरों में खोज नहीं करता है।
इस कार्यक्षमता से संबंधित कोड का मुख्य भाग ImageLoader::recursiveLoadLibraries में है ImageLoader.cpp।
एक macho बाइनरी लाइब्रेरी लोड करने के लिए 4 विभिन्न हेडर कमांड का उपयोग कर सकती है:
LC_LOAD_DYLIB कमांड एक dylib लोड करने के लिए सामान्य कमांड है।
LC_LOAD_WEAK_DYLIB कमांड पिछले वाले की तरह काम करता है, लेकिन यदि dylib नहीं पाया जाता है, तो निष्पादन बिना किसी त्रुटि के जारी रहता है।
LC_REEXPORT_DYLIB कमांड यह प्रतीक एक अलग लाइब्रेरी से प्रॉक्सी (या फिर से निर्यात) करता है।
LC_LOAD_UPWARD_DYLIB कमांड का उपयोग तब किया जाता है जब दो लाइब्रेरी एक-दूसरे पर निर्भर करती हैं (इसे upward dependency कहा जाता है)।
हालांकि, dylib हाइजैकिंग के 2 प्रकार हैं:
गायब कमजोर लिंक की गई लाइब्रेरी: इसका मतलब है कि एप्लिकेशन एक लाइब्रेरी लोड करने की कोशिश करेगा जो LC_LOAD_WEAK_DYLIB के साथ कॉन्फ़िगर की गई नहीं है। फिर, यदि एक हमलावर एक dylib को उस स्थान पर रखता है जहां इसे लोड करने की उम्मीद है।
लिंक "कमजोर" होने का मतलब है कि एप्लिकेशन लाइब्रेरी नहीं मिलने पर भी चलना जारी रखेगा।
इस से संबंधित कोडImageLoaderMachO::doGetDependentLibraries फ़ंक्शन में है ImageLoaderMachO.cpp जहां lib->required केवल तब false है जब LC_LOAD_WEAK_DYLIB सत्य है।
बाइनरी में कमजोर लिंक की गई लाइब्रेरी खोजें (आपके पास बाद में हाइजैकिंग लाइब्रेरी बनाने का एक उदाहरण है):
otool -l </path/to/bin> | grep LC_LOAD_WEAK_DYLIB -A 5 cmd LC_LOAD_WEAK_DYLIB cmdsize 56 name /var/tmp/lib/libUtl.1.dylib (offset 24) time stamp 2 Wed Jun 21 12:23:31 1969 current version 1.0.0 compatibility version 1.0.0
* **@rpath के साथ कॉन्फ़िगर किया गया**: Mach-O बाइनरी में **`LC_RPATH`** और **`LC_LOAD_DYLIB`** कमांड हो सकते हैं। उन कमांड के **मानों** के आधार पर, **लाइब्रेरी** **विभिन्न निर्देशिकाओं** से **लोड** की जाएगी।
* **`LC_RPATH`** में कुछ फ़ोल्डरों के पथ होते हैं जो बाइनरी द्वारा लाइब्रेरी लोड करने के लिए उपयोग किए जाते हैं।
* **`LC_LOAD_DYLIB`** में लोड करने के लिए विशिष्ट लाइब्रेरी का पथ होता है। ये पथ **`@rpath`** को शामिल कर सकते हैं, जिसे **`LC_RPATH`** में मानों द्वारा **बदल दिया जाएगा**। यदि **`LC_RPATH`** में कई पथ हैं, तो सभी का उपयोग लाइब्रेरी को लोड करने के लिए किया जाएगा। उदाहरण:
* यदि **`LC_LOAD_DYLIB`** में `@rpath/library.dylib` है और **`LC_RPATH`** में `/application/app.app/Contents/Framework/v1/` और `/application/app.app/Contents/Framework/v2/` है। दोनों फ़ोल्डर `library.dylib` को लोड करने के लिए उपयोग किए जाएंगे। यदि लाइब्रेरी `[...]/v1/` में मौजूद नहीं है और हमलावर इसे `[...]/v2/` में लोड करने के लिए रख सकता है क्योंकि **`LC_LOAD_DYLIB`** में पथों का क्रम अनुसरण किया जाता है।
* **बाइनरी में rpath पथ और लाइब्रेरी खोजें**: `otool -l </path/to/binary> | grep -E "LC_RPATH|LC_LOAD_DYLIB" -A 5`
<div data-gb-custom-block data-tag="hint" data-style='info'>
**`@executable_path`**: यह **मुख्य निष्पादन फ़ाइल** वाले निर्देशिका का **पथ** है।
**`@loader_path`**: यह **Mach-O बाइनरी** वाले **निर्देशिका** का **पथ** है जिसमें लोड कमांड होता है।
* जब इसे एक निष्पादन में उपयोग किया जाता है, तो **`@loader_path`** प्रभावी रूप से **`@executable_path`** के समान होता है।
* जब इसे एक **dylib** में उपयोग किया जाता है, तो **`@loader_path`** **dylib** का **पथ** देता है।
</div>
इस कार्यक्षमता का दुरुपयोग करके **अधिकार बढ़ाने** का तरीका तब होगा जब एक **एप्लिकेशन** जो **रूट** द्वारा **निष्पादित** किया जा रहा है, किसी **निर्देशिका में किसी लाइब्रेरी की तलाश कर रहा है जहां हमलावर के पास लिखने की अनुमति है।**
<div data-gb-custom-block data-tag="hint" data-style='success'>
एप्लिकेशनों में **गायब लाइब्रेरी** खोजने के लिए एक अच्छा **स्कैनर** [**Dylib Hijack Scanner**](https://objective-see.com/products/dhs.html) है या एक [**CLI संस्करण**](https://github.com/pandazheng/DylibHijack).\
इस तकनीक के बारे में तकनीकी विवरण के साथ एक अच्छा **रिपोर्ट** [**यहां**](https://www.virusbulletin.com/virusbulletin/2015/03/dylib-hijacking-os-x) पाया जा सकता है।
</div>
**उदाहरण**
<div data-gb-custom-block data-tag="content-ref" data-url='macos-dyld-hijacking-and-dyld_insert_libraries.md'>
[macos-dyld-hijacking-and-dyld\_insert\_libraries.md](macos-dyld-hijacking-and-dyld\_insert\_libraries.md)
</div>
## Dlopen Hijacking
<div data-gb-custom-block data-tag="hint" data-style='danger'>
याद रखें कि **पिछले लाइब्रेरी मान्यता प्रतिबंध भी लागू होते हैं** Dlopen हाइजैकिंग हमलों को करने के लिए।
</div>
**`man dlopen`** से:
* जब पथ **स्लैश वर्ण** नहीं रखता (यानी यह केवल एक पत्ते का नाम है), **dlopen() खोज करेगा**। यदि **`$DYLD_LIBRARY_PATH`** लॉन्च पर सेट किया गया था, तो dyld पहले उस निर्देशिका में **देखेगा**। अगला, यदि कॉलिंग mach-o फ़ाइल या मुख्य निष्पादन ने **`LC_RPATH`** निर्दिष्ट किया है, तो dyld उन निर्देशिकाओं में **देखेगा**। अगला, यदि प्रक्रिया **अप्रतिबंधित** है, तो dyld **वर्तमान कार्यशील निर्देशिका** में खोज करेगा। अंत में, पुराने बाइनरी के लिए, dyld कुछ फॉलबैक का प्रयास करेगा। यदि **`$DYLD_FALLBACK_LIBRARY_PATH`** लॉन्च पर सेट किया गया था, तो dyld उन निर्देशिकाओं में खोज करेगा, अन्यथा, dyld **`/usr/local/lib/`** में देखेगा (यदि प्रक्रिया अप्रतिबंधित है), और फिर **`/usr/lib/`** में (यह जानकारी **`man dlopen`** से ली गई थी)।
1. `$DYLD_LIBRARY_PATH`
2. `LC_RPATH`
3. `CWD`(यदि अप्रतिबंधित)
4. `$DYLD_FALLBACK_LIBRARY_PATH`
5. `/usr/local/lib/` (यदि अप्रतिबंधित)
6. `/usr/lib/`
<div data-gb-custom-block data-tag="hint" data-style='danger'>
यदि नाम में कोई स्लैश नहीं है, तो हाइजैकिंग करने के लिए 2 तरीके होंगे:
* यदि कोई **`LC_RPATH`** **लिखने योग्य** है (लेकिन हस्ताक्षर की जांच की जाती है, इसलिए इसके लिए आपको बाइनरी को भी अप्रतिबंधित होना चाहिए)
* यदि बाइनरी **अप्रतिबंधित** है और फिर CWD से कुछ लोड करना संभव है (या उल्लेखित env चर में से एक का दुरुपयोग करना)
</div>
* जब पथ **फ्रेमवर्क** पथ की तरह दिखता है (जैसे `/stuff/foo.framework/foo`), यदि **`$DYLD_FRAMEWORK_PATH`** लॉन्च पर सेट किया गया था, तो dyld पहले उस निर्देशिका में **फ्रेमवर्क आंशिक पथ** (जैसे `foo.framework/foo`) के लिए देखेगा। अगला, dyld **प्रदान किए गए पथ को जैसा है** (सापेक्ष पथों के लिए वर्तमान कार्यशील निर्देशिका का उपयोग करते हुए) का प्रयास करेगा। अंत में, पुराने बाइनरी के लिए, dyld कुछ फॉलबैक का प्रयास करेगा। यदि **`$DYLD_FALLBACK_FRAMEWORK_PATH`** लॉन्च पर सेट किया गया था, तो dyld उन निर्देशिकाओं में खोज करेगा। अन्यथा, यह **`/Library/Frameworks`** (macOS पर यदि प्रक्रिया अप्रतिबंधित है), फिर **`/System/Library/Frameworks`** में खोज करेगा।
1. `$DYLD_FRAMEWORK_PATH`
2. प्रदान किया गया पथ (यदि अप्रतिबंधित है तो सापेक्ष पथों के लिए वर्तमान कार्यशील निर्देशिका का उपयोग करना)
3. `$DYLD_FALLBACK_FRAMEWORK_PATH`
4. `/Library/Frameworks` (यदि अप्रतिबंधित)
5. `/System/Library/Frameworks`
<div data-gb-custom-block data-tag="hint" data-style='danger'>
यदि एक फ्रेमवर्क पथ है, तो इसे हाइजैक करने का तरीका होगा:
* यदि प्रक्रिया **अप्रतिबंधित** है, तो CWD से सापेक्ष पथ का दुरुपयोग करते हुए उल्लेखित env चर (यहां तक कि यदि यह दस्तावेज़ में नहीं कहा गया है यदि प्रक्रिया प्रतिबंधित है तो DYLD\_\* env vars हटा दिए जाते हैं)
</div>
* जब पथ **स्लैश रखता है लेकिन फ्रेमवर्क पथ नहीं है** (यानी एक पूर्ण पथ या dylib के लिए आंशिक पथ), dlopen() पहले (यदि सेट है) **`$DYLD_LIBRARY_PATH`** में देखता है (पथ से पत्ते का भाग)। अगला, dyld **प्रदान किए गए पथ का प्रयास करता है** (सापेक्ष पथों के लिए वर्तमान कार्यशील निर्देशिका का उपयोग करते हुए (लेकिन केवल अप्रतिबंधित प्रक्रियाओं के लिए))। अंत में, पुराने बाइनरी के लिए, dyld फॉलबैक का प्रयास करेगा। यदि **`$DYLD_FALLBACK_LIBRARY_PATH`** लॉन्च पर सेट किया गया था, तो dyld उन निर्देशिकाओं में खोज करेगा, अन्यथा, dyld **`/usr/local/lib/`** में देखेगा (यदि प्रक्रिया अप्रतिबंधित है), और फिर **`/usr/lib/`** में।
1. `$DYLD_LIBRARY_PATH`
2. प्रदान किया गया पथ (यदि अप्रतिबंधित है तो सापेक्ष पथों के लिए वर्तमान कार्यशील निर्देशिका का उपयोग करना)
3. `$DYLD_FALLBACK_LIBRARY_PATH`
4. `/usr/local/lib/` (यदि अप्रतिबंधित)
5. `/usr/lib/`
<div data-gb-custom-block data-tag="hint" data-style='danger'>
यदि नाम में स्लैश हैं और फ्रेमवर्क नहीं है, तो इसे हाइजैक करने का तरीका होगा:
* यदि बाइनरी **अप्रतिबंधित** है और फिर CWD या `/usr/local/lib` से कुछ लोड करना संभव है (या उल्लेखित env चर में से एक का दुरुपयोग करना)
</div>
<div data-gb-custom-block data-tag="hint" data-style='info'>
नोट: **dlopen खोज को नियंत्रित करने के लिए कोई** कॉन्फ़िगरेशन फ़ाइलें **नहीं हैं**।
नोट: यदि मुख्य निष्पादन **set\[ug]id बाइनरी या अधिकारों के साथ कोडसाइन** है, तो **सभी पर्यावरणीय चर अनदेखा कर दिए जाते हैं**, और केवल एक पूर्ण पथ का उपयोग किया जा सकता है ([DYLD\_INSERT\_LIBRARIES प्रतिबंधों की जांच करें](macos-dyld-hijacking-and-dyld\_insert\_libraries.md#check-dyld\_insert\_librery-restrictions) अधिक विस्तृत जानकारी के लिए)
नोट: Apple प्लेटफार्मों पर "यूनिवर्सल" फ़ाइलों का उपयोग 32-बिट और 64-बिट लाइब्रेरी को संयोजित करने के लिए किया जाता है। इसका मतलब है कि **कोई अलग 32-बिट और 64-बिट खोज पथ नहीं हैं**।
नोट: Apple प्लेटफार्मों पर अधिकांश OS dylibs **dyld कैश में संयोजित** होते हैं और डिस्क पर मौजूद नहीं होते हैं। इसलिए, यह जांचने के लिए **`stat()`** कॉल करना कि क्या कोई OS dylib मौजूद है **काम नहीं करेगा**। हालाँकि, **`dlopen_preflight()`** एक संगत mach-o फ़ाइल खोजने के लिए **`dlopen()`** के समान चरणों का उपयोग करता है।
</div>
**पथों की जांच करें**
आइए निम्नलिखित कोड के साथ सभी विकल्पों की जांच करें:
```c
// gcc dlopentest.c -o dlopentest -Wl,-rpath,/tmp/test
#include <dlfcn.h>
#include <stdio.h>
int main(void)
{
void* handle;
fprintf("--- No slash ---\n");
handle = dlopen("just_name_dlopentest.dylib",1);
if (!handle) {
fprintf(stderr, "Error loading: %s\n\n\n", dlerror());
}
fprintf("--- Relative framework ---\n");
handle = dlopen("a/framework/rel_framework_dlopentest.dylib",1);
if (!handle) {
fprintf(stderr, "Error loading: %s\n\n\n", dlerror());
}
fprintf("--- Abs framework ---\n");
handle = dlopen("/a/abs/framework/abs_framework_dlopentest.dylib",1);
if (!handle) {
fprintf(stderr, "Error loading: %s\n\n\n", dlerror());
}
fprintf("--- Relative Path ---\n");
handle = dlopen("a/folder/rel_folder_dlopentest.dylib",1);
if (!handle) {
fprintf(stderr, "Error loading: %s\n\n\n", dlerror());
}
fprintf("--- Abs Path ---\n");
handle = dlopen("/a/abs/folder/abs_folder_dlopentest.dylib",1);
if (!handle) {
fprintf(stderr, "Error loading: %s\n\n\n", dlerror());
}
return 0;
}
यदि आप इसे संकलित और निष्पादित करते हैं, तो आप देख सकते हैं कि प्रत्येक पुस्तकालय के लिए कहाँ असफलता से खोज की गई। इसके अलावा, आप FS लॉग को फ़िल्टर कर सकते हैं:
sudofs_usage|grep"dlopentest"
Relative Path Hijacking
यदि एक privileged binary/app (जैसे SUID या कुछ बाइनरी जिसमें शक्तिशाली अधिकार हैं) एक सापेक्ष पथ लाइब्रेरी को लोड कर रहा है (उदाहरण के लिए @executable_path या @loader_path का उपयोग करके) और Library Validation अक्षम है, तो यह संभव हो सकता है कि बाइनरी को एक स्थान पर ले जाया जाए जहाँ हमलावर सापेक्ष पथ लोड की गई लाइब्रेरी को संशोधित कर सके, और इसे प्रक्रिया में कोड इंजेक्ट करने के लिए दुरुपयोग कर सके।
Prune DYLD_* और LD_LIBRARY_PATH env variables
फाइल dyld-dyld-832.7.1/src/dyld2.cpp में pruneEnvironmentVariables नामक फ़ंक्शन पाया जा सकता है, जो किसी भी env वेरिएबल को हटा देगा जो DYLD_ और LD_LIBRARY_PATH= से शुरू होता है।
यह विशेष रूप से suid और sgid बाइनरी के लिए env वेरिएबल DYLD_FALLBACK_FRAMEWORK_PATH और DYLD_FALLBACK_LIBRARY_PATH को null पर सेट करेगा।
यह फ़ंक्शन उसी फ़ाइल के _main फ़ंक्शन से इस तरह से बुलाया जाता है यदि OSX को लक्षित किया गया हो:
और उन बूलियन फ्लैग्स को कोड में उसी फ़ाइल में सेट किया गया है:
#ifTARGET_OS_OSX// support chrooting from old kernelbool isRestricted =false;bool libraryValidation =false;// any processes with setuid or setgid bit set or with __RESTRICT segment is restrictedif ( issetugid() ||hasRestrictedSegment(mainExecutableMH) ) {isRestricted =true;}bool usingSIP = (csr_check(CSR_ALLOW_TASK_FOR_PID) !=0);uint32_t flags;if ( csops(0, CS_OPS_STATUS,&flags,sizeof(flags)) !=-1 ) {// On OS X CS_RESTRICT means the program was signed with entitlementsif ( ((flags & CS_RESTRICT) == CS_RESTRICT) && usingSIP ) {isRestricted =true;}// Library Validation loosens searching but requires everything to be code signedif ( flags & CS_REQUIRE_LV ) {isRestricted =false;libraryValidation =true;}}gLinkContext.allowAtPaths =!isRestricted;gLinkContext.allowEnvVarsPrint =!isRestricted;gLinkContext.allowEnvVarsPath =!isRestricted;gLinkContext.allowEnvVarsSharedCache =!libraryValidation ||!usingSIP;gLinkContext.allowClassicFallbackPaths =!isRestricted;gLinkContext.allowInsertFailures =false;gLinkContext.allowInterposing =true;
जो मूल रूप से यह मतलब है कि यदि बाइनरी suid या sgid है, या इसके हेडर में RESTRICT खंड है या इसे CS_RESTRICT ध्वज के साथ साइन किया गया है, तो !gLinkContext.allowEnvVarsPrint && !gLinkContext.allowEnvVarsPath && !gLinkContext.allowEnvVarsSharedCache सत्य है और env वेरिएबल्स को हटाया जाता है।
ध्यान दें कि यदि CS_REQUIRE_LV सत्य है, तो वेरिएबल्स को नहीं हटाया जाएगा लेकिन लाइब्रेरी मान्यता यह जांचेगी कि वे मूल बाइनरी के समान प्रमाणपत्र का उपयोग कर रहे हैं।
प्रतिबंधों की जांच करें
SUID & SGID
# Make it owned by root and suidsudochownroothellosudochmod+shello# Insert the libraryDYLD_INSERT_LIBRARIES=inject.dylib./hello# Remove suidsudochmod-shello
Keychain में एक नया प्रमाणपत्र बनाएं और इसका उपयोग बाइनरी पर हस्ताक्षर करने के लिए करें:
# Apply runtime proetctioncodesign-s<cert-name>--option=runtime./helloDYLD_INSERT_LIBRARIES=inject.dylib./hello#Library won't be injected# Apply library validationcodesign-f-s<cert-name>--option=library./helloDYLD_INSERT_LIBRARIES=inject.dylib ./hello-signed #Will throw an error because signature of binary and library aren't signed by same cert (signs must be from a valid Apple-signed developer certificate)
# Sign it## If the signature is from an unverified developer the injection will still work## If it's from a verified developer, it won'tcodesign-f-s<cert-name>inject.dylibDYLD_INSERT_LIBRARIES=inject.dylib./hello-signed# Apply CS_RESTRICT protectioncodesign-f-s<cert-name>--option=restricthello-signedDYLD_INSERT_LIBRARIES=inject.dylib./hello-signed# Won't work
ध्यान दें कि भले ही कुछ बाइनरीज़ 0x0(none) फ्लैग के साथ साइन की गई हों, वे निष्पादित होने पर CS_RESTRICT फ्लैग को गतिशील रूप से प्राप्त कर सकती हैं और इसलिए यह तकनीक उन पर काम नहीं करेगी।
आप यह जांच सकते हैं कि किसी प्रक्रिया में यह फ्लैग है या नहीं (get csops here):