Windows NT保護子系統

Windows NT保護子系統


▓初識
諸位Windows NT的玩家,應該對保護子系統這個名詞不漠生,剛開始接觸Windows NT時,對於它的架構也是充滿了好奇,曾在Windows NTTrace Windows CE的模擬器,覺得這些能將不同環境下開發的程式整合在一起的技術滿有趣,透過這次的文章,我將對Windows NT的保護子系統做一個介紹,在Windows NT中保護子系統扮演了重要的角色,從登入系統到啟動各個應用程式,保護子系統都在幕後掌控大局,
在此我先簡述一下Windows NT的開機流程,安裝Windows NT後,Boot磁區會被改寫,Partition的磁區並不會被動到。不過,Windows 9X會動到Partition的磁區,使用Linux Lilo的玩家,應該在重灌Windows 9X後,會遇到原來裝在硬碟Lilo所更改的Partition磁區被動過了。如下圖(),是我硬碟Boot磁區的部份資料,在開機時,會由Boot磁區啟動NTLDR,我們可以看到,其中包括了如果Boot磁區未能順利找到NTLDR這個檔案時,所發出的警告訊息。
Windows NT中,NTLDR除了負有提供多重開機的能力外,還肩負了把許多Windows NT系統檔案載入的重要使命。在NTLDR載入以後,同時也將系統由真實模式切入保護模式。如下圖(),是我在NTLDR執行檔中所找到的一些滿有趣的訊息,像我們一開機時所看到的  NTDETECT V4.0 正在檢查硬體” 便是由NTLDR所秀出的。除此之外NTLDR也負責把NTDETECT.COM所偵測的資料傳給NTOSKRNL.EXE(此檔可說是NT真正的核心),並把NTOSKRNL.EXE 載入記憶體執行。在圖(),是NTLDR執行檔中所包含的開機選單的訊息,看到這訊息被包在NTLDR執行檔中,就知道它是開機選單及流程最初的控制者了。
當然,NTLDR本身也提供了基本的檔案系統,可以在啟動NT的過程中,讀取FAT16  NTFS 格式的檔案系統,。在圖(),便是Windows NT啟動的一個簡圖。


()
NTDETECT V4.0 Checking Hardware …
NTDETECT V4.0 正在檢查硬體 …
……..
…………
參數 ‘osloadpartition’ 設定不正確
請檢查 ‘systempartition’ 路徑.
參數 ‘osloadfilename’ 並未指向正確的檔案.
<winnt root>\system32\ntoskrnl.exe.
<winnt root>\system32\hal.dll.
‘osloader’\hal.dll
load needed DLLs for HAL.
find system drivers.
read system drivers.
did not load system boot device driver
load system hardware configuration file.
\SYSTEM32\CONFIG\SYSTEM
()

 
請選擇您想要啟動的作業系統:
使用 ↑ 鍵和 ↓ 鍵,將您想要的選項反白,
選定後,請按 Enter 鍵確認.

()

 







()

▓子系統?
提到保護子系統,首先,我要先介紹一下在Win32PE檔案格式中所提供的一個欄位 “SUBSYSTEM”,如圖(),是在VC的線上文件所記載有關SUBSYSTEM的資訊,


/SUBSYSTEM:{CONSOLE|WINDOWS|NATIVE|WINDOWSCE|POSIX|}[,left[,right]]
You can specify any of the following subsystems:
The CONSOLE subsystem handles a Win32 character-mode application that use a console supplied by the operating system.
The WINDOWS subsystem handles an application that does not require a console and creates its own windows, if required.
The NATIVE subsystem handles a Windows NT device driver.
The WINDOWSCE subsystem handles Windows CE consumer electronics applications.
The POSIX subsystem handles a POSIX application in Windows NT.
()
既然提到了SUBSYSTEM,我就舉幾個我們常見到的例子,如下圖(),就是我在Windows NT中利用快速檢視(如果你有裝快速檢視的話,選擇檔案後,按下右鍵,就會在POPUP MENU中看到它了來查看\WINNT\SYSTEM32\*.SYS的檔案,在NTDevice Driver檔案的副檔名為SYS,我們可以在Subsystem的欄位中看到”Image doesn’t require a subsystem”,同理。在圖(),則是一個Win32 使用到GUI界面的應用程式在快速檢視下的結果。圖()Win32 Console Mode的應用程式。



()


()


()
說到這兒,我想到在Inside NT Second Edition 中有一個Creating Process的流程圖,我也畫了一個簡圖如圖()。在第一部份,開啟EXE檔後,.會判斷這個檔案所屬的子系統,並開啟所選擇的物件。第二部份,產生Windows NT Executive Process Object,並產生所需的資料結構,及配置記憶體空間。第三部份,產生新的執行序及程式堆疊。第四部份,把新產生的行程通知所屬的子系統。第五部份,開始執行新產生的執行序。第六部份,執行新產生的行程。
其實,在這我只把部份的內容做一個說明,在Inside Windows NT Second Edition中對一個行程的啟始有滿不錯的說明。在此我就不再累述,這兩期的文章,這本書給了我不少Hint(如本篇文章的圖()()(十一)),也讓我可以省去不少尋找一些細節資料的時間,如果讀者對這方面有興趣的話,我相信那決對是一本不錯的好書。



()
如下圖(),是NT中各子系統所使用的虛擬機器的執行檔名,我們可以發現像
(1)CMD.EXE:主要用於*.BAT,及我們一般常用的DOS Command(:DIR..etc)。所以,如果我們把CMD.EXE改名的話,再透過檔案總管去執行AUTOEXEC.BAT便會得到如下的結果。讀者可能會懷疑,為何要透過檔案總管,而不啟動DOS BOX?那是因為在NT中的DOS BOX就是透過CMD.EXE來模擬的,因為我們把CMD.EXE改名了,所以原來的DOS BOX捷徑所指的檔案已不存在。其實,我覺得CMD.EXE的角色如同是以前DOS下的COMMAND.COM,扮演了COMMAND INTERPRETER 的角色。

(2)NTVDM.EXE:當我們在DOS BOX中啟動一個DOS的程式時,系統會透過NTVDM.EXE這個DOS的虛擬機器,來把這個DOS的程式放入記憶體中執行,如果我們把NTVDM.EXE改名後。再啟動DOS的應用程式便會產生如下的錯誤



由於DOS的應用程式與Win16的應用程式是使用同一個虛擬機器,
以在NTVDM.EXE改名的情況下,執行Win16的應用程式會得到如下的錯誤結果
(3)Win 32的應用程式,是Windows NT系統在一啟動後首先提供的子系統,其它的保護子系統都是需要透過Win32子系統的協助才有可能完成所需的工作,筆者在此就不個別介紹POSIXOS/2子系統了,在本文的稍後我會有一個相關的說明。


()
如圖(十一),裡面有一些關於子系統的重要檔案名稱,我們可以發現子系統常常都是一個EXE 檔與一個DLL檔,我並沒實地製作一個子系統的經驗,不過稍後,我會針對目前已存在的子系統做一個探索。
Services.exe Service Controller Process
Winlogon.exe Logon Process
Smss.exe Session Manager Process
Psxss.exe POSIX Subsystem Process
OS2ss.exe OS/2 Subsystem Process
Csrss.exe Win32 Subsystem Process
Ntdll.dll Internal Support Functions and System Service
Dispatch stubs to Executive Functions
Kernel32.dll Win32 Subsystem DLLs
User32.dll
GDI32.dll
Psxdll.dll POSIX Subsystem DLL
NTOSKRNL.EXE Executive and Kernel
Hal.dll Hardware Abstraction Layer
Win32k.sys Win32 User and GDI Kernel-mode Components
(十一)
Win32子系統
Windows NT的登錄畫面出現以前,Win32子系統便被建立了,在Win32子系統初始化時,系統中只存在4個Process分別為

Process
PID
Pri
System
0x02
8
Smss
0x19
B
Csrss
0x21
D
Idle
0x00
0
既然,Win32Windows NT所啟動的第一個子系統,那Win32子系統CSRSS.EXE執行檔,是如何完成的呢相信讀者應該還記得,Device Driver 是屬於Kernel Mode的程式,因此,在DriverSubsystem欄位會顯示這個執行檔不需要子系統,那CSRSS.EXE?
如下圖(十二),我們可以發現CSRSS.EXE不同於一般的Win32程式,它並不需要一個子系統來維持它。有趣的是,在Import Table中我們看到CSRSRV.DLL這個Win32子系統的動態連結函式庫,同樣的,在它們Load到記憶體前,系統還沒有任何一個子系統形成,因此這個CSRSRV.DLLSubsystem欄位也是顯示不需要子系統。
在圖(十三)中,我們可以在CSRSS.EXEImport Table中看到CSRSRV.DLL所提供的CsrServerInitialization函式,這是CSRSS.EXE在初始化Win32環境的過程中所會呼叫的一個必備函式。
讀者可以觀察其它Win32的應用程式,會發現它們相關於子系統的一些有趣的事情。尤其,子系統往往都是一個EXE檔伴隨著DLL檔所建立起的一個架構,透過子系統的DLL檔,可以把許多環境所必需的基本函式給實作在子系統的DLL中。
(十四) –(十六)分別是CSRSRV.DLLSubsystem資料,Import TableExport Table,眼尖的讀找應該可以從圖(十六)Export Table中看到這個CSRSRV.DLL提供了許多與Win32行程管理及引線呼叫的函式。在圖(十六)中,我們也看到如Kernel32.dll一般,CSRSRV.DLL也是會去使用到許多NTDLL.DLL所提供的系統函式(讀者應該還記得上期文章所提到NTDLL.DLL2E中斷吧!。。。。^_^),所以囉!其實許多的子系統功能都是這樣一點一滴的用許多系統比較低階的函式來逐一構成的。尤其,Win32子系統是NT中最重要的一個子系統了。從系統一初始,到系統關機都會存在使用者的電腦中。


(十二)


(十三)

(十四)

(十五)


(十六)
Win16子系統

說到Win16,是這篇文章中我最喜歡的部份了,因為我覺得它非常的有趣,過去Windows3.1時代Win16的應用程式是共用一個虛擬的記憶體空間,同樣的情況在Windows NT中也是如此,如果我們在NT中啟動一個以上的Win16應用程式,我們會發現它們都會在同一個NTVDM.EXE之中(NT Virtual DOS Machine),也就是說目前系統中的Win16應用程式是活在一個DOS虛擬機器中,不過NT也不是這樣的不通人情的喔!由於Win16應用程式預設是共用一塊記憶體空間,且只分到一個CPU時間,所以如果要讓Win16應用程式得到較公平的對待的話,可以考慮在啟動Win16應用程式時,如下圖,



在個別的記憶體空間執行的選項勾起來。
(十七)
如下圖,是在NT中執行一個以上的Win16應用程式

(十八)
其實,讀者一定跟我一樣好奇,那一個Win16的應用程式除了使用NTVDM.EXE外,是如何模擬Win16的使用環境呢請看圖(十九),就是一個Win16應用程式在執行時所會一併執行的檔案。此時,CPUProtect Mode切到V86 Mode,還有,別忘了KRNL386.EXE可是個16bit DPMI Client!
如下圖,是我在Windows NT中啟動Win16應用程式時,攔截系統的動作,所得到的一些資料。我們不難看出A3W.EXE 這個Win16的應用程式在執行前,系統會把許多Win16環境的模組載入到系統中。當模擬的Win16環境完成後,才把A3W.EXE給真正載入到系統中,讀者可以看到包括KEYBOARD.DRV  MOUSE.DRVWin16系統基本的驅動程式,不過這一切對使用者來說是不自覺的,複雜的過程都被包在NT之中。
KERNEL C:\WINNT\SYSTEM32\KRNL386.EXE
SYSTEM C:\WINNT\SYSTEM32\SYSTEM.DRV
KEYBOARD C:\WINNT\SYSTEM32\KEYBOARD.DRV
MOUSE C:\WINNT\SYSTEM32\MOUSE.DRV
WIFEMAN C:\WINNT\SYSTEM32\WIFEMAN.DLL
DISPLAY C:\WINNT\SYSTEM32\VGA.DRV
SOUND C:\WINNT\SYSTEM32\SOUND.DRV
COMM C:\WINNT\SYSTEM32\COMM.DRV
USER C:\WINNT\SYSTEM32\USER.EXE
GDI C:\WINNT\SYSTEM32\GDI.EXE
WOWEXEC C:\WINNT\SYSTEM32\WOWEXEC.EXE
WINNNLS C:\WINNT\SYSTEM32\WINNLS.DLL
WFWNET C:\WINNT\SYSTEM32\WFWNET.DRV
MMSYSTEM C:\WINNT\SYSTEM32\MMSYSTEM.DLL
TIMER C:\WINNT\SYSTEM32\TIMER.DRV
SHELL C:\WINNT\SYSTEM32\SHELL.DLL
A3W D:\A3W\A3W.EXE
ICDLLWIN D:\AW3\ICDLLWIN.DLL
CTL3DV2 C:\WINNT\SYSTEM32\CTL3DV2.DLL
WIN87EM C:\WINNT\SYSTEM32\WIN87EM.DLL
COMMDLG C:\WINNT\SYSTEM32\COMMDLG.DLL
(十九)
在圖(十九)中所列的Win16程式啟動的檔案中,我們可以觀查這些程式的檔頭,如下圖為System.drv的檔頭部份

我們可以看到Windows NT中的System.drv仍是使用了Win16NE檔案格式,裡面的Code也是16 bit的程式碼。
如果再看Win16 A3W.EXE應用程式啟動後,從Windows NTSystem32目錄,所載入MemoryCOMMDLG.DLL,如下圖
都是16 BitCode,雖然它名為System32(因為還有一個同存在Windows NTSystem目錄),不過它所提供的檔案,可並不都是32Bit
筆者在Trace NTVDM.EXE時,發現一些滿有趣的字串。如下圖,看起來有點像是Source Code的目錄位置,不過這可是我隨便猜的喔!如果有讀者知道這些字串的意思的話,可以寫封信跟我說一下,說真的,我也想知道這些字串所代表的意思呢!我並不是微軟的工程師,所以囉,這就留給各位讀者來猜想這些字串的涵意好了。

 
D:\CHT\nt\private\mvdm\softpc.new\host\src\nt_hosts.c
D:\CHT\nt\private\mvdm\softpc.new\host\src\nt_sec.c
D:\CHT\nt\private\mvdm\softpc.new\host\src\x86_emm.c
D:\CHT\nt\private\mvdm\softpc.new\host\src\nt_timer.c
D:\CHT\nt\private\mvdm\softpc.new\host\src\nt_eoi.c

D:\CHT\nt\private\mvdm\softpc.new\host\src\nt_com.c

D:\CHT\nt\private\mvdm\softpc.new\host\src\nt_event.c

D:\CHT\nt\private\mvdm\softpc.new\host\src\nt_det.c


(二十)
▓其它子系統
附帶一提,保護子系統一旦被使用者啟動後,就不會再從記憶體中被釋放掉,除非使用者重新開機。
在此我將為各位介紹一下Windows NT中最屬於Unix類的保護子系統POSIX,不過Windows NT並未能支援非常完整的POSIX環境,我們可以在圖(二十一),中看到保護子系統PSXSS.EXEPSXDLL.DLL的檔頭。比較特殊的一點是PSXSS.EXE是屬於Win32的應用程式,而PSXDLL.DLL則是必須在Posix子系統下執行的程式。透過圖(二十二),相信對Unix熟悉的讀者應該面露微笑了,因為我們可以在PSXDLL.DLLExport Table中看到它所提供的許多系統函式,包括了 mkdirpiperead………等等,在Unix環境中所會使用到的函式。
不過在NT中的POSIX子系統只支援符合POSIX 1003.1規格的ConsoleMode應用程式。
我並沒有在文章中提到Windows NTOS/2子系統,主要也是因為筆者對OS/2系統所知比較有限。過去會使用OS/2也是抱著玩玩的心態,所以一直未能有機會把它給搞的很熟。希望諸位OS/2的玩家們不要見怪。
D:\CHT\nt\private\mvdm\softpc.new\host\src\nt_hosts.c
D:\CHT\nt\private\mvdm\softpc.new\host\src\nt_sec.c
D:\CHT\nt\private\mvdm\softpc.new\host\src\x86_emm.c
D:\CHT\nt\private\mvdm\softpc.new\host\src\nt_timer.c
D:\CHT\nt\private\mvdm\softpc.new\host\src\nt_eoi.c

D:\CHT\nt\private\mvdm\softpc.new\host\src\nt_com.c

D:\CHT\nt\private\mvdm\softpc.new\host\src\nt_event.c

D:\CHT\nt\private\mvdm\softpc.new\host\src\nt_det.c


(二十一)

(二十二)
▓結語
現在當紅的Java VM所架構的程式環境,與NT的保護子系統比較起來,算是比較低階一點了。NTWin32以外的子系統是透過Win32APINT呼叫來模擬出來的,讀者可以從PSXDLL.DLL中使用到大量的Win32 API來得知一二,如此則不若Java VM從應用程式所用的ByteCode來的低階許多。當然囉,我自己並不是一個Java的行家,如果讀者有不同的看法的話,可以來信與我討論一下,謝謝各位了。