昨晚失眠,其實已經累的半死。但看了 The Social Network 之後忍不著帶起耳機,放著洞雌洞雌的 AvB 與 Tiësto 又繼續摸摸 Linux kernel。用電影裡的說法就是 ─ Wired In!!!
修課的作業要求在核心新增一個 system call 提供一個分析記憶體狀態的介面,不過助教學長說我們也可以寫成 kernel module,於是便起了在 kernel module 中寫 system call 的想法。查了一下,要達到這樣的效果要靠 system call hooking 來達成,也就是去 hijack 目前存在的 system call,讓所有程式在呼叫該 system call 時都會變成執行到 module 中的某個 function,該 function 最後會再去呼叫正常的 system call routine。
目前的計畫是在 kernel 中新增一個 system call 來給自己的 module 來 hijack,不知道會不會是很沒有道理開發模式。
這是篇是今晚的筆記,雖然內容不多,但在精神不濟的時刻,相信我更需要做點筆記。:p
今天讀了幾篇簡單的 tutorial,分別是介紹如何新增 system call 以及撰寫自己的 kernel module。並實際寫了一個簡單的 hello world kernel module。不得不說「寫 syscall 與 kernel module」或許聽起來很嚇人,但其實不難入門。當然真正難的一定是在入門之後。
新增 system call 的部份看了實驗室學長以及阿怪寫的兩篇 tutorial [1] [2],大概了解一下狀況,但還沒實際撰寫。也依照 The Linux Kernel Module Programming Guide [3] 寫了一個簡單的 hello world 模組。
System call hooking 的機制是在 kernel module 中,透過 sys_call_table 這個陣列來取得某個 syscall 的位置。備份後,將其改為自行撰寫的 function。用程式碼的方式來呈現或許會更清楚:
接著,在 our_fake_exit_function 撰寫要 hook 的程式碼,並在 function 結束前呼叫備份的 original_sys_exit 便完成 hooking 的動作。詳細的 System call hooking 步驟以及範例可以在 Linux Journal 的一篇文章[4]中找到。
在 2.6 版本的核心中,為了保護系統免於 kernel rootkit 的攻擊, sys_call_table 不再能被 kernel module 中所任意存取。在 insmod 的時候便會發生 symbol not found 的錯誤而失敗。雖然還是有許多 hacking 方式可以取的 sys_call_table [5],但本人實在白的發亮(又弱的可以),所以直接修改 kernel 的程式碼來把 sys_call_table export 成 global。只要在 arch/x86/kernel/i386_ksyms_32.c 加入以下兩行就可以了:
如此一來,kernel module 內便可以存取 sys_call_table。但在 2.6 許多 distro 預設的狀況下 system call table 是唯讀的,因此在上述的第二步便會失敗。只要在 .config 裡將 CONFIG_DEBUG_RODATA 設為 n 後便可以成功的 hook 到 system calls。
Reference