Kaspersky लैब से क्रैकमे को हल करना

एक दिन ठीक है, टेलीग्राम के विभिन्न चैनलों ने LK से क्रैकरमेकर का लिंक फेंकना शुरू कर दिया। जो लोग सफलतापूर्वक कार्य पूरा कर लेते हैं उन्हें साक्षात्कार के लिए आमंत्रित किया जाएगा! । इस तरह के एक जोरदार बयान के बाद, मैं सोचता था कि रिवर्स कितना मुश्किल होगा। मैंने इस कार्य को कैसे हल किया, इसे कट (बहुत सारी तस्वीरों) के तहत पढ़ा जा सकता है।

घर आने के बाद, मैंने फिर से असाइनमेंट को ध्यान से पढ़ा, संग्रह डाउनलोड किया और जो अंदर था उसे देखना शुरू किया। और इसके अंदर था:



हम x64dbg को शुरू करते हैं, अनपैक करने के बाद डंप करते हैं, देखो वास्तव में अंदर क्या है:





हम कमांड लाइन के तर्कों से फ़ाइल का नाम लेते हैं -> खुला, पढ़ें -> पहले चरण को एन्क्रिप्ट करें -> दूसरे चरण को एन्क्रिप्ट करें -> एक नई फ़ाइल पर लिखें।

यह सरल है, यह एन्क्रिप्शन को देखने का समय है।

स्टेज 1 से शुरू करते हैं


पते पर 0x4033f4 एक फ़ंक्शन है जिसे मैंने crypt_64bit_up कहा है (बाद में आप समझेंगे कि क्यों), इसे स्टेज 1 के अंदर कहीं लूप से बुलाया जाता है



और एक बिट कुटिल विघटन परिणाम



पहले तो मैंने अजगर में एक ही एल्गोरिथ्म को फिर से लिखने की कोशिश की, इसे कई घंटों तक मार दिया और यह कुछ इस तरह से निकला (जो get_dword और byteswap नामों से स्पष्ट होना चाहिए)

def _add(x1, x2): return (x1+x2) & 0xFFFFFFFF def get_buf_val(t, buffer): t_0 = t & 0xFF t_1 = (t >> 8) & 0xFF t_2 = (t >> 16) & 0xFF t_3 = (t >> 24) & 0xFF res = _add(get_dword(buffer, t_0 + 0x312), (get_dword(buffer, t_1 + 0x212) ^ _add(get_dword(buffer, t_2+0x112), get_dword(buffer, t_3+0x12)))) # print('Got buf val: 0x%X' % res) return res def crypt_64bit_up(initials, buffer): steps = [] steps.append(get_dword(buffer, 0) ^ byteswap(initials[0])) # = z steps.append(get_buf_val(steps[-1], buffer) ^ byteswap(initials[1]) ^ get_dword(buffer, 1)) for i in range(2, 17): steps.append(get_buf_val(steps[-1], buffer) ^ get_dword(buffer, i) ^ steps[i-2]) res_0 = steps[15] ^ get_dword(buffer, 17) res_1 = steps[16] print('Res[0]=0x%X, res[1]=0x%X' % (res_0, res_1)) 

लेकिन तब मैंने स्थिरांक 0x12, 0x112, 0x212, 0x312 (बिना हेक्स 18, 274, 536 ... बहुत असामान्य के समान नहीं) पर ध्यान देने का फैसला किया। हम उन्हें गूगल करने का प्रयास करते हैं और एन्क्रिप्शन और डिक्रिप्शन फ़ंक्शन के कार्यान्वयन के साथ एक संपूर्ण रिपॉजिटरी (संकेत: एनटीआर) पाते हैं, यह सौभाग्य है। हम मूल प्रोग्राम में यादृच्छिक सामग्री के साथ एक परीक्षण फ़ाइल को एन्क्रिप्ट करने की कोशिश करते हैं, इसे डंप करते हैं और एक छोटी स्क्रिप्ट के साथ उसी फ़ाइल को एन्क्रिप्ट करते हैं, सब कुछ काम करना चाहिए और परिणाम समान होना चाहिए। उसके बाद, हम इसे डिक्रिप्ट करने की कोशिश करते हैं (मैंने विवरण में नहीं जाने का फैसला किया और स्रोत से डिक्रिप्शन फ़ंक्शन को सिर्फ कॉपी-पेस्ट किया)

 def crypt_64bit_down(initials, keybuf): x = initials[0] y = initials[1] for i in range(0x11, 1, -1): z = get_dword(keybuf, i) ^ x x = get_buf_val(z, keybuf) x = y ^ x y = z res_0 = x ^ get_dword(keybuf, 0x01) # x - step[i], y - step[i-1] res_1 = y ^ get_dword(keybuf, 0x0) return (res_1, res_0) def stage1_unpack(packed_data, state): res = bytearray() for i in range(0, len(packed_data), 8): ciphered = struct.unpack('>II', packed_data[i:i+8]) res += struct.pack('>II', *crypt_64bit_down(ciphered, state)) return res 

महत्वपूर्ण नोट: रिपॉजिटरी में कुंजी प्रोग्राम की कुंजी (जो काफी तार्किक है) से अलग है। इसलिए, कुंजी को आरंभीकृत करने के बाद, मैंने इसे बस एक फ़ाइल में डंप किया, यह बफर / कीबुफ है

हम दूसरे भाग को पास करते हैं


यहां सब कुछ बहुत सरल है: पहले, रेंज में 0x55 बाइट्स के आकार (33, 118) (प्रिंट करने योग्य चार्ट) के साथ एक अद्वितीय चर का एक सरणी बनाया जाता है, फिर 32-बिट मूल्य पहले बनाए गए सरणी से 5 प्रिंट करने योग्य वर्णों में पैक किया जाता है।





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

 def stage2_unpack(packed_data, state): # checked! res = bytearray() for j in range(0, len(packed_data), 5): mapped = [state.index(packed_data[j+i]) for i in range(5)] res += struct.pack('>I', sum([mapped[4-i]*0x55**i for i in range(5)])) return res 

हम ऐसा कुछ करते हैं:

 f = open('stage1.state.bin', 'rb') stage1 = f.read() f.close() f = open('stage2.state.bin', 'rb') stage2 = f.read() f.close() f = open('rprotected.dat', 'rb') packed = f.read() f.close() unpacked_from_2 = stage2_unpack(packed, stage2) f = open('unpacked_from_2', 'wb') f.write(unpacked_from_2) f.close() unpacked_from_1 = stage1_unpack(unpacked_from_2, stage1) f = open('unpacked_from_1', 'wb') f.write(unpacked_from_1) f.close() 

और हमें परिणाम मिलता है

Source: https://habr.com/ru/post/hi431690/


All Articles