如何在不重新編譯內核,不rmmod內核模塊的情況下修改系統調用
為了解決這個問題,最終實現了兩種解決方式:
1.Linux系統調用劫持
2.Kprobes內核調試技術(並非真正的修改)
下面分別說下:
Linux系統調用劫持:
其實就是修改內核符號表,來達到一個劫持的作用。因為系統調用實際上是觸發了一個0x80的軟中斷,然后轉到了系統調用處理程序的入口system_call()。system_call()會檢查系統調用號來得出到底是調用哪種服務,然后會根據內核符號表跳轉到所需要調用的內核函數的入口地址,所以,如果我們這個時候修改了內核符號表,使其跳轉到我們自己的函數上,就可以完成劫持。
不過2.6之后,內核符號表便不再導出了,所以需要我們在內存中找到它的位置。具體查找的方式為:查找到中斷向量表中的0x80中斷服務函數的位置,然后在這個中斷服務函數代碼中查找根據內核符號表跳轉的指令,從指令中可以分析出內核符號表的位置。
下面的是一個簡單的劫持mkdir系統調用的測試,通過加載hook.ko內核模塊,劫持mkdir系統調用,然后使用mkdir命令創建一個目錄,來測試是否截齒成功。如果成功的話會輸出“PID xxx called sys mkdir ! By qiankun”。結果測試成功。下面是經過。
kprobes內核調試技術
首先聲明兩點:
1.這種方式其實並非修改,而是只是在運行的內核中動態的插入探測點,當內核運行到該探測點后可以執行用戶預定義的回調函數。執行完畢后返回正常的執行流程。所以說他其實並非真正的修改了原有的系統調用。但是可以達到一定類似於修改了的效果,暫且算作一種“偽修改”吧。
2.我在測試的時候使用的是kprobes中的jprobe探測方式,其實其他的內核調試技術比如systemtap等應該能夠實現這種功能,但是我就不一一實現了。
Kprobes是一個輕量級的內核調試工具,利用kprobes技術可以再運行的內核中動態的插入探測點,在探測點進行用戶預定義的操作。
Kprobes使用主要可以分為三部分:
1.注冊探測點部分。
2.調試處理部分。
3.注銷探測點部分。
下面是使用kprobes中jprobe探測方式,對sys_open和sys_write進行添加探測點。這樣可以一定程度上影響sys_open和sys_write的最后結果,達到類似修改的目的。下面是測試過程,可以看到,每當內核調用sys_write和sys_open的時候,都會先調用我們的探測函數。

代碼如下:
附件列表

