analyzing-dotnet-assemblies について
.NET アセンブリを分析する、マルウェアアナリストやソースコードのない Windows アプリの調査担当者向けセキュリティスキルです。逆コンパイル、難読化やパッキング、実行時ダンプ、マルウェア特有の挙動の確認を扱います。
主な機能
- 01マネージドアセンブリと公開形式を判別
- 02アセンブリを読みやすいコードに逆コンパイル
- 03一般的な難読化ツールを検出して対処
- 04メモリからマネージドモジュールをダンプ
- 05dnSpyEx でアセンブリをデバッグ・修正
活用シーン
- 01ソースコードなしで Windows アプリやサービスを調査
- 02.NET マルウェアのローダーと後続段階を分析
- 03メモリ内の PowerShell または C# ローダーのロジックを復元
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ trilwu/ secskills --skill analyzing-dotnet-assembliesインストール後、Claude Code で/analyzing-dotnet-assembliesを入力して読み込まれたか確認します。
詳細
.NET アセンブリの解析
.NET は完全なメタデータを含む IL にコンパイルされるため、難読化されていないアセンブリは元の C# に近い形に逆コンパイルできます。そのため、重要なのは「どう読めばよいか」ではなく、「何が妨げになっているか」です。パッカー、難読化ツール、ランタイムローダー、あるいはマネージコードをネイティブホスト内に隠す発行モードが考えられます。
使用する場合
fileが PE と報告し、バイナリに CLR ヘッダーまたはmscoree.dllが含まれている- ILSpy または dnSpy でアセンブリを開けるが、名前が改変されているか、メソッド本体が空になっている
- .NET マルウェア、ローダー、レッドチーム用ツールを解析する
- ソースコードのない Windows デスクトップアプリケーションまたはサービスアプリケーションを調査する
- PowerShell または C# のインメモリローダーからロジックを復元する
使用しない場合
- Unity IL2CPP —
reversing-unity-il2cppを使用してください。C# はネイティブコードにコンパイルされます - Xamarin/MAUI モバイルアプリ — コンテナーの抽出には
reversing-xamarin-mauiを使用し、その後ここに戻って DLL を調べてください - 封じ込め前のマルウェアの疑いがある場合 — まず
analyzing-malwareを使用してください - Go または Rust のバイナリ — 該当するスキルを使用してください
マネージコードであることを確認する
# Linux
file target.exe # "Mono/.Net assembly"
rg -a -o 'BSJB|mscoree\.dll|System\.Private\.CoreLib' target.exe | head
# Windows
dotnet-tool: ildasm /text target.exe | head
# CLR header presence in the optional header data directory 14 is the real test
| 見つかったもの | 発行モード | アプローチ |
|---|---|---|
マネージ PE。mscorlib/System.Private.CoreLib を参照している | フレームワーク依存 | そのまま逆コンパイルする |
| マネージバンドルを埋め込んだネイティブ PE | 単一ファイル発行 | まずバンドルを抽出する |
| IL メタデータがまったくないネイティブ PE | NativeAOT | .NET のリバースエンジニアリングではありません — analyzing-binaries を使用してください |
エントリーポイントのない .dll | ライブラリ | 逆コンパイルし、別の場所で呼び出し元を探す |
# Single-file publish: the managed assemblies are appended as a bundle
# Extract with a bundle extractor, or carve on the manifest header
ilspycmd --list-bundle target.exe 2>/dev/null || binwalk -Me target.exe
逆コンパイルする
ilspycmd target.dll -o ./decompiled -p # -p writes a project structure
# GUI: dnSpyEx (maintained fork), ILSpy, dotPeek
# dnSpyEx also debugs and edits assemblies, which is why it is the default choice
rg -n 'https?://|ConnectionString|ApiKey|password|Convert\.FromBase64String' ./decompiled | head -40
エントリーポイント、製品名を冠した型、次にネットワーク、暗号、プロセスの API を参照するものの順に読みます。特定のクロージャを追う場合を除き、生成された型(<>c__DisplayClass、<Module>)は読み飛ばしてください。
対処する前に難読化ツールを特定する
ツール名が分かれば難読化解除は簡単ですが、分からないと手間がかかります。
detect-it-easy target.exe # or DIE's CLI: diec
# Look for: ConfuserEx, .NET Reactor, SmartAssembly, Eazfuscator, Babel,
# Dotfuscator, Agile.NET, Obfuscar
rg -a -o 'ConfuserEx|Reactor|SmartAssembly|Eazfuscator|Babel|DotNetPatcher' target.exe
# de4dot handles the classic obfuscators automatically
de4dot target.exe -o cleaned.exe
de4dot -p cr target.exe # force a specific profile when detection fails
# ConfuserEx specifically: use a maintained unpacker fork, since de4dot's
# built-in support predates later ConfuserEx versions
各難読化レイヤーの特徴と対処方法は次のとおりです。
| レイヤー | 見た目 | 対処方法 |
|---|---|---|
| 名前の改変 | Class1.method_3、Unicode/不可視の名前 | 表面的なものです — 読みながら名前を変更してください。de4dot で一部を復元できます |
| 文字列の暗号化 | あらゆる場所に <Module>.Decrypt(12345) がある | 復号器を実行します。de4dot を使うか、メソッドを動的に呼び出してください |
| 制御フローの平坦化 | 状態変数を使った巨大な switch | de4dot の CFG クリーンアップを使うか、動的に読み取ってください |
| プロキシ/デリゲート呼び出し | すべての呼び出しがヘルパーを経由する | de4dot で逆仮想化します |
| 改ざん防止/デバッグ対策 | dnSpy デバッガーで失敗する | チェックをパッチするか、復号後にダンプしてください |
| 仮想化(Agile.NET、KoiVM) | 認識可能な IL がまったくない | 逆仮想化ツール(KoiVM には OldRod)または動的解析 |
| IL を包むネイティブスタブ | マネージコードが実行時に復号される | メモリからダンプしてください — これが確実な方法です |
メモリからのダンプは、汎用的な切り抜け策です。 パッカーが何であれ、CLR はコードを実行するために最終的には実際の IL を保持する必要があります。読み込ませてからダンプしてください。
# MegaDumper / ExtremeDumper / pe-sieve — dump loaded managed modules from a
# running process, then decompile the dump
pe-sieve /pid <pid> /dmode 3
これはパックされたネイティブマルウェアでの「自身を展開させる」方法と同じです。悪意のあるものを実行する前の封じ込めについては、analyzing-malware を参照してください。
デバッグとパッチ適用
# dnSpyEx: set breakpoints in decompiled C#, inspect locals, edit method bodies,
# and save the modified assembly. This is unusually powerful — you can change a
# license check or a validation result and immediately re-run.
パッチ適用のワークフロー:dnSpyEx で IL または逆コンパイルした C# を編集し、アセンブリを保存して再実行します。保存すると厳密名の署名が無効になります。厳密名の要件を取り除くか、アプリが独自のハッシュを検証する場合は、そのチェックをフックしてください。署名付きアセンブリをアプリ自体が検証する場合、パッチ適用は通常適切な方法ではありません。代わりに実行時にフックしてください。
.NET マルウェアに関するメモ
.NET はローダーや一般的な RAT で広く使用されており、特徴的な痕跡が残ります。
Assembly.Load(byte[])— メモリ内で復号される第 2 段階のペイロードです。復号ルーチンを見つけてオフラインで実行し、結果として得られたアセンブリを解析します。これは .NET マルウェアで最もよく見られるパターンです。Activator.CreateInstanceとリフレクションによって、実際の呼び出しグラフを隠します。AmsiScanBuffer/EtwEventWriteのパッチ適用 — バイトパターン、または先行するGetProcAddress呼び出しを検索します。- P/Invoke 宣言(
[DllImport])から、ネイティブ機能が分かります。例:VirtualAlloc、CreateRemoteThread、SetWindowsHookEx。 - 暗号化されたペイロードを格納するリソースやサテライトアセンブリ — 必ずリソースセクションを列挙します。
rg -n 'DllImport|Assembly\.Load|CreateInstance|FromBase64String|RijndaelManaged|AmsiScanBuffer' ./decompiled | head -30
ilspycmd --list-resources target.dll
抽出した第 2 段階のペイロードはこのスキルでさらに解析し、機能と IOC の出力は analyzing-malware に、検出コンテンツは engineering-detections に渡します。
却下すべき合理化
- 「名前に意味がなく、難読化がひどすぎます。」 名前のマングリングは最も弱い層です。構造、文字列、P/Invoke はそのまま残っています。
- 「de4dot に失敗したので、難読化を解除できません。」 難読化ツールを特定し、専用のアンパッカーを使用するか、メモリからダンプします。
- 「ネイティブ EXE なので、.NET ではありません。」 単一ファイル発行や、マネージコードをラップするネイティブスタブがないか確認します。
- 「文字列が暗号化されています。」 復号器はアセンブリ内にあります。呼び出してください。
- 「ローダーを逆コンパイルしたので、これがマルウェアです。」 ローダーは第 1 段階です。
Assembly.Loadを見つけ、読み込まれるものを復元してください。 - 「平坦化された制御フローを手作業で読みます。」 クリーンアップを実行するか、dnSpyEx でデバッグして実際の経路を確認してください。
参考資料
analyzing-malware— 封じ込め、機能モデル、IOCanalyzing-binaries— NativeAOT とネイティブスタブの解析reversing-unity-il2cpp、reversing-xamarin-maui— その他の .NET コンテナーengineering-detections— 復元した挙動をルールに変換- dnSpyEx、ILSpy/ilspycmd、de4dot、Detect It Easy、pe-sieve、OldRod