Skip to content
KitploitKITPLOIT
أدواتعمليات الاستغلالالمدونة
Log in
إرسال
أدواتعمليات الاستغلالالمدونة
إرسال

أدوات الاختراق واختبار الاختراق والأمن السيبراني لترسانتك الأمنية!

Kitploit هو دليل لأدوات الاختراق والأمن السيبراني واختبار الاختراق. اكتشف آخر تحديثات المشاريع للعثور على الثغرات وتحليل الأنظمة وأتمتة الاختبارات وتعزيز أمنك.

··الخلاصات·اتصال·الخصوصية·© 2026 Kitploit

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
LdrShuffle — تقنية تنفيذ/حقن الأكواد باستخدام التلاعب ببنية وحدة DLL في PEB | Kitploit
أدوات/GitHubGitHub/rwxstoned/ldrshuffle
تحليل الكودالاستغلالالحركة الجانبيةشيل كودما بعد الاستغلالاختبار الاختراقالفريق الأحمرتطوير الحمولاتاستغلال الملفات الثنائية
GitHubrwxstoned/ldrshuffle

LdrShuffle

تقنية تنفيذ/حقن الأكواد باستخدام التلاعب ببنية وحدة DLL في PEB

2894410منذ سنة واحدةتمت المراجعة من قبل Kitploit

الأكثر شعبية

عرض الكل →

اكتشف الأدوات الأكثر استخدامًا من قبل مجتمعنا.

استكشف جميع الأدوات

تصفح مجموعتنا من الأدوات

عرض جميع الأدوات →
مشاركة
عرض المستودع

LdrShuffle

تنفيذ كود خفي عبر تعديل EntryPoint للوحدات المحمّلة وقت التشغيل.

ملخص

تمتلك عمليات Windows وحدات (modules) مختلفة محمّلة وقت التشغيل. لكل وحدة من هذه الوحدات دالة DllMain() معرفة، ويتم استدعاؤها عند إنشاء/إنهاء عملية أو مؤشر ترابط (أربعة سيناريوهات محتملة).

من أجل استدعاء هذه الدوال بشكل صحيح طوال عمر العملية، تشير دوال محمّل Windows (ntdll!Ldrp*) إلى قائمة من الإدخالات التي تحتوي على معاملات رئيسية (بما في ذلك حقل EntryPoint) لكل وحدة.

من خلال الكتابة فوق EntryPoint لوحدة DLL، نضمن إعادة توجيه تنفيذ الكود إلى مكان نختاره.

حالات الاستخدام

يمكن استخدام هذا كأداة بدائية لتنفيذ الكود (code execution primitive)، وللوساطة في استدعاءات API (API proxying)، أي لتشغيل بعض واجهات برمجة التطبيقات مع مكدس استدعاءات (callstack) غير مريب، حيث سيتم استدعاؤها بواسطة دوال Windows شرعية.

يمكن أيضًا استخدامه لبدء التنفيذ في عملية بعيدة، بشرط أن تكون لدى المهاجم القدرة على قراءة وكتابة الذاكرة في العملية الهدف. وبالمثل إلى Threadless Injection، يوفر هذا القدرة على تنفيذ كود في عملية دون استدعاء واجهات API التقليدية المرتبطة بالتنفيذ (CreateRemoteThread, QueueUserAPC).

التحديات

إن تحميل/إلغاء تحميل الوحدات داخل عملية Windows موضوع معقد يطرح الكثير من التحديات، واحتمال عدم الاستقرار، وسباقات التوقيت (race conditions)، والتعطل. من العقبات المعروفة المتعلقة بتشغيل كود كجزء من دالة DllMain() مثلاً، حقيقة وجود قفل المحمّل (Loader Lock) وأننا نعمل في مؤشر ترابط لم يتم إعداده بالكامل، أو أنه في طور الإنهاء.

لذلك، حاولت توثيق ما هو ممكن وما هو غير ممكن بشكل صحيح. على سبيل المثال، في حين يمكن تنفيذ معظم استدعاءات API المعتادة، فإن تشغيل beacon كامل يتطلب أن يكون في عملية منفصلة، لتجنب حالات الجمود (deadlocks) الناجمة عن الدوال المستخدمة في wininet.dll أو winhttp.dll.

التنفيذ

مراجعة تحميل DLL في Windows

تحتفظ كل عملية بقائمة من بنى _LDR_DATA_TABLE_ENTRY وقت التشغيل. تحتوي هذه البنى على تفاصيل كثيرة تتعلق بوحدة DLL، مثل EntryPoint (الذي سنقوم بالكتابة فوقه)، واسمها، وبعض التجزئات (hashes)، والطوابع الزمنية، وعدة أعلام (flags)، وما إلى ذلك. بعض هذه البنى موثّق وبعضها غير موثّق.

يمكن تصور ذلك عبر أمر WinDbg التالي:

dt nt!_LDR_DATA_TABLE_ENTRY 0xdeadbeef

0:006> dt nt!_LDR_DATA_TABLE_ENTRY 0x18d1c4838c0
ntdll!_LDR_DATA_TABLE_ENTRY
   +0x000 InLoadOrderLinks : _LIST_ENTRY [ 0x0000018d`1c485de0 - 0x0000018d`1c4832b0 ]
   +0x010 InMemoryOrderLinks : _LIST_ENTRY [ 0x0000018d`1c485df0 - 0x0000018d`1c4832c0 ]
   +0x020 InInitializationOrderLinks : _LIST_ENTRY [ 0x0000018d`1c4832d0 - 0x0000018d`1c482c80 ]
   +0x030 DllBase          : 0x00007ffe`e87e0000 Void
   +0x038 EntryPoint       : 0x00007ffe`e8838d00 Void
   +0x040 SizeOfImage      : 0x2fe000
   +0x048 FullDllName      : _UNICODE_STRING "C:\WINDOWS\System32\KERNELBASE.dll"
   +0x058 BaseDllName      : _UNICODE_STRING "KERNELBASE.dll"
   +0x068 FlagGroup        : [4]  "???"
   +0x068 Flags            : 0x8a2cc
   +0x068 PackagedBinary   : 0y0
   +0x068 MarkedForRemoval : 0y0
   +0x068 ImageDll         : 0y1
(...)
   +0x0e0 MappingInfoIndexNode : _RTL_BALANCED_NODE
   +0x0f8 OriginalBase     : 0x00007ffe`e87e0000
   +0x100 LoadTime         : _LARGE_INTEGER 0x01db5f86`2fa735fc
   +0x108 BaseNameHashValue : 0x235bec4
   +0x10c LoadReason       : 0 ( LoadReasonStaticDependency )
   +0x110 ImplicitPathOptions : 0x4000
   +0x114 ReferenceCount   : 1
   +0x118 DependentLoadFlags : 0x800
   +0x11c SigningLevel     : 0 ''

يمكن الحصول على عنوان البنية من خلال اجتياز بنية مرتبطة بشكل مضاعف (doubly-linked) مرجعية في PEB الخاص بالعملية داخل بنية PEB_LDR_DATA.

dt nt!_PEB_LDR_DATA 0xb4b4c3c3

لاحظ العلامة DontCallForThreads. كما يشير الاسم، إذا تم تعيين هذه العلامة، لن يقوم نظام التشغيل باستدعاء DllMain() لهذه الوحدة لأحداث المؤشرات (أي DLL_THREAD_ATTACH أو DLL_THREAD_DETACH).

عند إنشاء وحدة DLL، يجب اتباع القالب التالي للعمل جنبًا إلى جنب مع دوال محمّل نظام التشغيل:

BOOL WINAPI DllMain(
    HINSTANCE hinstDLL,  // handle to DLL module
    DWORD fdwReason,     // reason for calling function
    LPVOID lpvReserved )  // reserved
{
    // Perform actions based on the reason for calling.
    switch( fdwReason ) 
    { 
        case DLL_PROCESS_ATTACH:
         // Initialize once for each new process.
         // Return FALSE to fail DLL load.
            break;

        case DLL_THREAD_ATTACH:
         // Do thread-specific initialization.
            break;

        case DLL_THREAD_DETACH:
         // Do thread-specific cleanup.
            break;

        case DLL_PROCESS_DETACH:
        
            if (lpvReserved != nullptr)
            {
                break; // do not do cleanup if process termination scenario
            }
            
         // Perform any necessary cleanup.
            break;
    }
    return TRUE;  // Successful DLL_PROCESS_ATTACH.
}

تفاصيل تقنية حول التنفيذ

إعداد استدعاء API

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

يتم ذلك عبر تعريف بنية DATA_T في الكومة (heap)، بحيث تظل قابلة للوصول خلال الخطوات المختلفة.

تُعرَّف هذه البنية كما يلي:

typedef struct _DATA_T {
    // LDR structures manipulation
    ULONG_PTR   runner;             // malicious entry point to execute
    ULONG_PTR   bakOriginalBase;    // backup of overwritten OriginalBase
    ULONG_PTR   bakEntryPoint;      // backup of overwritten EntryPoint
    HANDLE      event;              // event signalling that the Runner has executed
    // function call
    ULONG_PTR   ret;                // return value
    DWORD       createThread;       // run this API call in a new thread (required for wininet/winhttp)
    ULONG_PTR   function;           // Windows API to call
    DWORD       dwArgs;             // number of args
    ULONG_PTR   args[MAX_ARGS];     // array of args
} DATA_T, * PDATA_T;

لإعداد تنفيذ API، يجب تجهيز هذه الحقول. قيمة ret هي التي ستجمع القيمة المرتجعة بعد التنفيذ. أما event فيُستخدم للمزامنة، للإشارة إلى اكتمال التنفيذ. جميع الحقول الأخرى هي مدخلات تحدد واجهة API المراد استدعاؤها (function)، وبأي وسائط (dwArgs و args[])، وعنوان دالة Runner() التي يُعاد توجيه التنفيذ إليها، ونسخ احتياطية لإدخالات DLL الأصلية التي تمت الكتابة فوقها (bakOriginalBase و bakEntryPoint).

يجب تعيين حقل createThread إلى 1 لوظائف API المعقدة التي لن تعمل بشكل جيد في إعداد DllMain() (وهذا يشمل العديد من مكتبات wininet و winhttp).

إليك مثال لإعداد استدعاء للدالة MessageBoxA() كما يظهر في الإثبات المفاهيمي (PoC):

 pDataT->dwArgs = 4;
 pDataT->runner = (ULONG_PTR)Runner;
 pDataT->function = (ULONG_PTR)MessageBoxA;
 pDataT->args[0] = (ULONG_PTR)0;
 pDataT->args[1] = (ULONG_PTR)"Hello";
 pDataT->args[2] = (ULONG_PTR)"LDRSHUFFLE";
 pDataT->args[3] = (ULONG_PTR)MB_OKCANCEL;
 pDataT->event = CreateEventA(NULL, FALSE, FALSE, "ExecEvt");

تعديل _LDR_DATA_TABLE_ENTRY

تتولى دالة UpdateLdr() مسؤولية إجراء التعديل الصحيح في _LDR_DATA_TABLE_ENTRY للوحدة الهدف.

ستقوم دالة RestoreLdr() باستعادة تلك التغييرات في مرحلة لاحقة (يتم استدعاؤها بواسطة Runner()).

تحدد هذه الدوال موقع PEB وتجتاز بنى الوحدات لتحديد وحدة DLL الصحيحة وحقولها. في ملفات الرؤوس، أعيد استخدام تعريفات استخدمها Batsec في DarkLoadLibrary، وأشجع القراء على الاطلاع على هذا المشروع ومقال MDSec المرتبط للاستفادة من العمل الرائع الذي قام به حول دواخل تحميل الوحدات في Windows.

ملاحظة: يقوم هذا الإثبات المفاهيمي بتحميل وحدة DLL تضحية (SACRIFICIAL_DLL_NAME) وينفذ تلك التغييرات على هذه الوحدة. ومع ذلك، من الممكن تمامًا تعديل وحدة DLL محمّلة بالفعل. في الواقع، هذا هو الأسلوب المتبع للحقن عبر العمليات. لأغراض الاستقرار، أوصي بتجنب التعامل مع وحدات DLL المهمة مثل ntdll أو kernel32، والتي تميل أيضًا إلى أن تكون أكثر تدقيقًا من قبل حلول الأمان.

التنفيذ

تنزيل الأداة