Ch2.5~Ch2.7 ( p53~p96 ) TEAM 4 指導教授 : 許富皓

Slides:



Advertisements
Similar presentations
WCI361 Windows Vista WCI361 Windows Vista 运行性能设计与 改进.
Advertisements

第一單元 建立java 程式.
LinkIt ONE開發板的簡介.
Chapter 2 Windows 系統總述 Team 1 (page 17 ~ page 56)
操作系统结构.
陳維魁 博士 儒林圖書公司 第九章 資料抽象化 陳維魁 博士 儒林圖書公司.
Project 2 JMVC code tracing
Hadoop 單機設定與啟動 step 1. 設定登入免密碼 step 2. 安裝java step 3. 下載安裝Hadoop
題目:十六對一多工器 姓名:李國豪 學號:B
程式語言的基礎 Input Output Program 世代 程式語言 第一世代 Machine language 第二世代
臺北市立大學 資訊科學系(含碩士班) 賴阿福
VMware Player 安裝說明 2018/11/14.
TCP協定 (傳輸層).
Q101 在701 SDX Linux上的標準安裝與使用程序v2
第一篇 Unix/Linux 操作介面 第 1 章 Unix/Linux 系統概論 第 2 章 開始使用 Unix/Linux
JDK 安裝教學 (for Win7) Soochow University
第1章 認識Arduino.
Windows 2000/XP网络组建与系统管理 李燕 中南分校.
Working with Databases (II) 靜宜大學資管系 楊子青
Google Data API Spreadsheet
電腦硬體裝修乙級 第二站-伺服器端系統安裝與環境設定
HiNet 光世代非固定制 用戶端IPv6設定方式說明
類別(class) 類別class與物件object.
SQL Stored Procedure SQL 預存程序.
R教學 安裝RStudio 羅琪老師.
安裝JDK 安裝Eclipse Eclipse 中文化
Merge Partners’ programs by Matlab
2017 Operating Systems 作業系統實習 助教:陳主恩、林欣穎 實驗室:720A.
雲端運算的基石(2) 虛擬化技術實作(XP篇─上)
檔案與磁碟的基本介紹.
OSGi (Open Service Gateway Initiative)
私立南山高中 信息組 電腦研習 電腦資料的備份 中華民國 99年4月20日 星期二.
Chap3 Linked List 鏈結串列.
電腦攻擊與防禦 使用電腦教室VMware軟體說明.
凌宁 系统工程师 亚洲区嵌入式系统事业群 微软(中国)有限公司
第3章 認識處理元.
網路安全技術期末報告 Proxy Server
網路安全技術 OSI七層 學生:A 郭瀝婷 指導教授:梁明章.
Topic Introduction—RMI
第一單元 建立java 程式.
Ch20. 計算器 (Mac 版本).
Linux作業系統 電腦教室Linux使用說明.
第 19 章 XML記憶體執行模式.
讓Emulator可以 使用Android Market
緩衝區溢位攻擊 學生:A 羅以豪 教授:梁明章
Class & Object 靜宜大學資工系 蔡奇偉副教授 ©2011.
FTP使用教學 簡介: 軟體名稱:FileZilla 軟體性質:Freeware 版本: 繁體中文版
File Input and Output Chap. 11: 施威銘的書 Chap. 7: K&R.
MicroSim pspice.
利用 EditorConfig 自訂文字編輯器設定
Video 影像 (VideoPlayer 影像播放器、Camcorder 錄影機) 靜宜大學資管系 楊子青
流程控制:Switch-Case 94學年度第一學期‧資訊教育 東海大學物理系.
取得與安裝TIDE 從TIBBO網站取得TIDE
MiRanda Java Interface v1.0的使用方法
案件名稱: 資安預警通報 通報等級: 第一級 發生時間: 2019/02/24 03:53:28 案件說明:
陣列與結構.
編輯網頁可用那些應用程式? 記事本 Word FrontPage Dreamweaver.
Chapter 15 檔案存取 LabVIEW中的檔案存取函數也可將程式中的資料儲存成Excel或Word檔。只要將欲存取的檔案路徑位址透過LabVIEW中的路徑元件告訴檔案存取函數後,LabVIEW便可將資料存成Excel或Word檔;當然也可以將Excel或Word檔的資料讀入LabVIEW的程式中。
Cloud Operating System - Unit 03: 雲端平台建構實驗
2018 Operating Systems 作業系統實習 助教:林欣穎 實驗室:720A.
MultiThread Introduction
安裝JDK 配置windows win7 環境變數
作業系統實習課(二) -Scheduler-Related System Calls-
ABAP Basic Concept (2) 運算子 控制式與迴圈 Subroutines Event Block
String類別 在C語言中提供兩種支援字串的方式 可以使用傳統以null結尾的字元陣列 使用string類別
Chapter 4 Multi-Threads (多執行緒).
Develop and Build Drives by Visual C++ IDE
Department of Computer Information Science, NCTU
ABAP Basic Concept (2) 運算子 控制式與迴圈 Subroutines Event Block
InputStreamReader Console Scanner
Presentation transcript:

Ch2.5~Ch2.7 ( p53~p96 ) TEAM 4 指導教授 : 許富皓 Window 核心原理與實務開發 Ch2.5~Ch2.7 ( p53~p96 ) TEAM 4 指導教授 : 許富皓 100522039      曾毓傑   985402018      左昌國 100522060      何儒軒 985402017   許齊顯 100522073      歐巡丞 100522004      陳威宇 100522078      李佳恆 100522109      連 捷 100522068      陳安琪 100522102      吳浩維 100552023      廖緯玲 995202109      關呂叡

Outline 2.5 Windows核心中的公用管理設施 2.6 Windows啟動過程 2.7 本章總結 2.5.2 登錄和組態管理員 2.5.3 事件追蹤 ( ETW ) 2.5.4 安全性管理 2.6 Windows啟動過程 2.6.1 核心載入 2.6.2 核心初始化 2.6.3 建立使用者登入工作階段 2.7 本章總結

2.5.1 Windows核心中的物件管理 (報告者 : 歐巡丞) (報告者 : 李佳恆)

物件管理員 子系統DLL NTDLL.DLL Windows 子系統 視窗管理 圖形介面 圖形驅 動程式 執行體API 記憶 體管 理員 行程和 緒程管 理員 隨插 即用 管理 員 安全 參照 監視 器 快取 管理 員 本地程序呼叫(LPC) 組態 管理員 (登錄) I/O 檔案 系統 物件管理員 網路 裝置驅 動程式 核心(或微核心) 硬體抽象層(HAL) 子系統服務 系統服務 使用者模式 核心模式

What’s Object? (wiki) Each resource, which are surfaced as logical objects Resources can be physical devices, files or folders on volumes, Registry entries or even processes and Threads

物件管理員 Object Manager is a subsystem implemented as part of the Windows Executive which manages Windows resources. (Wiki) 在Windows核心中,屬於執行體中的元件。 物件可分成物件標頭和物件主體。

物件標頭 引用計數 物件的控制代碼數 物件型別 各個資訊的記憶體偏移 安全描述項 根據物件型別提供資訊與否 物件主體開始

物件型別(Object Type) WRK支援31種物件,索引(Index)不可紀錄超過48種物件。

物件型別(Object Type) typedef struct _OBJECT_TYPE { … UNICODE_STRING Name; ULOGN Index; ULONG TotalNumberOfObjects; ULONG TotalNumberOfHandles; OBJECT_TYPE_INITIALIZER TypeInfo; } OBJECT_TYPE, *POBJECT_TYPE; Type Name, 例如 process 記錄在Type陣列中的索引 這個物件 是一個 TYPE (TYPE形式的物件) 系統變數:ObpObjectTypes陣列 :此陣列紀錄所有已建立的TYPE

物件結構 物件 1 物件型態 物件 2 名稱 型態名稱 路徑 Access Types 物件標頭 … 物件主體 Body 物件 3

建立一個物件 物件型別初始化 建立物件標頭,分配記憶體給物件主體 完成物件主體初始化

ObCreateObjectType NTSTATUS ObCreateObjectType( __in PUNICODE_STRING TypeName, __in POBJECT_TYPE_INITIALIZER ObjectTypeInitializer, __in_opt PSECURITY_DESCRIPTOR SecurityDescriptor, __out POBJECT_TYPE *ObjectType ); 物件型別初始化 建立物件標頭,分配記憶體給物件主體 完成物件主體初始化

_OBJECT_TYPE_INITIALIZER typedef struct _OBJECT_TYPE_INITIALIZER { USHORT Length; … OB_DUMP_METHOD DumpProcedure; OB_OPEN_METHOD OpenProcedure; OB_CLOSE_METHOD CloseProcedure; OB_DELETE_METHOD DeleteProcedure; OB_PARSE_METHOD ParseProcedure; } OBJECT_TYPE_INITIALIZER, *POBJECT_TYPE_INITIALIZER; 物件型別初始化 建立物件標頭,分配記憶體給物件主體 完成物件主體初始化

ObCreateObject NTSTATUS ObCreateObject( __in KPROCESSOR_MODE ProbeMode, __in POBJECT_TYPE ObjectType, __in POBJECT_ATTRIBUTE ObjectAttributes, … __in ULONG ObjectBodySize, __out PVOID *Object ); 物件型別初始化 建立物件標頭,分配記憶體給物件主體 完成物件主體初始化

Example: 建立Process 先初始化ObjectType一些欄位 建立Process的ObjectType 物件型別初始化 建立物件標頭,分配記憶體給物件主體 完成物件主體初始化

Example: 建立Process 建立Process的物件 利用PspCreateProcess函式建立Process. 物件型別初始化 建立物件標頭,分配記憶體給物件主體 完成物件主體初始化

物件管理員設計目的 提供一種統一而又可擴充的定義和控制機制 提供一致性的安全存取機制 無須修改已有系統程式碼,而又可加入新的物件型別 有一組標準的API來對物件執行各種操作 提供一種命名機制,與檔案系統的命名機制整合再一起。

物件層次目錄(系統全域命名空間) Windows 也提供以’名稱’的方式管理物件 --------------------------------------------------------------- WHY ? 方便找到某個物件 , 分類 剛剛前面所說 Windows 以 TYPE方式來管理 方便: 它可以使process 只需要透過<名稱> 來找到要引用或建立的物件 分類: 例如我門建立一個 Device 目錄.,而此目錄都放所有與device有關的物件 ------------------------------------------------------------------------------------------------- Window internal 5: 若物件不是用來作分享的 物件可以不給name

ObpRootDirectoryObject NtCreateDirectoryObject() 目錄建立過程 Winobj程式 ObpRootDirectoryObject 定義根目錄 NtCreateDirectoryObject() ObpRootDirectoryObject (全域變數) TYPE: ObpDirectoryObjectType 系統會預設建立一些子目錄 Winobj程式 可以存去到系統object manager所維護的目錄 建立子目錄

標準Object Directories (from book Windows internal 5th) \ arcname\ BaseNamedObjects\ callback\ device\ driver\ FileSystem\ GLOBAL??\ KnownDlls\ ObjectTypes\ RPC Control\ Windows\ Sessions\ UMDFCommunicationPort \ \ Symbolic links mapping ARC-style paths to NT-Style paths. Mutexes,events,semaphores,waitable timers and section objects for Session 0. Callback Object. Device objects. Driver objects. File system driver object and file system recognizer divice objects. MS-Dos device names. Section names and path for Known DLLs. Ames of tyes of objects. Port objects use by remote procedure calls. Windows subsystem ports and windows sations. Per-session namespace directory ALPC ports used by the User-Mode Driver Framwork 補充

物件管理員如何管理目錄 (物件管理員所提供的基本操作) ObpLookupDirectoryEntry函式: 在一個指定的目錄中收尋一個名稱 ObpInsertDirectoryEntry 把一個物件插到一個目錄中 ObpDeleteDirectoryEntry 刪除某個目錄中的物件 ObpLookupObjectName 可以從指定的目錄或根目錄,以名稱遞迴的尋找 (obOpenObjectByName,ObReferenceObjectByName 也利用此function) 前3個涵式都是在指定的目錄中運作 其他物件管理員得function也利用此ObpLookupObjectName來完成

EPROCEss – DeviceMap欄位 name Windows相容從DOS時代保留的下來的的習慣 ,以磁碟機代號來存取磁碟機或檔案系統的習慣 判別方法: 當物件管理員在解析名稱時,看到 “\??\”開頭或是 “ \??”它就會利用process的devicemap來取得相關的目錄,再進一步解析。  例: ”\??\C:\” DeviceMap: 定義一個Dos裝置命名空間 詳細第七章 這頁是說 除了剛剛的階成目錄外 EPROCEss – DeviceMap欄位

7.3.2 \??\C: 例子 根(\) DeviceMap DosDevice Directory HarddiskVolume1 \DosDevices\C: EPROCEss – DeviceMap欄位 Dos Devices C: D: 詳細第七章

Handle 物件管理員中得物件是執行體物件,所以這些物件位於KERNEL SPACE 但是PROCESS中執行的user mode code不能直接用指標來引用這些物件 所以只能透過Handle(控制代碼)來引用物件 詳細第三章  重這裡開始 跟 剛剛的Name無關 透過Handle(控制代碼)來引用物件 <配合system call>

Object生命週期管理 透過引用計數來管理生命週期 引用計數等於零 -> 物件生命週期結束 (所占用的記憶體可以回收) 引用計數  引用計數等於零 -> 物件生命週期結束 (所占用的記憶體可以回收) 引用計數 某物件被 系統中指標引用(Reference)      process使用Handle(控制代碼)引用 kernel指標引用( 核心中有人引用某物件 此物件記數+1else -1)

WinoBJ 介紹 WinObj 是 32 位元的 Windows 程式,使用原生 Windows NT API (由 NTDLL.DLL 所提供) 來存取和顯示 NT 物件管理員的命名空間資訊。 WinoBJ http://technet.microsoft.com/en-us/sysinternals/bb896657

WinoBJ

WinoBJ

WinoBJ Quota charges ???

登錄和組態管理員架構 (報告者 : 陳安琪 ) 組態管理員和登錄的初始化 2.5.2 登錄和組態管理員 登錄和組態管理員架構 (報告者 : 陳安琪 ) 組態管理員和登錄的初始化 P66 中間

組態管理員與登錄 Windows系統利用登錄檔( registry )作為系統的組態和管理中心 提供API供應用程式存取登錄 例如,我們安裝了Office Word,則安裝元件在過程中便會透過API來向Registry註冊檔案關聯。 安裝完畢後,*.docx檔案皆會與相應的程式 ( 即Office Word )關聯 由執行體中的組態管理員(configuration manager)負責實作 子系統DLL NTDLL.DLL Windows 子系統 視窗管理 圖形介面 圖形驅 動程式 執行體API 記憶 體管 理員 行程和 緒程管 理員 隨插 即用 管理 員 安全 參照 監視 器 快取 管理 員 本地程序呼叫(LPC) 組態 管理員 (登錄) I/O 檔案 系統 物件管理員 網路 裝置驅 動程式 核心(或微核心) 硬體抽象層(HAL) 子系統服務 系統服務 使用者模式 核心模式 P61 它包含電腦上所有硬體, 軟體, 使用者和參數的訊息和設定。無論什麼時候, 使用者對一個控制台設定, 檔案關聯或者系統策略做出更改, 或者安裝軟體, 更改都會反映並且儲存到登錄檔中。

登錄簡介 Root Key value Sub Key Value類型可大致分成 REG_DWORD ( 32位元整數 ) REG_BINARY ( 二進位資料 ) REG_SZ ( 字串 ) REG_LINK

登錄區( hive ) 登錄檔是由一組稱為登錄區( hive )的檔案所構成 每個登錄區皆為樹狀結構 包含了機碼 ( key )、值 ( value ) Value 包含了名稱、類型、資料 資料可為實際的資料或是索引值指向其他value 實作資料結構為CMHIVE 定義在base\ntos\config\cmp.h _HHIVE, which contains the mapping table used to translate cells full path, the number of handles to it that are open

Root Key 有關檔案關聯和COM的設置資訊 [HKCU] 有關目前使用者的資訊,這是一個符號連結,指向HKU中對應於目前使用者的子機碼 HKEY_CLASSES_ROOT [HKCR] 有關檔案關聯和COM的設置資訊 HKEY_CURRENT_USER [HKCU] 有關目前使用者的資訊,這是一個符號連結,指向HKU中對應於目前使用者的子機碼 P62~P63 + 表2.5 HKEY_LOCAL_MACHINE [HKLM] 存放整個系統全域的組態資訊 HKEY_USERS [HKU] 存放系統上所有使用者帳戶的資訊,並包含 一個.DEFAULT的預設檔 HKEY_CURRENT_CONFIG [HKCC] 有關目前硬體的設置資訊,指向HKLM\SYSTEM\CurrentControlSet\底下的subkey

Root Key ( cont. ) HKLM和HKU為真正存放系統設置資訊的子樹,不隨登入帳戶而發生變化 HKCU、HKCR、HKCC都是利用HKLM和HKU重新建構出針對目前使用者、硬體環境的檢視 P63上半部 + 中間 登錄的邏輯架構

HKEY_LOCAL_MACHINE HKLM存放系統的全域資訊,包含五個subkey HARDWARE 硬體設置 SAM (Security Account Manager) ,安全性帳戶管理員 SECURITY 安全性原則及使用者權限 SOFTWARE 軟體設置 SYSTEM 系統中的全域組態資訊,在系統初始化時會最先被載入, 包括裝置驅動程式和系統服務等

HKLM\SYSTEM 組態管理員透過HKLM\SYSTEM底下的hivelist建立起完整的登錄 HKLM\SYSTEM\CurrentControlSet\control\hivelist P63下半部 + 圖2.9 登錄的儲存架構

Invisible Root Key HKEY_PERFORMANCE_xxx並不存在登錄檔中,Windows系統為上層應用程式提供API來獲得效能資訊 HKEY_PERFORMANCE_DATA [HKPD] 與效能有關的資料,這是系統的執行狀態資訊 HKEY_PERFORMANCE_TEXT 以美國英語的文字來描述效能計數器 HKEY_PERFORMANCE_NLSTEXT 以系統本機語言的文字來描述效能計數器 P62~P63 + 表2.5

登錄區 登錄區的登錄機碼 登錄區的檔案路徑 揮發登錄區,僅存在記憶體中 \Windows\System32\Config\sam HKLM\HARDWARE 揮發登錄區,僅存在記憶體中 HKLM\SAM \Windows\System32\Config\sam HKLM\SECURITY \Windows\System32\Config\security HKLM\SOFTWARE \Windows\System32\Config\software HKLM\SYSTEM \Windows\System32\Config\system HKU\.DEFAULT \Windows\System32\Config\default HKU\<使用者的SID> \Document and Settings\<使用者名稱>ntuser.dat HKU\<使用者的SID>_Classes \Document and Settings\<使用者名稱>\Local Settings\Application Data\Microsoft\Windows\ usrclass.dat P63 表2.6

登錄區架構-Block Block為登錄區的基本分配單元 每個block大小為4K 登錄區的第一個Block稱為Base Block 儲存所有登錄區的訊息 ( Signature、 TimeStamp 、 RootCell…) 資料結構為HBASE_BLOCK P64下半部

登錄區架構-Cell、Bin Cell ( 儲存格 )為儲存登錄檔的基本單位 儲存箱 ( Bin )為擴充既有的登錄區所需申請的儲存單元 資料結構為HCELL 其中HCELL_INDEX為該Cell在檔案中的偏移量 資料型別為ULONG 可用來引用其他Cell,建立起Cells之間的關聯 儲存箱 ( Bin )為擴充既有的登錄區所需申請的儲存單元 資料結構為HBIN Defined in base\ntos\inc\hivedata.h

透過Cell Index建立關係 父機碼 儲存格 祖父機碼 儲存格 安全描述項 儲存格 類別名稱串 儲存格 值列表 儲存格 子機碼列表 儲存格 值1 儲存格 值2 儲存格 值n 儲存格 子機碼1 儲存格 子機碼2 儲存格 … …….. 指向父機碼儲存格 箭頭代表透過儲存格索引建立起來的引用關係 P65 圖2.10

Hive Structure [ref ] 每個儲存箱可容納一個以上的Block 第一個Block稱為Base Block 每個儲存箱簽名( hbin )後即為Cells區塊

登錄和組態管理員 每個登錄區在kernel address space中可能會有兩個Cell目錄 穩定(stable) 的配置資料: On-Disk 揮發(volatile)的配置資料: In Memory 每個儲存格目錄,有1024項,每一項指向一個儲存格表 每個儲存格表包含512個表項,每一項指向一個區塊(block) Stable Directory …. 1023 區塊 (block) Table Entry 0 …. Entry 511 Hive Main Storage ……. P66 中間 Volatile Directory …. 1023 區塊 (block)

HCELL_INDEX Structure 31 30 21 20 12 11 0 Type Cell Directory Index Cell Table Index Byte Offset in Block egistry hives live two lives: one, as on-disk files, stored in %WINDIR%\system32\config\, and another, as an in-memory structure that the Configuration Manager uses in memory. In the former, cell indices can be thought of essentially as simple  translate a cell index to a virtual address In Windows XP and Windows Server 2003, the configuration manager maps portions of a hive into memory as it needs to access them. It uses the cache manager's file mapping functions to map in 16-KB views into the hive files. HMAP_ENTRY

組態管理員起始化以前 組態管理員的實作仰賴於記憶體管理員、快取管理員、檔案系統… 在執行體元件 ( 組態管理員、記憶體管理員、快取管理員…)尚未完全初始化前,Windows已經需要使用登錄中的組態資訊了 核心載入器( ntldr )會將整個HKLM\SYSTEM登錄區視為Read-Only檔案載入記憶體 \Windows\System32\Config\System 組態管理員透過Cell Index+HKLM\SYSTEM基底位址即可取得Cell的位址

登錄和組態管理員架構 組態管理員和登錄的初始化 (報告者 : 何儒軒) 2.5.2 登錄和組態管理員 登錄和組態管理員架構 組態管理員和登錄的初始化 (報告者 : 何儒軒) P66 中間

組態管理員和登錄的初始化 分三個步驟初始化 第一部分:在核心初始化過程中建立HKLM\System及HKLM\Hardware 第二部分:由工作階段管理員(smss.exe)載入HKLM\Sam、HKLM\Security、HKLM\Software、HKLM\.Default登錄區 第三部分:由登入行程(winlogon.exe)載入剩下的一些登錄值

登錄初始化第一部分 開機過程中呼叫到CmInitSystem1()去初始化 初始化組態管理員的全域變數,但還沒有產生出組態管理員 建立出通用的CmpKeyObjectType base/ntos/init/initos.c, line 1437 Phase1InitializationDiscard() { ... CmInitSystem1(); } base/ntos/config/cmsysini.c, line 466 CmInitSystem1() { ... status = CmpCreateObjectType(); }

登錄初始化第一部分(Cont.) 建立主登錄區(\) 建立節點\Registry 使用CmpLinkHiveToMaster()將建立的Machine及User節點連結到\Registry\Machine及\Registry\User位置 將ntldr已經載入至記憶體的system hive去初始化\Registry\Machine\System base/ntos/config/cmsysini.c, line 476 status = CmpInitializeHive(...); base/ntos/config/cmsysini.c, line 506 status = CmpCreateRegistryRoot(...); base/ntos/config/cmsysini.c, line 574 CmpInitializeSystemHive(...);

登錄初始化第一部分(Cont.) 建立節點\Registry\Machine\System\CurrentControlSet 建立揮發性(volatile)節點\Registry\Machine\Hardware 將系統的開機資訊寫進Registry之中,包含\Registry\Machine\Hardware資訊、系統啟動資訊、網路資訊 base/ntos/config/cmsysini.c, line 584 status = CmpCreateControlSet(...); base/ntos/config/cmsysini.c, line 594 status = CmpInitializeHive(...);

登錄初始化第一部分(Cont.) \ \Registry \Registry\User \Registry\Machine \Registry\Machine\System \Registry\Machine\System\CurrentControlSet \Registry\Machine\Hardware

登錄初始化第二部分 由smss.exe呼叫NtInitializeRegistry() 呼叫CmpInitializeHiveList 讀取HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\hivelist 為裡面的機碼分別建立系統Thread:CmpLoadHiveThread 將個別的hive file去載入到對應的登錄區位置 base/ntos/config/ntapi.c, line 1199 NtInitializeRegistry(...) { CmpcmdInit(...); } base/ntos/config/cmworkers.c, line 277 CmpcmdInit(...) { CmpInitializeHiveList(); }

登錄初始化第二部分(Cont.) \ \Registry \Registry\User \Registry\Machine \Registry\Machine\System \Registry\Machine\System\CurrentControlSet \Registry\Machine\Hardware \Registry\Machine\Sam \Registry\Machine\Security \Registry\Machine\Software \Registry\Machine\.Default

登錄初始化第三部分 當某位使用者登入時,由winlogon.exe呼叫系統服務NtLoadKey去載入\Registry\<User SID>下的登錄值 NtLoadKey也使用CmpInitializeHiveList來處理要載入的hive file

登錄檔中的Key Key的資料結構為CM_KEY_BODY 組態管理員為每個開啟的Key物件加入一個Key Control Block(由NtOpenKey()去觸發) 資料結構為CM_KEY_CONTROL_BLOCK 使用物件管理員的CmpKeyObjectType 這些Key Control Block會經由Hash存放進CmpCacheTable 未來存取Key時,就從CmpCacheTable找出Key Control Block來操作該組Key ObjectType定義了一些function去操作Key E.g. CmdParseKey

給應用程式使用的Registry API NtOpenKey 拿到某個機碼的handle ObOpenObjectByName ObLookupObjectName CmpParseKey CmpBuildHashStackAndLookupCache base/ntos/config/ntapi.c, line 2028 NtOpenKey( __out PHANDLE KeyHandle, __in ACCESS_MASK DesiredAccess, __in POBJECT_ATTRIBUTES ObjectAttributes )

給應用程式使用的Registry API(Cont.) NtQueryValueKey 由NtOpenKey拿到keyHandle之後,就可以拿到該Key中某個value的data CmQueryValueKey CmpFindValueByNameFromCache base/ntos/config/ntapi.c, line 2028 NtQueryValueKey( __in HANDLE KeyHandle, __in PUNICODE_STRING ValueName, __in KEY_VALUE_INFORMATION_CLASS yValueInformationClass, __out_bcount_opt(Length) PVOID KeyValueInformation, __in ULONG Length, __out PULONG ResultLength )

給應用程式使用的Registry API(Cont.) NtCreateKey、NtDeleteKey、NtDeleteValueKey、 NtSetValueKey、NtFlushKey… Registry更新時的監聽API NtNotifyChangeKey、NtNotifyChangeMultipleKey

2.5.3 事件追蹤 ( ETW ) ETW (報告者:連捷)

Event Tracing for Windows ( ETW) Windows提供統一追蹤和紀錄事件的機制,稱為ETW ( Event Tracing for Windows )。使用者模式應用程式和核心模式應用程式都可以使用ETW來紀錄事件。 ETW是直接由核心支援的事件紀錄機制,有三種元件: 控制器(controller) 提供者(provider) 消費者(consumer) 控制器:控制器啟動、停止或配置事件紀錄工作階段。 提供者:它們向ETW註冊自己的事件類別,並接受控制器的命令,以便啟動或停止它們所負責的事件類別的記錄過程 消費者:針對讀取它們想要的資料,選擇一個或多個紀錄工作階段。它們既可以即時地接收ETW緩衝區中的資料,也可以接收日誌檔案中的事件資料。

ETW ( cont.) 事件追蹤對於診斷系統效能問題非常重要,Windows內建了一個核心日誌紀錄器(kernel logger),做為ETW提供者,專門紀錄核心和核心驅動程式的事件。 此核心日誌記錄器是由WMI裝(Windows Management Instrumentation)置驅動程式實作的,也是核心模組 ntoskrnl.exe 的一部分。

WMI簡介 WMI驅動程式的名稱為 “WMIxWDM”,它是在管理員初始化過程中呼叫WMI元件的初始化函式(WMIInitialize)而建立的。 由於實作的形式是驅動程式,因此其他的核心常式或裝置驅動程式可以透過I/O介面與他通訊。 WMI是工業標準WBEM ( Web-Based Enterprise Management )的一個實作。 (第二點後) 儘管 Windows 早期版本已經提供了像事件管理員和效能計數器這些機制來報告錯誤或只是關鍵的效能資料,但這需機制缺乏統一的程式編寫介面且都不具備良好的擴充能力。 隨著 Windows 系統越來越複雜,以及各個應用程式都有事件報告和效能分析的需求。 Windows 提供一個新的事件管理機制,即 WMI。 (第三點後) WBEM標準包含了一套針對企業系統的資料獲取和資料管理機制的設計方案,它具有很好的靈活性和擴充性。

WMI簡介 ( cont. ) 從 Windows NT 4 (SP4)開始的 Windows版本均支援WMI。 ETW的核心日誌記錄器實際上也是WMI機制的一部分。

核心日誌紀錄器 核心日誌紀錄器是一個事件提供者,他有一個預先定義的 GUID,即核心變數SystemTraceControlGuid。 核心日誌紀錄器支援多種事件類別,它採用旗標位元 (flag) 來只是否記錄某一事件的類型。下面是相關定義。 #define PERF_MASK_INDEX (0xe0000000) #define PERF_MASK_GROUP (~PERF_MASK_INDEX) #define PERF_NUM_MASKS 8 typedef ULONG PERFINFO_MASK; (解釋圖) 它將旗標位元分乘8個群組,每個群組使用一個遮罩(29位元)來描述旗標位元

PERFINFO_GROUPMASK物件 typedef struct_PERFINFO_GROUPMASK{ ULONG Masks[PERF_NUM_MASKS]; }PERFINFO_GROUPMASK , *PPERFINFO_GROUPMASK; 核心日誌記錄器的旗標位元安排是由 Windows 系統定義的,並且允許擴充。 PERFINFO_GROUPMASK的mask陣列包含8個ULONG成員,每個ULONG的最高3位元式群組的索引,低29位元為群組內的旗標位元。\

PERFT_CONTEXT_SWITCH定義 Windows Server 2003僅僅使用了一部分旗標位元,例如PERF_CONTEXT_SWITCH的定義如下: #define PERF_CONTEXT_SWITCH 0x20000004 // Context Switch 這說明處理器緒程環境切換的事件旗標位元是第2個群組的低3位元。 PERFINFO_GROUPMASK的mask陣列包含8個ULONG成員,每個ULONG的最高3位元式群組的索引,低29位元為群組內的旗標位元。\

PERFT_CONTEXT_SWITCH 在Windows中,系統的通用群組遮罩是由全域變數PerfGlobalGroupMask定義的,以環境切換事件為例,當PERF_CONTEXT_SWITCH旗標位元被設定時,緒程切換時就會記錄一個CSWITCH事件。 PERFINFO_GROUPMASK的mask陣列包含8個ULONG成員,每個ULONG的最高3位元式群組的索引,低29位元為群組內的旗標位元。\

緩衝區管理 緩衝區管理是WMI驅動程式的重要職責之一,它為環境切換事件定義了一個緩衝區陣列,讓每個處理器使用它自己的緩衝區,而避免緩衝區衝突。 一旦屬於某個處理器的目前緩衝區滿了,則交給WMI更新該緩衝區,下次紀錄新的CSWITCH事件時重新申請一個新的緩衝區做為目前緩衝區。 WMI為每個紀錄工作階段管理緩衝區,它在建立記錄工作階段時根據控制器的指示,建立合理數量的緩衝區。

xperf Microsoft提供了一個效能工具xperf,它既是一個控制器,也是一個消費者。xperf利用I/O介面與WMI驅動程式通訊。 Windows SDK 提供了事件追蹤API(位於advapi32.dll模組中),因而使用者模式應用程式可以很方便地操縱和控制WMI驅動程式。xperf直接在ntdll.dll的ETW介面上工作,並沒有使用advapi32.dll中的事件追蹤API。 (一開始)現在我們來看核心日誌記錄器的控制器和消費者

xperf ( cont. ) 儘管在Windows Server 2003中就有ETW和WMI的完整實作程式碼,但是限於核心日誌記錄器僅僅提供了有限的事件類別,並卻乏成熟的分析工具,因此,在Windows Server 2003 及以前的版本Windows 系統中ETW和WMI並沒有廣泛的使用。 從Windows Vista 開始,核心日誌記錄器提供了大量核心事件資訊,並且在許多關鍵上可以會出相關的呼叫堆疊,且xperf工具可以自由下載,其分析功能更架豐富。 因此,在更新版本的windows系統環境中利用ETW和WMI做為校能分析工具,有希望解決大量原先非常棘手或根本無從解決的問題。

xperf ( cont. ) Microsoft提供的xperf工具不能直接在Windows XP/server 2003上安裝,但實際上它的可持型模組可以在這些系統上執行,只不過受限於核心日誌記錄器的能力,它並不能截獲到像在Windows Vista以後系統中那麼多的事件。 WMI驅動程式的介面規格以及核心日誌記錄器支援的事件類別再不同的Windows系統中保持一致,這是xperf仍然可以在Windows XP/Server 2003 上持型的基礎。 在Windows Vista及以後的系統中,WMI驅動程式和核心日誌記錄器的內部實作有相關調整和變化。

2.5.4 安全性管理 (報告者:闕呂叡)

Windows 安全模型 作為一個現代作業系統,Windows 有嚴格的安全模型。 以物件為基礎的任意存取控制(discretionary access control) 系統級的強制存取控制(mandatory access control)

任意存取控制模型 物件的所有者授權或拒絕哪些人可以存取該物件。 考慮到了物件擁有者遺失的情形。 不能保護系統中的所有操作。 系統關機 備份檔案和目錄 互動式登入到系統中 在任意存取控制模型中,物件的所有者授權或拒絕那些人可以存取該物件。而且,Windows還考慮到了物件擁有者遺失的情形,即,當由於些原因物件的所有者不再有效時,特權使用者可以將物件的所有權接管過來,從而他們可以存取該物件,或授權其他使用者存取它。這在某些情形下是有意義的,比如若一個企業的員工離職了,系統管理員仍然可以存取到該員工的文件,即使這些文件只有該員工的帳戶才可以存取。

安全性管理的核心元件 Windows作業系統的簡化安全模型 負責回應SAS(安全注意序列),以及管理互動式登錄工作階段。當使用者登錄到系統中時,winlogon 創建一個初始行程,並進一步由建立外殼(shell)行程。 Windows作業系統的簡化安全模型 包含了有關目前系統的一些資訊,EX:誰被允許存取系統以及如何存取(互動式登錄、網路登入或者以服務方式登錄);分配給誰哪些特權;安全稽核如何進行等。 負責本地系統的安全策略,同時,它也認證用戶的身份,以及將安全稽核訊息發送到系統的事件日誌中。 包含了本機使用者和使用者群組,以及它們的密碼和其他屬性。 負責執行物件的安全訪問檢查、管理使用者特權、生成安全稽核消息,並且定義了存取權杖資料結構來表示一個安全環境。 在介紹如何實作任意存取控制和強制存取控制以前,我們首先看一下Windows作業系統中涉及安全性管理的核心元件 之前章節曾經提到過這裡的三個元件:winlogon,SRM和lsass 其中winlogon,lsass 是兩個使用者模式行程 SRM是Windows執行體中的元件

Windows作業系統的安全模型 在Windows 的安全模型中 winlogon 負責系統登入,包括對用戶身份的認證。 lsass 負責管理系統本機安全性原則的管理,並且將這些策略通知到核心中的SRM。 在核心中,SRM 負責實現基於物件的存取控制以及系統全域安全性原則的實施。

Windows作業系統的安全模型 在Windows 的安全模型中 lsass 和SRM 對於系統的安全性至關重要,一旦這兩個元件被惡意代碼修改或侵入,則系統的安全防線將不復存在。 Windows對這兩個元件有特殊的保護,普通應用程式無法與它們打交道,它們相互之間通過LPC進行通訊。 它們的LPC 連接在系統初始化時建立,而且,一旦其雙向LPC 連接建立起來,它們的LPC 埠便不再接受任何其他的連接請求,因而其他程式與它們無法建立LPC 連接。

Windows作業系統的安全模型 Windows 的自主存取模型與物件管理員整合在一起,每一種物件型別都定義了一個Security 方法,該方法傳回一個物件的安全資訊。 緒程在存取一個物件以前必須先開啟這個物件,並獲得一個指向該物件的控制碼。 在開啟物件的操作中,物件管理員呼叫SRM的函式,根據呼叫緒程的安全憑證、在開啟操作中請求的存取類型(EX:讀、寫、刪除等),以及該型別物件的Security 方法提供的物件安全資訊,來決定此開啟操作是否允許。

Windows作業系統的安全模型 如果可以開啟該物件,那麼,物件管理員在緒程的行程控制代碼表中建立一個控制碼,記錄下該物件以及它所請求的存取類型。 之後,當該緒程存取此物件時,它傳遞該物件的控制碼,而物件管理員將該緒程所請求的存取操作與該物件被開啟時所獲得的存取類型進行比較,如果目前的存取操作允許,則安全檢查通過,否則此次物件存取失敗。

Windows作業系統的安全模型 屬行程的安全環境,而是以其他帳戶身份 來運行的安全環境,這稱為模仿 (impersonation)。 在這個模型中有兩點值得提一下 1. 為了存取一個物件,緒程可以不使用它所 屬行程的安全環境,而是以其他帳戶身份 來運行的安全環境,這稱為模仿 (impersonation)。 2.同一個行程中的其他緒程也可以利用已經 得到的控制碼來存取該物件。 第一: 每個緒程有一個安全環境,其中最重要的資訊是一個存取權杖,即代表了該緒程的使用者的一次登入;每個物件有一個任意存取控制清單(ACL), 指明了允許誰以何種方式存取該物件,而拒絕那些使用者以何種方式存取它。為了存取一個物件,緒程可以不使用它所屬行程的安全環境,而是以其他帳戶身分來執行的安全環境,這稱為模仿(impersonation)。 第二: 物件管理員使用呼叫緒程的安全環境和它所請求的存取操作,對照該物件被開啟時獲得的存取類型進行檢查,以決定是否允許該操作。

物件管理員開啟一個物件時SRM所執行的安全檢查 呼叫緒程的安全環境: SECURITY_SUBJECT_CONTEXT { ClientToken PrimaryToken … } 描述了一個用戶的一次登錄 若模仿 權杖 由winlogon行程在認證了使用者身份以後建立 不模仿 同一個使用者工作階段中執行的行程都使用同樣的權杖 是物件管理員的函數,它將物件管理員與SRM 的安全監視機制連接起來。 呼叫ObCheckObjectAccess 然後呼叫型別物件的SecurityProcedure 函式成員,由它填充一個自包含的安全描述符緩衝區。 獲得目標物件的SD(安全描述項),資料類型為SECURITY_DESCRIPTOR。 被存取物件 DACL 執行安全訪問許可檢查。 ObGetObjectSecurity SecurityProcedure 安全描述項包含了物件所有者的SID、DACL 、 SACL,以及其他一些描述物件安全特徵的屬性。 對於每一種類型的物件,系統在建立它的型別物件時,可以指定該類物件的Security方法,即SecurityProcedure 函數成員 SeAccessCheck SeAccessCheck 是SRM 的一個核心介面函式,真正執行檢查任務是在SepAccessCheck 函式中。 SepNormalAccessCheck 函數的實現較為直截了當,對DACL 中的項逐一檢查是否允許或拒絕此次訪問操作。 SepAccessCheck SepNormalCheck 首先檢查呼叫者是否有SeSecurityPrivilege 特權,然後從物件的安全描述符中獲得DACL 否則,調用SepNormalAccessCheck 函數執行正常的許可檢查。 如果DACL 為空,則拒絕所有存取。 如果物件沒有DACL清單,則總是允許存取,傳回成功。 檢查 傳回 拒絕 成功 物件管理員開啟一個物件時SRM所執行的安全檢查

SePrivilegeCheck 函式的特權檢查程序 在權杖TOKEN 資料結構的定義中,有一個Privileges 成員,代表該權杖帳戶的所有特權 因此,SepPrivilegeCheck 函數的實作是,用一個雙重迴圈,對呼叫緒程所請求檢查的每一個特權,遊走Token 參數中的Privileges 陣列成員,看是否符合。 SRM 的強制存取控制是透過特權檢查來實施的 SePrivilegeCheck 函數是SRM 中用於特權檢查的核心介面函式 SePrivilegeCheck 執行實際的特權檢查 SepPrivilegeCheck(Token,RequiredPrivileges,RequirePrivilegeCount,PrivilegeSetControl…) 目前緒程的安全環境 定義了如何請求這些特權。 即,請求所有指定的特權或其中之一。 特權中已賦予的特權集合 請求檢查的特權集合 合起來指明了呼叫緒程要請求的一組特權 逐一匹配 已匹配個數 檢查 請求檢查所有的特權或其中之一 傳回TRUE或FALSE SePrivilegeCheck 函式的特權檢查程序

SePrivilegeCheck 函式的特權檢查程序 在Windows 中,特權是由LUID 物件來標識的 LUID 代表一個本地唯一識別字(Locally Unique Identifier) 由兩個LONG 成員構成 每一個特權都附帶一些屬性,兩者結合起來構成了LUID_AND_ATTRIBUTES 資料結構,而屬性是一個無符號長整數類型。 以下是LUID_AND_ATTRIBUTES 及一組屬性的定義: typedef struct _LUID_AND_ATTRIBUTES { LUID Luid; ULONG Attributes; } LUID_AND_ATTRIBUTES, * PLUID_AND_ATTRIBUTES; #define SE_PRIVILEGE_ENABLED_BY_DEFAULT (0x00000001L) #define SE_PRIVILEGE_ENABLED (0x00000002L) #define SE_PRIVILEGE_REMOVED (0X00000004L) #define SE_PRIVILEGE_USED_FOR_ACCESS (0x80000000L)

全域特權 Windows 內核中定義了一組特權,即類型為LUID 的Se<Xxx>全域變數,其定義位於base\ntos\se\seglobal.c 檔中,它們的初始化由該檔中的SepVariableInitialization 函數來完成。這組全域特權為:

SePrivilegeCheck 函式的特權檢查程序 對於每一種特權,當相關聯的操作(即需要此特權才能進行的操作)在核心中被適當的元件觸動時,應透過SePrivilegeCheck 或它的包裝函數SeSinglePrivilegeCheck,來檢查呼叫緒程是否具有相關的特權。 EX : SepCreateToken 函數在把權杖物件插入到行程的控制碼表之前呼叫SeSinglePrivilegeCheck 函數來檢查當前緒程是否具有SeCreateTokenPrivilege特權。 EX : IopParseDevice函數在打開一個設備物件時透過IopCheckBackupRestorePrivilege函數(它呼叫SePrivilegeCheck)來檢查呼叫緒程是否具有SeBackupPrivilege 或SeRestorePrivilege特權。

Conclusion Windows 安全性管理是一個複雜的話題,其安全模型涉及系統的方方面面,而且模型中的許多元件和擴展結構是在使用者模式下運行的。 本節僅僅討論了Windows 安全性管理的核心部分,即核心中的安全引用監視器,包括它的物件訪問和特權操作的檢查過程。 在Windows 核心中,與安全相關的函數以“Se”作為字首,有一些安全函式還存在對應的系統服務。這些系統服務函數的名稱以“Nt”作為字首,後面部分與“Se”函式相同。 在WRK 的public\sdk\inc\ntseapi.h 檔中包含了與安全有關的系統服務函數的原型宣告,而base\ntos\inc\se.h 檔中包含了核心安全函數的原型宣告,包括本節之前提到過的眾多以“Se”為首碼的函數(注意,以Sep 為字首的函數是SRM 的內建函式)。

2.6.1 核心載入 (報告者: 許齊顯) 2.6.2 核心初始化 2.6.3 建立使用者登入工作階段 2.6 Windows啟動過程 2.6.1 核心載入 (報告者: 許齊顯) 2.6.2 核心初始化 2.6.3 建立使用者登入工作階段 P66 中間

開機從哪裡執行? 剛開機時,作業系統尚未載入,Memory也沒有資料,於是,什麼都不能執行? 為了解決這種問題,硬體製造商與OS設計者產生一些 “約定”。

BIOS與硬體商的約定 硬體將直接把BIOS的啟動區塊載入到0xFE000~0xFFFFF,並且自0xFFFF:0x0000開始執行。

BIOS在用硬碟開機時的約定 在BIOS進行POST(Power on self test)結束後,將根據BIOS設定自相對應磁碟把第0磁碟第0磁軌第1磁區(512 bytes)載入0x07C00,然後執行。 第0磁碟第0磁軌第1磁區也被稱為MBR(Master Boot Record)

檔案系統設計者之間的約定 MBR會包含硬碟上可以拿來開機的磁碟分割。MBR的任務便是將搜尋到的磁碟分割的第一磁區載入並執行,此磁區稱為開機磁區,此磁碟分割稱為系統磁碟區。 OS會在安裝時將可開機的磁碟分割注入MBR之中。

Windows 對於開機磁區的修改 Windows會覆寫開機磁區使其自動載入Windows的OS Loader-ntldr,並將其載入至0x20000。 ntldr可分為2部分, 一部份為real mode的Binary程式 另一部份為標準的PE格式執行檔-osloader.exe

ntldr

ntldr - Real Mode Real mode的程式率先執行,此時,CPU處於真實模式,記憶體存取有著0xFFFFF(1MB)的上限,而且Page機制未啟動。 因此,real mode的目標為開啟Paging機制,並對應好前16MB的Paging Table,最後切換至Protected Mode並執行osloader.exe。

osloader.exe osloader.exe的任務是載入所有OS開機過程中所需的檔案。 主要流程 讀取boot.ini並搜尋Hiberfil.sys。若存在,進行休眠回復。 若非休眠回復,載入NTDETECT.COM以供利用BIOS查詢系統裝置資訊。 載入ntosktnl.exe,boot.ini中指定的HAL檔。

osloader.exe(cont.) 主要流程(續) 載入\Windows\System32\Config\System為System註冊機碼。 查詢System註冊機碼以載入適當驅動程式。 將過程中所有資料蒐集於LOADER_PARAMETER_BLOCK結構中,並執行ntoskrnl.exe的入口程式 (Entry Point)。

LOADER_PARAMETER_BLOCK [\public\internal\base\inc\arc.h] typedef struct _LOADER_PARAMETER_BLOCK { LIST_ENTRY LoadOrderListHead; // 載入模組的串列 LIST_ENTRY MemoryDescriptorListHead; LIST_ENTRY BootDriverListHead; ULONG_PTR KernelStack; // 核心堆疊的位置 ULONG_PTR Prcb; // Prcocessor Control Block ULONG_PTR Process; // EPROCESS ULONG_PTR Thread; // ETHREAD ULONG RegistryLength; PVOID RegistryBase; PCONFIGURATION_COMPONENT_DATA ConfigurationRoot; PCHAR ArcBootDeviceName; PCHAR ArcHalDeviceName; PCHAR NtBootPathName; PCHAR NtHalPathName; PCHAR LoadOptions; // boot.ini裡的選項 PNLS_DATA_BLOCK NlsData; PARC_DISK_INFORMATION ArcDiskInformation; PVOID OemFontFile; struct _SETUP_LOADER_BLOCK *SetupLoaderBlock; PLOADER_PARAMETER_EXTENSION Extension; union { I386_LOADER_BLOCK I386; // ALPHA_LOADER_BLOCK Alpha; // IA64_LOADER_BLOCK Ia64; } u; } LOADER_PARAMETER_BLOCK, *PLOADER_PARAMETER_BLOCK;

開機流程總結 BIOS MBR 開機磁區 ntldr 真實模式 osloader.exe ntoskrnl.exe: Entry Point

2.6.1 核心載入 2.6.2 核心初始化 (報告者: 許齊顯) 2.6.3 建立使用者登入工作階段 2.6 Windows啟動過程 2.6.1 核心載入 2.6.2 核心初始化 (報告者: 許齊顯) 2.6.3 建立使用者登入工作階段 P66 中間

入口程式(Entry Point) ntoskrnl.exe執行其入口程式 設定於\base\ntos\build\makefile 預設為KiSystemStartup !if "$(targ)" == “i386” 。。。 。。。 entrypoint = KiSystemStartup@4 !else entrypoint = KiSystemStartup !endif

核心初始化階段 核心初始分成2個階段:Phase 0與Phase 1 許多系統元件於此2階段進行不同的初始化。 KiSystemStartup()執行時,中斷(Interrupt)為禁止狀態。 KiSystemStartup()將在Phase 0不受任何中斷影響地初始化Phase 1所需的資料,並為了開啟中斷做準備。 Phase1Initialization()則接手初始好的基本資料,並進行Phase 1的初始化。

KiSystemStartup [\base\ntos\ke\i386\newsysbg.asm] 參數為OS loader傳入的LOADER_PARAMETER_BLOCK 初始化IDT(Interrupt Descriptor Table)、TSS(Task State Segment)、PCR(Processor Control Region) 主要流程 呼叫HalInitializeProcessor()初始化PCR及中斷向量 呼叫KiInitializeKernel()初始化核心相關的資料結構 啟用中斷並降低Priority以讓Phase 1啟動 執行KiIdleLoop()使目前執行緒成為Idle Thread

KiSystemStartup重點程式 cPublicProc _KiSystemStartup ,1 。。。 。。。 stdCall _HalInitializeProcessor, <dword ptr KissPbNumber, KissLoaderBlock> stdCall _KiInitializeKernel,<offset _KiInitialProcess,ebx,edx,dword ptr PCR[PcPrcb],eax,_KeLoaderBlock> Sti ; 啟用中斷 LowerIrql DISPATCH_LEVEL ; 降低Priority mov byte ptr [ebx]+ThWaitIrql, DISPATCH_LEVEL @@: cmp _KiBarrierWait, 0 ; check if barrier set YIELD jnz short @b jmp @KiIdleLoop@0 ; enter idle loop stdENDP _KiSystemStartup

KiInitializeKernel [\base\ntos\ke\i386\kernlini.c] 根據目前是否為開機核心(Processor 0)針對PRCB(Processor Control Block)進行更詳細的設定。 主要流程 呼叫KeInitializeThread()初始化目前執行緒的Thread Object,並初始化排程(Schedule)時所需的資料結構。 設定目前執行緒專屬於當前Processor。 呼叫ExpInitializeExecutive()初始化執行體。

KiInitializeKernel重點程式 VOID KiInitializeKernel ( IN PKPROCESS Process,IN PKTHREAD Thread,IN PVOID IdleStack, IN PKPRCB Prcb, IN CCHAR Number, PLOADER_PARAMETER_BLOCK LoaderBlock ){ 。。。 。。。 if (Number == 0) { // 判斷是否為開機核心 } else { } KeInitializeThread(Thread, (PVOID)((ULONG)IdleStack), (PKSYSTEM_ROUTINE)NULL, (PKSTART_ROUTINE)NULL, (PVOID)NULL, (PCONTEXT)NULL, (PVOID)NULL, Process); Thread->Affinity = (KAFFINITY)(1<<Number); // 設定此執行緒只能在這個Processor上執行 ExpInitializeExecutive(Number, LoaderBlock);

ExpInitializeExecutive [\base\ntos\init\initos.c] 主要執行執行體中各類元件的Phase 0初始化。 除HAL外元件都只在開機核心才進行初始化。 主要流程 初始化元件包含HAL、執行體、記憶體管理員、記憶體集區、物件管理員、安全子系統、行程資料、執行緒管理員、隨插即用管理員。

ExpInitializeExecutive重點程式 VOID ExpInitializeExecutive( IN ULONG Number,IN PLOADER_PARAMETER_BLOCK LoaderBlock ){ 。。。 。。。 if (Number == 0) { // 確認開機核心 InitializationPhase = 0L; // 設定指示“Phase”的全域變數 if (HalInitSystem(InitializationPhase, LoaderBlock) == FALSE) {} if (!ExInitSystem()){} // 初始化執行體相關資料結構 if (MmInitSystem (0, LoaderBlock) == FALSE) {} // 初始化記憶體管理員 if (!ObInitSystem()){} // 初始化物件管理員 if (!SeInitSystem()){} // 初始化安全子系統 if (PsInitSystem(0, LoaderBlock) == FALSE){} // 初始化行程及緒程 if (!PpInitSystem()) {} // 初始化隨插即用管理員 } else{

PspInitPhase0 [\base\ntos\ps\psinit.c] 由PsInitSystem於Phase 0呼叫 負責初始所有行程及執行緒皆須使用的資料結構。 並負責將初始目前行程為“Idle”`,並產生“System”行程,並加入進行Phase 1的執行緒

PspInitPhase0重點程式 BOOLEAN PspInitPhase0 ( IN PLOADER_PARAMETER_BLOCK LoaderBlock ){ 。。。 。。。 if(!NT_SUCCESS (ObCreateObjectType(&NameString, &ObjectTypeInitializer, (PSECURITY_DESCRIPTOR) NULL,&PsProcessType))) {} if (!NT_SUCCESS (PspCreateProcess (&PspInitialSystemProcessHandle, PROCESS_ALL_ACCESS,&ObjectAttributes, NULL, 0, NULL, NULL, NULL, 0))) {} strcpy((char *) &PsIdleProcess->ImageFileName[0], "Idle"); strcpy((char *) &PsInitialSystemProcess->ImageFileName[0], "System"); if (!NT_SUCCESS (PsCreateSystemThread (&ThreadHandle, THREAD_ALL_ACCESS, &ObjectAttributes, 0L, NULL, Phase1Initialization, (PVOID)LoaderBlock))) {} }

Phase1Initialization [\base\ntos\init\initos.c] 執行Phase1InitilizationDiscard() 而後結束內部初始流程,轉化執行緒為回收記憶體用的MmZeroPageThread()

Phase1InitializationDiscard [\base\ntos\init\initos.c] 呼叫KeStartAllProcessors() 對各項元件進行Phase 1的初始化,以正式啟用各項元件。 包含物件管理員、記憶體管理員、組態管理員等 把啟動時獲得的資料轉換成登錄碼中的 “HKLM\SYSTEM”及 “HKLM\HARDWARE” 初始化SRM,並開啟LPC Port接受lsass.exe的請求。 建立smss.exe行程,等待其執行並接手剩餘工作,於是Phase 1正式結束。

Phase1InitializationDiscard重點程式 VOID Phase1InitializationDiscard (PVOID Context){ 。。。 。。。 InitializationPhase = 1; KeStartAllProcessors(); RtlCopyMemory(ProcessParameters->ImagePathName.Buffer, // NtInitialUserProcessBuffer==“\SystemRoot\System32\smss.exe” NtInitialUserProcessBuffer, ProcessParameters->ImagePathName.Length); Status = RtlCreateUserProcess(&SessionManager, OBJ_CASE_INSENSITIVE, RtlDeNormalizeProcessParams( ProcessParameters ), NULL, NULL, NULL, FALSE, NULL, NULL, ProcessInformation); }

KeStartAllProcessors [\base\ntos\ke\i386\allproc.c] 設立全域變數KiBarrierWait,使其他Processor最多完成Phase 0的初始化。 呼叫KiInitProcessor()初始化其他Processor KiInitProcessor()呼叫KiInitProcessorState()建構其他Processor的啟動設定。 KiInitProcessor()呼叫HalStartNextProcessor()啟動Processor 等候所有其他Processor成功初始Phase 0,解除KiBarrierWait,其他Processor得以進入Phase 1。

KeStartAllProcessors重點程式 VOID KeStartAllProcessors (VOID){ 。。。 。。。 KiBarrierWait = 1; // 阻擋非開機Processor停在Phase 0 for (NewProcessorNumber = 1; NewProcessorNumber < MAXIMUM_PROCESSORS; NewProcessorNumber++) { if (! KiInitProcessor(NewProcessorNumber, &NodeNumber, IdtOffset, GdtOffset, ProcessorDataSize) ) {} } KiBarrierWait = 0;

KiInitProcessorState [\base\ntos\ke\i386\allproc.c] 藉由修改屬於該Processor的PCR,設定eip為KiSystemStartup

KiInitProcessorState重點程式 PKPRCB KiInitProcessorState( PKPROCESSOR_STATE pProcessorState, PVOID PerProcessorAllocation, ULONG NewProcessorNumber, UCHAR NodeNumber, ULONG IdtOffset, ULONG GdtOffset, PVOID *ppStack, PVOID *ppDpcStack ){ 。。。 。。。 pProcessorState->ContextFrame.Eip = (ULONG) KiSystemStartup; KiInitializePcr( (ULONG) NewProcessorNumber, (PKPCR) PCRDesc.Base, (PKIDTENTRY) pProcessorState ->SpecialRegisters.Idtr.Base, (PKGDTENTRY) pProcessorState ->SpecialRegisters.Gdtr.Base, (PKTSS) TSSDesc.Base, (PKTHREAD) pThreadObject, (PVOID) *ppDpcStack ); }

MmZeroPageThread [\base\ntos\mm\zeropage.c] 回收屬於 “INIT” section的Memory。 負責將OS回收的Memory Page的內容重設為 0。 如: #pragma alloc_text(INIT, ExpInitializeExecutive)

MmZeroPageThread重點程式 VOID MmZeroPageThread (VOID){ 。。。 。。。 MiFindInitializationCode (&StartVa, &EndVa); if (StartVa != NULL) { MiFreeInitializationCode (StartVa, EndVa); }

核心初始化總結 ntldr Processor 0 KiSystemStartup Other Processor Idle Process HalInitializeProcessor KiSystemStartup KiInitializeKernel HalInitializeProcessor KeInitializeThread ExpInitializeExecutive KiInitializeKernel HalInitSystem KeInitializeThread PsInitSystem ExpInitializeExecutive PspInitPhase0 KiIdleLoop HalInitSystem Phase1Initilization System Process KiIdleLoop Phase1InitializationDiscard KeStartAllProcessors KiInitProcessor KiInitProcessorState HalStartNextProcessor MmZeroPageThread

2.6.1 核心載入 2.6.2 核心初始化 2.6.3 建立使用者登入工作階段 (報告者 : 左昌國) 2.6 Windows啟動過程 2.6.1 核心載入 2.6.2 核心初始化 2.6.3 建立使用者登入工作階段 (報告者 : 左昌國) P66 中間

建立使用者登入工作階段 前面所提到的Phase1主函式Phase1InitializationDiscard 在最後會建立工作階段管理員子系統行程(Session Manager Subsystem) smss.exe,這一節主要就是在講解smss.exe在Windows系統啟動的過程中,所扮演的角色。 WRK裡沒有包含smss.exe的原始碼,必須要用run-time debugging來trace code

建立使用者登入工作階段 \SystemRoot\System32\smss.exe base/ntos/init/initos.c : 01776 SessionManager = ProcessParameters->ImagePathName; 01777 Status = RtlCreateUserProcess( 01778 &SessionManager, 01779 OBJ_CASE_INSENSITIVE, 01780 RtlDeNormalizeProcessParams( ProcessParameters ), 01781 NULL, 01782 NULL, 01783 NULL, 01784 FALSE, 01785 NULL, 01786 NULL, 01787 ProcessInformation); … 01818 OldTime.QuadPart = Int32x32To64(5, -(10 * 1000 * 1000)); 01819 Status = ZwWaitForSingleObject( 01820 ProcessInformation->Process, 01821 FALSE, 01822 &OldTime 01823 ); 在這邊就已經建好smss.exe 這邊會等5秒鐘

建立使用者登入工作階段 smss.exe Windows系統啟動時第一個執行的user-mode process 屬於native application 建立時,沒有Windows Subsystem smss的其中一個任務就是建立其他的Subsystem 使用native APIs,無法使用Win32 APIs 視為trusted OS component,可以做一些需要高權限的工作

建立使用者登入工作階段 smss的工作 載入除了SYSTEM,以及使用者設定檔以外的registry到記憶體裡 執行開機時的檔案刪除或是檔案重新命名 執行已知的DLL(例如一些子系統DLL) 建立分頁檔 載入win32k.sys (子系統的核心模組) 執行子系統csrss.exe 執行登入行程winlogon.exe 前面在phase1的時候,就已經載入了system registry

建立使用者登入工作階段 載入registry smss呼叫系統服務NtInitializeRegistry(原始碼位於base/ntos/config/ntapi.c#1030)來初始化registry以及載入某些registry NtInitializeRegistry呼叫CmpInitializeHiveList來載入登錄區域(page39)

建立使用者登入工作階段 Call stack, 下面的是caller, 上面的是callee

建立使用者登入工作階段 前面39頁

建立使用者登入工作階段

建立使用者登入工作階段 系統啟動時要執行的程式 smss的主要函式SmpLoadDataFromRegistry會讀取在registry裡HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\BootExecute所記錄的值,並且視為開機階段要執行的程式,並透過SmpExecuteCommand去執行 基本上會有autochk.exe 接下來的很多工作都是從這個主要函式來控制 基本上BootExecute裡面會有autochk, 開機後版本的chkdsk

建立使用者登入工作階段

建立使用者登入工作階段 開機時刪除檔案或更改檔案名稱 呼叫SmpProcessFileRenames,根據存在HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\FileRenameOperations的機碼,視為檔案名稱來做這項動作 這邊因為是空的,所以開機時沒有執行

建立使用者登入工作階段 執行已知的DLL 呼叫SmpInitializeKnownDlls,根據HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs裡面紀錄的機碼來找到需要被載入的DLL file

建立使用者登入工作階段 HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs

建立使用者登入工作階段 建立分頁檔(Paging Files) 呼叫SmpCreatePagingFiles,分頁檔列表在HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management\PagingFiles HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management 576最小值, 1152最大值

建立使用者登入工作階段 載入win32k.sys base/ntos/ex/sysinfo.c 透過系統服務NtSetSystemInformation來達成在kernel中載入win32k.sys base/ntos/ex/sysinfo.c 03452 Image = *(PUNICODE_STRING)SystemInformation; 03453 Status = MmLoadSystemImage(&Image, 03454 NULL, 03455 NULL, 03456 MM_LOAD_IMAGE_IN_SESSION, 03457 &SectionPointer, 03458 (PVOID *)&ImageBaseAddress); “\SystemRoot\System32\win32k.sys”

建立使用者登入工作階段

建立使用者登入工作階段 執行子系統csrss.exe 呼叫SmpLoadSubSystem來載入csrss,csrss.exe的路徑紀錄在HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\SubSystems裡的Windows機碼 HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\SubSystems

建立使用者登入工作階段

建立使用者登入工作階段 執行登入行程winlogon.exe smss做完上述的初始化工作之後,就會執行winlogon.exe,並且等待(WaitForSingleObject)csrss和winlogon的結束,一旦smss發現其中有一個結束,就代表Windows出現問題,就會跳到CheckBug程序並且當機 winlogon.exe也會做很多事情 建立初始視窗工作站Winsta0 建立登入桌面 啟動服務控制管理員(SCM, Service Control Manager) 啟動子系統lsass 啟動userinit

建立使用者登入工作階段 建立Winsta0 建立登入桌面(winlogon desktop) 建立桌面Thread以及RIT(Raw Input Thread) 建立登入桌面(winlogon desktop) 只有winlogon.exe可以存取登入桌面,因此與密碼相關的操作以及鎖定/解除桌面的操作,只能透過winlogon.exe,用來當作保護措施 啟動服務控制管理員(SCM, Service Control Manager) SCM即為services.exe SCM用來控制所有的服務與裝置驅動程式 SCM在載入時會啟動auto-start類型的服務以及驅動程式 Station和desktop在第9章 Window station是一個物件(object), 同一個session只會有一個interactive station 其他的station只有可能是service的non-interactive station 剪貼簿就屬於window station 桌面(desktop): station可以有多個desktop, 重要的desktop有default desktop和winlogon desktop Default就是一般的桌面 登入時看到的桌面是winlogon desktop

建立使用者登入工作階段 啟動子系統lsass 本機安全性授權子系統(Local Security Authority subsystem) Lsass啟動後,winlogon和lsass之間會建立一個LPC(LsaAuthenticationPort),在使用者登入和登出的時候用來在兩個程序當中通訊 子系統相關在ch 9

建立使用者登入工作階段 啟動userinit Winlogon會透過HKLM\SOFTWARE\Microsoft\WindowsNT\Current Version\Winlogon\Userinit來取得userinit.exe的路徑 執行userinit.exe之後,會載入使用者設定檔 並且執行shell(explorer.exe),預設的shell路徑在HKLM\SOFTWARE\Microsoft\WindowsNT\Current Version\Winlogon\Shell 登入完成後,userinit.exe會自動結束

建立使用者登入工作階段 HKLM\SOFTWARE\Microsoft\WindowsNT\Current Version\Winlogon

建立使用者登入工作階段 smss.exe 載入registry 載入win32k.sys 執行csrss.exe 執行winlogon.exe 建立視窗工作站 建立登入桌面 執行SCM(services.exe) 載入auto-start services和drivers 執行lsass.exe 使用者登入 認證 lsass.exe 執行userinit.exe 執行shell explorer.exe 結束

END Q & A