سؤال

لماذا يكون من السهل جدًا فك ترجمة كود .NET IL إلى كود مصدر، مقارنة بفك ترجمة ثنائيات x86 الأصلية؟(ينتج برنامج Reflector كود مصدر جيد جدًا في معظم الأوقات، بينما يكاد يكون من المستحيل فك ترجمة مخرجات مترجم C++.)

هل لأن IL يحتوي على الكثير من البيانات التعريفية؟أم أن IL هو تجريد أعلى من تعليمات x86؟لقد أجريت بعض الأبحاث ووجدت المقالتين المفيدتين التاليتين، لكن لم يجيب أي منهما على سؤالي.

هل كانت مفيدة؟

المحلول

أعتقد أن لديك الأجزاء الأكثر أهمية بالفعل.

  • كما قلت، هناك المزيد من البيانات الوصفية المتاحة.لا أعرف تفاصيل ما ينبعث من مترجم C أو C++، ولكن أظن بعيد يتم تضمين المزيد من الأسماء والمعلومات المماثلة في IL.ما عليك سوى إلقاء نظرة على ما يعرفه برنامج إلغاء الترجمة حول ما يوجد في إطار مكدس معين، على سبيل المثال - بقدر ما يتعلق الأمر بـ x86، فأنت تعرف فقط كيفية عمل المكدس مستخدم ;في IL أنت تعرف ما هي محتويات المكدس يمثل (أو على الأقل النوع - وليس المعنى الدلالي!)
  • مرة أخرى، كما ذكرت سابقًا، يعد IL مستوى تجريدًا أعلى من x86.ليس لدى x86 أي فكرة عن الطريقة أو استدعاء الوظيفة أو الحدث أو الخاصية وما إلى ذلك.IL لديه كل هذه المعلومات لا تزال بداخله.
  • عادةً ما يتم تحسين برامج التحويل البرمجي C وC++ بشكل أكبر بكثير من (على سبيل المثال) برنامج التحويل البرمجي C#.وذلك لأن مترجم C# يفترض أنه لا يزال من الممكن إجراء معظم عمليات التحسين لاحقًا - بواسطة JIT.في بعض النواحي يكون ذلك منطقيًا بالنسبة لمترجم C# لا لمحاولة القيام بالكثير من التحسين، نظرًا لوجود أجزاء مختلفة من المعلومات المتوفرة لـ JIT ولكن ليس لمترجم C#.من الصعب تفكيك التعليمات البرمجية المُحسّنة، لأنها أبعد ما تكون عن كونها تمثيلاً طبيعيًا لكود المصدر الأصلي.
  • تم تصميم IL ليتم تجميعه بواسطة JIT؛تم تصميم الإصدار x86 ليتم تنفيذه محليًا (من خلال الكود الصغير).المعلومات التي يحتاجها برنامج التحويل البرمجي JIT مشابهة لتلك التي قد يحتاجها برنامج فك التحويل البرمجي، لذا فإن برنامج فك التحويل البرمجي لديه وقت أسهل مع IL.في بعض النواحي، يعد هذا مجرد إعادة صياغة للنقطة الثانية.

نصائح أخرى

هناك عدد من الأشياء التي تجعل الهندسة العكسية سهلة إلى حد ما.

  • اكتب المعلومات.هذا هائل.في مجمع x86، عليك استنتاج أنواع المتغيرات بناءً على كيفية استخدامها.

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

  • أسماء.معرفة أسماء الأشياء يمكن أن تكون مفيدة.

هذه الأشياء مجتمعة تعني أن لديك الكثير من البيانات حول الملف القابل للتنفيذ.يعمل Il بشكل أساسي على مستوى أقرب بكثير إلى المصدر من مترجم الكود الأصلي.كلما كان المستوى الأعلى الذي يعمل فيه الرمز الثانوي، كانت الهندسة العكسية أسهل بشكل عام.

C# و IL يرسمان تقريبًا واحدًا لواحد.(وهذا أقل من ذلك مع بعض ميزات C# 3.0 الأحدث.) إن قرب التعيين (وعدم وجود مُحسِّن في مترجم C#) يجعل الأمور "قابلة للعكس".

توسيع إجابة براين الصحيحة

إذا كنت تعتقد أن كل IL يمكن فك ترجمتها بسهولة، أقترح كتابة برنامج F# غير تافه ومحاولة فك هذا الرمز.يقوم F# بالكثير من تحويلات التعليمات البرمجية وبالتالي لديه تعيين ضعيف للغاية من IL المنبعث الفعلي وقاعدة التعليمات البرمجية الأصلية.IMHO، من الصعب جدًا النظر إلى كود F# الذي تم فك ترجمته واستعادة البرنامج الأصلي مقارنةً بـ C# أو VB.Net.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top