プロセスの親子関係とファイル作成
report.txtを生成した記録から、生成元のPythonと親のエディターを調べます。後から同じPIDを使った別プロセスが混ざる例も検索し、時刻、パス、GUIDの役割を確認します。
説明
プロセスIDは終了後に再利用されます。SysmonのProcessGuidとParentProcessGuidを使うと、同じ端末で観測したプロセスの親子関係をPIDだけより安全に追えます。
report.txtを生成した記録から、生成元のPythonと親のエディターを調べます。後から同じPIDを使った別プロセスが混ざる例も検索し、時刻、パス、GUIDの役割を確認します。
1生成されたファイルを検索する
pathに一致する生成記録を起点にします。sha256はこの表では説明用の短縮値です。
from oplab import *
db=connect(3)
show(db, 'SELECT生成されたファイルを検索する * FROM files WHERE path="C:/Users/alice/report.txt"')f1は時刻13、生成元GUIDはg2です。ファイル名だけでは同名の別ファイルと区別できないため、端末と生成元も残します。
2生成元の実行内容を調べる
端末とGUIDを使ってファイル生成とプロセス生成を結合します。
show(db, 'SELECT生成元の実行内容を調べる f.id,p.id,p.pid,p.image,p.command FROM files f JOIN processes p USING(host,guid)')report.pyを実行したpython.exeへ対応しました。Pythonという実行ファイル名だけでなく、引数のスクリプト名が調査の手掛かりになります。
3親プロセスを調べる
子のparentと親のguidを同じ端末内で結びます。
show(db, 'SELECT親プロセスを調べる c.guid,c.image,p.guid AS parent_guid,p.image AS parent_image FROM processes c JOIN processes p ON c.host=p.host AND c.parent=p.guid WHERE c.guid="g2"')親はg1のeditor.exeです。親子関係は起動の連続性を示しますが、利用者が意図して起動したかは別の調査事項です。
4PIDだけで検索した結果を見る
親のPID400を検索し、再利用の例を確認します。
show(db, 'SELECTPIDだけで検索した結果を見る t,guid,pid,image FROM processes WHERE pid=400 ORDER BY t')時刻50にはviewer.exeがPID400を使っています。後のプロセス一覧だけを見て親を決めると、editor.exeを取り違えます。
5祖先を再帰検索する
WITH RECURSIVEでg2から親GUIDを順にたどります。試料の親関係は循環しない構造です。
show(db, 'WITH祖先を再帰検索する RECURSIVE chain(guid,parent,image,depth) AS (SELECT guid,parent,image,0 FROM processes WHERE guid="g2" UNION ALL SELECT p.guid,p.parent,p.image,c.depth+1 FROM processes p JOIN chain c ON p.guid=c.parent WHERE p.host="ws7") SELECT * FROM chain ORDER BY depth')g2、g1の順に得られます。g0のプロセス記録がないため、それ以前の親子関係はこの検索では分かりません。
6保存時刻と実行開始を並べる
プロセス開始より後にファイル生成が観測されているか照合します。
show(db, 'SELECT保存時刻と実行開始を並べる p.id AS process_event,p.t AS started,f.id AS file_event,f.t AS created,f.t-p.t AS seconds FROM files f JOIN processes p USING(host,guid)')生成は開始の1秒後です。p2とf1が対応することを根拠にし、ファイルの内容や悪性判断は別の確認として残します。
まとめ
生成は開始の1秒後です。p2とf1が対応することを根拠にし、ファイルの内容や悪性判断は別の確認として残します。
表示された証拠IDと検索条件を残すと、調査結果を元の記録までたどれます。
操作履歴と解説を振り返れます。
Python 3.15 / SQLite・固定の調査記録
from oplab import *
db=connect(3)
show(db, 'SELECT * FROM files WHERE path="C:/Users/alice/report.txt"')id | t | host | guid | path | sha256 f1 | 13 | ws7 | g2 | C:/Users/alice/report.txt | abc7
show(db, 'SELECT f.id,p.id,p.pid,p.image,p.command FROM files f JOIN processes p USING(host,guid)')id | id | pid | image | command f1 | p2 | 500 | python.exe | python.exe report.py
show(db, 'SELECT c.guid,c.image,p.guid AS parent_guid,p.image AS parent_image FROM processes c JOIN processes p ON c.host=p.host AND c.parent=p.guid WHERE c.guid="g2"')guid | image | parent_guid | parent_image g2 | python.exe | g1 | editor.exe
show(db, 'SELECT t,guid,pid,image FROM processes WHERE pid=400 ORDER BY t')t | guid | pid | image 10 | g1 | 400 | editor.exe 50 | g3 | 400 | viewer.exe
show(db, 'WITH RECURSIVE chain(guid,parent,image,depth) AS (SELECT guid,parent,image,0 FROM processes WHERE guid="g2" UNION ALL SELECT p.guid,p.parent,p.image,c.depth+1 FROM processes p JOIN chain c ON p.guid=c.parent WHERE p.host="ws7") SELECT * FROM chain ORDER BY depth')guid | parent | image | depth g2 | g1 | python.exe | 0 g1 | g0 | editor.exe | 1
show(db, 'SELECT p.id AS process_event,p.t AS started,f.id AS file_event,f.t AS created,f.t-p.t AS seconds FROM files f JOIN processes p USING(host,guid)')process_event | started | file_event | created | seconds p2 | 12 | f1 | 13 | 1
演習完了