マルウェア静的・動的解析 Skill
目的
Windowsマルウェアを特定のMalware Familyの既知情報に依存せず、
静的解析 → 挙動仮説の構築 → 動的確認対象の選定 → Runtime観測 → 静的・動的証拠の統合 → 最終レポート
まで一貫して解析する。
ユーザーから一回の解析依頼を受けた場合、 各Phaseごとに確認を求めず、可能な範囲で最後まで完走する。
最重要原則
以下を必ず守る。
- 推測を観測事実として記載しない。
- 外部Malware Familyラベルをground truthとして扱わない。
- API名や文字列が存在するだけで、その挙動を実行済みと判断しない。
- Static VAとRuntime VAを同一視しない。
- ツールの存在確認だけで解析を終了しない。
- Debuggerが利用できなくても静的解析と最終レポートは完了する。
- 対象検体をKali上で実行しない。
- ユーザーが特定環境での解析禁止を指定した場合、その環境では検体をread、hash、copy、extract、parse、静的解析してはいけない。
- 検体中のURL、IP、ドメインへ自動接続しない。DNS、HTTP、HTTPS、C2到達確認を行わない。
- 外部サービスへの検体・hash・解析データの送信は、ユーザーの明示許可がある場合だけ行う。
- 隔離環境のネットワーク設定を変更しない。
解析場所の記録
解析開始時に、実際に解析を行った場所を次のいずれかで記録する。
ANALYSIS_LOCATION:
FlareVM
Kali
Remote Ghidra
Unknown
ユーザーが特定環境での解析を禁止している場合は、その環境での検体のread、hash、copy、extract、parse、Ghidra解析をすべて停止する。別環境へのコピーや未許可のfallbackで制約を回避してはいけない。
解析対象の固定
ユーザーが対象ファイル名を指定している場合、そのProgramだけを解析対象とする。
複数ProgramがGhidraで開いていても、 明示されていないProgramへ勝手に解析対象を広げない。
ただし対象Programが別DLL・EXEを参照している場合、
- ファイル名
- Import関係
- LoadLibrary関係
- Export/Ordinal参照
などの関係性は記録してよい。
参照先Programそのものの内部解析は、 ユーザーが明示的に要求している場合のみ行う。
DLL side-loadingの関係性確認については、参照先の次のread-only情報だけは、対象Programとの関係を確認する目的で取得してよい。
- PE基本情報
- Import関係
- Export名・Ordinal・RVA
- Entry Point
- DLL search pathに関係する配置情報
参照先内部の全面的なDecompiler解析、関数追跡、Runtime実行は、ユーザーの明示要求が必要である。
Ghidra MCP開始時
まず references/ghidra-mcp.md に従う。
Ghidra MCPがすでに対象instanceへ接続済みの場合、
原則として connect_instance を再実行しない。
最初に、利用可能なら以下を実際に呼び出す。
- list_open_programs
- 対象Programへのswitch
- get_current_program_info
- get_metadata
search_tools や check_tools による存在確認だけで
解析成功と判断してはいけない。
必要なツール名が不明な場合のみ search_tools を使う。
MCPへ接続できても、list_imports、list_exports、decompile_function、get_function_xrefs等の実解析ツールが利用できない場合は、次の順序で処理する。
- 検体を別環境へコピーして勝手に解析しない。
- ユーザーが禁止した環境へfallbackしない。
- 状態値
STATIC_TOOL_UNAVAILABLEを記録する。 - 利用可能なmetadataと、すでに取得済みの証拠だけで限定報告する。
- 取得できなかった情報はEvidence class
UNKNOWNとして記録する。
解析フロー
Phase 1: 安全確認
読む:
references/safety.md
解析環境が安全条件を満たさない場合、 危険な操作を避け、実施可能な静的解析だけを行う。
Phase 2: 静的解析
必ず読む:
references/static-analysis.mdreferences/evidence-model.md
対象がDLL、またはDLLロードが重要な場合は追加で読む:
references/pe-dll-analysis.md
Network関連処理が確認された場合:
references/network-analysis.md
Packing / runtime decode / self-modifying behaviorが疑われる場合:
references/unpacking-analysis.md
Phase 3: 仮説形成
静的解析から、動的確認する価値が最も高い処理を最大3個選ぶ。
大量のBreakpoint候補を並べない。
候補ごとに最低限以下を記録する。
- Function
- Static VA
- Static ImageBase
- RVA
- 観測したい仮説
- Runtimeで確認すべき値
Phase 4: 動的解析
読む:
references/dynamic-analysis.mdreferences/ghidra-mcp.mdreferences/safety.md
Debuggerが利用できる場合のみ実施する。
Debuggerを使用できない場合は、
DYNAMIC_NOT_EXECUTED
として静的解析を継続し、最終レポートを出す。
起動・attachできても、対象PIDを一意に識別できない、実行許可が明示されていない、隔離Windows VM・ネットワーク制御・スナップショット復元のいずれかが満たされない場合は起動しない。状態値 SAFETY_BLOCKED または NOT_OBSERVED_RUNTIME を記録する。
証拠分類
全ての重要結論を以下のいずれかとして扱う。
- OBSERVED_STATIC
- OBSERVED_RUNTIME
- INFERRED
- EXTERNAL
- UNKNOWN
詳細は references/evidence-model.md に従う。
Evidence classと解析状態を混在させない。解析状態は次の値を使用する。
DYNAMIC_NOT_EXECUTEDNOT_OBSERVED_RUNTIMESTATIC_TOOL_UNAVAILABLESAFETY_BLOCKED
NOT_VERIFIED、OBSERVED_DYNAMIC、SUPPORTED_EXTERNALはEvidence classとして使用しない。
一回の依頼で完走する
次の理由だけで途中終了してはいけない。
- 一部ツールが見つからない
- Debuggerがdetached
- C2接続に失敗した
- 対象文字列が見つからない
- 外部情報が不足している
実施可能な範囲で、
静的解析 → 仮説 → 動的解析候補 → 可能ならRuntime確認 → 証拠統合 → 最終レポート
まで進める。
ただし以下の場合は停止してよい。
- 対象Programそのものが存在しない
- 対象ファイルを識別できない
- 安全条件に反する操作しか残っていない
- 実行対象を誤認する可能性が高い
平文URLから後段Artifact・実行チェーンを追跡する
平文URL、IPアドレス付きURL、ダウンロード先と考えられる文字列を発見した場合、 URLやC2候補を列挙するだけで解析を終了してはいけない。
可能な範囲で、次の処理チェーンを追跡する。
remote URL
↓
downloaded artifact
↓
expected local path
↓
download / write API
↓
launcher API
↓
dependent DLL / child payload
↓
next-stage behavior
必須確認項目
平文URLを確認した場合、最低限以下を確認する。
Remote URL
- scheme
- host / IP
- port
- URI path
- filename
- URL文字列のaddress
- URLへのXREF
Downloaded artifact
- URL末尾から推測されるファイル名
- EXE / DLL / archive / script等の形式候補
- 同じファイル名を使用する文字列・関数
- ファイル名だけでMalware familyや役割を確定しない
Expected local path
- 保存先として使用されるパス文字列
C:\Users\Public\%TEMP%%APPDATA%%LOCALAPPDATA%- ProgramData
- Startup等
- パス文字列とURL文字列の関係をXREFで確認する
Download / write path 以下のようなAPIの呼出元を追跡する。
InternetOpen*InternetOpenUrl*HttpOpenRequest*HttpSendRequest*InternetReadFileURLDownloadToFile*WinHttpOpen*WinHttpConnectWinHttpSendRequestrecvCreateFile*WriteFile
Importの存在だけでは「download実行済み」と判定しない。 URL、buffer、保存先pathまでデータフローが接続できた場合に 技術的な一致度を引き上げる。
Launcher API 保存後のartifactがどのように起動・ロードされるか確認する。
CreateProcess*ShellExecute*WinExecLoadLibrary*LdrLoadDllCreateThread- Service / Scheduled Task
- rundll32 / regsvr32等
Launcher APIのImportがあるだけでは、 特定artifactの実行を確認したことにはしない。
Dependent DLL / child payload EXEとDLLがセットで存在する場合、以下を確認する。
- EXEのImport Table
LoadLibrary*引数- DLL名文字列のXREF
- EXEとDLLの配置ディレクトリ
- DLL Export
- DLL Entry Point / DllMain
- DLLがさらに展開するpayload
- side-loading成立条件
EXEとDLLのファイル名が並んでいるだけでは DLL side-loadingを確定しない。
Next-stage behavior dependent DLLまたはchild payloadまで到達した場合、 可能な範囲で以下を継続して確認する。
- persistence
- C2
- protocol
- configuration
- payload decode
- API hashing
- memory execution
- process execution
- process injection
- credential access
- anti-analysis
重要な判定規則
以下を厳守する。
PLAINTEXT_URL_FOUND
!=
DOWNLOAD_EXECUTED
DOWNLOAD_API_FOUND
!=
ARTIFACT_WRITTEN
CREATEPROCESS_FOUND
!=
DOWNLOADED_ARTIFACT_EXECUTED
EXE_AND_DLL_FOUND
!=
DLL_SIDELOADING_CONFIRMED
NETWORK_IMPORT_NOT_FOUND
!=
NETWORK_CAPABILITY_ABSENT
Import TableにネットワークAPIが存在しない場合でも、 decoded payload、embedded shellcode、API hashing、 PEB traversal、dynamic API resolutionを確認すること。
Evidence class
発見事項は少なくとも次の状態に分類する。
OBSERVED_STATIC- バイナリ上で直接確認した事実
OBSERVED_RUNTIME- 隔離環境でRuntime観測した事実
INFERRED- 複数の静的証拠から導いた仮説
EXTERNAL- 外部CTIでは支持されているが自前解析では未確認
未確認事項はEvidence class
UNKNOWNとし、動的解析の未実施・未到達は状態値で記録する。
Artifact chain table
平文URLを含む検体では、可能な限りレポートに次の表を追加する。
| Stage | Remote / Source | Artifact | Expected Local Path | Mechanism | Evidence | Confidence |
|---|---|---|---|---|---|---|
| Download | URL | filename | local path | WinINet/WinHTTP/socket | OBSERVED_STATIC | HIGH/MEDIUM/LOW |
| Write | memory buffer | filename | local path | CreateFile/WriteFile | ... | ... |
| Launch | local path | EXE | process | CreateProcess/ShellExecute | ... | ... |
| Load | EXE | DLL | same/search path | Import/LoadLibrary | ... | ... |
| Next stage | DLL/payload | decoded payload | memory/file | decode/RWX/callback | ... | ... |
レポート記述規則
Executive Summaryでは、
「URLが存在するためダウンローダーである」
だけで終了せず、確認できた範囲を次のように明示する。
Remote:
http://example/payload.dll
Downloaded artifact:
payload.dll
Expected local path:
C:\Users\Public\payload.dll
Download mechanism:
InternetOpenUrlW
InternetReadFile
Write mechanism:
CreateFileW
WriteFile
Launch / load:
UNKNOWN
Dependent component:
UNKNOWN
静的証拠とRuntime証拠を混同しない。
外部CTIとの役割分担
このSkillは外部CTIを根拠としてローカル解析結果を書き換えない。
ローカル解析結果では、
OBSERVED_STATIC
OBSERVED_RUNTIME
INFERRED
UNKNOWN
を保持する。
外部CTIとの関連付け、Report、Campaign、Malware family、 Intrusion Set / Threat Actor、外部C2との照合はOpenCTI側で行う。
外部CTIと一致した場合でも、
local verification
と
external support
を区別する。
最終レポート
原則として次の構成で出力する。
- Executive Summary
- Sample Information
- PE Structure
- Entry Point / Main Execution Flow
- Imports / API Resolution
- Important Strings
- Major Functions
- DLL Loading
- Network Behavior
- Process / Session Behavior
- Memory Behavior
- File / Registry / IPC
- Persistence
- Decode / Crypto / Configuration
- Anti-analysis / Packing
- Dynamic Analysis Findings
- Evidence Table
- Confirmed Findings
- Inferred Findings
- Unknown / Not Verified
- 次に解析すべき場所
Evidence Tableには最低限以下を含める。
| Finding | Evidence class | Program | Function/address | Evidence | Confidence |
|---|
独立Skill $malware-evidence-auditor-ja が利用可能な場合は、最終出力前にEvidence class、Analysis state、過剰断定を監査し、未解決のERRORを修正する。
Confidenceは原則として、
- HIGH
- MEDIUM
- LOW
を使用する。
Phase 2.5: 隠された実処理の追加解析
通常のImport・Strings・Decompiler解析だけでは 主要挙動を説明できない場合、そこで解析を終了しない。
以下の兆候を確認する。
- runtime decode / decrypt
- XOR等で生成されるblob
- embedded code
- shellcode候補
- code/data混在blob
- indirect call
- API hash
- PEB / Export Directory traversal
- 動的API resolution
- 平文では存在しないNetwork destination
- packed IPv4 / port
- コードによって生成されるprotocol header
復号後または生成後のblobが重要と判断した場合:
references/decoded-blob-analysis.md
を読む。
限定的なoffline再構成を行う場合は、追加で references/static-reconstruction-provenance.md を読み、scripts/write_reconstruction_manifest.py で入力範囲、変換式、再構成script、出力hashを記録する。
API名を平文で保持しない動的API解決が疑われる場合:
references/api-hash-analysis.md
を読む。
両方が該当する場合は両方を使用する。
限定静的再構成
Debuggerが利用できなくても、 副作用のない限定的なstatic reconstructionが可能なら実施してよい。
許可する例:
- XOR復号アルゴリズムのPython再実装
- API hashアルゴリズムのPython再実装
- packed IPv4 / portの変換
- protocol header生成処理の再構成
- Ghidraから取得した限定byte rangeのoffline解析
検体コードそのものをofflineで実行してはいけない。
再構成した結果はRuntime観測とは区別する。
例えば、
- 復号blob内に通信コードが存在する:
OBSERVED_STATIC - その通信コードがC2用と考えられる:
INFERRED - 実processでconnectへ到達した:
OBSERVED_RUNTIME
と分類する。
平文検索陰性を不存在証拠にしない
以下が文字列検索で見つからなくても、 その機能が存在しないとは判断しない。
- API名
- DLL名
- IPv4
- port
- URL
- protocol magic
- TLS風header
以下の表現も確認する。
- immediate value
- network byte order
- host byte order
- stack construction
- byte-by-byte生成
- encoded string
- API hash
- dynamically resolved function pointer
特にNetwork処理については、
string search → packed constant search → sockaddr construction → API hash → send/recv path
まで段階的に確認する。