
توليد آلات افتراضية متعددة الأشكال ومستقلة عن الموقع (PIVMs) من شيل كود x86/x64 عشوائي.
اقرأ البحث (مكتوب للإصدار 1.0.0).
mkPIVM هي محاكي افتراضي متعدد الأشكال ومستقل عن الموضع لشل كود ويندوز x86 و x64 (قريبًا لينكس).
قم بتغذيته بشل كود خام. ينتج كتلة خام أخرى: جهاز افتراضي صغير يفسر نسخة مرتفعة ومشفرة عند السكون من تعليماتك الأصلية. الناتج هو كود مستقل عن الموضع بذاته ويعمل في أي مكان يمكن لشل كود الأصلي العمل فيه، من محمل خيوط بعيد إلى منعطف كهف كود. كل مقبض لكل بذرة يختلف بشكل مستقل: عائلة التشفير، تخطيط فتحات السجلات، تبديل opcode إلى المعالج، طوبولوجيا المرسل، نمط القمامة، نقاط إدخال إخفاء IR. بنائان من نفس المدخلات يشتركان في أقل من مئة بايت عشوائي من عشرات الكيلوبايتات.
لماذا: شل كود الأصلي سهل التوقيع. تغليفه في جهاز افتراضي لكل حالة مع تشفير لكل حالة لا يترك شيئًا مفيدًا عند السكون، ورفع التعليمات إلى بايت كود يضع جدارًا آخر بين بايتات القرص وأي مفكك يعرف شكل x86. على حد علمي من مسح الأدبيات، لا توجد أداة عامة تشحن هذا المسار تمامًا: PIC خام في، PIC خام متعدد الأشكال للجهاز الافتراضي خارج. لذا، ذكرت ذلك في البحث الذي تطلبه. بصراحة، إذا كنت على صواب بأن لا أحد فعل هذا (علنًا) من قبل، وأنا واثق جدًا، أنا مندهش. على أي حال، استمتع.
mkpivm.exe shellcode.bin --arch x64 -o out.bin
جهاز PIVM جاهز وساخن. هذا هو أبسط مسار. تختلف عدة أوضاع أخرى في مدى عدوانية افتراضية التعليمات الأصلية، وما إذا كان الناتج عبارة عن كتلة مستقلة أو PE معدّل، وما إذا كان الرفع يعمل على الإطلاق.
# عرض توضيحي
لدي الأدلة. يمكنك مشاهدة فيديو لـ mkPIVM أثناء العمل أدناه، وهو يقوم بافتراضية كاملة لمخزن Meterpreter (عادي بالمناسبة)، ويحقنه في explorer.exe، ونلتقط رد الاتصال. بالطبع هذا مجرد مثال، ويمكن تطبيق mkPIVM على أكثر من ذلك بكثير، بافتراض أن التعليمات الموجودة في الشيل كود مدعومة. إذا لم تكن مدعومة، افتح مشكلة، أرسل لي الشيل كود، أنا معك.
شاهده [هنا](https://github.com/D7EAD/mkPIVM/raw/refs/heads/main/media/mkpivm-showcase.mp4). مستضاف في ./media، للأسف لا يمكن تضمينه.
إليك تقرير VirusTotal لهذه العينة الافتراضية بالضبط (حتى 06/04/2026).
<img src="https://assets.kitploit.com/production/public/readmes/7466/3f4a6dbe2777c02fb32f71749a5b1fa2aa324cb0dac2f77d5681bbe3a4e17a81.png">
...والنسخة المضغوطة، غير الافتراضية، ذات إنتروبيا أعلى بشكل ملحوظ.
<img src="https://assets.kitploit.com/production/public/readmes/7466/47f68372e31a2c24fa49eb71648adbdf8944977db90d645df337125c1bdfa8e3.png">
إليك نتائج إشارة Cobalt Strike عادية للمقارنة.
<img src="https://assets.kitploit.com/production/public/readmes/7466/76e2107589cd2b1b65c846a671aed173aa5e6d89630f5e9d283d99c546a2d566.png">
تم الاهتمام الدقيق بإنتروبيا مخرجات هذه الأداة، مما ينتج شيل كود بإنتروبيا أقل من مكتبات Windows WinAPI DLL النموذجية (خارج وضع التعبئة)، مثل ntdll.dll أو kernel32.dll. مقارنة الإنتروبيا تقريبًا...
| الملف | البايت | الإنتروبيا |
|------|-------|---------|
| `p_m64.bin` | 3,969 | **7.1181** |
| `msvcrt.dll` | 699,888 | 6.5319 |
| `wininet.dll` | 2,724,528 | 6.4934 |
| `shell32.dll` | 7,839,992 | 6.3639 |
| `kernel32.dll` | 836,232 | 6.3597 |
| `crypt32.dll` | 1,538,632 | 6.3010 |
| `rpcrt4.dll` | 1,162,672 | 6.2405 |
| `ntdll.dll` | 2,522,104 | 6.1934 |
| `v.bin` | 29,229 | **6.0442** |
## نظرة سريعة على الأوضاع
| الوضع | العلم | التغييرات |
|------|-------|--------------|
| Default | لا شيء | رفع المدخلات بالكامل. كل شيء ظاهري. |
| Packer | `--pack` | لا ترفع. لفّ المدخلات كبيانات مشفرة، فك التشفير في وقت التشغيل، اقفز إليها. |
| Hybrid | `--ranges A:B,...` | ارفع نطاقات البايت المختارة فقط. الباقي يبقى أصليًا. |
| Stacked | `--pack --ranges A:B` | أنشئ الكتلة الهجينة، ثم لفّها بالتعبئة. |
| Detour | `--embed-into PE --at RVA` | خذ كتلة مبنية مسبقًا، ضعها في PE، وصّل قفزة jmp في RVA المختارة. |
| Scan | `--scan` | اطبع مرشحي `--ranges` من CFG للمدخلات، ثم اخرج. |
| RX | `--rx` | كتلة PAGE_EXECUTE_READ. تبقى جزيرة البيانات مشفرة عند السكون؛ محلل PEB في الكتلة يحل VirtualProtect، يفك التشفير في مكانه عند state_init. |
| RX مع محمّل | `--rx --rx-loader-vp` | مثل `--rx` ولكن المحمّل يمرر VirtualProtect كأول وسيط للكتلة. لا محلل PEB. |
كل وضع يحترم `--seed` و `--arch` و `--input-format` و `--format`. انظر أقسام كل وضع أدناه لخط أنابيب البناء وتدفق وقت التشغيل.
## الافتراضية الافتراضية
يمر الرافع عبر CFG بأكمله ويخفض كل تعليمة إلى IR مخصص. يمر IR عبر تمريري تشويش، ثم عبر برامج ترميز تشفر كل تعليمة إلى شكل البايت كود الخاص بالبذرة. يتم تشفير جدول الكتل وجدول المعالجات وجزيرة البيانات بنفس تشفير الدفق لكل بايت مثل البايت كود. في وقت التشغيل، يفك المقدمة تلك المناطق الثلاثة في مكانها، وتقوم حلقة المرسل بجلب بايتات البايت كود واحدًا تلو الآخر، وفك التشفير والإرسال إلى معالج يقوم بالعمل.
### خط أنابيب البناء
الخطوات التي يقوم بها البناء لتحويل الشيل كود الخام إلى الكتلة الافتراضية المنبعثة، من البداية إلى النهاية. _جميع الرسوم البيانية أدناه تنطبق على الإصدار 1.0.0، وقد تغيرت منذ ذلك الحين، لكن الفكرة نفسها._```mermaid
flowchart TB
A[shellcode.bin] --> CFG[CFGBuilder: identify blocks via Zydis disasm + recursive descent]
SEED[seed u64] --> VMC[VMConfig: pick cipher kind, reg perm, opcode map, dispatcher topology]
CFG --> LIFT[LifterRegistry: lower each block to IR]
LIFT --> RBT[resolve_branch_targets: link BR_CC/BR/CALL_VM/LOOP_DEC to target_block_id; synthesize JMP_NATIVE block for any out-of-range jcc]
RBT --> OBF1[obfuscate_ir_dead_inject: 20% per insn-gap, IMM Tmp2/Tmp3 random]
OBF1 --> OBF2[obfuscate_ir_opaque_predicates: 25% per block, split block with IMM Tmp3=0 + TEST + BR_CC NZ random_block, never taken]
OBF2 --> ENC[BytecodeBuilder: each codec emits its variant for this seed]
ENC --> CDATA[compact data island: bytes not covered by any CFG block]
CDATA --> PROMO[promote LEA-fixup target VAs back into data island if CFG put them in code]
ENC --> BTAB[build block table: va_off to bytecode_off pairs]
PROMO --> ECIPH[encrypt data island with cipher_init]
BTAB --> ECIPH2[encrypt block table with cipher_init]
ENC --> ECIPH3[encrypt bytecode per-block with cipher_init reset at each block start]
VMC --> STUB[VMCodeGen::emit_full: prologue, state init, dispatcher tail, handlers, sbox_inv, exit handler]
STUB --> HTAB[handler table: 256 entries, each a 32-bit offset from handler_base; encrypted at rest]
ECIPH --> ASM[finalize: stub + trampolines + sbox_inv + bytecode + data island + block table]
ECIPH2 --> ASM
ECIPH3 --> ASM
HTAB --> ASM
ASM --> OUT[out.bin]