Skip to content
KitploitKITPLOIT
OutilsExploitsBlog
Log in
Soumettre
OutilsExploitsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

FluxContactConfidentialité© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
lacuna-rs — Rust crate pour le spoofing de pile d'appels ghost-frame, les appels système indirects à l'exécution, et l'injection APC sur Windows x64. Fournit la résolution SSN, l'émission de stubs JIT, et le chiffrement de paramètres basé sur VEH pour l'évasion EDR. | Kitploit
Outils/GitHubGitHub/karkas66/lacuna-rs
ShellcodePost-ExploitationRed TeamingDéveloppement de Charges UtilesExploitation de Binaires
GitHubkarkas66/lacuna-rs

lacuna-rs

Rust crate pour le spoofing de pile d'appels ghost-frame, les appels système indirects à l'exécution, et l'injection APC sur Windows x64. Fournit la résolution SSN, l'émission de stubs JIT, et le chiffrement de paramètres basé sur VEH pour l'évasion EDR.

Voir le dépôt
18172il y a 18 joursVérifié par Kitploit

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

lacuna-rs

Usurpation de pile d'appels par ghost-frame + syscalls indirects à l'exécution pour Windows x64 — porté en Rust.

Porté depuis LACUNA Chain (lacuna_chain.c) par Mohamed Alzhrani (0xmaz).

lacuna-rs est une crate Rust réutilisable qui fournit les mêmes primitives que le TTP C original, structurée pour pouvoir être intégrée dans n'importe quel projet Rust — comme wsyscall-rs ou syscalls-rs, mais avec résolution des SSN à l'exécution, ciblage syscall;ret par fonction, et usurpation de pile par ghost-frame.


Critique : Exigence de frame-pointer

La fonctionnalité stack-spoof échouera silencieusement si la crate consommatrice n'est pas compilée avec les frame pointers.

Les primitives de stack-stomping dans chain.rs localisent l'emplacement de l'adresse de retour de l'appelant via l'assembleur inline mov rbp, {x}. Cela nécessite que la chaîne RBP soit intacte. Rust (et la plupart des compilateurs en mode release) omet les frame pointers par défaut.

build.rs définit force-frame-pointers=yes pour la génération de code de cette crate elle-même, mais Cargo ne peut pas propager les flags du compilateur aux crates en aval. Vous devez ajouter ceci à votre propre projet :```toml

.cargo/config.toml (in YOUR crate, not in lacuna-rs)

[build] rustflags = ["-C", "force-frame-pointers=yes"]

Sans cela, `stomp_plant()` lira des données corrompues depuis RBP et soit ne fera rien (meilleur cas), soit corrompra la pile (pire cas). Le crate n'a aucun moyen de détecter à l'exécution si les frame pointers sont activés — cela ne fonctionnera tout simplement pas.

Si vous n'avez besoin que du scanning, de la résolution SSN ou des primitives d'injection (sans stack spoofing), vous pouvez omettre la feature `stack-spoof` et cette exigence ne s'applique pas.

---

## Ce qu'il fait

| Primitive | Fonction C | Module Rust |
|---|---|---|
| Analyse des sections PE + exports | `pe_section()`, `pe_export()` | `pe` |
| Scan des ghost-regions `.pdata` | `scan_ghosts()`, `best_ghost()` | `scan` |
| Découverte de ghost-gadgets (`jmp [rbx]`) | `scan_ghost_gadgets()` | `scan` |
| Recherche de NOP-gap `win32u` | `win32u_nop_gap()` | `scan` |
| Recherche d'ancre BYOUD-MF | `find_mf_target()` | `scan` |
| Résolution SSN (Hell's Gate / Halo's Gate) | `resolve_ssn()` | `nt` |
| Localisateur `syscall;ret` par fonction | `find_func_syscall()` | `nt` |
| Émission de stub d'indirect-syscall JIT | `alloc_stub()` | `stub` |
| Redirection de stub ghost-gadget | (dans `alloc_stub()`) | `stub` |
| Chiffrement des paramètres VEH + hardware-breakpoint | `param_encrypt_veh()`, `pcrypt_arm()` | `veh` |
| VEH chain-guard | `chain_veh()` | `veh` |
| Construction de chaîne LACUNA | `build_chain()` | `chain` |
| Stack stomp (BYOUD-RT) | `stomp_plant()`, `stomp_restore()` | `chain` |
| Parcours de chaîne (vérification) | `lacuna_walk_chain()` | `chain` |
| Injection APC basée sur les sections | `do_inject_sapc()` | `inject` |

---

## Feature flags```toml
[dependencies]
lacuna-rs = { version = "0.4", features = ["inject", "stack-spoof", "veh"] }
FonctionnalitéDescriptionNécessite les pointeurs de frame ?
syscalls (par défaut)Résolution SSN + émission de stub JITNon
inject (par défaut)Injection APC basée sur les sections (inject::inject_sapc)Non
vehVEH + chiffrement des paramètres par point d'arrêt matérielNon
stack-spoofChaîne de ghost-frames LACUNA + stack stompOui
no-stdMode no_std (expérimental)Non

Lorsqu'aucune fonctionnalité n'est activée, seules les couches scanning/PE/NT sont disponibles.


Démarrage rapide

Rechercher des régions fantômes```sh

cargo run --example scan

### Construire + vérifier la chaîne de trames fantômes```sh
cargo run --example verify --features stack-spoof

Injection de shellcode via section + APC

Preuve d'injection Preuve d'injection -- la charge utile s'est exécutée à l'intérieur du processus cible.```sh cargo run --example inject --features inject,stack-spoof,veh -- <sc.bin>

Ajoutez `--verbose` pour activer la sortie de diagnostic VEH (dumps de pile, impressions de registres) :```sh
cargo run --example inject --features inject,stack-spoof,veh -- <pid> <sc.bin> --verbose

Algorithme de notation des threads

inject_sapc classe les threads de la cible. Le signal de classement le plus fort est de savoir si un thread possède une fenêtre :

  • Possède une fenêtre (thread GUI/message-pump) — EnumWindows + GetWindowThreadProcessId. Un thread GUI se met en attente alertable dans sa boucle de messages, donc un APC mis en file d'attente s'y exécute en premier. +1000.
  • Temps de cycle — NtQueryInformationThread(ThreadCycleTime) ; se rabat sur ThreadTimes lorsque la classe n'est pas disponible sur la build en cours (voir examples/tprobe.rs). Normalisé et ajouté.
  • Temps CPU — NtQueryInformationThread(ThreadTimes) — temps noyau + utilisateur.
  • Compteur de suspension — NtQueryInformationThread(ThreadSuspendCount). Un thread suspendu ne peut pas exécuter d'APC : −2000 par compteur de suspension.
  • Priorité — NtQueryInformationThread(ThreadBasicInformation). Une priorité 8–10 obtient +150 ; une priorité hors plage obtient −300.

Filtrage. Les threads suspendus et les threads en attente noyau non alertable — WrDelayExecution (Sleep/NtDelayExecution) ou WrSuspended, lus depuis NtQuerySystemInformation(SystemProcessInformation) — sont écartés d'emblée (ils ne peuvent jamais prendre un APC). La raison d'attente est sinon purement diagnostique : elle est journalisée par candidat sous la forme State: / Reason: / Alert:, mais elle n' influence pas le score, car KWAIT_REASON n'encode pas l'alertabilité (une attente d'objet alertable et non alertable rapportent la même valeur — vérifié avec un sondage de style examples/tprobe.rs).

Les candidats sont triés (score le plus élevé, départage GUI puis cycles) et tronqués à MAX_APC_CANDIDATES (10) pour l'énumération/la journalisation.

Énumérer ≠ injecter. Le nombre de threads listés est découplé du nombre injectés. MAX_APC_CANDIDATES (10) contrôle combien sont classés et journalisés ; APC_INJECT_THREADS (5) contrôle combien reçoivent réellement l'APC.

Pourquoi injecter vers plusieurs, puis réessayer : le mode utilisateur ne peut pas déterminer quel thread est en attente alertable, et un seul thread choisi n'y entre souvent jamais, donc l' APC ne se déclencherait jamais. inject_sapc met donc l'APC en file d'attente vers plusieurs threads puis remet en file d'attente dans une courte boucle (~80 ms) jusqu'à ce que le mot de barrière partagé bascule de 0 à 1 — c'est-à-dire jusqu'à ce qu'un thread cible ait réellement exécuté la charge utile. Il journalise si cela s'est produit : payload claimed the gate (exécuté) vs gate NOT claimed.

Pourquoi exécuter une seule fois : le même shellcode/contexte est mis en file d'attente vers chaque thread, donc sans protection une charge utile non réentrante s'exécuterait concurremment et ferait planter l'hôte (mesuré : 3 exécutions simultanées). La barrière de réentrance (USE_REENTRANCY_GATE, activée par défaut) fait que le corps de la charge utile s'exécute exactement une fois quel que soit le nombre de threads (ou le nombre de cycles de nouvelle tentative) qui prennent l'APC (mesuré : exactement 1). Laissez la barrière activée sauf si votre charge utile est explicitement sûre en concurrence.


Utilisation en tant que bibliothèque

Basique : scan + résolution SSN```rust

use lacuna::{scan, nt, win::get_module};

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

Télécharger l’outil