【テクニカル・上級編】【ユーザーセッション切り替え検知】WMI イベントクエリを活用したログオン・ログオフおよび画面ロック状態の検出 – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク

序文:静寂なる監視者としてのVBScript

現代のエンタープライズ環境において、PowerShellやPythonが台頭して久しい。しかし、我々のような現場の最前線に立つアーキテクトは知っている。OSの深淵に根を張り、最小限のフットプリントで「沈黙の守護者」として機能し続けるのは、今なおVBScript(WSH)であることを。

ユーザーの離席、画面ロック、あるいは不意のログアウト。これらのセッション状態の変化をトリガーとした自動化処理は、セキュリティガバナンスや業務ログの精緻化において極めて重要なピースとなる。今回は、WMI(Windows Management Instrumentation)のイベントクエリを駆使し、Windows APIに頼らずともOSの鼓動をリアルタイムで検知する、極限の「セッション・センティネル(監視)」の実装について解説する。

—

1. WMIイベントクエリの真髄:ポーリングを捨て、イベントを待て

初心者は `Do…Loop` の中で `Win32_Process` を繰り返し取得し、CPUリソースを浪費する「ポーリング」に走る。だが、真のシニアエンジニアは WMI Event Query (WQL) を用いた 通知(Notification) モデルを採用する。

監視の対象:Win32_Process と LogonUI.exe

Windowsにおいて、画面がロックされた際、システムは `LogonUI.exe` を起動する。逆にロックが解除されればこのプロセスは消滅する。この「インスタンスの生成と消滅」をWMIでフックするのが、最も確実かつ軽量なアプローチだ。

  • __InstanceCreationEvent: プロセス(LogonUI.exe)が生成された = ロックされた
  • __InstanceDeletionEvent: プロセスが消滅した = 解除された

—

2. 実装:非同期イベントハンドリングの極致

以下に示すコードは、単なるスクリプトではない。メモリリークを抑止し、予期せぬエラーでもプロセスをハングさせないための、堅牢なテンプレートである。

‘
‘ Title: WMI Session Sentinel (Session Lock/Unlock Detector)
‘ Author: Legacy System Architect
‘ Description: WMIイベントクエリを利用し、セッションのロック/アンロックを非同期監視する
‘

Option Explicit

‘ — 設定エリア —
‘ WITHIN 句の秒数は、監視の精度とCPU負荷のトレードオフである。
‘ 2秒はエンタープライズ環境における黄金比だ。
Const POLLING_INTERVAL = 2

‘ — メインロジック —
Call MonitorSessionEvents()

Sub MonitorSessionEvents()
Dim strComputer, objWMIService, objSink
Dim strQueryCreation, strQueryDeletion

strComputer = “.”

‘ WMIサービスへの接続 ( impersonationLevelの明示は必須 )
Set objWMIService = GetObject(“winmgmts:{impersonationLevel=impersonate}!\\” & strComputer & “\root\cimv2”)

‘ 非同期受信用のシンク(Sink)オブジェクトを生成
‘ これにより、スクリプトはイベントを待機しながら別の処理を行うことも可能になる
Set objSink = WScript.CreateObject(“WbemScripting.SWbemSink”, “SINK_”)

‘ クエリの定義:LogonUI.exe の生成(ロック)を監視
strQueryCreation = “SELECT FROM __InstanceCreationEvent WITHIN ” & POLLING_INTERVAL & ” ” & _
“WHERE TargetInstance ISA ‘Win32_Process’ AND TargetInstance.Name = ‘LogonUI.exe'”

‘ クエリの定義:LogonUI.exe の消滅(アンロック)を監視
strQueryDeletion = “SELECT FROM __InstanceDeletionEvent WITHIN ” & POLLING_INTERVAL & ” ” & _
“WHERE TargetInstance ISA ‘Win32_Process’ AND TargetInstance.Name = ‘LogonUI.exe'”

‘ 非同期クエリの実行
objWMIService.ExecNotificationQueryAsync objSink, strQueryCreation
objWMIService.ExecNotificationQueryAsync objSink, strQueryDeletion

‘ 監視開始のログ(デバッグ用)
WScript.Echo “Session Monitoring Started. [” & Now & “]”

‘ メインスレッドを維持するための無限ループ
‘ WSHはイベント駆動型ではないため、何らかの待機が必要となる
Do
WScript.Sleep 10000 ‘ 10秒ごとにスリープし、CPU負荷を最小化
Loop
End Sub

‘ — イベントハンドラ:インスタンス生成時(ロック時) —
Sub SINK_OnObjectReady(objObject, objAsyncContext)
‘ ターゲットが Creation か Deletion かを判定
If objObject.Path_.Class = “__InstanceCreationEvent” Then
Call OnSessionLocked()
ElseIf objObject.Path_.Class = “__InstanceDeletionEvent” Then
Call OnSessionUnlocked()
End If
End Sub

‘ — 業務ロジック:ロック時の処理 —
Sub OnSessionLocked()
‘ ここにログ出力、バックグラウンドプロセスの停止、あるいはセキュリティフラグの立案を記述する
WScript.Echo “EVENT: Screen Locked – ” & Now
‘ Example: objShell.Run “logger.exe –event lock”, 0, True
End Sub

‘ — 業務ロジック:アンロック時の処理 —
Sub OnSessionUnlocked()
‘ 業務再開時の自動セットアップ、未送信データの同期などを記述
WScript.Echo “EVENT: Screen Unlocked – ” & Now
End Sub

‘ — クリーンアップ(通常、無限ループのため到達しないが、アーキテクチャの作法として記述) —
Sub SINK_OnCompleted(hResult, objErrorObject, objAsyncContext)
Set objErrorObject = Nothing
Set objAsyncContext = Nothing
End Sub

—

3. アーキテクトが教える「運用の急所」

メモリ最適化とライフサイクル

VBScriptにおいて最も恐れるべきは、COMオブジェクトの残存によるメモリリークだ。上記のコードでは `SWbemSink` を使用しているが、長期運用(数ヶ月単位の連続稼働)を行う場合、定期的なスクリプトの再起動をタスクスケジューラで行うのが、レガシー環境における「枯れた知恵」である。

WITHIN 句の重み

`WITHIN 2` という指定は、「2秒ごとにWMIリポジトリをスキャンせよ」という命令だ。これを `1` にするとリアルタイム性は増すが、低スペックなシンクライアント環境では `WmiPrvSE.exe` のCPU使用率が跳ね上がる。業務端末のスペックに合わせて 2〜5 の間で調整するのがプロの仕事だ。

ログオン・ログオフの検知への応用

セッションロックだけでなく、ログオン・ログオフそのものを検知したい場合は、`Win32_ComputerSystemEvent` よりも `Win32_LogonSession` クラスの `__InstanceCreationEvent` を監視する方が精度が高い。ただし、Windowsのログオンセッションは、システムアカウントやネットワークログオンを含め多岐にわたるため、`LogonType = 2`(インタラクティブログオン)によるフィルタリングが必須となる。

—

4. 結言:枯れた技術に魂を込める

VBScriptはもはや「新しい」技術ではない。しかし、OSのコアに近い場所で動作し、標準構成だけでこれほどの強力な監視システムを構築できるツールは他に類を見ない。

WMIイベントクエリをマスターすることは、WindowsというOSの挙動を支配することと同義である。現場の制約を言い訳にするのではなく、与えられた環境で最高効率の解を導き出す。その執念こそが、我々エンジニアを「伝説」へと昇華させるのである。

このコードが、貴殿のシステムの安定稼働と、運用の自動化に寄与することを願ってやまない。

タイトルとURLをコピーしました