برنامج بدون استيرادات - نسخة قابلة للطباعة +- الفريق العربي للهندسة العكسية (https://www.at4re.net/f) +-- قسم : منتديات الهندسة العكسية - Reverse Engineering Forums (https://www.at4re.net/f/forum-4.html) +--- قسم : الهندسة العكسية المتقدمة - Advanced RCE (https://www.at4re.net/f/forum-26.html) +--- الموضوع : برنامج بدون استيرادات (/thread-3065.html) |
برنامج بدون استيرادات - siddigss - 10-04-2022 أثناء بحثي عن موضوع ما وجدت برنامجا يُدّعى أنه يعمل بدون استيرات أي مكتبة ولا حتى kernel32.dll، ولكنه يستدعي الدالة MessageBox والتي توجد في المكتبة USER32.dll. وفعلا في cff explorer لا وجود لجدول imports. البرنامج للأسف لا يعمل عندي على windows 8. من كان عنده windows xp إلى 7 يمكنه التحقق لنا . فقمت بتنقيح البرنامج ومحاولة فهم الأوامر، في ما يلي سأوضح نظريا كيف يعمل البرنامج على الرغم من عدم امتلاكي لنسخة تعمل منه حاليا، كما سأوضح سبب فشل البرنامج (البرنامج في المرفقات). تنبيه: هذا التحليل لا يعني أن البرنامج لن يعمل على الأنظمة السابقة ل windows 8! بل على العكس، فكرة البرنامج تبدو صالحة لو لا بعض الافتراضات الضمنية التي لا تتحقق في windows 8. وغالب ظني أنه فعلا يعمل على الأنظمة السابقة. خطة البرنامج بشكل مختصر: 1- يفترض البرنامج أن kernel32.dll قد تم تحمليها مسبقا بشكل تلقائي حتى ولو لم يطلب البرنامج ذلك (وهو الحال فعلا). 2- انطلاقا من هذا الفرض 1 يحاول البرنامج البحث عن ال base address ل kernel32.dll. 3- يبحث البرنامج في ال export directory في ال PE Header الخاص ب kernel32.dll عن الدالة LoadLibrary. 4- باستعمال الدالة LoadLibrary يستطيع البرنامج تحميل المكتية USER32.dll ومعرفة عنوانها. 5- البحث في ال export directory في ال PE Header الخاص ب USER32.dll عن الدالة MessageBox 6- استدعاء الدالة MessageBox. التفاصيل: سنستعمل ال structure التالي لتخزين معلومات الدوال التي نود البحث عنها. function_name_length و function_name ثابتان في الحقيقة بينما function_address هو المتغير الذي سوف نقوم بتعبئته عند الخطوتين 3 و 5.البرنامج يعرف المتغيرات العمومية (Global أهذه الترجمة جيدة؟) التالية: علي اليمين العناوين المطلقة التي ظهرت عندي وعنوان الأساس كان 0x400000، وأود أن أنوه أن جميع العناويين في هذه المشاركة مطلقة كما أن أسماء المتغيرات والدوال من تسميتي.لنلق نظرة على kernel32_functions_info_array نرى أن kernel32_functions_info_array عبارة عن ثلاث function_info متعاقبة، وبالمثل user32_functions_info_array أسماء الدوال التي تظهر في kernel32_functions_info_array و user32_functions_info_array هي أسماء الدوال التي سيبحث البرنامج عن عناوينها بدون استيراد مكتباتها بشكل صريح.الأوامر: سنفصل الخطوتين 2 و 3، لأن البقية واضحة و الخطوة 5 مطابقة ل 3 (فقط باختلاف قيمة DLL_base_address). الخطوة 2: عمليا يبدأ البرنامج باستدعاء الدالة Fill_kernel32_address_directly_after_running المعرفة كالتالي تبدأ الدالة ب ecx = [esp+4] وهذا لأن أول ما يوجد في المكدس هو عنوان داخل نطاق kernel32.dll. لكننا نريد عنوان الأساس وليس أي عنوان في kernel32.dll. نعلم أن عنوان الأساس يحقق الخصائص التالية1- عنوان الأساس يساوي قيمة PE_Header.Optional_Header.ImageBase والذي يمكننا الوصول إليه كالتالي أي أن الشرط الأول على ecx هو
2- أصغر من قيمة ecx أعلاه (هل هذا صحيح دائما؟). كما أن البرنامج يضيف الشرط التالي 3- أن يكون dx & F800 == 0 ولعل المقصود أن تكون قيمة edx صغيرة فلا يحصل memory access violation exception. فما تقوم به الدالة Fill_kernel32_address_directly_after_running هو انقاص قيمة ecx باستمرار والتحقق من الشرطين 1 و 3. إذا تحققا فهذا هو عنوان الأساس ل kernel32.dll !! لكن لا بد أنكم رأيتم التعليق access violation exception. Fix this أعلاه، وهذا عندي لوجود مناطق ذاكرة محجوزة تتخلل منطقة ذاكرة kernel32.dll. يبدو أن هذا لم يكن الحال في الأنظمة السابقة. الخطوة 3: بما أننا حصلنا على عنوان kernel32.dll وخزناه في DLL_base_address فإبمكاننا الوصول إلى export directory ببساطة والبحث عن أسماء الدوال التي نريد. لنعرف الدالة التالية قد تبدو كبيرة لكن نظريا بسيطة وجل ما تقوم به هو التالي:1- استخراج بعض المعلومات من ال PE Header الخاص بال dll المراد البحث فيه وهو في حالتنا الآن kernel32.dll. 2- في ال while loop يقوم بمقارنة اسم الدالة التي نريد أن نبحث عنها (esi) مع قائمة الأسماء المسخرجة في 1 والتي خزنت في edi. 3- بعد إيجاد ترتيب اسم الدالة في قائمة الأسماء (ebx) نستعمله كأنه ال ordinal المحدد للدالة في ال PE Header الخاص ب kernerl32.dll وباستعماله نستطيع إيجاد عنوان الدالة. هذه الخطوات تطبيق عملي لل PE Header Structure. هل انتبهت للتعليق False ordinal؟ في الحقيقة حتى هنا توجد مشكلة وهي أن المبرمج افترض أن ترتيب اسم الدالة ebx في مصوفة الأسماء edi سيكون مطابقا ل ordinal الدالة! للأسف هذا غير صحيح عندي. كان من المفترض أن يستخدم address of addresses of names وليس address of first name (انظر التعليقات على الأوامر) لكنه افترض أن ترتيب الأسماء هنا وهناك سيكون متطابقا! -------------------- في المرفقات: تجدون البرنامج وملف txt فيه أوامر البرنامج معكوسة كلها تقريبا لمن أراد التعقب أثناء التنقيح أو محاولة إعادة كتابة البرنامج لجعله يعمل على الأنظمة الجديدة. المراجع: البرنامج الأصلي يوجد في مجلد yoda/NoImports.exe بعد التحميل من هنا. RE: برنامج بدون استيرادات - siddigss - 11-04-2022 ملحق: تذكير سريع بال export directory في ال PE Header. RE: برنامج بدون استيرادات - MountLegacy - 11-04-2022 مجهود ممتاز بارك الله فيك جاري النشر علي الفيس بوك RE: برنامج بدون استيرادات - siddigss - 13-04-2022 تحديث: كتبت نسخة من البرنامج تعمل على windows 8، وأتخيل أنها تعمل على جميع الأنظمة من xp إلى 10. أرجو من أصحاب النظم المختلفة تجربة البرنامج. كما ذكرنا آنفا، البرنامج كان به مشكلتان، الأولى أن طريقته في الوصول إلى عنوان الأساس ل kernel32.dll لم تعد تنفع، والثانية استعماله لقائمة الأسماء بدل قائمة عناوين الأسماء. المشكلة الثانية حلها بسيط. لحل الأولى علينا استعمال أسلوب مختلف. يمكننا الحصول على معلومات المكتبات المحملة من خانة InMemoryOrderModuleList في جدول LDR الذي بدوره يوجد في جدول PEB وهذا الأخير في TIB. يمكننا الوصول لجدول TIB باستعمال المسجل fs، فمثلا العنوان fs:[0x30] يحوي مؤشرا إلى جدول PEB. بهذه الطريقة يمكننا الوصول إلى عناوين وأسماء المكتبات المحملة، ويجدر بالذكر أن الأسماء في InMemoryOrderModuleList هي من النوع wchar_t* وليس char*. في المرفات: تجدون البرنامج مع المصدر بلغة C موضحا بتعليقات وملف نصي فيه أمر التجميع (compilation). ملاحظات: افترضت أن جميع أسماء المكتبات في InMemoryOrderModuleList تنتهي بصفر على الرغم من أن صفحة مايكروسوف لا تؤكد ذلك (انظر UNICODE_STRING في المراجع). المراجع: https://docs.microsoft.com/en-us/windows/win32/api/winternl/ns-winternl-peb_ldr_data https://docs.microsoft.com/en-us/windows/win32/api/winternl/ns-winternl-peb https://en.wikipedia.org/wiki/Win32_Thread_Information_Block https://docs.microsoft.com/en-us/windows/win32/api/ntdef/ns-ntdef-_unicode_string RE: برنامج بدون استيرادات - Newhak - 09-05-2022 موضوع جميل جدا بارك الله فيك اخي الحبيب مشكلة استيراد واخفاء الدوال تواجه الكثير منا بالذات في البرامج المضغوط حيث يقوم الضاغط باخفاء بعض الدوال المهمة لمنع العبث بالبرنامج ونحتاج في كثير من الاحيان لاضافة الدوال يدويا اتمنى ان يكون هناك شرح مصور لمثال عملي على العموم الله يجزيك كل خير على طرح الموضوع وهذه المعلومات القيمة |