contributed by < vectorr >
從程式碼看,是 find_ge_pid
被自訂的 hook_find_ge_pid
所取代。
TODO: 了解使用 ftrace hook function 的機制。
以下是推導如何使用修改 find_ge_pid
來隱藏 cron 的 pid 的過程:
先 strace
觀察 pidof cron
使用了哪些系統呼叫。
在進入 /proc
( chdir("/proc")
) 後,呼叫 getdents64
,然後就開始依序地進入每個 pid 的目錄,讀取 stat
, cmdline
, exe
的內容,這邊推測應該是在比對有沒有 cron 字串。
getdents64
系統呼叫,通常是透過 C 執行時期函式庫的 readdir
去呼叫,是要取得這個目錄內的子目錄列表。
Linux 沿襲 UNIX 傳統,使用 "directory"
好的,已更改,謝謝~Vectorr
推測 pidof
是取得 /proc
下的所有子目錄名稱,然後分別輪詢每個目錄內的相關檔案是否有 cron 的字串,因為有相關檔案的子目錄的名稱即是此 process 的 pid,藉此取得 cron 的 pid。
從完整的 strace
輸出看出,當使用這個 driver 隱藏 cron 的 pid 後,不會去輪詢到 cron pid 的那個子目錄,推測 getdents64
在當下不會回傳 cron 的 pid 那個子目錄。
接下來要尋找 find_ge_pid
跟 getdents64
有什麼關係, trace 一下 kernel source code 得到下面的呼叫關係。
再用 ftrace
來追蹤 pidof cron
使用到的 function call,也可以看到 proc_root_readdir
跟 proc_pid_readdir
。
kernel裡的 x86_64 的 system call table arch/x86/entry/syscalls/syscall_64.tbl
可以看到 217 common getdents64 __x64_sys_getdents64
,即 getdents64
會觸發 __x64_sys_getdents64
被呼叫。
再搭配上面 ftrace pidof cron
的紀錄可以看到,__x64_sys_getdents64
會一路呼叫到 proc_pid_readdir
。
再根據更早之前得到的呼叫關係可以得到 find_ge_pid
是一路從 user space 呼叫 getdents64
system call,然後跳到 kernel space 後觸發 __x64_sys_getdents64
被呼叫,然後一路被呼叫到的。
TODO: 不知道為什麼有的 function 不會出現在 ftrace 的輸出,像 find_ge_pid
,應該是有什麼規則,需要再去了解。
從上面的追蹤推論,pidof cron
會去取得 /proc
的所有子目錄列表,根據檢查 cron 是在哪個 pid 的子目錄中,來判斷 cron 的 pid 為何。在取得 /proc
的子目錄的路徑中,有一個地方會呼叫到 find_ge_pid
,我們透過 ftrace hook function 的機制, 用 hook_find_ge_pid
去取代原本 find_ge_pid
的行為。透過回傳 pid 時,把我們要隱藏的pid跳掉,使得回傳的子目錄列表缺少了被我們隱藏的 pid 所屬的目錄。