2017-06-30 17 views
6

मैं एक साधारण सी कार्यक्रम कि बस निष्पादन पर main() का पता प्रिंट कर दिया है: x86 के लिएविंडोज़ मेरे निष्पादन योग्य के मूल पते को यादृच्छिक क्यों नहीं रखता है?

printf("%08X\n", &main);

मैं विज़ुअल सी ++ 2015 के साथ यह संकलन पैरामीटर /DYNAMICBASE साथ, (एक ही बात होता है जब संकलन x64 के लिए)।

पहले दो बार मैं इसे चलाता हूं, जैसा कि अपेक्षित किया गया पता अलग-अलग होता है। हालांकि, दो बार के बाद, पता कार्यक्रम रिटर्न रहता है एक ही:

00C31050 
00221050 
00221050 
00221050 

recompiling या निष्पादन का नाम बदलने फिर पता randomizes।

यहां क्या हो रहा है? विंडोज़ किसी भी तरह निष्पादन योग्य कैशिंग है?

+1

आप रनों के बीच रीबूट करना भूल गए हैं। या तुलना करने के लिए जब आप इसे किसी अन्य मशीन पर चलाते हैं, तो एएसएलआर का असली बिंदु। जिस तरह से आप इसे काम करना पसंद करेंगे, प्रक्रियाओं के बीच कोड साझा करना बहुत मुश्किल हो जाएगा। एएसएलआर का एक अधिक परिष्कृत स्वाद उन कार्यक्रमों के लिए उपलब्ध है जिन्हें वर्षों से चलाने की उम्मीद की जा सकती है,/HIGHENTRYOPYVA x64 कोड के लिए उपलब्ध है। –

+0

मुझे पता है कि यह रीबूट या विभिन्न मशीनों के बीच बदल जाएगा, और यह वास्तव में एएसएलआर का बिंदु है। मैं सिर्फ उत्सुक हूं कि कुछ रनों के बाद उसी मशीन पर एक ही पते पर निष्पादन योग्य रहता है, और क्यों। – Thomas

+1

@ थॉमस यह [प्रीफेचर] (https://en.wikipedia.org/wiki/Prefetcher) से संबंधित हो सकता है। यह आईएमओ को समझता है क्योंकि पहली बार जब आप ताज़ा संकलित करते हैं .exe यह एक यादृच्छिक पता और उसके आगे के रन चलाता है .exe इसे प्रीफेचर से प्राप्त करता है इसलिए आपको एक ही पता मिलता है। –

उत्तर

2

सबसे पहले, आपको फ़ंक्शन का पता लेने की आवश्यकता नहीं है और पॉइंटर्स% p विनिर्देशक के साथ मुद्रित करने के लिए बेहतर हैं, जो कंपाइलर को प्रकारों की जांच करने में मदद करता है। अधिक सटीक कोड होगा:

printf ("%p\n", main); 

विषय पर, ASLR technology, जो निष्पादन योग्य छवियों रिबेसिंग के लिए जिम्मेदार है एक OS विशेषता यह है कि adresses कम पूर्वानुमान बनाकर बफर लंघन हमलों झेलने के लिए तैयार किया गया है। यह गारंटी है कि दो अनुक्रमिक रनों के लिए छवि विभिन्न स्थानों पर रखी जाएगी, लेकिन एक ओएस कई कारकों के आधार पर समय-समय पर आधार को बदलने की कोशिश करता है।

00BE1260 
00BE1260 
00221260 
00F71260 
01391260 
01391260 
01391260 
01391260 
01391260 
003A1260 

आप देख सकते हैं, भले ही लगातार रन ही स्थानों पर रखा गया था: मेरे परीक्षण के लिए मैं (उदाहरण के लिए) विंडोज -7 पर निम्नलिखित परिणाम 32-बिट का निर्माण 10 अनुक्रमिक रन पर तुरंत संकलन के बाद मिला , थोड़ी देर बाद आधार बदल जाता है। गारंटी दी जा सकती है कि गतिशील आधार के समर्थन के बिना निष्पादन योग्य छवि को हमेशा आधार पर रखा जाएगा, जो एक्सई-हेडर में लिंकर द्वारा सेट किया जाएगा। निष्पादन योग्य छवि के लिए डिफ़ॉल्ट आधार 400000h है, इसलिए मुद्रित मूल्य कुछ इस तरह होगा:

00401260 
00401260 
00401260 
00401260 
00401260 
... 

अपने मामले के लिए जैसा कि मैंने पर हमला है कि ओएस रिबेसिंग एल्गोरिथ्म ओएस एल्गोरिथ्म व्यवहार की वजह से अधिक भविष्य कहनेवाला काम करता है लगता है खतरों कम संभावित या एंट्रॉपी या संसाधनों की कमी के कारण। रीबेजिंग के लिए मेमोरी पेजों को रीमेप करने और स्थानांतरित करने के लिए अतिरिक्त समय और संसाधनों की आवश्यकता होती है, इसलिए ओएस यह तय कर सकता है कि आपके मामले में लगातार रिबेजिंग अनियंत्रित है।

बेशक, विंडोज कैश ने अपने स्टार्टअप को तेज करने के लिए एक्जिक्यूटिव लोड किए। यही कारण है कि अगले दौड़ पर आधार नहीं बदलेगा संभावना काफी अधिक है। यदि आपके पास बहुत सी रैम है, तो कैश के लिए अधिक रैम का उपयोग किया जा सकता है, और अधिक संभावना है कि छवि को पुन: विश्राम नहीं किया जाएगा। यदि छवि पूरी तरह से पुनः लोड हो जाती है तो समान आधार रखने का कोई कारण नहीं है। साथ ही, ओएस संस्करणों के बीच रिबेसिंग नीति भिन्न हो सकती है।

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

संपादित करें:

Btw, मैंने पाया कि/DYNAMICBASE विकल्प VS2015 द्वारा नजरअंदाज कर दिया जाता है और लिंकर हमेशा ASLR समर्थन के साथ निष्पादन योग्य छवि बनाता है, भले ही मैं स्पष्ट रूप/DYNAMICBASE सेट: सं। इसके अलावा बिट-टू-बिट तुलना से पता चलता है कि संकलित फाइलें एक टाइमस्टैम्प के अपवाद के साथ समान हैं (परिणामस्वरूप) एक चेकसम। एएसएलआर समर्थन के बिना वीएस2015 द्वारा निष्पादित निष्पादन योग्य प्राप्त करने के लिए मुझे exe-header में IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE बिट मैन्युअल रूप से निकालना पड़ा। यह नहीं पता कि यह जानबूझकर बनाया गया था या यह एक एमएस बग है।

+0

धन्यवाद, यह बहुत समझ में आता है कि प्रदर्शन कारणों से छवि कैश की गई है। वैसे; का उपयोग/DYNAMICBASE: वीसी ++ 2015 में मेरे लिए कोई काम ठीक नहीं है, इसलिए हो सकता है कि आप वीसी ++ बग या कॉन्फ़िगरेशन त्रुटि को मार रहे हों। – Thomas

संबंधित मुद्दे