Jump to content

本文會詳細分析Windows即將推出的最大安全功能——智能應用控制(Smart App Control,SAC)。 “智能應用控制”功能是什麼,為什麼我認為它是Windows 中最牛的安全功能之一。首先,SAC 會嵌入在操作系統中,啟用後將阻止惡意或不受信任的應用程序。這與AppLocker 非常相似。

在之前一篇文章中,我們看到了SAC是如何啟用和初始化的。在本文中,我們將討論SAC如何執行這些操作。即使SAC是一個新功能,該功能使用的大部分代碼也已經在操作系統中了。我的意思是,在22H2之前的版本中,通過使用適當的策略規範,可以獲得類似的行為。總之,SAC的最大變化是MS將激活特定的WDAC策略,類似於啟用HVCI時,操作系統如何啟用Driver Block Rule策略。

需要注意的是,因為我們在這篇文章中看到的很多內容在操作系統中已經存在了很長時間。 AppLocker或AppID等功能利用了它。當然,有幾個方面只適用於SAC,我一定會注意到這些。從好的方面來看,這篇文章的絕大多數可以推斷出其他WDAC策略是如何評估的。

1.png

SAC運行在本節中,我們將重點關注CI處理來自內核的驗證請求所採取的步驟。我們將深入探討此過程中涉及的主要例程,還將討論CI使用的一些主要結構。正如我剛才提到的,這些步驟中的大多數並不是SAC獨有的,無論啟用哪種策略,都將採取這些步驟。如上圖所示,我們看到有三個主要的評估來源。據我所知,這些要點與以下功能/策略規範有關,至於是選擇使用一個或多個評估取決於策略規範。

OriginClaim (EAs or Token): 託管安裝程序、AppLocker、SmartScreen和SAC;

Query 防禦措施: Intelligent Security Graph (ISG) SAC;

Policy FileRules: 通用於所有具有FileRule的策略。

2.png

在上一篇文章中,我們已經說過全局g_CiPolicyState具有位NW_ENABLED,這意味著SAC已啟用,SAC策略(強製或評估)處於活動狀態,並存儲在g_SiPolicyCtx中。現在,讓我們看看CI向內核提供的回調,看看內核的驗證方式。以下函數建議執行某種類型的驗證:

CiValidateImageHeader;

CiValidateImageData;

CiValidateFileAsImageType;

CiRevalidateImage;

在本文中,我將只關注CiValidateImageHeader。

CiValidateImageHeader可以說,此函數是大多數CI驗證的主要入口點。內核將從MiValidateSectionCreate中引用的SeValidateImageHeader調用此函數。 CiValidateImageHeader將處理CI初始化的第2階段,主要初始化minCrypt、ETW、Lookaside緩衝區等。一旦完成(只有一次),第一步是獲取指定映像(CiGetActionsForImage)行為。此函數將根據諸如Requested SigningLevel之類的內容,或者如果對象來自受保護進程或系統進程,來確定將要進行的驗證操作,這些操作是位字段枚舉,但我不知道大多數值的含義.

操作進行後,函數就可以開始驗證映像了。如果操作變量設置了位0(action_FILE_In_CACHE(0x1)),則CI將嘗試獲取之前為此FO設置的任何驗證數據,並重新驗證。

在本文中,我們不會涉及CI緩存及其驗證原理。本質上,它將嘗試獲取內核EA:$Kernel.Purge.CIpCache或$Kernell.Purge.ESBCache(請參閱函數CipGetFileCache)。然後,它會將策略應用於CiApplyPolicyToSyntheticEa內的這些屬性。這個例程最終將調用CipApplySiPolicyEx,我們稍後將詳細討論。

如果未設置“file in cache”屬性,則會分配用於處理驗證的主結構(CipAllocateValidationContext)。此結構用於所有類型的驗證,例如,此上下文也用於HVCI驗證(請參閱CiHvciSetValidationContextForHvci)。一旦分配了這個上下文,我看到UMCI驗證會發生兩個操作。

如果設置了位2(ACTION_PAGE_HASH(0x4)),驗證函數為-CipValidatePageHash;

如果設置了位8(ACTION_FILE_HASH(0x100)),驗證函數為-CipValidateFileHash。

CipValidateImageHash將接收發生操作的Validation函數作為函數指針。無論傳遞的是什麼函數指針,PageHash還是FileHash,CipValidateImageHash最終都會調用它。在這兩個驗證函數中,CI都會使用被驗證對象的信息更新驗證上下文。諸如FileInfo(CipUpdateValidationContextWithFileInfo)、文件版本(CiGetFileResourceInformation)、嵌入簽名(CipImageGetCertInfo)或對象哈希(Page CipCalculateHeaderHash或File CipCalpulateImageHash)。有了所有這些信息,代碼將通過函數CipApplySiPolicyEx方法繼續應用策略。

對於未簽名映像的驗證,驗證函數將返回STATUS_INVALID_IMAGE_HASH,代碼將進入CipApplySIPolicyUMCI,最終調用前面提到的CipApply SiPolicyEx。相反,對於簽名文件,將從CiVerifyPageHashSignedFile或CiVerify FileHashSingedFile訪問此函數。簡單說明一下,這兩個函數有它們的HVCI對應函數CiHvciXxx。

CipApplySiPolicyEx顧名思義,此函數將把策略應用於正在驗證的對象。該函數將首先設置兩個結構,然後將其傳遞給驗證引擎。一個結構將保存正在驗證的ImageFile的信息,而另一個結構則包含“外部”授權過程所需的信息,我說“外部”授權是因為MS在驗證對象的回調函數名中使用了“外部”授權這個詞。

這兩個結構將存儲在Validation Context中,並且實際上都將被來自Validation Context的數據填充。其中一個包含映像數據,我命名為CI_VALIDATE_IMAGE_DATA,其中包含以下內容:

3.png

另一方面,外部授權結構(我將其命名為CI_EXTERNAL_AUTH)具有以下有趣的值:

4.png

在調用驗證引擎例程之前,CipApplySiPolicyEx將設置一個結構數組,其中包含每個策略的驗證結果,該數組的大小將等於活動策略的數量。我將此結構命名為CI_VALIDATION_RESULT,它具有以下字段:

5.png

最後,我們準備調用SIPolicyObjectValidationEngine,它具有以下原型:

6.png

這個例程將簡單地遍歷策略和補充策略,為每個策略調用內部例程SIPolicyValidateImageInternal。

內部驗證例程的任務是調用外部授權回調,以從“外部源”獲取驗證分數。它將根據此分數,選擇繼續或不繼續根據策略中的規範評估映像。我們將首先關注外部回調,設置為函數CipExternalAuthorizationCallback,然後我們將討論如何評估策略規範。

從代碼中我可以看到,這與MS在文件規範優先順序一節中聲明的有些不同。他們說“它將首先處理它找到的所有顯式拒絕規範。然後,它將處理所有顯式允許規範。如果不存在拒絕或允許規範,WDAC將檢查託管安裝程序EA。最後,如果這些集合都不存在,WDAC會回到ISG”。相反,在代碼中,似乎在處理FileRule之前檢查了託管安裝程序和ISG(外部授權)。

CipExternalAuthorizationCallback這個函數包含了SAC的核心功能,即使它從21H2到22H2沒有太大的變化,當啟用SAC時,有一些細節會造成很大的不同。儘管如此,我們將要討論的大部分內容都將被AppLocker和ISG使用(並且已經被使用了),所以從好的方面來看,我們也將從中學習一些東西。為了概述我們是如何做到這一點的,下面是我們到達外部授權回調時的堆棧,用於驗證未簽名映像時的堆棧。

7.png

該函數將通過檢查策略選項Intelligent Security Graph Authorization(智能安全圖授權)或Managed Installer(託管安裝程序)啟動,如果這些選項都沒有設置,則該函數將退出,SIPolicyValidateImageInternal將繼續處理策略FileRule,我們將在稍後的章節中看到這一點。

如果設置了任何選項,下一步是根據簽名級別確定映像是否可信。這是通過使用為映像獲取的ValidatedSigningLevel,並將此值與全局變量g_CipWhichLevelComparisons內索引為0xC的位掩碼進行比較來實現的。

請注意:全局變量g_CipWhichLevelComparisons存儲了一個指向ulong數組的指針。每個值表示適用於此簽名級別的比較級別。通常與已驗證的簽名級別一起使用,以確定映像的不同操作/選項。例如,對於等於“File Unsigned”(即數組中的索引1)的已驗證簽名級別,位掩碼為0xFFFFFFFE,因此大多數情況下測試此位掩碼時,結果都為正值。在其他情況下,如上所述,索引在代碼中被硬編碼為僅作用於與該索引的位掩碼匹配的已驗證簽名級別。下表有望幫助理解g_CipWhichLevelComparisons和ValidatedSigningLevel之間的關係。

8.png

如上表所示,索引0xC表示位掩碼0x5000,表示“Windows簽名”和“Windows TCB簽名”。此外,接下來的兩個級別“僅用於.NET NGEN編譯器的簽名”和由使用AMPPL的產品的反病毒簽名”也將包含在可信映像列表中。此時,函數將繼續調用CipCheckSmartlockerEAandProcessToken以獲得第一個驗證分數。

我覺得這是一個討論命名的好時機,希望微軟的人能聯繫到我,並澄清命名。有人稱之為Smart App Control和Nights Watch,也有人稱之為AppLocker,內部名稱似乎是SmartLocker。相同或非常相似的事物有4個不同的名稱。這確實有點令人困惑。

該函數具有以下原型:

9.png

這個函數有兩條路徑,其中一條總是被執行,另一條基於booleanIsTrustedSigning。如果不受信任,那麼下面的EA將被查詢為正在驗證的文件對象,它也試圖從當前流程文件對像中獲得相同的EA,但除了存儲在驗證上下文中,我沒有看到它們在其他地方被使用。

$ Kernel.Smartlocker.Hash: 包含映像的哈希;

$ Kernel.Purge.Smartlocker.Valid: 布爾值是否有效;

$Kernel.Smartlocker.OriginClaim: 包含我命名為EA_ORIGIN_CLAIM的結構。

10.png

如果獲得了有效的EA,那麼將檢查OriginClaim結構以確定圖像的分數。 Origin值將決定第一個分數,如果Origin==0,則score |=1,如果Origin==1,則score |=0x1002。

不過我對這方面了解不多。這很可能與WDAC在策略中設置託管安裝程序選項時在AppLocker中使用的特殊規範集合有關。這很可能與在策略中設置託管安裝程序選項時WDAC使用的AppLocker中的特殊規範集合有關。從我所看到的,我知道appid.sys確實設置了此EA,另一種設置此EA的方法是通過CI回調cisetcachedorigin聲明。這個函數在發出帶有標誌0x2000的syscall NtSetCachedSigningLevel時被內核調用,當然不像調用這個syscall來設置EA origin聲明那麼容易,如果這個syscall以前的模式是UserMode,那麼NtSetCachedSigningLevel2將確保請求來自一個受保護的進程。

下一步,無論我們是否檢查了EA,都是獲取存儲在令牌對像中的OriginClaim。對於令牌對象,origin聲明存儲在令牌的SecurityAttributes列表中,這些屬性存儲為Authz SecurityAttributes,並且可以使用函數sequerysecurityattributeken按名稱查詢/檢索。在本例中,將尋找兩個安全屬性:

SMARTLOCKER://ORIGINCLAIM;

SMARTLOCKER://SMARTSCREENORIGINCLAIMNOTINHERITED(Newin22H2,previously“SMARTLOCKER://SMARTSCREENORIGINCLAIM”)

首先將查找OriginClaim。如果發現,分數將相應調整。同樣,我對這方面不太了解,也沒有有關此聲明的結構外觀的信息(appid.sys設置此值令牌)。

之後,將查詢SmartScreen OriginClaim未繼承屬性,如果它被發現並設置標籤CLAIM_DANGEROUS_EXT (0x80) (這不是官方名稱),然後函數將繼續檢查ImageFile是否有被認為是危險擴展名。同樣,在所有情況下,代碼都將檢查ImageFile是否具有InstallerExtension。對於安裝程序擴展,它只會檢查.msi,對於危險擴展的情況,這些值如下:

11.png

如果ImageFile與這些值中的任何一個匹配,則分數將設置為DangerousExtension (0x800),並通過調用CiCatDbSmartlockerDefenderCheck向防禦措施發出查詢,有關此函數稍後將詳細討論。

0 Comments

Recommended Comments

There are no comments to display.

Guest
Add a comment...