सी ++ में सुरक्षित मेमोरी आवंटक

मैं एक आवंटक बनाना चाहता हूं जो निम्नलिखित विशेषताओं के साथ स्मृति प्रदान करता है:

  • डिस्क पर पेज नहीं किया जा सकता है।
  • एक संलग्न डीबगर
  • के माध्यम से पहुंचने के लिए अविश्वसनीय रूप से कठिन है

विचार यह है कि इसमें संवेदनशील जानकारी (जैसे लाइसेंस जानकारी) होगी जो उपयोगकर्ता के लिए पहुंच योग्य नहीं होनी चाहिए। मैंने ऑनलाइन सामान्य शोध किया है और इसके बारे में कुछ अन्य लोगों से पूछा है, लेकिन मुझे इस समस्या पर एक अच्छी जगह नहीं मिल सकती है।

अपडेट

Josh mentions using VirtualAlloc to set protection on the memory space. I have created a custom allocator ( shown below ) I have found the using the VirtualLock function it limits the amount of memory I can allocate. This seems to be by design though. Since I am using it for small objects this is not a problem.

//
template
class LockedVirtualMemAllocator : public std::allocator<_Ty>
{
public:
    template
    LockedVirtualMemAllocator<_Ty>& operator=(const LockedVirtualMemAllocator<_Other>&)
    {  //assign from a related LockedVirtualMemAllocator (do nothing)
        return (*this);
    }

    template
    struct rebind {
        typedef LockedVirtualMemAllocator other;
    };

    pointer allocate( size_type _n )
    {
        SIZE_T  allocLen = (_n * sizeof(_Ty));
        DWORD   allocType = MEM_COMMIT;
        DWORD   allocProtect = PAGE_READWRITE;
        LPVOID pMem = ::VirtualAlloc( NULL, allocLen, allocType, allocProtect );
        if ( pMem != NULL ) {
            ::VirtualLock( pMem, allocLen );
        }
        return reinterpret_cast( pMem );
    }
    pointer allocate( size_type _n, const void* )
    {
        return allocate( _n );
    }

    void deallocate(void* _pPtr, size_type _n )
    {
        if ( _pPtr != NULL ) {
            SIZE_T  allocLen = (_n * sizeof(_Ty));
            ::SecureZeroMemory( _pPtr, allocLen );
            ::VirtualUnlock( _pPtr, allocLen );
            ::VirtualFree( _pPtr, 0, MEM_RELEASE );
        }
    }
};

और प्रयोग किया जाता है

 //a memory safe std::string
 typedef std::basic_string, 
                           LockedVirtualMemAllocato > modulestring_t;

Ted Percival mentions mlock, but I have no implementation of that yet.

मैंने नील फर्ग्यूसन और ब्रूस शनीयर द्वारा प्रैक्टिकल क्रिप्टोग्राफी को भी काफी मददगार पाया।

0
ro fr bn

13 उत्तर

@ डेरेक: ओह, लेकिन भरोसेमंद कंप्यूटिंग के साथ, आप स्मृति पर्दा का उपयोग कर सकते हैं! :-P

0
जोड़ा

आप जो पूछ रहे हैं वह ओएस स्तर पर संभाला जाता है। एक बार डेटा आपके प्रोग्राम में है, तो इसे बाहर निकाला जा सकता है।

स्मृति तक पहुंचने के लिए, एक प्रेरित व्यक्ति हार्डवेयर डीबगर संलग्न कर सकता है।

0
जोड़ा

आइए इसे एक समय में थोड़ा सा लें:

मैं एक आवंटक बनाना चाहता हूं जो   निम्नलिखित के साथ स्मृति प्रदान करता है   गुण:

यह काफी उचित है।

  * डिस्क पर पेज नहीं किया जा सकता है।
 

यह मुश्किल होने जा रहा है। जहां तक ​​मुझे पता है, आप वर्चुअल पेजिंग को अक्षम नहीं कर सकते क्योंकि इसे ओएस द्वारा नियंत्रित किया जाता है। यदि कोई रास्ता है, तो आप ओएस के आंतों में spelunking होगा।

 * संलग्न डीबगर के माध्यम से पहुंचने के लिए अविश्वसनीय रूप से कठिन है
 

आप इसे पीजीपी के माध्यम से चला सकते हैं और इसे स्मृति में एन्क्रिप्ट किया जा सकता है और इसे आवश्यकतानुसार अनएन्क्रिप्ट कर सकते हैं। भारी प्रदर्शन हिट।

विचार यह है कि इसमें शामिल होगा   संवेदनशील जानकारी (लाइसेंस की तरह   सूचना) जो होना चाहिए   उपयोगकर्ता के लिए पहुंच योग्य नहीं है। मैंने कर लिया है   सामान्य शोध ऑनलाइन और एक पूछा   इसके बारे में कुछ अन्य लोग, लेकिन मैं   इस पर एक अच्छी जगह शुरू नहीं हो सकती है   समस्या।

मशीन से सभी संवेदनशील जानकारी रखें। गंभीरता से। स्मृति में संवेदनशील जानकारी स्टोर न करें। एक कस्टम डिलीट दिनचर्या लिखें जो आपके द्वारा किए गए किसी भी आवंटन से स्वचालित रूप से सभी डेटा निकाल देगा। इस पर संवेदनशील सामग्री वाले मशीन तक सामान्य पहुंच की अनुमति न दें। यदि आप डीबी एक्सेस करते हैं, तो सुनिश्चित करें कि फायरिंग से पहले सभी एक्सेस को स्वच्छ किया गया है। केवल विशिष्ट लॉग-इन वाले लोगों तक पहुंचने की अनुमति है। कोई सामान्य समूह का उपयोग नहीं।

एक तरफ ध्यान दें, अन्य विधियां क्या हैं   ए की स्मृति तक पहुंचने के लिए   एक संलग्न करने के अलावा अन्य प्रक्रिया   डिबगर?

स्मृति का डंप लेना।

0
जोड़ा
इसे एक अलग मशीन पर रखो। यदि आप संवेदनशील मशीन पर कुछ छोड़ देते हैं तो एक दुर्भावनापूर्ण उपयोगकर्ता इसका निरीक्षण और डिक्रिप्ट कर सकता है। यदि आप इसकी आवश्यकता होने पर जानकारी लाते हैं और इसे एक्सेस करते समय केवल इसे डिक्रिप्ट करते हैं और फिर तुरंत इसे हटा दें तो यह कठिन हो जाता है। हालांकि कोई डिवाइस पूरी तरह मूर्ख नहीं है। किसी ने निर्धारित किया है कि इसे बाधित कर देगा। आपको 99.9% बेवकूफ बनाने के लिए पर्याप्त कठिन बनाना है, लेकिन 99.9% को परेशान करने के लिए पर्याप्त नहीं है।
जोड़ा लेखक graham.reeds, स्रोत
"मशीन से सभी संवेदनशील जानकारी रखें।" अगर मैं गलत समझता हूं तो मुझे माफ़ कर दो, लेकिन क्या आपको संवेदनशील जानकारी के साथ क्या करना चाहिए? क्या आप सिर्फ कंप्यूटर को खिसकते हैं और इसे हाथ से करते हैं?
जोड़ा लेखक Parker Kemp, स्रोत

@ डेरेक पार्क

उन्होंने केवल कठिन कहा, असंभव नहीं। पीजीपी इसे कठिन, असंभव नहीं बना देगा।

0
जोड़ा

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

Win32 API फ़ंक्शन VirtualAlloc </ए> ओएस स्तर मेमोरी आवंटक है। यह आपको एक्सेस सुरक्षा सेट करने की अनुमति देता है; आप क्या कर सकते हैं PAGE_GUARD या PAGE_NOACCESS तक पहुंच सेट करें, और अपने प्रोग्राम को पढ़ने के दौरान कुछ मित्रवत तक पहुंच को फ़्लिप करें, और इसे बाद में रीसेट करें, लेकिन यह केवल एक गति कूबड़ है कोई आपके रहस्य पर देखने के लिए वास्तव में कड़ी मेहनत कर रहा है।

संक्षेप में, अपने प्लेटफ़ॉर्म पर क्रिप्टो एपीआई देखें, वे आपके द्वारा स्वयं को हैक करने की तुलना में समस्या को बेहतर तरीके से संबोधित करेंगे।

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

आप वास्तव में स्मृति पहुंच के खिलाफ सुरक्षा नहीं कर सकते हैं। यदि आप व्यवस्थापक के रूप में या सिस्टम के रूप में चल रहे हैं, तो आप शायद पेजिंग को रोक सकते हैं, लेकिन आप व्यवस्थापक या सिस्टम को अपनी याददाश्त पढ़ने से नहीं रोक सकते हैं। भले ही आप किसी भी तरह से अपनी प्रक्रिया को पढ़ने से अन्य प्रक्रियाओं को पूरी तरह से अवरुद्ध कर सकें (जो आप नहीं कर सकते), एक और प्रक्रिया वास्तव में आपकी प्रक्रिया में एक नया धागा इंजेक्ट कर सकती है और इस तरह स्मृति को पढ़ सकती है।

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

आप सिस्टम के मालिक से स्मृति सामग्री को नहीं कर सकते कर सकते हैं। हॉलीवुड और संगीत उद्योग वर्षों से इस के लिए दर्द कर रहे हैं। यदि यह संभव था, तो वे पहले से ही कर रहे थे।

0
जोड़ा
यदि/यह सच है, तो PlayReady (<3.0), वाइडविन, आदि कैसे क्रैक किए बिना काम करते हैं?
जोड़ा लेखक davidkomer, स्रोत
सीपीयू से बाहर होने से पहले एक कुंजी के साथ डेटा एन्कोडिंग के बारे में कैसे?
जोड़ा लेखक v.oddou, स्रोत

@graham

आप इसे पीजीपी के माध्यम से चला सकते हैं और इसे स्मृति में एन्क्रिप्ट किया जा सकता है और इसे आवश्यकतानुसार अनएन्क्रिप्ट कर सकते हैं। भारी प्रदर्शन हिट।

फिर आपको स्मृति में कुंजी पकड़नी होगी। इससे थोड़ा कठिन हो जाएगा, लेकिन निश्चित रूप से असंभव नहीं है। कोई भी प्रेरित अभी भी स्मृति से डेटा प्राप्त करने में कामयाब रहेगा।

0
जोड़ा

@roo

मैं वास्तव में उम्मीद कर रहा था कि यह संभव था, और मुझे अभी तक यह नहीं मिला था। आपके उदाहरण ने मुझे अभी महसूस किया है कि यह वही है जो हम करने की कोशिश कर रहे हैं - केवल हमारे कार्यक्रम के संदर्भ में फ़ाइलों तक पहुंच की अनुमति दें और इसलिए आईपी को सुरक्षित रखें।

     

मुझे लगता है कि मुझे यह स्वीकार करना होगा कि किसी अन्य कंप्यूटर पर किसी की फाइलों को स्टोर करने का कोई सही तरीका नहीं है, खासकर यदि किसी बिंदु पर मालिक द्वारा उस फ़ाइल तक पहुंच की अनुमति है।

यह निश्चित रूप से समस्या है। जब तक आप पहुंच प्रदान नहीं करते हैं, तब तक आप सुरक्षित रूप से कुछ स्टोर कर सकते हैं, लेकिन जैसे ही आप पहुंच प्रदान करते हैं, आपका नियंत्रण समाप्त हो जाता है। आप इसे थोड़ा और कठिन बना सकते हैं, लेकिन यह सब कुछ है।

0
जोड़ा

@Chris

ओह, लेकिन भरोसेमंद कंप्यूटिंग के साथ, आप मेमोरी पर्दे का उपयोग कर सकते हैं! :-P

लेकिन फिर आपको वास्तव में किसी अन्य कंप्यूटर के लिए भुगतान करने के लिए तैयार रहना होगा। : p

0
जोड़ा

आपकी सबसे अच्छी शर्त .NET की सिक्योरस्टिंग क्लास के समान कुछ लागू करना है, और जैसे ही आप कर चुके हैं, अपने डेटा की किसी भी सादे टेक्स्ट प्रतियों को शून्य करने के लिए बहुत सावधान रहें (अपवादों को फेंकने पर भी सफाई करना न भूलें)। Std :: स्ट्रिंग के साथ ऐसा करने का एक अच्छा तरीका है और ऐसा एक कस्टम आवंटक </एक>।

विंडोज़ पर, यदि आप CryptProtectMemory (या पुराने सिस्टम के लिए RtlEncryptMemory) का उपयोग करते हैं, तो एन्क्रिप्शन पासवर्ड गैर-पेजेबल (कर्नेल?) मेमोरी में संग्रहीत होता है। मेरे परीक्षण में, ये कार्य बहुत तेज हैं, esp। वे आपको जो सुरक्षा दे रहे हैं उसे ध्यान में रखते हुए।

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

कुल मिलाकर, यह रणनीति एक व्यापक रक्षा-गहन दृष्टिकोण का केवल एक हिस्सा है। यह भी ध्यान रखें कि बफर ओवरफ्लो जैसी सरल बग और प्रोग्राम इनपुट को स्वच्छ नहीं करना अब तक का सबसे आम हमला वैक्टर है।

0
जोड़ा

यूनिक्स सिस्टम पर आप स्मृति पृष्ठों को रैम में लॉक करने के लिए mlock (2) का उपयोग कर सकते हैं, उन्हें रोकना पेजिंग किया जा रहा है।

mlock() और mlockall() क्रमशः भाग या सभी कॉलिंग को लॉक करें   प्रक्रिया में वर्चुअल एड्रेस स्पेस रैम में, उस मेमोरी को रोक रहा है   स्वैप क्षेत्र में जा रहा है।

प्रत्येक प्रक्रिया को कितनी मेमोरी लॉक कर सकती है इसकी एक सीमा है, इसे ulimit -l के साथ दिखाया जा सकता है और इसे किलोबाइट में मापा जाता है। मेरे सिस्टम पर, प्रति सीमा 32 किबा प्रति डिफ़ॉल्ट सीमा है।

0
जोड़ा

आप सिस्टम के मालिक से स्मृति सामग्री की रक्षा नहीं कर सकते हैं।   हॉलीवुड और संगीत उद्योग वर्षों से इस के लिए दर्द कर रहे हैं।   यदि यह संभव था, तो वे पहले से ही कर रहे होंगे।

क्या आपने Vista (और ऊपर) संरक्षित प्रक्रियाएं (प्रत्यक्ष । डॉक्टर डाउनलोड )। मेरा मानना ​​है कि ऑपरेटिंग सिस्टम-लागू सुरक्षा मनोरंजन उद्योग की सौजन्य है।

0
जोड़ा

install Libsodium, use allocation mechanisms by #including

संरक्षित ढेर आवंटन

Malloc() और दोस्तों से धीमे, उन्हें वर्चुअल मेमोरी के 3 या 4 अतिरिक्त पृष्ठों की आवश्यकता होती है।

void *sodium_malloc(size_t size);

sodium_malloc() और sodium_allocarray() का उपयोग करके संवेदनशील डेटा को संग्रहीत करने के लिए स्मृति आवंटित करें। इन ढेर गार्ड का उपयोग करने से पहले आपको पहले sodium_init() को कॉल करना होगा।

void *sodium_allocarray(size_t count, size_t size);

sodium_allocarray() फ़ंक्शन एक पॉइंटर लौटाता है जिसमें से गिनती ऑब्जेक्ट्स हैं जो मेमोरी के आकार बाइट्स को एक्सेस किया जा सकता है। यह sodium_malloc() के समान गारंटी प्रदान करता है, लेकिन count * size SIZE_MAX से अधिक होने पर अंकगणित ओवरफ़्लो के विरुद्ध भी सुरक्षा करता है।

ये फ़ंक्शंस संरक्षित डेटा के चारों ओर गार्ड पेज जोड़ते हैं ताकि इसे दिल की तरह दिखने वाले परिदृश्य में पहुंचने की संभावना कम हो सके।

इसके अलावा, लॉकिंग मेमोरी ऑपरेशंस का उपयोग करके आवंटित स्मृति क्षेत्रों के लिए सुरक्षा को बदला जा सकता है: sodium_mprotect_noaccess() , sodium_mprotect_readonly() और sodium_mprotect_readwrite() </कोड>।

sodium_malloc के बाद आप स्मृति को अनलॉक और डिलीकेट करने के लिए sodium_free() का उपयोग कर सकते हैं। इस समय आपके कार्यान्वयन में उपयोग के बाद स्मृति को शून्य करने पर विचार करें।

उपयोग के बाद स्मृति शून्य

void sodium_memzero(void * const pnt, const size_t len);

उपयोग के बाद, संवेदनशील डेटा को अधिलेखित किया जाना चाहिए, लेकिन memset() और हाथ से लिखित कोड को एक अनुकूलित कंपेलर या लिंकर द्वारा चुपचाप हटाया जा सकता है।

Sodium_memzero() फ़ंक्शन पीएनटी से शुरू होने वाले प्रभावी रूप से शून्य लेन बाइट्स की कोशिश करता है, भले ही अनुकूलन कोड पर लागू हो रहे हों।

स्मृति आवंटन को लॉक करना

int sodium_mlock(void * const addr, const size_t len);

sodium_mlock() फ़ंक्शन लॉक कम से कम लेंस बाइट्स मेमोरी से शुरू होता है। यह संवेदनशील डेटा को डिस्क पर स्वैप करने से बचने में मदद कर सकता है।

int sodium_mprotect_noaccess(void *ptr);

Sodium_mprotect_noaccess() फ़ंक्शन sodium_malloc() या सोडियम_लोकैरे() को उपयोग करने योग्य आवंटित क्षेत्र बनाता है। इसे पढ़ या लिखा नहीं जा सकता है, लेकिन डेटा संरक्षित है। इस फ़ंक्शन का उपयोग गोपनीय डेटा को पहुंचने के लिए किया जा सकता है, सिवाय इसके कि जब वास्तव में किसी विशिष्ट ऑपरेशन के लिए आवश्यक हो।

int sodium_mprotect_readonly(void *ptr);

Sodium_mprotect_readonly() फ़ंक्शन केवल सोडियम_मॉलोक() या सोडियम_लोकैरे() को केवल पढ़ने के लिए आवंटित क्षेत्र को चिह्नित करता है। डेटा को संशोधित करने का प्रयास प्रक्रिया को समाप्त करने का कारण बन जाएगा।

int sodium_mprotect_readwrite(void *ptr);

sodium_mprotect_readwrite() फ़ंक्शन sodium_malloc() या sodium_allocarray() को पढ़ने योग्य और लिखने योग्य के रूप में आवंटित क्षेत्र को चिह्नित करता है, <�कोड का उपयोग करके संरक्षित होने के बाद > sodium_mprotect_readonly() या sodium_mprotect_noaccess()

0
जोड़ा