Handling Debug Registers by:GamingMasteR - نسخة قابلة للطباعة +- الفريق العربي للهندسة العكسية (https://www.at4re.net/f) +-- قسم : منتديات الهندسة العكسية - Reverse Engineering Forums (https://www.at4re.net/f/forum-4.html) +--- قسم : الهندسة العكسية - Reverse Code Engineering (https://www.at4re.net/f/forum-19.html) +--- الموضوع : Handling Debug Registers by:GamingMasteR (/thread-4238.html) |
Handling Debug Registers by:GamingMasteR - TeRcO - 05-01-2025 (05-01-2025, 12:51 AM)GamingMasteR كتب : تاريخ المشاركة 2008-08-26 - 07:39 PM السلام عليكم ورحمة الله وبركاته .
درس اليوم عن كيفية كتابة debugger للتحكم في سير البرنامج و كيفية وضع نقط توقف Hardware Breakpoints .كما نعلم فإن الـHardware Breakpoints - او سنرمز لها اختصاراً بـHWBP - أقصى عدد يمكن وضعه هو 4 ويتم التعامل معها عبر مسجلات التنقيح Debug Registers وهي 8 مسجلات طول كل منهم 32bit وظيفتهم كالتالي :- Dr0-Dr1-Dr2-Dr3 : يمثل كل مسجل منهم العنوان الذي سنضع عليه نقطة التوقف . Dr4-Dr5 : محجوزان ولا يمكن استعمالهم . Dr6 : يسمى ايضا Debug Status Register و يمكننا من معرفة أي HWBP حدث .. سنتطرق له بالتفصيل لاحقاً . Dr7 : يسمى بـDebug Control Register وهو الذي يتحكم بالـHWBP (الكل في الكل) ,, تركيبته كالتالي : أول 8 بتات ( 0 -> 7 ) يمكن تقسيمهم الى اثنين اثنين بحيث كل اثنين يخصان احدى نقط التوقف ,, اذا تم وضع اول بت (L) فأن نقطة التوقف تكون local breakpoint أي يحدث الـDebug exception في الـProcess صاحب الـthread الذي غيرنا Dr7 له . ثاني بت (G) لوصف نقطة التوقف على انها global breakpoint اي يحدث الـdebug exception اذا توافرت شروطه في جميع الـprocesses . من R/W0 الى R/W3 : لتحديد نوع نقطة التوقف ,, هل اذا تم القراءة من العنوان او الكتابة عليه او تنفيذه كتعليمة ,, يمكن وضع قيمته كالتالي (بالبت) : 00 : توقف عند تنفيذ التعليمة التي بالعنوان . 01 : توقف عند الكتابة على العنوان . 10 : لا تستعمل الا في ظروف خاصة (للهاردوير) . 11 : توقف عند القراءة او الكتابة من العنوان . من LEN0 الى LEN3 : لتحديد طول البيانات التي ستضع عليها نقطة التوقف ,, يمكن وضع قيمته كالتالي (بالبت) : 00 : لتحديد طول 1 بايت . 01 : لتحديد طول 2 بايت . 10 : تستخدم في بعض المعالجات لتحديد طول 8 بايت (اقرأ الـdocumentations الخاصة بإنتل او AMD لتفاصيل اكثر) . 11 : لتحديد طول 4 بايت . ----------------------------------------- حسنا لقد تعرفنا بما فيه الكفاية على مسجلات التنقيح ... الان ما الخطة التي سنعمل عليها ؟ كيف سنقوم بوضع HWBP عملياً على Process معين ؟ كيف سنعرف انه تم الوصول الى نقطة توقف معينة ؟ لتوضيح الفكرة بشكل عملي سنقوم بكتابة debugger صغير يقوم بعمل debug على برنامج crackme كمثال ووضع نقط توقف فيه وعمل اشياء اخرى . لتنقيح برنامج معين يمكن فعل ذلك عن طريق انشاء العملية بالدالة CreateProcess ووضع بارامتر الاعلام flags == DEBUG_PROCESS .. كفكرة عامة ما الذي يحدث عند وقوع خطأ في برنامج معين ليس تحت التنقيح ؟ يتم اظهار الـexception او كما يقال exception raise ويتم تسليم اول SEH handler التنفيذ (ليس بدقّة) .. لكن ما يحدث عند وجود البرنامج تحت التنقيح ان الـdebugger هو الذي يستلم الـexecution ونوع الـexception الذي حدث ويقرر اذا كان سيتعامل مع هذا الـexception ام يجعل البرنامج نفسه (debuggee) هو الذي يتعامل مع الـexception .. أرجو ان تكون هذه الفكرة واضحة ! دوال win32api توفر عدة دوال للتعامل مع التنقيح مثل WaitForDebugEvent - GetThreadContext - SetThreadContext - Read/WriteProcessMemory .. طبعا نحن هنا لسنا بصدد التعرف على تلك الدوال .. يمكنك التطلع عليهم اكثر في مكتبة MSDN . عند حدوث HWBP يتم رفع exception من النوع EXCEPTION_SINGLE_STEP الى المنقح اذا كان موجوداً .. اذا لابد علينا من عمل handling لهذا الـexception code .. طيب سؤال اخر .. كيف نعرف اي HWBP من الاربعة هو الذي حدث ؟ لا توجد دوال api معينة لمعرفة ذلك ! صحيح .. نحن لم نتكلم عن Dr6 بالتفصيل بعد كما وعدنا وها قد حان الوقت .. تركيبة هذا المسجل بسيطة جداً كالتالي : ما يهمنا معرفته هو أول 4 bits وهي تمثل بت لكل HWBP .. اذا تم وضع احدهم فهو يدل على ان الـHWBP المناظر له هو الذي حدث . حسنا كيف نضع HWBP ؟؟ ستقول لي من مسجلات التنقيح Drx ؟! طيب ما انت عارف ان استخدامها privileged ولايمكن تغييرها من user-mode !! سأقول لك لا .. أين ذهبت دالة SetThreadContext اذا ؟؟
hThread : مقبض handle للثريد الذي سنغير الـcontext له .. lpContext : مؤشر الى structure به الـcontext الجديد .. ما هو الـThread Context ؟؟ تعرفون ان نظام ويندوز يتمتع بخاصية الـMultithreading أي امكانية عمل اكثر من thread في نفس الـprocess .. لكل thread له مسجلاته الخاصة و المكدس و اشياء اخرى . يوجد في قلب النظام ما يسمى بالـKernel Dispatcher وهو المسؤول عن تنظيم الـthreads او ThreadScheduling . عند عمل swap-out لـthread لابد من حفظ كل ما يتعلق به (مسجلات - مكدس - storage areas .. الخ) في مكان آمن حتى اذا تم عمل swap-in يتم استرجاع البيانات من هذا المكان مرة اخرى والعكس .. هذا المكان او الذاكرة هي ما نقصده بالـThread Context او Context مباشرة . تركيب الـCONTEXT strcuture هي كالتالي :
كما ترون توجد جميع مسجلات التنقيح داخل الـstrcuture ... اذا ما سنفعله هو كالتالي : 1- جلب الـcontext عن طريق الدالة GetThreadContext . 2- تعديل مسجل Dr7 ووضع البتات الخاصة بطول الـHWBP و نوعها . 3- وضع عنوان الـHWBP في احد المسجلات الاربعة Dr0 -> Dr3 . 4- ارجاع الـcontext المعدلة عن طريق الدالة SetThreadContext . هذا كود مبسط لشرح الكلام النظري السابق :
ولحذف HWBP نفعل مثل ما سبق لكن نصفّر الـbit الخاص بالـlocal والمسجل الخاص بالعنوان له :
لتعامل أسهل مع مسجل Dr7 قمنا بعمل structure لتسهيل الامر بدلا من انجاز كل شئ بالـshifting والـbit level :
مثال عملي : سنقوم بعمل مثال loader على crackme بسيط للأخ dj-siba نقتنص فيه السيريال الصحيح + نتخطى رسالة badboy المزعجة .. التحدي اسمه "حاول ان تكسرني - تمرين رقم واحد" .. موجود بالمرفقات . بتحليل سريع للتحدي اليكم المفيد :
ما سنفعله هو كالتالي .. وضع نقطة توقف للـexecution عند العنوان 0x00403FF4 وبذلك نضمن وجود السيريال الصحيح في العنوان الذي يشير اليه المسجل edx . وضع نقطة توقف اخرى عند عنوان القفزة التي تؤدي الى اضهار رسالة عدم التسجيل 0x00403FFA . في اول HWBP نقوم بجلب مسجل edx عن طريق GetThreadContext ثم نقوم بقراءة العنوان الذي يشير اليه المسجل من الـprocess عن طريق الدالة ReadProcessMemory ونقوم باظهار السيريال الصحيح . في ثاني HWBP نقوم بجلب مسجل الاعلام EFLAGS و نقوم بوضع العلم ZF وذلك كي تتم القفزة المشروطة و نتخطى الرسالة المزعجة . مسجل EFLAGS أيضا يمكن التعامل معه عن طريق الـbit level لكن قمت بعمل structure لتسهيل الأمر :
المراجع : Intel® 64 and IA-32 Architectures , System Programming Guide, Part 2 Toggle hardware data/read/execute breakpoints programmatically GamingMaster aka Sadistic-X
Arab Team 4 Reverse Engineering RE: Handling Debug Registers by:GamingMasteR - Morpheus - 07-01-2025 موضوع شيق أخي .كنت رأيت مقال لشخص يقوم بعمل BP لبرنامج لتغيير البرامترات تم تنفيد الفانكشن لتخطي بعض الحمايات. كان عندي سؤال خارج الموضوع قليلا ادا تكرمت اخي و لديك اجابة أريد ان اعرف كيف يتم تمرير الarguments التي تستعملهم الentry point مثلا في برنامج سي main() كيف يتم تمرير البرامترات مثلا عندما يكون argc ==0 كيف يتم عمل set للargument argc=0 كنت قد قرأت طريقة اتبتاع createprocess() في كتاب windows internals part 2 لكن يا اما انا لم افهم ام ان الكتاب لم يشرح جيدا لابسط لك اكثر لدي برنامج x يقوم بانشاء بروسسy اخر سواء ب createprocess اوrtlcreateuserprocess ولنفرض البروسس y لديه نقطة ادخال entry() ولديها برامتر char* مثلا كما الشكل الاتي entry(char*p) كيف يقوم يتمرير هدا البرامتر من البروسس x RE: Handling Debug Registers by:GamingMasteR - TeRcO - 07-01-2025 دالة CreateProcess تستخدم بنية PROCESS_INFORMATION، ولتمرير البرامترات إلى البروسيس الجديد، يتم استخدام المعامل lpCommandLine الذي يمثل سطر الأوامر الذي سيتم تمريره إلى العملية الجديدة. عندما تستدعي CreateProcess مع سطر الأوامر (command line) ، فإن النظام يقوم بتوزيع هذا السطر على الذاكرة، بحيث يتمكن البروسيس الجديد من الوصول إلى هذه البيانات عبر argc و argv - argc يحتوي على عدد البرامترات. - argv هو مصفوفة تحتوي على البرامترات. RE: Handling Debug Registers by:GamingMasteR - Morpheus - 07-01-2025 نعم اخي و بعدها قبل البدء في الانتري بوينت للبرنامج الثاني كيف يتم يقوم البرنامج الدي عملنا له spawn باخد البرامترات قبل البدء في العملية الاولى main RE: Handling Debug Registers by:GamingMasteR - TeRcO - 07-01-2025 يقوم نظام التشغيل بتوزيع سطر الأوامر مثلا (app.exe param1 param2 ) الذي مررته عبر المعامل lpCommandLine في الذاكرة ثم يقوم بتقسيمه إلى برامترات. هذه البرامترات تخزن في الذاكرة ويتم تمريرها إلى العملية الجديدة عند بداية التنفيذ، حيث يمكن للبرنامج الوصول إليها عبر المتغيرات argc و argv. RE: Handling Debug Registers by:GamingMasteR - Morpheus - 07-01-2025 نعم هدا ما كنت اتحدث عنه يعني يوجد loader في النضام اريد ان اعرف كيف يقوم يتوزيع هاته البرامترات في الداكرة كيف يقوم بعمل دلك قبل ان تبدأ الدالة main و تجدهم |