mcpField
R
reverse-engineering-dotnet-malware-with-dnspy

reverse-engineering-dotnet-malware-with-dnspy

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

reverse-engineering-dotnet-malware-with-dnspy について

dnSpy を使って .NET サンプルを調べる、マルウェア分析担当者向けのリバースエンジニアリングスキルです。難読化解除、コード確認、実行時デバッグ、設定や C2 情報の抽出を扱い、隔離環境での分析を前提とします。

主な機能

  1. 01.NET アセンブリと難読化方式の識別
  2. 02de4dot による一般的な難読化の解除
  3. 03dnSpy でのコード逆コンパイル
  4. 04C2 設定と指標の抽出
  5. 05ブレークポイントによる実行時動作の観察

活用シーン

  1. 01AgentTesla など .NET マルウェアの分析
  2. 02難読化されたアセンブリのコードと文字列の確認
  3. 03ハードコードされた C2 アドレスや鍵の抽出
  4. 04復号や動的ロードの挙動の観察

インストール

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

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

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

同梱ファイル

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

LICENSE
references/
api-reference.md
scripts/
agent.py

詳細

dnSpyを使用した.NETマルウェアのリバースエンジニアリング

使用する場面

  • マルウェアのサンプルが、逆コンパイルが必要な.NETアセンブリ(C#、VB.NET、F#)として特定された場合
  • .NETベースのマルウェアファミリー(AgentTesla、AsyncRAT、RedLine Stealer、Quasar RAT)を分析する場合
  • ConfuserEx、SmartAssembly、またはカスタム難読化ツールで保護された.NETコードを難読化解除する場合
  • マネージアセンブリからハードコードされたC2設定、暗号化キー、認証情報を抽出する場合
  • 実行時に.NETマルウェアをデバッグし、復号ルーチンや動的な動作を観察する場合

ネイティブ(アンマネージド)PEバイナリには使用しないでください。ネイティブコードの分析にはGhidraまたはIDAを使用してください。

前提条件

  • dnSpyまたはdnSpyExがインストールされていること(https://github.com/dnSpyEx/dnSpy - コミュニティによって保守されているフォーク)
  • 自動.NET難読化解除用のde4dot(https://github.com/de4dot/de4dot)
  • 相互検証用の代替逆コンパイラーとしてILSpy
  • 分析中に変更したアセンブリを再コンパイルするため、.NET SDKがインストールされていること
  • 実際のマルウェアでdnSpyデバッガーを実行するための隔離されたWindows VM
  • 使用されている.NET難読化ツールを特定するためのDetect It Easy(DIE)

ワークフロー

ステップ1:.NETアセンブリと難読化ツールを特定する

サンプルが.NETバイナリであることを確認し、保護を検出します:

# Check if file is .NET assembly
file suspect.exe
# Output should contain "PE32 executable" with .NET metadata

# Detect obfuscator with Detect It Easy
diec suspect.exe

# Python-based .NET detection
python3 << 'PYEOF'
import pefile

pe = pefile.PE("suspect.exe")

# Check for .NET COM descriptor
if hasattr(pe, 'DIRECTORY_ENTRY_COM_DESCRIPTOR'):
    print("[*] .NET assembly detected")
    print(f"    Runtime version: {pe.DIRECTORY_ENTRY_COM_DESCRIPTOR}")
else:
    # Check for mscoree.dll import (alternative detection)
    for entry in pe.DIRECTORY_ENTRY_IMPORT:
        if entry.dll.decode().lower() == "mscoree.dll":
            print("[*] .NET assembly detected (mscoree.dll import)")
            break
    else:
        print("[!] Not a .NET assembly")

# Check section names for .NET indicators
for section in pe.sections:
    name = section.Name.decode().rstrip('\x00')
    if name in ['.text', '.rsrc', '.reloc']:
        print(f"    Section: {name} (typical .NET)")
PYEOF
ステップ2:de4dotで難読化を解除する

手動分析の前に、一般的な.NET難読化を解除します:

# Run de4dot to identify and remove obfuscation
de4dot suspect.exe -o suspect_cleaned.exe

# Force specific deobfuscator
de4dot suspect.exe -p cf  # ConfuserEx
de4dot suspect.exe -p sa  # SmartAssembly
de4dot suspect.exe -p dr  # Dotfuscator
de4dot suspect.exe -p rv  # Reactor
de4dot suspect.exe -p bl  # Babel.NET

# Verbose output for debugging
de4dot -v suspect.exe -o suspect_cleaned.exe

# Handle multi-file assemblies
de4dot suspect.exe suspect_helper.dll -o cleaned/
Common .NET Obfuscators:
━━━━━━━━━━━━━━━━━━━━━━━
ConfuserEx:      String encryption, control flow, anti-debug, anti-tamper
SmartAssembly:   String encoding, flow obfuscation, pruning
Dotfuscator:     Renaming, string encryption, control flow
.NET Reactor:    Native code generation, necrobit, anti-debug
Babel.NET:       String encryption, resource encryption, code virtualization
Crypto Obfuscator: String encryption, anti-debug, watermarking
Custom:          Malware-specific obfuscation (manual de4dot configuration needed)
ステップ3:dnSpyで開いてコードを分析する

難読化を解除したアセンブリをdnSpyに読み込み、ソースコードレベルで分析します:

dnSpy Analysis Workflow:
━━━━━━━━━━━━━━━━━━━━━━━
1. File -> Open -> Select cleaned assembly
2. Navigate to the entry point:
   - Assembly Explorer -> <namespace> -> Program class -> Main method
   - Or: Right-click assembly -> Go to Entry Point

3. Key areas to examine:
   - Entry point (Main) for initialization and execution flow
   - Form classes for UI-based malware (RATs, stealers)
   - Network/HTTP classes for C2 communication
   - Crypto/encryption classes for data protection
   - Resource access for embedded payloads
   - Timer/Thread classes for persistence and scheduling

4. Navigation shortcuts:
   Ctrl+G       - Go to token/address
   Ctrl+Shift+K - Search assemblies
   F12          - Go to definition
   Ctrl+R       - Analyze (find usages)
   F5           - Start debugging
   F9           - Toggle breakpoint
ステップ4:設定とC2データを抽出する

逆コンパイルしたソースコードから、ハードコードされた設定を特定します:

// Common .NET malware configuration patterns:

// Pattern 1: Static class with hardcoded values
public static class Config {
    public static string Host = "185.220.101.42";
    public static int Port = 4782;
    public static string Key = "GhOsT_RaT_2025";
    public static string Mutex = "AsyncMutex_6SI8OkPnk";
    public static bool Install = true;
    public static string InstallFolder = "%AppData%";
}

// Pattern 2: Encrypted strings decrypted at runtime
public static string Decrypt(string input) {
    byte[] data = Convert.FromBase64String(input);
    byte[] key = Encoding.UTF8.GetBytes("SecretKey123");
    for (int i = 0; i < data.Length; i++) {
        data[i] ^= key[i % key.Length];
    }
    return Encoding.UTF8.GetString(data);
}

// Pattern 3: Resource-embedded configuration
byte[] configData = Properties.Resources.config;
string config = AES.Decrypt(configData, derivedKey);
# Python script to extract .NET resource strings
import subprocess
import re
import base64

# Use monodis (Mono) or ildasm (.NET SDK) to dump IL
result = subprocess.run(
    ["monodis", "--output=il_dump.il", "suspect_cleaned.exe"],
    capture_output=True, text=True
)

# Search for string literals in IL dump
with open("il_dump.il", errors="ignore") as f:
    il_code = f.read()

# Find ldstr (load string) instructions
strings = re.findall(r'ldstr\s+"([^"]+)"', il_code)
for s in strings:
    # Check for Base64 encoded strings
    try:
        decoded = base64.b64decode(s).decode('utf-8', errors='ignore')
        if len(decoded) > 3 and decoded.isprintable():
            print(f"  Base64: {s[:40]}... -> {decoded[:100]}")
    except:
        pass
    # Check for URLs/IPs
    if re.match(r'https?://', s) or re.match(r'\d+\.\d+\.\d+\.\d+', s):
        print(f"  Network: {s}")
ステップ5:dnSpyでデバッグする

ブレークポイントを設定してマルウェアをデバッグし、実行時の動作を観察します:

dnSpy Debugging Workflow:
━━━━━━━━━━━━━━━━━━━━━━━
1. Set breakpoints on key methods:
   - String decryption functions (to capture decrypted values)
   - Network connection methods (to capture C2 URLs)
   - File write operations (to see what is dropped)
   - Registry modification methods (to see persistence)

2. Debug -> Start Debugging (F5)
   - Select the assembly to debug
   - Set command-line arguments if needed
   - Configure exception handling (break on all CLR exceptions)

3. At each breakpoint:
   - Inspect local variables (Locals window)
   - Evaluate expressions (Immediate window)
   - View call stack to understand execution context
   - Step over (F10) / Step into (F11) / Step out (Shift+F11)

4. Capture decrypted strings:
   - Set breakpoint after decryption function returns
   - Read the return value from the Locals window
   - Document all decrypted configuration values
ステップ6:調査結果を記録する

分析結果を整理されたレポートにまとめます:

Analysis documentation should include:
- .NET assembly metadata (CLR version, target framework, compilation info)
- Obfuscator identified and deobfuscation method used
- Complete C2 configuration (hosts, ports, encryption keys, mutex names)
- Malware capabilities (keylogging, screen capture, file theft, etc.)
- Persistence mechanisms (registry, scheduled tasks, startup folder)
- Anti-analysis techniques (VM detection, debugger detection, sandbox evasion)
- Extracted IOCs (C2 IPs/domains, file hashes, mutex names, registry keys)
- YARA rule based on unique code patterns or strings

主な概念

用語定義
CIL/MSIL共通中間言語。 .NETアセンブリのコンパイル先となるバイトコード形式で、逆コンパイルして高水準のC#/VB.NETに戻すことができます
メタデータトークンアセンブリのメタデータテーブル内にある.NETの型、メソッド、フィールドを識別する一意の識別子。dnSpyでのナビゲーションに使用します
de4dot多くの商用およびマルウェア専用の難読化ツールを特定し、保護を解除するオープンソースの.NET難読化解除ツール
ConfuserExマルウェア作成者が文字列の暗号化や制御フローの難読化に頻繁に使用する、人気のオープンソース.NET難読化ツール
文字列の暗号化文字列リテラルを暗号化データと実行時の復号呼び出しに置き換え、静的分析からIOCを隠す難読化手法
リソースの埋め込み設定、ペイロード、または追加のアセンブリを.NETの埋め込みリソースに格納する手法。アセンブリのメタデータから導出したキーで暗号化されることがよくあります
Assembly.Loadメモリ内のバイト配列からアセンブリを読み込む.NETメソッド。埋め込みペイロードのファイルレス実行を可能にします

ツールとシステム

  • dnSpy/dnSpyEx:C#およびVB.NETの逆コンパイルに対応した、オープンソースの.NETアセンブリエディター、逆コンパイラー、デバッガー
  • de4dot:ConfuserEx、SmartAssembly、Dotfuscator、Reactorなど、多数のプロテクターに対応した自動.NET難読化解除ツール
  • ILSpy:アセンブリコードのC#、VB.NET、ILビューを提供するオープンソースの.NET逆コンパイラー
  • dotPeek:シンボルサーバーと相互参照ナビゲーションを備えた、JetBrainsの無料.NET逆コンパイラー
  • Detect It Easy(DIE):.NET Frameworkのバージョン、難読化ツール、コンパイラー情報を特定するマルチフォーマットファイル解析ツール

よくあるシナリオ

シナリオ:AgentTesla の情報窃取型マルウェアを分析する

コンテキスト:フィッシングメールによって、AgentTesla と特定された .NET 実行ファイルが配信されます。サンプルを分析し、窃取する認証情報、データの持ち出し方法、C2 の設定を特定する必要があります。

アプローチ:

  1. Detect It Easy を実行して、難読化ツールを特定します(一般的には ConfuserEx またはカスタムのものです)。
  2. de4dot で難読化を解除し、クラス名とメソッド名を読みやすい状態に戻して、文字列を復号します。
  3. dnSpy で開き、エントリーポイントに移動して初期化処理を理解します。
  4. 認証情報を収集するモジュール(ブラウザー、メール、FTP、VPN のパスワードを窃取するクラス)を特定します。
  5. 持ち出し方法(SMTP メール、FTP アップロード、HTTP POST、Telegram ボット API)を見つけます。
  6. C2 の設定(SMTP サーバー、認証情報、送信先メールアドレス、または HTTP URL)を抽出します。
  7. 復号関数にデバッガーのブレークポイントを設定し、すべての復号済み文字列を一度に取得します。

注意点:

  • 最初に de4dot を使わずに分析する(ConfuserEx により、手動での分析が非常に困難になります)。
  • 複数段階の読み込みを確認しない(最初の .NET 実行ファイルが、リソースから追加のアセンブリを読み込む場合があります)。
  • .NET リソース内に保存された設定を見落とす(ハードコードされた文字列ではない場合があります)。
  • ネットワークを隔離せずにデバッガーを実行する(AgentTesla はすぐにデータを持ち出そうとします)。

出力形式

.NET MALWARE ANALYSIS REPORT
================================
Sample:           invoice_scanner.exe
SHA-256:          e3b0c44298fc1c149afbf4c8996fb924...
Type:             .NET Assembly (C#)
Framework:        .NET Framework 4.8
Obfuscator:       ConfuserEx v1.6
Deobfuscated:     Yes (de4dot -p cf)

CLASSIFICATION
Family:           AgentTesla v3
Type:             Information Stealer / Keylogger
Compile Date:     2025-09-10

C2 CONFIGURATION
Exfil Method:     SMTP (Email)
SMTP Server:      smtp.yandex[.]com:587
SMTP User:        exfil.account@yandex[.]com
SMTP Pass:        Str0ngP@ssw0rd2025
Recipient:        operator@protonmail[.]com
Interval:         30 minutes
Encryption:       AES-256 with key "AgentTesla_2025_key"

CAPABILITIES
[*] Browser credential theft (Chrome, Firefox, Edge, Opera)
[*] Email client passwords (Outlook, Thunderbird)
[*] FTP client credentials (FileZilla, WinSCP)
[*] VPN credentials (NordVPN, OpenVPN)
[*] Keylogging (SetWindowsHookEx)
[*] Screenshot capture (every 30 seconds)
[*] Clipboard monitoring

PERSISTENCE
Method:           Registry Run key + Scheduled Task
Registry:         HKCU\Software\Microsoft\Windows\CurrentVersion\Run\WindowsUpdate
Task:             \Microsoft\Windows\WindowsUpdate\Updater

EXTRACTED IOCs
SMTP Server:      smtp.yandex[.]com
Exfil Email:      exfil.account@yandex[.]com
Recipient:        operator@protonmail[.]com
Mutex:            AgentTesla_2025_Q3_MUTEX
Install Path:     %AppData%\Microsoft\Windows\svchost.exe

コメント