بسم الله الرحمن الرحيم,

 

في المقالتين السابقتين, تعرفنا على أنواع الهندسة العكسية, الادوات التي نستعملها في كل نوع, و بعض المفاهيم التقنية التي أردت أن أتأكد من وجودها عند القارئ.

قبل أن ابدأ -و كما ذكرنا في المقال السابق- بأذن الله سيكون هنالك مقالتين عن الهندسة العكسية البرمجية,و مقالتين عن الهندسة العكسية الالكترونية. هذا المقال بدوره مقسم الى جزئين, في هذا الجزء سنتحدث فيه بأذن الله عن الهندسة العكسية لبرنامج بسيط جدا من برمجتنا ليكون بمثابة مقدمة تعريفية للأدوات المستخدمة و طريقة التفكير و بعض الشروحات التقنية البسيطة, و الجزء الثاني سنتحدث عن برنامج تجاري و سنقوم بالتعديل عليه بعض الشئ.

 

البرنامج الذي سنقوم بالشرح عليه بأذن الله اليوم هو برنامج بسيط جدا مكتوب بلغة السي C, تستطيع أن تطلع عليه من خلال جزء المراجع في نهاية المقال.

 

البرنامج بسيط جدا, كل ما يقوم به هو أخذ كلمة من المستخدم, و مقارنتها بكلمة أخرى, و اذا كانت الكلمتين متطابقتين يكتب البرنامج أن كلمة السر صحيحة, غير ذلك, يكتب أن كلمة السر خاطئة.

في البداية, نقوم بترجمة Compile هذا البرنامج باستخدام أي مترجم, شخصيا أفضل استخدام المترجم المجاني البسيط Dev-c++ Bloodshed على ويندوز Windows, و من ثم نأخذ الملف التنفيذي الخارج من عملية الترجمة و هذا ما سنقوم بعمل الهندسة العكسية عليه.

 

في البداية -و كما ذكرنا سابقا- ,نقوم بتحميل البرنامج التنفيذي الخاص بنا بداخل برنامج disassembler الذي يقوم بتحويل اللغة الثنائية الى لغة المجمع. سأستخدم هنا البرنامج المفضل لدي Immunity Disassembler and Debugger, هذا البرنامج يقوم بتحويل الملف التنفيذي للغة المجمع و في نفس الوقت نستطيع بدأ تنفيذ البرنامج المراد دراسته و تتبع حالته في المعالج, كما أننا نستطيع برمجة بعض السكريبتات Scripts المساعدة له باستخدام Python و هي احدى لغاتي المفضلة.

و هذه صورة البرنامج بعد أن قمنا بتحميله داخل برنامج Immunity.

لعلك لاحظت تنوع الالوان و جمال الواجهة و بساطتها في الصورة السابقة, ولهذا حقيقة أفضل استخدام Immunity عن جميع البرامج الاخرى.

لنقم الآن بشرح الشاشة التى أمامنا, فكل جزء منها يقوم بتتبع إما جزء في المعالج او جزء في الذاكرة.الواجهة تنقسم لأربع أقسام:

– أول قسم (أعلى اليمين): يقوم بتتبع حالة المعالج تفصيليا بعد تنفيذ كل تعليمة من كود المجمع, فنستطيع رؤية السجلات العامة امامنا General Purpose Registers, سواء كانت سجلات البيانات ( AX, BX, CX,…) او سجلات الارقام العشرية FLAGS, بما في ذلك سجلاتها المكدسة (  ST0 -> ST7 ), و سجلات مقاطع الذاكرة (ES, CS, SS,…), و أخيرا سلسلة السجلات المدمجة حديثا بمعالج Intel و هي سجلات MMX و التى تقوم بتسريع نقل البيانات بين السجلات الاخرى, كما ان لها استخدامات في حساب المعادلات الرياضية و المصفوفات (MM0 -> MM7).

– القسم الثاني (أعلي اليسار): يقوم بتتبع مقطع الكود في الذاكرة العشوائية Code Segment in RAM, هذا هو الكود التنفيذي للبرنامج بعد ما تم تحويله للغة المجمع. الجزء الصغير الذي باسفل هذا القسم يوضح محتوى السجلات المستخدمة في التعليمة instruction الحالية, فمثلا لو كانت التعليمة الحالية:
MOV EAX,EBX

ستراه يسرد محتوى السجل EAX و السجل EBX.

– القسم الثالث (أسفل اليمين): يقوم بتتبع محتوى الذاكرة المكدسة الخاصة بالبرنامج.

– القسم الرابع: يقوم بتتبع جزء في الذاكرة العشوائية الخاصة بالمتغيرات و البيانات. نستطيع أن نرى انه مقسم لثلاثة أقسام. القسم الاول (اقصى اليسار) يوضح العنوان الذي نقوم بقرائته حاليا. القسم الثاني (الاوسط) يوضح محتوى العنوان (محول للنظام السادس عشري hexadecimal). و القسم الاخير يوضح محتوى العنوان و لكن بنظام التحويل العالمي ASCII character representation.

– شريط الأدوات (أعلى شاشة البرنامج): يحتوي على كثير من الأدوات التي تسهل علينا تتبع أو البحث في محتويات البرنامج المراد دراسته في الذاكرة, و سنعرف باختصار ماذا تعني كل أداة من اليسار لليمين:

-فتح برنامج جديد لدراسته.

-فتح مترجم Python لتنفيذ سكربتات Python مساعِدة.

-سرد كل سكريبتات Python المساعِدة.

-تحويل البرنامج الي اشكال بيانية يسهل قرائتها (بدلا من تعليمات متتالية).

-اعادة فتح نفس البرنامج المراد دراسته من جديد.

-اغلاق البرنامج المراد دراسته من داخل برنامج Immunity.

-بدأ تنفيذ البرنامج المراد دراسته من داخل برنامج Immunity.

-وقف التنفيذ و عرض حالة المعالج و الذاكرة.

-بدأ تنفيذ البرنامج و الوقوف بعد كل تعليمة (اذا قابل تعليمة نداء لدالة, يقوم بالدخول و يقف عند اول تعليمة للدالة, فتلك الاداة تقوم بالدخول و تتبع تعليمات الدالة و الوقوف بعد كل تعليمة).

-بدأ تنفيذ البرنامج و الوقوف بعد كل تعليمة (اذا قابل تعليمة نداء لدالة, يقوم بالدخول و تنفيذ كل تعليمات الدالة و يقف عند الخروج منها, الفرق بينه و بين سابقه أن السابق يدخل و يتتبع تعليمات الدالة و يقف بعد كل تعليمة, اما تلك الاداة فتنفذ الدالة كلها ولا تقف حتى تنتهي من تنفيذ كل التعليمات التي بداخلها).

-بدأ التنفيذ مع الوقوف اذا صادف اي مشكلة او توفر شرط معين, وتتبع المشكلة و سلسلة الاوامر التي أدت لتلك المشكلة (بما في ذلك الدوال التي تم استدعائها).

-بدأ التنفيذ مع الوقوف اذا صادف اي مشكلة او توفر شرط معين, وتتبع المشكلة و سلسلة الاوامر التي أدت لتلك المشكلة (بدون الدوال التي تم استدعائها).

-بدأ التنفيذ و الوقوف حتى الانتهاء من الدالة الحالية.

-الذهاب الي عنوان معين.

-شاشة تظهر البرنامج Disassembler و آخر الاوامر التي قام بها في البرنامج المراد دراسته.

-شاشة تظهر الملفات و المكتبات التي يستدعيها و يستخدمها البرنامج المراد دراسته.

-شاشة تظهر مقاطع الذاكرة للبرنامج المراد دراسته بعد تحميله في الذاكرة العشوائية RAM.

-شاشة تظهر المواضيع threads التي تم استدعائها من قبل البرنامج المراد دراسته.

-شاشة تظهر ارقام الواجهات الرسومية Graphical Interface في الذاكرة العشوائية التي قام البرنامج المراد دراسته بصنعها.

-شاشة تظهر المعالجات handlers التي قام البرنامج بصنعها (مثل الاتصال الشبكي Network Handler, الاتصال بنظام الملفات File System Handler, الاتصال من خلال الذاكرة Memory Sharing handlers).

-شاشة تظهر نفس المعلومات التي أمامنا في الشاشة الرئيسية لبرنامج Immunity.

-شاشة تظهر التعديلات التي قمنا بها على الكود في الذاكرة.

-شاشة تظهر المكدس بشكل ابسط من الشاشة التي بالاسفل.

-شاشة تظهر نقاط التوقف software breakpoints التي قمنا بوضعها في الكود.

-شاشة تظهر نقاط التوقف hardware breakpoints التي قمنا بوضعها في الكود او الذاكرة.

-شاشة تظهر التعليمات التي تؤشر الى التعليمة التي يقف عليها المعالج حاليا.

-شاشة تظهر تتبع التنفيذ من عناوين و مواضيع threads و بعض البيانات الاخري الخاصة بتتبع الكود و معرفة ملخص لما تم صنعه او تدميره من قبل البرنامج المراد دراسته.

-شاشة تظهر المصادر التي ممكن ان تستبدل بعض القطع من الاكواد بعبارات يحددها المستخدم.

-شاشة المساعدة الخاصة ببرنامج Immunity.

 

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

أول سؤال لمعرفة أين و كيف نبدأ, هو ماذا نريد أن نفعل؟ ما هدفنا من استخدام الهندسة العكسية؟

و هنا نسأل أنفسنا نفس السؤال, و الاجابة هي أننا نريد في النهاية أن نعلم كلمة السر المتواجدة داخل البرنامج.

الخبير في مجال الهندسة العكسية سيدرك انه يستطيع القيام بذلك باستخدام عدد كبير من الطرق, فمثلا نستطيع أن ندخل الى النافذة التي تحوي كل العبارات المتواجدة في البرنامج المراد دراسته. كما يمكن أن ندخل على النافذة الخاصة بجميع الدالات التي يستدعيها البرنامج و نقوم بتتبعها, وهذه هي الطريقة التي سأستخدمها بأذن الله في هذا المقال لأنها الاقصر و الابسط.

الطريقة بكل بساطة, هي أننا نعلم اسماء الدالات التي يستخدمها نظام التشغيل Windows ليقارن بين عبارتين, لاحظ هنا ان معرفتنا باسم الدالة ليس بسبب أننا نحن من برمجنا البرنامج الذي نقوم بفهمه حاليا, بل علمناها من خلال دراستنا و خبرتنا في علم نظم التشغيل و بمعني أدق لمعرفتنا و خبرتنا في نظام التشغيل الذي نقوم بعمل الهندسة العكسية عليه. فنحن نعرف جيدا أن Windows مثله مثل Linux و مثل أي نظام تشغيل آخر له مكتباته الخاصة و دالاته التي يستخدمها للقيام بمهامه, وتسمى تلك المكتبات و الدالات في Windows المكتبة المحلية Native Library, تلك المكتبة منخفضة المستوى جدا لانها تتعامل مباشرة مع اجزاء الحاسب Hardware, كما أن شركة Microsoft رفضت عن الافصاح لكثير من دالاتها (لا تقلق, فنحن مهندسون عكسيون, بأذن الله سنقوم في أحد الدروس بأخذ احد الدالات من تلك المكتبات و فهم محتواها بل و سوف نكتب لها وثيقة تقنية كاملة Documentation كالتي تصدرها Microsoft نفسها), و لهذا السبب قامت Microsoft باصدار واجهة برمجية API تسمح للمبرمجين باستخدام واجهة مبسطة و سهلة و موثقة Documented من مكتباتها المحلية, وقامت بتسمية تلك الواجهة البرمجية Win32 API.

الدالة الخاصة بمقارنة عبارتين في الواجهة البرمجية Win32 API هي:
strcmp

لا يختلط عليك الامر, هذه الدالة ليست هي الدالة المستخدمة في لغة C التي قمنا باستخدامها في برمجة البرنامج الذي نعمل عليه حاليا, هذا تشابه في التسمية فقط.

الآن تفكيري سيكون كالتالي:

-البحث عن أي نداء للدالة strcmp.

-وضع نقطة توقف عند تعليمة النداء Software Breakpoint, و هذا سيجعل البرنامج -عند تنفيذه- يقف حينما يقوم بتنفيذ التعليمة التي تحتوي على نقطة التوقف.

-نذهب للمكدس و نرى آخر قيمتين تم دفعهما بداخله.

 

السؤال الذي قد يأتي للبعض, لماذا ننظر للمكدس؟
من خبراتنا و معرفتنا في علم نظم التشغيل, نعرف أن أي دالة يتم النداء عليها تقوم اولا بدفع متغيرات الدوال parameters التي تحتاجها الدالة الى المكدس, و من معرفتنا و قرائتنا لوثيقة شركة Microsoft التي توضح كيفية استخدام الدالة strcmp للمبرمجين, نعرف أن تلك الدالة تأخذ متغيران فقط و هما العبارتان اللتان ستقارنهما الدالة ببعضهما البعض (ستجد الصفحة الخاصة بوثيقة تعريف الدالة من شركة Microsoft في جزء المراجع في نهاية المقال), فبالتالي حينما يقف البرنامج عند نقطة الوقوف Software Breakpoint, سنجد في المكدس مؤشران للمتغيرين.

 

فأذا لنبدأ بالبحث عن الدالات المستخدمة في البرنامج المراد دراسته.

ثم نقوم بالبحث عن الدالة strcmp.

 

نلاحظ هنا أن تلك الدالة لم تستخدم سوى مرة واحدة فقط في البرنامج.

نقوم الان بالضغط مرتين على اسم الدالة لنذهب لمكان استخدامها.

 

بعد ذلك نقوم بالضغط على F2 لنضع على هذه التعليمة نقطة توقف.

و أخيرا نبدأ البرنامج من خلال علامة البدأ التي قمنا بشرحها في شريط الادوات.

سنجد أن البرنامج المراد دراسته قد بدأ, و يطلب مننا ادخال كلمة مرور, ندخل أي كلمة ولتكن:
HelloWorld

حينها سنجد أن البرنامج قد توقف, و اذا رجعنا الي نافذة البرنامج Immunity, و نظرنا في قسم المكدس (اسفل اليمين), سنجد اخر قيمتين تم دفعهما الي المكدس و هما كلمة المرور الاصلية التي نبحث عنها و كلمة المرور التي أدخلناها.

ها هي كلمة المرور, اكتشفنا أنها MyPassword!!\n ,لا تتعجب من هذه الاشارة التي في نهاية العبارة في المكدس, تلك الاشارة هي linefeed (\n) character ,لأن تقنيا نحن استخدمنا دالة fgets في البرنامج الذي كتبناه في البداية, و هذه الدالة تقوم بوضع هذه العلامة في آخر العبارة التي تقرأها من المستخدم, و تلك العلامة ليس لها أي شكل في نظام ASCII, لهذا فان البرنامج قد وضعها بهذا الشكل الغريب في آخر العبارة.

 

اذا بفضل الله تعالي استطعنا اليوم أن نقوم بأول تجربة عملية لنا في علم الهندسة العكسية, و استطعنا استخراج كلمة السر المخبأة في البرنامج. و ادركنا ايضا مدى أهمية معرفتنا بعلم نظم التشغيل و خصوصا نظام التشغيل الذي قمنا بعمل الهندسة العكسية عليه, لأن لولاه لما كنا لنفهم آلية استخراج الكلمة من الاساس. هذا البرنامج في قمة البساطة و السهولة, فهو لم يحتوي على أي تعقيد أو تشفير, في المقالات القادمة بأذن الله سنقوم بفهم المزيد من البرامج و القيام بالهندسة العكسية عليها.

 

المراجع:

البرنامج.

– برنامج Immunity Debugger.

– الدالة strcmp.