في أحد الأيام الجميلة ، بدأت قنوات مختلفة في
البرق تلقي
ارتباطًا بمصنّع الكراك من LK ،
وستتم دعوة الذين أتموا المهمة بنجاح لإجراء مقابلة معهم! . بعد مثل هذا البيان الصريح ، تساءلت عن مدى صعوبة العكس. كيف يمكنني حل هذه المهمة يمكن قراءتها تحت خفض (الكثير من الصور).
بعد وصولي إلى المنزل ، قمت مجددًا بإعادة قراءة المهمة ، وقمت بتنزيل الأرشيف وبدأت في النظر إلى ما بداخلها. وداخله كان:

نبدأ x64dbg ، تفريغ بعد التفريغ ، انظر ما هو في الواقع داخل:


نأخذ اسم الملف من وسيطات سطر الأوامر -> فتح ، قراءة -> تشفير الخطوة الأولى -> تشفير الخطوة الثانية -> الكتابة إلى ملف جديد.
إنه بسيط ، لقد حان الوقت للنظر في التشفير.
لنبدأ مع stage1
في العنوان 0x4033f4 هناك وظيفة أسميتها crypt_64bit_up (فيما بعد ستفهم السبب) ، يطلق عليها من حلقة في مكان ما داخل stage1

وقليلا نتيجة التعقيم ملتوية

في البداية حاولت إعادة كتابة نفس الخوارزمية في بيثون ، وقتلتها لعدة ساعات واتضح شيئًا كهذا (والذي يجب أن يكون 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))))
ولكن بعد ذلك قررت الانتباه إلى الثوابت 0x12 ، 0x112 ، 0x212 ، 0x312 (بدون ست عشري 18 ، 274 ، 536 ... ليس مشابهًا جدًا لشيء غير عادي). نحن نحاول google لهم والعثور على مستودع كامل (تلميح: NTR) مع تنفيذ وظائف
التشفير وفك التشفير ، وهذا هو التوفيق. نحاول تشفير ملف اختبار بمحتويات عشوائية في البرنامج الأصلي ، وإفراغه وتشفير الملف نفسه بنص صغير ، يجب أن يعمل كل شيء ، ويجب أن تكون النتائج كما هي. بعد ذلك ، نحاول فك تشفيره (قررت عدم الخوض في التفاصيل ونسخ وظيفة فك التشفير من المصدر فقط)
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)
ملاحظة مهمة: يختلف المفتاح في المستودع عن المفتاح في البرنامج (وهو منطقي تمامًا). لذلك ، بعد تهيئة المفتاح ، أنا فقط ألقيت به في ملف ، وهذا هو المخزن المؤقت / keybuf
نمر إلى الجزء الثاني
كل شيء أبسط من ذلك بكثير: أولاً ، يتم إنشاء مجموعة من الأحرف الفريدة بحجم 0x55 بايت في النطاق (33 ، 118) (الأحرف القابلة للطباعة) ، ثم يتم تجميع القيمة 32 بت في 5 أحرف قابلة للطباعة من الصفيف التي تم إنشاؤها مسبقًا.


نظرًا لعدم وجود عشوائي عند إنشاء المصفوفة المذكورة أعلاه ، في كل مرة يبدأ فيها البرنامج ، ستكون هذه المصفوفة هي نفسها ، ونفريغها بعد التهيئة ويمكننا فك حزمة stage_2 من خلال وظيفة بسيطة
def stage2_unpack(packed_data, state):
نحن نفعل شيئا مثل هذا:
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()
ونحصل على النتيجة
