下面的偽代碼或多或少地展示了SmartLocker非繼承屬性的最後一部分是如何工作的。
注意: 根據稍後如何使用此函數中的值來填充TraceLogging字符串,我們知道防禦措施將評估過程的所有這一部分視為: Is防禦措施Shell。
這或多或少就是我們通過在調用之後立即雙擊從資源管理器啟動的進程所需要的:
CipCheckSmartlockerEAandProcessToken的情況就這樣了,現在再說說CipExternalAuthorizationCallback。
現在,讓我們說說Intelligent Security Graph所使用的代碼段,它現在已被擴展以添加一些SAC功能。首先,將再次檢查策略選項Intelligent Security Graph Authorization(智能安全圖授權),如果未設置,函數將使用從CipCheckSmartlockerEAandProcessToken獲取的值退出。如果該值在策略中處於活動狀態(SAC策略就是這種情況),該函數將使用前面討論的IsTrustedSigning來確定它是否應該繼續。如果映像可信,將執行以下檢查:
如果ValidatedSigningLevel等於“由使用AMPPL(7)的產品的AV簽名”,並且策略的值為VerifiedAndReputableAllowAntiMalware,則分數將用值AllowAnti Malware(0x100000)進行異或運算,函數將返回。
如果映像不可信,則函數將繼續查詢防禦措施。如上所述,向防禦措施發出查詢的函數是CiCatDbSmartlockerDefenderCheck。此函數將接收兩個MPFILE_TRUST_EXTRA_INFO結構,一個填充請求數據,另一個接收回複數據。代碼還將從FileObject傳遞FileName。 MPFILE_TRUST_EXTRA_INFO結構如下所示。
雙方之間的通信是使用RPC實現的,CI.dll將實現客戶端,服務器將在cryptcatsvc.dll中實現。為了記錄,RPC存根的IID是f50aac00-c7f3-428e-a022a6b71bfb9d43。
cryptcatsvc在服務CryptSvc中運行。在用於RPC服務器的發送函數中,我們重點關注以下函數:
s_SSCatDBSmartlockerDefenderCheck(Alreadypresentin22H1);s_SSCatDBSmartlockerDefenderCheck2(Newto22H2);s_SSCatDBSendSmartAppControlBlockToast;s_SSCatDBSendSmartAppControlSwitchEnforceToast;SmartLockerDefenderCheck函數的v1和v2之間的最大區別在於,在v2中,該函數接受請求和回复MPFILE_TRUST_EXTRA_INFO作為其參數的一部分。這兩個函數最終都調用了助手函數CatDBSmartlockerDefenderCheckHelper。
CI將從這些函數調用s_SSCatDBSmartlockerDefenderCheck2,它將首先加載MpClient.dll。
注意:在第一次執行時,將在防禦措施配置中啟用SmartLocker。該函數將調用MpClient導出的函數MpSmartLockerEnable。此函數只需註冊Defender ELAM證書信息(打開Wdboot.sys的句柄並調用InstallELAMCertificateInfo),然後使用RPC從MpSvc.dll調用方法ServerMpEnableSmartLocker,它將檢查防禦措施配置中是否設置了SmartLockerMode,如果沒有,它將寫入。
打開庫的句柄後,該函數將使用CI.dll提供的文件名來打開一個文件句柄,該句柄將被傳遞給MpClient導出的函數MpQueryFileTrustByHandle2,該函數只在來自於DefenderCheck2時被調用,如果是舊版本的DefenderCheck,則將調用MpQueryFileTrustByHandle。
在MpQueryFileTrustByHandle2內部,代碼將使用該文件的句柄來創建文件映射,該文件映射將被防禦程序用於對其進行內存掃描。下面的InSequence函數將通過從MpClient(客戶端)到MpSvc(服務器)發出RPC調用來執行。顯然,我們剛才看到的所有函數調用都接受CI.dll設置的MPFILE_TRUST_EXTRA_INFO作為參數的一部分。
ServerMpRpcMemoryScanStart:設置CMpMemScanContext和CMpMemScanEngineVfz(使用GetAttributeTrustCheck作為GetAttributions函數),並進行異步掃描;
ServerMpRpcMemoryScanQueryNotification:檢索掃描信息;
ServerMpRpcMemoryScanClose:關閉並清除CMpMemScanContext。
這些函數的內部結構不在本文所講的範圍,我想強調的是,當啟用SAC時,防禦措施將主動掃描文件並進行雲查詢。
從掃描檢索到的信息中有三個可能的信號:
0x31001:檢索到的MPTRUST_INFO(IGS);
0x31002:檢索到的MPFILE_TRUST_EXTRA_INFO(SAC);
0x4005:與RSIG_VIRINFO相關;
最後完成防禦措施通信,下圖顯示了代碼到達防禦措施時客戶端(CI)和服務器(cryptcatsvc)堆棧。
需要注意的是,如果我們的SAC處於強制狀態,並且設備中沒有互聯網連接,則默認操作是阻止該進程,並且將顯示一條通知,提示“智能應用程序控制無法驗證此應用程序,請檢查您的互聯網連接,然後重試”。
返回外部授權回調,如果RPC調用失敗,則未設置策略設置VerifiedAndReputableAllowUnknown,並且ValidateSigningLevel不是以下任何一項:
MicrosoftStoresignedappPPL(ProtectedProcessLight)MicrosoftStore-signedMicrosoftsignedWindowssignedOnlyusedforsigningofthe.NETNGENcompilerWindowsTrustedComputingBasesigned然後將驗證分數與值Unattainable(0x40000)進行異或運算,函數將返回。如果RPC調用成功,則將調用函數CiHandleDefenderSignals。顧名思義,此函數將處理防禦措施發送回的消息。它將遍歷返回的元素數,其中每個元素的類型為MPFILE_TRUST_EXTRA_INFO。根據ReplyType字段,它將執行不同的操作。更有趣的兩種情況是:首先,當返回信任結果時。在該示例中,信息將指向MP_INFO_RESULT,其中的值將復製到驗證上下文:
第二個有趣的示例是信息指向MP_NW_CONTROL枚舉。在該示例中,根據控制命令,該功能將被禁用或切換到強制模式。這基本上將更新VerifiedAndReputablePolicyState RegKey,並更新WorkItem中的策略。
在我們從學習模式更改為強制模式的情況下,將發出對函數s_SSCatDBSendSmartAppControlSwitchEnforceToast的RPC調用。在此函數中,DLL wldap . DLL將被加載,然後調用函數WldpSendSmartAppControlSwitchEnforceToast。
從信號處理程序回來後,有一些細微差別。如果NW控制命令設置了標誌IsUnfriendlyFile,則Score將更新為值UnfriendalyFile(0x80000),函數將返回。如果未設置標誌,則TrustInfo和FileObject將被傳遞到帶有標誌0x82的函數CipSetFileCache中,這意味著EA$Kernel.Purge.CIpCache將用於存儲此信息。
最後,需要根據防禦程序返回的信任調整分數,有5個選項:
Trust==1:分數將使用值0x202進行異或運算,不過我對這個值不太了解;
Trust==-1 (0xFFFFFFFF):如果策略設置VerifiedAndReputableAllowUnknown被設置,則分數將使用值AllowUnderknown(0x20000)進行異或運算;
Trust==-2 (0xFFFFFFFE):分數將使用值Malicious (0x80)進行異或運算;
Trust==-3 (0xFFFFFFFD):分數將用PUA(0x100)值進行異或運算;
任何其他情況下,分數將用值0x42進行異或運算。
這幾乎就是外部授權回調的全部內容,現在我們回到調用外部授權回調時的SIPolicyValidateImageInternal!
SIPolicyValidateImageInternal在進入外部授權回調之前,我們將討論SIPolicyObjectValidationEngine函數如何遍歷策略並調用內部SIPolicy ValidateImageInternal,後者稍後將調用外部auth回調。現在,調用回調後,我們返回到SIPolicyValidateImageInternal,並返回驗證分數。如果啟用了SAC,則該函數將繼續評估分數,並將此分數傳播到驗證引擎分數,並根據該得分設置相應的NTSTATUS。
如上圖所示,在大多數分支中,它會將相應的NTSTATUS設置為驗證狀態,然後跳轉到我所稱為ProcessDbgAndReprieve的狀態。這只不過是一種檢查內核調試器是否附加到調試器控制台中以記錄策略衝突的方法。
如果未遵循前一個映像中的任何分支,或者分數為Unattainable但設置了AllowUnknown,則函數將繼續根據策略規範評估對象。首先檢查文件規範,這將在函數SIPolicyMatchFileRules內完成。此函數將接收以下參數:
具有要評估的文件規範的策略;
OriginalFileName;InternalName;FileDescription;ProductName;我強烈建議閱讀MSDN的“理解Windows防禦應用程序控制(WDAC)策略規範和文件規範”一節,以了解更多關於策略規範和可用於它們的不同選項的內容。
與我們在第1部分中看到的Policy Secure Settings類似,該函數將使用作為key傳遞到函數bsearch的數據建立一個結構。關鍵結構具有以下原型:
bsearch函數的base和num將取自SI_POLICY結構。將策略解析為SI_policy結構時,將設置一個包含兩個場景的數組。每個場景都包含其特定的文件規範、允許的簽名者、拒絕的簽名者和異常規範。如上所述,當調用SIPolicyMatchFileRules時,要評估的場景的特定數量被傳遞給函數。此數字將用作函數的索引,以了解要選取Scenarios數組的哪個元素。每個場景都由以下結構表示:
如果沒有FileName級別的文件規範匹配,則函數將繼續計算哈希級別的文件規範:
如果FileName或Hash匹配,則SIPolicyMatchFileRules返回TRUE,驗證狀態將設置為status_SYSTEM_INTEGRITY_POLICY_VIOLATION。
如果對SAC策略使用的哈希和文件名感興趣,可以查看策略的FileRule標籤下的整個列表。
如果沒有匹配的文件規範,則下一步(如果映像已簽名)是根據“拒絕”和“允許”簽名者驗證簽名鏈信息。首先,將檢查被拒絕的簽名者。如果與前面相同的規範在此匹配,該函數將把驗證狀態設置為status_system_integrity_policy_violate。如果沒有拒絕簽名者規範匹配,代碼將繼續檢查允許的簽名者規範。在該示例中,如果存在匹配,則會清除以前的任何狀態/分數。根據策略簽名驗證映像簽名的過程主要在函數SIPolicyValidateChainAgainstSigner中完成。此函數將作為第一個參數接收映像的SI_CHAIN_INFO,並在@r8中接收POLICY_SIGNERS_DATA。
關於這個POLICY_SIGNERS_DATA結構,基本上SI_POLICY結構保留一個POLICY-SIGNERS_DATA數組。這些代表兩種方案的所有Allow和Deny簽名。代碼知道哪些規範適用於哪個場景的方式,這意味著要使用POLICY_SIGNERS_DATA數組的哪個索引是非常聰明的。這是我之前在文件規範中沒有解釋的事情,所以現在是檢查它的好時機。如果你返回並檢查SI_POLICY_SCENARIO結構,將看到對於每個規範類型結構(file, Allow, Deny),都有一個SI_RULES結構,其中包含一個我稱為IndexArray的字段。基本上,這是一個索引數組,用於指示該特定場景和規則必須使用包含數據的數組中的哪個索引。讓我們看一個快速的偽代碼片段,以便更好地理解這一點。
這可能不是百分之百準確的,因為我省略了很多在中間進行的檢查。
為了更好地了解簽名是如何驗證的,接下來你可以找到POLICY_SIGNERS_DATA的原型,注意,這將適用於允許簽名者和拒絕簽名者。
通過查看SI_CHAIN_INFO和POLICY_SIGNERS_DATA,你可以或多或少地了解如何在SIPolicyValidateChainAgainstSigner函數中進行比較。最後,為了總結Signer規範的驗證,下面是在SIPolicyValidateChainAgainstSigner條目處使用SAC強制策略驗證ProcessHacker時記錄的映像。
老實說,為了達到這張圖片的目的,我不得不稍微修改代碼流。因為在第一次簽名檢查時,Type將匹配,然後它將退出循環。之所以會實現這一點,是因為這個POLICY_SIGNERS_DATA中的信息比第一個檢查的要多。在第一次選中時,唯一的填充值是Type(設置為0x14)。我已嘗試查找有關此Type值的信息,但找不到任何信息。
因此,在為每個活動策略和補充策略運行整個過程之後,我們將返回函數CipApplySiPolicyEx,為每個BasePolicy提供一個CI_VALIDATION_RESULT。補充策略的結果將寫入與BasePolicy相同的CI_VALIDATION_RESULT中。此時,該函數只會遍歷驗證結果,將這些結果存儲在validation Context中。此外,此時SmartLocker事件將記錄在函數CiLogSIPolicySmartlockerEvent中。此處可以記錄四種類型的事件:
SmartlockerOperationalAudit(EventId:3091)SmartlockerOperationalFailure(EventId:3092)SmartlockerVerbose(EventId:3088)SmartlockerOperationalSuccess(EventId:3090)
我們幾乎完成了,現在將進入調用堆棧,將驗證狀態傳遞到上面的函數。最後,我們將回到CI入口點CiValidateImageHeader,與之前一樣,我們不會對這個函數進行過多討論。關於SAC唯一有趣的一點是,如果SigningLevel匹配以下任何一項:
尚未檢查簽名級別;
文件未簽名;
受Windows防禦措施應用程序控制策略信任;
開發者簽名代碼;
SAC結果是允許執行,然後將使用函數CipInstrumentNightsWatchAllow記錄操作。此函數可以為提供程序CodeIntegrity編寫四個基於TraceLogging的事件。具有以下名稱的NWActivityVerbose CodeIntegrity.NWActivity。
執行此函數時,將記錄QuestionableAllow或Allow。如果採用了記錄QuestionableAllow的路徑,那麼如果所需數據可用,還將寫入QuestionaleAllowSignatureInfoOriginClaimData。
由於這些是基於跟踪日誌記錄的事件,我們需要使用一些特殊辦法來捕獲跟踪。值得慶幸的是,Matt已經做了所有艱苦的工作來研究和記錄這類事件的過程。看了他的文章《Windows RE使用WPP和TraceLogging》 後,我們可以使用powershell中的以下4行代碼來啟動ETW會話,該會話將捕獲NWActivity和NWActovityVerbose提供程序。
開始跟踪並使用一些應用程序/安裝程序後,你應該有一個可以用EventViewer打開的EventLog,你可以發現防禦措施最終信任ProcessHacker之類的事情。
總結就個人而言,我認為微軟為提高操作系統的安全性而採取的措施是很好的,其最終目標是讓用戶更加安全。另一方面,我確實看到了SAC和Windows 10 S之間的一些相似之處。對於SAC,當設置為強制時,限制由具有數字簽名的應用程序設置,如果沒有簽名,則由防禦措施雲認為可信的應用程序進行設置。
第一種選擇,即使你知道數字簽名可以很好地驗證應用程序,許多開源項目或自由開發者負擔不起,不幸的是,這給開發者帶來了一些限制。
第二個選項,即對“智能雲安全服務”的查詢,這也是我希望微軟提供更多信息的地方,因為基本上應用程序能否運行的決定將完全取決於微軟。