mcpField
R
reverse-engineering-ransomware-encryption-routine

reverse-engineering-ransomware-encryption-routine

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

reverse-engineering-ransomware-encryption-routine について

管理された環境でランサムウェアの暗号化処理を調べる、許可を得たセキュリティ研究者向けのリバースエンジニアリング手順です。アルゴリズムや鍵生成、暗号化の流れを分析し、復号の可能性を評価します。

主な機能

  1. 01暗号アルゴリズムと API の特定
  2. 02ファイル暗号化フローの分析
  3. 03鍵生成と IV の調査
  4. 04対象ファイルの傾向と拡張子の抽出
  5. 05実装上の欠陥と復号可能性の評価

活用シーン

  1. 01サンドボックスでのランサムウェア検体分析
  2. 02許可を得た侵入テストやレッドチーム演習
  3. 03攻撃手法に基づく検知機能の構築

インストール

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

$npx skills add https://github.com/mukul975/anthropic-cybersecurity-skills --skill reverse-engineering-ransomware-encryption-routine

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

同梱ファイル

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

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

詳細

ランサムウェアの暗号化ルーチンのリバースエンジニアリング

概要

最新のランサムウェアは、ファイルの暗号化に対称アルゴリズム(AES-256-CBC/CTR、ChaCha20、Salsa20)を、鍵の保護に非対称アルゴリズム(RSA-2048/4096、Curve25519)を組み合わせたハイブリッド暗号化を使用します。通常、暗号化ルーチンはファイルごとにランダムな対称鍵を生成し、ファイルの内容を暗号化した後、攻撃者が埋め込んだ公開鍵で対称鍵を暗号化します。これらのルーチンをリバースエンジニアリングすると、具体的なアルゴリズム、鍵導出方法、初期化ベクトル、ファイルの標的パターン、身代金を支払わずに復号できる可能性のある実装上の欠陥を特定できます。代表的な例には、Rhysida(AES-256-CTR + RSA-4096)、Qilin.B(AES-256-CTR。AES-NI または ChaCha20 にフォールバック)、Medusa(AES-256 + RSA)があります。

使用する場面

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

前提条件

  • 静的逆アセンブル用の IDA Pro または Ghidra
  • 動的デバッグ用の x64dbg/WinDbg
  • pycryptodome、pefile をインストールした Python 3.9+
  • AES、RSA、ChaCha20、Curve25519 アルゴリズムの理解
  • Windows CryptoAPI および CNG(BCrypt)関数の知識
  • 安全に実行するためのサンドボックス環境

主な概念

ハイブリッド暗号化モデル

ランサムウェアはファイルごとに固有の AES 鍵と IV を生成します。ファイルの内容はこの対称鍵で暗号化されます。次に、対称鍵が攻撃者の RSA 公開鍵(バイナリに埋め込まれているか、C2 から取得される)で暗号化されます。暗号化された鍵は、暗号化済みファイルの末尾または先頭に追加されます。RSA 秘密鍵を持つ攻撃者だけが、ファイルごとの対称鍵を復号できます。

暗号化 API の特定

Windows のランサムウェアは通常、CryptoAPI(CryptAcquireContext、CryptGenKey、CryptEncrypt)または CNG(BCryptGenerateSymmetricKey、BCryptEncrypt)を使用します。OpenSSL や独自の実装を使用するものもあります。これらの API 呼び出しを特定すると、アルゴリズム、鍵長、動作モードについてすぐに把握できます。

実装上の欠陥

復号の機会につながる要因には、ハードコードされた暗号鍵、鍵生成に弱い PRNG を使用すること(シードに GetTickCount や time() を使用するなど)、ファイル間での IV の再利用、ECB モードの使用、暗号化後もメモリに残る鍵、暗号化中に鍵を捕捉できる競合状態などがあります。

ワークフロー

ステップ 1:暗号化関数を特定する
#!/usr/bin/env python3
"""Identify cryptographic functions in ransomware PE files."""
import pefile
import sys

CRYPTO_APIS = {
    # Windows CryptoAPI
    "CryptAcquireContextA": "CryptoAPI context acquisition",
    "CryptAcquireContextW": "CryptoAPI context acquisition",
    "CryptGenKey": "Key generation",
    "CryptDeriveKey": "Key derivation",
    "CryptEncrypt": "Encryption operation",
    "CryptDecrypt": "Decryption operation",
    "CryptImportKey": "Key import (public key?)",
    "CryptExportKey": "Key export",
    "CryptGenRandom": "Random number generation",
    "CryptCreateHash": "Hash creation",
    "CryptHashData": "Hashing operation",
    # Windows CNG (BCrypt)
    "BCryptOpenAlgorithmProvider": "CNG algorithm initialization",
    "BCryptGenerateSymmetricKey": "CNG symmetric key generation",
    "BCryptEncrypt": "CNG encryption",
    "BCryptDecrypt": "CNG decryption",
    "BCryptGenerateKeyPair": "CNG key pair generation",
    "BCryptImportKeyPair": "CNG key import",
    # OpenSSL
    "EVP_EncryptInit_ex": "OpenSSL encrypt init",
    "EVP_EncryptUpdate": "OpenSSL encrypt update",
    "EVP_EncryptFinal_ex": "OpenSSL encrypt final",
    "RSA_public_encrypt": "OpenSSL RSA encryption",
    "AES_set_encrypt_key": "OpenSSL AES key setup",
    # File operations
    "CreateFileW": "File open (target files)",
    "ReadFile": "File read (before encryption)",
    "WriteFile": "File write (after encryption)",
    "FindFirstFileW": "File enumeration (targeting)",
    "FindNextFileW": "File enumeration",
    "MoveFileW": "File rename (extension change)",
    "DeleteFileW": "File deletion (originals)",
}

AES_SBOX = bytes([
    0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
    0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
])

CHACHA20_CONSTANT = b"expand 32-byte k"


def analyze_imports(filepath):
    """Analyze PE imports for cryptographic APIs."""
    try:
        pe = pefile.PE(filepath)
    except pefile.PEFormatError:
        print("[-] Not a valid PE file")
        return

    print("[+] Cryptographic API Analysis")
    print("=" * 60)

    crypto_imports = []
    if hasattr(pe, 'DIRECTORY_ENTRY_IMPORT'):
        for entry in pe.DIRECTORY_ENTRY_IMPORT:
            dll = entry.dll.decode('utf-8', errors='replace')
            for imp in entry.imports:
                if imp.name:
                    name = imp.name.decode('utf-8', errors='replace')
                    if name in CRYPTO_APIS:
                        desc = CRYPTO_APIS[name]
                        crypto_imports.append((dll, name, desc))
                        print(f"  [{dll}] {name}: {desc}")

    if not crypto_imports:
        print("  No known crypto APIs found in imports")
        print("  Malware may use custom implementation or dynamic loading")

    return crypto_imports


def find_crypto_constants(filepath):
    """Search for embedded cryptographic constants."""
    with open(filepath, 'rb') as f:
        data = f.read()

    print("\n[+] Cryptographic Constants Search")
    print("=" * 60)

    # AES S-Box
    offset = data.find(AES_SBOX)
    if offset != -1:
        print(f"  AES S-Box found at offset 0x{offset:x}")

    # ChaCha20/Salsa20 constant
    offset = data.find(CHACHA20_CONSTANT)
    if offset != -1:
        print(f"  ChaCha20 constant at offset 0x{offset:x}")

    # RSA public key markers
    rsa_markers = [
        b'-----BEGIN PUBLIC KEY-----',
        b'-----BEGIN RSA PUBLIC KEY-----',
        b'\x30\x82',  # ASN.1 SEQUENCE
    ]
    for marker in rsa_markers:
        offset = data.find(marker)
        if offset != -1:
            print(f"  RSA key marker at offset 0x{offset:x}")

    # Common ransomware file extension patterns
    import re
    ext_pattern = re.compile(rb'\.\w{3,10}(?=\x00)', re.IGNORECASE)
    extensions = set()
    for match in ext_pattern.finditer(data):
        ext = match.group().decode('ascii', errors='replace').lower()
        target_exts = [
            '.doc', '.docx', '.xls', '.xlsx', '.pdf', '.ppt',
            '.jpg', '.png', '.sql', '.mdb', '.bak', '.zip',
        ]
        if ext in target_exts:
            extensions.add(ext)

    if extensions:
        print(f"\n  Target file extensions: {', '.join(sorted(extensions))}")


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

    analyze_imports(sys.argv[1])
    find_crypto_constants(sys.argv[1])
ステップ 2:暗号化フローを分析する
def analyze_encryption_pattern(filepath):
    """Analyze file encryption patterns from ransomware artifacts."""
    import os
    import struct

    with open(filepath, 'rb') as f:
        data = f.read()

    file_size = len(data)
    print(f"\n[+] Encrypted File Analysis: {filepath}")
    print(f"  Size: {file_size:,} bytes")

    # Check for appended key material (common pattern)
    # Many ransomware families append encrypted key at end of file
    tail_sizes = [256, 512, 1024, 2048]  # Common RSA ciphertext sizes
    for size in tail_sizes:
        if file_size > size + 16:
            tail = data[-size:]
            # High entropy suggests encrypted data
            entropy = calculate_entropy(tail)
            if entropy > 7.5:
                print(f"  Possible encrypted key ({size} bytes) "
                      f"at end of file (entropy: {entropy:.2f})")

    # Check for header modifications
    # Many ransomware prepend metadata
    header = data[:64]
    print(f"  First 16 bytes: {header[:16].hex()}")

    # Check if original file header is preserved
    known_headers = {
        b'PK': 'ZIP/Office',
        b'\x89PNG': 'PNG',
        b'\xff\xd8\xff': 'JPEG',
        b'%PDF': 'PDF',
        b'\xd0\xcf\x11\xe0': 'OLE (DOC/XLS)',
    }
    for magic, ftype in known_headers.items():
        if header.startswith(magic):
            print(f"  Original format preserved: {ftype}")
            break
    else:
        print("  Original header destroyed/encrypted")


def calculate_entropy(data):
    """Calculate Shannon entropy of data."""
    from collections import Counter
    import math

    if not data:
        return 0

    freq = Counter(data)
    length = len(data)
    entropy = -sum(
        (count / length) * math.log2(count / length)
        for count in freq.values()
    )
    return entropy

検証基準

  • 暗号化アルゴリズム(AES、RSA、ChaCha20 など)を特定している
  • 鍵長と動作モードを判定している
  • 鍵生成方法を分析し、潜在的な弱点を調べている
  • ファイルごとの鍵暗号化方式を記録している
  • ファイルの標的パターンと拡張子の一覧を抽出している
  • インフラとの関連付けに使う埋め込み公開鍵を抽出している
  • 復号できる可能性のある機会を評価している

参考資料

コメント