Rootkit--阻止其他模塊加載

目的

把進來的漏洞堵上,防止其他人進入系統,尤其是阻止有可能威脅rootkit的代碼。如Anit-rootkit,這個有些難度,我們先實現了基本的控制內核模塊的加載。

例子:小偷潛入了銀行,要保證偷偷在銀行這段時間不會被警察給揪出來。

通知鏈機制

在實現我們如何控制內核模塊加載前,我們先簡要介紹一下linux的通知鏈機制。

大多數的內核子系統都是相互獨立的,因此有可能某個子系統對其他子系統產生的事件感興趣。爲了滿足這個需求,linux提供了通知鏈的機制,使得某個子系統在發生某個事件時通知其他的子系統。

通知鏈的數據結構如下:

struct notifier_block
{
    int (*notifier_call)(struct notifier_block *self, unsigned long, void *);
    struct notifier_block *next;
    int priority;
};

所以這個數據結構是一個函數鏈表,每個節點都註冊了一個函數,當某個事件發生時鏈表上的所有節點對應的函數就會被執行。

另外通知這個事件使所運行的函數由被通知方決定,就是說被通知方可以在鏈表上註冊一個通知函數,在發生某個事件的時候,這些函數就會得到執行,從而通知到被通知方。

我們這裏的事件是加載模塊。所以現在我們來分析一下內核中加載模塊的代碼。首先是init_module,在init_module下函數會返回一個load_module函數,所以我們跟進到load_module函數,會發現有好多流程,比如檢查簽名、prepare_coming_module、使模塊與sysfs發生聯繫、執行模塊入口函數等等。我們關注的是prepare_coming_module,因爲這裏將會調用註冊的通知處理函數。然後我們繼續跟進到prepare_coming_module,會發現它有個blocking_notifier_call_chain函數傳入了MODULE_STATE_COMING參數,還有通知鏈表module_notify_list。它會調用通知鏈中的通知處理函數。這裏相當於內核告訴模塊通知鏈的通知處理函數一個信:MODULE_STATE_COMING,即一個模塊準備好了,同時把這個模塊傳遞給處理函數。繼續跟進,會發現有這樣一行代碼說明在這裏調用我們的通知處理函數。

ret = notifier_call_chain(&nh->head, val, v, nr_to_call,nr_calls);

所以,加載模塊這個事件使用了linux通知鏈的機制,即模塊加載時會執行通知鏈表上的通知處理函數。於是我們就可以編寫一個通知處理函數,當其他模塊完成加載,開始初始化前的狀態爲module_state_coming時,我們篡改他的入口函數和出口函數,達到了其他模塊僞加載的目的。

實現

  • 實現通知處理函數
    • 加鎖
    • 當模塊狀態爲MODULE_STATE_COMING,我們篡改其入口函數與出口函數。
    • 解鎖
  • 註冊入口函數和註銷出口函數

加鎖的目的是爲了保證篡改成功。

    //保存中斷狀態加鎖。
    spin_lock_irqsave(&module_notifier_spinlock, flags);
    switch (module->state) {
    case MODULE_STATE_COMING:
        printk("Replacing init and exit functions: %s.\n",
                 module->name);
        // 篡改模塊的初始函數與退出函數。
        module->init = fake_init;
        module->exit = fake_exit;
        break;
    default:
        break;
    }

    // 恢復中斷狀態解鎖。
    spin_unlock_irqrestore(&module_notifier_spinlock, flags);

功能展示

guard目錄下是阻止其他內核模塊的加載,lamb目錄下是一個簡單的模塊。

正常情況下lamb目錄下模塊的加載是這樣的。

輸入:

在這裏插入圖片描述
結果:

在這裏插入圖片描述

而當加載了module_block模塊後,簡單模塊被其阻止加載了。

輸入:

image-20191101132238493

實驗結果:

image4

參考:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章