Skip to content
KitploitKITPLOIT
ツールブログ
提出
ツールブログ
提出

ハッキング、侵入テスト、サイバーセキュリティツールをあなたのセキュリティアーセナルに!

Kitploitはハッキング、サイバーセキュリティ、ペネトレーションテストのツールディレクトリです。最新のプロジェクトアップデートを見つけて、脆弱性の発見、システム分析、テストの自動化、セキュリティの強化を行いましょう。

··フィード·お問い合わせ·プライバシー·© 2026 Kitploit

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
lacuna-rs — Windows x64向けのRustクレート: ghost-frame call-stack spoofing、runtime indirect syscalls、APC injectionを提供。SSN resolution、JIT stub emission、VEH-based parameter encryptionを提供し、EDR evasionを実現。 | Kitploit
ツール/GitHubGitHub/karkas66/lacuna-rs
シェルコードポストエクスプロイトレッドチーミングペイロード開発バイナリエクスプロイト
GitHubkarkas66/lacuna-rs

lacuna-rs

Windows x64向けのRustクレート: ghost-frame call-stack spoofing、runtime indirect syscalls、APC injectionを提供。SSN resolution、JIT stub emission、VEH-based parameter encryptionを提供し、EDR evasionを実現。

リポジトリを見る
1811ヶ月前未レビュー

人気

すべて見る →

コミュニティで最も使われているツールを見つけましょう。

すべてのツールを探索

ツールコレクションを閲覧

すべてのツールを見る →
共有

lacuna-rs

Ghost-frame コールスタック偽装 + ランタイム間接システムコール for Windows x64 — Rust に移植済み。

Mohamed Alzhrani (0xmaz) による LACUNA Chain (lacuna_chain.c) からの移植。

lacuna-rs は、再利用可能な Rust クレートであり、元の C TTP と同じプリミティブを提供します。構造化されているため、任意の Rust プロジェクトにドロップインできます。wsyscall-rs や syscalls-rs と似ていますが、ランタイム SSN 解決、関数ごとの syscall;ret ターゲティング、および ghost-frame スタックスプーフィング を備えています。


重要: フレームポインタの要件

stack-spoof 機能は、利用側クレートがフレームポインタ付きでコンパイルされていない場合、サイレントに失敗します。

chain.rs のスタック破壊プリミティブは、mov rbp, {x} インライン asm を介して呼び出し元のリターンアドレススロットを特定します。これには RBP チェーンがそのままである必要があります。Rust(およびほとんどのリリースモードコンパイラ)はデフォルトでフレームポインタを省略します。

build.rs はこのクレート自身のコード生成に対して force-frame-pointers=yes を設定しますが、Cargo はコンパイラフラグをダウンストリームクレートに伝播できません。 自身のプロジェクトに以下を追加する必要があります:

root@kitploit:~
# .cargo/config.toml  (lacuna-rs 内ではなく、YOUR クレート内)
[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

ghost-frame チェーンの構築と検証

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

スレッドスコアリングアルゴリズム

ターゲットプロセスのすべてのスレッドに APC をキューイングする代わりに(同時に多数のスレッドが通知されるとプロセスがクラッシュする可能性がある)、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!("{} ghost regions in 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);

任意の NT API の間接システムコールスタブを生成

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]
// (または build_chain が呼ばれていれば、jmp [ghost_gadget] -> JMP [RBX] -> syscall;ret)
let stub = stub::make_stub(ssn, syscall_ret).expect("stub alloc failed");

// 対応する関数ポインタ型にキャストして呼び出し
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()) };

ghost-frame チェーンの構築 + VEH 登録

root@kitploit:~
// ntdll/kernelbase/wow64/win32u をスキャンしてゴースト領域を探し、
// 6層の偽呼び出しスタックを構築します。G_GHOST_GADGET を設定し、
// スタブが署名付き DLL 内の JMP [RBX] を経由するようにします。
lacuna::chain::build_chain();

// VEH ハンドラの登録 (パラメータ暗号化 + チェーンガード)
let _veh = lacuna::veh::VehGuard::register().expect("VEH registration failed");

// オプション: 実行時に詳細診断を有効化
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();

// syscall;ret に DR0 を設定 — VEH が境界でパラメータを XOR 復号
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 がインジェクションやポストエクスプロイトアクティビティとして相関させる呼び出しを隠すことです。

間接システムコール + ゴーストフレーム + パラメータ暗号化の背後に置くべきもの

これらは EDR がフックして相関させる「クラウン・ジュエル」NT システムコールです:

これらのそれぞれについて:

  1. nt::resolve(ntdll, b"NtXxx\0") で解決
  2. stub::make_stub(ssn, syscall_ret) でスタブを生成
  3. veh::pcrypt_arm(key, syscall_ret, true) で機密パラメータを XOR 暗号化
  4. 呼び出しを chain::stomp_plant() と chain::stomp_restore() でラップ

直接呼び出し可能(ゴーストフレーム不要)

重要な原則

  1. 解決: すべての NT システムコールを nt::resolve(ntdll, b"NtXxx\0") で解決。戻り値は (SSN, syscall_ret_VA)。
  2. 生成: stub::make_stub(ssn, syscall_ret) で JIT スタブを生成。呼び出し可能な関数ポインタを返す。
  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 論文 からの 9 つの主要な貢献すべてがコードに反映されています:

検出対象範囲


なぜ単に syscalls-rs を使わないのか?

syscalls-rs と wsyscall-rs は、特定の Windows ビルドの ntdll から ビルド時の SSN テーブル を生成します。ターゲットマシンが異なるビルドを実行している場合、SSN が間違っており、システムコールは失敗するか(または EDR ヒューリスティックをトリガーします)。

lacuna-rs は ntdll のスタブを直接読み取ることで ランタイム で SSN を解決し、関数自身の syscall;ret 命令をターゲットとするため、RIP はカーネルエントリ時に ntdll 内にあります。これにより、EDR の「SSN 不一致」および「バッキングされていないメモリからの間接システムコール」ヒューリスティックを無効にします。

さらに、lacuna-rs は syscalls-rs が持たない ghost-frame スタックスプーフィング チェーンを提供します。


ビルド要件

  • ターゲット: 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              # stack-spoof の force-frame-pointers を設定
├── src/
│   ├── lib.rs            # クレートルート + 再エクスポート + scan_all() + litcrypt2 セットアップ
│   ├── win.rs            # Win32/NT FFI バインディング (no_std 互換)
│   ├── pe.rs             # PE セクション + エクスポート解析
│   ├── scan.rs           # .pdata ゴースト領域 + ガジェットスキャン
│   ├── nt.rs             # SSN 解決 + syscall;ret ターゲティング
│   ├── stub.rs           # JIT 間接システムコールスタブ生成
│   ├── veh.rs            # VEH + ハードウェアブレークポイントパラメータ暗号化
│   ├── chain.rs          # LACUNA ghost-frame チェーン + スタンプ
│   └── 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 + windows-msvc ターゲット

クレジット

  • オリジナル研究 & C 実装: Mohamed Alzhrani (0xmaz) — LACUNA Chain
  • テクニック: Ghost Frames: Forging Plausible Call Stacks from .pdata Lacunae
  • 最適な APC スレッドロジックの検索: FrankensteinAPCInjection by S12cybersecurity から適応
  • 文字列難読化: litcrypt2 v0.1.3

完全な開示

このプロジェクトは AI チャットボットの積極的な支援を受けました。私は新しい非常に能力の高いオープンソースモデル (Z.ai (Zhipu AI) の GLM-5.2) をテストする機会があり、それに挑戦的なタスクを与えたいと考えました。 学んだ教訓: 人間が結果をどうあるべきか知っている場合はうまく機能しました。そうでない場合は... ただのゴミでした。

ライセンス

MIT

ツールをダウンロード
プリミティブC 関数Rust モジュール
PE セクション + エクスポート解析pe_section(), pe_export()pe
.pdata ゴースト領域スキャンscan_ghosts(), best_ghost()scan
ゴーストガジェット発見 (jmp [rbx])scan_ghost_gadgets()scan
win32u NOP ギャップ検出win32u_nop_gap()scan
BYOUD-MF アンカー検出find_mf_target()scan
SSN 解決 (Hell's Gate / Halo's Gate)resolve_ssn()nt
関数ごとの syscall;ret ロケーターfind_func_syscall()nt
JIT 間接システムコールスタブ生成alloc_stub()stub
ゴーストガジェットスタブリダイレクト(alloc_stub() 内)stub
VEH + ハードウェアブレークポイントパラメータ暗号化param_encrypt_veh(), pcrypt_arm()veh
チェーンガード VEHchain_veh()veh
LACUNA チェーン構築build_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-spoofLACUNA ghost-frame チェーン + スタック破壊はい
no-stdno_std モード (実験的)いいえ
呼び出し機密性の理由
NtOpenProcess別のプロセスへのハンドルを開く — インジェクションの第一歩
NtCreateSection + NtMapViewOfSection (リモート)セクションベースのインジェクションシグネチャ
NtWriteVirtualMemoryプロセス間書き込み — 古典的なインジェクション指標
NtCreateThreadExリモートスレッド作成 — 最高シグナルのインジェクションプリミティブ
NtQueueApcThreadAPC インジェクション — 高シグナル
NtProtectVirtualMemoryRWX 権限変更 — シェルコードステージング指標
NtAllocateVirtualMemory (リモート)リモート割り当て — インジェクションの前段階
NtSetInformationThreadスレッド隠蔽 (HideFromDebugger) — 回避指標
呼び出し安全な理由
NtQueryInformationThreadクエリのみ、めったにフックされず、プロセス間書き込みなし
NtDelayExecutionスリープ — 良性、すべてのアプリケーションで使用
NtCloseハンドルクローズ — 良性、非常に一般的
GetModuleHandleA / GetProcAddressモジュール解決 — システムコールではなく、EDR ユーザーランドフックでフック不可
CreateToolhelp32Snapshot / Thread32First / Thread32Nextスレッド列挙 — kernel32、ntdll システムコールではない
OpenThread / CloseHandle標準ハンドル操作 — kernel32
GetThreadContext / SetThreadContextDR0 に必要 — kernel32、自己プロセスのみ
set_verbose(true)
#論文の概念コードの場所説明
1BYOUD-Gap (ゼロ .pdata 変更)chain.rs — ゴーストフレームチェーン構築RUNTIME_FUNCTION エントリ間のギャップを悪用;アンワインダはそれらをリーフフレームとして扱う (RSP += 8)
2ETW-Ti APC ウィンドウ攻撃inject.rs — NtDelayExecution アラータブルドレインスレッドアラータブル状態を操作することで ETW-Ti APC スタックスナップショットの発火タイミングを制御
3BYOUD コンテキストにおけるパラメータ暗号化veh.rs — pcrypt_arm(), param_encrypt_veh()ステージング時にシステムコールパラメータを XOR 暗号化;syscall 命令でハードウェアブレークポイント VEH 内で復号
4Win32u NOP ギャップチェーン + ゴーストガジェットscan.rs — win32u_nop_gap(), scan_ghost_gadgets()win32u.dll 内の 1,242 個の NOP ギャップがホワイトリスト化されたリーフフレームを提供;ntdll+0xFC47B に JMP [RBX] ゴーストガジェット
5kernelbase 意味的ゴースト近接性chain.rs — L2_kbase レイヤー、VirtualProtect 付近VirtualProtect のエントリポイントで終了する 238 バイトのゴースト — 実際の VP リターンサイトと区別不能
6BYOUD-MF (マシンフレーム RSP テレポート)chain.rs — MachFrame 構造体、scan.rs — find_mf_target()KiUser* ディスパッチャにおける UWOP_PUSH_MACHFRAME (opcode 10) を悪用し、単一フレームで任意の RSP テレポートを実現
7BYOUD-RT (ランタイム RSP 計算)chain.rs — teb_stack_base(), teb_stack_limit()呼び出し時に TEB.StackBase (GS:[0x08]) を読み取って正確なフレーム距離を計算 — 事前キャリブレーション不要
8wow64.dll ゴースト近接性chain.rs — L1_wow64 レイヤー、scan.rs — Wow64PrepareForException をターゲットWow64PrepareForException エントリで終了する 91 バイトのゴースト — チェーンの 4 番目の意味的レイヤー
96 層 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 ウィンドウ攻撃でスナップショットタイミングを制御
パラメータ検査回避HW ブレークポイント VEH 復号
カーネルコールバック一部ハンドル操作は依然として ObRegisterCallbacks を発生させる