自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

淺析Windows的訪(fǎng)問(wèn)權(quán)限檢查機(jī)制

安全 網(wǎng)站安全
在操作系統(tǒng)中,當(dāng)我們提到安全的時(shí)候,意味著有一些資源需要被保護(hù),在Windows操作系統(tǒng)中,這些被保護(hù)的資源大多以對(duì)象(Object)的形式存在,對(duì)象是對(duì)資源的一種抽象。每個(gè)對(duì)象都可以擁有自己的安全描述符(Security Descriptor),用來(lái)描述它能夠被誰(shuí)、以何種方式而訪(fǎng)問(wèn)。

0x00 簡(jiǎn)介

在操作系統(tǒng)中,當(dāng)我們提到安全的時(shí)候,意味著有一些資源需要被保護(hù),在Windows操作系統(tǒng)中,這些被保護(hù)的資源大多以對(duì)象(Object)的形式存在,對(duì)象是對(duì)資源的一種抽象。每個(gè)對(duì)象都可以擁有自己的安全描述符(Security Descriptor),用來(lái)描述它能夠被誰(shuí)、以何種方式而訪(fǎng)問(wèn)。這些對(duì)象是客體,那么訪(fǎng)問(wèn)這些對(duì)象的主體是什么呢?這些主體就是操作系統(tǒng)中的各個(gè)進(jìn)程,更準(zhǔn)確地說(shuō)是這些進(jìn)程中的每個(gè)線(xiàn)程。每個(gè)進(jìn)程都有一個(gè)基本令牌 (Primary Token),可以被進(jìn)程中的每個(gè)線(xiàn)程所共享,而有些線(xiàn)程比較特殊,它們正在模擬(Impersonating)某個(gè)客戶(hù)端的身份,因此擁有一個(gè)模擬令牌(Impersonation Token),對(duì)于這些線(xiàn)程來(lái)說(shuō),有效令牌就是模擬令牌,而其他線(xiàn)程的有效令牌則是其所屬進(jìn)程的基本令牌。當(dāng)主體嘗試去訪(fǎng)問(wèn)客體時(shí),操作系統(tǒng)會(huì)執(zhí)行訪(fǎng)問(wèn)權(quán)限檢查(Access Check),具體來(lái)說(shuō),是用主體的有效令牌與客體的安全描述符進(jìn)行比對(duì),從而確定該次訪(fǎng)問(wèn)是否合法。為了提高效率,訪(fǎng)問(wèn)權(quán)限檢查(Access Check)提供了一種緩存機(jī)制,即只有當(dāng)一個(gè)對(duì)象被一個(gè)進(jìn)程創(chuàng)建或者打開(kāi)時(shí),才會(huì)進(jìn)行訪(fǎng)問(wèn)權(quán)限檢查,訪(fǎng)問(wèn)權(quán)限檢查的結(jié)果會(huì)被緩存到進(jìn)程的句柄表(Handle Table)中,該進(jìn)程對(duì)該對(duì)象的后續(xù)操作只需要查詢(xún)句柄表中內(nèi)容即可確定訪(fǎng)問(wèn)的合法性,而不必每次都執(zhí)行開(kāi)銷(xiāo)更大的訪(fǎng)問(wèn)權(quán)限檢查(Access Check)。因?yàn)閷?duì)象和進(jìn)程都有各自的繼承層次,所以對(duì)象的安全描述符和進(jìn)程的令牌從邏輯上講也是可以繼承的,比如文件系統(tǒng)中的文件可以繼承其所在目錄的安全描述符,子進(jìn)程可以繼承父進(jìn)程的令牌,這種繼承機(jī)制使讓對(duì)象和進(jìn)程擁有了缺省的安全屬性,因此,在一個(gè)系統(tǒng)中的安全描述符和令牌的實(shí)例數(shù)目非常有限,大多數(shù)情況下是從父輩們繼承過(guò)來(lái)的缺省值。

 

模擬線(xiàn)程

 

0x01 訪(fǎng)問(wèn)權(quán)限檢查

訪(fǎng)問(wèn)權(quán)限檢查包含了多個(gè)維度上的檢查:

DACL檢查

DACL(自主訪(fǎng)問(wèn)控制表,Discretionary Access Control List)檢查是最基本的訪(fǎng)問(wèn)權(quán)限檢查。

 

安全描述符

 

在安全描述符中存在著一個(gè)DACL表(見(jiàn)安全描述符圖解),里面描述了擁有何種身份的主體申請(qǐng)的何種訪(fǎng)問(wèn)權(quán)限會(huì)被允許或者拒絕。DACL表中的每個(gè)表項(xiàng)擁有如下的結(jié)構(gòu):

We'll define the structure of the predefined ACE types.  Pictorally
the structure of the predefined ACE's is as follows:

     3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
     1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
    +---------------+-------+-------+---------------+---------------+
    |    AceFlags   | Resd  |Inherit|    AceSize    |     AceType   |
    +---------------+-------+-------+---------------+---------------+
    |                              Mask                             |
    +---------------------------------------------------------------+
    |                                                               |
    +                                                               +
    |                                                               |
    +                              Sid                              +
    |                                                               |
    +                                                               +
    |                                                               |
    +---------------------------------------------------------------+

Mask is the access mask associated with the ACE.  This is either the
access allowed, access denied, audit, or alarm mask.

Sid is the Sid associated with the ACE.

其中,對(duì)于DACL來(lái)說(shuō),AceType可以有

#define ACCESS_ALLOWED_ACE_TYPE (0x0)

#define ACCESS_DENIED_ACE_TYPE (0x1)

兩種可能;Mask是一個(gè)代表相關(guān)權(quán)限集合的位圖;主體的身份使用Sid(Security Identifier)來(lái)表示,這是一個(gè)變長(zhǎng)的數(shù)據(jù)結(jié)構(gòu):

kd> dt nt!_SID
   +0x000 Revision         : UChar
   +0x001 SubAuthorityCount : UChar
   +0x002 IdentifierAuthority : _SID_IDENTIFIER_AUTHORITY
   +0x008 SubAuthority     : [1] Uint4B

Sid是Windows安全系統(tǒng)中一個(gè)基本類(lèi)型,可以用來(lái)唯一標(biāo)識(shí)多種不同種類(lèi)的實(shí)體,比如標(biāo)識(shí)用戶(hù)身份與組身份,標(biāo)識(shí)完整性級(jí)別、可信賴(lài)級(jí)別,AppContainer中的Capability等等。

DACL檢查過(guò)程是這樣的,如果對(duì)象的安全描述符為空,代表著這個(gè)對(duì)象不受任何保護(hù),即可以被任何令牌代表的主體訪(fǎng)問(wèn);如果對(duì)象擁有一個(gè)非空的安全描述符,但是安全描述符中的Dacl成員為空,代表該對(duì)象沒(méi)有顯式地賦予任何主體任何訪(fǎng)問(wèn)權(quán)限,即不允許被訪(fǎng)問(wèn);如果Dacl成員非空,就按照表中的順序逐一與當(dāng)前主體的身份Sid進(jìn)行比對(duì),直到該主體所請(qǐng)求的權(quán)限被全部顯式允許,或者某一請(qǐng)求的權(quán)限被顯式地拒絕,檢查結(jié)束;如果直到Dacl表檢查結(jié)束,主體申請(qǐng)的權(quán)限仍未被全部顯式允許,那么仍然代表拒絕。

根據(jù)以上規(guī)則可知,DACL中各個(gè)表項(xiàng)的順序?qū)υL(fǎng)問(wèn)權(quán)限檢查的結(jié)果至關(guān)重要,比如說(shuō)有一條有關(guān)某主體的顯式拒絕的表項(xiàng)位于表的最后,如果位于其之前的表項(xiàng)已經(jīng)顯式允許了這一主體申請(qǐng)的權(quán)限,那么這條顯式拒絕的表項(xiàng)將起不到任何作用?;诖朔N原因,如果通過(guò)Windows右鍵安全選項(xiàng)菜單添加的DACL表項(xiàng),顯式拒絕的表項(xiàng)永遠(yuǎn)被置于顯式允許表項(xiàng)前面,以保證其有效性。直接通過(guò)API添加則不受此種限制。

特權(quán)(Privileges)以及超級(jí)特權(quán)(Super Privileges)檢查

所謂特權(quán),是指那些不與某一具體對(duì)象相關(guān)的、影響整個(gè)系統(tǒng)的訪(fǎng)問(wèn)權(quán)限。而超級(jí)特權(quán)是這樣的一些特權(quán),你一旦擁有其中的一項(xiàng)超級(jí)特權(quán),就擁有了取得所有其他特權(quán)和權(quán)限的潛質(zhì),比如SeDebugPrivilege,在一般情況下,一旦擁有該特權(quán),就可以任意讀寫(xiě)目標(biāo)進(jìn)程的內(nèi)存,而不僅僅局限于打開(kāi)該進(jìn)程獲得句柄時(shí)得到的那些權(quán)限及特權(quán)。

完整性級(jí)別(Integrity Level)和強(qiáng)制策略(Mandatory Policy)檢查

完整性級(jí)別(IL)機(jī)制是Windows Vista引入的重要的安全機(jī)制,建立在其基礎(chǔ)上的沙盒機(jī)制十分簡(jiǎn)單又異常強(qiáng)大。

受限令牌(Restricted Token)檢查

通過(guò)創(chuàng)建受限令牌,可以獲得一個(gè)普通令牌所有擁有的權(quán)限集合的一個(gè)子集,用來(lái)進(jìn)行一些低權(quán)限操作,降低安全風(fēng)險(xiǎn)。

AppContainer's Capabilities檢查

LowBox令牌以及AppContainer's Capabilities組身份是從Windows 8開(kāi)始引入的安全機(jī)制,它提供了另一種更加復(fù)雜的沙盒機(jī)制。Capabilities與Android系統(tǒng)中對(duì)于A(yíng)pp權(quán)限限制非常類(lèi)似。

可信級(jí)別(Trust Level)檢查

完整性級(jí)別檢查是一種粗粒度的、相對(duì)穩(wěn)定的訪(fǎng)問(wèn)權(quán)限控制手段;伴隨著Windows的不斷進(jìn)化,對(duì)于簽名機(jī)制的依賴(lài)越來(lái)越明顯,簽名代表了一種可信賴(lài)程度。筆者認(rèn)為,Windows正在逐漸建立一套完善的基于可信賴(lài)級(jí)別的權(quán)限檢查機(jī)制,受保護(hù)進(jìn)程(Protected Process)就是這是這套機(jī)制中一部分。

上面的內(nèi)容簡(jiǎn)單介紹了Windows的權(quán)限檢查模型,以及權(quán)限檢查的維度;下面將介紹一些實(shí)現(xiàn)細(xì)節(jié)。

0x02 令牌

TOKEN結(jié)構(gòu)體

Token結(jié)構(gòu)體是訪(fǎng)問(wèn)權(quán)限檢查中的代表主體身份的核心數(shù)據(jù)結(jié)構(gòu),下面展示的是Windows 10 x64平臺(tái)下的構(gòu)成。

kd> dt nt!_TOKEN
   +0x000 TokenSource      : _TOKEN_SOURCE
   +0x010 TokenId          : _LUID
   +0x018 AuthenticationId : _LUID
   +0x020 ParentTokenId    : _LUID
   +0x028 ExpirationTime   : _LARGE_INTEGER
   +0x030 TokenLock        : Ptr64 _ERESOURCE
   +0x038 ModifiedId       : _LUID
   +0x040 Privileges       : _SEP_TOKEN_PRIVILEGES
   +0x058 AuditPolicy      : _SEP_AUDIT_POLICY
   +0x078 SessionId        : Uint4B
   +0x07c UserAndGroupCount : Uint4B
   +0x080 RestrictedSidCount : Uint4B
   +0x084 VariableLength   : Uint4B
   +0x088 DynamicCharged   : Uint4B
   +0x08c DynamicAvailable : Uint4B
   +0x090 DefaultOwnerIndex : Uint4B
   +0x098 UserAndGroups    : Ptr64 _SID_AND_ATTRIBUTES
   +0x0a0 RestrictedSids   : Ptr64 _SID_AND_ATTRIBUTES
   +0x0a8 PrimaryGroup     : Ptr64 Void
   +0x0b0 DynamicPart      : Ptr64 Uint4B
   +0x0b8 DefaultDacl      : Ptr64 _ACL
   +0x0c0 TokenType        : _TOKEN_TYPE
   +0x0c4 ImpersonationLevel : _SECURITY_IMPERSONATION_LEVEL
   +0x0c8 TokenFlags       : Uint4B
   +0x0cc TokenInUse       : UChar
   +0x0d0 IntegrityLevelIndex : Uint4B
   +0x0d4 MandatoryPolicy  : Uint4B
   +0x0d8 LogonSession     : Ptr64 _SEP_LOGON_SESSION_REFERENCES
   +0x0e0 OriginatingLogonSession : _LUID
   +0x0e8 SidHash          : _SID_AND_ATTRIBUTES_HASH
   +0x1f8 RestrictedSidHash : _SID_AND_ATTRIBUTES_HASH
   +0x308 pSecurityAttributes : Ptr64 _AUTHZBASEP_SECURITY_ATTRIBUTES_INFORMATION
   +0x310 Package          : Ptr64 Void
   +0x318 Capabilities     : Ptr64 _SID_AND_ATTRIBUTES
   +0x320 CapabilityCount  : Uint4B
   +0x328 CapabilitiesHash : _SID_AND_ATTRIBUTES_HASH
   +0x438 LowboxNumberEntry : Ptr64 _SEP_LOWBOX_NUMBER_ENTRY
   +0x440 LowboxHandlesEntry : Ptr64 _SEP_LOWBOX_HANDLES_ENTRY
   +0x448 pClaimAttributes : Ptr64 _AUTHZBASEP_CLAIM_ATTRIBUTES_COLLECTION
   +0x450 TrustLevelSid    : Ptr64 Void
   +0x458 TrustLinkedToken : Ptr64 _TOKEN
   +0x460 IntegrityLevelSidValue : Ptr64 Void
   +0x468 TokenSidValues   : Ptr64 _SEP_SID_VALUES_BLOCK
   +0x470 IndexEntry       : Ptr64 _SEP_LUID_TO_INDEX_MAP_ENTRY
   +0x478 VariablePart     : Uint8B

我們比較關(guān)注其中的特權(quán)位圖和三個(gè)代表主體身份的Sid數(shù)組:UserAndGroups,RestrictedSids,Capabilities。

 

_TOKEN結(jié)構(gòu)體

 

Privileges位圖

特權(quán)在用戶(hù)態(tài)是通過(guò)LUID來(lái)表示,在內(nèi)核結(jié)構(gòu)體_TOKEN中是使用三個(gè)位圖來(lái)表示:

kd> dt _SEP_TOKEN_PRIVILEGES
nt!_SEP_TOKEN_PRIVILEGES
   +0x000 Present          : Uint8B
   +0x008 Enabled          : Uint8B
   +0x010 EnabledByDefault : Uint8B

分別代表當(dāng)前的主體可以選用的特權(quán)集合(Present)、已經(jīng)打開(kāi)的特權(quán)集合(Enabled)和默認(rèn)打開(kāi)的特權(quán)集合(EnabledByDefault),后兩個(gè)集合應(yīng)該是Present集合的子集。

與代表主體身份的Sid數(shù)組不同,特權(quán)集合的表示簡(jiǎn)單,而且沒(méi)有任何保護(hù)。從用戶(hù)態(tài)通過(guò)API只能打開(kāi)或者關(guān)閉某一項(xiàng)已經(jīng)存在的特權(quán),而不能增加可選的特權(quán),換句話(huà)說(shuō),用戶(hù)態(tài)只能修改Enabled特權(quán)集合,而不能修改Present特權(quán)集合;從內(nèi)核態(tài)可以直接修改Present特權(quán)集合,比如給普通進(jìn)程增加SeAssignPrimaryTokenPrivilege特權(quán),以便為子進(jìn)程顯式指定令牌,而不是繼承當(dāng)前進(jìn)程的令牌,可以達(dá)到擴(kuò)大子進(jìn)程權(quán)限的效果。

代表主體身份的Sid數(shù)組

三個(gè)代表主體身份的Sid數(shù)組分別是:

UserAndGroups:

代表著主體的普通用戶(hù)身份和組身份,是不可或缺的成員;

RestrictedSids:

可選成員,如果不為空,則代表著當(dāng)前的令牌是受限令牌,受限令牌通過(guò)從普通令牌中過(guò)濾掉一些比較敏感的身份轉(zhuǎn)化而來(lái),受限令牌中的UserAndGroups成員與普通令牌相同,但是RestriectedSids成員不為空,里面保存著過(guò)濾后的身份子集;由于在訪(fǎng)問(wèn)權(quán)限檢查時(shí),三個(gè)身份Sid數(shù)組要同時(shí)進(jìn)行檢查,只有結(jié)果都通過(guò)才允許該次訪(fǎng)問(wèn),因此通過(guò)增加代表著受限制的權(quán)限集合的RestrictedSids成員,既達(dá)到了限制令牌權(quán)限的目的,又在UserAndGroups成員中保留了原有令牌的完整身份信息。

Capabilities:

可選成員,僅用于A(yíng)ppContainer,其中的Sid代表著與App相關(guān)的身份,比如擁有連接網(wǎng)絡(luò)、訪(fǎng)問(wèn)當(dāng)前位置等權(quán)限的身份。

這三個(gè)Sid數(shù)組都關(guān)聯(lián)了哈希信息,以保護(hù)其完整性,因此,即使從內(nèi)核態(tài)直接修改,也會(huì)因?yàn)闊o(wú)法通過(guò)完整性驗(yàn)證而失敗。不過(guò)好在哈希的算法非常簡(jiǎn)單,下面展示的就是Windows 10 x64平臺(tái)下面該算法的C++演示代碼:

  1. static 
  2. NTSTATUS  
  3. RtlSidHashInitialize  
  4. (  
  5.     __in PSID_AND_ATTRIBUTES Groups,  
  6.     __in size_t GroupsCount,  
  7.     __inout PSID_AND_ATTRIBUTES_HASH HashBuffer  
  8. )  
  9. {  
  10.     if (NULL == HashBuffer)  
  11.         return 0xC000000D;  
  12.    
  13.     memset(HashBuffer, 0, 0x110);    
  14.     if (0 == GroupsCount || NULL == Groups)  
  15.         return 0;  
  16.    
  17.     HashBuffer->SidCount = GroupsCount;  
  18.     HashBuffer->SidAttr = Groups;  
  19.    
  20.     if (GroupsCount > 0x40)  
  21.         GroupsCount = 0x40;    
  22.     if (0 == GroupsCount)  
  23.         return 0;  
  24.    
  25.     size_t bit_pos = 1;  
  26.    
  27.     for (size_t i = 0; i < GroupsCount; i++)  
  28.     {  
  29.         PISID sid = reinterpret_cast<PISID>((Groups + i)->Sid);   
  30.    
  31.         size_t sub_authority_count = sid->SubAuthorityCount;  
  32.    
  33.         DWORD sub_authority = sid->SubAuthority[sub_authority_count - 1];  
  34.    
  35.         *(size_t*)(&HashBuffer->Hash[(sub_authority & 0x0000000F)]) |= bit_pos;  
  36.         *(size_t*)(&HashBuffer->Hash[((sub_authority & 0x000000F0) >> 4) + 0x10]) |= bit_pos;  
  37.    
  38.         bit_pos <<= 1;  
  39.     }  
  40.    
  41.     return 0;  

該算法有兩處明顯的局限,只計(jì)算每個(gè)Sid的最后一個(gè)Sub Authority的最低位字節(jié),以及最多只有前64個(gè)Sid參與計(jì)算。

UAC與關(guān)聯(lián)令牌

UAC是Vista版本引入的比較重要的安全機(jī)制,很多用戶(hù)抱怨它帶來(lái)的不便性,然而它就像Linux操作系統(tǒng)中的sudo一樣,是保護(hù)系統(tǒng)安全的一道重要屏障。當(dāng)用戶(hù)登錄Windows時(shí),操作系統(tǒng)會(huì)為用戶(hù)生成一對(duì)初始令牌,分別是代表著用戶(hù)所擁有的全部權(quán)限的完整版本令牌(即管理員權(quán)限令牌),以及被限制管理員權(quán)限后的普通令牌,二者互為關(guān)聯(lián)令牌;此后,代表用戶(hù)的進(jìn)程所使用的令牌都是由普通令牌繼承而來(lái),用來(lái)進(jìn)行常規(guī)的、非敏感的操作;當(dāng)用戶(hù)需要進(jìn)行一些需要管理員權(quán)限的操作時(shí),比如安裝軟件、修改重要的系統(tǒng)設(shè)置時(shí),都會(huì)通過(guò)彈出提權(quán)對(duì)話(huà)框的形式提示用戶(hù)面臨的風(fēng)險(xiǎn),征求用戶(hù)的同意,一旦用戶(hù)同意,將會(huì)切換到當(dāng)前普通令牌關(guān)聯(lián)的管理員權(quán)限令牌,來(lái)進(jìn)行敏感操作。通過(guò)這種與用戶(hù)交互的方式,避免一些惡意程序在后臺(tái)稍稍執(zhí)行敏感操作。

關(guān)聯(lián)令牌是通過(guò)Logon Session來(lái)實(shí)現(xiàn)的,下圖展示了其大致原理:

 

關(guān)聯(lián)令牌

 

并非所有的令牌都有關(guān)聯(lián)令牌,比如一直運(yùn)行在較高權(quán)限下不需要進(jìn)行提權(quán)操作的令牌。

0x03 對(duì)象

對(duì)象的結(jié)構(gòu)

對(duì)象是對(duì)操作系統(tǒng)中需要保護(hù)和集中管理的資源的一種抽象,對(duì)象擁有統(tǒng)一的頭部,保存著抽象出來(lái)的信息。

kd> dt _OBJECT_HEADER
nt!_OBJECT_HEADER
   +0x000 PointerCount     : Int8B
   +0x008 HandleCount      : Int8B
   +0x008 NextToFree       : Ptr64 Void
   +0x010 Lock             : _EX_PUSH_LOCK
   +0x018 TypeIndex        : UChar
   +0x019 TraceFlags       : UChar
   +0x019 DbgRefTrace      : Pos 0, 1 Bit
   +0x019 DbgTracePermanent : Pos 1, 1 Bit
   +0x01a InfoMask         : UChar
   +0x01b Flags            : UChar
   +0x01b NewObject        : Pos 0, 1 Bit
   +0x01b KernelObject     : Pos 1, 1 Bit
   +0x01b KernelOnlyAccess : Pos 2, 1 Bit
   +0x01b ExclusiveObject  : Pos 3, 1 Bit
   +0x01b PermanentObject  : Pos 4, 1 Bit
   +0x01b DefaultSecurityQuota : Pos 5, 1 Bit
   +0x01b SingleHandleEntry : Pos 6, 1 Bit
   +0x01b DeletedInline    : Pos 7, 1 Bit
   +0x01c Spare            : Uint4B
   +0x020 ObjectCreateInfo : Ptr64 _OBJECT_CREATE_INFORMATION
   +0x020 QuotaBlockCharged : Ptr64 Void
   +0x028 SecurityDescriptor : Ptr64 Void
   +0x030 Body             : _QUAD

 

對(duì)象頭

 

對(duì)象的頭部包含著指向安全描述符的指針。

安全描述符

安全描述符保存著作為訪(fǎng)問(wèn)權(quán)限檢查客體的對(duì)象的主要信息。它包含著4個(gè)關(guān)鍵成員,根據(jù)這4個(gè)成員是嵌入在結(jié)構(gòu)體的尾部,還是引用自外部緩存位置的差異,可以分為兩種不同的結(jié)構(gòu)形式:

kd> dt _SECURITY_DESCRIPTOR
ntdll!_SECURITY_DESCRIPTOR
   +0x000 Revision         : UChar
   +0x001 Sbz1             : UChar
   +0x002 Control          : Uint2B
   +0x008 Owner            : Ptr64 Void
   +0x010 Group            : Ptr64 Void
   +0x018 Sacl             : Ptr64 _ACL
   +0x020 Dacl             : Ptr64 _ACL
kd> dt _SECURITY_DESCRIPTOR_RELATIVE
nt!_SECURITY_DESCRIPTOR_RELATIVE
   +0x000 Revision         : UChar
   +0x001 Sbz1             : UChar
   +0x002 Control          : Uint2B
   +0x004 Owner            : Uint4B
   +0x008 Group            : Uint4B
   +0x00c Sacl             : Uint4B
   +0x010 Dacl             : Uint4B

Owner和Group代表了該安全描述符的屬主Sid,Sacl是系統(tǒng)訪(fǎng)問(wèn)控制表(System Access Control List)的簡(jiǎn)稱(chēng),里面可以包含當(dāng)前對(duì)象的審計(jì)(Audit)、完整性級(jí)別(Integrity Level)以及可信賴(lài)級(jí)別(Trust Level)等信息,與前面提到的Dacl共用同一結(jié)構(gòu)體。

可選頭部

對(duì)象除了擁有共同的固定頭部外,還可以有可選的頭部,保存著名稱(chēng)等可選信息。通過(guò)固定頭部的InfoMask成員查表可以得到可選頭部的位置,如圖所示:

 

可選頭部

 

對(duì)象目錄

只有部分對(duì)象擁有名稱(chēng)信息,它們被稱(chēng)為命名對(duì)象。命名對(duì)象的主要作用是方便對(duì)象在不同的進(jìn)程中共享,它們被按類(lèi)別編纂成對(duì)象目錄,因此可以通過(guò)在對(duì)象目錄中的路徑信息找到該對(duì)象。對(duì)象目錄的實(shí)現(xiàn)如下圖所示:

 

對(duì)象目錄

 

對(duì)象類(lèi)型

對(duì)象類(lèi)型是對(duì)象中非常重要的信息,Windows將對(duì)象的類(lèi)型信息從同一類(lèi)對(duì)象中抽象出來(lái),保存成一個(gè)單獨(dú)的類(lèi)型對(duì)象。系統(tǒng)中全部的類(lèi)型對(duì)象被集中放置在一個(gè)表中,對(duì)象通過(guò)維護(hù)一個(gè)指向該表的索引(TypeIndex)來(lái)表明當(dāng)前對(duì)象的類(lèi)型。這個(gè)索引值直接保存在對(duì)象的頭部,而對(duì)象體與對(duì)象頭部直接相鄰,如果對(duì)象體被損壞,有可能導(dǎo)致頭部的索引值被改變,使所謂的類(lèi)型混淆(Type Confusion)利用成為可能。為了緩解這一問(wèn)題,Windows 10對(duì)該索引值做了特殊保護(hù),如下圖所示:

 

類(lèi)型索引保護(hù)

 

這種保護(hù)方式簡(jiǎn)單而強(qiáng)大,新的索引值由3部分經(jīng)過(guò)異或操作得到:類(lèi)型對(duì)象在類(lèi)型對(duì)象表中的真實(shí)索引值,對(duì)象頭部地址的第二個(gè)字節(jié)(即第8到第15位),保存在ObHeaderCookie全局變量中的因每次系統(tǒng)啟動(dòng)而異的Cookie字節(jié)。其中,ObHeaderCookie的引入,使同一類(lèi)型的對(duì)象在不同機(jī)器上,甚至是同一機(jī)器上兩次啟動(dòng)之間的索引值不同,然而這樣并不足以緩解類(lèi)型混淆利用,我們還可以利用信息泄露(Info Leak)來(lái)繞過(guò)(Bypass)該保護(hù),因此還引入了對(duì)象頭部地址,使得在同一時(shí)刻、同一系統(tǒng)中的兩個(gè)相同類(lèi)型對(duì)象的不同實(shí)例間的索引值也不相同,從而有效地緩解類(lèi)型混淆利用。

0x04 完整性級(jí)別檢查

完整性級(jí)別(IL)檢查是沙盒的最簡(jiǎn)單實(shí)現(xiàn)方式,通過(guò)完整性級(jí)別在對(duì)象和進(jìn)程層次之間的繼承關(guān)系,就如同在操作系統(tǒng)中建立起了“世襲制度”。通過(guò)嚴(yán)格控制完整性級(jí)別的繼承規(guī)則,以及設(shè)置嚴(yán)格的完整性級(jí)別檢查制度,可以保證“出身低微”的主體無(wú)法訪(fǎng)問(wèn)到“出身高貴”的客體資源。

完整性擁有以下幾個(gè)級(jí)別:

SeUntrustedMandatorySid
SeLowMandatorySid
SeMediumMandatorySid
SeHighMandatorySid
SeSystemMandatorySid

主體的缺省完整性級(jí)別是SeUntrustedMandatorySid,而客體的缺省完整性級(jí)別是SeMediumMandatorySid,這種差異也進(jìn)一步地強(qiáng)化了這種“世襲制度”。

0x05 保護(hù)進(jìn)程

保護(hù)進(jìn)程(Protected Process)是Windows操作系統(tǒng)為了保護(hù)某些關(guān)鍵進(jìn)程,防止其被普通進(jìn)程調(diào)試、注入、甚至是讀取內(nèi)存信息而建立起來(lái)的一種安全機(jī)制。

保護(hù)進(jìn)程與其他普通進(jìn)程的區(qū)別在于,保護(hù)進(jìn)程的Protection成員不為0。

kd> dt nt!_EPROCESS Protection
   +0x6b2 Protection : _PS_PROTECTION
kd> dt nt!_PS_PROTECTION
   +0x000 Level            : UChar
   +0x000 Type             : Pos 0, 3 Bits
   +0x000 Audit            : Pos 3, 1 Bit
   +0x000 Signer           : Pos 4, 4 Bits

保護(hù)進(jìn)程的Type成員可以代表兩種保護(hù)類(lèi)型:Protected Process(PP),Protected Process Lite(PPL),兩者的區(qū)別在于PP保護(hù)進(jìn)程擁有更高的權(quán)限。保護(hù)進(jìn)程的Signer成員代表該進(jìn)程的簽名發(fā)布者的類(lèi)別。對(duì)于Signer為PsProtectedSignerWindows(5)和PsProtectedSignerTcb(6)的保護(hù)進(jìn)程,其Type和Signer信息會(huì)被抽取出來(lái),組裝成一個(gè)Sid,代表著該進(jìn)程的可信賴(lài)級(jí)別,保存到基本令牌中的TrustLevelSid成員中。當(dāng)一個(gè)令牌中的TrustLevelSid被使用時(shí),需要保證與當(dāng)前進(jìn)程的Protection信息保持同步,這主要是為了應(yīng)對(duì)令牌在不同進(jìn)程間傳遞時(shí)(比如子進(jìn)程繼承父進(jìn)程的令牌)導(dǎo)致的TrustLevelSid成員過(guò)時(shí)的情形。

當(dāng)調(diào)試或者創(chuàng)建一個(gè)進(jìn)程時(shí),會(huì)調(diào)用內(nèi)核函數(shù)PspCheckForInvalidAccessByProtection進(jìn)行權(quán)限檢查,該函數(shù)根據(jù)當(dāng)前進(jìn)程以及目標(biāo)進(jìn)程的Protection來(lái)判定當(dāng)前操作是否需要遵守保護(hù)進(jìn)程規(guī)定的權(quán)限限制,具體判定規(guī)則如下:

如果操作來(lái)自于內(nèi)核態(tài)代碼,不需要遵守限制;

如果目標(biāo)進(jìn)程的Protection成員為空,表示目標(biāo)進(jìn)程不是保護(hù)進(jìn)程,不需要遵守限制;

如果當(dāng)前進(jìn)程是PP類(lèi)型保護(hù)進(jìn)程,該類(lèi)型保護(hù)進(jìn)程擁有最高權(quán)限,不需要遵守限制;

如果當(dāng)前進(jìn)程與目標(biāo)進(jìn)程都是PPL類(lèi)型保護(hù)進(jìn)程,需要根據(jù)RtlProtectedAccess表來(lái)判斷當(dāng)前進(jìn)程的Signer是否優(yōu)先于(dominate)目標(biāo)進(jìn)程的Signer,如果是,不需要遵守限制;

其他情況,需要遵守限制。

RtlProtectedAccess表如下所示:

RTL_PROTECTED_ACCESS RtlProtectedAccess[] =
{
//   Domination,       Process,         Thread,
//         Mask,  Restrictions,   Restrictions,
    {         0,             0,             0}, //PsProtectedSignerNone               Subject To Restriction Type
    {         2,    0x000fc7fe,    0x000fe3fd}, //PsProtectedSignerAuthenticode       0y00000010
    {         4,    0x000fc7fe,    0x000fe3fd}, //PsProtectedSignerCodeGen            0y00000100
    {         8,    0x000fc7ff,    0x000fe3ff}, //PsProtectedSignerAntimalware        0y00001000
    {      0x10,    0x000fc7ff,    0x000fe3ff}, //PsProtectedSignerLsa                0y00010000
    {      0x3e,    0x000fc7fe,    0x000fe3fd}, //PsProtectedSignerWindows            0y00111110
    {      0x7e,    0x000fc7ff,    0x000fe3ff}, //PsProtectedSignerTcb                0y01111110
};

其中,Process Restrictions以及Thread Restrictions分別代表著進(jìn)程和線(xiàn)程的權(quán)限限制,詳解如下圖:

 

保護(hù)進(jìn)程與線(xiàn)程的權(quán)限限制

 

我們可以通過(guò)NtDebugActiveProcess以及NtCreateUserProcess的演示代碼來(lái)理解保護(hù)進(jìn)程及其限制的邏輯:

  1. static 
  2. NTSTATUS  
  3. NtDebugActiveProcess(  
  4.     __in HANDLE ProcessHandle,  
  5.     __in HANDLE DebugObjectHandle  
  6.     )  
  7. {  
  8.     PEPROCESS target_process = nullptr;  
  9.     NTSTATUS result = ObReferenceObjectByHandleWithTag( ProcessHandle, &target_process);  
  10.     if (! NT_SUCCESS(result))  
  11.         return result;  
  12.    
  13.     PEPROCESS host_process = PsGetCurrentProcess();  
  14.    
  15.     if (host_process == target_process)  
  16.         return 0xC0000022;  
  17.    
  18.     if (PsInitialSystemProcess == target_process)  
  19.         return 0xC0000022;  
  20.    
  21.     if (PspCheckForInvalidAccessByProtection(PreviousMode, host_process->Protection, target_process->Protection))  
  22.         return 0xC0000712;  
  23.    
  24.     // ......  
  25. }  
  26.    
  27.    
  28. static 
  29. NTSTATUS  
  30. NtCreateUserProcess(  
  31.     __out PHANDLE ProcessHandle,  
  32.     __out PHANDLE ThreadHandle,  
  33.     __in  ACCESS_MASK ProcessDesiredAccess ,  
  34.     __in  ACCESS_MASK ThreadDesiredAccess ,  
  35.     __in  POBJECT_ATTRIBUTES ProcessObjectAttributes OPTIONAL ,  
  36.     __in  POBJECT_ATTRIBUTES ThreadObjectAttributes OPTIONAL ,  
  37.     __in  ULONG CreateProcessFlags,  
  38.     __in  ULONG CreateThreadFlags,  
  39.     __in  PRTL_USER_PROCESS_PARAMETERS ProcessParameters ,  
  40.     __in  PVOID Parameter9,  
  41.     __in  PNT_PROC_THREAD_ATTRIBUTE_LIST AttributeList  
  42.     )  
  43. {  
  44.     ACCESS_MASK allowed_process_access = ProcessDesiredAccess ;  
  45.     ACCESS_MASK allowed_thread_access = ThreadDesiredAccess ;  
  46.     PS_PROTECTION protection = ProcessContext.member_at_0x20;  
  47.     if (PspCheckForInvalidAccessByProtection(PreviousMode, host_process->Protection, target_process->Protection))  
  48.     {  
  49.         // 1 << 0x19 = 0x80000,  WRITE_OWNER  
  50.         if ( MAXIMUM_ALLOWED == ProcessDesiredAccess )  
  51.             allowed_process_access = (((~RtlProtectedAccess[protection.Signer].DeniedProcessAccess) & 0x1FFFFF) | ProcessDesiredAccess) & (~(1 << 0x19));  
  52.    
  53.         if ( MAXIMUM_ALLOWED == ThreadDesiredAccess )  
  54.             allowed_thread_access = (((~RtlProtectedAccess[protection.Signer].DeniedThreadAccess) & 0x1FFFFF) | ThreadDesiredAccess) & (~(1 << 0x19));  
  55.     }  
  56.     //PspInsertProcess(..., allowed_process_access, ...);  
  57.     //PspInsertThread(..., allowed_thread_access, ...);  

0x06 結(jié)語(yǔ)

Windows操作系統(tǒng)中的權(quán)限檢查機(jī)制以及安全系統(tǒng)一直都在不斷地進(jìn)化著,探索其實(shí)現(xiàn)的細(xì)節(jié)以及推測(cè)其背后的設(shè)計(jì)理念是一件非常有趣有益的事情,本文僅僅是作者在探索中的小結(jié),難免有疏漏甚至錯(cuò)誤,更加詳細(xì)的內(nèi)容可以參考下列材料,或者直接分析和調(diào)試Windows內(nèi)核,以了解最新最真實(shí)的Windows。

James Forshaw: The Windows Sandbox Paradox

James Forshaw: A Link to the Past: Abusing Symbolic Links on Windows

Alex Ionescu: The Evolution of Protected Processes Part 1: Pass-the-Hash Mitigations in Windows 8.1

Alex Ionescu: The Evolution of Protected Processes Part 2: Exploit/Jailbreak Mitigations, Unkillable Processes and Protected Services

Alex Ionescu: Protected Processes Part 3 : Windows PKI Internals (Signing Levels, Scenarios, Root Keys, EKUs & Runtime Signers)

Daniel & Azure: Did You Get Your Token?

責(zé)任編輯:藍(lán)雨淚 來(lái)源: 烏云知識(shí)庫(kù)
相關(guān)推薦

2009-07-27 14:24:16

ASP.NET訪(fǎng)問(wèn)權(quán)限

2011-06-28 13:26:23

Oracle數(shù)據(jù)庫(kù)ODBC

2009-06-11 17:03:29

Java線(xiàn)程

2011-05-19 10:57:45

DNSSEC密鑰加密

2017-04-12 11:46:46

前端瀏覽器渲染機(jī)制

2021-08-30 09:44:47

Kubelet機(jī)制驅(qū)逐

2009-09-16 15:45:56

email的正則表達(dá)式

2010-08-13 13:09:14

CISCO路由器

2010-08-03 12:33:16

路由器權(quán)限

2013-03-26 13:38:12

Android per

2023-07-07 10:41:00

Javajar文件

2009-07-06 14:52:10

ServletConfServletCont

2009-06-23 14:15:00

Java垃圾回收

2022-06-01 16:01:58

MySQL內(nèi)存管理系統(tǒng)

2017-08-25 10:20:46

Docker容器機(jī)制

2010-01-26 14:43:53

Android數(shù)據(jù)存儲(chǔ)

2011-03-10 15:22:08

訪(fǎng)問(wèn)控制機(jī)制Java

2016-08-23 14:25:19

MySQL約束數(shù)據(jù)庫(kù)

2010-06-07 13:30:15

2009-04-08 09:58:07

ASP.NET MVCTempData框架
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)