पिछले दो हफ्तों में, हमने लेखों की एक श्रृंखला देखी है जिसमें लोकप्रिय ओपन-सोर्स पासवर्ड मैनेजर कीपास में "मास्टर पासवर्ड क्रैक" के रूप में वर्णित किया गया है।
बग को आधिकारिक अमेरिकी सरकार पहचानकर्ता (इसे इस नाम से जाना जाता है) पाने के लिए काफी महत्वपूर्ण माना गया था CVE-2023-32784, यदि आप इसका पता लगाना चाहते हैं), और यह देखते हुए कि आपके पासवर्ड मैनेजर का मास्टर पासवर्ड आपके पूरे डिजिटल महल की कुंजी है, आप समझ सकते हैं कि कहानी ने इतना उत्साह क्यों पैदा किया।
अच्छी खबर यह है कि जो हमलावर इस बग का फायदा उठाना चाहता है, उसे निश्चित रूप से आपके कंप्यूटर को पहले से ही मैलवेयर से संक्रमित करना होगा, और इसलिए वह किसी भी तरह आपके कीस्ट्रोक्स और चल रहे प्रोग्रामों की जासूसी करने में सक्षम होगा।
दूसरे शब्दों में, बग को आसानी से प्रबंधित जोखिम माना जा सकता है जब तक कि KeePass का निर्माता एक अपडेट के साथ नहीं आता है, जो जल्द ही दिखाई देना चाहिए (जाहिर तौर पर जून 2023 की शुरुआत में)।
जैसा कि बग का खुलासा करने वाला ध्यान रखता है इशारा करना:
यदि आप एक मजबूत पासवर्ड के साथ पूर्ण डिस्क एन्क्रिप्शन का उपयोग करते हैं और आपका सिस्टम [मैलवेयर से मुक्त] है, तो आपको ठीक होना चाहिए। केवल इस खोज से कोई भी इंटरनेट पर दूर से भी आपका पासवर्ड नहीं चुरा सकता।
जोखिमों की व्याख्या की गई
मोटे तौर पर संक्षेप में कहें तो, बग यह सुनिश्चित करने की कठिनाई तक सीमित हो जाता है कि गोपनीय डेटा के सभी निशान आपके समाप्त होने के बाद मेमोरी से मिटा दिए जाते हैं।
हम यहां उन समस्याओं को नज़रअंदाज़ करेंगे कि मेमोरी में गुप्त डेटा होने से कैसे बचा जाए, भले ही संक्षेप में।
इस लेख में, हम हर जगह के प्रोग्रामर्स को बस यह याद दिलाना चाहते हैं कि कोड को एक सुरक्षा-सचेत समीक्षक द्वारा "स्वयं ही सही ढंग से साफ़ होता प्रतीत होता है" जैसी टिप्पणी के साथ अनुमोदित किया गया है...
...वास्तव में यह पूरी तरह से साफ़ नहीं हो सकता है, और संभावित डेटा रिसाव कोड के प्रत्यक्ष अध्ययन से स्पष्ट नहीं हो सकता है।
सीधे शब्दों में कहें तो, CVE-2023-32784 भेद्यता का मतलब है कि KeyPass प्रोग्राम समाप्त होने के बाद भी KeePass मास्टर पासवर्ड सिस्टम डेटा से पुनर्प्राप्त किया जा सकता है, क्योंकि आपके पासवर्ड के बारे में पर्याप्त जानकारी (हालांकि वास्तव में कच्चा पासवर्ड नहीं है, जिस पर हम ध्यान केंद्रित करेंगे) एक पल में चालू) सिस्टम स्वैप या स्लीप फ़ाइलों में पीछे रह सकता है, जहां आवंटित सिस्टम मेमोरी बाद के लिए सहेजी जा सकती है।
विंडोज़ कंप्यूटर पर जहां सिस्टम बंद होने पर हार्ड डिस्क को एन्क्रिप्ट करने के लिए बिटलॉकर का उपयोग नहीं किया जाता है, इससे आपके लैपटॉप को चुराने वाले बदमाश को यूएसबी या सीडी ड्राइव से बूट करने और यहां तक कि आपके मास्टर पासवर्ड को पुनर्प्राप्त करने का मौका मिलेगा। हालाँकि KeyPass प्रोग्राम स्वयं इस बात का ध्यान रखता है कि इसे कभी भी डिस्क पर स्थायी रूप से सेव न किया जाए।
मेमोरी में लंबे समय तक पासवर्ड लीक होने का मतलब यह भी है कि पासवर्ड, सैद्धांतिक रूप से, KeyPass प्रोग्राम के मेमोरी डंप से पुनर्प्राप्त किया जा सकता है, भले ही वह डंप आपके द्वारा पासवर्ड टाइप करने के लंबे समय बाद और KeePass के लंबे समय बाद पकड़ा गया हो। अब उसे अपने पास रखने की कोई आवश्यकता नहीं रही।
स्पष्ट रूप से, आपको यह मान लेना चाहिए कि आपके सिस्टम पर पहले से मौजूद मैलवेयर विभिन्न वास्तविक समय की स्नूपिंग तकनीकों के माध्यम से लगभग किसी भी टाइप किए गए पासवर्ड को पुनर्प्राप्त कर सकता है, जब तक कि वे आपके टाइपिंग के समय सक्रिय थे। लेकिन आप उचित रूप से उम्मीद कर सकते हैं कि खतरे के संपर्क में आने वाला आपका समय टाइपिंग की संक्षिप्त अवधि तक ही सीमित होगा, उसके बाद कई मिनटों, घंटों या दिनों तक या शायद उससे अधिक समय तक नहीं बढ़ाया जाएगा, जिसमें आपके कंप्यूटर को बंद करने के बाद भी शामिल होगा।
पीछे क्या छूट जाता है?
इसलिए हमने सोचा कि हम इस बात पर उच्च-स्तरीय नज़र डालेंगे कि कैसे गुप्त डेटा मेमोरी में ऐसे तरीकों से छोड़ा जा सकता है जो कोड से सीधे तौर पर स्पष्ट नहीं होते हैं।
यदि आप प्रोग्रामर नहीं हैं तो चिंता न करें - हम इसे सरल रखेंगे, और जैसे-जैसे आगे बढ़ेंगे समझाएँगे।
हम एक साधारण सी प्रोग्राम में मेमोरी उपयोग और क्लीनअप को देखकर शुरुआत करेंगे जो निम्न कार्य करके पासवर्ड दर्ज करने और अस्थायी रूप से संग्रहीत करने का अनुकरण करता है:
- स्मृति का एक समर्पित हिस्सा आवंटित करना विशेष रूप से पासवर्ड संग्रहीत करने के लिए.
- एक ज्ञात पाठ स्ट्रिंग सम्मिलित करना ताकि जरूरत पड़ने पर हम इसे आसानी से मेमोरी में ढूंढ सकें।
- 16 छद्म-यादृच्छिक 8-बिट ASCII वर्ण जोड़ना रेंज एपी से.
- मुद्रित करना सिम्युलेटेड पासवर्ड बफ़र.
- स्मृति को मुक्त करना पासवर्ड बफ़र को मिटाने की आशा में।
- बाहर निकल रहा है कार्यक्रम।
अत्यधिक सरलीकृत, सी कोड कुछ इस तरह दिख सकता है, बिना किसी त्रुटि जांच के, सी रनटाइम फ़ंक्शन से खराब-गुणवत्ता वाले छद्म-यादृच्छिक संख्याओं का उपयोग करते हुए rand()
, और किसी भी बफ़र ओवरफ्लो जांच को अनदेखा करना (वास्तविक कोड में कभी भी ऐसा न करें!):
// Ask for memory char* buff = malloc(128); // Copy in fixed string we can recognise in RAM strcpy(buff,"unlikelytext"); // Append 16 pseudo-random ASCII characters for (int i = 1; i <= 16; i++) { // Choose a letter from A (65+0) to P (65+15) char ch = 65 + (rand() & 15); // Modify the buff string directly in memory strncat(buff,&ch,1); } // Print it out, so we're done with buff printf("Full string was: %sn",buff); // Return the unwanted buffer and hope that expunges it free(buff);
वास्तव में, जिस कोड का हमने अंततः अपने परीक्षणों में उपयोग किया, उसमें नीचे दिखाए गए कुछ अतिरिक्त बिट्स और टुकड़े शामिल हैं, ताकि हम अवांछित या बची हुई सामग्री को देखने के लिए अपने अस्थायी पासवर्ड बफर की पूरी सामग्री को डंप कर सकें जैसा कि हमने इसका उपयोग किया था।
ध्यान दें कि हम कॉल करने के बाद जानबूझकर बफ़र को डंप कर देते हैं free()
, जो तकनीकी रूप से एक उपयोग-बाद-मुक्त बग है, लेकिन हम इसे यहां यह देखने के एक गुप्त तरीके के रूप में कर रहे हैं कि क्या हमारे बफर को वापस सौंपने के बाद कुछ भी महत्वपूर्ण चीज पीछे छूट जाती है, जिससे वास्तविक जीवन में एक खतरनाक डेटा रिसाव छेद हो सकता है।
हमने भी दो डाले हैं Waiting for [Enter]
प्रोग्राम में मुख्य बिंदुओं पर मेमोरी डंप बनाने का मौका देने के लिए कोड में संकेत देता है, जिससे हमें बाद में खोजने के लिए कच्चा डेटा मिलता है, ताकि हम देख सकें कि प्रोग्राम चलने के दौरान क्या पीछे रह गया था।
मेमोरी डंप करने के लिए, हम Microsoft का उपयोग करेंगे Sysinternals उपकरण procdump
साथ -ma
विकल्प (सारी मेमोरी डंप करें), जो विंडोज़ का उपयोग करने के लिए अपना स्वयं का कोड लिखने की आवश्यकता से बचाता है DbgHelp
प्रणाली और यह काफी जटिल है MiniDumpXxxx()
कार्यों.
सी कोड को संकलित करने के लिए, हमने फैब्रिस बेलार्ड के मुफ़्त और ओपन-सोर्स के अपने स्वयं के छोटे और सरल निर्माण का उपयोग किया टिनी सी कंपाइलर, 64-बिट विंडोज़ के लिए उपलब्ध है स्रोत और बाइनरी फॉर्म सीधे हमारे GitHub पेज से।
लेख में चित्रित सभी स्रोत कोड का कॉपी-और-पेस्ट करने योग्य पाठ पृष्ठ के नीचे दिखाई देता है।
जब हमने परीक्षण कार्यक्रम संकलित और चलाया तो यही हुआ:
C:UsersduckKEYPASS> petcc64 -stdinc -stdlib unl1.c टिनी C कंपाइलर - कॉपीराइट (C) 2001-2023 फैब्रिस बेलार्ड को एक शिक्षण उपकरण के रूप में उपयोग करने के लिए पॉल डकलिन द्वारा हटा दिया गया संस्करण petcc64-0.9.27 [0006] - 64-बिट उत्पन्न करता है केवल पीई -> unl1.c -> c:/users/duck/tcc/petccinc/stdio.h [। . . .] -> c:/users/duck/tcc/petcclib/libpetcc1_64.a -> C:/Windows/system32/msvcrt.dll -> C:/Windows/system32/kernel32.dll -------- ---------------------- पुण्य फ़ाइल का आकार अनुभाग 1000 200 438 .पाठ 2000 800 2एसी .डेटा 3000 सी00 24 .पीडेटा -------- ---------------------- <- unl1.exe (3584 बाइट्स) C:UsersduckKEYPASS> unl1.exe प्रारंभ 00F51390 पर 'नया' बफर डंप करना: 90 57 F5 00 00 00 00 00 50 01 F5 00 00 00 00 00 .W......P....... 00F513A0: 73 74 65 6D 33 32 5C 63 6D 64 2E 65 78 65 00 44 स्टेम32cmd. exe.D 00F513B0: 72 69 76 65 72 44 61 74 61 3D 43 3A 5C 57 69 6E नदी डेटा=C:Win 00F513C0: 64 6F 77 73 5C 53 79 73 74 65 6D 33 32 5C 44 72 डॉउज़ सिस्टम32Dr 00F513D0: 69 76 65 72 73 5सी 44 72 69 76 65 72 44 61 74 61 इवर्सड्राइवरडेटा 00एफ513ई0: 00 45 46 43 5एफ 34 33 37 32 3डी 31 00 46 50 53 5एफ .ईएफसी_4372=1.एफपीएस_ 00एफ 513एफ0: 42 52 4एफ 57 53 45 52 5एफ 41 50 50 5एफ 50 52 4एफ 46 ब्राउज़र_एपीपी_प्रोफ 00एफ51400: 49 4सी 45 5एफ 53 54 52 49 4ई 47 3डी 49 6ई 74 65 72 आईएलई_स्ट्रिंग=इंटर 00एफ51410: 6ई 65 74 20 45 78 70 6सी 7ए 56 एफ4 3सी एसी 4बी 00 00 नेट एक्सप्लज़वी।< .K.. पूरी स्ट्रिंग थी: असंभावित टेक्स्टJHKNEJJCPOMDJHAN 00F51390: 75 6E 6C 69 6B 65 6C 79 74 65 78 74 4A 48 4B 4E असंभावित टेक्स्टJHKN 00F513A0: 45 4A 4A 43 50 4F 4D 44 4A 48 41 4E 00 65 00 44 EJJCPOMDJHAN.eD 00F513B0 : 72 69 76 65 72 44 61 74 61 3डी 43 3ए 5सी 57 69 6ई रिवरडेटा=सी:विन 00एफ513सी0: 64 6एफ 77 73 5सी 53 79 73 74 65 6डी 33 32 5सी 44 72 डॉउ सिस्टम 32डॉ 00एफ513डी0: 69 76 65 72 73 5सी 44 72 69 76 65 72 44 61 74 61 इवर्सड्राइवरडेटा 00F513E0: 00 45 46 43 5F 34 33 37 32 3D 31 00 46 50 53 5F .EFC_4372=1.FPS_ 00F513F0: 42 52 4एफ 57 53 45 52 5एफ 41 50 50 5एफ 50 52 4F 46 Browser_APP_PROF 00F51400: 49 4C 45 5F 53 54 52 49 4E 47 3D 49 6E 74 65 72 ILE_STRING=इंटर 00F51410: 6E 65 74 20 45 78 70 6C 7A 56 F4 3C AC 4B 00 00 नेट एक्स्प्लज़V.<.K.. बफर मुक्त होने के लिए [ENTER] की प्रतीक्षा की जा रही है... मुक्त() 00F51390 के बाद डंपिंग बफर: A0 67 F5 00 00 00 00 00 50 01 F5 00 00 00 00 00 .g......P...... . 00F513A0: 45 4A 4A 43 50 4F 4D 44 4A 48 41 4E 00 65 00 44 EJJCPOMDJHAN.eD 00F513B0: 72 69 76 65 72 44 61 74 61 3D 43 3A 5C 57 69 6 00ई रिवरडेटा=सी:विन 513एफ0सी64: 6 77एफ 73 5 53C 79 73 74 65 6 33D 32 5 44C 72 32 dowsSystem00Dr 513F0D69: 76 65 72 73 5 44C 72 69 76 65 72 44 61 74 61 00 iversDriverData 513F0E 00: 45 46 43 5 34एफ 33 37 32 3 31डी 00 46 50 53 5 4372F .EFC_1=00.FPS_ 513F0F42: 52 4 57F 53 45 52 5 41F 50 50 5 50F 52 4 46F 00 ब्राउज़र_APP_PROF 51400F49: 4 45C 5 53F 54 52 49 4 47 ई 3 49डी 6 74ई 65 72 00 ILE_STRING=इंटर 51410F6: 65E 74 20 45 78 70 6 4सी 00डी 00 4 4डी एसी 00बी 00 XNUMX नेट स्पष्टीकरण..एमके। [ENTER] के मुख्य() से बाहर निकलने की प्रतीक्षा की जा रही है... C:UsersduckKEYPASS>
इस रन में, हमने किसी भी प्रोसेस मेमोरी डंप को पकड़ने की जहमत नहीं उठाई, क्योंकि हम आउटपुट से तुरंत देख सकते थे कि यह कोड डेटा लीक कर रहा है।
विंडोज़ सी रनटाइम लाइब्रेरी फ़ंक्शन को कॉल करने के ठीक बाद malloc()
, हम देख सकते हैं कि जो बफ़र हमें वापस मिलता है उसमें प्रोग्राम के स्टार्टअप कोड से बचा हुआ पर्यावरण चर डेटा जैसा दिखता है, पहले 16 बाइट्स को स्पष्ट रूप से कुछ प्रकार के बाएं-ओवर मेमोरी आवंटन हेडर की तरह दिखने के लिए बदल दिया जाता है।
(ध्यान दें कि वे 16 बाइट्स दो 8-बाइट मेमोरी पतों की तरह कैसे दिखते हैं, 0xF55790
और 0xF50150
, जो क्रमशः हमारे अपने मेमोरी बफ़र के ठीक बाद और ठीक पहले हैं।)
जब पासवर्ड मेमोरी में होना चाहिए, तो हम बफर में पूरी स्ट्रिंग को स्पष्ट रूप से देख सकते हैं, जैसा कि हम उम्मीद करेंगे।
लेकिन कॉल करने के बाद free()
, ध्यान दें कि कैसे हमारे बफ़र के पहले 16 बाइट्स को एक बार फिर पास के मेमोरी एड्रेस की तरह दिखने के साथ फिर से लिखा गया है, संभवतः इसलिए मेमोरी एलोकेटर मेमोरी में ब्लॉक का ट्रैक रख सकता है जिसे वह फिर से उपयोग कर सकता है ...
...लेकिन हमारा बाकी "समाप्त" पासवर्ड टेक्स्ट (अंतिम 12 यादृच्छिक अक्षर EJJCPOMDJHAN
) को पीछे छोड़ दिया गया है।
न केवल हमें सी में अपने स्वयं के मेमोरी आवंटन और डी-आवंटन को प्रबंधित करने की आवश्यकता है, हमें यह भी सुनिश्चित करना होगा कि हम डेटा बफ़र्स के लिए सही सिस्टम फ़ंक्शंस चुनें यदि हम उन्हें सटीक रूप से नियंत्रित करना चाहते हैं।
उदाहरण के लिए, इसके बजाय इस कोड पर स्विच करने से, हमें मेमोरी में क्या है उस पर थोड़ा अधिक नियंत्रण मिलता है:
से स्विच करके malloc()
और free()
निम्न-स्तरीय विंडोज़ आवंटन फ़ंक्शंस का उपयोग करने के लिए VirtualAlloc()
और VirtualFree()
सीधे तौर पर, हमें बेहतर नियंत्रण मिलता है।
हालाँकि, हम गति की कीमत चुकाते हैं, क्योंकि प्रत्येक कॉल VirtualAlloc()
एक कॉल से अधिक कार्य करता है malloc()
, जो पूर्व-आवंटित निम्न-स्तरीय मेमोरी के एक ब्लॉक को लगातार विभाजित और उप-विभाजित करके काम करता है।
का प्रयोग VirtualAlloc()
बार-बार छोटे ब्लॉकों के लिए भी समग्र रूप से अधिक मेमोरी का उपयोग होता है, क्योंकि प्रत्येक ब्लॉक द्वारा वितरित किया जाता है VirtualAlloc()
आम तौर पर 4KB मेमोरी (या 2MB, यदि आप तथाकथित का उपयोग कर रहे हैं) की खपत करता है बड़े स्मृति पन्ने), ताकि ऊपर दिया गया हमारा 128-बाइट बफ़र 4096 बाइट्स तक पूर्णांकित हो जाए, जिससे 3968KB मेमोरी ब्लॉक के अंत में 4 बाइट्स बर्बाद हो जाएँ।
लेकिन, जैसा कि आप देख सकते हैं, जो मेमोरी हमें वापस मिलती है वह स्वचालित रूप से खाली हो जाती है (शून्य पर सेट हो जाती है), इसलिए हम यह नहीं देख सकते कि पहले क्या था, और इस बार जब हम अपना उपयोग-बाद-मुक्त करने का प्रयास करते हैं तो प्रोग्राम क्रैश हो जाता है ट्रिक, क्योंकि विंडोज़ यह पता लगाता है कि हम उस मेमोरी पर नज़र डालने की कोशिश कर रहे हैं जो अब हमारे पास नहीं है:
C:UsersduckKEYPASS> unl2 प्रारंभ में डंपिंग 'नया' बफर 0000000000EA0000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0000000000EA0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0000000000EA0020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 .. .............. 0000000000EA0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000000000 0040 00 ................ 00EA00: 00 00 00 00 00 00 00 00 00 00 00 00 00 0000000000 0050 00 ................ 00EA00: 00 00 00 00 00 00 00 00 00 00 00 00 00 0000000000 0060 00 ................ 00EA00: 00 00 00 00 00 00 00 00 00 00 00 00 00 0000000000 0070 00 ................ 00EA00: 00 00 00 00 00 00 00 00 00 00 00 00 00 0000000000 0080 00 ................ 00EA00: 00 00 00 00 00 00 00 00 00 00 00 00 00 0000000000 0000 75 6 ................ पूर्ण स्ट्रिंग थी: असंभावित टेक्स्टआईबीआईपीजेपीएचईओपीओआईडीएलएल 6ईए69: 6 65ई 6सी 79 74बी 65 78सी 74 49 42 49 50 0000000000 0010 4 50 असंभावितटेक्स्टआईबीआईपी 50ईए48: 45ए 4 50 4 49 44 4F 4 00F 00 00 00C 0000000000C 0020 00 00 00 JPPHEOPOIDLL.... 00EA00: 00 00 00 00 00 00 00 00 00 00 00 0000000000 0030 00 00 00 ................ 00EA00 : 00 00 00 00 00 00 00 00 00 00 00 0000000000 0040 00 00 00 ................ 00EA00: 00 00 00 00 00 00 00 00 00 00 00 0000000000 0050 00 00 00 ................ 00EA00: 00 00 00 00 00 00 00 00 00 00 00 0000000000 0060 00 00 00 ............... . 00EA00: 00 00 00 00 00 00 00 00 00 00 00 0000000000 0070 00 00 00 ................ 00EA00: 00 00 00 00 00 00 00 00 00 00 00 0000000000 0080 00 00 00 ................ 00EA00: 00 00 00 00 00 00 00 00 00 00 00 0000000000 0000 XNUMX XNUMX XNUMX ............... ... बफर मुक्त होने के लिए [ENTER] की प्रतीक्षा की जा रही है... मुक्त होने के बाद डंपिंग बफर() XNUMXEAXNUMX: [प्रोग्राम यहीं समाप्त हो गया क्योंकि विंडोज़ ने हमारे मुक्त-बाद-उपयोग को पकड़ लिया]
क्योंकि जो मेमोरी हमने खाली कर दी है, उसे पुनः आवंटित करने की आवश्यकता होगी VirtualAlloc()
इससे पहले कि इसे दोबारा इस्तेमाल किया जा सके, हम यह मान सकते हैं कि इसे पुनर्चक्रित करने से पहले इसे शून्य कर दिया जाएगा।
हालाँकि, यदि हम यह सुनिश्चित करना चाहते हैं कि इसे खाली कर दिया गया है, तो हम विशेष विंडोज़ फ़ंक्शन को कॉल कर सकते हैं RtlSecureZeroMemory()
इसे मुक्त करने से ठीक पहले, यह गारंटी देने के लिए कि विंडोज़ पहले हमारे बफर में शून्य लिखेगा।
संबंधित कार्य RtlZeroMemory()
, यदि आप सोच रहे थे, एक समान काम करता है, लेकिन वास्तव में काम करने की गारंटी के बिना, क्योंकि कंपाइलर्स को इसे सैद्धांतिक रूप से अनावश्यक के रूप में हटाने की अनुमति है यदि वे देखते हैं कि बफर का बाद में दोबारा उपयोग नहीं किया जाता है।
जैसा कि आप देख सकते हैं, यदि हम उस समय को कम करना चाहते हैं जब स्मृति में संग्रहीत रहस्य बाद के लिए पड़े रह सकते हैं, तो हमें सही विंडोज़ फ़ंक्शंस का उपयोग करने में काफी सावधानी बरतने की आवश्यकता है।
इस आलेख में, हम यह देखने नहीं जा रहे हैं कि आप भौतिक रैम में लॉक करके रहस्यों को अपनी स्वैप फ़ाइल में गलती से सहेजे जाने से कैसे रोक सकते हैं। (संकेत देना: VirtualLock()
वास्तव में यह अपने आप में पर्याप्त नहीं है।) यदि आप निम्न-स्तरीय विंडोज़ मेमोरी सुरक्षा के बारे में अधिक जानना चाहते हैं, तो हमें टिप्पणियों में बताएं और हम इसे भविष्य के लेख में देखेंगे।
स्वचालित मेमोरी प्रबंधन का उपयोग करना
मेमोरी को स्वयं आवंटित करने, प्रबंधित करने और हटाने से बचने का एक अच्छा तरीका एक प्रोग्रामिंग भाषा का उपयोग करना है जो इसका ख्याल रखती है malloc()
और free()
या, VirtualAlloc()
और VirtualFree()
, स्वचालित रूप से।
स्क्रिप्टिंग भाषा जैसे पर्ल, अजगर, लुआ, जावास्क्रिप्ट और अन्य लोग पृष्ठभूमि में आपके लिए मेमोरी उपयोग को ट्रैक करके, C और C++ कोड को परेशान करने वाले सबसे आम मेमोरी सुरक्षा बग से छुटकारा पाते हैं।
जैसा कि हमने पहले उल्लेख किया है, ऊपर हमारा खराब ढंग से लिखा गया नमूना सी कोड अब ठीक काम करता है, लेकिन केवल इसलिए कि यह अभी भी एक सुपर-सरल प्रोग्राम है, निश्चित आकार के डेटा संरचनाओं के साथ, जहां हम निरीक्षण द्वारा सत्यापित कर सकते हैं कि हम अपने 128- को ओवरराइट नहीं करेंगे। बाइट बफ़र, और केवल एक ही निष्पादन पथ है जो इससे शुरू होता है malloc()
और संगत के साथ समाप्त होता है free()
.
लेकिन अगर हमने इसे वेरिएबल-लेंथ पासवर्ड जेनरेशन की अनुमति देने के लिए अपडेट किया है, या जेनरेशन प्रक्रिया में अतिरिक्त सुविधाएं जोड़ी हैं, तो हम (या जो भी कोड को आगे बनाए रखता है) आसानी से बफर ओवरफ्लो, उपयोग-बाद-मुक्त बग, या मेमोरी के साथ समाप्त हो सकता है। कभी भी मुक्त नहीं होता है और इसलिए गुप्त डेटा को लंबे समय तक लटका हुआ छोड़ देता है जब इसकी आवश्यकता नहीं रह जाती है।
लुआ जैसी भाषा में, हम लुआ को रन-टाइम वातावरण दे सकते हैं, जो वही करता है जिसे शब्दजाल में जाना जाता है स्वचालित कचरा संग्रहण, सिस्टम से मेमोरी प्राप्त करने और जब यह पता चले कि हमने इसका उपयोग बंद कर दिया है तो इसे वापस करना।
जिस C प्रोग्राम को हमने ऊपर सूचीबद्ध किया है वह बहुत सरल हो जाता है जब हमारे लिए मेमोरी आवंटन और डी-आवंटन का ध्यान रखा जाता है:
हम स्ट्रिंग को होल्ड करने के लिए मेमोरी आवंटित करते हैं s
बस स्ट्रिंग निर्दिष्ट करके 'unlikelytext'
यह करने के लिए.
हम बाद में या तो लुआ को स्पष्ट रूप से संकेत दे सकते हैं कि अब हमें इसमें कोई दिलचस्पी नहीं है s
इसे मान निर्दिष्ट करके nil
(सब nils
मूलतः वही लुआ ऑब्जेक्ट हैं), या उपयोग करना बंद कर दें s
और लुआ को यह पता चलने तक प्रतीक्षा करें कि अब इसकी आवश्यकता नहीं है।
किसी भी तरह, द्वारा उपयोग की गई मेमोरी s
अंततः स्वचालित रूप से पुनर्प्राप्त हो जाएगा.
और टेक्स्ट स्ट्रिंग्स (लुआ ऑपरेटर) में जोड़ते समय बफर ओवरफ्लो या आकार के कुप्रबंधन को रोकने के लिए ..
, उच्चारण कॉनकैट, अनिवार्य रूप से दो तारों को एक साथ जोड़ता है, जैसे +
पायथन में), हर बार जब हम किसी स्ट्रिंग को बढ़ाते हैं या छोटा करते हैं, तो लुआ जादुई रूप से मूल स्ट्रिंग को उसके मौजूदा मेमोरी स्थान में संशोधित करने या बदलने के बजाय, एक बिल्कुल नई स्ट्रिंग के लिए स्थान आवंटित करता है।
यह दृष्टिकोण धीमा है, और पाठ हेरफेर के दौरान आवंटित मध्यवर्ती स्ट्रिंग्स के कारण सी में प्राप्त मेमोरी उपयोग शिखर से अधिक है, लेकिन बफर ओवरफ्लो के संबंध में यह अधिक सुरक्षित है।
लेकिन इस प्रकार का स्वचालित स्ट्रिंग प्रबंधन (जिसे शब्दजाल में जाना जाता है अचल स्थिति, क्योंकि तार कभी नहीं मिलते उत्परिवर्तित, या एक बार बन जाने के बाद उन्हें संशोधित कर दिया जाता है), अपने साथ नए साइबर सुरक्षा सिरदर्द लेकर आते हैं।
हमने विंडोज़ पर उपरोक्त लूआ प्रोग्राम को प्रोग्राम के बाहर निकलने से ठीक पहले, दूसरे विराम तक चलाया:
C:UsersduckKEYPASS> lua s1.lua पूरी स्ट्रिंग है: अनचाहे textHLKONBOJILAGLNLN स्ट्रिंग को मुक्त करने से पहले [ENTER] की प्रतीक्षा की जा रही है... बाहर निकलने से पहले [ENTER] की प्रतीक्षा की जा रही है...
इस बार, हमने एक प्रोसेस मेमोरी डंप लिया, इस प्रकार:
C:UsersduckKEYPASS> procdump -ma lua lua-s1.dmp ProcDump v11.0 - Sysinternals प्रक्रिया डंप उपयोगिता कॉपीराइट (C) 2009-2022 मार्क रसिनोविच और एंड्रयू रिचर्ड्स Sysinternals - www.sysinternals.com [00:00:00] डंप 1 आरंभ: C:UsersduckKEYPASSlua-s1.dmp [00:00:00] डंप 1 लेखन: अनुमानित डंप फ़ाइल का आकार 10 एमबी है। [00:00:00] डंप 1 पूर्ण: 10 एमबी 0.1 सेकंड में लिखा गया [00:00:01] डंप गिनती पहुंच गई।
फिर हमने यह सरल स्क्रिप्ट चलाई, जो डंप फ़ाइल को वापस पढ़ती है, मेमोरी में हर जगह उस ज्ञात स्ट्रिंग को ढूंढती है unlikelytext
दिखाई देता है, और इसे डंपफ़ाइल में इसके स्थान और तुरंत आने वाले ASCII वर्णों के साथ प्रिंट करता है:
भले ही आपने पहले स्क्रिप्ट भाषाओं का उपयोग किया हो, या तथाकथित सुविधाओं वाले किसी प्रोग्रामिंग इकोसिस्टम में काम किया हो प्रबंधित तार, जहां सिस्टम आपके लिए मेमोरी आवंटन और डीलोकेशन का ट्रैक रखता है, और उन्हें आवश्यकतानुसार संभालता है...
...आप इस मेमोरी स्कैन द्वारा उत्पन्न आउटपुट को देखकर आश्चर्यचकित हो सकते हैं:
C:UsersduckKEYPASS> lua findit.lua lua-s1.dmp 006D8AFC: असंभावित टेक्स्टALJBNGOAPLLBDEB 006D8B3C: असंभावित टेक्स्टALJBNGOA 006D8B7C: असंभावित टेक्स्टALJBNGO 006D8BFC: असंभावित टेक्स्टALJBNGOAPLLBDEBJ 006D8CBC: असंभावित टेक्स्टALJBN 006D8D 7C: असंभावित टेक्स्टALJBNGOAP 006D903C: असंभावित टेक्स्टALJBNGOAPL 006D90BC: असंभावित टेक्स्टALJBNGOAPLL 006D90FC: असंभावित टेक्स्टALJBNG 006D913C: असंभावित टेक्स्टALJBNGOAPLLB 006D91BC: असंभावित टेक्स्टALJB 006D91FC: असंभावित टेक्स्टALJBNGOAPLLBD 006D923C : असंभावित टेक्स्टALJBNGOAPLLBDE 006DB70C: असंभावित टेक्स्टALJ 006DBB8C: असंभावित टेक्स्टAL 006DBD0C: असंभावित टेक्स्टए
लो और देखो, उस समय हमने अपना मेमोरी डंप पकड़ लिया, भले ही हम स्ट्रिंग के साथ समाप्त हो गए थे s
(और लुआ से कहा कि हमें इसकी अब और आवश्यकता नहीं है s = nil
), कोड द्वारा बनाए गए सभी तार अभी भी रैम में मौजूद थे, अभी तक पुनर्प्राप्त या हटाए नहीं गए थे।
वास्तव में, यदि हम उपरोक्त आउटपुट को रैम में दिखाई देने वाले क्रम का पालन करने के बजाय स्ट्रिंग्स द्वारा स्वयं सॉर्ट करते हैं, तो आप यह देखने में सक्षम होंगे कि लूप के दौरान क्या हुआ था जहां हमने एक समय में एक अक्षर को हमारी पासवर्ड स्ट्रिंग में जोड़ा था:
C:UsersduckKEYPASS> lua findit.lua lua-s1.dmp | सॉर्ट /+10 006DBD0C: असंभावित टेक्स्टA 006DBB8C: असंभावित टेक्स्टAL 006DB70C: असंभावित टेक्स्टALJ 006D91BC: असंभावित टेक्स्टALJB 006D8CBC: असंभावित टेक्स्टALJBN 006D90FC: असंभावित टेक्स्टALJBNG 006D8B7C: असंभावित टेक्स्टALJBNGO 006D8B3C: असंभावित टेक्स्टALJBNGOA 006 D8D7C: असंभावित टेक्स्टALJBNGOAP 006D903C: असंभावित टेक्स्टALJBNGOAPL 006D90BC: असंभावित टेक्स्टALJBNGOAPLL 006D913C: असंभावित टेक्स्टALJBNGOAPLLB 006D91FC: असंभावित टेक्स्टALJBNGOAPLLBD 006D923C: असंभावित टेक्स्टALJBNGOAPLLBDE 006D8AFC: असंभावित टेक्स्टALJBNGOAPLLBD ईबी 006डी8बीएफसी : असंभावित टेक्स्टALJBNGOAPLLBDEBJ
वे सभी अस्थायी, मध्यवर्ती तार अभी भी वहाँ हैं, इसलिए भले ही हमने अंतिम मान को सफलतापूर्वक मिटा दिया हो s
, हम अभी भी इसके अंतिम चरित्र को छोड़कर सब कुछ लीक कर रहे होंगे।
वास्तव में, इस मामले में, तब भी जब हमने विशेष लुआ फ़ंक्शन को कॉल करके जानबूझकर अपने प्रोग्राम को सभी अनावश्यक डेटा का निपटान करने के लिए मजबूर किया था collectgarbage()
(अधिकांश स्क्रिप्टिंग भाषाओं में कुछ समान होता है), उन अजीब अस्थायी स्ट्रिंग्स में अधिकांश डेटा वैसे भी रैम में फंस जाता है, क्योंकि हमने पुराने अच्छे का उपयोग करके लुआ को स्वचालित मेमोरी प्रबंधन करने के लिए संकलित किया था malloc()
और free()
.
दूसरे शब्दों में, भले ही लुआ ने अपने अस्थायी मेमोरी ब्लॉकों को फिर से उपयोग करने के लिए पुनः प्राप्त कर लिया, हम यह नियंत्रित नहीं कर सके कि उन मेमोरी ब्लॉकों का पुन: उपयोग कैसे और कब किया जाएगा, और इस प्रकार वे अपने बाएं हाथ के साथ प्रक्रिया के अंदर कितनी देर तक पड़े रहेंगे- डेटा के ख़त्म होने, डंप होने या अन्यथा लीक होने की प्रतीक्षा में।
.NET दर्ज करें
लेकिन KeePass के बारे में क्या, जहां से यह लेख शुरू हुआ?
KeePass C# में लिखा गया है, और .NET रनटाइम का उपयोग करता है, इसलिए यह मेमोरी कुप्रबंधन की समस्याओं से बचाता है जो C प्रोग्राम अपने साथ लाते हैं...
...लेकिन C# अपने स्वयं के टेक्स्ट स्ट्रिंग्स को प्रबंधित करता है, बल्कि लुआ की तरह, जो सवाल उठाता है:
भले ही प्रोग्रामर ने पूरा मास्टर पासवर्ड पूरा करने के बाद उसे एक ही स्थान पर संग्रहीत करने से परहेज किया हो, फिर भी मेमोरी डंप तक पहुंच रखने वाले हमलावरों को मास्टर पासवर्ड का अनुमान लगाने या पुनर्प्राप्त करने के लिए पर्याप्त बचा हुआ अस्थायी डेटा मिल सकता है, भले ही वे आपके द्वारा पासवर्ड टाइप करने के कुछ मिनटों, घंटों या दिनों के बाद हमलावरों को आपके कंप्यूटर तक पहुंच मिल गई?
सीधे शब्दों में कहें तो, क्या आपके मास्टर पासवर्ड के पता लगाने योग्य, भूतिया अवशेष हैं जो रैम में जीवित रहते हैं, भले ही आप उम्मीद करते हों कि उन्हें मिटा दिया गया है?
जीथब उपयोगकर्ता के रूप में, कष्टप्रद वडोहनी ने खोजा, उत्तर (कम से कम 2.54 से पहले के KeePass संस्करणों के लिए) है, "हाँ।"
स्पष्ट होने के लिए, हमें नहीं लगता कि आपका वास्तविक मास्टर पासवर्ड KeePass मेमोरी डंप से एकल टेक्स्ट स्ट्रिंग के रूप में पुनर्प्राप्त किया जा सकता है, क्योंकि लेखक ने मास्टर पासवर्ड प्रविष्टि के लिए एक विशेष फ़ंक्शन बनाया है जो पूर्ण भंडारण से बचने के लिए अपने रास्ते से हट जाता है पासवर्ड जहां इसे आसानी से देखा और सूंघा जा सके।
हमने अपना मास्टर पासवर्ड सेट करके खुद को संतुष्ट कर लिया SIXTEENPASSCHARS
, इसे टाइप करना, और फिर तुरंत, शीघ्र ही, और लंबे समय बाद मेमोरी डंप लेना।
हमने एक साधारण लुआ स्क्रिप्ट के साथ डंप की खोज की, जो उस पासवर्ड टेक्स्ट को 8-बिट एएससीआईआई प्रारूप में और 16-बिट यूटीएफ -16 (विंडोज वाइडचर) प्रारूप में, इस तरह से ढूंढती थी:
परिणाम उत्साहवर्धक थे:
C:UsersduckKEYPASS> lua searchknown.lua kp2-post.dmp डंप फ़ाइल में पढ़ना... हो गया। 8-बिट ASCII के रूप में SIXTEENPASCHARS की खोज की जा रही है... नहीं मिला। UTF-16 के रूप में SIXTEENPASCHARS की खोज की जा रही है... नहीं मिला।
लेकिन CVE-2023-32784 के खोजकर्ता Vdohney ने देखा कि जैसे ही आप अपना मास्टर पासवर्ड टाइप करते हैं, KeePass आपको यूनिकोड "ब्लॉब" वर्णों से युक्त एक प्लेसहोल्डर स्ट्रिंग का निर्माण और प्रदर्शित करके दृश्य प्रतिक्रिया देता है, जिसमें आपकी लंबाई भी शामिल होती है। पासवर्ड:
विंडोज़ पर वाइडचर टेक्स्ट स्ट्रिंग्स में (जिसमें प्रति कैरेक्टर दो बाइट्स होते हैं, ASCII की तरह केवल एक बाइट नहीं), "ब्लॉब" कैरेक्टर को रैम में हेक्स बाइट के रूप में एन्कोड किया जाता है 0xCF
द्वारा पीछा 0x25
(जो ASCII में प्रतिशत चिह्न होता है)।
इसलिए, भले ही KeePass आपके द्वारा पासवर्ड दर्ज करते समय आपके द्वारा टाइप किए जाने वाले कच्चे अक्षरों के साथ बहुत सावधानी बरत रहा हो, आपके पास "ब्लॉब" वर्णों की बची हुई स्ट्रिंग हो सकती है, जिन्हें बार-बार चलाने पर मेमोरी में आसानी से पता लगाया जा सकता है जैसे कि CF25CF25
or CF25CF25CF25
...
...और, यदि ऐसा है, तो आपके द्वारा पाए गए ब्लॉब वर्णों की सबसे लंबी श्रृंखला संभवतः आपके पासवर्ड की लंबाई बता देगी, जो कि पासवर्ड जानकारी रिसाव का एक मामूली रूप होगा, यदि कुछ और नहीं।
हमने बचे हुए पासवर्ड प्लेसहोल्डर स्ट्रिंग के संकेतों को देखने के लिए निम्नलिखित लुआ स्क्रिप्ट का उपयोग किया:
आउटपुट आश्चर्यजनक था (हमने स्थान बचाने के लिए समान संख्या में ब्लॉब्स वाली, या पिछली पंक्ति की तुलना में कम ब्लॉब्स वाली क्रमिक पंक्तियों को हटा दिया है):
C:UsersduckKEYPASS> lua findblobs.lua kp2-post.dmp 000EFF3C: * [। . .] 00बीई621बी: ** 00बीई64सी7: *** [. . .] 00BE6E8F: **** [. . .] 00BE795F: ***** [. . .] 00BE84F7: ****** [. . .] 00बीई8एफ37: ******* [8 बूँद, 9 बूँद, आदि के लिए इसी तरह जारी रहता है] [ठीक 16 बूँदों की दो अंतिम पंक्तियों तक] 00सी0503बी: ************* *** 00सी05077: **************** 00सी09337: * 00सी09738: * [ शेष सभी मैच एक बूँद लंबे हैं] 0123बी058: *
पास-पास लेकिन लगातार बढ़ती मेमोरी पतों पर, हमें 3 ब्लॉब्स की एक व्यवस्थित सूची मिली, फिर 4 ब्लॉब्स और इसी तरह 16 ब्लॉब्स (हमारे पासवर्ड की लंबाई) तक, इसके बाद सिंगल-ब्लॉब स्ट्रिंग्स के कई बेतरतीब ढंग से बिखरे हुए उदाहरण मिले। .
तो, वे प्लेसहोल्डर "ब्लॉब" स्ट्रिंग्स वास्तव में मेमोरी में लीक हो रही हैं और पासवर्ड की लंबाई को लीक करने के लिए पीछे रह रही हैं, जब तक कि कीपास सॉफ़्टवेयर आपके मास्टर पासवर्ड के साथ समाप्त नहीं हो जाता।
अगला चरण
हमने और अधिक खुदाई करने का निर्णय लिया, ठीक वैसे ही जैसे वडोहनी ने किया था।
हमने 16-बिट प्रारूप में किसी एकल ASCII वर्ण के बाद ब्लॉब वर्णों की श्रृंखला का पता लगाने के लिए अपने पैटर्न मिलान कोड को बदल दिया (ASCII वर्णों को UTF-16 में उनके सामान्य 8-बिट ASCII कोड के रूप में दर्शाया जाता है, जिसके बाद एक शून्य बाइट होता है)।
इस बार, स्थान बचाने के लिए, हमने किसी भी मैच के आउटपुट को दबा दिया है जो पिछले मैच से बिल्कुल मेल खाता है:
अचंभा अचंभा:
C:UsersduckKEYPASS> lua searchkp.lua kp2-post.dmp 00BE581B: *I 00BE621B: **X 00BE6BD3: ***T 00BE769B: ****E 00BE822B: *****E 00BE8C6B: ******N 00BE974B: *******P 00BEA25B: ********A 00BEAD33: *********S 00BEB81B: **********S 00BEC383: ***********C 00BECEEB: ************H 00BEDA5B: *************A 00BEE623: **************R 00BEF1A3: ***************S 03E97CF2: *N 0AA6F0AF: *W 0D8AF7C8: *X 0F27BAF8: *S
देखिए, .NET के प्रबंधित स्ट्रिंग मेमोरी क्षेत्र से हमें क्या मिलता है!
अस्थायी "ब्लॉब स्ट्रिंग्स" का एक बारीकी से समूहीकृत सेट जो हमारे पासवर्ड में दूसरे अक्षर से शुरू होने वाले क्रमिक अक्षरों को प्रकट करता है।
उन लीक तारों के बाद व्यापक रूप से वितरित एकल-वर्ण मिलान होते हैं जिन्हें हम संयोग से उत्पन्न मानते हैं। (कीपास डंप फ़ाइल का आकार लगभग 250 एमबी है, इसलिए इसमें "ब्लॉब" वर्णों के प्रकट होने के लिए पर्याप्त जगह है जैसे कि यह भाग्य से हो।)
भले ही हम उन अतिरिक्त चार मिलानों को ध्यान में रखें, बजाय उन्हें संभावित बेमेल के रूप में त्यागने के, हम अनुमान लगा सकते हैं कि मास्टर पासवर्ड इनमें से एक है:
?Xteenpasschars ?Xteenpasschars ?Xteenpasschars ?Xteenpasschars
जाहिर है, यह सरल तकनीक पासवर्ड में पहला अक्षर नहीं ढूंढती है, क्योंकि पहला "ब्लॉब स्ट्रिंग" केवल उस पहले अक्षर के टाइप होने के बाद ही बनाया जाता है।
ध्यान दें कि यह सूची अच्छी और छोटी है क्योंकि हमने उन मैचों को फ़िल्टर कर दिया है जो ASCII वर्णों में समाप्त नहीं होते थे।
यदि आप किसी भिन्न श्रेणी के पात्रों की तलाश कर रहे थे, जैसे कि चीनी या कोरियाई अक्षर, तो आपको अधिक आकस्मिक हिट मिल सकते हैं, क्योंकि मिलान करने के लिए बहुत अधिक संभावित पात्र हैं...
...लेकिन हमें संदेह है कि आप किसी भी तरह अपने मास्टर पासवर्ड के काफी करीब पहुंच जाएंगे, और पासवर्ड से संबंधित "ब्लॉब स्ट्रिंग्स" को रैम में एक साथ समूहीकृत किया गया प्रतीत होता है, संभवतः क्योंकि वे लगभग एक ही समय में एक ही भाग द्वारा आवंटित किए गए थे .NET रनटाइम।
और वहाँ, एक निश्चित रूप से लंबे और विचारोत्तेजक संक्षेप में, की दिलचस्प कहानी है CVE-2023-32784.
क्या करना है?
- यदि आप KeePass उपयोगकर्ता हैं, तो घबराएं नहीं। हालाँकि यह एक बग है, और तकनीकी रूप से एक शोषण योग्य भेद्यता है, दूरस्थ हमलावर जो इस बग का उपयोग करके आपके पासवर्ड को क्रैक करना चाहते हैं, उन्हें पहले आपके कंप्यूटर पर मैलवेयर इम्प्लांट करना होगा। इससे उन्हें सीधे आपके पासवर्ड चुराने के कई अन्य तरीके मिलेंगे, भले ही यह बग मौजूद न हो, उदाहरण के लिए आपके टाइप करते समय आपके कीस्ट्रोक्स को लॉग करना। इस बिंदु पर, आप बस आगामी अपडेट पर नज़र रख सकते हैं, और जब यह तैयार हो जाए तो इसे प्राप्त कर सकते हैं।
- यदि आप पूर्ण-डिस्क एन्क्रिप्शन का उपयोग नहीं कर रहे हैं, तो इसे सक्षम करने पर विचार करें। आपकी स्वैप फ़ाइल या हाइबरनेशन फ़ाइल (भारी लोड के दौरान या जब आपका कंप्यूटर "सो रहा है" के दौरान मेमोरी सामग्री को अस्थायी रूप से सहेजने के लिए उपयोग की जाने वाली ऑपरेटिंग सिस्टम डिस्क फ़ाइलें) से बचे हुए पासवर्ड निकालने के लिए, हमलावरों को आपकी हार्ड डिस्क तक सीधी पहुंच की आवश्यकता होगी। यदि आपके पास अन्य ऑपरेटिंग सिस्टम के लिए BitLocker या इसके समकक्ष सक्रिय है, तो वे आपकी स्वैप फ़ाइल, आपकी हाइबरनेशन फ़ाइल, या किसी अन्य व्यक्तिगत डेटा जैसे दस्तावेज़, स्प्रेडशीट, सहेजे गए ईमेल इत्यादि तक नहीं पहुंच पाएंगे।
- यदि आप एक प्रोग्रामर हैं, तो मेमोरी प्रबंधन संबंधी मुद्दों के बारे में स्वयं को सूचित रखें। यह मत मानिए कि सिर्फ इसलिए कि हर
free()
इसके संगत से मेल खाता हैmalloc()
कि आपका डेटा सुरक्षित और अच्छी तरह से प्रबंधित है। कभी-कभी, आपको गुप्त डेटा इधर-उधर पड़े रहने से बचने के लिए अतिरिक्त सावधानी बरतने की आवश्यकता हो सकती है, और ये सावधानियां ऑपरेटिंग सिस्टम से ऑपरेटिंग सिस्टम तक बहुत अधिक होती हैं। - यदि आप QA परीक्षक या कोड समीक्षक हैं, तो हमेशा "पर्दे के पीछे" सोचें। भले ही मेमोरी प्रबंधन कोड साफ-सुथरा और संतुलित दिखे, लेकिन पर्दे के पीछे क्या हो रहा है, इसके बारे में जागरूक रहें (क्योंकि मूल प्रोग्रामर को ऐसा करने की जानकारी नहीं होगी), और रनटाइम मॉनिटरिंग और मेमोरी जैसे कुछ परीक्षण-शैली के काम करने के लिए तैयार हो जाएं। यह सत्यापित करने के लिए डंपिंग करें कि सुरक्षित कोड वास्तव में वैसा ही व्यवहार कर रहा है जैसा उसे करना चाहिए।
लेख से कोड: UNL1.C
#शामिल करना #शामिल करना #शामिल करना void hexdump(unsigned char* buff, int len) {// 16-बाइट खंडों में बफर प्रिंट करें (int i = 0; i < len+16; i = i+16) { printf("%016X: ",buff +i); // (int j = 16; j < 0; j = j+16) { printf("%1X ",buff[i+j]); के लिए हेक्स मान के रूप में 02 बाइट्स दिखाएं; } // उन 16 बाइट्स को वर्णों के रूप में दोहराएं (int j = 0; j < 16; j = j+1) { unsigned ch = buff[i+j]; printf("%c",(ch>=32 && ch<=127)?ch:'.'); } प्रिंटफ('एन'); } प्रिंटफ('एन'); } int main(void) {// पासवर्ड स्टोर करने के लिए मेमोरी प्राप्त करें, और दिखाएं कि // बफर में क्या है जब यह आधिकारिक तौर पर "नया" हो... char* buff = Malloc(128); प्रिंटफ ("शुरुआत में 'नया' बफर डंप करना"); हेक्सडंप(बफ़,128); // यादृच्छिक बीज श्रैंड ((अहस्ताक्षरित) बफ) के रूप में छद्म यादृच्छिक बफर पते का उपयोग करें; // पासवर्ड को कुछ निश्चित, खोजने योग्य टेक्स्ट strcpy(buff,'unlilytext') से प्रारंभ करें; // 16 छद्म यादृच्छिक अक्षर जोड़ें, एक समय में एक (int i = 1; i <= 16; i++) के लिए {// A (65+0) से P (65+15) char ch = 65 + तक एक अक्षर चुनें (रैंड() और 15); // फिर बफ़ स्ट्रिंग को strncat(buff,&ch,1) के स्थान पर संशोधित करें; } // पूरा पासवर्ड अब मेमोरी में है, इसलिए // इसे एक स्ट्रिंग के रूप में प्रिंट करें, और संपूर्ण बफ़र दिखाएं... प्रिंटफ ("पूर्ण स्ट्रिंग थी: %sn", बफ़); हेक्सडंप(बफ़,128); // प्रक्रिया RAM को अभी डंप करने के लिए रोकें (कोशिश करें: 'procdump -ma') डालता है ("बफर मुक्त करने के लिए [ENTER] की प्रतीक्षा कर रहा है..."); getchar(); // औपचारिक रूप से मेमोरी को मुक्त करें और बफर दिखाएं // फिर से देखें कि क्या कुछ पीछे रह गया है... मुफ्त (बफ़); प्रिंटफ ("फ्री()एन के बाद डंपिंग बफर"); हेक्सडंप(बफ़,128); // मतभेदों का निरीक्षण करने के लिए रैम को फिर से डंप करने के लिए रोकें ("मुख्य() से बाहर निकलने के लिए [ENTER] की प्रतीक्षा की जा रही है..."); getchar(); वापसी 0; }
लेख से कोड: UNL2.C
#शामिल करना #शामिल करना #शामिल करना #शामिल करना void hexdump(unsigned char* buff, int len) {// 16-बाइट खंडों में बफर प्रिंट करें (int i = 0; i < len+16; i = i+16) { printf("%016X: ",buff +i); // (int j = 16; j < 0; j = j+16) { printf("%1X ",buff[i+j]); के लिए हेक्स मान के रूप में 02 बाइट्स दिखाएं; } // उन 16 बाइट्स को वर्णों के रूप में दोहराएं (int j = 0; j < 16; j = j+1) { unsigned ch = buff[i+j]; printf("%c",(ch>=32 && ch<=127)?ch:'.'); } प्रिंटफ('एन'); } प्रिंटफ('एन'); } int main(void) {// पासवर्ड स्टोर करने के लिए मेमोरी प्राप्त करें, और दिखाएं कि // बफर में क्या है जब यह आधिकारिक तौर पर "नया" हो... char* buff = VirtualAlloc(0,128,MEM_COMMIT,PAGE_READWRITE); प्रिंटफ ("शुरुआत में 'नया' बफर डंप करना"); हेक्सडंप(बफ़,128); // यादृच्छिक बीज श्रैंड ((अहस्ताक्षरित) बफ) के रूप में छद्म यादृच्छिक बफर पते का उपयोग करें; // पासवर्ड को कुछ निश्चित, खोजने योग्य टेक्स्ट strcpy(buff,'unlilytext') से प्रारंभ करें; // 16 छद्म यादृच्छिक अक्षर जोड़ें, एक समय में एक (int i = 1; i <= 16; i++) के लिए {// A (65+0) से P (65+15) char ch = 65 + तक एक अक्षर चुनें (रैंड() और 15); // फिर बफ़ स्ट्रिंग को strncat(buff,&ch,1) के स्थान पर संशोधित करें; } // पूरा पासवर्ड अब मेमोरी में है, इसलिए // इसे एक स्ट्रिंग के रूप में प्रिंट करें, और संपूर्ण बफ़र दिखाएं... प्रिंटफ ("पूर्ण स्ट्रिंग थी: %sn", बफ़); हेक्सडंप(बफ़,128); // प्रक्रिया RAM को अभी डंप करने के लिए रोकें (कोशिश करें: 'procdump -ma') डालता है ("बफर मुक्त करने के लिए [ENTER] की प्रतीक्षा कर रहा है..."); getchar(); // औपचारिक रूप से मेमोरी मुक्त करें और बफर दिखाएं // फिर से देखें कि क्या कुछ पीछे रह गया है... वर्चुअलफ्री (बफ, 0, एमईएम_रिलीज); प्रिंटफ ("फ्री()एन के बाद डंपिंग बफर"); हेक्सडंप(बफ़,128); // मतभेदों का निरीक्षण करने के लिए रैम को फिर से डंप करने के लिए रोकें ("मुख्य() से बाहर निकलने के लिए [ENTER] की प्रतीक्षा की जा रही है..."); getchar(); वापसी 0; }
लेख से कोड: S1.LUA
- कुछ निश्चित, खोजने योग्य पाठ से शुरू करें s = 'असंभावित पाठ' - i = 16 do s = s .. string.char(1,16+math.random() के लिए 'ए' से 'पी' तक 65 यादृच्छिक वर्ण जोड़ें 0,15)) एंड प्रिंट ('पूर्ण स्ट्रिंग है:', एस, 'एन') - प्रक्रिया रैम प्रिंट को डंप करने के लिए रोकें ('स्ट्रिंग को मुक्त करने से पहले [ENTER] की प्रतीक्षा कर रहा है...') io.read() - - स्ट्रिंग को पोंछें और अप्रयुक्त वैरिएबल को चिह्नित करें s = शून्य - अंतर प्रिंट देखने के लिए रैम को फिर से डंप करें ('बाहर निकलने से पहले [ENTER] की प्रतीक्षा कर रहा है...') io.read()
लेख से कोड: FINDIT.LUA
- डंप फ़ाइल में पढ़ें स्थानीय f = io.open(arg[1],'rb'):read('*a') - एक या अधिक यादृच्छिक ASCII वर्ण स्थानीय b,e के बाद मार्कर टेक्स्ट देखें ,m = 0,0, शून्य जबकि सत्य है - अगले मैच की तलाश करें और ऑफसेट याद रखें b,e,m = f:find('(unlytext[AZ]+)',e+1) - जब नहीं रह जाए तो बाहर निकलें मेल खाता है यदि बी नहीं है तो ब्रेक एंड - रिपोर्ट स्थिति और स्ट्रिंग मिली प्रिंट (स्ट्रिंग.फॉर्मेट ('% 08X: % s', b, m)) एंड
लेख से कोड: SEARCHKNOWN.LUA
io.write('डंप फ़ाइल में पढ़ना...') स्थानीय f = io.open(arg[1],'rb'):read('*a') io.write('DONE.n') io. लिखें('8-बिट ASCII के रूप में SIXTEENPASSCHARS की खोज कर रहे हैं...') स्थानीय p08 = f:find('SIXTEENPASCHARS') io.write(p08 और 'FOUND' या 'notमिला','.n') io.write ('UTF-16 के रूप में SIXTEENPASSCHARS की खोज...') स्थानीय p16 = f:find('Sx00Ix00Xx00Tx00Ex00Ex00Nx00Px00'.. 'Ax00Sx00Sx00Cx00Hx00Ax00Rx00Sx00') io.write(p16 और 'मिला' या 'नहीं मिला' ,'.n')
लेख से कोड: FINDBLOBS.LUA
- कमांड लाइन पर निर्दिष्ट डंप फ़ाइल में पढ़ें स्थानीय f = io.open(arg[1],'rb'):read('*a') - एक या अधिक पासवर्ड ब्लॉब देखें, उसके बाद कोई गैर-ब्लॉब -- ध्यान दें कि ब्लॉब वर्ण (●) विंडोज़ वाइडचार में एन्कोड होते हैं -- लिट्टे-एंडियन यूटीएफ-16 कोड के रूप में, हेक्स में सीएफ 25 के रूप में सामने आते हैं। स्थानीय बी,ई,एम = 0,0,शून्य जबकि सच है - हम एक या अधिक ब्लॉब्स चाहते हैं, उसके बाद कोई गैर-ब्लॉब। - हम एक स्पष्ट CF25 की तलाश करके कोड को सरल बनाते हैं - इसके बाद कोई भी स्ट्रिंग जिसमें केवल CF या 25 है, - इसलिए हम CF25CFCF या CF2525CF के साथ-साथ CF25CF25 भी पाएंगे। -- यदि कोई "झूठी सकारात्मकता" है तो हम उसे बाद में फ़िल्टर कर देंगे। -- हमें x25 के स्थान पर '%%' लिखने की आवश्यकता है क्योंकि x25 -- वर्ण (प्रतिशत चिह्न) लुआ में एक विशेष खोज वर्ण है! b,e,m = f:find('(xCF%%[xCF%%]*)',e+1) - बाहर निकलें जब कोई और मेल नहीं खाता यदि b नहीं तो ब्रेक एंड - CMD.EXE प्रिंट नहीं कर सकता बूँदें, इसलिए हम उन्हें सितारों में परिवर्तित करते हैं। print(string.format('%08X: %s',b,m:gsub('xCF%%','*'))) समाप्त
लेख से कोड: SEARCHKP.LUA
- कमांड लाइन पर निर्दिष्ट डंप फ़ाइल में पढ़ें स्थानीय f = io.open(arg[1],'rb'):read('*a') स्थानीय b,e,m,p = 0,0,nil,nil जबकि सच है - अब, हम एक या अधिक ब्लॉब्स (CF25) चाहते हैं जिसके बाद कोड हो - A..Z के लिए ACSCII को UTF-0 में बदलने के लिए 16 बाइट के बाद b,e,m = f:find(' (xCF%%[xCF%%]*[AZ])x00',e+1) - जब कोई और मेल नहीं खाता तो बाहर निकलें यदि b नहीं तो ब्रेक एंड - CMD.EXE ब्लॉब्स प्रिंट नहीं कर सकता, इसलिए हम उन्हें इसमें परिवर्तित करते हैं सितारे। - स्थान बचाने के लिए हम क्रमिक मिलानों को दबा देते हैं यदि m ~= p तो print(string.format('%08X: %s',b,m:gsub('xCF%%','*'))) p = m अंत अंत
- एसईओ संचालित सामग्री और पीआर वितरण। आज ही प्रवर्धित हो जाओ।
- प्लेटोआईस्ट्रीम। Web3 डेटा इंटेलिजेंस। ज्ञान प्रवर्धित। यहां पहुंचें।
- मिंटिंग द फ्यूचर डब्ल्यू एड्रिएन एशले। यहां पहुंचें।
- PREIPO® के साथ PRE-IPO कंपनियों में शेयर खरीदें और बेचें। यहां पहुंचें।
- स्रोत: https://nakedsecurity.sophos.com/2023/05/31/serious-security-that-keepass-master-password-crack-and-what-we-can-learn-from-it/
- :हैस
- :है
- :नहीं
- :कहाँ
- ][पी
- $यूपी
- 1
- 10
- 12
- 15% तक
- 20
- 200
- 2023
- 24
- 250
- 27
- 31
- 3d
- 49
- 50
- 67
- 70
- 72
- 77
- 8
- 9
- a
- योग्य
- About
- ऊपर
- पूर्ण
- AC
- पहुँच
- लेखा
- अधिग्रहण
- प्राप्ति
- सक्रिय
- वास्तविक
- वास्तव में
- जोड़ा
- अतिरिक्त
- पता
- पतों
- जोड़ता है
- बाद
- बाद में
- फिर
- सब
- आवंटित
- आबंटित करता है
- आवंटन
- आवंटन
- अनुमति देना
- अकेला
- साथ में
- पहले ही
- भी
- बदल
- हालांकि
- हमेशा
- an
- और
- एंड्रयू
- जवाब
- कोई
- कुछ भी
- कुछ भी महत्वपूर्ण
- दिखाई देते हैं
- छपी
- दृष्टिकोण
- अनुमोदित
- हैं
- चारों ओर
- लेख
- लेख
- AS
- At
- लेखक
- स्वत:
- स्वचालित
- स्वतः
- उपलब्ध
- से बचने
- बचा
- जागरूक
- दूर
- वापस
- पृष्ठभूमि
- पृष्ठभूमि छवि
- BE
- क्योंकि
- हो जाता है
- किया गया
- से पहले
- शुरू
- पीछे
- परदे के पीछे
- नीचे
- बेहतर
- बिट
- खंड
- ब्लॉक
- सीमा
- के छात्रों
- तल
- ब्रांड
- ब्रांड नई
- टूटना
- संक्षिप्त
- लाना
- बफर
- बफर अतिप्रवाह
- दोष
- कीड़े
- निर्माण
- लेकिन
- by
- सी + +
- कॉल
- बुला
- कर सकते हैं
- पा सकते हैं
- कौन
- मामला
- पकड़ा
- CD
- केंद्र
- निश्चित रूप से
- चेन
- संयोग
- बदल
- चरित्र
- अक्षर
- जाँच
- जाँचता
- चीनी
- चुनें
- स्पष्ट
- स्पष्ट रूप से
- समापन
- कोड
- रंग
- COM
- आता है
- अ रहे है
- टिप्पणी
- टिप्पणियाँ
- सामान्य
- पूरा
- जटिल
- कंप्यूटर
- विचार करना
- काफी
- माना
- मिलकर
- निर्माण
- सामग्री
- अंतर्वस्तु
- लगातार
- जारी
- नियंत्रण
- बदलना
- Copyright
- इसी
- सका
- आवरण
- दरार
- बनाना
- बनाया
- निर्माता
- महत्वपूर्ण
- साइबर सुरक्षा
- खतरा
- खतरनाक
- तिथि
- गोपनीय जानकारी का चोरी हो जाना
- दिन
- सौदा
- का फैसला किया
- समर्पित
- वर्णित
- डीआईडी
- मतभेद
- विभिन्न
- कठिनाई
- डीआईजी
- डिजिटल
- प्रत्यक्ष
- सीधी पहुँच
- सीधे
- डिस्प्ले
- प्रदर्शित
- है
- do
- दस्तावेजों
- कर देता है
- नहीं करता है
- कर
- किया
- dont
- नीचे
- ड्राइव
- दो
- फेंकना
- दौरान
- e
- से प्रत्येक
- पूर्व
- आसानी
- पारिस्थितिकी तंत्र
- भी
- अन्य
- ईमेल
- समर्थकारी
- को प्रोत्साहित करने
- एन्क्रिप्शन
- समाप्त
- समाप्त होता है
- पर्याप्त
- सुनिश्चित
- सुनिश्चित
- दर्ज
- में प्रवेश
- संपूर्ण
- प्रविष्टि
- वातावरण
- बराबर
- त्रुटि
- अनिवार्य
- अनुमानित
- आदि
- ईथर (ईटीएच)
- और भी
- अंत में
- बढ़ती
- प्रत्येक
- सब कुछ
- ठीक ठीक
- उदाहरण
- सिवाय
- उत्तेजना
- निष्पादन
- मौजूद
- मौजूदा
- निकास
- बाहर निकल रहा है
- उम्मीद
- समझाना
- शोषण करना
- उजागर
- विस्तार
- अतिरिक्त
- उद्धरण
- तथ्य
- असत्य
- आकर्षक
- विशेषताएं
- प्रतिक्रिया
- कम
- मार पिटाई
- पट्टिका
- फ़ाइलें
- फ़िल्टर
- अंतिम
- अंत में
- खोज
- खोज
- पाता
- अंत
- प्रथम
- तय
- फोकस
- पीछा किया
- निम्नलिखित
- के लिए
- प्रपत्र
- औपचारिक रूप से
- प्रारूप
- आगामी
- पाया
- चार
- मुक्त
- से
- पूर्ण
- पूरी तरह से
- समारोह
- कार्यों
- आगे
- भविष्य
- उत्पन्न करता है
- पीढ़ी
- मिल
- मिल रहा
- GitHub
- देना
- दी
- देता है
- देते
- Go
- चला जाता है
- जा
- अच्छा
- सरकार
- पकड़ लेना
- महान
- गारंटी
- था
- हैंडल
- हुआ
- हो रहा है
- हो जाता
- कठिन
- है
- होने
- सिर दर्द
- mmmmm
- ऊंचाई
- यहाँ उत्पन्न करें
- HEX
- उच्च स्तर
- उच्चतर
- हिट्स
- पकड़
- छेद
- आशा
- घंटे
- मंडराना
- कैसे
- How To
- HTTPS
- शिकार
- i
- पहचानकर्ता
- if
- तुरंत
- महत्वपूर्ण
- in
- शामिल
- सहित
- करें-
- सूचित
- बजाय
- रुचि
- मध्यवर्ती
- इंटरनेट
- में
- मुद्दों
- IT
- आईटी इस
- खुद
- शब्दजाल
- जून
- केवल
- सिर्फ एक
- रखना
- कुंजी
- जानना
- जानने वाला
- कोरियाई
- भाषा
- भाषाऐं
- लैपटॉप
- पिछली बार
- बाद में
- नेतृत्व
- बिक्रीसूत्र
- रिसाव
- लीक
- जानें
- सीख रहा हूँ
- कम से कम
- छोड़ने
- बाएं
- लंबाई
- पत्र
- पुस्तकालय
- जीवन
- पसंद
- संभावित
- सीमित
- लाइन
- पंक्तियां
- सूची
- सूचीबद्ध
- ll
- भार
- स्थानीय
- स्थान
- लॉगिंग
- लंबा
- लंबे समय तक
- लंबे समय तक
- देखिए
- हमशक्ल
- देखा
- देख
- लग रहा है
- लॉट
- भाग्य
- का कहना है
- बनाना
- मैलवेयर
- प्रबंधन
- कामयाब
- प्रबंध
- प्रबंधक
- प्रबंधन करता है
- जोड़ - तोड़
- बहुत
- हाशिया
- निशान
- मार्कर
- मास्टर
- मैच
- मिलान
- अधिकतम-चौड़ाई
- मई..
- साधन
- याद
- उल्लेख किया
- माइक्रोसॉफ्ट
- हो सकता है
- मिनट
- मामूली
- संशोधित
- संशोधित
- पल
- निगरानी
- अधिक
- अधिकांश
- बहुत
- विभिन्न
- स्वच्छ
- आवश्यकता
- जरूरत
- जाल
- कभी नहीँ
- फिर भी
- नया
- समाचार
- अगला
- अच्छा
- नहीं
- साधारण
- कुछ नहीं
- सूचना..
- अभी
- संख्या
- संख्या
- वस्तु
- स्पष्ट
- of
- बंद
- सरकारी
- आधिकारिक तौर पर
- ओफ़्सेट
- पुराना
- on
- एक बार
- ONE
- केवल
- खुला स्रोत
- परिचालन
- ऑपरेटिंग सिस्टम
- ऑपरेटिंग सिस्टम
- ऑपरेटर
- विकल्प
- or
- आदेश
- मूल
- अन्य
- अन्य
- अन्यथा
- हमारी
- आप
- आउट
- उत्पादन
- के ऊपर
- कुल
- अपना
- पृष्ठ
- आतंक
- भाग
- पासवर्ड
- पासवर्ड मैनेजर
- पासवर्ड
- पथ
- पैटर्न
- पॉल
- विराम
- वेतन
- प्रतिशत
- शायद
- अवधि
- हमेशा
- स्टाफ़
- व्यक्तिगत डेटा
- भौतिक
- चित्र
- टुकड़े
- जगह
- प्लेसहोल्डर
- प्लेग
- प्लेटो
- प्लेटो डेटा इंटेलिजेंस
- प्लेटोडाटा
- बहुत सारे
- बिन्दु
- अंक
- लोकप्रिय
- स्थिति
- संभव
- पोस्ट
- संभावित
- ठीक - ठीक
- वर्तमान
- सुंदर
- को रोकने के
- पिछला
- मूल्य
- छाप
- प्रिंट
- शायद
- समस्याओं
- प्रक्रिया
- कार्यक्रम
- प्रोग्रामर
- प्रोग्रामर्स
- प्रोग्रामिंग
- प्रोग्राम्स
- स्पष्ट
- रखना
- अजगर
- क्यू एंड ए
- प्रश्न
- उठाता
- रैम
- बिना सोचे समझे
- रेंज
- बल्कि
- कच्चा
- कच्चा डेटा
- RE
- पहुँचे
- पढ़ना
- पढ़ना
- तैयार
- वास्तविक
- असली जीवन
- वास्तविक समय
- वास्तव में
- पहचानना
- की वसूली
- ठीक हो
- सम्बंधित
- शेष
- याद
- दूरस्थ
- हटाना
- दोहराना
- दोहराया गया
- बार बार
- रिपोर्ट
- प्रतिनिधित्व
- सम्मान
- क्रमश
- बाकी
- परिणाम
- वापसी
- लौटने
- प्रकट
- छुटकारा
- सही
- जोखिम
- जोखिम
- कक्ष
- रन
- दौड़ना
- रनटाइम निगरानी
- s
- सुरक्षित
- सुरक्षित
- वही
- संतुष्ट
- सहेजें
- कहावत
- स्कैन
- बिखरे
- दृश्यों
- Search
- खोज
- दूसरा
- सेकंड
- गुप्त
- अनुभाग
- सुरक्षित
- सुरक्षा
- देखना
- बीज
- देखकर
- लगता है
- देखा
- देखता है
- कई
- गंभीर
- सेट
- की स्थापना
- कम
- कुछ ही समय
- चाहिए
- दिखाना
- दिखाया
- हस्ताक्षर
- लक्षण
- समान
- उसी प्रकार
- सरल
- सरलीकृत
- को आसान बनाने में
- केवल
- एक
- आकार
- नींद
- छोटा
- डरपोक
- स्नूपिंग
- So
- सॉफ्टवेयर
- ठोस
- कुछ
- कुछ
- जल्दी
- स्रोत
- स्रोत कोड
- अंतरिक्ष
- विशेष
- विशेष रूप से
- विनिर्दिष्ट
- गति
- सितारे
- प्रारंभ
- शुरू
- शुरुआत में
- शुरू होता है
- स्टार्टअप
- फिर भी
- चुरा लिया
- रुकें
- रोक
- की दुकान
- संग्रहित
- कहानी
- तार
- मजबूत
- अध्ययन
- सफलतापूर्वक
- ऐसा
- पर्याप्त
- माना
- आश्चर्य
- आश्चर्य चकित
- आश्चर्य की बात
- जीवित रहने के
- एसवीजी
- विनिमय
- प्रणाली
- सिस्टम
- लेना
- लिया
- लेता है
- ले जा
- में बात कर
- तकनीकी रूप से
- तकनीक
- अस्थायी
- परीक्षण
- परीक्षण
- से
- कि
- RSI
- स्रोत
- लेकिन हाल ही
- उन
- अपने
- फिर
- सिद्धांत
- वहाँ।
- इसलिये
- वे
- बात
- सोचना
- इसका
- उन
- हालांकि?
- विचार
- पहर
- शीर्षक
- सेवा मेरे
- एक साथ
- ले गया
- साधन
- ऊपर का
- ट्रैक
- ट्रैकिंग
- संक्रमण
- पारदर्शी
- <strong>उद्देश्य</strong>
- कोशिश
- बदल गया
- दो
- टाइप
- आम तौर पर
- समझना
- यूनिकोड
- जब तक
- अप्रयुक्त
- अवांछित
- अपडेट
- अद्यतन
- यूआरएल
- us
- अमेरिकी सरकार
- प्रयोग
- USB के
- उपयोग
- का उपयोग के बाद नि: शुल्क
- प्रयुक्त
- उपयोगकर्ता
- का उपयोग करता है
- का उपयोग
- उपयोगिता
- मूल्य
- मान
- विविधता
- सत्यापित
- संस्करण
- बहुत
- के माध्यम से
- भेद्यता
- W
- प्रतीक्षा
- इंतज़ार कर रही
- करना चाहते हैं
- जरूरत है
- था
- घड़ी
- मार्ग..
- तरीके
- we
- सप्ताह
- कुंआ
- थे
- क्या
- कब
- या
- कौन कौन से
- जब
- कौन
- जो कोई
- पूरा का पूरा
- क्यों
- मर्जी
- जीतना
- खिड़कियां
- पोंछ
- साथ में
- बिना
- सोच
- शब्द
- काम
- काम किया
- काम कर रहे
- कार्य
- चिंता
- होगा
- देना होगा
- लिखना
- लिख रहे हैं
- लिखा हुआ
- अभी तक
- इसलिए आप
- आपका
- स्वयं
- जेफिरनेट
- शून्य