All Articles

Windows Forensic で利用される SRUM の解析に関するメモ書き

先日とあるフォレンジックの勉強会に参加させていただいた際に SRUM(System Resource Usage Monitor) という Windows のアーティファクトの存在を知りました。

Forensic 界隈では常識的なシステムなのかもしれませんが、インサイド Windows や公式のドキュメントを検索してもほとんど情報が見つからなかったので、今回新しく知る機会を得られて非常に良かったと思います。

Forensic の観点では SRUM の情報は不審なプロセスやネットワークのアクティビティの発見に利用しているようでしたが、今回は主にパフォーマンス系のトラブルシューティングの観点で SRUM の情報を利用する方法についてまとめてみようと思います。

参考:Windows 10, version 1809 basic diagnostic events and fields (Windows 10) - Windows Privacy | Microsoft Learn

もくじ

SRUM とは

SRUM(System Resource Usage Monitor) は、アプリケーションやサービス等の利用状況を監視するWindowsの機能で、Windows 8 から導入されているらしいです。

SRUM が収集したデータはシステム内に一時保存された後、1 時間ごと、もしくはシャットダウン時に C:\Windows\System32\sru\SRUDB.dat に転送されるようです。

なお、以下の記事では SRUM が収集した情報は、SRUDB.dat に転送されるまで一時的に SOFTWARE レジストリに保持されると記載されています。

参考:フォレンジックにおけるSRUMの活用: NECセキュリティブログ | NEC

しかし、以下では最新の Windows では SRUM で収集した情報は SOFTWARE レジストリではなくメモリ内の記憶領域に保存されるようになっていると説明されています。

In recent versions of Windows, SRUM no longer uses the registry to store temporarily database records. Nowadays, SRUM relies on 2 types of storage:

A Tier1 store, which is in memory and is updated every Tier1Period (60 seconds by default) with the data from the SRUM extensions. A Tier2 store, which is the SRUM database on disk and is updated every Tier2Period (1 hour by default) with the content of the Tier1 store.

参考:SRUM Analysis · WithSecureLabs/chainsaw Wiki

SRUM の動作について正式に公開されているドキュメントは確認できませんが、いずれにせよ一時保存されたデータがおよそ 1 時間ごとに C:\Windows\System32\sru\SRUDB.dat に保存されるという点については共通しているようです。

SRUM には、ネットワークデータ通信の使用量やアプリケーションの使用状況に関する統計情報が記録されます。

image-20250316130504584

参考:Beyond Windows Forensics with Built-in Microsoft Tooling

参考:SRUM: Forensic Analysis of System Resource Utilization Monitor

なお、Forensic insights about the DLLs related to the SRUM extensions の記載によると、SRUM データベースに保存される情報はいくつかの拡張機能で収集されていることが示されています。

ネットワークデータに関する情報収集は WFP に依存しており、記録される通信データのサイズには OSI モデル第 2 層のフレームのサイズが記録されるそうです。

また、端末のネットワークトラフィックが VPN プロセスを経由する場合、監査された入出力データのサイズは VPN プロセスに紐づけられるようです。

また、この SRUDB は Extensible Storage Engine(ESE) というフォーマットで保存されているらしく、あとで使用する通り libesedb などのライブラリを用いて解析を行うこともできます。

参考:拡張可能なストレージ エンジン - Win32 apps | Microsoft Learn

参考:libyal/libesedb: Library and tools to access the Extensible Storage Engine (ESE) Database File (EDB) format.

SRUM データベースの解析

C:\Windows\System32\sru\SRUDB.dat に保存された情報は srum-dump や NetworkUsageView などのツールを使用して解析することができます。

参考:MarkBaggett/srum-dump: A forensics tool to convert the data in the Windows srum (System Resource Usage Monitor) database to an xlsx spreadsheet.

参考:Displays network usage information stored in the SRUDB.dat database of Windows 10/8.

NetworkUsageView を使用する場合、アプリケーションを起動して [Options]>[Advanced Options] から調査対象のデバイスで取得した SRUDB.dat をロードすることで SRUMDB からネットワークデータの情報を参照できます。

image-20250315162817723

なお、srum-dump を使用した場合にはネットワークデータだけでなくアプリケーションの利用情報なども簡単にダンプすることができたので、より多くの情報を参照したいのであれば srum-dump を使用するのがよさそうです。

ちなみに、C:\Windows\System32\sru\SRUDB.dat のコピーは以下のようなエラーで結構頻繁に失敗します。(大体 1 分くらい待つとコピーできるようになります)

image-20250315170250248

なので、例えば以下のように robocopy などを使用してコピー操作をリトライさせるようにすると良いと思います。

robocopy "C:\Windows\System32\sru" "C:\Users\Public\Downloads" /B

NetworkUsageView を使用した解析

1 GB のファイルを Microsoft Edge からアップロードした場合の SRUMDB を解析してみます。

まずは Microsoft Edge から適当なアップロードサイトに 1 GB のファイルアップロードを実施します。

Wire Shark で取得したパケットキャプチャの統計情報でも、ちょうど 1 GB のデータを外部アドレスに送信していることを確認できます。

image-20250316104500109

実際にこのアップロード操作を行った端末でキャプチャされた SRUMDB を解析すると、Microsoft Edge のアプリケーションからちょうど 1 GB 程度のアップロードが行われていることがわかります。

image-20250316105112089

注意が必要なのは、この時の Timestamp の値は実際に通信が発生した時刻ではなく、SRUMDB にデータが書き込まれた時間である点です。

また、この時表示されている通信データサイズなどは、前回のイベント転送以降に記録された情報に該当します。(SRUMDB にデータが転送されるのはおよそ 1 時間ごと、もしくは端末のシャットダウン時です。)

このあたりの説明は以下の記事にて非常にわかりやすく説明されており、参考になりました。

image-20250316123616251

参考:フォレンジックにおけるSRUMの活用: NECセキュリティブログ | NEC

Note:App Name が空の項目について

ちなみに、1 番上の App ID が 1 で App Name が空の項目ですが、これは SRUMDB のテーブルの一つである SruDbIdMapTable の idBlob カラムの値が空であることを示しているようです。

実際に以下のスクリプトで libesedb ライブラリを使用して SRUMDB の SruDbIdMapTable テーブルをダンプしてみると、App ID が 1 となる項目の場合は idBlob が None となることを確認できます。

# sudo apt-get install libesedb-utils libesedb-dev python3-libesedb
import pyesedb

esedb_file = "SRUDB.dat"
esedb = pyesedb.file()
esedb.open(esedb_file)

table_names = [esedb.get_table(i).get_name() for i in range(esedb.number_of_tables)]
print(table_names)

table = esedb.get_table_by_name("SruDbIdMapTable")
column_names = [table.get_column(i).get_name() for i in range(table.number_of_columns)]
print(column_names)

for record_index in range(table.number_of_records):
	record = table.get_record(record_index)
	id_type = record.get_value_data_as_integer(0)
	id_index = record.get_value_data_as_integer(1)

	try:
		id_blob = record.get_value_data(2).decode("utf-16le", errors="ignore").strip("\x00")
		if id_type == 0:
			print(f"AppID: {id_index}, AppName: {id_blob}")
	
	except:
		# AppID: 0 AppName: None
		if id_type == 0:
			print(f"AppID: {id_index}, AppName: {record.get_value_data(2)}")

実際のところこの App Id が 1 のエントリが何を指しているのかを示す情報を見つけることはできませんでした。

ただし、Chat GPT の回答や以下のスレッドのコメントなどを見ると、システム全体の I/O を追跡しているのではないかという情報を確認できました。

image-20250316124903461

実際に Microsoft Edge から 1GB のファイルをアップロードした際には、ほぼ同程度の通信料が App ID 1 のエントリと紐づけられており、ある程度の信憑性はありそうに思えます。

image-20250316105112089

この辺りは、もし詳しい方がいればぜひ教えていただけると助かります。

Note:libesedb のビルド

今回は apt で libesedb をインストールしましたが、以下のコマンドでソースコードからビルドすることもできました。

sudo apt install git autoconf automake autopoint libtool pkg-config

wget https://github.com/libyal/libesedb/releases/download/20240420/libesedb-experimental-20240420.tar.gz
targz  libesedb-experimental-20240420.tar.gz
cd libesedb-20240420/

./configure --enable-python
make
sudo make install

参考:Building · libyal/libesdb Wiki

まとめ

SRUM は Forensic の用途で使用されることが多いようですが、個人的にはパフォーマンスやネットワーク系のトラブルシューティングにも非常に有用そうだと感じました(恐らくこちらが本来の用途だとは思いますが)

特に再現性の低いパフォーマンスや帯域逼迫系の問題の場合、負荷高騰を引き起こしたプロセスの特定が調査のボトルネックになることがしばしばありますが、SRUM の解析を行うことでこのような問題の原因をスムーズに調査することができるようになりそうです。