JavaScript is not enabled!...Please enable javascript in your browser

جافا سكريبت غير ممكن! ... الرجاء تفعيل الجافا سكريبت في متصفحك.

-->
الصفحة الرئيسية

الهندسة العكسيه

 


الهندسية العكسيه


الهندسة العكسية هي واحدة من أكثر المجالات إثارة للاهتمام في الأمن السيبراني والقرصنة الأخلاقية. سنحاول من خلال هذا المنشور تبسيط هذا المجال من خلال استعراض الأفكار المتضمنة خطوة بخطوة. سنركز على الملفات التنفيذية البسيطة لـ ELF Linux في الوقت الحالي وفي وقت لاحق سنبحث أيضًا في البرامج التنفيذية لـ windows exe و bytecode لـ JVM وما إلى ذلك. لذا فلنبدأ!


ما هي الهندسة العكسية؟

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


معظم البرامج التي ليست مفتوحة المصدر لا توفر شفرة المصدر الخاصة بها وبدلاً من ذلك لدينا الكود القابل للتنفيذ المترجم معنا. علينا بطريقة ما معرفة ما كان soruce (أو مجموعة فرعية منه) من الكود القابل للتنفيذ. هذا ليس بالأمر السهل بشكل عام لأن كود الآلة / التجميع معقد للغاية ولديه أيضًا الكثير من تحسينات المترجم المضافة إليه.


بشكل عام ، قد لا يكون الملف القابل للتنفيذ المقدم إلينا تعليمات ثنائية أو تعليمات تجميعية ، بل يمكن أن يكون أيضًا في شكل رمز بايت مستقل للنظام الأساسي ينفذه أي جهاز افتراضي (مثل جهاز Java الظاهري). ومع ذلك ، سننظر فقط في ملفات Linux التنفيذية التي تم إنشاؤها من كود C / C ++ في هذا البرنامج التعليمي حيث يوفر ذلك نظرة عامة رائعة على المجال. للقيام بذلك ومع ذلك ، يجب أن نفهم التجميع الأساسي.


مقدمة إلى x86 Assembly

x86 Assembly هو رمز تعليمات التجميع المستخدم بواسطة معالجات غير ARM (Intel / AMD) وستستخدم معظم مشكلات CTF رمز التعليمات هذا. قد تختلف التعليمات التي تم إنشاؤها من نظام تشغيل إلى آخر وسننظر في ملفات لينكس التنفيذية (تنسيق ELF). قبل المتابعة أيضًا ، لاحظ أن هناك مجموعة متنوعة من صيغ التجميع المختلفة ، سنستخدم بناء جملة Intel Assembly في هذا البرنامج التعليمي على الرغم من أن بناء جملة AT&T البديل شائع جدًا أيضًا.


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


السجلات

يمكن اعتبار السجل موقعًا خاصًا للذاكرة في وحدة المعالجة المركزية. هناك 6 سجلات للأغراض العامة وسجلين خاصين متاحين. يمكننا القيام بجميع عمليات التجميع الممكنة على هذه السجلات مثل إضافة القيم والطرح وما إلى ذلك.


يتم تسمية السجلات الثمانية باسم EAX, EBX, ECX, EDX, ESI, EDI, ESP, EBP.


ومع ذلك ، إذا مررت بأي رمز تجميع ، فسترى اختلافات مختلفة في أسماء التسجيل. هناك طرق مختلفة يمكنك من خلالها استدعاء سجلات مختلفة. تتيح لك التسمية أعلاه الوصول إلى 32 بت المرتبطة بكل سجل. في الوقت الحاضر في أنظمة 64 بت ، يتم تخصيص 64 بت لكل سجل والتي يمكن استدعاؤها باستخدام الأسماء RAX, RBX, RCX, RDX, RSI, RDI, RSP, RBP.


وبالمثل ، إذا كنت تريد 16 بتًا فقط ، فستتصل بهم AX, BX, CX.. هكذا وهكذا. للحصول على ثماني بتات سوف تستخدمها AL, BL, CL..وهكذا. يوضح الرسم البياني التالي هذا بشكل أفضل:






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


هناك شيء آخر مهم يجب ملاحظته وهو أنه ESP and EBPيتم استخدامه لتخزين موقع ذاكرة المكدس. ESPيشير إلى أعلى المكدس EBPويشير (بشكل عام) إلى القاع. إعلان المتغيرات على المكدس سيكون بالتالي معادلاً لجمع وطرح القيم من ESPو EBP. لاحظ أنك لا تحتاج عمومًا إلى معرفة التفاصيل الدقيقة ولكن وجود فكرة غامضة تنجح.


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


عمليات التجميع الأساسية

movعملية

العملية movهي واحدة من أبسط العمليات وكل ما تفعله هو نقل القيم (أو تعيين قيم). بناء الجملة movهو ما يلي:


mov destination, source

12لنفترض أنني أرغب في تعيين القيمة EAXثم سأقوم بتشغيل العملية:


mov eax, 12

هناك شيء آخر يجب فهمه وهو إلغاء الإشارة. هذا مشابه لـ C. لنفترض أن السجل ECXيحتوي على القيمة 0x6665fالتي تمثل موقعًا في الذاكرة. ECXهو بالتالي مشابه لمؤشر. إذا كنت أرغب في تحميل القيمة المخزنة في 0x6665f، EAXفسوف أستخدم الأمر التالي:


mov eax, [ecx]

تعمل الأقواس []بشكل مشابه لما *في C / C ++ وتقوم بإلغاء تحديد موقع الذاكرة وإخراج القيمة في ذلك الموقع.


addعملية

هذا بسيط جدا. ضع في اعتبارك رمز التجميع التالي:


add eax, ebx

هذا يعادل:


eax = eax + ebx

subعملية

هذا مشابه ايضا ضع في اعتبارك رمز التجميع التالي:


sub eax, ebx

هذا يعادل:


eax = eax - ebx

cmpعملية

هذه عملية مفيدة للغاية وتستخدم لمقارنة القيم. يمكن دمج نتيجة هذه العملية مع jumpعمليات للتحكم في التدفق. ضع في اعتبارك الكود التالي:


cmp ecx, 15h

jz 0x7eb 

دعونا نرى ما يفعله هذا. يقارن cmpالأمر القيم المعطاة له ، في هذه الحالة هي القيمة المخزنة ecxوالقيمة 21المعطاة كنظام سداسي عشري. cmpيطرح بشكل أساسي هاتين القيمتين ويضع بعضًا FLAGSمما تحدثنا عنه من قبل. هنا إذا كانت كلتا القيمتين متساويتين ، فسيكون الطرح 0وهكذا ZEROسيتم تعيين العلم.


التعليمات التالية jzتعني "قفزة إذا كانت صفرًا". وبالتالي ، إذا تم تعيين علامة الصفر ، ينتقل البرنامج إلى موقع الرمز المحدد حسب 0x7ebالعنوان (يمكن رؤية ذلك بسهولة باستخدام مصحح الأخطاء). وبالتالي فإن هذا مشابه لبيان "if".


/p>

اتضح أنه يمكننا استخدام مثل هذه الأوامر ذكية لبناء for، whileوحلقات أخرى. سنتناول هذا في المقالة التالية. بدلاً من jzالاستخدام إذا استخدمنا jle، لكانت القفزة ستحدث إذا ecx <= 15hاقتنعت بذلك. في الواقع ، يمكن استخدام مجموعة متنوعة من هذه الشروط لمحاكاة التحكم في التدفق.


pushوpop

هذه ليست مهمة حقا بالنسبة لنا. يتكون بناء الجملة في الغالب من النموذج:


push/pop register

هذه العملية مسؤولة عن دفع / ظهور القيم في المكدس. لن نستخدم هذا كثيرا.


testعملية

هذا مشابه cmpباستثناء أنه يحسب الثنائي ANDبدلاً من الطرح. وبالتالي ، إذا كان الثنائي ANDبين المدخلات المعطاة هو 0عندئذٍ يتم تعيين العلم الصفري.


Cوبالتالي يمكن ترجمة الشرط التالي بسهولة إلى تجميع:


if (eax == 0){

 // do stuff

}

سيكون التجمع المقابل:


test eax, eax

jz location_to_do_stuff

leaعملية.

هذه هي العملية الأخيرة التي سنراها هنا. هذا مشابه movولكن بدلاً من نسخ القيمة ، يقوم بنسخ العنوان.


lea eax, [ecx]

سيقوم الكود أعلاه بنسخ القيمة المخزنة في ecx(أي العنوان) إلى eax. لاحظ أنه movكان من الممكن نسخ القيمة المخزنة في العنوان المخزن فيه ecx. وبالتالي leaيقوم بتحميل العنوان بدلاً من القيمة. إنها تعني تحميل العنوان الفعال.

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


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


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


عملية التحكم في التدفق هي ذات أهمية كبيرة لمبرمجي الحاسوب. حيث تُعتبر الأوامر و التحكم في التدفق أساسيات البرمجة التعليمية و كل مبرمج عليها التركيز.

 

و بالنسبة للمبرمجين المبتدئين، يجب عليهم فهم أساسيات هذه الأوامر وكيفية التحكم في التدفق. و يتم ذلك من خلال القراءة الوافية عن هذه الأوامر والتدرب عليها من خلال كتابة الشفرة و إنشاء برامج صغيرة لاختبار وفهم كيفية عملها.


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


مقدمة في التفكيك الساكن للهندسة العكسية.

شوهد الكثير من النظريات حتى الآن. دعونا نرى الآن كيف يمكننا أن نضع كل ذلك موضع التنفيذ!


سنحتاج إلى برنامج تفكيك للحصول على كود التجميع والتحقيق فيه. دعونا نستخدم المفكك الثابت في الوقت الحالي. لا يسمح لنا برنامج التفكيك الثابت بتشغيل الملف ولكنه يوفر تحليلًا مفككًا ومفككًا لرمز التجميع. IDA هو المعيار الصناعي لهذا وقم بتنزيل الإصدار المجاني من IDA وتشغيله من هنااضغط هنا


بمجرد تثبيت IDA Free ، يمكنك البدء في العمل وتحليل الكود. دعونا نحل هذا التحدي CTFLearn باستخدام IDA.


قم بتنزيل الملف وتحميله في IDA. استمر في النقر فوق التالي ، ولا تغير أي خيارات (دع IDA يقرر أنه ELF على سبيل المثال!). يجب أن تصل إلى الشاشة التالية: 




إذا قمت بتشغيل الملف ، فلاحظت أنك بحاجة إلى إدخال دبوس حتى يعمل هذا. إذا أدخلت أي إدخال عشوائي ، فسيتم إخراج "PIN Salah!" من الواضح أننا نريد العثور على رقم التعريف الشخصي الذي يعطي الاحتمال الآخر.


تظهر الفروع أعلاه الاحتمال الآخر ، فأنت تريد الحصول على "PIN benar!" لاحظ أنه من خلال testالطريقة الوحيدة يمكننا الحصول على "PIN Salah!" هو إذا تم EAXالاحتفاظ بالقيمة 0.


لذلك بطريقة ما عندما نقوم بإدخال رقم التعريف الشخصي الخطأ EAXيتم تعيينه على 0. لاحظ أن هناك تعليمات تسمى call cek. callفي التجميع يعني أننا نستدعي وظيفة. انقر نقرًا مزدوجًا هناك لمعرفة رمز cekالوظيفة:






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


الآن نرى ذلك جيدًا بعد كل ما يحدث في الكتلة العلوية cekهناك طريقان. يتم تعيين مسار واحد eaxلـ 1و else to 0. من الواضح أننا نريد أن نرى متى يتم تعيين القيمة على 1هذا فقط عندها يكون الدبوس صحيحًا.


يتم تحديد المتفرعة بواسطة jnz. هذا يعني "القفز إن لم يكن صفر". وبما أننا نستخدم cmpهذا يعني أنه فقط عند تعيين العلم الصفري لن نقفز (ومن ثم نحصل على EAX1).


متى يتم تعيين علامة الصفر؟ هذا يحدث فقط عندما [rbp+var_4] == eax. ومع ذلك ، فإن ما ورد أعلاه movsيوضح أن القيمة الموجودة الآن [rbp+var_4]هي نفس القيمة الموجودة في ediوالتي eaxكانت في شيء يسمى cs:valid.


ما هذا cs:valid؟ اتضح أنه مجرد اسم تم إعطاؤه IDAلبعض القيمة المخزنة في النظام الثنائي. إذا نقرنا نقرًا مزدوجًا فوق هذا ، فسنحصل على بيانات القيمة التالية:






الآن لم نر أين يتم تخزين مدخلاتنا. اتضح أنه يتم تخزينه في ملفات EDI. هذا يتغير بشكل عام ولكن باستخدام شيء يسمى المفكك الديناميكي (gdb) يمكننا معرفة ذلك (سنرى هذا في البرنامج التعليمي التالي). حتى بدون معرفة ذلك ، يمكننا تخمين أنه يتم تخزين المدخلات بشكل جيد EDIوكما سنرى تبين أن هذا التخمين صحيح.


لذلك إذا كان مدخلاتنا مساوية للقيمة (المعطاة في شكل 51615hسداسي عشري) فسوف ندخل وبالتالي يجب أن يكون رقم التعريف الشخصي (PIN)! تحويل هذا إلى ثنائي نحصل على هذه القيمة.1EAX333333


دعونا ندخل هذا ونرى ما إذا كان هذا صحيحًا أم لا.






وبالفعل حصلنا على "PIN benar!" هذا هو رقم التعريف الشخصي ووجدنا رقم التعريف الشخصي باستخدام بعض مهارات التفكيك والتحقيق الذكية!


هذا يلخص هذه المشكلة. كانت هذه في الواقع واحدة من أبسط مشاكل الهندسة العكسية حيث تمكنا من حلها باستخدام المفكك الساكن فقط. سنرى لاحقًا بعض المشكلات الأكثر تعقيدًا التي يجب حلها باستخدام أدوات أخرى مثل gdb، radare2إلخ.


هذه نهاية هذا البرنامج التعليمي. لا تتردد في تجربة المزيد من المشاكل باستخدام IDA وتذكر أيضًا أن تتصفح google كثيرًا. إن فهم التجميع ليس بالأمر السهل ويجب على المرء أن يتصفح google بشكل متكرر لمعرفة ما تفعله كل عملية. هذا هو المتعة والاستمرار في القرصنة!


الهندسة العكسيه

المطور محمد الحزمي

تعليقات
ليست هناك تعليقات
إرسال تعليق
    الاسمبريد إلكترونيرسالة