這次 30 天鐵人賽,我想做的不是一個單純「偵測惡意程式」的小工具,而是一個簡化版的 Linux 行為式威脅偵測與回應系統。
我把這個專案暫時命名為:
BehaviorGuard
它的目標是讓系統可以回答:
整體架構預計會慢慢做到:
Linux Host
↓
Telemetry Collection
↓
Event Normalization
↓
Detection Rules
↓
Behavior Correlation
↓
Risk Scoring
↓
Alert
↓
Investigation
↓
Response
Day 1 先從最基本、同時也是 EDR 非常重要的一個資料來源開始:
Process。
平常我們會說:
Chrome 是一個程式
Python 是一個程式
Bash 是一個程式
但是當一個程式真正被執行後,作業系統會建立一個正在運作中的實體。
這個實體就叫:
Process
例如:
python3 test.py
當這行指令執行後,Linux 就會建立一個 Python Process。
每個 Process 都會有自己的編號,稱為:
PID
也就是:
Process ID
在 Linux Terminal 輸入:
ps aux
會看到類似:
USER PID %CPU %MEM COMMAND
root 1 0.0 0.1 /sbin/init
user 1325 0.0 0.2 bash
user 1632 0.1 1.0 python3
Day 1 不需要一次理解所有欄位。
先記住兩個:
PID
COMMAND
例如:
PID: 1632
COMMAND: python3
代表目前系統中有一個 Python Process,而它的 PID 是 1632。
Linux 裡有一個非常重要的虛擬檔案系統:
/proc
可以輸入:
ls /proc
會看到:
1
2
143
521
cpuinfo
meminfo
net
self
...
其中像:
1
2
143
521
這些數字其實都是 PID。
也就是說:
/proc/521
代表:
PID 521 的 Process
因此 /proc 可以提供大量目前系統正在運作的資訊,而這些資訊正是之後 BehaviorGuard 可以利用的 Telemetry 來源之一。
在 Terminal 輸入:
echo $$
例如輸出:
3501
代表現在這個 Shell 的 PID 是:
3501
因此它的 Process 資料可以在:
/proc/3501
找到。
也可以直接輸入:
ls /proc/$$
這裡的:
$$
代表目前 Shell 的 PID。
輸入:
ls /proc/$$
會看到很多資料:
cmdline
cwd
environ
exe
fd
maps
stat
status
...
這些資料對行為監控非常重要。
例如:
cmdline
可以查看這個 Process 執行時所使用的 Command Line。
status
可以查看:
PID
PPID
UID
Process Name
State
另外還有:
exe
可以知道實際執行的程式路徑。
以及:
fd
和 File Descriptor 有關。
Day 1 先從:
status
cmdline
開始。
輸入:
cat /proc/$$/status
可以看到類似:
Name: bash
State: S
Pid: 3501
PPid: 3490
Uid: 1000
Gid: 1000
其中:
Pid
就是目前 Process 的 PID。
而另一個很重要的是:
PPid
PPID 代表:
Parent Process ID
也就是:
是哪一個 Process 啟動了現在這個 Process。
單獨看到一個:
bash
其實很正常。
但是如果 Process 關係變成:
apache2
↓
bash
就會變得比較值得注意。
如果後面又變成:
apache2
↓
bash
↓
curl
↓
download.sh
整個行為就更可疑。
因為安全產品在判斷威脅時,不應該只看:
Process Name
更重要的是看:
誰啟動誰
也就是:
Process Tree
假設目前系統中有:
bash
└── python3
└── curl
可以理解成:
bash
啟動:
python3
而 Python 又啟動:
curl
每一層之間都可以透過:
PID
PPID
建立關係。
這也是後面 BehaviorGuard 要做 Behavior Correlation 的重要基礎。
例如:
bash
很正常。
curl
也很正常。
TCP Connection
本身也不一定有問題。
但如果看到:
bash
↓
curl
↓
Download Script
↓
Outbound Connection
就可能代表一段值得調查的行為。
因此未來 BehaviorGuard 不會只判斷:
這個程式危不危險?
而是會嘗試判斷:
這一連串行為組合起來是否可疑?
這就是之後會實作的:
Behavior Correlation
今天先建立基本專案架構。
mkdir behaviorguard
cd behaviorguard
建立資料夾:
mkdir agent detection response data logs
最後結構會像:
behaviorguard/
│
├── agent/
├── detection/
├── response/
├── data/
└── logs/
預計用途如下:
agent/
負責收集 Linux 系統 Telemetry。
detection/
負責放 Detection Rules。
response/
負責事件 Response。
data/
存放之後產生的 JSON、Dataset 等資料。
logs/
保存 BehaviorGuard 自己的執行紀錄。
建立:
nano agent/process_monitor.py
加入:
import os
pid = os.getpid()
print("BehaviorGuard Process Monitor")
print("-----------------------------")
print("Current PID:", pid)
with open(f"/proc/{pid}/status", "r") as f:
print(f.read())
執行:
python3 agent/process_monitor.py
可能會看到:
BehaviorGuard Process Monitor
-----------------------------
Current PID: 4821
Name: python3
State: R
Pid: 4821
PPid: 3501
Uid: 1000
...
首先:
import os
匯入 Python 的 os 模組。
接著:
pid = os.getpid()
取得目前 Python Process 自己的 PID。
假設:
pid = 4821
那麼:
f"/proc/{pid}/status"
最後就會變成:
/proc/4821/status
接著:
with open(f"/proc/{pid}/status", "r") as f:
代表用 Read Mode 開啟 Process Status。
最後:
f.read()
把裡面的內容讀出來。
整個流程可以簡化成:
Python 啟動
↓
取得自己的 PID
↓
找到 /proc/PID/status
↓
讀取 Process 資料
↓
輸出結果
接著可以再把程式簡化並加入 PPID。
import os
pid = os.getpid()
ppid = os.getppid()
print("=== BehaviorGuard ===")
print("PID :", pid)
print("PPID:", ppid)
其中:
os.getpid()
代表:
目前 Process 的 PID
而:
os.getppid()
代表:
Parent Process 的 PID
如果輸出:
=== BehaviorGuard ===
PID : 5301
PPID: 2614
代表:
PID 2614
↓
PID 5301
如果 PID 2614 剛好是 Bash:
bash
↓
python3
這就是最簡單的 Process Tree。
Day 1 還沒有真的開始「抓攻擊」。
今天主要先建立 BehaviorGuard 的第一個基礎:
Endpoint Telemetry
也就是:
從 Linux Endpoint 收集系統行為資料
今天先理解:
Process
PID
PPID
/proc
status
cmdline
並建立第一個:
process_monitor.py
目前它只能取得自己的 Process 資訊,但這會是後面所有行為分析的起點。