mcpField
R
reverse-engineering-rust-malware

reverse-engineering-rust-malware

github.com/mukul975セキュリティ35.2k96 回インストール8 週間前に更新
リポジトリ

reverse-engineering-rust-malware について

Rust製マルウェアを調査する、許可を得たセキュリティ分析者向けのリバースエンジニアリングスキルです。Rustバイナリのメタデータや文字列、依存関係、コードパターンを扱います。

主な機能

  1. 01Rustバイナリのメタデータ分析
  2. 02crate依存関係の抽出
  3. 03Rust文字列の解析
  4. 04エントリーポイントと中核ロジックの特定
  5. 05暗号化・通信・永続化コードの調査

活用シーン

  1. 01管理された環境でのRust製マルウェア分析
  2. 02許可を得たリバースエンジニアリング評価
  3. 03Rustバイナリ内のマルウェア機能の特定

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/mukul975/anthropic-cybersecurity-skills --skill reverse-engineering-rust-malware

インストール後、Claude Code で/reverse-engineering-rust-malwareを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

LICENSE
assets/
template.md
references/
api-reference.md
standards.md
workflows.md
scripts/
agent.py

詳細

Rust マルウェアのリバースエンジニアリング

概要

Rust は、クロスコンパイルに対応し、メモリ安全性が保証され、リバースエンジニアにとって解析が複雑になることから、マルウェア開発でますます広く使われるようになっています。Rust のバイナリには標準ライブラリ全体が静的リンクされるため、ボイラープレートコードを大量に含む大きなバイナリが生成されます。主な課題として、ヌル終端されない文字列(Rust ではポインターと長さを持つファットポインターを使用)、モノモーフィゼーションによるジェネリックコードの重複生成、複雑なエラー処理(Result/Option の unwrap チェーン)、そしてなじみのない呼び出し規約が挙げられます。Rust を C に逆コンパイルしても、C/C++ のバイナリと比べて有用な出力は得られません。クレート抽出用の Ghidra スクリプトや、Rust 固有のパターンに重点を置いたトレーニング(2024-2025)が、こうした課題への対処に役立ちます。代表的な Rust マルウェアには、BlackCat/ALPHV ランサムウェア、Hive ランサムウェアの亜種、Buer Loader があります。

使用する場面

  • Rust マルウェアのリバースエンジニアリングを含む、許可されたセキュリティテストを実施する場合
  • 管理された環境でマルウェアサンプルや攻撃の痕跡を分析する場合
  • レッドチーム演習やペネトレーションテストを実施する場合
  • 攻撃手法の理解に基づいて検出機能を構築する場合

前提条件

  • IDA Pro 8.0+ または Ghidra 11.0+
  • 参照用コンパイルのための Rust ツールチェーン
  • ヘルパースクリプト用の Python 3.9+
  • Rust のメモリモデル(所有権、借用)に関する理解
  • Rust の文字列型(String、&str、CString)に関する知識

ワークフロー

ステップ 1:Rust バイナリのメタデータを特定して解析する
#!/usr/bin/env python3
"""Analyze Rust malware binary metadata and extract crate dependencies."""
import re
import sys
import json


def identify_rust_binary(data):
    """Check if binary is Rust-compiled and extract version info."""
    indicators = {
        "rust_panic_strings": bool(re.search(rb'panicked at', data)),
        "rust_unwrap": bool(re.search(rb'called.*unwrap.*on.*None', data)),
        "core_panic": bool(re.search(rb'core::panicking', data)),
        "std_rt": bool(re.search(rb'std::rt::lang_start', data)),
        "cargo_path": bool(re.search(rb'\.cargo[/\\]registry', data)),
        "rustc_version": None,
    }

    version = re.search(rb'rustc\s+(\d+\.\d+\.\d+)', data)
    if version:
        indicators["rustc_version"] = version.group(1).decode()

    is_rust = sum(1 for v in indicators.values() if v) >= 2
    return is_rust, indicators


def extract_crates(data):
    """Extract Rust crate (dependency) names from binary strings."""
    crate_pattern = re.compile(
        rb'(?:crates\.io-[a-f0-9]+/|\.cargo/registry/src/[^/]+/)'
        rb'([\w-]+)-(\d+\.\d+\.\d+)'
    )
    crates = {}
    for match in crate_pattern.finditer(data):
        name = match.group(1).decode()
        version = match.group(2).decode()
        crates[name] = version

    # Also check for common malware-relevant crates
    suspicious_crates = {
        "reqwest": "HTTP client",
        "hyper": "HTTP library",
        "tokio": "Async runtime",
        "aes": "AES encryption",
        "chacha20": "ChaCha20 encryption",
        "rsa": "RSA encryption",
        "ring": "Crypto library",
        "base64": "Base64 encoding",
        "winapi": "Windows API bindings",
        "winreg": "Registry access",
        "sysinfo": "System information",
        "screenshots": "Screen capture",
        "clipboard": "Clipboard access",
        "keylogger": "Key logging",
    }

    capabilities = []
    for crate_name, description in suspicious_crates.items():
        if crate_name in crates:
            capabilities.append({
                "crate": crate_name,
                "version": crates[crate_name],
                "capability": description,
            })

    return crates, capabilities


def extract_rust_strings(data):
    """Extract strings handling Rust's non-null-terminated format."""
    # Rust strings are stored as pointer+length, but string literals
    # are often in .rodata as contiguous sequences
    strings = []
    ascii_pattern = re.compile(rb'[\x20-\x7e]{8,500}')
    for match in ascii_pattern.finditer(data):
        s = match.group().decode('ascii')
        # Filter for malware-relevant strings
        keywords = ['http', 'socket', 'encrypt', 'decrypt', 'shell',
                    'exec', 'cmd', 'upload', 'download', 'persist',
                    'registry', 'mutex', 'pipe', 'inject']
        if any(kw in s.lower() for kw in keywords):
            strings.append(s)

    return strings


if __name__ == "__main__":
    if len(sys.argv) < 2:
        print(f"Usage: {sys.argv[0]} <rust_binary>")
        sys.exit(1)

    with open(sys.argv[1], 'rb') as f:
        data = f.read()

    is_rust, indicators = identify_rust_binary(data)
    print(f"[{'+'if is_rust else '-'}] Rust binary: {is_rust}")
    print(json.dumps(indicators, indent=2, default=str))

    crates, capabilities = extract_crates(data)
    print(f"\n[+] Crates ({len(crates)}):")
    for name, ver in sorted(crates.items()):
        print(f"  {name} v{ver}")

    if capabilities:
        print(f"\n[!] Suspicious capabilities:")
        for cap in capabilities:
            print(f"  {cap['crate']} -> {cap['capability']}")

    strings = extract_rust_strings(data)
    if strings:
        print(f"\n[+] Suspicious strings ({len(strings)}):")
        for s in strings[:20]:
            print(f"  {s}")

検証基準

  • バイナリが Rust でコンパイルされたものとして正しく識別され、バージョン情報も確認できる
  • クレート依存関係が抽出され、マルウェアの機能が明らかになる
  • Rust 固有の文字列抽出でファットポインター形式に対応できる
  • メインエントリーポイントと中核ロジックの関数が特定される
  • 暗号化、ネットワーク通信、永続化のコードが特定される

参考資料

コメント