长期以来,大家可能认为PowerShell实际上就是System.Management.Automation.dll,但我们在这里将介绍不使用该类库前提下的PowerShell脚本执行方法,具体而言就是借助InsecurePowerShell。
不依赖powershell.exe的PowerShell脚本执行
首先,我们要对本文的标题进行一下解释。本文中的内容源自于大量有关“不依赖powershell.exe的PowerShell脚本执行”的相关研究。我们在研究中发现,powershell.exe进程只是为System.Management.Automation.dll的实现提供了一个DLL Host。而它的核心,实际上就是System.Management.Automation.dll,这也是PowerShell的真实身份。此外,还有其他本地Windows进程同样也作为PowerShell的Host,比如powershell_ise.exe。
然而,我们也可以创建自己的进程来为System.Management.Automation.dll提供Host。目前已经有一些开源项目实现了这一点,例如UnmanagedPowerShell,(https://github.com/leechristensen/UnmanagedPowerShell)、SharpPick(https://github.com/PowerShellEmpire/PowerTools/tree/master/PowerPick/SharpPick)、PSAttack(https://github.com/jaredhaight/PSAttack)以及nps(https://github.com/Ben0xA/nps)。
当然,使用PowerShell的优势之一在于,PowerShell.exe是经过微软签名的二进制文件,会被应用程序加入白名单,方便我们的使用。而自己创建的进程则不会被应用程序所信任,但是通过这样的方式,可以在powershell.exe被禁用的情况下执行PowerShell。
不使用System.Management.Automation.dll的PowerShell
在这里,我们要重点介绍另一个开源项目InsecurePowerShell(https://github.com/cobbr/InsecurePowerShell)。既然我们想要创建一个新的进程作为PowerShell的Host,就不一定再继续使用System.Management.Automation.dll,我们可以对其进行修改,并为修改后的版本提供Host。另外,希望大家了解的是,PowerShell目前新加入了很多安全特性,特别是在v5版本中,其中包括:脚本块日志(ScriptBlock Logging)、模块日志(Module Logging)、转录日志(Transcription Logging)、反恶意软件扫描接口(AMSI)、受限语言模式(Constrained Language Mode)等。而上述所有这些安全功能,都是在System.Management.Automation.dll中实现的。
我们理想的System.Management.Automation.dll,最好是带有最新版本的PowerShell支持的全部功能,同时没有任何安全防护功能。我们如何得到这样的修改后版本呢?事实上,InsecurePowerShell就可以做到这一点。所以到现在,大家应该已经理解了我们标题的含义,所谓的“不使用” System.Management.Automation.dll,实际上是不使用默认的System.Management.Automation.dll。
InsecurePowerShell是开源项目PowerShell Core v6.0.0的一个分支,仅对其进行了一些修改。InsecurePowerShell从PowerShell中删除了下列安全功能:
AMSI:InsecurePowerShell不会将任何PowerShell代码提交给AMSI,即使是在有主动监听的反恶意软件产品(AntiMalware Provider)的情况下。
PowerShell日志记录:InsecurePowerShell将禁用脚本块日志、模块日志和转录日志。即使已经在组策略中启用这些日志记录,也会在InsecurePowerShell中被忽略。
语言模式:InsecurePowerShell始终以全语言(Full Language)模式运行PowerShell代码。如果尝试将InsecurePowerShell设置为约束语言(Constrained Language)、限制语言(Restricted Language)等备选语言模式,实际上将不会产生任何作用。
ETW:InsecurePowerShell不使用ETW(Windows的事件跟踪)。
使用方法
InsecurePowerShell的编译方式与PowerShell Core版本完全相同,所以我们可以通过完全一样的方式使用。InsecurePowerShell的发行版本中包含一个名为pwsh.exe的二进制文件,该文件就是PowerShell.exe的替代,和标准PowerShell和新版本的用法相同。我们可以以交互的方式使用,也可以非交互式地借助-Command或者-EncodedComand参数使用。
以下是如何使用pwsh.exe的示例:
PS
C:InsecurePowerShell> .pwsh.exe
PowerShell
v6.0.0-rc.2-67-g642a8fe0eb0b49f4046e434dc16748ea5c963d51
Copyright
(c) Microsoft Corporation. All rights reserved.
https://aka.ms/pscore6-docs
Type
'help' to get help.
PS
C:InsecurePowerShell> $Execution.SessionState.LanguageMode =
'ConstrainedLanguage'
PS
C:InsecurePowerShell> $Execution.SessionState.LanguageMode
FullLanguage
PS
C:InsecurePowerShell> Get-WinEvent -FilterHashtable
@{ProviderName="Microsoft-Windows-PowerShell"; Id=4104} | % Message
Creating
Scriptblock text (1 of 1):
.pwsh.exe
ScriptBlock
ID: 877d94f3-4bb5-4a26-88e3-58bb8091e1d8
Path:
Creating
Scriptblock text (1 of 1):
prompt
ScriptBlock
ID: 72983606-2c4d-4266-808c-280c718550c4
Path:
InsecurePowerShellHost
除了这个与powershell.exe非常相似的复制版本pwsh.exe之外,我还创建了一个名为InsecurePowerShellHost的.NET Core应用。正如大家看到的那样,InsecurePowerShellHost是在InsecurePowerShell创建的应用,用于为修改后的System.Management.Automation.dll提供Host。InsecurePowerShellHost只能借助–Command和–EncodedCommand参数非交互使用。在InsecurePowerShell上,使用InsecurePowerShellHost的主要优势是,相比于InsecurePowerShell的完整构建,它是一个更为轻量级的工具。
以下是如何使用InsecurePowerShellHost的示例:
PS
C:InsecurePowerShellHost> .InsecurePowerShellHost.exe
usage:
InsecurePowerShellHost.exe [--EncodedCommand encoded_command | --Command
command]
PS
C:InsecurePowerShellHost> .InsecurePowerShellHost.exe --Command
"`$Execution.SessionState.LanguageMode = 'ConstrainedLanguage';
`$Execution.SessionState.LanguageMode"
FullLanguage
总结
InsecurePowerShell和InsecurePowerShellHost是非常简单的概念,并没有太多突破性的技术。同时,它还存在着一些缺点,应该不会被广泛应用于实际攻防场景之中。然而,我想要证明的一点是,我们可以创建一个定制版本的PowerShell,在无法将自己的应用程序加入白名单的情况下,转换一种思路,使用不包含安全特性的应用程序。我认为,InsecurePowerShell很好地证明了这一观点。
在这种思路的引导下,让我们来谈谈使用InsecurePowerShell的优缺点。
InsecurePowerShell的优点
1. 不包含安全功能的PowerShell:这是目前它最大的优势所在,InsecurePowerShell能够运行不具有安全功能的PowerShell,没有AMSI、脚本块记录、模块记录和转录记录。
2. 具有良好的兼容性:作为.NET Core应用程序,我们可以在Windows 7 SP1、Windows 8.1、Windows 10、Windows Server 2008 R2 SP1、Windows Server 2012和Windows Server 2016上运行InsecurePowerShell。
3. 具有PowerShell Core 6.0版本的全部功能:作为攻防人员,我们为了避免PowerShell的安全特性,最常使用的是PowerShell的2.0版本。但借助于InsecurePowerShell,我们就不再受到版本的限制,可以畅通无阻地使用6.0版本的所有功能。
InsecurePowerShell的缺点
1. 需要接触到磁盘:作为.NET Core应用程序,我们不仅需要将二进制文件放到磁盘上,同时还需要放置支持.NET Core所需的DLL文件。尽管这些文件大多是经过微软签名的,但我们还是更倾向于尽量减少对磁盘的接触。事实上,InsecurePowerShell完全不符合攻击过程中的“离地原则”。
2. 不使用应用程序白名单:InsecurePowerShell不会使用一个强大的应用程序白名单作为解决方案,因此我们也失去了powershell.exe的一个巨大优势。
3. PowerShell Core并不是Windows PowerShell:我们要知道,InsecurePowerShell是PowerShell Core的一个分支,并不是Windows PowerShell。而Windows PowerShell和PowerShell Core之间,并不会进行功能校验。因此,可能会在使用InsecurePowerShell的过程中出现一些实际问题,预先准备的PowerShell工具可能无法在PowerShell Core中正常工作。
防护方式
InsecurePowerShell和InsecurePowerShellHost都需要将二进制和DLL文件放入磁盘。因此,只需要将修改后的System.Management.Automation.dll加入黑名单,就能够实现防护。并且,你也可以同时将旧版本的System.Management.Automation.dll加入黑名单,特别是攻击者经常使用的2.0版本,这样就多了一份保障。
尽管,黑名单是一个快速、简单的防护方式。但如果想要彻底进行防护,我们还需要一个应用程序白名单的解决方案。事实上,攻击者只需要重新编译一下InsecurePowerShell和InsecurePowerShellHost,就能不再受到黑名单的限制,这个过程也非常简单。
后续计划
InsecurePowershell的原理非常简单,因此我并不打算做太多的后续维护工作。但是,有一些有意思的内容可以增强我们的InsecurePowerShell,因此我可能会在以后对其展开深入研究。
1. 动态加载程序集:我将研究过程中的绝大部分精力都放在尝试在InsecurePowershell上创建一个能动态加载修改后System.Management.Automation.dll和.NET Core DLL的二进制文件,希望借此,能让InsecurePowershell作为单独的二进制文件进行分发。然而,这个过程比我预期的更为困难。目前来说,InsecurePowerShell作为一个ZIP文件存在,必须将其解压缩成多个文件后再运行。在以后,我将会继续这方面的研究,目标是让其变成只有一个文件。
2. PowerShell Core代理:假如我们拥有一个完整的PowerShell C2代理,可以与PowerShell Core兼容,会让我们的实际使用过程非常方便。然而,由于Windows PowerShell和PowerShell Core之间没有功能校验机制,会导致大多数已有的PowerShell C2代理出现问题。 我打算对该问题进行研究,并尝试解决。
InsecurePowerShell的源代码请参见:https://github.com/cobbr/InsecurePowerShell ,InsecurePowerShellHost的源代码请参见:https://github.com/cobbr/InsecurePowerShellHost 。
发表评论
您还未登录,请先登录。
登录