
مُخطِّط PE انعكاسي ومحرك stomping للوحدات مُحصَّن ضد التهرب لنظام Windows x64
مُخطِّط PE انعكاسي بسيط ومحرك استبدال وحدات (module stomping) لنظام Windows x64، مبني حول واجهة IPlugin نظيفة. يقوم بتخطيط DLL من مخزن بايتات في الذاكرة، ويحل الصادرات (exports)، ويستدعي دوال الإضافة — إما من ذاكرة مجهولة (تحميل انعكاسي كلاسيكي) أو من داخل DLL تضحية مُحمَّلة بشكل شرعي (استبدال الوحدات).
مسار استبدال الوحدات مُحصَّن ضد الكشف: حمايات لكل قسم (بدون RWX)، تنظيف التخطيط الخاص، استعادة البايتات الأصلية، وتنظيف الكومة (heap scrubbing). عمليات الفحص بعد التنظيف باستخدام pe-sieve وMoneta وhollows_hunter وBeaconEye وYARA تُرجع صفر نتائج على الوحدة المستبدلة.
يتطلب CMake 3.15+ وإما MSVC أو Clang أو MinGW على Windows.
# Configure (defaults to Release)
cmake -B build -G Ninja
# Build
cmake --build build
# The build produces:
# build/Modules/CmdPlugin/cmdplugin.dll (example plugin)
# build/Testing/harness.exe (test harness)
لإنشاء إصدار Debug مع مخرجات تشخيصية كاملة:
cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug
cmake --build build
.\harness.exe cmdplugin.dll whoami
يعيّن الإضافة إلى ذاكرة مُخصصة عبر VirtualAlloc. لا يوجد إدخال في PEB، ولا إشعار للمُحمّل.
.\harness.exe cmdplugin.dll whoami --stomp xpsservices.dll
.\harness.exe cmdplugin.dll "dir C:\" --stomp mscms.dll
يحمّل DLL القرباني بشكل مشروع عبر LoadLibrary، ثم يستبدل قسم .text الخاص به بالإضافة كصورة متجاورة. يحدث التنفيذ من مساحة عنوان DLL القرباني — حيث تُنسب مكدسات الاستدعاء وقوائم الوحدات الكود إلى الوحدة القربانية.
يتوقف المشغّل مؤقتًا بعد التنظيف حتى تتمكن من تشغيل ماسحات الذاكرة ضد العملية.
1. MapImage(plugin) private reflective mapping
2. LoadLibrary(sacrificial) legitimate load, PEB entry
3. Save original .text bytes for later restoration
4. Copy plugin image -> .text contiguous image preserves RIP-relative offsets
5. Relocate stomped code fix addresses for new base
6. Patch entry point mov eax,1; ret (safe FreeLibrary)
7. Per-section protections RX / R / RW per section (never RWX)
8. Resolve exports from private mapping, return stomped addresses
9. Free private mapping eliminates floating PE artifact
10. Execute plugin code runs inside "sacrificial.dll"
11. Restore original .text bytes sacrificial code back in place
12. FreeLibrary(sacrificial) unloads the module
13. LoadLibrary(sacrificial) fresh load = clean file-backed pages
14. Scrub heap buffers zero saved bytes + raw DLL data
بعد التنظيف، تصبح DLL القربانية غير قابلة للتمييز عن وحدة نمطية محمّلة بشكل طبيعي. الصفحات مدعومة بالملفات (وليست خاصة)، والمحتوى يطابق الملف الموجود على القرص، ولا تبقى أي آثار PE على الكومة.
| IOC | التخفيف |
|---|---|
| مناطق ذاكرة RWX | حمايات لكل قسم: .text RX، .rdata R، .data RW |
| ذاكرة تنفيذية خاصة (PE عائم) | VirtualFree للتعيين الخاص بعد حل التصدير |
| كود وحدة نمطية معدّل | استعادة بايتات .text الأصلية، ثم FreeLibrary + LoadLibrary للحصول على صفحات نظيفة مدعومة بالملفات |
| رؤوس PE على الكومة | memset(0) لمخزن DLL الخام والبايتات المحفوظة قبل التحرير |
| انهيار DllMain عند الإلغاء | تم تصحيح نقطة الدخول إلى mov eax,1; ret قبل الطمس |
ReflectivePluginLoader/
├── CMakeLists.txt
├── Include/
│ ├── IPlugin.h Plugin ABI (TaskApi, IPlugin)
│ ├── ReflectiveLoaderEngine.h PE mapper + export resolver
│ └── StompedLoaderEngine.h Module stomping engine
├── Modules/
│ └── CmdPlugin/
│ ├── cmdplugin.cpp Command execution plugin
│ └── CMakeLists.txt
├── Testing/
│ ├── main.cpp Test harness
│ └── CMakeLists.txt
└── Tools/
└── file2hex.py DLL to C byte array converter
Modules/ وقم بتضمين IPlugin.h.IPlugin:#include "IPlugin.h"
class MyPlugin : public IPlugin {
public:
void init() const override { /* setup */ }
void execute(TaskApi* task) const override { /* work */ }
void cleanup() const override { /* tear */ }
};
صدّر نقاط الدخول الخمس (create_plugin، destroy_plugin، plugin_init، plugin_exec، plugin_cleanup). استخدم HeapAlloc + placement new لتخصيص آمن مع CRT.
أضف CMakeLists.txt وسجّله في الجذر باستخدام add_subdirectory().
يجب أن يكون قسم .text في DLL القرباني أكبر من حجم الصورة الافتراضية للإضافة. يجب ألا يكون مستخدمًا بشكل نشط من قبل العملية أو خاضعًا لفحص السلامة في وقت التشغيل.
مرشحون جيدون: xpsservices.dll (1.8 MB .text)، mscms.dll، colorui.dll، npmproxy.dll
مرشحون سيئون: ntdll.dll، kernel32.dll (مستخدم بشكل نشط)، clr.dll (خاضع لفحص السلامة)
.text القربانيهذا الإصدار هو إعادة كتابة من الصفر لإثبات المفهوم الأصلي:
StompedLoaderEngine.h) — سحق الصورة المتجاورة مع تنظيف تهرب كامل.text RX، .rdata R، .data RW؛ لا مزيد من مناطق RWXFreeLibrary + LoadLibrary تستبدل الصفحات المُخصَّصة بصفحات نظيفة مدعومة بالملفات.text الأصلي المحفوظ يتم تصفيرهما قبل نافذة الفحصmov eax,1; ret يمنع انهيار DllMain أثناء FreeLibraryVirtualFree للتعيين الانعكاسي بعد حل التصدير (يزيل PE العائم)ReflectiveLoaderEngine.h) — تعيين مباشر من مخزن الإدخال، بدون نسخة VirtualAlloc وسيطةIPlugin.h) — إزالة المساعدات الميتة (BeaconCout، CStrLenA، PluginAlloc، PluginFree)main.cpp) — ترجمة شرطية عبر NDEBUG؛ إصدارات Release تعرض فقط مخرجات الأوامر وأوامر الفحص-nostartfiles لـ DLL الإضافات (بدون CRT في الكود المحمّل انعكاسيًا)