Skip to content
KitploitKITPLOIT
ツールエクスプロイトブログ
Log in
提出
ツールエクスプロイトブログ
提出

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

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

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

ツールディレクトリ

カテゴリ

すべてのカテゴリを見る
Loading categories
DInvoke_rs — 動的に任意のアンマネージドコードを呼び出す | Kitploit
ツール/GitHubGitHub/kudaes/dinvoke_rs
IDS/IPS回避シェルコードポストエクスプロイトバイナリ解析レッドチーミングペイロード開発
GitHubkudaes/dinvoke_rs

DInvoke_rs

動的に任意のアンマネージドコードを呼び出す

リポジトリを見る
36643153ヶ月前Kitploit レビュー済み

人気

すべて見る →

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

すべてのツールを探索

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

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

DInvoke_rs

DInvoke_rs は Dinvoke の Rust 移植版です。DInvoke_rs は、PE パース、動的なエクスポート関数の解決、実行時の PE プラグインの動的ロード、API フック回避など、さまざまな目的に使用できます。

機能:

  • Rust から未公開の Windows API を動的に解決・呼び出します。
  • 戦略的な API フック回避を可能にするプリミティブ。
  • 間接システムコール。 x64 のみ
  • ディスクまたはメモリから直接 PE モジュールを手動でマッピングします。
  • PE ヘッダーのパース。
  • PE モジュールをディスク上の任意のモジュールにバックされたセクションにマッピングします。 Opsec 非対応
  • マップされた PE を隠すためのモジュール変動(並行処理対応)。 Opsec 非対応
  • 例外フィルタとハードウェアブレークポイントによるシステムコールパラメータのスプーフィング。 x64 のみ
  • モジュールスタンピングとシェルコード変動。
  • テンプレートスタンピング。

クレジット

このツールのオリジナル C# 実装の作成者にすべての功績があります:

  • The Wover
  • FuzzySec (b33f)
  • cobbr

目次

  • エクスポートされた関数の解決
  • アンマネージコードの動的呼び出し
  • 間接システムコールの実行
  • ディスクまたはメモリから PE を手動マッピング
  • メモリセクションのオーバーロード
  • モジュール変動
  • ハードウェアブレークポイントを使用したシステムコールパラメータのスプーフィング
  • モジュールスタンピングとシェルコード変動
  • テンプレートスタンピング

使い方

以下の行を cargo.toml に追加して、このクレートをプロジェクトにインポートします:```rust [dependencies] dinvoke_rs = "0.2.2"

# 使用例
## エクスポートされたAPIの解決

以下の例は、DInvoke_rsを使用してDLL(この場合は`ntdll.dll`)のエクスポートを動的に検索して呼び出す方法を示しています。

1) ntdllのベースアドレスを取得します。
2) `get_function_address()`を使用して、`ntdll.dll`内のエクスポートを名前で検索します。これは、DLLのEATを走査して解析することで実現されます。
3) `get_function_address_by_ordinal()`を呼び出すことで、オーディナル(序数)でエクスポートを検索することもできます。```rust

fn main() {

    // Dynamically obtain ntdll.dll's base address. 
    let ntdll = dinvoke_rs::dinvoke::get_module_base_address("ntdll.dll");

    if ntdll != 0 
    {
        println!("ntdll.dll base address is 0x{:X}", ntdll);
        
        // Dynamically obtain the address of a function by name.
        let nt_create_thread = dinvoke_rs::dinvoke::get_function_address(ntdll, "NtCreateThread");
        if nt_create_thread != 0
        {
            println!("NtCreateThread is at address 0x{:X}", nt_create_thread);
        }

        // Dynamically obtain the address of a function by ordinal.
        let ordinal_8 = dinvoke_rs::dinvoke::get_function_address_by_ordinal(ntdll, 8);
        if ordinal_8 != 0 
        {
            println!("The function with ordinal 8 is located at addresss 0x{:X}", ordinal_8);
        }
    }   
}

アンマネージドコードの呼び出し

以下の例では、DInvoke_rs を使用して RtlAdjustPrivilege を動的に呼び出し、現在のプロセスのトークンに対して SeDebugPrivilege を有効にします。この種の実行は、Win32 に存在する API フックをバイパスします。また、最終的な PE の Import Address Table にエントリを作成しないため、実行せずに PE の動作を検出することがより困難になります。```rust

fn main() {

// Dynamically obtain ntdll.dll's base address. 
let ntdll = dinvoke_rs::dinvoke::get_module_base_address("ntdll.dll");

if ntdll != 0 
{
    unsafe 
    {
        let func_ptr:  unsafe extern "system" fn (u32, u8, u8, *mut u8) -> i32; // Function header available at data::RtlAdjustPrivilege
        let ret: Option<i32>; // RtlAdjustPrivilege returns an NSTATUS value, which in Rust can be represented as an i32
        let privilege: u32 = 20; // This value matches with SeDebugPrivilege
        let enable: u8 = 1; // Enable the privilege
        let current_thread: u8 = 0; // Enable the privilege for the current process, not only for the current thread
        let e = u8::default(); // https://github.com/Kudaes/rust_tips_and_tricks/tree/main#transmute
        let enabled: *mut u8 = std::mem::transmute(&e); 
        dinvoke_rs::dinvoke::dynamic_invoke!(ntdll,"RtlAdjustPrivilege",func_ptr,ret,privilege,enable,current_thread,enabled); 

        match ret {
            Some(x) => 
            	if x == 0 { println!("NTSTATUS == Success. Privilege enabled."); } 
              	else { println!("[x] NTSTATUS == {:X}", x as u32); },
            None => panic!("[x] Error!"),
        }
    } 
}   

}

## 間接システムコールの実行
次の例では、DInvoke_rs を使用して `NtQueryInformationProcess` 関数に対応するシステムコールを実行します。`execute_syscall!()` マクロは目的のシステムコールを実行するために必要なシェルコードを動的に割り当てて実行するため、`ntdll.dll` 内に存在するすべてのフックがバイパスされます。割り当てられたメモリはシステムコールが戻ると解放され、実行権限を持つメモリページが恒久的に存在することを回避します。```rust

use std::mem::size_of;
use windows::Win32::System::Threading::{GetCurrentProcess, PROCESS_BASIC_INFORMATION};
use dinvoke_rs::data::{NtQueryInformationProcess, PVOID};

fn main() {

    unsafe 
    {
        let function_type:NtQueryInformationProcess;
        let ret: Option<i32>; //NtQueryInformationProcess returns a NTSTATUS, which is a i32.
        let handle = GetCurrentProcess();
        let p = PROCESS_BASIC_INFORMATION::default();
        let process_information: PVOID = std::mem::transmute(&p); 
        let r = u32::default();
        let return_length: *mut u32 = std::mem::transmute(&r);
        dinvoke_rs::dinvoke::execute_syscall!(
            "NtQueryInformationProcess",
            function_type,
            ret,
            handle,
            0,
            process_information,
            size_of::<PROCESS_BASIC_INFORMATION>() as u32,
            return_length
        );

        let pbi: *mut PROCESS_BASIC_INFORMATION;
        match ret {
            Some(x) => 
                if x == 0 {
                    pbi = std::mem::transmute(process_information);
                    let pbi = *pbi;
                    println!("The Process Environment Block base address is 0x{:X}", pbi.PebBaseAddress as u64);
                },
            None => println!("[x] Error executing direct syscall for NtQueryInformationProcess."),
        }  

    }
}

手動PEマッピング

この例では、DInvoke_rsを使用して、EDRフックを含まないクリーンなntdll.dllのコピーを手動でマッピングします。その後、そのクリーンなntdll.dllのコピーを使用して、任意の関数を実行できます。

この手動マッピングはメモリからも実行でき(その場合はmanually_map_module()を使用)、古典的なリフレクティブDLLインジェクションを実行できます。```rust

use dinvoke_rs::data::PeMetadata;

fn main() {

unsafe 
{

    let ntdll: (PeMetadata, usize) = dinvoke_rs::manualmap::read_and_map_module(r"C:\Windows\System32\ntdll.dll", true, false).unwrap();

    let func_ptr:  unsafe extern "system" fn (u32, u8, u8, *mut u8) -> i32; // Function header available at data::RtlAdjustPrivilege
    let ret: Option<i32>; // RtlAdjustPrivilege returns an NSTATUS value, which is an i32
    let privilege: u32 = 20; // This value matches with SeDebugPrivilege
    let enable: u8 = 1; // Enable the privilege
    let current_thread: u8 = 0; // Enable the privilege for the current process, not only for the current thread
    let e = u8::default();
    let enabled: *mut u8 = std::mem::transmute(&e); 
    dinvoke_rs::dinvoke::dynamic_invoke!(ntdll.1,"RtlAdjustPrivilege",func_ptr,ret,privilege,enable,current_thread,enabled);

    match ret {
        Some(x) => 
            if x == 0 { println!("NTSTATUS == Success. Privilege enabled."); } 
            else { println!("[x] NTSTATUS == {:X}", x as u32); },
        None => panic!("[x] Error!"),
    }

}

}

## メモリセクションのオーバーロード
次のサンプルでは、DInvoke_rs を使用してファイルバッキングされたメモリセクションを作成し、その後 PE を手動でマッピングしてオーバーロードします。メモリセクションは、デフォルトでは `%WINDIR%\System32\` にある正当なファイルを指しますが、他のデコイモジュールを使用することもできます。

このオーバーロードは、メモリから PE をマッピングして実行することもできます(次の例に示すとおり)。これにより、ペイロードをディスクに書き込むことなくオーバーロードを実行できます。```rust

use dinvoke_rs::data::PeMetadata;

fn main() {

    unsafe 
    {

        let payload: Vec<u8> = your_download_function();
ツールをダウンロード