組態管理員(登錄)

Download Report

Transcript 組態管理員(登錄)

Window 核心原理與實務開發
Ch2.5~Ch2.7 ( p53~p96 )
TEAM 4
指導教授 : 許富皓
100522039
100522060
100522073
100522078
100522068
100552023
曾毓傑
何儒軒
歐巡丞
李佳恆
陳安琪
廖緯玲
985402018
985402017
100522004
100522109
100522102
995202109
左昌國
許齊顯
陳威宇
連 捷
吳浩維
關呂叡
1
Outline
• 2.5 Windows核心中的公用管理設施
– 2.5.1 Windows核心中的物件管理
– 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
2.5.1 Windows核心中的物件管理
 (報告者 : 歐巡丞)
 (報告者 : 李佳恆)
3
物件管理員
子系統DLL
NTDLL.DLL
使用者模式
子系統服務
Windows
子系統
視窗管理
圖形介面
圖形驅
動程式
核心模式
系統服務
執行體API
記憶 行程和 隨插 安全 快取
體管 緒程管 即用 參照 管理
理員 理員
管理 監視 員
員
器
本地程
序呼叫
(LPC)
物件管理員
核心(或微核心)
組態
管理員
(登錄)
I/O
管理
員
檔案
系統
網路
裝置驅
動程式
硬體抽象層(HAL)
4
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
5
物件管理員
• Object Manager is a subsystem implemented as
part of the Windows Executive which manages
Windows resources. (Wiki)
• 在Windows核心中,屬於執行體中的元件。
• 物件可分成物件標頭和物件主體。
6
物件標頭
引用計數
物件的控
制代碼數
物件型別
安全描述
項
各個資訊
的記憶體
偏移
根據物件
型別提供
資訊與否
物件主體
開始
7
物件型別(Object Type)
• WRK支援31種物件,索引(Index)不可紀錄超
過48種物件。
8
物件型別(Object Type)
typedef struct _OBJECT_TYPE {
…
UNICODE_STRING Name;
…
ULOGN Index;
ULONG TotalNumberOfObjects;
ULONG TotalNumberOfHandles;
…
Type Name, 例如 process
記錄在Type陣列中的索引
OBJECT_TYPE_INITIALIZER TypeInfo;
…
} OBJECT_TYPE, *POBJECT_TYPE;
系統變數:ObpObjectTypes陣列 :此陣列紀錄所有已建立的TYPE
物件結構
物件 1
名稱
路徑
物件標頭
…
物件型態
物件 2
型態名稱
Access Types
物件主體
Body
物件 3
10
建立一個物件
物件型別初始化
建立物件標頭,分配記
憶體給物件主體
完成物件主體初始化
11
ObCreateObjectType
NTSTATUS
物件型別初始化
ObCreateObjectType(
__in PUNICODE_STRING TypeName,
__in POBJECT_TYPE_INITIALIZER ObjectTypeInitializer,
__in_opt PSECURITY_DESCRIPTOR SecurityDescriptor,
__out POBJECT_TYPE *ObjectType
建立物件標頭,分配
記憶體給物件主體
);
完成物件主體初始化
12
_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;
完成物件主體初始化
13
ObCreateObject
NTSTATUS
ObCreateObject(
__in KPROCESSOR_MODE ProbeMode,
__in POBJECT_TYPE ObjectType,
__in POBJECT_ATTRIBUTE ObjectAttributes,
…
__in ULONG ObjectBodySize,
…
__out PVOID *Object
物件型別初始化
建立物件標頭,分配
記憶體給物件主體
);
完成物件主體初始化
14
Example: 建立Process
1. 先初始化ObjectType一些欄位
2. 建立Process的ObjectType
物件型別初始化
建立物件標頭,分配
記憶體給物件主體
完成物件主體初始化
15
Example: 建立Process
3. 建立Process的物件
物件型別初始化
建立物件標頭,分配
記憶體給物件主體
4. 利用PspCreateProcess函式建立Process.
完成物件主體初始化
16
物件管理員設計目的
• 提供一種統一而又可擴充的定義和控制機制
• 提供一致性的安全存取機制
• 無須修改已有系統程式碼,而又可加入新的物
件型別
• 有一組標準的API來對物件執行各種操作
• 提供一種命名機制,與檔案系統的命名機制整
合再一起。
17
物件層次目錄(系統全域命名空間)
• Windows 也提供以’名稱’的方式管理物件
--------------------------------------------------------------• WHY ?
方便找到某個物件 , 分類
目錄建立過程
Winobj程式
ObpRootDirectoryObject 定義根目錄
NtCreateDirectoryObject() 建立子目錄
標準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)
name
 Windows相容從DOS時代保留的下來的的習慣 ,以磁
碟機代號來存取磁碟機或檔案系統的習慣
判別方法:
當物件管理員在解析名稱時,看到 “\??\”開頭或是 “ \??”
它就會利用process的devicemap來取得相關的目錄,再
進一步解析。
例: ”\??\C:\”
• DeviceMap: 定義一個Dos裝置命名空間
詳細第七章
7.3.2
例子
\??\C:
根(\)
DeviceMap
DosDevice
Directory
Device
HarddiskVolume1
HarddiskVolume2
\DosDevices\C:
Dos
Devices
C:
D:
詳細第七章
Handle
• 物件管理員中得物件是執行體物件,所以這些物件位於KERNEL
SPACE
• 但是PROCESS中執行的user mode code不能直接用指標來引用這些物
件
• 所以只能透過Handle(控制代碼)來引用物件
 詳細第三章
Object生命週期管理
• 透過引用計數來管理生命週期
引用計數等於零 -> 物件生命週期結束
(所占用的記憶體可以回收)
 引用計數
某物件被 系統中指標引用(Reference)
process使用Handle(控制代碼)引用
WinoBJ
介紹
• WinObj 是 32 位元的 Windows 程式,使用原
生 Windows NT API (由 NTDLL.DLL 所提供)
來存取和顯示 NT 物件管理員的命名空間資訊。
WinoBJ
http://technet.microsoft.com/en-us/sysinternals/bb896657
WinoBJ
WinoBJ
WinoBJ
2.5.2 登錄和組態管理員
登錄和組態管理員架構
(報告者 : 陳安琪 )
組態管理員和登錄的初始化
30
組態管理員與登錄
• Windows系統利用登錄檔( registry )作為系統的組態和管理中
心
– 提供API供應用程式存取登錄
子系統DLL
NTDLL.DLL
• 例如,我們安裝了Office Word,則安裝元件在過程中便會透過API
使用者模式
來向Registry註冊檔案關聯。
子系統服務
系統服務 ( 即Office Word 核心模式
• 安裝完畢後,*.docx檔案皆會與相應的程式
)關聯
執行體API
manager)負責實作
Windows– 由執行體中的組態管理員(configuration
子系統
視窗管理
圖形介面
圖形驅
動程式
記憶 行程和 隨插 安全 快取
體管 緒程管 即用 參照 管理
理員 理員
管理 監視 員
員
器
本地程
序呼叫
(LPC)
物件管理員
核心(或微核心)
組態
管理員
(登錄)
I/O
管理
員
檔案
系統
網路
裝置驅
動程式
硬體抽象層(HAL)
31
登錄簡介
Root Key
value
Sub Key
• Value類型可大致分成
–
–
–
–
REG_DWORD ( 32位元整數 )
REG_BINARY ( 二進位資料 )
REG_SZ ( 字串 )
REG_LINK
32
登錄區( hive )
• 登錄檔是由一組稱為登錄區( hive )的檔案所
構成
– 每個登錄區皆為樹狀結構
– 包含了機碼 ( key )、值 ( value )
• Value 包含了名稱、類型、資料
– 資料可為實際的資料或是索引值指向其他value
– 實作資料結構為CMHIVE
• 定義在base\ntos\config\cmp.h
33
Root Key
HKEY_CLASSES_ROOT [HKCR] 有關檔案關聯和COM的設置資訊
HKEY_CURRENT_USER [HKCU] 有關目前使用者的資訊,這是一個符號連結,
指向HKU中對應於目前使用者的子機碼
HKEY_LOCAL_MACHINE
[HKLM] 存放整個系統全域的組態資訊
HKEY_USERS [HKU]
存放系統上所有使用者帳戶的資訊,並包含
一個.DEFAULT的預設檔
HKEY_CURRENT_CONFIG [HKCC] 有關目前硬體的設置資訊,指向
HKLM\SYSTEM\CurrentControlSet\底下
的subkey
34
Root Key ( cont. )
• HKLM和HKU為真正存放系統設置資訊的子樹,
不隨登入帳戶而發生變化
– HKCU、HKCR、HKCC都是利用HKLM和HKU
重新建構出針對目前使用者、硬體環境的檢視
35
HKEY_LOCAL_MACHINE
• HKLM存放系統的全域資訊,包含五個subkey
– HARDWARE
• 硬體設置
– SAM (Security Account Manager)
• ,安全性帳戶管理員
– SECURITY
• 安全性原則及使用者權限
– SOFTWARE
• 軟體設置
– SYSTEM
• 系統中的全域組態資訊,在系統初始化時會最先被載入,
包括裝置驅動程式和系統服務等
36
HKLM\SYSTEM
• 組態管理員透過HKLM\SYSTEM底下的hivelist
建立起完整的登錄
– HKLM\SYSTEM\CurrentControlSet\control\hivelist
37
Invisible Root Key
• HKEY_PERFORMANCE_xxx並不存在登錄檔
中,Windows系統為上層應用程式提供API來
獲得效能資訊
HKEY_PERFORMANCE_DATA
[HKPD] 與效能有關的資料,這是系統的執行狀態
資訊
HKEY_PERFORMANCE_TEXT
HKEY_PERFORMANCE_NLSTEXT
以美國英語的文字來描述效能計數器
以系統本機語言的文字來描述效能計數器
38
登錄區
登錄區的登錄機碼
登錄區的檔案路徑
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
39
登錄區架構-Block
• Block為登錄區的基本分配單元
– 每個block大小為4K
– 登錄區的第一個Block稱為Base Block
• 儲存所有登錄區的訊息 ( Signature、 TimeStamp 、
RootCell…)
• 資料結構為HBASE_BLOCK
40
登錄區架構-Cell、Bin
• Cell ( 儲存格 )為儲存登錄檔的基本單位
– 資料結構為HCELL
– 其中HCELL_INDEX為該Cell在檔案中的偏移量
• 資料型別為ULONG
• 可用來引用其他Cell,建立起Cells之間的關聯
• 儲存箱 ( Bin )為擴充既有的登錄區所需申請的
儲存單元
– 資料結構為HBIN
Defined in base\ntos\inc\hivedata.h
41
透過Cell Index建立關係
父機碼
儲存格
祖父機碼
儲存格
值1
儲存格
安全描述項
儲存格
值2
儲存格
箭頭代表透過儲
存格索引建立起
來的引用關係
…
類別名稱串
儲存格
值列表
儲存格
子機碼列表
儲存格
值n
儲存格
子機碼1
儲存格
子機碼2
儲存格
…
…..
值n
儲存格
指向父機碼儲存格
42
Hive Structure [ref ]
• 每個儲存箱可容納一個以上的Block
– 第一個Block稱為Base Block
– 每個儲存箱簽名( hbin )後即為Cells區塊
43
登錄和組態管理員
• 每個登錄區在kernel address space中可能會有兩個Cell目錄
– 穩定(stable) 的配置資料: On-Disk
– 揮發(volatile)的配置資料: In Memory
• 每個儲存格目錄,有1024項,每一項指向一個儲存格表
• 每個儲存格表包含512個表項,每一項指向一個區塊(block)
Stable Directory
0
Main Storage
Hive
….
Table
….
Entry 0
1023
….
Volatile Directory
0
….
….
區塊
(block)
…….
….
Entry 511
區塊
(block)
1023
44
HCELL_INDEX Structure
31
Type
30
21
Cell Directory Index
20
12
Cell Table Index
11
0
Byte Offset in
Block
HMAP_ENTRY
45
組態管理員起始化以前
• 組態管理員的實作仰賴於記憶體管理員、快取
管理員、檔案系統…
• 在執行體元件 ( 組態管理員、記憶體管理員、
快取管理員…)尚未完全初始化前,Windows已
經需要使用登錄中的組態資訊了
– 核心載入器( ntldr )會將整個HKLM\SYSTEM登
錄區視為Read-Only檔案載入記憶體
• \Windows\System32\Config\System
• 組態管理員透過Cell Index+HKLM\SYSTEM基底位
址即可取得Cell的位址
46
2.5.2 登錄和組態管理員
登錄和組態管理員架構
組態管理員和登錄的初始化
(報告者 : 何儒軒)
47
組態管理員和登錄的初始化
• 分三個步驟初始化
– 第一部分:在核心初始化過程中建立
HKLM\System及HKLM\Hardware
– 第二部分:由工作階段管理員(smss.exe)載入
HKLM\Sam、HKLM\Security、HKLM\Software、
HKLM\.Default登錄區
– 第三部分:由登入行程(winlogon.exe)載入剩下
的一些登錄值
48
登錄初始化第一部分
• 開機過程中呼叫到CmInitSystem1()去初始化
base/ntos/init/initos.c, line 1437
Phase1InitializationDiscard() {
...
CmInitSystem1();
...
}
• 初始化組態管理員的全域變數,但還沒有產生
出組態管理員
• 建立出通用的CmpKeyObjectType
base/ntos/config/cmsysini.c, line 466
CmInitSystem1() {
...
status = CmpCreateObjectType();
...
}
49
登錄初始化第一部分(Cont.)
• 建立主登錄區(\)
base/ntos/config/cmsysini.c, line 476
status = CmpInitializeHive(...);
• 建立節點\Registry
base/ntos/config/cmsysini.c, line 506
status = CmpCreateRegistryRoot(...);
• 使用CmpLinkHiveToMaster()將建立的Machine
及User節點連結到\Registry\Machine及
\Registry\User位置
• 將ntldr已經載入至記憶體的system hive去初始
化\Registry\Machine\System
base/ntos/config/cmsysini.c, line 574
CmpInitializeSystemHive(...);
50
登錄初始化第一部分(Cont.)
• 建立節點
\Registry\Machine\System\CurrentControlSet
base/ntos/config/cmsysini.c, line 584
status = CmpCreateControlSet(...);
• 建立揮發性(volatile)節點
\Registry\Machine\Hardware
base/ntos/config/cmsysini.c, line 594
status = CmpInitializeHive(...);
• 將系統的開機資訊寫進Registry之中,包含
\Registry\Machine\Hardware資訊、系統啟動資
訊、網路資訊
51
登錄初始化第一部分(Cont.)
\
\Registry
\Registry\User
\Registry\Machine
 \Registry\Machine\System
 \Registry\Machine\System\CurrentControl
Set
 \Registry\Machine\Hardware
52
登錄初始化第二部分
• 由smss.exe呼叫NtInitializeRegistry()
– 呼叫CmpInitializeHiveList
• 讀取
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControl
Set\Control\hivelist
• 為裡面的機碼分別建立系統Thread:
CmpLoadHiveThread
– 將個別的hive file去載入到對應的登錄區位置
base/ntos/config/ntapi.c, line 1199
NtInitializeRegistry(...) {
CmpcmdInit(...);
}
base/ntos/config/cmworkers.c, line 277
CmpcmdInit(...) {
CmpInitializeHiveList();
}
53
登錄初始化第二部分(Cont.)
\
\Registry
\Registry\User
\Registry\Machine
 \Registry\Machine\System
 \Registry\Machine\System\CurrentControl
Set
 \Registry\Machine\Hardware
 \Registry\Machine\Sam
 \Registry\Machine\Security
 \Registry\Machine\Software
 \Registry\Machine\.Default
54
登錄初始化第三部分
• 當某位使用者登入時,由winlogon.exe呼叫系
統服務NtLoadKey去載入\Registry\<User SID>
下的登錄值
• NtLoadKey也使用CmpInitializeHiveList來處理
要載入的hive file
55
登錄檔中的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
56
給應用程式使用的Registry API
• NtOpenKey
base/ntos/config/ntapi.c, line 2028
NtOpenKey(
__out PHANDLE KeyHandle,
__in ACCESS_MASK DesiredAccess,
__in POBJECT_ATTRIBUTES ObjectAttributes
)
– 拿到某個機碼的handle
– ObOpenObjectByName
– ObLookupObjectName
–
CmpParseKey
–
CmpBuildHashStackAndLookupCache
57
給應用程式使用的Registry API(Cont.)
• NtQueryValueKey
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
)
– 由NtOpenKey拿到keyHandle之後,就可以拿到
該Key中某個value的data
– CmQueryValueKey
– CmpFindValueByNameFromCache
58
給應用程式使用的Registry API(Cont.)
• 更多存取Registry的API
– NtCreateKey、NtDeleteKey、NtDeleteValueKey、
NtSetValueKey、NtFlushKey…
• Registry更新時的監聽API
– NtNotifyChangeKey、
NtNotifyChangeMultipleKey
59
2.5.3 事件追蹤 ( ETW )
 ETW (報告者:連捷)
60
Event Tracing for Windows ( ETW)
• Windows提供統一追蹤和紀錄事件的機制,稱為ETW
( Event Tracing for Windows )。使用者模式應用程式和核心
模式應用程式都可以使用ETW來紀錄事件。
• ETW是直接由核心支援的事件紀錄機制,有三種元件:
– 控制器(controller)
– 提供者(provider)
– 消費者(consumer)
61
ETW ( cont.)
• 事件追蹤對於診斷系統效能問題非常重要,Windows內建
了一個核心日誌紀錄器(kernel logger),做為ETW提供者,
專門紀錄核心和核心驅動程式的事件。
• 此核心日誌記錄器是由WMI裝(Windows Management
Instrumentation)置驅動程式實作的,也是核心模組
ntoskrnl.exe 的一部分。
62
WMI簡介
• WMI驅動程式的名稱為 “WMIxWDM”,它是在管理員初
始化過程中呼叫WMI元件的初始化函式(WMIInitialize)而
建立的。
• 由於實作的形式是驅動程式,因此其他的核心常式或裝置
驅動程式可以透過I/O介面與他通訊。
• WMI是工業標準WBEM ( Web-Based Enterprise
Management )的一個實作。
63
WMI簡介 ( cont. )
• 從 Windows NT 4 (SP4)開始的 Windows版本均支援WMI。
• ETW的核心日誌記錄器實際上也是WMI機制的一部分。
64
核心日誌紀錄器
• 核心日誌紀錄器是一個事件提供者,他有一個預先定義的
GUID,即核心變數SystemTraceControlGuid。
• 核心日誌紀錄器支援多種事件類別,它採用旗標位元 (flag)
來只是否記錄某一事件的類型。下面是相關定義。
#define PERF_MASK_INDEX
#define PERF_MASK_GROUP
(0xe0000000)
(~PERF_MASK_INDEX)
#define PERF_NUM_MASKS
8
typedef ULONG PERFINFO_MASK;
65
PERFINFO_GROUPMASK物件
• 當控制器程式指示核心日誌記錄器記錄某些類型的核心事
件時,它們需要建構一個PERFINFO_GROUPMASK物件,
將需要紀錄的旗標位置上
typedef struct_PERFINFO_GROUPMASK{
ULONG Masks[PERF_NUM_MASKS];
}PERFINFO_GROUPMASK , *PPERFINFO_GROUPMASK;
• 核心日誌記錄器的旗標位元安排是由 Windows 系統定義
的,並且允許擴充。
66
PERFT_CONTEXT_SWITCH定義
• Windows Server 2003僅僅使用了一部分旗標位元,例如
PERF_CONTEXT_SWITCH的定義如下:
• #define PERF_CONTEXT_SWITCH 0x20000004
// Context Switch
• 這說明處理器緒程環境切換的事件旗標位元是第2個群組
的低3位元。
67
PERFT_CONTEXT_SWITCH
• 在Windows中,系統的通用群組遮罩是由全域變數
PerfGlobalGroupMask定義的,以環境切換事件為例,當
PERF_CONTEXT_SWITCH旗標位元被設定時,緒程切換
時就會記錄一個CSWITCH事件。
68
緩衝區管理
• 緩衝區管理是WMI驅動程式的重要職責之一,它為環境切
換事件定義了一個緩衝區陣列,讓每個處理器使用它自己
的緩衝區,而避免緩衝區衝突。
• 一旦屬於某個處理器的目前緩衝區滿了,則交給WMI更新
該緩衝區,下次紀錄新的CSWITCH事件時重新申請一個
新的緩衝區做為目前緩衝區。
• WMI為每個紀錄工作階段管理緩衝區,它在建立記錄工作
階段時根據控制器的指示,建立合理數量的緩衝區。
69
xperf
• Microsoft提供了一個效能工具xperf,它既是一個控制器,
也是一個消費者。xperf利用I/O介面與WMI驅動程式通訊。
• Windows SDK 提供了事件追蹤API(位於advapi32.dll模組
中),因而使用者模式應用程式可以很方便地操縱和控制
WMI驅動程式。xperf直接在ntdll.dll的ETW介面上工作,
並沒有使用advapi32.dll中的事件追蹤API。
70
xperf ( cont. )
• 儘管在Windows Server 2003中就有ETW和WMI的完整實作
程式碼,但是限於核心日誌記錄器僅僅提供了有限的事件
類別,並卻乏成熟的分析工具,因此,在Windows Server
2003 及以前的版本Windows 系統中ETW和WMI並沒有廣
泛的使用。
• 從Windows Vista 開始,核心日誌記錄器提供了大量核心
事件資訊,並且在許多關鍵上可以會出相關的呼叫堆疊,
且xperf工具可以自由下載,其分析功能更架豐富。
71
xperf ( cont. )
• Microsoft提供的xperf工具不能直接在Windows XP/server
2003上安裝,但實際上它的可持型模組可以在這些系統上
執行,只不過受限於核心日誌記錄器的能力,它並不能截
獲到像在Windows Vista以後系統中那麼多的事件。
• WMI驅動程式的介面規格以及核心日誌記錄器支援的事件
類別再不同的Windows系統中保持一致,這是xperf仍然可
以在Windows XP/Server 2003 上持型的基礎。
72
2.5.4 安全性管理
 (報告者:闕呂叡)
73
Windows 安全模型
• 作為一個現代作業系統,Windows 有嚴格的安全
模型。
– 以物件為基礎的任意存取控制(discretionary access
control)
– 系統級的強制存取控制(mandatory access control)
74
任意存取控制模型
• 物件的所有者授權或拒絕哪些人可以存取該物件。
• 考慮到了物件擁有者遺失的情形。
• 不能保護系統中的所有操作。
– 系統關機
– 備份檔案和目錄
– 互動式登入到系統中
75
安全性管理的核心元件
負責回應SAS(安全注意序列),
以及管理互動式登錄工作階段。
當使用者登錄到系統中時,
winlogon 創建一個初始行程,並
進一步由建立外殼(shell)行程。
負責執行物件的安全訪問檢查、
管理使用者特權、生成安全稽
核消息,並且定義了存取權杖
資料結構來表示一個安全環境。
負責本地系統的安全策略,
同時,它也認證用戶的身份,
以及將安全稽核訊息發送到
系統的事件日誌中。
包含了有關目前系統的一些資
訊,EX:誰被允許存取系統以及
如何存取(互動式登錄、網路
登入或者以服務方式登錄);
分配給誰哪些特權;安全稽核
如何進行等。
包含了本機使用者和使
用者群組,以及它們的
密碼和其他屬性。
• Windows作業系統的簡化安全模型
76
Windows作業系統的安全模型
• 在Windows 的安全模型中
– winlogon 負責系統登入,包括對用戶身份的認證。
– lsass 負責管理系統本機安全性原則的管理,並且將這
些策略通知到核心中的SRM。
– 在核心中,SRM 負責實現基於物件的存取控制以及系
統全域安全性原則的實施。
77
Windows作業系統的安全模型
• 在Windows 的安全模型中
– lsass 和SRM 對於系統的安全性至關重要,一旦這兩個
元件被惡意代碼修改或侵入,則系統的安全防線將不
復存在。
– Windows對這兩個元件有特殊的保護,普通應用程式無
法與它們打交道,它們相互之間通過LPC進行通訊。
– 它們的LPC 連接在系統初始化時建立,而且,一旦其
雙向LPC 連接建立起來,它們的LPC 埠便不再接受任
何其他的連接請求,因而其他程式與它們無法建立LPC
連接。
78
Windows作業系統的安全模型
• Windows 的自主存取模型與物件管理員整合在一起,
每一種物件型別都定義了一個Security 方法,該方
法傳回一個物件的安全資訊。
• 緒程在存取一個物件以前必須先開啟這個物件,並
獲得一個指向該物件的控制碼。
• 在開啟物件的操作中,物件管理員呼叫SRM的函式,
根據呼叫緒程的安全憑證、在開啟操作中請求的存
取類型(EX:讀、寫、刪除等),以及該型別物件
的Security 方法提供的物件安全資訊,來決定此開
啟操作是否允許。
79
Windows作業系統的安全模型
• 如果可以開啟該物件,那麼,物件管理員在緒
程的行程控制代碼表中建立一個控制碼,記錄
下該物件以及它所請求的存取類型。
• 之後,當該緒程存取此物件時,它傳遞該物件
的控制碼,而物件管理員將該緒程所請求的存
取操作與該物件被開啟時所獲得的存取類型進
行比較,如果目前的存取操作允許,則安全檢
查通過,否則此次物件存取失敗。
80
Windows作業系統的安全模型
• 在這個模型中有兩點值得提一下
• 1. 為了存取一個物件,緒程可以不使用它所
屬行程的安全環境,而是以其他帳戶身份
來運行的安全環境,這稱為模仿
(impersonation)。
• 2.同一個行程中的其他緒程也可以利用已經
得到的控制碼來存取該物件。
81
SRM安全檢查
呼叫緒程的安全環境:
SECURITY_SUBJECT_CONTEXT
{
若模仿
ClientToken
權杖
PrimaryToken
…
不模仿
}
是物件管理員的函數,它將物件管理員與
SRM 的安全監視機制連接起來。
描述了一個用戶的一次登錄
由winlogon行程在認證了使用者身份以後建立
同一個使用者工作階段中執行的行程都使用同樣的權杖
呼叫ObCheckObjectAccess
然後呼叫型別物件的SecurityProcedure 函式成員,
獲得目標物件的SD(安全描述項),資料類型為
被存取物件
由它填充一個自包含的安全描述符緩衝區。
SECURITY_DESCRIPTOR。
執行安全訪問許可檢查。
ObGetObjectSecurity
SecurityProcedure
DACL
對於每一種類型的物件,系統在建立它的型別物
安全描述項包含了物件所有者的SID、DACL
、
件時,可以指定該類物件的Security方法,即
SACL,以及其他一些描述物件安全特徵的屬性。
SeAccessCheck 是SRM 的一個核心介面函式,真正
SeAccessCheck
SecurityProcedure 函數成員
執行檢查任務是在SepAccessCheck 函式中。
SepNormalAccessCheck 函數的實現較為
SepAccessCheck
SepNormalCheck
直截了當,對DACL 中的項逐一檢查是否
首先檢查呼叫者是否有SeSecurityPrivilege 特權,然後從物件的安全描述符中獲得DACL
允許或拒絕此次訪問操作。
否則,調用SepNormalAccessCheck
如果物件沒有DACL清單,則總是允許存取,傳回成功。
函數執行正常的許可檢查。
如果DACL 為空,則拒絕所有存取。
檢查
傳回
成功
拒絕
物件管理員開啟一個物件時SRM所執行的安全檢查
82
SePrivilegeCheck 函式的特權檢查程序
在權杖TOKEN 資料結構的定義中,有一個Privileges 成員,代表該權杖帳戶的所有特權
因此,SepPrivilegeCheck 函數的實作是,用一個雙重迴圈,對呼叫緒程所請求檢查的
SRM 的強制存取控制是透過特權檢查來實施的
每一個特權,遊走Token 參數中的Privileges 陣列成員,看是否符合。
SePrivilegeCheck 函數是SRM 中用於特權檢查的核心介面函式
SePrivilegeCheck
執行實際的特權檢查
SepPrivilegeCheck(Token,RequiredPrivileges,RequirePrivilegeCount,PrivilegeSetControl…)
目前緒程的安全環境
特權中已賦予
的特權集合
請求檢查的
合起來指明了呼叫緒程要請求的一組特權
特權集合
逐一匹配
定義了如何請求這些特權。
即,請求所有指定的特權或其中之一。
已匹配個數
檢查
請求檢查所有的
特權或其中之一
傳回TRUE或FALSE
SePrivilegeCheck 函式的特權檢查程序
83
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
#define SE_PRIVILEGE_ENABLED
#define SE_PRIVILEGE_REMOVED
#define SE_PRIVILEGE_USED_FOR_ACCESS
(0x00000001L)
(0x00000002L)
(0X00000004L)
(0x80000000L)
84
全域特權
• Windows 內核中定義了一組特權,即類型為LUID 的Se<Xxx>全
域變數,其定義位於base\ntos\se\seglobal.c 檔中,它們的初始化
由該檔中的SepVariableInitialization 函數來完成。這組全域特權為:
85
SePrivilegeCheck 函式的特權檢查程
序
• 對於每一種特權,當相關聯的操作(即需要此特權才能進
行的操作)在核心中被適當的元件觸動時,應透過
SePrivilegeCheck 或它的包裝函數SeSinglePrivilegeCheck,
來檢查呼叫緒程是否具有相關的特權。
– EX : SepCreateToken 函數在把權杖物件插入到行程的控制碼表之
前呼叫SeSinglePrivilegeCheck 函數來檢查當前緒程是否具有
SeCreateTokenPrivilege特權。
– EX : IopParseDevice函數在打開一個設備物件時透過
IopCheckBackupRestorePrivilege函數(它呼叫SePrivilegeCheck)來
檢查呼叫緒程是否具有SeBackupPrivilege 或SeRestorePrivilege特權。
86
Conclusion
• Windows 安全性管理是一個複雜的話題,其安
全模型涉及系統的方方面面,而且模型中的許
多元件和擴展結構是在使用者模式下運行的。
• 本節僅僅討論了Windows 安全性管理的核心部
分,即核心中的安全引用監視器,包括它的物
件訪問和特權操作的檢查過程。
87
2.6 Windows啟動過程
2.6.1 核心載入 (報告者: 許齊顯)
2.6.2 核心初始化
2.6.3 建立使用者登入工作階段
88
開機從哪裡執行?
• 剛開機時,作業系統尚未載入,Memory也沒
有資料,於是,什麼都不能執行?
• 為了解決這種問題,硬體製造商與OS設計者
產生一些 “約定”。
89
BIOS與硬體商的約定
• 硬體將直接把BIOS的啟動區塊載入到0xFE000
~0xFFFFF,並且自0xFFFF:0x0000開始執行。
• 因此,開機之後的第一個程式-BIOS啟動區,
可以順利進行硬體檢查等工作。
90
BIOS在用硬碟開機時的約定
• 在BIOS進行POST(Power on self test)結束後,
將根據BIOS設定自相對應磁碟把第0磁碟第0
磁軌第1磁區(512 bytes)載入0x07C00,然後執
行。
• 第0磁碟第0磁軌第1磁區也被稱為MBR(Master
Boot Record)
91
檔案系統設計者之間的約定
• MBR會包含硬碟上可以拿來開機的磁碟分割。
MBR的任務便是將搜尋到的磁碟分割的第一
磁區載入並執行,此磁區稱為開機磁區,此磁
碟分割稱為系統磁碟區。
• OS會在安裝時將可開機的磁碟分割注入MBR
之中。
92
Windows 對於開機磁區的修改
• Windows會覆寫開機磁區使其自動載入
Windows的OS Loader-ntldr,並將其載入至
0x20000。
• ntldr可分為2部分,
– 一部份為real mode的Binary程式
– 另一部份為標準的PE格式執行檔-osloader.exe
93
ntldr
94
ntldr - Real Mode
• Real mode的程式率先執行,此時,CPU處於
真實模式,記憶體存取有著0xFFFFF(1MB)的
上限,而且Page機制未啟動。
• 因此,real mode的目標為開啟Paging機制,並
對應好前16MB的Paging Table,最後切換至
Protected Mode並執行osloader.exe。
95
osloader.exe
• osloader.exe的任務是載入所有OS開機過程中
所需的檔案。
• 主要流程
1. 讀取boot.ini並搜尋Hiberfil.sys。若存在,進行
休眠回復。
2. 若非休眠回復,載入NTDETECT.COM以供利
用BIOS查詢系統裝置資訊。
3. 載入ntosktnl.exe,boot.ini中指定的HAL檔。
96
osloader.exe(cont.)
• 主要流程(續)
4. 載入\Windows\System32\Config\System為
System註冊機碼。
5. 查詢System註冊機碼以載入適當驅動程式。
6. 將過程中所有資料蒐集於
LOADER_PARAMETER_BLOCK結構中,並
執行ntoskrnl.exe的入口程式 (Entry Point)。
97
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;
98
開機流程總結
BIOS
MBR
開機磁區
ntldr
• 真實模式
• osloader.exe
ntoskrnl.exe: Entry Point
99
2.6 Windows啟動過程
2.6.1 核心載入
2.6.2 核心初始化 (報告者: 許齊顯)
2.6.3 建立使用者登入工作階段
100
入口程式(Entry Point)
• ntoskrnl.exe執行其入口程式
– 設定於\base\ntos\build\makefile
– 預設為KiSystemStartup
!if "$(targ)" == “i386”
。。。 。。。
entrypoint
= KiSystemStartup@4
!else
。。。 。。。
entrypoint
= KiSystemStartup
!endif
101
核心初始化階段
• 核心初始分成2個階段:Phase 0與Phase 1
– 許多系統元件於此2階段進行不同的初始化。
– KiSystemStartup()執行時,中斷(Interrupt)
為禁止狀態。
– KiSystemStartup()將在Phase 0不受任何中
斷影響地初始化Phase 1所需的資料,並為了開
啟中斷做準備。
– Phase1Initialization()則接手初始好的
基本資料,並進行Phase 1的初始化。
102
KiSystemStartup
[\base\ntos\ke\i386\newsysbg.asm]
• 參數為OS loader傳入的
LOADER_PARAMETER_BLOCK
• 初始化IDT(Interrupt Descriptor Table)、TSS(Task
State Segment)、PCR(Processor Control Region)
• 主要流程
1. 呼叫HalInitializeProcessor()初始化PCR
及中斷向量
2. 呼叫KiInitializeKernel()初始化核心相關
的資料結構
3. 啟用中斷並降低Priority以讓Phase 1啟動
4. 執行KiIdleLoop()使目前執行緒成為Idle
Thread
103
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
104
KiInitializeKernel
[\base\ntos\ke\i386\kernlini.c]
• 根據目前是否為開機核心(Processor 0)針對
PRCB(Processor Control Block)進行更詳細的設
定。
• 主要流程
1. 呼叫KeInitializeThread()初始化目前
執行緒的Thread Object,並初始化排程
(Schedule)時所需的資料結構。
2. 設定目前執行緒專屬於當前Processor。
3. 呼叫ExpInitializeExecutive()初始化
執行體。
105
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);
106
。。。 。。。
ExpInitializeExecutive
[\base\ntos\init\initos.c]
• 主要執行執行體中各類元件的Phase 0初始化。
• 除HAL外元件都只在開機核心才進行初始化。
• 主要流程
1. 初始化元件包含HAL、執行體、記憶體管理
員、記憶體集區、物件管理員、安全子系統、
行程資料、執行緒管理員、隨插即用管理員。
107
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{
if (HalInitSystem(InitializationPhase, LoaderBlock) == FALSE) {}
}
108
PspInitPhase0
[\base\ntos\ps\psinit.c]
• 由PsInitSystem於Phase 0呼叫
• 負責初始所有行程及執行緒皆須使用的資料結
構。
• 並負責將初始目前行程為“Idle”`,並產生
“System”行程,並加入進行Phase 1的執行緒
109
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))) {}
。。。 。。。
}
110
Phase1Initialization
[\base\ntos\init\initos.c]
• 執行Phase1InitilizationDiscard()
• 而後結束內部初始流程,轉化執行緒為回收記
憶體用的MmZeroPageThread()
111
Phase1InitializationDiscard
[\base\ntos\init\initos.c]
• 設定初始階段為Phase 1。
• 呼叫KeStartAllProcessors()
• 對各項元件進行Phase 1的初始化,以正式啟用各
項元件。
– 包含物件管理員、記憶體管理員、組態管理員等
• 把啟動時獲得的資料轉換成登錄碼中的
“HKLM\SYSTEM”及 “HKLM\HARDWARE”
• 初始化SRM,並開啟LPC Port接受lsass.exe的請求。
• 建立smss.exe行程,等待其執行並接手剩餘工作,
於是Phase 1正式結束。
112
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);
。。。 。。。
}
113
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。
114
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;
}
115
KiInitProcessorState
[\base\ntos\ke\i386\allproc.c]
• 設定Processor啟動時應有的啟動設定。
• 藉由修改屬於該Processor的PCR,設定eip為
KiSystemStartup
116
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
);
117
MmZeroPageThread
[\base\ntos\mm\zeropage.c]
• 回收屬於 “INIT” section的Memory。
• 負責將OS回收的Memory Page的內容重設為 0。
• 如:
#pragma alloc_text(INIT, ExpInitializeExecutive)
118
MmZeroPageThread重點程式
VOID MmZeroPageThread (VOID){
。。。 。。。
MiFindInitializationCode (&StartVa, &EndVa);
if (StartVa != NULL) {
MiFreeInitializationCode (StartVa, EndVa);
}
。。。 。。。
}
119
核心初始化總結
ntldr
Processor 0
KiSystemStartup
HalInitializeProcessor
Idle Process
KiSystemStartup
KiInitializeKernel
KeInitializeThread
ExpInitializeExecutive
HalInitSystem
PsInitSystem
KiIdleLoop
Other Processor
Idle Process
PspInitPhase0
Phase1Initilization
System Process
Phase1InitializationDiscard
KeStartAllProcessors
HalInitializeProcessor
KiInitializeKernel
KeInitializeThread
ExpInitializeExecutive
HalInitSystem
KiIdleLoop
KiInitProcessor
KiInitProcessorState
HalStartNextProcessor
MmZeroPageThread
120
2.6 Windows啟動過程
2.6.1 核心載入
2.6.2 核心初始化
2.6.3 建立使用者登入工作階段
(報告者 : 左昌國)
121
建立使用者登入工作階段
• 前面所提到的Phase1主函式
Phase1InitializationDiscard 在最後
會建立工作階段管理員子系統行程(Session
Manager Subsystem) smss.exe,這一節主要就
是在講解smss.exe在Windows系統啟動的過程
中,所扮演的角色。
• WRK裡沒有包含smss.exe的原始碼,必須要用
run-time debugging來trace code
122
建立使用者登入工作階段
base/ntos/init/initos.c :
\SystemRoot\System32\smss.exe
01776
SessionManager = ProcessParameters->ImagePathName;
01777
Status = RtlCreateUserProcess(
01778
&SessionManager,
01779
OBJ_CASE_INSENSITIVE,
01780
RtlDeNormalizeProcessParams( ProcessParameters ),
01781
NULL,
01782
NULL,
在這邊就已經建好smss.exe
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
);
這邊會等5秒鐘
123
建立使用者登入工作階段
• smss.exe
– Windows系統啟動時第一個執行的user-mode
process
– 屬於native application
•
•
•
•
建立時,沒有Windows Subsystem
smss的其中一個任務就是建立其他的Subsystem
使用native APIs,無法使用Win32 APIs
視為trusted OS component,可以做一些需要高權限
的工作
124
建立使用者登入工作階段
• smss的工作
– 載入除了SYSTEM,以及使用者設定檔以外的
registry到記憶體裡
– 執行在registry裡面所設定的”開機時執行程式”
– 執行開機時的檔案刪除或是檔案重新命名
– 執行已知的DLL(例如一些子系統DLL)
– 建立分頁檔
– 載入win32k.sys (子系統的核心模組)
– 執行子系統csrss.exe
– 執行登入行程winlogon.exe
125
建立使用者登入工作階段
• 載入registry
– smss呼叫系統服務
NtInitializeRegistry(原始碼位於
base/ntos/config/ntapi.c#1030)來初始化registry以
及載入某些registry
– NtInitializeRegistry呼叫
CmpInitializeHiveList來載入登錄區域
(page39)
126
建立使用者登入工作階段
127
建立使用者登入工作階段
128
建立使用者登入工作階段
129
建立使用者登入工作階段
• 系統啟動時要執行的程式
– smss的主要函式
SmpLoadDataFromRegistry會讀取在
registry裡
HKLM\SYSTEM\CurrentControlSet\Control\Sessi
on Manager\BootExecute所記錄的值,並且視為
開機階段要執行的程式,並透過
SmpExecuteCommand去執行
– 基本上會有autochk.exe
130
建立使用者登入工作階段
131
建立使用者登入工作階段
• 開機時刪除檔案或更改檔案名稱
– 呼叫SmpProcessFileRenames,根據存在
HKLM\SYSTEM\CurrentControlSet\Control\Sessi
on Manager\FileRenameOperations的機碼,視為
檔案名稱來做這項動作
132
建立使用者登入工作階段
• 執行已知的DLL
– 呼叫SmpInitializeKnownDlls,根據
HKLM\SYSTEM\CurrentControlSet\Control\Sessi
on Manager\KnownDLLs裡面紀錄的機碼來找到
需要被載入的DLL file
133
建立使用者登入工作階段
HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs
134
建立使用者登入工作階段
• 建立分頁檔(Paging Files)
– 呼叫SmpCreatePagingFiles,分頁檔列表在
HKLM\SYSTEM\CurrentControlSet\Control\Sessi
on Manager\Memory Management\PagingFiles
HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management
135
建立使用者登入工作階段
• 載入win32k.sys
– 透過系統服務NtSetSystemInformation來達成在kernel中
載入win32k.sys
base/ntos/ex/sysinfo.c
“\SystemRoot\System32\win32k.sys”
03452 Image = *(PUNICODE_STRING)SystemInformation;
03453 Status = MmLoadSystemImage(&Image,
03454
NULL,
03455
NULL,
03456
MM_LOAD_IMAGE_IN_SESSION,
03457
&SectionPointer,
03458
(PVOID *)&ImageBaseAddress);
136
建立使用者登入工作階段
137
建立使用者登入工作階段
• 執行子系統csrss.exe
– 呼叫SmpLoadSubSystem來載入csrss,csrss.exe
的路徑紀錄在
HKLM\SYSTEM\CurrentControlSet\Control\Sessi
on Manager\SubSystems裡的Windows機碼
HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\SubSystems
138
建立使用者登入工作階段
139
建立使用者登入工作階段
• 執行登入行程winlogon.exe
• smss做完上述的初始化工作之後,就會執行
winlogon.exe,並且等待(WaitForSingleObject)csrss和
winlogon的結束,一旦smss發現其中有一個結束,就代
表Windows出現問題,就會跳到CheckBug程序並且當
機
• winlogon.exe也會做很多事情
–
–
–
–
–
建立初始視窗工作站Winsta0
建立登入桌面
啟動服務控制管理員(SCM, Service Control Manager)
啟動子系統lsass
啟動userinit
140
建立使用者登入工作階段
• 建立Winsta0
– 建立桌面Thread以及RIT(Raw Input Thread)
• 建立登入桌面(winlogon desktop)
– 只有winlogon.exe可以存取登入桌面,因此與密碼
相關的操作以及鎖定/解除桌面的操作,只能透過
winlogon.exe,用來當作保護措施
• 啟動服務控制管理員(SCM, Service Control
Manager)
– SCM即為services.exe
– SCM用來控制所有的服務與裝置驅動程式
– SCM在載入時會啟動auto-start類型的服務以及驅動
程式
141
建立使用者登入工作階段
• 啟動子系統lsass
– 本機安全性授權子系統(Local Security Authority
subsystem)
– Lsass啟動後,winlogon和lsass之間會建立一個
LPC(LsaAuthenticationPort),在使用者登入和
登出的時候用來在兩個程序當中通訊
142
建立使用者登入工作階段
• 啟動userinit
– Winlogon會透過
HKLM\SOFTWARE\Microsoft\WindowsNT\Curr
ent Version\Winlogon\Userinit來取得userinit.exe
的路徑
– 執行userinit.exe之後,會載入使用者設定檔
– 並且執行shell(explorer.exe),預設的shell路徑在
HKLM\SOFTWARE\Microsoft\WindowsNT\Curr
ent Version\Winlogon\Shell
– 登入完成後,userinit.exe會自動結束
143
建立使用者登入工作階段
HKLM\SOFTWARE\Microsoft\WindowsNT\Current Version\Winlogon
144
建立使用者登入工作階段
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
結束
145
END
Q &A
146