EDRのプロセス・ファイル・通信ログ
端末、中央記録、対応処理を照合し、記録から言える範囲を判断します。
説明
EDRは端末の活動を集め、関連するイベントを分析して対応につなげます。記録の収集、検知、端末への措置は別々の処理です。
Sysmonのプロセス識別子という考え方に沿った固定記録を、SQLで調べます。時刻は開始からの秒、guidは短縮した教材用識別子です。PIDの再利用と中央への転送遅延を順に確かめます。
端末、中央記録、対応処理を照合し、記録から言える範囲を判断します。
1端末とイベントの種類を確認する
5行の記録を発生順に並べます。
from sp02 import *
db = connect()
show端末とイベントの種類を確認する(db,"SELECT record,host,t,kind,guid,pid FROM event ORDER BY t")ws7のPID 410とws8のPID 410は別の端末です。PIDだけでは結び付けられません。
2同じPIDが再利用される
ws7だけに絞っても開始時刻が異なるプロセスが残ります。
show同じPIDが再利用される(db,"SELECT t,guid,pid,image FROM event WHERE host='ws7' AND kind='process' ORDER BY t")0秒のg1と70秒のg2は別プロセスです。プロセス識別子と端末を組み合わせて追います。
3一つのプロセスの活動を並べる
g1に属するファイルと通信を取得します。
show一つのプロセスの活動を並べる(db,"SELECT t,kind,detail FROM event WHERE host='ws7' AND guid='g1' ORDER BY t")起動、report.txtの生成、443番ポートへの接続が同じg1に対応します。この並びだけで悪意までは断定できません。
4起動元を確認する
プロセス起動の行には親の識別子もあります。
show起動元を確認する(db,"SELECT guid,parent,image FROM event WHERE kind='process' ORDER BY t")g1とg2の親はg0です。ただし今回の資料にはg0の起動行がありません。親の実行ファイル名まで推測で補いません。
5実行ファイルとハッシュを対応付ける
公開試料のSHA-256を計算し、記録値と照合します。
print(hashlib.sha256実行ファイルとハッシュを対応付ける(PAYLOAD).hexdigest())
show(db,"SELECT e.guid,e.image,i.sha256 FROM event e JOIN image i USING(guid) WHERE e.kind='process'")ハッシュはファイル内容の同一性を確認する値です。同じ名前の別ファイルや、同じファイルから起動した別プロセスを区別する材料になります。
6中央へ届くまでの時間を求める
ingestedは中央へ取り込んだ時刻です。
show中央へ届くまでの時間を求める(db,"SELECT record,t,ingested,ingested-t AS delay_seconds FROM event ORDER BY record")接続記録3は発生8秒、取込20秒で12秒遅れています。中央で10秒時点に検索してもまだ見えません。
7検索時点による差を確認する
10秒までに中央へ届いたg1の記録だけを取得します。
show検索時点による差を確認する(db,"SELECT record,kind FROM event WHERE guid='g1' AND ingested<=10 ORDER BY t")起動とファイルだけが出ます。検索結果に接続がないことと、端末が接続しなかったことは同じではありません。
まとめ
端末とプロセス識別子で活動を結び付けます。
ファイルのハッシュとプロセスの識別子は用途が異なります。
発生時刻と取込時刻を分けて調べます。
操作履歴と解説を振り返れます。
Python 3.15 / SQLite / 固定の端末記録
from sp02 import *
db = connect()
show(db,"SELECT record,host,t,kind,guid,pid FROM event ORDER BY t")record | host | t | kind | guid | pid 1 | ws7 | 0 | process | g1 | 410 5 | ws8 | 3 | network | g3 | 410 2 | ws7 | 4 | file | g1 | 410 3 | ws7 | 8 | network | g1 | 410 4 | ws7 | 70 | process | g2 | 410
show(db,"SELECT t,guid,pid,image FROM event WHERE host='ws7' AND kind='process' ORDER BY t")t | guid | pid | image 0 | g1 | 410 | diagnostic.exe 70 | g2 | 410 | viewer.exe
show(db,"SELECT t,kind,detail FROM event WHERE host='ws7' AND guid='g1' ORDER BY t")t | kind | detail 0 | process | start 4 | file | report.txt 8 | network | 192.0.2.20:443
show(db,"SELECT guid,parent,image FROM event WHERE kind='process' ORDER BY t")guid | parent | image g1 | g0 | diagnostic.exe g2 | g0 | viewer.exe
print(hashlib.sha256(PAYLOAD).hexdigest())
show(db,"SELECT e.guid,e.image,i.sha256 FROM event e JOIN image i USING(guid) WHERE e.kind='process'")6beeffaa5d98894a2b7169eb6616bd5ac650232ed1cda83be77ae1c213d03001 guid | image | sha256 g1 | diagnostic.exe | 6beeffaa5d98894a2b7169eb6616bd5ac650232ed1cda83be77ae1c213d03001
show(db,"SELECT record,t,ingested,ingested-t AS delay_seconds FROM event ORDER BY record")record | t | ingested | delay_seconds 1 | 0 | 1 | 1 2 | 4 | 6 | 2 3 | 8 | 20 | 12 4 | 70 | 71 | 1 5 | 3 | 4 | 1
show(db,"SELECT record,kind FROM event WHERE guid='g1' AND ingested<=10 ORDER BY t")record | kind 1 | process 2 | file
演習完了