iT邦幫忙

2026 iThome 鐵人賽

DAY 24
0
Security

《Nyahello!從零開始的 30 天 malware 學習日誌》系列 第 24

【Day 24】Rootkits:從 SSDT Hooking 看懂核心層惡意程式

  • 分享至 

  • xImage
  •  

前言

前面介紹 Kernel Debugging 時,我們已經開始接觸 Windows Kernel,以及如何使用 WinDbg 分析惡意的 Kernel Driver。

而當惡意程式進入 Kernel Mode 之後,除了能取得相當高的權限之外,還有一件非常重要的事情可以做:

修改作業系統原本的行為。

這也帶出了今天的主題——Rootkit

Rootkit 最麻煩的地方不一定在於它執行了什麼惡意功能,而是它可以修改作業系統內部的功能,進一步隱藏自己的存在

例如隱藏:

  • Files
  • Processes
  • Network Connections
  • 其他系統資源

這代表即使我們使用一般程式去查看系統狀態,看到的結果也不一定是真的。

今天會從教材中的經典案例 SSDT Hooking 開始,看看 Rootkit 如何攔截 Windows 的 System Call,以及分析人員如何透過 WinDbg 與 IDA Pro 找出這些 Hook。

【聲明】由於時間問題本日文章由 AI 生成QQ


Rootkits

Rootkit 的核心概念,可以簡單理解成:

修改作業系統內部功能,讓系統替惡意程式隱藏某些資訊。

一般惡意程式可能會建立檔案、Process 或 Network Connection,而防毒軟體與分析人員可以透過各種工具尋找這些跡象。

但是,如果 Rootkit 直接修改了 OS 回傳資訊的方式,情況就不一樣了。

假設系統裡其實存在:

malware.sys

正常情況下,我們向 Windows 查詢目錄內容,Windows 應該會告訴我們這個檔案存在。

但 Rootkit 可以在 Kernel 中攔截這些操作,把 malware.sys 從結果中移除。

如此一來,檔案實際上仍然存在,只是 User Mode 程式所取得的結果已經被 Rootkit 動過手腳。

也因此,Rootkit 能讓 Antivirus、Administrator,甚至 Malware Analyst 更難發現惡意活動。

教材提到,大部分 Rootkit 都會透過某種方式修改 Kernel,而其中一個非常經典的技術就是:

System Service Descriptor Table Hooking,也就是 SSDT Hooking。

SSDT Hooking 是一種相對老舊,而且比其他 Rootkit 技術容易被偵測的方法。

不過它的原理簡單、彈性高,也很好理解,因此很適合拿來學習 Rootkit 到底如何修改 Windows Kernel 的行為。


System Service Descriptor Table

在理解 SSDT Hooking 以前,要先知道 SSDT 是什麼

SSDT 全名是:

System Service Descriptor Table

有時也會被稱為:

System Service Dispatch Table

Windows 會在內部使用 SSDT 尋找對應的 Kernel Function。

我們前面學過,User Mode 的程式不能直接隨意執行 Kernel Mode Code。

User Space 要進入 Kernel Space,需要透過特定機制,例如:

SYSCALL
SYSENTER
INT 0x2E

教材使用的系統中則是透過 SYSENTER 進入 Kernel。

例如,當程式需要呼叫:

NtCreateFile

ntdll.dll 中可以看到類似下面的程式碼:

mov eax, 25h
mov edx, 7FFE0300h
call dword ptr [edx]
retn 2Ch

接著執行:

mov edx, esp
sysenter

這裡最值得注意的是:

mov eax, 25h

也就是把:

0x25

放進 EAX。

這個數值代表 NtCreateFile 對應的 Function Number。

進入 Kernel 之後,Windows 就能使用這個數字作為 Index,到 SSDT 中尋找真正需要執行的 Kernel Function。

可以把 SSDT 簡化想成:

SSDT

0x22 → NtCreateDirectoryObject
0x23 → NtCreateEvent
0x24 → NtCreateEventPair
0x25 → NtCreateFile
0x26 → NtCreateIoCompletion
0x27 → NtCreateJobObject

所以:

EAX = 0x25

就代表要執行 SSDT 中 Index 0x25 所指向的 Function。

正常情況下,這個位置會指向真正的:

NtCreateFile

SSDT Hooking

知道 SSDT 的用途之後,Rootkit 要做的事情其實就很好理解了。

假設原本:

SSDT[0x25] → NtCreateFile

Rootkit 可以直接修改 SSDT 裡面的 Function Address,讓它變成:

SSDT[0x25] → Rootkit Function

如此一來,User Mode 程式雖然還是正常呼叫 NtCreateFile,但是進入 Kernel 並查詢 SSDT 之後,真正被執行的卻變成 Rootkit 自己的程式碼。

流程原本是:

Application
    ↓
NtCreateFile
    ↓
SYSENTER
    ↓
SSDT[0x25]
    ↓
真正的 NtCreateFile

被 Hook 之後則變成:

Application
    ↓
NtCreateFile
    ↓
SYSENTER
    ↓
SSDT[0x25]
    ↓
Rootkit Hook

Rootkit 取得控制權之後,就能決定接下來要怎麼處理這個 Request。

不過 Rootkit 通常不會把原本的 NtCreateFile 完全丟掉。

比較常見的作法是:

Request
   ↓
Rootkit Hook
   ↓
檢查 Request
   ↓
要隱藏?
 ┌───────┴───────┐
 Yes             No
 ↓                ↓
阻止 Request    Original NtCreateFile

也就是只針對 Rootkit 想隱藏的內容進行 Filter,其他正常操作仍然交給原本的 NtCreateFile

例如有人試圖開啟 Rootkit 自己的檔案,就回傳「檔案不存在」。

但如果使用者開啟:

C:\Windows\notepad.exe

Rootkit 根本不需要干涉,直接讓原本的 NtCreateFile 繼續執行即可。

要注意的是,教材中的例子只 Hook NtCreateFile,因此主要能阻止特定檔案被開啟,不代表檔案就不會出現在 Directory Listing 中

如果要完整隱藏檔案,還需要處理其他相關操作。


Rootkit Analysis in Practice

知道 Rootkit 怎麼 Hook SSDT 之後,接下來就是實際分析。

假設現在拿到一台疑似遭到感染的電腦,我們懷疑系統裡安裝了惡意 Driver。

既然懷疑的是 SSDT Hooking,最直接的方法自然就是:

檢查 SSDT。

在 WinDbg 中,可以透過:

nt!KeServiceDescriptorTable

找到 SSDT。

正常情況下,SSDT 裡面的 Function Address 應該要指向 Windows Kernel,也就是 ntoskrnl.exe 所在的 Address Range。

教材中的 ntoskrnl.exe 範圍為:

804d7000
~
806cd580

因此如果 SSDT 裡突然出現:

f7ad94a4

就非常可疑。

因為:

f7ad94a4

根本不在 ntoskrnl.exe 的範圍裡。

進一步檢查之後,可以發現異常位置剛好就是:

SSDT[0x25]

也就是原本應該對應:

NtCreateFile

的位置。

換句話說,我們已經找到一個很重要的跡象:

NtCreateFile
    ↓
SSDT[0x25]
    ↓
不再指向 ntoskrnl.exe

很可能代表這個 Function 已經被 Hook。


找出 Hook 來自哪個 Driver

知道:

f7ad94a4

很可疑之後,下一個問題自然是:

這個 Address 到底屬於誰?

這時候可以使用 WinDbg:

lm

列出目前載入的 Module。

在 Kernel Debugging 中,這裡看到的 Module 主要就是各種 Driver。

教材中的結果可以看到:

f7ad9000 f7ada680 Rootkit

而剛才找到的 Hook Address:

f7ad94a4

剛好落在:

f7ad9000 ~ f7ada680

之間。

所以我們就知道:

SSDT[0x25]
        ↓
0xf7ad94a4
        ↓
Rootkit Driver

到這裡已經可以建立出相當完整的關係:

NtCreateFile
    ↓
SSDT[0x25]
    ↓
被修改
    ↓
Rootkit Driver

接下來就可以開始 Reverse Engineering 這個 Driver。


分析 Rootkit Driver

找到惡意 Driver 之後,教材接著使用 IDA Pro 進行分析。

這時主要要找兩個部分:

  1. 安裝 Hook 的程式碼

  2. Hook 被觸發之後實際執行的 Function

其中尋找 Hook 安裝程式碼的一種簡單方法,就是在 IDA Pro 中尋找對 Hook Function 的 Data Reference。

教材中的 Rootkit 會先處理兩個重要名稱:

NtCreateFile
KeServiceDescriptorTable

接著使用:

MmGetSystemRoutineAddress

取得它們的 Address。


MmGetSystemRoutineAddress

如果之前分析過 User Mode Malware,可能很熟悉:

GetProcAddress

它可以用來取得 Exported Function 的 Address。

但現在是在 Kernel Mode。

Kernel Mode 不能直接使用 GetProcAddress,因此這裡使用的是:

MmGetSystemRoutineAddress

可以先簡單把它理解成 Kernel Mode 中類似 GetProcAddress 的存在。

不過兩者並不完全相同,教材特別指出 MmGetSystemRoutineAddress 只能取得 halntoskrnl Kernel Module 所 Export 的 Address。

這個 Rootkit 第一次呼叫:

MmGetSystemRoutineAddress

取得:

NtCreateFile

真正的 Address。

第二次則取得:

KeServiceDescriptorTable

的 Address。

因此 Rootkit 現在同時知道:

NtCreateFile 在哪

以及:

SSDT 在哪

接下來就可以修改 SSDT。


找到 NtCreateFile 的 SSDT Entry

取得兩個 Address 之後,Rootkit 開始跑一個 Loop。

概念大致上是:

從 SSDT 開始
    ↓
讀取一個 Entry
    ↓
是不是 NtCreateFile?
    ↓
不是 → 下一個 Entry
    ↓
是不是 NtCreateFile?
    ↓
...

因為每個 Address 為 4 Bytes,所以程式中會看到:

add ecx, 4

接著:

cmp [ecx], ebx

比較目前 SSDT Entry 與真正的 NtCreateFile Address。

找到之後,Rootkit 最後執行:

mov dword ptr [ecx], offset sub_104A4

這行就是整個 SSDT Hooking 最關鍵的地方。

原本:

[ecx] → NtCreateFile

現在被改成:

[ecx] → sub_104A4

sub_104A4 就是 Rootkit 自己的 Hook Function。

Hook 到這裡正式完成。


Hook Function 在做什麼?

接下來分析:

sub_104A4

也就是當程式呼叫 NtCreateFile 時,Rootkit 實際會執行的 Hook Function。

教材中的 Function 主要有兩條路。

其中一條最後:

jmp NtCreateFile

也就是:

這個 Request 沒有問題,交回原本的 NtCreateFile 處理。

另一條則:

mov eax, 0C0000034h
retn 2Ch

其中:

0xC0000034

代表:

STATUS_OBJECT_NAME_NOT_FOUND

也就是告訴呼叫者:

找不到這個 Object。

Hook Function 中會檢查傳入的 ObjectAttributes,其中包含 Filename 等資訊。

如果 Rootkit 判斷這個 File 可以正常存取:

Rootkit Hook
    ↓
Original NtCreateFile

如果判斷這個 File 應該被隱藏:

Rootkit Hook
    ↓
STATUS_OBJECT_NAME_NOT_FOUND

User Mode Application 最後得到的結果就是:

File does not exist

即使那個 File 實際上存在。

這也是 Rootkit 很重要的一個概念:

不是把東西真的刪掉,而是修改系統呈現給其他程式的結果。


Interrupts

除了 SSDT Hooking 之外,教材最後還介紹另一個 Rootkit 可能利用的機制:

Interrupts。

現代處理器會使用 Interrupt,讓 Hardware 能夠觸發 Software Event。

例如系統向某個 Hardware 發出 Command,Hardware 完成工作之後,就可以透過 Interrupt 通知 Processor。

Driver 也會利用這套機制。

Driver 可以呼叫:

IoConnectInterrupt

為某個 Interrupt Code 註冊 Handler,並指定:

Interrupt Service Routine

也就是 ISR

之後每當這個 Interrupt 發生,OS 就會執行對應的 ISR。


Interrupt Descriptor Table

既然系統需要知道:

Interrupt → 哪一個 ISR

自然也需要一個地方保存這些資訊。

這就是:

Interrupt Descriptor Table,IDT

在 WinDbg 中可以使用:

!idt

查看 Interrupt Descriptor Table。

正常情況下,我們可能會看到:

hal!HalpApcInterrupt
atapi!IdePortInterrupt
NDIS!ndisMIsr
USBPORT!USBPORT_InterruptService
i8042prt!I8042KeyboardInterruptService

這些 Interrupt 都指向已知的正常 Driver。

因此分析 Rootkit 時,也可以檢查 IDT。

如果發現 Interrupt 指向:

  • Unknown Driver

  • Unsigned Driver

  • 名稱或來源可疑的 Driver

就值得進一步調查。

這不代表看到陌生 Driver 就一定是 Rootkit,但它可以成為分析 Kernel Malware 時的重要線索。


結語

今天介紹的 Rootkit,和之前分析的一般 User Mode Malware 有很大的不同。

一般 Malware Analysis 常常是在觀察:

CreateProcess
CreateFile
Registry
Network
Persistence

但進入 Rootkit Analysis 之後,我們開始關心:

Kernel
Driver
System Call
SSDT
Hook
Interrupt
IDT

其中教材最主要的案例就是 SSDT Hooking

整個流程可以濃縮成:

User Mode Application
        ↓
NtCreateFile
        ↓
SYSENTER
        ↓
SSDT
        ↓
Rootkit Hook
        ↓
檢查 Request
      ↙       ↘
允許           阻止
 ↓              ↓
NtCreateFile   STATUS_OBJECT_NAME_NOT_FOUND

而站在 Malware Analyst 的角度,分析流程則剛好反過來:

檢查 SSDT
    ↓
找到異常 Function Address
    ↓
確認 Address 屬於哪個 Driver
    ↓
Reverse Engineering Driver
    ↓
找到安裝 Hook 的程式碼
    ↓
找到 Hook Function
    ↓
分析它到底過濾、隱藏了什麼

Rootkit 最值得理解的地方,就是它讓我們看到一件事情:

我們從作業系統 API 得到的資訊,本身也可能是不可信的。

當惡意程式已經進入 Kernel 並修改 OS 的內部行為時,分析就不能只停留在 User Mode 觀察 Process 或 File,而需要進一步理解 System Call、Kernel Driver、SSDT,甚至 Interrupt 等底層機制。

這也是為什麼前面學習的 Kernel Debugging 很重要——當惡意程式躲進 Kernel 裡,就必須跟著它進入 Kernel,才能真正看見它做了什麼。

參考資料

  • Practical Malware Analysis (Chapter 10)
  • chatGPT

本日貓味

https://ithelp.ithome.com.tw/upload/images/20260919/20183878vnbG03T2Zy.jpg


上一篇
【Day 23】惡意程式分析研究資源整理:Conference、Blog、Podcast 與 Paper
下一篇
【Day 25】總結:WinDbg for Malware Analysis
系列文
《Nyahello!從零開始的 30 天 malware 學習日誌》28
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言