應用軟件在用戶空間可以訪問的最低地址是MM_LOWEST_USER_ADDRESS,定義爲0x10000,就是一個64KB邊界的地方,從0開始的64KB不能訪問
KI_USER_SHARED_DATA這個常數定義爲0xFFDF0000,是一個區間的起點。這個區間是在系統空間,卻又劃出來讓用戶空間的程序訪問,目的是用來讓用戶空間的程序訪問內核中的一些數據。而且,這個區間是由系統空間和所有用戶空間共享即爲所有進程所共享的。
nt!_KUSER_SHARED_DATA +0x000 TickCountLow : Uint4B +0x004 TickCountMultiplier : Uint4B +0x008 InterruptTime : _KSYSTEM_TIME +0x014 SystemTime : _KSYSTEM_TIME +0x020 TimeZoneBias : _KSYSTEM_TIME +0x02c ImageNumberLow : Uint2B +0x02e ImageNumberHigh : Uint2B +0x030 NtSystemRoot : [260] Uint2B +0x238 MaxStackTraceDepth : Uint4B +0x23c CryptoExponent : Uint4B +0x240 TimeZoneId : Uint4B +0x244 Reserved2 : [8] Uint4B +0x264 NtProductType : _NT_PRODUCT_TYPE +0x268 ProductTypeIsValid : UChar +0x26c NtMajorVersion : Uint4B +0x270 NtMinorVersion : Uint4B +0x274 ProcessorFeatures : [64] UChar +0x2b4 Reserved1 : Uint4B +0x2b8 Reserved3 : Uint4B +0x2bc TimeSlip : Uint4B +0x2c0 AlternativeArchitecture : _ALTERNATIVE_ARCHITECTURE_TYPE +0x2c8 SystemExpirationDate : _LARGE_INTEGER +0x2d0 SuiteMask : Uint4B +0x2d4 KdDebuggerEnabled : UChar +0x2d5 NXSupportPolicy : UChar +0x2d8 ActiveConsoleId : Uint4B +0x2dc DismountCount : Uint4B +0x2e0 ComPlusPackage : Uint4B +0x2e4 LastSystemRITEventTickCount : Uint4B +0x2e8 NumberOfPhysicalPages : Uint4B +0x2ec SafeBootMode : UChar +0x2f0 TraceLogging : Uint4B +0x2f8 TestRetInstruction : Uint8B +0x300 SystemCall : Uint4B +0x304 SystemCallReturn : Uint4B +0x308 SystemCallPad : [3] Uint8B +0x320 TickCount : _KSYSTEM_TIME +0x320 TickCountQuad : Uint8B +0x330 Cookie : Uint4B
地址0xFFDF0000就是KUSER_SHARED_DATA數據結構的起點,而用戶空間的程序則可以通過指針SharedUserData讀取這個結構中各個成分的內容。
進程用戶空間的創建:
1.進程控制塊EPROCESS結構中有個成分VadRoot,就是代表用戶空間的MADRESS_SPACE數據結構。所以在創建進程時要通過MmInitializeAddressSpace()對新建進程的地址空間VadRoot進行初始化,特別是將此數據結構中的成分LowestAddress設置成MM_LOWEST_USER_ADDRESS
2.建立用戶共享區,把從USER_SHARED_DATA即0xFFDF0000開始的一個頁面分配給用戶空間,讓用戶空間的程序可以對該頁面作“可執行和只讀”訪問。實際大小是一個頁面4KB。
3.目標EXE映像的映射,在調用NtCreateProcess之前,調用者已經爲目標映像創建了一個Section即“文件映射區”,通過MmMapViewOfSection把這個映射區映射到新建進程的用戶空間。
4.把許多動態鏈接庫也裝入或映射到用戶空間。ntdll.dll是最基本的DLL,Windows內核在初始化階段首次需要裝入這個DLL的時候爲其創建一個文件映射區,並使一個全局指針PspSystemDllSection指向該對象的數據結構,以後凡需要裝入這個DLL的進程就只有映射這個文件映射區就可以了。
5.進程環境塊PEB的建立,有PspCreateProcess調用MmCreatePeb完成的。MiCreatePeborTeb在分配地址空間時是由上而下的,所以是從0x7FFE0000開始往下搜索,以找到第一塊滿足大小要求的區間。由於此時的用戶空間尚是空白,所要求的地址肯定能夠滿足,而PEB和TEB的大小都是一個頁面,即0x1000(4KB),所以PEB分得的地址肯定是0x7FFDF000。
6.通過MmMapViewOfSection將NLS的碼錶映射到用戶空間。
7.初始化PEB,PEB佔用一個頁面,但是實際使用的大小卻沒有那麼大,所以把剩下的部分用做一個存儲堆(Heap)指針數組。剩餘的部分能容納多少個指針,這個進程最多就可以有多少個堆。
8.把進程參數寫入新進程的參數塊。
9.創建新進程的第一個線程及TEB。