Skip to content
KitploitKITPLOIT
FerramentasExploitsBlog
Log in
Enviar
FerramentasExploitsBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

FeedsContatoPrivacidade© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
lacuna-rs — Crate Rust para falsificação de pilha de chamadas ghost-frame, chamadas de sistema indiretas em tempo de execução e injeção APC no Windows x64. Fornece resolução SSN, emissão de stubs JIT e criptografia de parâmetros baseada em VEH para evasão de EDR. | Kitploit
Ferramentas/GitHubGitHub/karkas66/lacuna-rs
ShellcodePós-ExploraçãoRed TeamingDesenvolvimento de PayloadsExploração de Binários
GitHubkarkas66/lacuna-rs

lacuna-rs

Crate Rust para falsificação de pilha de chamadas ghost-frame, chamadas de sistema indiretas em tempo de execução e injeção APC no Windows x64. Fornece resolução SSN, emissão de stubs JIT e criptografia de parâmetros baseada em VEH para evasão de EDR.

Ver Repositório
18172há 19 diasRevisado pelo Kitploit

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

lacuna-rs

Spoofing de pilha de chamadas com ghost-frame + syscalls indiretas em runtime para Windows x64 — portado para Rust.

Portado de LACUNA Chain (lacuna_chain.c) por Mohamed Alzhrani (0xmaz).

lacuna-rs é uma crate Rust reutilizável que fornece as mesmas primitivas que a TTP original em C, estruturada para poder ser inserida em qualquer projeto Rust — como wsyscall-rs ou syscalls-rs, mas com resolução de SSN em runtime, direcionamento de syscall;ret por função e spoofing de pilha com ghost-frame.


Crítico: Requisito de Frame-Pointer

A feature stack-spoof falhará silenciosamente se a crate consumidora não for compilada com frame pointers.

As primitivas de stack-stomping em chain.rs localizam o slot do endereço de retorno do chamador via inline asm mov rbp, {x}. Isto requer que a cadeia RBP esteja intacta. O Rust (e a maioria dos compiladores em modo release) omite frame pointers por padrão.

O build.rs define force-frame-pointers=yes para a codegen desta própria crate, mas o Cargo não consegue propagar flags de compilador para crates dependentes. Deve adicionar isto ao seu próprio projeto:```toml

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

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

Sem isso, `stomp_plant()` lerá lixo do RBP e ou não fará nada (melhor caso) ou corromperá a pilha (pior caso). O crate não tem como detectar em tempo de execução se os frame pointers estão habilitados — simplesmente não funcionará.

Se você precisa apenas do scanning, da resolução de SSN ou das primitivas de injeção (sem stack spoofing), você pode omitir a feature `stack-spoof` e este requisito não se aplica.

---

## O que ele faz

| Primitiva | Função C | Módulo Rust |
|---|---|---|
| Análise de seção PE + exportação | `pe_section()`, `pe_export()` | `pe` |
| Varredura de região fantasma `.pdata` | `scan_ghosts()`, `best_ghost()` | `scan` |
| Descoberta de ghost-gadget (`jmp [rbx]`) | `scan_ghost_gadgets()` | `scan` |
| Localizador de lacuna NOP em `win32u` | `win32u_nop_gap()` | `scan` |
| Localizador de âncora BYOUD-MF | `find_mf_target()` | `scan` |
| Resolução de SSN (Hell's Gate / Halo's Gate) | `resolve_ssn()` | `nt` |
| Localizador de `syscall;ret` por função | `find_func_syscall()` | `nt` |
| Emissão de stub de syscall indireta JIT | `alloc_stub()` | `stub` |
| Redirecionamento de stub de ghost-gadget | (em `alloc_stub()`) | `stub` |
| Criptografia de parâmetros VEH + hardware-breakpoint | `param_encrypt_veh()`, `pcrypt_arm()` | `veh` |
| VEH de chain-guard | `chain_veh()` | `veh` |
| Construção de cadeia LACUNA | `build_chain()` | `chain` |
| Stack stomp (BYOUD-RT) | `stomp_plant()`, `stomp_restore()` | `chain` |
| Chain walker (verificação) | `lacuna_walk_chain()` | `chain` |
| Injeção APC baseada em seção | `do_inject_sapc()` | `inject` |

---

## Feature flags```toml
[dependencies]
lacuna-rs = { version = "0.4", features = ["inject", "stack-spoof", "veh"] }

| Recurso | Descrição | Requer frame pointers? | |---|---|---|---| | syscalls (padrão) | Resolução de SSN + emissão de stub JIT | Não | | inject (padrão) | Injeção APC baseada em seção (inject::inject_sapc) | Não | | veh | Criptografia de parâmetros VEH + hardware-breakpoint | Não | | stack-spoof | Cadeia de ghost-frame LACUNA + stack stomp | Sim | | no-std | Modo no_std (experimental) | Não |

Quando nenhum recurso está habilitado, apenas as camadas de scanning/PE/NT estão disponíveis.


Início rápido

Escanear por ghost regions```sh

cargo run --example scan

### Compilar + verificar a cadeia de ghost-frame```sh
cargo run --example verify --features stack-spoof

Injetar shellcode via seção + APC

Prova de injeção Prova de injeção -- o payload foi executado dentro do processo alvo.```sh cargo run --example inject --features inject,stack-spoof,veh -- <sc.bin>

Adicione `--verbose` para habilitar a saída de diagnóstico do VEH (despejos de pilha, impressões de registradores):```sh
cargo run --example inject --features inject,stack-spoof,veh -- <pid> <sc.bin> --verbose

Algoritmo de pontuação de threads

inject_sapc classifica as threads do alvo. O sinal de classificação mais forte é se uma thread possui uma janela:

  • Possui uma janela (thread de GUI/message-pump) — EnumWindows + GetWindowThreadProcessId. Uma thread de GUI estaciona em uma espera alertável em seu loop de mensagens, então um APC enfileirado executa lá primeiro. +1000.
  • Tempo de ciclo — NtQueryInformationThread(ThreadCycleTime); recorre a ThreadTimes quando a classe não está disponível na build em execução (veja examples/tprobe.rs). Normalizado e adicionado.
  • Tempo de CPU — NtQueryInformationThread(ThreadTimes) — tempo de kernel + usuário.
  • Contagem de suspensão — NtQueryInformationThread(ThreadSuspendCount). Uma thread suspensa não pode executar um APC: −2000 por contagem de suspensão.
  • Prioridade — NtQueryInformationThread(ThreadBasicInformation). Prioridade 8–10 recebe +150; prioridade fora do intervalo recebe −300.

Filtragem. Threads suspensas e threads estacionadas em uma espera de kernel não alertável — WrDelayExecution (Sleep/NtDelayExecution) ou WrSuspended, lidas de NtQuerySystemInformation(SystemProcessInformation) — são descartadas de imediato (elas nunca podem receber um APC). O motivo da espera é, fora isso, apenas diagnóstico: é registrado por candidato como State: / Reason: / Alert:, mas não influencia a pontuação, porque KWAIT_REASON não codifica alertabilidade (uma espera de objeto alertável e uma não alertável reportam o mesmo valor — verificado com sondagem no estilo de examples/tprobe.rs).

Os candidatos são ordenados (maior pontuação, desempate por GUI e depois ciclos) e truncados para MAX_APC_CANDIDATES (10) para enumeração/logging.

Enumerar ≠ injetar. O número de threads listadas é desacoplado do número injetado. MAX_APC_CANDIDATES (10) controla quantas são classificadas e registradas; APC_INJECT_THREADS (5) controla quantas realmente recebem o APC.

Por que injetar em várias, depois tentar novamente: o modo usuário não consegue dizer qual thread está em uma espera alertável, e uma única thread escolhida frequentemente nunca entra em uma, então o APC nunca dispararia. inject_sapc portanto enfileira o APC para várias threads e então reenfileira em um loop curto (~80 ms) até que a palavra de gate compartilhada mude de 0 para 1 — ou seja, até que alguma thread alvo realmente execute o payload. Ele registra se isso aconteceu: payload claimed the gate (executou) vs gate NOT claimed.

Por que executar uma vez: o mesmo shellcode/contexto é enfileirado para cada thread, então sem proteção um payload não reentrante executaria concorrentemente e travaria o host (medido: 3 execuções simultâneas). O gate de reentrância (USE_REENTRANCY_GATE, ativado por padrão) faz o corpo do payload executar exatamente uma vez independentemente de quantas threads (ou quantas rodadas de retry) recebam o APC (medido: exatamente 1). Deixe o gate ativado a menos que seu payload seja explicitamente seguro para concorrência.


Usando como biblioteca

Básico: scan + resolução de SSN```rust

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

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

// Scan for ghost regions let mut ghosts = [scan::Ghost::default(); 512]; let n = scan::scan_ghosts(ntdll, &[b"NtAllocateVirtualMemory\0"], &mut ghosts); println!("{} ghost regions in ntdll", n);

Baixar ferramenta