第一章 基礎概念
- 進程、線程與作業
-
三個概念中進程最大,進程由以下幾個部分構成:
- 私有的虛擬內存空間。程序運行時pe文件會被按照一定規則加載到一個4G(x86)虛擬內存空間中,而當執行該程序時CPU會取出該虛擬內存中的一部分加載到實際的內存中。其他進程無法訪問(除非其有訪問權限或者本進程定義了一個共用的內存空間)
- 可執行的程序,即加載到虛擬內存中的代碼與數據
- 已打開的句柄列表,其中每個句柄指向一個可以訪問的系統資源(例如文件,通道等等),進程中所有線程均可訪問
- 訪問令牌,標識了進程相關的用戶組,特權等等安全信息
- 進程ID,進程獨一無二的標識符
- 至少一個的線程,線程可以讀取同一個進程內其他線程的空間
同樣進程也指向父進程或者創建該進程的進程(可以不存在或者關閉,不影響子進程)
-
線程包括:
- 一組保存的CPU寄存器的值
- 兩個棧(一個用於內核模式,一個用於用戶模式)
- 一個線程局部存儲區域TLS
- 一個線程ID(唯一標識符)
- 有時可以包括自身的安全環境
寄存器,棧與私有內存被合稱爲線程的環境(CONTEXT)
-
作業:Windows上提供的用於管理一組進程的概念。
-
-
虛擬內存
- Windows對每個進程都分配有1個獨立的虛擬內存空間,對於PE文件將按照一定的規則裝載到這個虛擬內存空間中,直到CPU執行時纔將其按照一定規則取出映射到內存之中。
- 其中對於x86系統,每個進程的虛擬內存爲4G,其中默認2G屬於系統所有(0x80000000-0xFFFFFFFF),剩餘的是用戶代碼所能使用的空間。
-
用戶模式與內核模式
- 一般情況下在操作系統中用戶代碼只能運行在用戶模式中(ring3),而涉及到系統底層調用時我們需要ring0級別的訪問權限,則此時我們需要使用系統API,內核模式本質上是一種處理器執行模式,當執行到API的實現代碼時(例如user32.dll中的代碼),處理器切換到ring0的狀態(與線程切換沒有關係),執行完成後切換回ring3將控制轉交給用戶代碼。
- 一般PE文件區塊屬性中(_IMAGE_SECTION_HEADER)包含有區塊是否可讀可寫可執行的屬性,對於用戶代碼來說起到了防止發生錯誤訪問的作用(例如棧不可寫DEP技術防止將shellcode或跳板部署在棧上),而一旦切換到了ring0,可以實現無視保護的任意地址讀寫。因此只提供給用戶一個API而禁止其進行直接的ring0操作(然而.sys的驅動是擁有ring0級別的權限,所以在x64之後驅動需要有安全機構認證的簽名才能進行安裝)
-
對象與句柄
- 內核對象指靜態定義的對象類型的單個運行實例,對象類型由系統定義的數據類型,在該數據類型實例上進行的操作的一組函數以及一組對象屬性構成,Windows中任何進程都是進程對象的實例,文件是文件對象的實例,等等。
- 可以將其理解爲C++中的類,對象屬性爲類中的成員變量,對象方法爲成員函數,而句柄則可以理解爲一個指向對象的指針
- 由於對象內部是不透明的(許多結構Windows沒有公開定義的文檔,相關資料都是大佬們研究出來的),類似於C++的private,我們只能使用成員函數來修改其中的成員變量
- 並非所有數據結構都是對象,只有需要被共享,保護,命名等等的數據才放在對象中
第二章 系統架構
-
操作系統模型與整體架構
- 在大部分操作系統中,操作系統與用戶代碼都是隔離的,以防用戶代碼錯誤操作破壞操作系統。對於Windows系統,也體現了面向對象的思想,一般我們無法直接訪問某個結構的數據,而是通過接口(成員函數)來進行訪問/修改數據,以防破壞。然而需要注意,爲了可移植性,Windows大部分代碼都是用C而不是C++寫的,少量需要效率的交互使用匯編編寫,只是借用了面對對象的特性。
- 操作系統的基本架構如下圖
其中,用戶模式進程有以下四種基本類型:- 固定的系統支持進程,例如登錄,進程與會話管理器,他們並非系統服務
- 服務進程,例如TaskSchedule,Windows服務要求獨立用戶登錄進行。在我理解中,Windows爲一個多用戶操作系統,每個用戶都擁有自己的進程,登出更換賬號則將關閉進程,而這個Windows服務進程則不受用戶登錄登出影響
- 用戶應用程序,即一般我們理解中的進程。對於16位進程只能在32位系統下運行,而64位程序在32位系統安裝組件的情況下同樣可以運行
- 環境子系統服務器進程,實現操作系統環境的支持部分
其中需要注意DLL,因爲我們一般調用DLL中的API,而這些API則將調用更多的API,實現了將一個已文檔化的API轉化爲若干未文檔化的原生系統調用(在我理解爲更加底層的API)。
- Windows的內核組件包含:
- Windows執行體,包含了基本的操作系統服務,例如內存管理,進程/線程管理,安全性,I/O,網絡,跨進程通信等等。
- Windows內核,由一部分低層次的操作系統的功能組成,例如線程調度,中斷,異常分發以及多處理器同步等等。
- 設備驅動程序,既包括硬件設備驅動程序,也包括文件、網絡等等非硬件驅動程序。
- 硬件抽象層(HAL),將內核、設備驅動程序與Windows執行體其他部分,和與平臺相關的硬件差距隔離開。
- 窗口與圖形系統,實現了圖形界面的功能。
Windows的核心文件
文件名稱 | 組件 |
---|---|
Ntoskrnl.exe | 執行體與內核 |
Ntkrnlpa.exe(僅適用於32位) | 執行體與內核,支持物理地址擴展,使得32位擴展到64GB內存,將內存標記爲不可執行 |
Hal.dll | 硬件抽象層 |
Win32k.sys | Windows子系統的內核模式部分 |
Ntdll.dll | 內部支持函數,執行體函數後的系統服務分發存根(stub) |
Kernel32.dll,Advapi32.dll,User32.dll,Gdi32.dll | Windows的核心子系統dll |
-
Windows子系統
- Windows子系統中存放了基本的功能函數,其他子系統使用這些功能時調用Windows子系統完成
- Windows子系統包括以下基本內容
- 對於每個會話,環境子系統進程(Csrss.exe)一個實例加載三個DLL(Basesrv.dll、Winsrv.dll、Csrsrv.dll),其中包含以下支持:
- 創建/刪除進程、線程
- 對16位DOS虛擬機(VDM)的部分支持(僅32位Windows)
- 部分API,例如GetTempFile、DefineDosService、ExitWindowsEx,以及部分自然語言函數支持
- 內核模式設備驅動函數(Win32k.exe)
- 窗口管理器,控制窗口顯示,屏幕輸出,採集外設輸入,負責將用戶消息傳遞給應用程序
- 圖形設備接口(GDI),針對圖形輸出設備
- DirectX的封裝函數(不包括支持)
- 控制檯宿主進程(Conhost.exe),提供對CUI的支持
- 子系統DLL(例如Kernel32.dll,Advapi.dll,User32.dll,Gdi32.dll),將已經文檔化的API轉換爲未文檔化的Ntoskrnl.exe與Win32k.sys中的底層API調用
- 圖形設備驅動程序
- 對於每個會話,環境子系統進程(Csrss.exe)一個實例加載三個DLL(Basesrv.dll、Winsrv.dll、Csrsrv.dll),其中包含以下支持:
-
Dtdll.dll
- 系統服務分發存根(Stub),調用Windows執行體的系統服務,在用戶模式下程序可以通過這些接口函數調用Windows執行體的系統服務,例如NtCreateFile,NtSetEvent等等。在Ntdll的函數內部切換到內核模式,之後調用系統服務分發器(system service dispatcher),檢驗參數後調用真正的系統函數。
- 內部支持函數,供子系統,子系統DLL及其他原生映像文件使用,例如映像加載器,堆管理器,Windows子系統進程通信函數。以及用戶態調試函數,Windows事件跟蹤,以及一個小型的C的庫
-
執行體
- Windows執行體爲Ntoskrnl.exe中的上層(內核爲下層),其中包含如下函數
- 可在用戶模式下調用的導出函數,這些函數稱爲系統服務,通過Ntdll導出,其中絕大部分都可以通過系統API訪問
- 通過DeviceIoControl來調用設備驅動函數,這個爲用戶模式到內核模式提供一個接口
- 只能在內核模式下調用的導出函數(已經文檔化的部分)
- 內核模式下調用但是未文檔化的函數
- 執行體中包含以下主要組件
- 配置管理器,負責實現管理系統的註冊表
- 進程管理器,創建與終止進程與線程。針對進程線程的底層實現與支持是在Windows內核中實現的,而執行體在底層對象的基礎上添加了額外語義與功能。
- 安全引用監視器,守護操作系統資源,實行運行時對對象的保護與審計
- I/O管理器,負責將I/O請求分配到對應的設備驅動
- 即插即用管理器,確定對於特定的設備需要哪些驅動,負責加載驅動,以及獲取運行時的資源需求並分配資源。
- 電源管理器,負責協調電源事件,產生電源I/O通知發送給設備驅動程序
- Windows驅動程序模型的WMI例程,允許設備驅動程序發佈有關性能與配置消息,接收來自用戶模式的WMI服務命令。
- 緩存管理程序,將引用的磁盤數據存儲在主存,提高運行效率
- 內存管理器,實現了虛擬內存
- 邏輯預取器,加速系統與進程啓動
- 執行體包括以下四類主要的支持函數:
- 對象管理器,創建,管理與刪除Windows執行體對象與抽象數據類,它們代表着Windows的資源,例如進程,線程與各種同步對象
- 高級LPC設施,爲同一臺機器上的客戶端進程與服務器進程傳遞消息
- 公共庫運行函數,例如字符串處理,算數操作,數據類型轉換等等
- 執行體支持例程,例如系統內存分配,互鎖內存訪問等等
- Windows執行體爲Ntoskrnl.exe中的上層(內核爲下層),其中包含如下函數
-
內核
- 內核由Ntoskrnl.exe中的一組函數以及對硬件底層架構的支持(例如中斷與異常)構成的,Ntoskrnl.exe中的函數提供了一些最基本的機制,例如線程調度與同步,供執行體組件使用,而面對硬件底層部分則由硬件決定
-
內核對象
- 相對於執行體標記的對象(需要對象句柄,安全檢查,資源配置等等),內核對象更加簡單,不需要這些額外開銷。絕大多數執行體層對象都封裝了一個及以上的內核對象,併合並了內核屬性。
- 其中執行體通過內核函數來創建管理內核對象,其中內核對象包括
- 控制對象,包括控制各種操作系統功能的語義
- 分發器對象,融合了同步能力,具有影響、改變線程調度能力,例如線程,互斥體,事件,定時器等等。
-
內核處理器控制區與控制塊
* 內和使用一個處理器控制區(KPCR)存放處理器相關數據。KPCR包含基本信息,例如處理器中斷分發表(IDT)、任務狀態段(TSS)、全局描述符表(GDT)
* KPCR中包含了一個內核處理器控制塊(KPCRB),其中包含調度信息,處理器信息等等。 -
硬件抽象層(HAL)
- 爲了方便移植,Windows操作系統使用HAL來隱藏底部細節,並且提供對於硬件訪問的功能,對於不同的硬件平臺只需替換HAL即可
-
設備驅動程序
- 可加載的內核模式模塊(一般爲.sys),他們在I/O管理器與相應的硬件之間建立連接。設備驅動程序一般運行於內核模式下,三種環境中:
- 在發起I/O功能的用戶線程環境中
- 在內核模式系統線程的環境中
- 作爲中斷的結果(此時不處於特定線程、進程環境中)
- 設備驅動程序往往不直接用於維護硬件,而是調用HAL中的函數與硬件交互,一般而言驅動可以在Windows支持的CPU體系中以源碼移植,或同一體系中以二進制移植
- 設備驅動程序包括:
- 硬件設備驅動程序
- 文件系統驅動程序
- 文件系統過濾驅動程序
- 網絡重定向器與服務器
- 協議驅動程序
- 內核流式過濾驅動程序
- 某種角度而言驅動程序是用戶在系統添加自己代碼的方式
- 可加載的內核模式模塊(一般爲.sys),他們在I/O管理器與相應的硬件之間建立連接。設備驅動程序一般運行於內核模式下,三種環境中:
-
Windows驅動程序模型
- 從WDM角度看存在三種驅動程序
- 總線驅動程序
- 功能驅動程序
- 過濾驅動程序
- 從WDM角度看存在三種驅動程序
-
Windows驅動程序基礎(WDF)
- WDF簡化了驅動的開發,它提供兩個框架:內核模式驅動程序框架(KMDF)與用戶模式驅動程序框架(UMDF)
-
系統進程
- 基礎系統進程包括
- Idle進程,用於佔用空閒CPU時間
- system進程,所有系統子線程都是屬於system進程,只能在內核模式運行。
- 會話管理器(Smss.exe),系統創建的第一個用戶模式進程
- 本地會話管理器(Lsm.exe)
- Windows子系統(Csrss.exe)
- 會話0初始化(Wininit.exe)
- 登錄進程(Winlogon.exe)
- 服務控制管理器(Services.exe)以及其創建的子服務進程(例如通用服務宿主進程Svchost.exe)
- 本地安全認證服務器(Lsass.exe)
- 基礎系統進程包括