115 調查局特考三等 資訊科學組 作業系統及系統程式 考古題詳解
第 一 題15 分
某政府機關建置線上申辦系統,採用三層式分散式系統架構(Three-tier Distributed Architecture),其中 Web Server、Application Server 與 Database Server 部署於虛擬化平台(Virtualization Platform)之虛擬機(Virtual Machine, VM)。部分應用程式運用容器(Container)與微服務(Microservices)架構部署,透過 API 進行服務間通訊。近期系統發生異常事件,系統管理者需於不中斷主要服務的情況下完成維護及安全處置。
- 部分 Web Server CPU 使用率持續偏高,導致系統回應時間明顯增加。
- 某一微服務無法正常存取資料庫,造成部分功能無法使用。
- 某容器遭惡意程式入侵,疑似透過橫向移動(Lateral Movement)攻擊其他容器或虛擬機。
(一) 對於上述系統異常事件,請列舉可能發生之二項原因;並請提出三項系統管理或資訊安全措施,以降低攻擊影響並維持服務可用性,並說明各項措施之目的。(15 分)
(二) 請製表比較虛擬機(Virtual Machine, VM)、容器(Container)與微服務(Microservices)三種技術於系統部署、資源管理、擴充性及故障隔離四方面之差異;並說明在本案例中如何整合上述技術,以提升系統之可用性、擴充性及資訊安全。(10 分)
登入後即可作答並保存紀錄。
核心觀念
本題考查三層式系統的故障判斷與維運,以及虛擬機、容器、微服務在部署、資源管理、擴充性和故障隔離上的差異。作答時要把「異常的可能原因」和「可採取的維運措施」分開,再對照題目四個面向比較技術特性。
三層式架構由 Web Server 負責接收及呈現請求、Application Server 執行應用邏輯、Database Server 儲存與處理資料。虛擬機以虛擬化層提供隔離的作業系統環境;容器以映像檔封裝應用程式及相依元件,通常共用主機核心;微服務則是將應用拆成可獨立部署、透過 API 通訊的服務架構。
解題方法
依題幹中的三項現象,分別從「資源瓶頸」、「服務連線或設定故障」及「入侵後的擴散風險」找原因。措施則應涵蓋維持服務、縮小攻擊範圍及恢復可信任狀態;並說明各措施的目的,而不只列出名稱。
比較技術時,要避免把三者當成同一層級:VM 與容器主要是部署及隔離執行環境的技術,微服務是應用程式的架構設計。三者可以搭配使用。
(一)異常原因與管理/安全措施
可能原因(二項)
-
Web Server 負載過高或資源配置不當 突增的請求量、惡意流量、程式效率不佳或 VM 配置的 vCPU 不足,都可能使 CPU 長時間維持高使用率,增加請求排隊時間,造成回應延遲。
-
微服務與資料庫間的連線或設定故障 例如資料庫位址、連接埠或憑證設定錯誤,網路路由或防火牆規則阻擋,資料庫連線池耗盡,或資料庫本身過載,都會使該微服務無法存取資料庫,造成相關功能失效。
系統管理或資訊安全措施(三項)
-
流量監控、負載平衡與彈性擴充 監控 Web Server 的 CPU、請求量及回應時間,透過負載平衡分散流量,並依負載增加或調整 Web Server VM/容器實例。目的在降低單一節點的資源瓶頸,維持服務可用性與回應效能。
-
網路分區、最小權限與服務存取控制 將 Web、應用程式、資料庫及容器工作負載分區;以防火牆或網路政策限制各服務只能連線至業務所需的目的地和連接埠,並採用最小權限的服務帳號及 API 驗證。目的在阻止遭入侵容器任意掃描或存取其他容器、VM、資料庫,降低橫向移動及資料外洩風險。
-
隔離受感染容器並以可信映像重建 先將疑似遭入侵的容器自服務網路隔離,保留必要的事件紀錄,再以已驗證的映像檔重新部署;若服務允許,將流量切至健康實例,並輪替受影響的憑證或金鑰。目的在限制惡意程式擴散、移除遭竄改的執行環境,並讓主要服務持續提供服務。
(二)VM、容器與微服務比較及整合
| 比較面向 | 虛擬機(VM) | 容器(Container) | 微服務(Microservices) |
|---|---|---|---|
| 系統部署 | 透過虛擬化平台建立完整的虛擬硬體與作業系統環境,可在 VM 內部署作業系統及應用程式。 |
第 二 題10 分
下列 Linux 程式使用 fork() 建立子行程,並於父、子行程中分別建立執行緒。請閱讀下列 C 程式碼並回答問題。假設所有系統呼叫皆成功;PID 與 Thread ID 的實際數值不固定,輸出順序則依 pthread_join() 與 wait() 所形成的先後關係判斷。
01 // 省略標頭檔
02 int value = 10;
03 void *worker(void *arg){
04 int *local = (int *)arg;
05 value = value + (*local);
06 printf("PID=%d, TID=%lu, value=%d\n",
07 getpid(), (unsigned long)pthread_self(), value);
08 return NULL;
09 }
10 int main(void){
11 int x = 5;
12 pthread_t tid;
13 pid_t pid = fork();
14 if (pid == 0) {
15 x = 20;
16 value = value + x;
17 pthread_create(&tid, NULL, worker, &x);
18 pthread_join(tid, NULL);
19 printf("C_PID=%d, value=%d, x=%d\n", getpid(), value, x);
20 } else {
21 x = 30;
22 value = value + x;
23 pthread_create(&tid, NULL, worker, &x);
24 pthread_join(tid, NULL);
25 wait(NULL);
26 printf("P_PID=%d, value=%d, x=%d\n", getpid(), value, x);
27 }
28 return 0;
29 }
(一) 請分析上述程式碼之執行結果,分別說明父行程與子行程中變數 value 與 x 的最終值,並列出可能的輸出內容。(10 分)
(二) 請從作業系統行程與執行緒管理的角度回答下列問題。(15 分)
-
請說明
fork()執行後,父行程與子行程分別擁有之獨立或共享資源,包含虛擬位址空間、程式碼、全域變數、堆疊、檔案描述符及行程識別碼之關係。 -
請說明同一行程內的多個執行緒共享及各自獨立擁有之資源,包含程式碼區、資料區、Heap、Stack、暫存器與 Thread ID。
-
若同一行程中建立多個 worker 執行緒,且這些執行緒可能同時執行
value = value + (*local);,請說明可能發生的同步問題,以及如何利用 Mutex 避免該問題。
登入後即可作答並保存紀錄。
核心觀念
本題考查 fork 建立子行程後的記憶體隔離、同一行程內執行緒的共享記憶體、pthread_join 與 wait 的同步順序,以及共享變數更新時的競爭條件。
fork之後,父、子行程各自有獨立的虛擬位址空間。子行程起初取得父行程記憶體內容的副本,因此全域變數value與區域變數x起始值相同,但之後各自行程的修改互不影響。- 同一行程中的執行緒共享該行程的全域變數與一般記憶體;各執行緒則有自己的執行堆疊、暫存器狀態及 Thread ID。
pthread_join等待指定執行緒結束;wait等待子行程結束。它們分別建立執行緒內與父子行程間的先後關係。
解題方法
先分別追蹤父、子行程的 value 與 x。fork 後兩者起始皆為 value = 10、x = 5,之後依各分支的指令逐步更新。工作執行緒透過 arg 取得該行程自己的 x 位址,因此會再將該行程的 x 加入該行程的 value。
子行程
子行程先執行:
x = 20value = value + x,故value = 10 + 20 = 30- worker 以子行程的
x位址作為參數,執行value = value + (*local),故value = 30 + 20 = 50 pthread_join等待 worker 結束後,才印出子行程資料
因此子行程最後為 value = 50、x = 20。
父行程
父行程的記憶體是另一份獨立狀態,起始仍為 value = 10、x = 5。它執行:
x = 30value = value + x,故value = 10 + 30 = 40- worker 使用父行程的
x,執行後value = 40 + 30 = 70 pthread_join等待 worker 結束;wait再等待子行程結束,之後才印出父行程資料
因此父行程最後為 value = 70、x = 30。子行程將 value 改為 50,不會改變父行程的 value。
輸出順序與可能輸出
各行程的 worker 都必須先於該行程的結尾訊息輸出,因為結尾訊息前有 pthread_join。子行程的結尾訊息也必須先於父行程的結尾訊息,因為父行程在輸出前呼叫 wait。
因此輸出順序固定為:子 worker、父 worker、子行程結尾、父行程結尾。兩個 worker 的先後順序不固定,因為父、子行程可由作業系統排程交錯執行。
以 P、C 分別代表父、子行程的 PID,以 T_P、T_C 代表各自 worker 的 Thread ID,可能輸出如下:
PID=C, TID=T_C, value=50
PID=P, TID=T_P, value=70
C_PID=C, value=50, x=20
P_PID=P, value=70, x=30
也可能先輸出父 worker,再輸出子 worker:
第 三 題10 分
針對 MIPS 指令及架構的組合語言程式,假設 與 均為每個元素占用 Bytes 的一維整數陣列,變數 、、、、 分別配置於暫存器 $s0、$s1、$s2、$s3、$s4,而陣列 與 的起始位址分別儲存於暫存器 $s6 與 $s7。
I1 addi $t0, $s6, 36
I2 lw $t0, 0($t0)
I3 sll $t0, $t0, 3
I4 sll $t1, $s4, 2
I5 add $t1, $t1, $s7
I6 lw $t1, 0($t1)
I7 add $t0, $t0, $t1
I8 add $s3, $t0, $s2
(一) 請說明上述 MIPS 組合語言程式(I1)~(I6)的運作邏輯,並將整個程式轉換為等效的 C 語言程式碼。(10 分)
(二) 假設上述程式在單一發射、循序執行的典型五階段 MIPS 管線處理器中執行,管線階段依序為 IF、ID、EX、MEM 與 WB。處理器具有由 EX/MEM 與 MEM/WB 管線暫存器至 EX 階段的完整資料轉傳路徑,且 lw 指令載入的資料須至 MEM 階段結束後才能使用。請找出程式中可能發生的資料危障(Data Hazard),指出具有 RAW 資料相依關係的指令及相依暫存器,並說明哪些危障可透過資料轉傳解決,以及哪些載入使用危障(Load-use Hazard)仍須插入停頓週期(Stall Cycle)。(15 分)
登入後即可作答並保存紀錄。
核心觀念
本題考查兩個重點:
- MIPS 位址計算與陣列索引:每個整數元素占 Bytes,因此索引為 的元素位址是「陣列起始位址 」。
- 五階段管線的 RAW 資料危障:RAW(Read After Write)是後續指令要讀取某暫存器,但前一指令尚未完成寫入。資料轉傳可將結果直接送至 EX 階段;但
lw的資料要到 MEM 階段結束才產生,若下一條指令立即使用,仍須停頓一個週期。
解題方法
先逐行追蹤每條指令的來源與目的暫存器,再把載入的位址換算成陣列索引。管線部分則逐一檢查每條指令的來源暫存器是否依賴先前指令的目的暫存器,並區分一般運算結果與 lw 載入結果。
(一)指令運作與等效 C 程式
| 指令 | 運作邏輯 |
|---|---|
I1 addi $t0, $s6, 36 | $s6 儲存 X 起始位址;先計算 $t0 = X 起始位址 + 36。 |
I2 lw $t0, 0($t0) | 載入該位址的整數,即 $t0 = X[36/4] = X[9]。 |
I3 sll $t0, $t0, 3 | 左移 3 位相當於乘以 ,故 $t0 = X[9] × 8。 |
I4 sll $t1, $s4, 2 | $s4 儲存 e;左移 2 位相當於乘以 ,故 $t1 = e × 4,形成 Y[e] 的位元組位移量。 |
I5 add $t1, $t1, $s7 | 加上 $s7 中的 Y 起始位址,得到 Y[e] 的位址。 |
I6 lw $t1, 0($t1) | 載入 Y[e],故 $t1 = Y[e]。 |
I7 add $t0, $t0, $t1 | $t0 = X[9] × 8 + Y[e]。 |
I8 add $s3, $t0, $s2 | $s3 = $t0 + c;因 $s3 對應 d、$s2 對應 c,故將結果存入 d。 |
因此,整段程式的等效 C 程式碼為:
d = X[9] * 8 + Y[e] + c;
(二)RAW 資料危障與停頓
以下列出程式中所有由先前指令產生、並被後續指令讀取的 RAW 相依關係:
第 四 題8 分
某政府機關 Linux Web Server 疑似發生資安問題,管理者發現系統 CPU 使用率異常偏高,且有未知程序持續對外連線。請依下列要求進行系統安全檢查與數位鑑識。
(一) 請利用 Linux 指令完成下列工作。(8 分)
- 列出系統中所有執行中的程序,並依 CPU 使用率由高至低排序。
- 找出目前已建立 TCP 連線之程序,顯示本機位址、遠端位址、連接埠、程序名稱及 PID。
- 顯示系統目前所有處於 Listening 狀態之 TCP 與 UDP Port,並找出其對應程序。
- 建立並保存系統記憶體映像檔(Memory Image),以供後續數位鑑識分析使用。
(二) 若已取得該主機之記憶體映像檔(Memory Image),請說明如何利用 Volatility 工具進行下列分析,並寫出適當之 Volatility 分析模組(Plugin)名稱。(17 分)
- 分析記憶體中的網路連線資訊,找出本機與遠端 IP、Port、連線狀態及所屬 PID,並判斷是否存在連往可疑外部 IP 或異常 Port 之程序。
- 分析程序是否存在程式碼注入(Code Injection)、異常可執行記憶體區段(Executable Memory Region)、可疑共享物件(Shared Object)載入或可疑記憶體區域(Memory Region)等異常行為,並說明其可能造成之安全風險。
- 利用
pslist(Process Listing)與psscan(Process Scanning)等不同方式交叉驗證程序資訊,判斷是否存在遭 Rootkit 隱藏、已終止但程序結構仍殘留,或未出現在正常程序鏈結中的程序,並分析其可能原因。 - 若發現可疑程序,請說明如何利用 Volatility 擷取其程序記憶體內容或可復原之可執行檔,計算其 SHA-256 雜湊值,並說明該雜湊值於驗證證據完整性、與已知惡意程式雜湊資料庫進行比對,以及數位鑑識證據保存之用途。
登入後即可作答並保存紀錄。
核心觀念
本題考查 Linux 即時系統檢查與記憶體鑑識的基本流程,重點是以多種系統工具蒐集程序、網路連線及監聽埠資訊,再以 Volatility 從記憶體映像檔分析網路端點、程序異常與可疑程式內容。
記憶體映像檔是鑑識證據。擷取時應記錄主機、時間、工具與命令,並盡量將映像檔寫入外接或遠端儲存裝置,避免覆寫來源磁碟;擷取後計算雜湊值,供後續驗證完整性。下列 Linux 指令與 Volatility 參數依常見 Linux 系統及 Volatility 3 語法說明;實際可用選項仍須配合映像檔作業系統與工具版本。
解題方法
(一)Linux 系統檢查與記憶體擷取
1. 依 CPU 使用率排序執行中程序
ps -eo pid,ppid,user,stat,%cpu,%mem,comm,args --sort=-%cpu
ps -e 列出所有程序,--sort=-%cpu 依 CPU 使用率遞減排序。若只需快速監看,可使用 top,並依 CPU 欄位排序;但 ps 較適合輸出成可保存的文字紀錄。
2. 列出已建立 TCP 連線及所屬程序
sudo ss -ntp state established
-n 以數字顯示位址與連接埠,-t 篩選 TCP,-p 顯示程序資訊,state established 篩選已建立連線。輸出包含本機與遠端端點,以及程序名稱、PID。若系統沒有 ss,可使用:
sudo netstat -ntp
並檢視狀態為 ESTABLISHED 的列。權限不足時,程序欄位可能無法完整顯示。
3. 列出 TCP、UDP 監聽埠及對應程序
sudo ss -lntup
-l 顯示監聽中的 Socket,-n 顯示數字位址與連接埠,-t、-u 分別選取 TCP 與 UDP,-p 顯示程序。TCP 會呈現 LISTEN 狀態;UDP 沒有 TCP 式的連線狀態,應以列出的 UDP 監聽 Socket 判讀。
4. 建立並保存記憶體映像檔
Linux 記憶體擷取可使用具備相容核心支援的 LiME。以下假設模組已依目標核心建置,且外接儲存裝置已掛載:
sudo insmod lime.ko "path=/mnt/evidence/memory.lime format=lime"
擷取後保存基本資訊與雜湊:
date -u
sha256sum /mnt/evidence/memory.lime
應將雜湊值、擷取時間、主機識別資訊與工具版本記入鑑識紀錄。直接在受疑主機安裝或載入擷取工具會改變系統狀態,因此須記錄操作;鑑識作業宜由受控媒體執行,並將映像檔保存於安全、受控的證據儲存位置。
(二)Volatility 記憶體分析
以下以 Volatility 3 命令列形式表示:
vol -f memory.lime <plugin>
分析前須確認映像檔格式及作業系統支援情形,並以 vol --help 或 vol <plugin> --help 確認當前版本的外掛名稱與參數。
1. 分析記憶體中的網路連線
使用:
vol -f memory.lime linux.sockstat
linux.sockstat 用於列出 Linux Socket 資訊,可檢視本機/遠端 IP、Port、Socket 狀態及所屬程序或 PID 等欄位。將外部端點、異常連接埠、非預期連線狀態與程序名稱交叉比對,並與主機即時輸出的 ss 紀錄互相核對。若目標系統或 Volatility 版本另提供 Linux 網路專用外掛,應依該版本文件選用;外掛可取得欄位會隨核心版本及映像狀況而不同。
2. 檢查程式碼注入與異常記憶體區域
先列出程序及記憶體映射,再針對可疑 PID 檢查:
vol -f memory.lime linux.pslist
vol -f memory.lime linux.proc.Maps --pid <PID>
Volatility 3 的 Linux 記憶體映射外掛通常以 linux.proc.Maps 類型名稱呈現;實際名稱及參數應依安裝版本確認。檢查程序映射中具有執行權限的區段,尤其是匿名映射、權限組合異常的區段,或與程序執行檔及已載入共享物件不相符的區段。可進一步擷取程序記憶體映射供離線分析;