वास्तव में यह क्या करता है? मुझे समझ नहीं आ रहा है कि आप इसके साथ बेस मेमोरी तक कैसे पहुँच सकते हैं ... थोड़े अजीब लगते हैं। क्या ये सुरक्षित है?
dd if=/dev/urandom of=/dev/mem
वास्तव में यह क्या करता है? मुझे समझ नहीं आ रहा है कि आप इसके साथ बेस मेमोरी तक कैसे पहुँच सकते हैं ... थोड़े अजीब लगते हैं। क्या ये सुरक्षित है?
dd if=/dev/urandom of=/dev/mem
जवाबों:
दरअसल, अधिकांश प्लेटफार्मों पर, यह सिर्फ एक त्रुटि के साथ विफल होता है, लेकिन यह हार्डवेयर आर्किटेक्चर पर निर्भर करता है। यह निश्चित रूप से कोई गारंटी नहीं है कि यह हानिरहित है जब तक कि आप कमांड को अनप्रिवलाइज्ड उपयोगकर्ता के रूप में नहीं चलाते हैं। एक अनपेक्षित उपयोगकर्ता के साथ, कमांड पूरी तरह से हानिरहित है क्योंकि आप खोल नहीं सकते हैं /dev/mem
।
जब आप एक कमांड को रूट के रूप में चलाते हैं, तो आपको पता होना चाहिए कि आप क्या कर रहे हैं। कर्नेल कभी-कभी आपको कुछ खतरनाक करने से रोकेगा, लेकिन हमेशा नहीं। /dev/mem
उन संभावित खतरनाक चीजों में से एक है जहां आप वास्तव में यह जानना चाहते हैं कि आप क्या कर रहे हैं।
मैं कैसे /dev/mem
लिनक्स पर काम करने के लिए एक लिखने के माध्यम से चल रहा हूँ । सामान्य सिद्धांत अन्य यूनियनों पर समान होगा, लेकिन कर्नेल विकल्प जैसी चीजें पूरी तरह से अलग हैं।
जब कोई प्रक्रिया किसी डिवाइस फ़ाइल को पढ़ती या लिखती है तो क्या होता है, यह कर्नेल तक होता है। डिवाइस फ़ाइल की पहुंच ड्राइवर में कुछ कोड चलाता है जो इस डिवाइस फ़ाइल को संभालता है। उदाहरण के लिए, के लिए लिख /dev/mem
समारोह का आह्वान write_mem
मेंdrivers/char/mem.c
। यह फ़ंक्शन 4 तर्क लेता है: एक डेटा संरचना जो खुली फ़ाइल का प्रतिनिधित्व करती है, लिखने के लिए डेटा के लिए एक संकेतक, लिखने के लिए बाइट्स की संख्या और फ़ाइल में वर्तमान स्थिति।
ध्यान दें कि आपको केवल वह ही मिलता है जब कॉलर को पहली बार में फ़ाइल खोलने की अनुमति थी। डिवाइस फ़ाइलें सामान्य रूप से फ़ाइल अनुमतियों का पालन करती हैं। के सामान्य अनुमतियों /dev/mem
कर रहे हैं crw-r-----
के स्वामित्व में root:kmem
है, इसलिए यदि आप रूट किया जा रहा बिना लिखने के लिए इसे खोलने के लिए प्रयास करते हैं, तो आप सिर्फ मिलेगा "अनुमति अस्वीकृत" (EACCESS)। लेकिन अगर आप रूट कर रहे हैं (या यदि रूट ने इस फ़ाइल की अनुमति बदल दी है), तो उद्घाटन हो जाता है और फिर आप लिखने का प्रयास कर सकते हैं।
write_mem
फ़ंक्शन का कोड कुछ पवित्रता जांच करता है, लेकिन ये चेक सब कुछ खराब होने से बचाने के लिए पर्याप्त नहीं हैं। पहली चीज़ जो वर्तमान फ़ाइल स्थिति *ppos
को एक भौतिक पते में परिवर्तित करती है । यदि वह विफल हो जाता है (व्यवहार में, क्योंकि आप 32-बिट भौतिक पते वाले प्लेटफ़ॉर्म पर हैं लेकिन 64-बिट फ़ाइल ऑफ़सेट और फ़ाइल ऑफ़सेट 2 ^ 32 से बड़ा है), लेखन EFBIG (फ़ाइल बहुत बड़ी) के साथ विफल हो जाता है। अगला चेक यह है कि क्या लिखने के लिए भौतिक पते की सीमा इस विशेष प्रोसेसर वास्तुकला पर मान्य है, और EFAULT (खराब पते) में विफलता का परिणाम है।
अगला, स्पार्क और m68k पर, बहुत पहले भौतिक पृष्ठ में लिखने का कोई भी हिस्सा चुपचाप छोड़ दिया जाता है।
अब हम मुख्य लूप में पहुंच गए हैं जो उन ब्लॉकों में डेटा पर पुनरावृत्ति करता है जो एक एमएमयू पृष्ठ के भीतर फिट हो सकते हैं ।
/dev/mem
भौतिक मेमोरी तक पहुंच होती है, वर्चुअल मेमोरी नहीं, लेकिन प्रोसेसर मेमोरी में डेटा को लोड और स्टोर करने के निर्देश देता है, इसलिए कोड को कुछ वर्चुअल पते पर भौतिक मेमोरी को मैप करने की व्यवस्था करने की आवश्यकता होती है। लिनक्स पर, प्रोसेसर आर्किटेक्चर और कर्नेल कॉन्फ़िगरेशन के आधार पर, यह मैपिंग या तो परमानेंट रूप से मौजूद है या इसे फ्लाई पर बनाया जाना है; यह काम है xlate_dev_mem_ptr
(और unxlate_dev_mem_ptr
जो कुछ भी xlate_dev_mem_ptr
करता है उसे पूर्ववत करता है)। फिर फ़ंक्शन copy_from_user
उस बफर से पढ़ता है जिसे पास किया गया थाwrite
सिस्टम कॉल और बस उस वर्चुअल पते पर लिखता है जहाँ वर्तमान में भौतिक मेमोरी मैप की गई है। कोड सामान्य मेमोरी स्टोर निर्देशों का उत्सर्जन करता है, और इसका मतलब हार्डवेयर तक है।
इससे पहले कि मैं इस बात पर चर्चा करूँ कि एक भौतिक पते पर एक लेख लिखता है, मैं इस जाँच पर चर्चा करता हूँ जो इस लेखन से पहले होती है। लूप के अंदर, फ़ंक्शन page_is_allowed
कुछ पते तक पहुंचता है यदि कर्नेल कॉन्फ़िगरेशन विकल्प CONFIG_STRICT_DEVMEM
सक्षम किया गया है (जो डिफ़ॉल्ट रूप से मामला है): केवल उन पतों के devmem_is_allowed
माध्यम से पहुंचा जा सकता है /dev/mem
, अन्य के लिए EPERM के साथ विफल रहता है (ऑपरेशन की अनुमति नहीं है)। इस विकल्प का वर्णन बताता है:
यदि इस विकल्प को चालू किया जाता है, और IO_STRICT_DEVMEM = n, / dev / मेम फ़ाइल केवल PCI स्थान और BIOS कोड और डेटा क्षेत्रों के लिए उपयोगकर्ताओं की पहुँच की अनुमति देता है। यह dosemu और X और सभी सामान्य उपयोगकर्ताओं / dev / मेम के लिए पर्याप्त है।
यह बहुत ही x86- केंद्रित वर्णन है। वास्तव में, अधिक उदारता से, CONFIG_STRICT_DEVMEM
रैम को मैप करने वाले भौतिक मेमोरी पते तक पहुंच को अवरुद्ध करता है, लेकिन उन पते तक पहुंच की अनुमति देता है जो रैम को मैप नहीं करते हैं। भौतिक पते की किस श्रेणी की अनुमति है इसका विवरण प्रोसेसर वास्तुकला पर निर्भर करता है, लेकिन उनमें से सभी रैम को बाहर कर देते हैं जहां कर्नेल और उपयोगकर्ता भूमि प्रक्रियाओं का डेटा संग्रहीत किया जाता है। अतिरिक्त विकल्प CONFIG_IO_STRICT_DEVMEM
(उबंटू 18.04 के रूप में अक्षम) एक ड्राइवर द्वारा दावा किए गए भौतिक पते तक पहुंच को अवरुद्ध करता है।
भौतिक स्मृति उस मानचित्र को RAM में संबोधित करती है । तो भौतिक मेमोरी पते हैं जो RAM को मैप नहीं करते हैं? हाँ। यह चर्चा है कि मैंने इसके बारे में ऊपर वादा किया था कि इसका पता एक पते पर लिखने का क्या मतलब है।
एक मेमोरी स्टोर इंस्ट्रक्शन आवश्यक रूप से रैम को नहीं लिखता है। प्रोसेसर पते को विघटित करता है और निर्णय करता है कि किस परिधीय को स्टोर को भेजना है। (जब मैं "प्रोसेसर" कहता हूं, तो मैं परिधीय नियंत्रकों को शामिल करता हूं जो एक ही निर्माता से नहीं आ सकते हैं।) रैम केवल उन बाह्य उपकरणों में से एक है। प्रेषण कैसे किया जाता है यह प्रोसेसर आर्किटेक्चर पर बहुत निर्भर है, लेकिन सभी आर्किटेक्चर पर फंडामेंटल समान हैं। प्रोसेसर मूल रूप से पते के उच्च बिट्स को विघटित करता है और उन्हें कुछ तालिकाओं में दिखता है जो हार्ड-कोडित जानकारी, कुछ बसों की जांच द्वारा प्राप्त जानकारी और सॉफ्टवेयर द्वारा कॉन्फ़िगर की गई जानकारी के आधार पर पॉप अप होते हैं। बहुत सारे कैशिंग और बफरिंग शामिल हो सकते हैं, लेकिन संक्षेप में, इस अपघटन के बाद,बस और फिर उससे निपटने के लिए परिधीय पर निर्भर है। (या तालिका लुकअप का परिणाम यह हो सकता है कि इस पते पर कोई परिधीय नहीं है, इस स्थिति में प्रोसेसर एक ट्रैप स्थिति में प्रवेश करता है जहां यह कर्नेल में कुछ कोड निष्पादित करता है जो सामान्य रूप से कॉलिंग प्रक्रिया के लिए एक SIGBUS में परिणाम होता है ।)
एक पते के लिए एक स्टोर जो रैम में मैप करता है, वह इस पते पर पहले से संग्रहीत मूल्य को अधिलेखित करने के अलावा कुछ भी नहीं करता है, इस वादे के साथ कि उसी पते पर बाद में लोड पिछले संग्रहीत मूल्य को वापस देगा। लेकिन यहां तक कि रैम के कुछ पते हैं जो इस तरह से व्यवहार नहीं करते हैं: इसमें कुछ रजिस्टर हैं जो ताज़ा दर और वोल्टेज जैसी चीजों को नियंत्रित कर सकते हैं।
सामान्य तौर पर, एक हार्डवेयर रजिस्टर को पढ़ने या लिखने के लिए जो भी हार्डवेयर प्रोग्राम करने के लिए किया जाता है। अधिकांश हार्डवेयर इस तरह से काम करते हैं: सॉफ्टवेयर (सामान्य रूप से कर्नेल कोड) एक निश्चित भौतिक पते तक पहुंचता है, यह उस बस तक पहुंचता है जो प्रोसेसर को परिधीय से जोड़ता है, और परिधीय अपना काम करता है। कुछ प्रोसेसर (विशेष रूप से x86) में अलग-अलग सीपीयू निर्देश भी होते हैं, जो उन बाह्य उपकरणों को पढ़ता / लिखता है जो मेमोरी लोड और स्टोर से अलग होते हैं, लेकिन x86 पर भी, कई बाह्य उपकरणों को लोड / स्टोर के माध्यम से पहुँचा जाता है।
कमांड dd if=/dev/urandom of=/dev/mem
0 (और बाद के पते, जब तक कि लेखन सफल होता है) पर परिधीय को यादृच्छिक डेटा लिखता है। व्यवहार में, मुझे उम्मीद है कि कई आर्किटेक्चर पर, भौतिक पता 0 में कोई परिधीय मैप नहीं है, या रैम है, और इसलिए बहुत पहले लिखने का प्रयास विफल रहता है। लेकिन अगर पता 0 पर परिधीय मानचित्रण है, या यदि आप एक अलग पते पर लिखने के लिए कमांड बदलते हैं, तो आप परिधीय में अप्रत्याशित कुछ ट्रिगर करेंगे। बढ़ते हुए पते पर यादृच्छिक डेटा के साथ, यह कुछ दिलचस्प करने की संभावना नहीं है, लेकिन सिद्धांत रूप में यह कंप्यूटर को बंद कर सकता है (वास्तव में ऐसा पता है जो वास्तव में ऐसा करता है), कुछ BIOS सेटिंग को अधिलेखित करता है जो बूट करना असंभव बनाता है, या यहां तक कि कुछ हिट भी करता है। छोटी गाड़ी परिधीय एक तरह से इसे नुकसान पहुंचाती है।
alias Russian_roulette='dd if=/dev/urandom of=/dev/mem seek=$((4096*RANDOM+4096*32768*RANDOM))'
CONFIG_STRICT_DEVMEM
आप सक्षम हैं तो वास्तव में आप कर्नेल को नुकसान नहीं पहुंचा सकते ।
प्रति मैनुअल पेज मेम (4) :
/ dev / mem एक कैरेक्टर डिवाइस फाइल है जो कंप्यूटर की मुख्य मेमोरी की एक छवि है। इसका उपयोग, उदाहरण के लिए, (और यहां तक कि पैच) सिस्टम की जांच करने के लिए किया जा सकता है।
तो सिद्धांत रूप में, dd if=/dev/urandom of=/dev/mem
भौतिक स्मृति द्वारा स्थापित किए गए के पूरे पता स्थान के ऊपर लिख चाहिए, और गिरी और अन्य कार्यक्रमों स्मृति से चलाने के बाद से इस करना चाहिए सिस्टम प्रभावी ढंग से क्रैश । व्यवहार में, इसकी सीमा है। उसी मैन पेज से:
चूंकि लिनक्स 2.6.26, और आर्किटेक्चर के आधार पर, CONFIG_STRICT_DEVMEM कर्नेल कॉन्फ़िगरेशन विकल्प उन क्षेत्रों को सीमित करता है, जिन्हें इस फ़ाइल के माध्यम से एक्सेस किया जा सकता है।
वर्चुअल मशीन Ubuntu 18.04 पर यह कोशिश करते हुए, यह रूट के लिए अनुमति के बावजूद dd: writing to '/dev/mem': Operation not permitted
भी त्रुटि देता है । से उबंटू विकी :sudo
crw-r-----
/ देव / मेम संरक्षण
कुछ एप्लिकेशन (Xorg) को उपयोगकर्ता-अंतरिक्ष से भौतिक मेमोरी तक सीधे पहुंच की आवश्यकता होती है। इस एक्सेस को प्रदान करने के लिए विशेष फ़ाइल / dev / mem मौजूद है। अतीत में, इस फ़ाइल से कर्नेल मेमोरी को देखना और बदलना संभव था यदि किसी हमलावर की रूट एक्सेस थी। CONFIG_STRICT_DEVMEM कर्नेल विकल्प को गैर-डिवाइस मेमोरी एक्सेस (मूल रूप से CONFIG_NONPROMISC_DEVMEM नाम दिया गया) को ब्लॉक करने के लिए पेश किया गया था।
इसलिए तकनीकी रूप से, यह सुरक्षित नहीं है (क्योंकि यह सिस्टम को क्रैश करेगा) और यदि कर्नेल विकल्प CONFIG_STRICT_DEVMEM
अक्षम है जो एक सुरक्षा छेद है, लेकिन जो मैं अभी तक देख रहा हूं वह कमांड चालू नहीं होगा यदि वह विकल्प सक्षम है। क्रॉस-साइट डुप्लिकेट के अनुसार , एक रिबूट इसके साथ किसी भी मुद्दे को ठीक कर देगा, लेकिन उस समय रैम में निश्चित रूप से डेटा खो जाएगा और डिस्क में फ्लश नहीं किया जाएगा (यदि कोई होना चाहिए)।
पहले उपयोग किए गए डुप्लिकेट पर एक सुझाई गई विधि है, busybox devmem
इसलिए यदि आप रैम के साथ गड़बड़ करने के लिए निर्धारित हैं, तो एक तरीका हो सकता है।
CONFIG_STRICT_DEVMEM
, आप मेमोरी क्षेत्रों तक पहुंच सकते हैं जहां एक परिधीय मैप किया जाता है, जो पूरे होने का बिंदु है /dev/mem
। यदि आप परिधीयों को यादृच्छिक सामान लिखते हैं, तो कुछ भी हो सकता है। यदि आपको मैप न किए जाने वाले पते पर पहुंचने का प्रयास करने पर "ऑपरेशन की अनुमति नहीं है" मिलता है, और कमांड पते पर शुरू होता है 0. क्या पता 0 मानचित्र कुछ खराब है हार्डवेयर आर्किटेक्चर पर निर्भर करता है। सभी के लिए मुझे पता है कि यह पीसी पर कभी भी मैप नहीं हो सकता है, लेकिन यह सामान्य रूप से सुरक्षित नहीं है।
head -c 1024 </dev/mem | od -tx1
), लेकिन मुझे नहीं पता कि इनका उपयोग तब किया जाता है जब प्रोसेसर वास्तविक मोड (8088 मोड) में नहीं होता है। मुझे नहीं लगता कि उनका उपयोग 64-बिट मोड में किया जा सकता है: आखिरकार, 8088 इंटरप्ट वैक्टर में पते के लिए केवल 32 बिट्स हैं। और वैसे यह CONFIG_STRICT_DEVMEM
सेट के साथ सुलभ है , इसलिए मुझे लगता है कि लिनक्स इसका उपयोग नहीं करता है।