天天看點

linux劫持程序函數,Linux系統核心劫持方法分析(3)

call *sys_call_table(0, %eax, 4)    //Calling sys_call_table[eax]

movl %eax,PT_EAX(%esp)    //Storing of return value

系統調用例程核心。eax寄存器存放系統調用号,即sys_call_table數組索引值,指向

某個特定系統調用函數。函數傳回值将存放到棧中的eax寄存器中,傳回給使用者空間。盡管

系統調用例程核心很适合劫持,但我們不利用此位置,因為系統調用表指針是目前各種掃描

工具首要的檢測點。

cli                                   //Clear Interrupts

movl TI_flags(%ebp), %ecx              //Copy process flags in ecx

testw $_TIF_ALLWORK_MASK, %cx     //Is needed extra work?

jne syscallexitwork                   //If so, do extra work

當系統調用函數傳回時,系統會屏蔽所有中斷,程序測試是否有額外的工作(确信不丢

失需要排程或發信号挂起的中斷)。上面的代碼片段提供了另一個劫持機會。movl和testw

指令共8位元組大小,足以存放JMP指令,而且這兩條指令完全獨立不在任一标簽體内,可複制。

RESTORE_REGS     //CPU’s registers restoration

addl $4, %esp       //Clearing up system call number from stack

iret           //Return from interrupt

調用例程實作體尾部即準備從系統态切回到使用者态。用暫存在棧上的值恢複所有CPU寄

存器值,清除系統調用号,觸發iret指令。尾部指令也可作為劫持位置,但問題是當程序被

跟蹤時,并不會使用這些代碼片段。

3.2 改變系統調用例程中的程式控制流

通過3.1 小節分析,我們已經在系統調用例程中确定了兩個合适位置可劫持系統控制流

程。在 2.6核心的所有版本都相容這種方式的更改,具備很好的相容性和可用性。我們的目

的是修改系統調用函數的傳回值,即在原函數調用後,再劫持轉入到 hack 函數執行。故,

我們将确定選擇第二個位置實作劫持,如圖2 所示。否則,若在函數還未調用之前,轉入攻

擊者設定的hack函數時,執行完hack 函數後,再調用原函數,則無法實作hack函數目的,

如隐藏檔案效果等,而且若不再調用原函數,顯然也不合乎邏輯,否則上層應用程式明明是

調用 fork 函數建立一個子程序,卻沒有實作此功能,很容易被使用者感覺到存在核心鈎子程

序。

我們重寫了movl TI_flags(%ebp), %ecx 和testw $_TIF_ALLWORK_MASK, %cx

兩條指令,并跳轉到trampoline()函數中重新執行,但在重新執行上面兩條指令之前,事先

儲存了棧頂位址值,以確定能準确通路到系統調用結果,而後調用hack函數,修改原系統調

用的結果資訊,如過濾待隐藏的木馬檔案、惡意程序等。執行完此函數後,再對此函數的棧

痕迹進行清理,最後重新jmp到原位置繼續執行。

實驗

為了驗證前面提出的劫持方法,筆者基于此方法開發了兩款rootkits,分别為MoleKit

和 Powerkit。MoleKit能夠借助/dev/mem檔案有效滲透到系統。Molekit可提供一些基本的

服務,如程序、目錄隐藏等。因為這種攻擊方式涉及到很多啟發式搜尋,如在記憶體中尋找代

碼片段特征值等,但這也是一種很好的思路,可以在不借助可加載子產品支援前提下,實作系

統滲透;Powerkit則是使用核心子產品滲透到核心,其主要好處是可友善通路核心API,并實

現 keylogging或權限提升等。

小結

本文給出了劫持Linux核心的一個新方法,此類攻擊在2.6核心的所有版本上均驗證可

行,并給出了兩款基于此技術的Rootkit,且目前并沒有很好的Anti-Rootkit或掃描器等工

具能夠檢測此類攻擊。