「LNKファイル・ジャンプリストの解析」「hiberfil.sys・pagefile.sys の証拠保全」「Wi-Fi・Bluetooth接続の詳細証跡」「ETW(Windowsイベントトレーシング)」「マルウェアの静的解析コマンド」の5本柱の徹底解説 対応OS:Windows / macOS / Linux

解析

フォレンジック系コマンド記事の第7弾です。第1〜6弾でイベントログ・メモリ解析・USB証跡・ブラウザ・レジストリ・アンチフォレンジック・横展開・DNS・仮想マシン・PowerShell難読化・MFT・Auditd・クラウドCLI・サムネイル・SQLiteアプリ証跡まで幅広く扱ってきました。今回も前回までに登場していない完全新テーマをお届けします。

今回のテーマは「LNKファイル・ジャンプリストの解析」「hiberfil.sys・pagefile.sys の証拠保全」「Wi-Fi・Bluetooth接続の詳細証跡」「ETW(Windowsイベントトレーシング)」「マルウェアの静的解析コマンド」の5本柱です。どれも現場のフォレンジックアナリストが実際に使う技術です。「まだこんな証拠が残っていたのか」という発見を楽しんでください。

⚠️ 重要: 本記事の内容は自分が管理するシステムの調査・学習を目的としています。他者のシステムへの無断調査は不正アクセス禁止法の対象です。組織内での調査は必ず法務・情報セキュリティ部門の承認のもとで実施してください。


目次

  1. 【LNKファイル・ジャンプリスト編】Windowsが密かに記録するファイルアクセス証拠
  2. 【hiberfil.sys・pagefile.sys 編】電源を切っても消えないメモリの残像
  3. 【Wi-Fi・Bluetooth証跡編】無線接続が残す詳細な行動履歴
  4. 【ETW 深層分析編】Windowsカーネルが語る超詳細な実行記録
  5. 【マルウェア静的解析編】実行せずに不審ファイルの正体を暴くコマンド
  6. まとめ

【LNKファイル・ジャンプリスト編】Windowsが密かに記録するファイルアクセス証拠

Windowsはユーザーがファイルを開くたびに「LNKファイル(ショートカットファイル)」と「ジャンプリスト」という2種類の証跡を自動生成します。これらはユーザーが意識することなく蓄積され続け、削除した元ファイルの存在・アクセス日時・ファイルが存在していたドライブ(外部メディア含む)の情報まで記録しています。内部犯行調査や持ち出し行為の立証において、最も重要な証拠の一つに数えられます。

💡 FACT: LNKファイルのフォーマットはMicrosoftが公式仕様を公開しており(MS-SHLLINK)、Windowsがいつ・どのファイルを・どのドライブから開いたかを記録するために設計されています。SANS DFIRのコースでは「LNKファイルはWindowsフォレンジック調査における最重要アーティファクトの一つ」として最初期に教えられる技術です。元ファイルを削除しても、LNKファイルが残る限り「そのファイルがそこに存在した事実」を証明できます。

① LNKファイルの内容を詳しく読む(Windows)

LNKファイルには元ファイルのフルパス・ファイルサイズ・タイムスタンプ・ボリュームシリアル番号・ネットワーク共有パスなどが記録されています。

Windows(PowerShell):

# Recentフォルダ内のLNKファイル一覧を最新順に表示
$recentPath = "$env:APPDATA\Microsoft\Windows\Recent"
Get-ChildItem $recentPath -Filter "*.lnk" |
  Sort-Object LastWriteTime -Descending |
  Select-Object Name, LastWriteTime | Select-Object -First 50 | Format-Table -AutoSize

# LNKファイルからリンク先パスを読み取る(Shellクラスを使用)
$shell = New-Object -ComObject WScript.Shell
Get-ChildItem "$env:APPDATA\Microsoft\Windows\Recent" -Filter "*.lnk" |
  Sort-Object LastWriteTime -Descending | Select-Object -First 30 |
  ForEach-Object {
    try {
      $lnk = $shell.CreateShortcut($_.FullName)
      [PSCustomObject]@{
        LNKName       = $_.Name
        LastAccessed  = $_.LastWriteTime
        TargetPath    = $lnk.TargetPath
        WorkingDir    = $lnk.WorkingDirectory
        Arguments     = $lnk.Arguments
      }
    } catch {}
  } | Format-Table -AutoSize

# USBや外部ドライブへのアクセスを示すLNKを抽出(ドライブレターがD:以降)
Get-ChildItem "$env:APPDATA\Microsoft\Windows\Recent" -Filter "*.lnk" |
  Sort-Object LastWriteTime -Descending |
  ForEach-Object {
    try {
      $lnk = $shell.CreateShortcut($_.FullName)
      if ($lnk.TargetPath -match "^[D-Z]:\\|^\\\\") {
        Write-Host "外部/ネットワーク: $($lnk.TargetPath) [$($_.LastWriteTime)]"
      }
    } catch {}
  }

# ネットワーク共有パスへのアクセスを示すLNKを抽出(UNCパス)
Get-ChildItem "$env:APPDATA\Microsoft\Windows\Recent" -Filter "*.lnk" |
  ForEach-Object {
    try {
      $lnk = $shell.CreateShortcut($_.FullName)
      if ($lnk.TargetPath -match "^\\\\") {
        Write-Host "ネットワーク共有アクセス: $($lnk.TargetPath)"
        Write-Host "  日時: $($_.LastWriteTime)"
      }
    } catch {}
  }

② ジャンプリストを解析する(Windows)

ジャンプリストはタスクバーのアプリケーションアイコンを右クリックしたときに表示される「最近使ったファイル一覧」のデータです。アプリケーションごとにAutomaticDestinations(自動生成)とCustomDestinations(手動ピン留め)の2種類があり、どちらも詳細なファイルアクセス記録を含んでいます。

Windows(PowerShell):

# ジャンプリストのファイル一覧(AutomaticDestinations)
$autoDestPath = "$env:APPDATA\Microsoft\Windows\Recent\AutomaticDestinations"
Get-ChildItem $autoDestPath -ErrorAction SilentlyContinue |
  Sort-Object LastWriteTime -Descending |
  Select-Object Name, LastWriteTime, @{N='SizeKB';E={[math]::Round($_.Length/1KB,1)}} |
  Format-Table -AutoSize

# CustomDestinations(手動でピン留めされたファイル)
$customDestPath = "$env:APPDATA\Microsoft\Windows\Recent\CustomDestinations"
Get-ChildItem $customDestPath -ErrorAction SilentlyContinue |
  Sort-Object LastWriteTime -Descending |
  Select-Object Name, LastWriteTime | Format-Table -AutoSize

# アプリIDとアプリ名の対応を調べる(主要なAppID)
$appIDs = @{
  "5f7b5f1e01b83767" = "Windows Explorer"
  "b91d2e9e42d02e26" = "Microsoft Word"
  "ae16083266e0f0ef" = "Microsoft Excel"
  "14001ee6968e6d2c" = "Microsoft PowerPoint"
  "19899c9d99f5b4aa" = "Notepad"
  "b3ccdb2aa57dea9a" = "Visual Studio Code"
}

Get-ChildItem $autoDestPath -ErrorAction SilentlyContinue |
  ForEach-Object {
    $id = $_.BaseName
    $appName = if ($appIDs[$id]) { $appIDs[$id] } else { "不明($id)" }
    [PSCustomObject]@{
      AppName    = $appName
      LastWrite  = $_.LastWriteTime
      SizeKB     = [math]::Round($_.Length/1KB,1)
    }
  } | Sort-Object LastWrite -Descending | Format-Table -AutoSize

③ LNKファイルを全ユーザー横断で確認する(管理者権限)

Windows(PowerShell):

# 全ユーザーのRecentフォルダを横断的に確認
Get-ChildItem "C:\Users\*\AppData\Roaming\Microsoft\Windows\Recent\*.lnk" -ErrorAction SilentlyContinue |
  Sort-Object LastWriteTime -Descending |
  ForEach-Object {
    try {
      $lnk = $shell.CreateShortcut($_.FullName)
      [PSCustomObject]@{
        User       = ($_.FullName -split "\\")[2]
        AccessTime = $_.LastWriteTime
        Target     = $lnk.TargetPath
      }
    } catch {}
  } | Where-Object { $_.Target } |
    Sort-Object AccessTime -Descending | Select-Object -First 40 | Format-Table -AutoSize

# 全ユーザーのジャンプリストを横断的に確認
Get-ChildItem "C:\Users\*\AppData\Roaming\Microsoft\Windows\Recent\AutomaticDestinations\*" `
  -ErrorAction SilentlyContinue |
  Sort-Object LastWriteTime -Descending | Select-Object -First 20 |
  Select-Object FullName, LastWriteTime | Format-Table -AutoSize

【hiberfil.sys・pagefile.sys 編】電源を切っても消えないメモリの残像

「PCの電源を切ればメモリの内容は消える」――これは半分正しく、半分間違いです。Windowsには電源を切る際にRAMの内容をディスクに書き出す「ハイバネーション(休止状態)」機能があり、その内容はhiberfil.sysとして保存されます。また、RAMが不足したときにメモリの内容をディスクに退避するpagefile.sysも存在します。どちらも「過去のメモリの残像」として膨大な証拠を含んでいます。

💡 FACT: NIST SP 800-86「コンピュータフォレンジックへの統合ガイド」では、hiberfil.sysをメモリフォレンジックの代替手法として明記しています。PCの電源が入っておらずライブメモリが取得できない場合でも、ハイバネーションファイルから実行中のプロセス・ネットワーク接続・暗号化キーを復元できることがあります。VeraCryptやBitLockerの暗号化キーがhiberfil.sysから発見された事例は複数報告されています。

① hiberfil.sysの存在確認と基本情報取得(Windows)

Windows(PowerShell):

# hiberfil.sysの存在とサイズを確認
$hiberFile = Get-Item "C:\hiberfil.sys" -Force -ErrorAction SilentlyContinue
if ($hiberFile) {
  Write-Host "hiberfil.sys が存在します"
  Write-Host "  サイズ: $([math]::Round($hiberFile.Length / 1GB, 2)) GB"
  Write-Host "  最終更新: $($hiberFile.LastWriteTime)"
  Write-Host "  ※ 最終更新日時 = 最後にハイバネーションに入った日時"
} else {
  Write-Host "hiberfil.sys は存在しません(ハイバネーション無効または既に抽出済み)"
}

# ハイバネーションの設定状態を確認
powercfg /a
powercfg /query SCHEME_CURRENT SUB_SLEEP

# ハイバネーションが有効かどうかをレジストリで確認
reg query "HKLM\SYSTEM\CurrentControlSet\Control\Power" /v HibernateEnabled

# hiberfil.sysを証拠ファイルとしてコピー(RawCopyが必要 / Volume Shadow Copy経由)
# 通常のcopyコマンドはシステム保護でブロックされるため、VSS経由でコピー
$shadow = (Get-WmiObject Win32_ShadowCopy | Sort-Object InstallDate -Descending | Select-Object -First 1)
if ($shadow) {
  $shadowPath = $shadow.DeviceObject + "\hiberfil.sys"
  Write-Host "VSS経由でコピー可能なパス: $shadowPath"
}

② hiberfil.sysをVolatilityで解析する

hiberfil.sysはそのままではメモリダンプとして使えませんが、専用ツールで変換することで通常のメモリフォレンジックと同じ解析が可能になります。

Linux(Volatility3):

# hiberfil.sysをrawメモリイメージに変換(volatilityの内部処理で自動対応)
python3 vol.py -f hiberfil.sys windows.info

# ハイバネーション時に実行中だったプロセスを確認
python3 vol.py -f hiberfil.sys windows.pslist
python3 vol.py -f hiberfil.sys windows.pstree

# ハイバネーション時のネットワーク接続を復元
python3 vol.py -f hiberfil.sys windows.netstat

# ハイバネーション時のレジストリキャッシュを確認
python3 vol.py -f hiberfil.sys windows.registry.hivelist

# 暗号化キー(BitLocker FVEK)を探す
python3 vol.py -f hiberfil.sys windows.bitlocker

# hiberfil.sysからrawイメージに変換するツール(hibr2bin)
# hibr2bin.exe /HI hiberfil.sys /OUTPUT memory_raw.bin

③ pagefile.sysから文字列を抽出する(Windows)

Windows(PowerShell):

# pagefile.sysの存在とサイズを確認
$pageFile = Get-Item "C:\pagefile.sys" -Force -ErrorAction SilentlyContinue
if ($pageFile) {
  Write-Host "pagefile.sys が存在します"
  Write-Host "  サイズ: $([math]::Round($pageFile.Length / 1GB, 2)) GB"
}

# ページファイルの設定を確認
Get-WmiObject Win32_PageFileUsage | Select-Object Name, CurrentUsage, PeakUsage, AllocatedBaseSize
reg query "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management" /v PagingFiles

# pagefile.sysのVSS経由コピー
$shadow = (Get-WmiObject Win32_ShadowCopy | Sort-Object InstallDate -Descending | Select-Object -First 1)
if ($shadow) {
  Write-Host "VSS経由コピーパス: $($shadow.DeviceObject)\pagefile.sys"
}

Linux(stringsで内容を抽出):

# pagefile.sysのコピーをLinux側でstringsで解析
strings -n 8 pagefile_copy.sys | grep -E "https?://|password|Authorization|Bearer " | head -50

# Base64エンコードされた文字列を抽出(マルウェアのC2通信等)
strings pagefile_copy.sys | grep -E "^[A-Za-z0-9+/]{40,}={0,2}$" | head -20

# メールアドレスらしき文字列を抽出
strings pagefile_copy.sys | grep -E "[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}" | sort -u | head -30

# WindowsのAPIコール名を抽出(マルウェアの動作を間接的に把握)
strings pagefile_copy.sys | grep -E "VirtualAlloc|CreateRemoteThread|WriteProcessMemory|RegSetValue" | head -20

【Wi-Fi・Bluetooth証跡編】無線接続が残す詳細な行動履歴

Wi-FiとBluetoothの接続履歴は「その人物がいつどこにいたか」を証明する地理的証拠になりえます。カフェのWi-Fi名・自宅のSSID・接続したBluetoothデバイスが記録されており、アリバイの確認や行動の再構築に活用されます。企業セキュリティの観点では、社外の不明なWi-Fiへの接続(潜在的な中間者攻撃リスク)や、未承認のBluetoothデバイス接続の検出にも有効です。

① Wi-Fi接続の詳細履歴を調べる(Windows)

Windows(コマンドプロンプト / PowerShell):

# 過去に接続したWi-Fiプロファイルの一覧
netsh wlan show profiles

# 全プロファイルの詳細(接続タイプ・認証方式)を一括確認
netsh wlan show profiles | Select-String "Profile" |
  ForEach-Object {
    $name = ($_ -split ":")[1].Trim()
    Write-Host "=== $name ==="
    netsh wlan show profile name="$name" | Select-String "SSID|Authentication|Connection|Date"
  }

# パスワードを含む詳細情報(管理者権限)
netsh wlan show profile name="Wi-Fi名" key=clear

# WLAN AutoConfigのイベントログから接続日時を確認
Get-WinEvent -LogName "Microsoft-Windows-WLAN-AutoConfig/Operational" -ErrorAction SilentlyContinue |
  Where-Object { $_.Id -eq 8001 -or $_.Id -eq 8002 -or $_.Id -eq 8003 } |
  Select-Object TimeCreated, Id,
    @{N='EventType';E={switch($_.Id){8001{"接続成功"};8002{"接続失敗"};8003{"切断"}}}},
    @{N='SSID';E={$_.Properties[1].Value}} |
  Sort-Object TimeCreated -Descending | Select-Object -First 50 | Format-Table -AutoSize

# 接続履歴をCSVに保存
Get-WinEvent -LogName "Microsoft-Windows-WLAN-AutoConfig/Operational" -ErrorAction SilentlyContinue |
  Where-Object { $_.Id -in 8001,8002,8003 } |
  Select-Object TimeCreated, Id, @{N='SSID';E={$_.Properties[1].Value}} |
  Export-Csv "C:\forensics\wifi_history.csv" -NoTypeInformation -Encoding UTF8

② macOS / Linuxのwi-fi接続履歴を調べる

macOS:

# 過去に接続したWi-Fiのプロファイルを確認
defaults read /Library/Preferences/SystemConfiguration/com.apple.airport.preferences 2>/dev/null |
  grep -A5 "SSIDString\|LastConnected\|_timeStamp"

# より詳細な情報をシステム設定ファイルから確認
sudo cat /Library/Preferences/SystemConfiguration/com.apple.airport.preferences.plist 2>/dev/null |
  python3 -c "import sys,plistlib; d=plistlib.load(sys.stdin.buffer); [print(n.get('SSIDString',''),n.get('_timeStamp','')) for n in d.get('KnownNetworks',{}).values()]" 2>/dev/null

# Wi-Fi接続イベントをシステムログから取得
log show --predicate 'subsystem == "com.apple.wifi"' --last 30d |
  grep -E "connected|disconnect|associat" | head -50

# 詳細なWi-Fi診断ログ
sudo /System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport -I

Linux:

# NetworkManagerの接続プロファイル一覧
nmcli connection show

# 接続履歴の詳細(タイムスタンプ付き)
nmcli connection show --active
journalctl -u NetworkManager --since "30 days ago" | grep -E "activated|deactivated|Associated" | head -50

# Wi-Fiプロファイルの詳細情報
sudo cat /etc/NetworkManager/system-connections/*.nmconnection 2>/dev/null |
  grep -E "ssid|timestamp|type=wifi"

# ログから接続先SSIDと接続日時を抽出
journalctl -u NetworkManager | grep "ssid\|SSID\|connected to" | tail -30

💡 FACT: 米国の連邦裁判所の判例(U.S. v. Carpenter, 2018年)では、位置情報を含む電子記録が修正第4条の保護対象であるという判断が下されました。この判決以降、Wi-Fi接続履歴やBluetoothペアリング記録が「移動の記録」として法的証拠価値を持つことが広く認識されるようになっています。

③ Bluetoothのペアリング・接続履歴を調べる

Windows(PowerShell):

# ペアリングされたBluetoothデバイスの一覧
Get-PnpDevice -Class Bluetooth -ErrorAction SilentlyContinue |
  Select-Object FriendlyName, Status, InstanceId | Format-Table -AutoSize

# Bluetoothデバイスの詳細(MACアドレス含む)をレジストリから取得
Get-ChildItem "HKLM:\SYSTEM\CurrentControlSet\Services\BTHPORT\Parameters\Devices" -ErrorAction SilentlyContinue |
  ForEach-Object {
    $props = Get-ItemProperty $_.PsPath -ErrorAction SilentlyContinue
    [PSCustomObject]@{
      DeviceAddress = $_.PSChildName -replace '(..)(..)(..)(..)(..)(..)', '$1:$2:$3:$4:$5:$6'
      DeviceName    = $props.Name
      LastSeen      = if ($props.LastSeen) { [datetime]::FromFileTime($props.LastSeen) }
      LastUsed      = if ($props.LastUsed) { [datetime]::FromFileTime($props.LastUsed) }
    }
  } | Format-Table -AutoSize

# BluetoothデバイスのイベントログからPIN入力・接続イベントを確認
Get-WinEvent -LogName "Microsoft-Windows-Bluetooth-BthLEPreparingToSleep/Analytic" -ErrorAction SilentlyContinue |
  Select-Object TimeCreated, Message | Select-Object -First 10

macOS:

# ペアリング済みBluetoothデバイスの一覧
system_profiler SPBluetoothDataType 2>/dev/null |
  grep -A5 "Device Name\|Address\|Connected\|Last Connected"

# Bluetoothシステムログを確認
log show --predicate 'subsystem == "com.apple.bluetooth"' --last 7d |
  grep -E "connected|disconnected|paired" | head -50

# Bluetoothデバイスのplistから詳細を確認
sudo defaults read /Library/Preferences/com.apple.Bluetooth.plist 2>/dev/null |
  grep -A3 "DeviceAddress\|LastNameUpdate\|LastServicesUpdate"

【ETW 深層分析編】Windowsカーネルが語る超詳細な実行記録

ETW(Event Tracing for Windows)はWindowsカーネルに組み込まれた超高性能なトレーシングフレームワークです。プロセス・ネットワーク・ディスクI/O・メモリアロケーション・レジストリアクセスに至るまで、システムのあらゆる動作をほぼゼロオーバーヘッドで記録できます。通常のイベントログより遥かに詳細で高速なため、APT(Advanced Persistent Threat)レベルの攻撃調査にも使用されます。

💡 FACT: MicrosoftのDefender for EndpointはETWをバックエンドの主要データソースとして使用しています。ETWプロバイダは2,000以上存在し、その中にはカーネルレベルのプロセス生成・DLLロード・ネットワーク接続をミリ秒単位で記録するものが含まれます。ブルーチームのセキュリティエンジニアはETWを「Windows標準搭載の最強センサー」と表現することがあります。

① ETWプロバイダの確認と有効化(Windows)

Windows(管理者権限のコマンドプロンプト / PowerShell):

# 利用可能なETWプロバイダの一覧(2,000以上存在する)
logman query providers | head -50

# 特定キーワードでプロバイダを検索
logman query providers | Select-String "Network\|Process\|Security"

# 重要なプロバイダの詳細を確認
logman query providers "Microsoft-Windows-Kernel-Process"
logman query providers "Microsoft-Windows-Kernel-Network"
logman query providers "Microsoft-Windows-DNS-Client"

# ETWセッションの一覧(現在動作中のトレースセッション)
logman query -ets

# NTKernelLoggerセッション(常時動作しているカーネルトレース)の詳細
logman query "NT Kernel Logger" -ets

② ETWでプロセス・ネットワーク・ファイルI/Oをリアルタイムに記録する

Windows(管理者権限のコマンドプロンプト):

# プロセス生成をリアルタイムで記録するETWセッションを開始
logman create trace "ProcessTrace" -ets ^
  -p "Microsoft-Windows-Kernel-Process" 0x10 ^
  -o C:\forensics\process_trace.etl

# ネットワーク接続を記録するETWセッション
logman create trace "NetworkTrace" -ets ^
  -p "Microsoft-Windows-Kernel-Network" 0x20 ^
  -o C:\forensics\network_trace.etl

# ファイルI/Oを記録するETWセッション
logman create trace "FileTrace" -ets ^
  -p "Microsoft-Windows-Kernel-File" 0xFFFF ^
  -o C:\forensics\file_trace.etl

# 一定時間後にセッションを停止(例:60秒間収集)
Start-Sleep 60
logman stop "ProcessTrace" -ets
logman stop "NetworkTrace" -ets
logman stop "FileTrace" -ets

# ETLファイルを人が読めるXML/TXTに変換
tracerpt C:\forensics\process_trace.etl -o C:\forensics\process_trace.xml -of XML
tracerpt C:\forensics\network_trace.etl -o C:\forensics\network_trace.txt -of CSV

③ xperfでシステム全体の詳細トレースを取得する

Windows(Windows Performance Toolkit / 管理者権限):

# Windows Performance Toolkit(xperf)のインストール確認
# Windows SDKに含まれる / winget install Microsoft.WindowsSDK.10.0.22621

# すべての主要カーネルイベントを同時に記録(包括的フォレンジックトレース)
xperf -on PROC_THREAD+LOADER+DISK_IO+HARD_FAULTS+DPC+INTERRUPT+CSWITCH+PROFILE+NETWORKTRACE ^
  -f C:\forensics\kernel_trace.etl

# 一定時間後に停止(例:30秒)
timeout /t 30
xperf -d C:\forensics\kernel_trace_merged.etl

# Windows Performance Analyzer(WPA)でGUI解析(インストールされている場合)
# wpa C:\forensics\kernel_trace_merged.etl

# xperfコマンドラインでプロセス一覧を抽出
xperf -i C:\forensics\kernel_trace_merged.etl -o C:\forensics\process_summary.txt -a process

④ SilkETW・SealighterでETWを実践的なセキュリティ監視に活用する

Windows(SilkETW / PowerShell):

# SilkETW(Microsoft製・無償)でPowerShell実行をリアルタイム監視
# .\SilkETW.exe -t user -pn Microsoft-Windows-PowerShell -ot file -p C:\forensics\ps_etw.json

# Microsoft-Windows-Threat-Intelligenceプロバイダ(プロセスインジェクション検出)
# このプロバイダはEDRが使用する最重要プロバイダの一つ
logman query providers "Microsoft-Windows-Threat-Intelligence"

# ETWを使ったリアルタイムのDNSクエリ監視
logman create trace "DnsTrace" -ets ^
  -p "Microsoft-Windows-DNS-Client" 0xFFFF ^
  -o C:\forensics\dns_etw.etl
Start-Sleep 120
logman stop "DnsTrace" -ets
tracerpt C:\forensics\dns_etw.etl -o C:\forensics\dns_queries.csv -of CSV

【マルウェア静的解析編】実行せずに不審ファイルの正体を暴くコマンド

不審なファイルを発見したとき、実行して確認するのは危険です。「静的解析」とはファイルを実行せずにその内容・構造・特性を調べる手法です。ハッシュ値の照合・文字列抽出・ファイル形式の深掘り・インポートAPI分析など、コマンドだけで驚くほど多くの情報が得られます。

① ファイルの基本的な特性を静的に調べる

macOS / Linux:

# ファイルの種類・アーキテクチャを確認
file suspicious_file.exe
file -b --mime-type suspicious_file

# SHA-256/MD5ハッシュを計算してVirusTotalに照合
sha256sum suspicious_file.exe
md5sum suspicious_file.exe

# バイナリの基本情報を確認(ELFの場合)
readelf -h suspicious_binary     # ELFヘッダー
readelf -l suspicious_binary     # プログラムヘッダー(セグメント)
readelf -s suspicious_binary     # シンボルテーブル

# PEファイル(Windows実行ファイル)の情報を確認(pefileが必要)
python3 -c "
import pefile, sys
pe = pefile.PE(sys.argv[1])
print('Machine:', hex(pe.FILE_HEADER.Machine))
print('Timestamp:', pe.FILE_HEADER.TimeDateStamp)
print('Sections:', [s.Name.decode().strip() for s in pe.sections])
print('Imports:', [e.dll.decode() for e in pe.DIRECTORY_ENTRY_IMPORT] if hasattr(pe, 'DIRECTORY_ENTRY_IMPORT') else 'None')
" suspicious_file.exe 2>/dev/null

Windows(PowerShell):

# ファイルのデジタル署名を確認
Get-AuthenticodeSignature "C:\path\to\suspicious.exe" |
  Select-Object Path, Status, StatusMessage, SignerCertificate

# 署名なし・無効署名のファイルは要注意
$files = Get-ChildItem "C:\Users\$env:USERNAME\Downloads\" -Include "*.exe","*.dll","*.ps1" -Recurse
$files | ForEach-Object {
  $sig = Get-AuthenticodeSignature $_.FullName -ErrorAction SilentlyContinue
  if ($sig.Status -ne "Valid") {
    Write-Host "⚠ 署名なし/無効: $($_.FullName)"
    Write-Host "   ステータス: $($sig.Status)"
  }
}

# PEファイルのコンパイル日時を確認(タイムスタンプ偽装のチェック)
$bytes = [System.IO.File]::ReadAllBytes("C:\path\to\suspicious.exe")
$peOffset = [BitConverter]::ToInt32($bytes, 0x3C)
$timestamp = [BitConverter]::ToInt32($bytes, $peOffset + 8)
$compileTime = [DateTimeOffset]::FromUnixTimeSeconds($timestamp).LocalDateTime
Write-Host "PEコンパイル日時: $compileTime"

② インポートAPIから不審な機能を推測する

マルウェアが使うWindowsAPIには典型的なパターンがあります。インポートしているAPIを確認することで、そのファイルが「何をしようとしているか」を実行前に推測できます。

macOS / Linux(stringsとgrepの組み合わせ):

# 危険なWindowsAPIをインポートしているか確認
strings suspicious.exe | grep -iE \
  "VirtualAlloc|VirtualProtect|WriteProcessMemory|CreateRemoteThread|
   ShellExecute|WinExec|CreateProcess|LoadLibrary|GetProcAddress|
   InternetOpen|HttpSendRequest|URLDownloadToFile|
   RegSetValue|RegCreateKey|
   CryptEncrypt|CryptDecrypt|
   IsDebuggerPresent|CheckRemoteDebuggerPresent" | sort -u

# ネットワーク通信機能の確認
strings suspicious.exe | grep -iE \
  "socket|connect|send|recv|WSAStartup|InternetConnect|
   WinHttpOpen|curl_easy|libcurl" | sort -u

# 難読化・パッキングの兆候(高エントロピーセクションの存在)
strings suspicious.exe | grep -E "UPX|MPRESS|Themida|VMProtect|PECompact" | head -5

# C2サーバーのIPアドレス・ドメインらしき文字列を抽出
strings suspicious.exe | grep -E "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" | sort -u
strings suspicious.exe | grep -E "https?://[a-zA-Z0-9.-]+\.[a-z]{2,}" | sort -u

💡 FACT: MITRE ATT&CKデータベースに登録された実際のマルウェアサンプル分析によると、90%以上のマルウェアがVirtualAllocVirtualProtectWriteProcessMemoryのいずれかをインポートしています。これらはコードインジェクション・シェルコード実行・プロセスハロウイングに必須のAPIです。逆にこれらが使われていないマルウェアは、動的にAPIアドレスを解決する(GetProcAddressを使う)より高度な難読化を施している可能性があります。

③ objdump・nm・rabin2でバイナリを深く解析する

macOS / Linux:

# objdumpでPEファイルのセクション一覧を確認
objdump -h suspicious.exe 2>/dev/null | grep -E "Name|VMA|Size"

# nmでシンボルテーブルを確認(静的リンクの場合に有効)
nm suspicious_binary 2>/dev/null | grep -v "^$" | head -30

# rabin2(radare2付属)でより詳細な静的解析
# sudo apt install radare2
rabin2 -I suspicious.exe 2>/dev/null    # 基本情報
rabin2 -i suspicious.exe 2>/dev/null    # インポート関数一覧
rabin2 -e suspicious.exe 2>/dev/null    # エクスポート関数一覧
rabin2 -S suspicious.exe 2>/dev/null    # セクション情報(エントロピー値含む)
rabin2 -z suspicious.exe 2>/dev/null    # データセクションの文字列
rabin2 -H suspicious.exe 2>/dev/null    # ファイルハッシュ(md5/sha1/sha256)

④ Windowsで静的解析に使えるコマンドラインツール

Windows(PowerShell / Sysinternals):

# sigcheck(Sysinternals)でファイルの詳細情報とVirusTotalスキャン
# .\sigcheck.exe -vt -h suspicious.exe   # VirusTotalに自動照合(-vt)

# PEファイルのセクション情報をPowerShellで確認
$bytes = [System.IO.File]::ReadAllBytes("suspicious.exe")
$peOffset = [BitConverter]::ToInt32($bytes, 0x3C)
$numSections = [BitConverter]::ToUInt16($bytes, $peOffset + 6)
$optHeaderSize = [BitConverter]::ToUInt16($bytes, $peOffset + 20)
$sectionOffset = $peOffset + 24 + $optHeaderSize

Write-Host "セクション数: $numSections"
for ($i = 0; $i -lt $numSections; $i++) {
  $off = $sectionOffset + ($i * 40)
  $name = [System.Text.Encoding]::ASCII.GetString($bytes[$off..($off+7)]).TrimEnd([char]0)
  $virtualSize = [BitConverter]::ToUInt32($bytes, $off + 8)
  Write-Host "  セクション: $name  仮想サイズ: $virtualSize bytes"
}

# PowerShellでYARAルールを実行(yaraコマンドが必要)
# yara -r malware_rules.yar C:\suspicious_folder\

まとめ

本記事で紹介したコマンドと手法を一覧にまとめました。

カテゴリコマンド / 手法調査目的
LNKファイルWScript.Shell CreateShortcut + Recentフォルダファイルアクセス履歴と元ファイルパスの復元
LNKファイル外部ドライブ・UNCパスのLNK抽出USBや共有フォルダへのアクセス証明
LNKファイルAutomaticDestinations(ジャンプリスト)アプリごとの最近使ったファイル一覧
hiberfil.syshiberfil.sys のサイズ・更新日時確認最後のハイバネーション日時と内容サイズ
hiberfil.sysVolatility3でhiberfil.sysを解析ハイバネーション時のプロセス・接続の復元
hiberfil.syspagefile.sys に対してstrings解析スワップ済みメモリからの文字列・認証情報抽出
Wi-Fi・BTWLAN-AutoConfig イベントID 8001/8002/8003Wi-Fi接続成功・失敗・切断の正確な日時
Wi-Fi・BTBTHPORT レジストリキーBluetoothデバイスの最終接続・使用日時
Wi-Fi・BTnmcli / airport / journalctl NetworkManagerLinux/macOSのWi-Fi接続履歴の詳細
ETWlogman + Kernel-Process/Network プロバイダカーネルレベルのプロセス・通信のリアルタイム記録
ETWxperf -on PROC_THREAD+NETWORKTRACE包括的なカーネルトレースの取得と解析
ETWThreat-Intelligence プロバイダプロセスインジェクション検出(EDRと同等)
マルウェア静的解析Get-AuthenticodeSignatureデジタル署名の有効性確認
マルウェア静的解析strings + grep(危険APIパターン)インポートAPIからマルウェアの機能を推測
マルウェア静的解析rabin2(radare2)/ PEセクション解析バイナリ構造・エントロピー・インポート詳細

フォレンジック7弾シリーズの奥深さ

第7弾まで来て、改めて気づくことがあります。Windows・macOS・Linuxというプラットフォームは、セキュリティ調査者にとって驚くほど多くの「証拠の宝庫」です。

今回だけで見ても、LNKファイルは「そのファイルにアクセスした事実」を元ファイル削除後も保持し、hiberfil.sysは「電源を切ったあとも」メモリの残像を持ち、Wi-Fi接続ログは「その日その時刻にどのネットワークにいたか」を記録し、ETWはカーネルレベルで「すべての動作をミリ秒単位で」記録しています。

これらはすべてOSが自動的に・無意識に積み重ねてきたデータです。フォレンジック調査の本質は「普段から自動的に積み重なっているこのデータを、いかに素早く・正確に読み解くか」にあります。コマンドはその最もシンプルで強力な道具です。


※ 本記事の内容は情報セキュリティの学習・自己管理目的で掲載しています。他者のシステムへの無断調査は不正アクセス禁止法により処罰の対象となります。hiberfil.sys・pagefile.sysの取得、ETWトレース、マルウェア静的解析は自分が管理するシステム上でのみ実施してください。企業・組織内での調査は法務・情報セキュリティ部門の承認のもとで実施してください

コメント