导语:WDEG ASR虽然很好,但它却不能提供EMET ASR规则所提供的配置粒度。为了弥补这一差距,Windows Defender应用程序控制引入了在特定进程中阻止模块的功能。

介绍

使用EMET 5中的攻击面减少(ASR)功能的人可能会很喜欢这个功能,因为它能够轻易的阻止在指定的进程中加载特定的DLL。例如,作为针对Casey Smith的regsvr32.exe脚本攻击的缓解措施,NSA IAD发布了一个很好的EMET ASR规则集,来阻止在regsvr32.exe上下文中加载scrobj.dll。

从Windows 10 1709开始,EMET 不再受支持,因为它已被Windows Defender Exploit Guard(WDEG)所取代。WDEG也有自己的功能,称为攻击面减少,这个功能是阻止Office套件产品创建可疑的子进程的好方法,但它不允许你指定自定义的阻止规则,而且还依赖于Windows Defender反病毒软件。WDEG ASR虽然很好,但它却不能提供EMET ASR规则所提供的配置粒度。

据推测,为了弥补这一差距,Windows Defender应用程序控制(以前称为Device Guard)引入了在特定进程中阻止模块的功能。

好的一面:是一种相当可靠的阻止滥用DLL的方案

以下文件是建立一个非常简单的阻止regsvr32.exe加载scrobj.dll的规则集,可以在三行代码中完成:

$ScrObjBlockRule = New-CIPolicyRule -DriverFilePath $Env:windir\System32\scrobj.dll -Level FileName -Deny -AppID $Env:windir\System32\regsvr32.exe    

# Merge the block rule into the allow all template rule included in the OS    
Merge-CIPolicy -OutputFilePath CustomASRPolicy.xml -PolicyPaths $Env:windir\schemas\CodeIntegrity\ExamplePolicies\AllowAll.xml -Rules $ScrObjBlockRule    

# This must be run elevated. Convert the policy to binary form and copy it to where WDAC will consume it.    
ConvertFrom-CIPolicy -XmlFilePath .\CustomASRPolicy.xml -BinaryFilePath $Env:windir\System32\CodeIntegrity\SIPolicy.p7b    

# Now reboot and the policy will take effect.

作为参考,这些命令将生成以下XML WDAC策略:

<?xml version="1.0" encoding="utf-8"?>    
<SiPolicy xmlns="urn:schemas-microsoft-com:sipolicy">    
<VersionEx>10.0.0.0</VersionEx>    
<PolicyTypeID>{A244370E-44C9-4C06-B551-F6016E563076}</PolicyTypeID>    
<PlatformID>{2E07F7E4-194C-4D20-B7C9-6F44A6C5A234}</PlatformID>    
<Rules>    
<Rule>    
<Option>Enabled:Unsigned System Integrity Policy</Option>    
</Rule>    
<Rule>    
<Option>Enabled:Advanced Boot Options Menu</Option>    
</Rule>    
<Rule>    
<Option>Enabled:UMCI</Option>    
</Rule>    
<Rule>    
<Option>Enabled:Update Policy No Reboot</Option>    
</Rule>    
</Rules>    
<!--EKUS-->    
<EKUs />    
<!--File Rules-->    
<FileRules>    
<Allow ID="ID_ALLOW_A_1_0" FriendlyName="" FileName="*" />    
<Allow ID="ID_ALLOW_A_2_0" FriendlyName="" FileName="*" />    
<Deny ID="ID_DENY_D_1_1" FriendlyName="C:\Windows\System32\scrobj.dll FileRule" FileName="scrobj.dll" MinimumFileVersion="65535.65535.65535.65535" AppIDs="REGSVR32.EXE" />    
</FileRules>    
<!--Signers-->    
<Signers />    
<!--Driver Signing Scenarios-->    
<SigningScenarios>    
<SigningScenario Value="131" ID="ID_SIGNINGSCENARIO_DRIVERS_1" FriendlyName="Auto generated policy on 01-25-2018">    
<ProductSigners>    
<FileRulesRef>    
<FileRuleRef RuleID="ID_ALLOW_A_1_0" />    
</FileRulesRef>    
</ProductSigners>    
</SigningScenario>    
<SigningScenario Value="12" ID="ID_SIGNINGSCENARIO_WINDOWS" FriendlyName="Auto generated policy on 01-25-2018">    
<ProductSigners>    
<FileRulesRef>    
<FileRuleRef RuleID="ID_ALLOW_A_2_0" />    
<FileRuleRef RuleID="ID_DENY_D_1_1" />    
</FileRulesRef>    
</ProductSigners>    
</SigningScenario>    
</SigningScenarios>    
<UpdatePolicySigners />    
<CiSigners />    
<HvciOptions>0</HvciOptions>    
<Settings>    
<Setting Provider="PolicyInfo" Key="Information" ValueName="Name">    
<Value>    
<String>AllowAll</String>    
</Value>    
</Setting>    
<Setting Provider="PolicyInfo" Key="Information" ValueName="Id">    
<Value>    
<String>041417</String>    
</Value>    
</Setting>    
</Settings>    
</SiPolicy>

这个XML策略将允许所有的用户和内核模式代码运行,当加载程序试图将scrobj.dll加载到regsvr32.exe内存空间时,不会去考虑scrobj.dll的签署者是谁。

重新启动后,策略将生效,scrobj.dll将被阻止加载到regsvr32.exe中,并且将生成Microsoft-Windows-CodeIntegrity / Operational 3077事件。例如,运行以下命令将相应地生成代码完整性事件:

regsvr32 /s /n /u /i:Backdoor.sct scrobj.dll

image.png

代码完整性事件ID 3077指示scrobj.dll被阻止加载。

隐形攻击者可能会尝试通过执行以下操作来逃避检测:

1.将regsvr32.exe复制到攻击者控制的位置,并将其重命名为看起来正常的文件名 —— 例如notepad.exe

2.将Backdoor.sct重命名为看起来正常的文件名称并删除sct扩展名。

3.将scrobj.dll复制到攻击者控制的位置,并将其重命名为blah.txt

这种规避策略很可能会规避那种针对检测恶意regsvr32使用的命令行日志记录。一个规避调用的示例可能如下所示:

notepad /s /n /u /i:foo blah.txt

令攻击者惊讶的是,这个规避姿势的企图也被阻止了。

image.png

尽管重命名了所有二进制文件,但是成功阻止了攻击的原因是因为阻止规则是基于嵌入在PE资源中的OriginalFileName属性。该规则不考虑磁盘上的文件名。

所以我们现在有一种方法可以有效地阻止加载到我们所选择的进程中的指定的DLL。

坏的一面:绕过阻止规则

考虑到生成的策略允许所有的代码运行,无论在regsvr32.exe的上下文中的scrobj.dll的签署者是谁,目前没有什么方法可以防止攻击者更改OriginalFileName属性中的“scrobj.dll”。 在重命名的blah.txt文件中,“scrobj.dll”的OriginalFileName属性被简单地改为“tcrobj.dll”,果然,scrobj.dll规则被规避了,如下面的procmon事件详细信息所证明的那样:

image.png

scrobj.dll阻止规则绕过

一种可能的缓解措施是在Windows Defender Exploit Guard中严格加载regsvr32.exe中仅限微软签名的二进制文件:

image.png

尽管在regsvr32.exe的上下文中阻止了scrobj.dll的修改版本(因为修改后,它们的签名将不再有效),但这些规则仅适用于文件名,这意味着如果攻击者将regsvr32.exe重命名为任何其他文件名,例如notepad.exe,那么使用WDEG缓解措施将变得无效。

阻碍

在所有操作系统SKU上均可使用EMET ASR的情况下,必须在Windows 10 Enterprise SKU上配置Windows Defender应用程序控制规则。对于任何想要仅使用WDAC来阻止来自特定进程的模块的人来说,这可能是一个主要的阻碍。

另一个问题是,因为你正在处理WDAC用户模式规则,所以用户模式代码完整性将被强制执行,这意味着PowerShell将被置于受限语言模式。我认为我可以使用Set-RuleOption cmdlet 设置“Disabled:Script Enforcement”策略规则选项,但是由于受限语言模式仍然有待强制执行,因此它看起来没有太大意义。

结论

使用Windows Defender应用程序控制模块阻止规则,是阻止那些攻击技能比较幼稚的攻击者将目标DLL加载到特定进程中的一种有效方式,但对于利用规避策略的攻击者无效。让阻止规则变得健壮的唯一的可能方式就是将它们与实际的WDAC白名单策略结合起来,原因如下:

1、尽管攻击者重命名了regsvr32.exe,但在scrobj.dll中修改OriginalFileName将始终被阻止。

2、通过适当的应用程序白名单强制执行,期望应该是适用于PowerShell的规则,在这种情况下,会在受限语言模式中执行。

3、还有很多其他的攻击变种,其中脚本可以执行并且scrobj.dll可以被用于除regsvr32.exe以外的其他进程,例如mshta,rundll32等。这将需要进行测试,但只是阻止scrobj.dll可能是有意义的,在这种情况下,你只需要编写一个适用于全局的标准的WDAC拒绝规则。全局拒绝规则的例子可以在这里找到。

因此,可以得出的最终结论是,模块阻止规则仅对那些已经部署了强大的WDAC白名单策略的用户有利。另外,现在应该清楚的是,与EMET ASR规则所使用的规则没有直接的平行关系。而这不一定是坏事,希望EMET ASR规则能相应地设置均势的期望。也许最终有一天,微软将在Windows的所有SKU上开放WDAC策略配置。

我的总体建议是不要单独使用WDAC模块阻止规则——即允许所有用户/内核模式规则同时使用。通过所有的方法来规避这些规则,这些规则只有在适当的WDAC白名单策略中才有意义。如果你想了解更多关于WDAC / Device Guard的信息,请阅读微软的官方文档并阅读我之前写的许多关于Device Guard 的文章中的这一篇。

源链接

Hacking more

...