摘要

這份研究報告提供了對 Linux rootkit Hooking 機制演進與實作的全面技術分析。隨著 Linux 核心架構日趨成熟,像是系統呼叫表劫持(System call table hijacking)這類傳統方法,由於核心頁面保護(Kernel page protection)等強化安全功能,以及近幾個核心版本中轉向基於 switch 的分配器,已逐漸變得過時。此研究探討了從使用者空間共享物件注入(Userland shared object injection),到先進的核心層級技術的轉變,包括可載入核心模組 (Loadable Kernel Module, LKM)、eBPF 惡意程式注入,以及新興的 io_uring 介面濫用。透過剖析如 FlipSwitch 和 Curing 等具體實作策略,報告強調了核心層級威脅與防禦性偵測之間持續不斷的軍備競賽。

Kernel 介面戰爭:從 LKM 到 io_uring,Linux 作業系統服務的 Hooking Points 全面剖析 | 資訊安全新聞

1. 簡介

Rootkit 代表了一類複雜的惡意軟體,目的在透過破壞作業系統的核心功能,來維持對系統的持久、隱蔽存取。在 Linux 生態系統中,rootkit 的主要目標是攔截使用者層級應用程式與核心之間的通訊流,這個過程稱為「Hooking」[1]。歷史上,這是透過修改 sys_call_table (一個包含系統呼叫處理程序指標的跳轉表)來實現的。然而,現代核心 (v6.9+) 引入了架構上的變更,用 Hardcoded switch statement 取代了直接的陣列查詢,有效地抵銷了傳統的修補表技術(Table-patching techniques) [2]

2. Hooking 技術分類

Linux rootkit 的演進可分為四種不同的實作模型,每一種都代表了作業系統目標層級的轉移。

時期 實作模型 主要機制 偵測挑戰
2000 年代初 使用者空間共享物件 (SO) LD_PRELOAD 劫持 靜態連結二進位檔輕易繞過
2000 年代 - 2010 年代 可載入核心模組 (LKM) 系統呼叫表 / ftrace Hooking /proc/modules 中可見
2010 年代末 eBPF 惡意程式注入 附加到 kprobes/tracepoints 對傳統 LKM 掃描器不可見
2025+ 濫用 io_uring 的 Rootkit Asynchronous I/O ring 濫用 繞過依賴系統呼叫的 EDR 偵測

3. 進階核心Hooking:FlipSwitch 技術

隨著 Linux Kernel 6.9 的推出, sys_call_table 分配器的移除迫使攻擊者開發更具侵入性的方法。FlipSwitch 技術代表了一種新穎的途徑,它直接修補核心系統呼叫進入點 x64_sys_call 的編譯後機器碼 [2]

3.1. 透過 Kprobes 進行動態符號解析

由於許多關鍵核心函式(如 kallsyms_lookup_name )不再匯出給模組,rootkit 必須使用 kprobes 來動態解析它們的位址。透過在已知符號上註冊一個探測點,rootkit 可以從 kprobe 結構中提取函式指標。

  1. /**
  2. * Find the address of kallsyms_lookup_name using kprobes
  3. * This bypasses the restriction where the symbol is not exported to LKMs.
  4. */
  5. void *find_kallsyms_lookup_name(void)
  6. {
  7. struct kprobe *kp;
  8. void *addr;
  9. kp = kzalloc(sizeof(*kp), GFP_KERNEL); // Allocate kprobe structure in kernel memory
  10. if (!kp)
  11. return NULL;
  12. // Use the string obfuscation to avoid static detection
  13. kp->symbol_name = "kallsyms_lookup_name";
  14. if (register_kprobe(kp) != 0) { // Registering the probe triggers symbol resolution
  15. kfree(kp);
  16. return NULL;
  17. }
  18. addr = kp->addr; // Extract the resolved address
  19. unregister_kprobe(kp); // Clean up
  20. kfree(kp);
  21. return addr;
  22. }

3.2. Inline Machine Code 修補

一旦找到目標位址,rootkit 會掃描 x64_sys_call 函式,尋找 0xe8 操作碼(Near call)。它會計算相對 offset,以驗證該呼叫是否指向原始的系統呼叫。如果找到匹配項,rootkit 會修改 offset,使其指向其惡意封裝函式。

graph TD A[Userland Syscall] --> B{x64_sys_call
Dispatcher} B -- Original Code --> C[Original sys_kill] B -- Patched Code --> D[Rootkit fake_kill] D --> E[Malicious Logic:
Hide Process]

4. 使用 io_uring 繞過系統呼叫稽核

io_uring 介面於 Linux 5.1 中引入,提供了一個高效能非同步 I/O 框架,它利用使用者空間與核心之間的共用記憶體環(Shared memory ring)。這種架構允許 rootkit 執行檔案和網路操作,而無需呼叫對應的系統呼叫,例如 read connect [3]

4.1. Curing Rootkit 架構

Curing rootkit 示範了如何使用 io_uring 來建立隱蔽的通訊頻道。透過向 Submission Queue (SQ) 送出 I/O 請求,並從 Completion Queue (CQ) 取得結果,rootkit 避免了觸發安全工具(如 Falco 或 Tetragon)所使用的濫用 eBPF 的系統呼叫 Hooking [3]

  1. /*
  2. * Simplified io_uring request submission for stealthy file access.
  3. * This bypasses traditional 'read' syscall hooks.
  4. */
  5. struct io_uring ring;
  6. io_uring_queue_init(32, &ring, 0); // Initialize the shared rings
  7. struct io_uring_sqe *sqe = io_uring_get_sqe(&ring); // Get a Submission Queue Entry
  8. // Prepare a vectored read operation (IORING_OP_READV)
  9. io_uring_prep_readv(sqe, fd, &iov, 1, 0);
  10. // Submit the request to the kernel.
  11. // Only 'io_uring_enter' is called, hiding the actual 'read' intent.
  12. io_uring_submit(&ring);

5. 繞過記憶體保護機制

為了套用這些 Hooks,rootkit 必須繞過核心在 CR0 暫存器中的寫入保護 (Write protection, WP) 位元。此位元可防止 CPU 寫入唯讀記憶體頁面,例如 Kernel text segment。

  1. /*
  2. * Temporarily disable kernel write protection by clearing the 16th bit of CR0.
  3. * This allows the rootkit to patch the kernel's executable code.
  4. */
  5. static inline void disable_write_protection(void)
  6. {
  7. unsigned long cr0 = read_cr0(); // Read current control register 0
  8. clear_bit(16, &cr0); // Clear the WP (Write Protect) bit
  9. // Use inline assembly to force the write, bypassing compiler optimizations
  10. asm volatile("mov %0, %%cr0" : "+r"(cr0), "+m"(dummy));
  11. }

6. 結論

Linux rootkit 的技術格局正從簡單的表操作,轉向複雜的機器碼修補以及對效能導向核心子系統的攻擊。FlipSwitch 技術凸顯了即使是現代 kernel dispatchers 也容易受到 inline patching 的攻擊,而像 Curing 這類濫用 io_uring 的 rootkit 則揭露了以系統呼叫為中心的安全監控存在根本上的盲點。未來的防禦策略必須超越系統呼叫稽核,並納入核心執行時期安全檢測 (Kernel Runtime Security Instrumentation, KRSI) 和利用 LSM 的 Hooking,以便在這些深度核心操作中保持能見度。