一覧OS-11-3 · Windowsの基本構造

Windowsサービスの実行アカウントと設定

サービスのPIDから、レジストリ設定・ファイル・ストリーム・ハンドルの参照関係を調べます。

説明

Windowsのサービスは設定されたアカウントで動き、ファイルやレジストリキーなどの資源を開いて利用します。開いた資源へのハンドルは、パス文字列やサービス名とは別の参照です。NTFSのファイルには複数のデータストリームを持たせることもできます。

LabReaderサービスの実行主体とPIDを確認し、レジストリのConfigPathから設定ファイル、レポートへと参照をたどります。その後、ストリームの内容とハンドル表を調べ、設定上の参照先と現在開いている資源を照合します。

1サービスの実行主体とプロセス

LabReaderは教材用サービスです。サービス情報から名前、状態、実行アカウント、PID、実行ファイルを取り出します。

Get-CimInstance Win32_Serviceサービス情報 -Filter "Name='LabReader'"対象サービスを指定 | Select-Object Name,State,StartName,ProcessId,PathName主体と実行先

利用者ayaが操作するコンソールと、LocalServiceで動くサービスは別の主体です。サービスがファイルやレジストリへアクセスするときは、そのサービスプロセスのトークンが判定に使われます。

2レジストリの設定値

このサービスはHKLMの設定キーにあるConfigPathを使います。キーと値を確認します。

Get-ItemPropertyキー内の値を読む HKLM:\Software\Lbox\LabReader設定キー -Name ConfigPath値の名前 | Select-Object ConfigPath参照先だけ表示

HKLMはHKEY_LOCAL_MACHINEを指すPowerShellのドライブ名です。キーは階層、ConfigPathはキー内の値の名前です。値がファイルパスの文字列でも、レジストリの値と参照先のファイルは別のオブジェクトとしてアクセス制御されます。

3設定ファイルから出力先を確認

ConfigPathが指したJSONを読みます。reportPathはサービスが利用するレポートのパスです。

Get-Contentファイル内容 C:\Lab\settings.jsonレジストリ値の参照先 -Raw全体を一つの文字列で読む

レジストリ→設定ファイル→レポートという参照関係が分かります。設定ファイルを読めることだけでは、そこに書かれたレポートの読取り権もあるとは限りません。各対象のセキュリティ記述子を別々に確認します。

4一つのファイルにある複数のストリーム

report.txtには無名のデータストリームとauditという名前付きストリームがあります。ストリーム名と長さを表示します。

Get-Itemファイルの属性 C:\Lab\report.txt対象 -Stream *すべてのストリーム | Select-Object Stream,Length名前と長さ

無名の内容total=42は8バイト、auditのcheckedは7バイトです。NTFSでは同じファイルに複数のデータストリームを持てます。通常の内容読取りだけでは、名前付きストリームの存在を一覧できません。

5ストリームを指定して内容を読む

無名のストリームとauditを順に読みます。

Get-Content C:\Lab\report.txt無名の内容; Get-Content C:\Lab\report.txt -Stream audit名前付きの内容

同じファイル名でも、指定したストリームにより読むバイト列が変わります。名前付きストリームがあることだけで不正なファイルとは判断できません。ストリームの用途、生成元、内容を調べます。

6開いた資源の記録

handles.csvは二つのプロセスが持つハンドルを整理した教材表です。PID、ハンドル値、資源種別、参照先を読みます。

$handles = Import-Csv参照の記録を読む .\handles.csvハンドル表; $handles | Format-Table PID,Handle,Type,Target主体と参照先

PID4120は設定ファイルとレジストリキーを開いています。別のPID8000にも0x80がありますが、参照先はレポートです。ハンドル値はプロセス内の表で意味を持ち、数値だけを全プロセス共通のオブジェクトIDとして使えません。

7サービスのPIDで参照を絞る

最初のサービス情報にあったPID4120で、開いている資源を絞ります。

$handles | Where-Object PID -eq 4120サービスのプロセスだけ | Format-Table Handle,Type,Target資源を表示

この記録時点で二つの参照があります。設定値に書かれたreportPathと、現在開いているハンドルは同じ種類の証拠ではありません。パスを知っていても未使用か、過去に開いて閉じたかは、この一覧だけでは決まりません。

8同じハンドル値を持つ別プロセス

0x80だけを条件にすると何が混ざるかを確認します。

$handles | Where-Object Handle -eq "0x80"ハンドル値で絞る | Format-Table PID,Targetプロセスを含めて比較

二つの別の参照先が残ります。PIDとハンドル値を組にして参照を調べます。同じプロセスでも閉じたハンドル値が後から再利用される場合があるため、時系列の記録では取得時点も対応させます。

まとめ

サービスの資源アクセスは、そのサービスの実行主体で判定されます。

レジストリ値、ファイルパス、ストリーム、開いたハンドルは異なる参照情報です。

ハンドル値はプロセス内で解釈し、PIDと取得時点も含めて照合します。

操作履歴と解説を振り返れます。

PowerShell 7 / LAB\aya

1
Get-CimInstance Win32_Service -Filter "Name='LabReader'" | Select-Object Name,State,StartName,ProcessId,PathName
Name      : LabReader
State     : Running
StartName : NT AUTHORITY\LocalService
ProcessId : 4120
PathName  : C:\Lab\reader.exe
2
Get-ItemProperty HKLM:\Software\Lbox\LabReader -Name ConfigPath | Select-Object ConfigPath
ConfigPath
----------
C:\Lab\settings.json
3
Get-Content C:\Lab\settings.json -Raw
{"reportPath":"C:\\Lab\\report.txt","mode":"read"}
4
Get-Item C:\Lab\report.txt -Stream * | Select-Object Stream,Length
Stream Length
------ ------
:$DATA      8
audit       7
5
Get-Content C:\Lab\report.txt; Get-Content C:\Lab\report.txt -Stream audit
total=42
checked
6
$handles = Import-Csv .\handles.csv; $handles | Format-Table PID,Handle,Type,Target
PID  Handle Type Target
---  ------ ---- ------
4120 0x80   File C:\Lab\settings.json
4120 0x84   Key  HKLM\Software\Lbox\LabReader
8000 0x80   File C:\Lab\report.txt
7
$handles | Where-Object PID -eq 4120 | Format-Table Handle,Type,Target
Handle Type Target
------ ---- ------
0x80   File C:\Lab\settings.json
0x84   Key  HKLM\Software\Lbox\LabReader
8
$handles | Where-Object Handle -eq "0x80" | Format-Table PID,Target
PID  Target
---  ------
4120 C:\Lab\settings.json
8000 C:\Lab\report.txt

演習完了