安全路透社
当前位置:安全路透社 > 网络转载 > 正文

应用程序白名单和受限Powershell绕过方法详解

对于Windows 7和8.1,很容易利用Powershell并通过反射PE注入绕过应用程序白名单,但Windows 10就不同了。Windows 10中激活了Powershell受限语言模式,再加上AppLockr,上述方法似乎不再行得通。当然,我们可以将PowerShellEmpire作为攻击框架,并采用HTML应用程序攻击向量,但在Powershell受限语言模式为启用状态下,这种攻击颇费周折。那到底还能否采用反射PE注入攻击方法呢?让我们一探究竟。

HTA攻击

我们先简单说一下HTML应用程序作为攻击向量和Powershell Empire的工作原理。在启动Powershell Empire并创建一个监听器之后,我们创建一个HTA stager,并简单地设置监听器名称和输出文件:

1.png

我们把它放在一个可以从受害者机器访问的网络服务器上。 HTA文件包含以下代码:

2.png

由于HTA文件在浏览器沙箱外部打开,因此允许ActiveX对象执行。其只是用base64编码的命令(拉取另一个更大的Empire代理并在内存中执行)启动Powershell。受害者浏览链接并看到:

3.png

然后看到:

4.png

单击运行后发生回调,Empire在受害者机器上启动一个新代理:

5.png

AppLocker和Powershell受限语言

本文讨论的是在AppLocker和“Powershell受限语言模式”为启用状态下如何通过HTA文件获得Empire代理。在此之前先强调一下攻击者获得的结果。如果尝试在计算机上运行一个恶意软件,比如名为Malware.exe的恶意软件,将得到以下提示:

6.png

如果尝试在Powershell中使用.NET组件运行命令,如下所示其被阻止:

7.png

同样,如果像之前一样使用HTA尝试启动相同的攻击,其也将被停止:

8.png

因受限语言模式,我们从Powershell获得了相同的错误。 我们现在必须围绕这一点想办法。

不用Powershell的Powershell

对不使用Powershell.exe运行Powershell命令我们已有研究。想法是,Powershell.exe其实只是.NET程序集System.Management.Automation的一个解释器,完全有可能编写我们自己的解释器来调用该程序集。我们面临的问题是应用程序白名单的存在,因此我们需要以某种方式启动我们的自定义解释器。此外,这个解释器必须运行在一些进程空间,最好把它注入一个现有的进程,而不是创建其自己的进程(代理在使用时其必须保持运行)。我们不妨利用PowerPick项目,其中包含一个名为ReflectivePick的模块,这是一个C ++应用程序,被编译为单个DLL并从System.Management.Automation调用自定义运行空间,这样一来就允许执行Powershell命令。

为了开始测试,我们使用一条简单的命令编译ReflectivePick DLL,以便在运行空间中执行,如下所示:

9.png

我们然后通过使用来自加入白名单的文件夹的rundll32运行ReflectivePick DLL,获得如下结果:

10.png

Powershell命令被执行,更重要的是,虽然AppLocker将Powershell.exe锁定为受限语言,但运行空间的语言模式是FullLanguage。

我们用此更新了argument参数,以包含之前的base64编码的Powershell Empire stager,以及一个解码例程,因为我们不再使用编码参数。我们还将解码的命令记录到了一个文件中,以便能够进行调试。完整命令如下所示:

11.png

从命令行运行更新后的DLL可在文本文件中显示解码的Empire stager:

12.png

一个Empire代理被启动:

13.png

转到其他进程

到目前为止,我们是通过rundll32.exe创建一个新进程,并将DLL加载到其中。这不是一个可行的方法,因为DLL不在白名单中,还有,我们是在创建一个新进程。为了避免这两个问题,我们可以使用Powershell脚本Invoke-ReflectivePEInjection将ReflectivePickDLL加载到另一个进程中。这样无疑会产生在受限语言模式为启用状态下启动Powershell脚本的问题,不过我们稍后再讨论这一点。Invoke-ReflectivePEInjection为我们的用例使用两个参数,即作为字节数组的DLL和要注入的进程的进程ID(PID)。我们想将ReflectivePick DLL注入到explorer进程,所以我们先找到其PID:

14.png

然后我们获得ReflectivePick DLL的内容——字节数组,如下所示:

15.png

Invoke-ReflectivePEInjection脚本作为一个函数编写,因此我们首先导入模块,确保将其放在白名单文件夹中,以暂时避免“受限语言”。然后使用PID和DLL调用它:

16.png

我们注意到,Empire stager创建了调试文本文件,如下所示,我们成功地让代理从explorer进程内运行:

17.png

让我们将用于从DLL获取PID和字节的命令嵌入到Powershell脚本中,并调用该函数,这样我们就不需要先导入它。这通过在脚本文件的末尾添加以下内容来实现:

18.png

然后我们运行没有任何参数的Powershell脚本文件:

19.png

然后我们获得我们的Empire代理回调:

20.png

我们仍然面临着ReflectivePick DLL是磁盘上的外部文件的问题,所以我们将它嵌入到Powershell脚本中。这是通过将DLL字节编码为base64来实现的,如下所示:

21.png

然后将编码文件的内容复制到Powershell脚本中并分配一个变量:

22.png

我们不是从磁盘获取文件的字节,而是通过base64解码变量的内容获得:

23.png

我们再一次收到Empire代理:

24.png

从InstallUtil.exe调用Powershell

原则上,我们还没有实现任何东西,因为我们现在使用Powershell将DLL加载到调用Powershell的内存中,“受限语言模式”仍将阻止它。但是,我们已经确定,Powershell执行发生在现有进程而不是新进程内。因“受限语言模式”的阻止,我们确实需要克服调用Invoke-ReflectivePEInjection的问题。为实现这一点,我们使用InstallUtil.exe运行自定义EXE,这会创建一个非托管Powershell运行空间。

我们将代码修改为只执行一个预定义的命令,开始只是一些虚设代码,目的是确保其按如下所示有效:

25.png

将此编译为名为Bypass.exe的EXE并尝试在受害者机器上运行,其明显被AppLocker阻止。

26.png

然后我们运行InstallUtil.exe,以使用命令行参数执行卸载方法:

27.png

从上面的图片我们可以看到,命令被执行,且自定义Powershell运行空间没有启用“受限语言模式”。从这里,我们将测试命令更改为整个Invoke-ReflectivePEInjection脚本以及我们之前添加的嵌入式DLL和启动命令。我们面临另一个困难,Powershell在新行或分号处打断命令。Invoke-ReflectivePEInjection是用新行创建的,但是将它嵌入到C#项目中需要它在一行中,为此我们首先对整个文件进行base64编码,如下所示:

28.png

然后将其与base64解码例程一起嵌入到EXE中:

29.png

我们还将解码的Powershell命令写入test5.txt文件,以确保其可以正常工作。对更新的代码运行InstallUtil.exe可以得到:

30.png

Invoke-ReflectivePEInjection脚本被解码并保留其新行,此外,Empirestager也被写入其调试文件。Empire代理成功启动,如下所示:

31.png

调用InstallUtil.exe

到目前为止,我们成功将Powershell受限语言模式的绕过转换为了EXE文件的AppLocker绕过。虽然我们也成功地执行了EXE,但我们仍然需要一些方法调用InstallUtil.exe和下载EXE到磁盘。为实现这一点,我们将使用Regsvr32.exe。

Regsvr32.exe可以用来执行scriptlet——其可以包含任意JavaScript。所以,开始我们先欺骗,仍然让EXE在磁盘上,但从Regsvr32.exe运行的脚本片段执行InstallUtil.exe:

32.png

运行后显示如下:

33.png

这给了我们一个Empire代理回调:

34.png

现在你可能想知道为什么要使用Regsvr32.exe启动InstallUtil.exe,因为这样并没有真正获得什么。不过,关键是Regsvr32.exe也可以用来下载EXE到磁盘,此外,脚本片段文件也可以存储在web服务器上,如下图所示:

35.png

下载文件

为测试通过Regsvr32.exe下载,我们base64编码了一些虚设文本:

36.png

然后,我们使用另一种滥用certutil.exe以解码并将其写入磁盘的方法。base64编码文本放在BEGIN CERTIFICATE和END CERTIFICATE标签中,以给certutil.exe提供正确的格式。然后我们将base64编码文本写入文件,然后使用certutil.exe解码,如下所示:

37.png

按以下方式执行:

38.png

文件的内容明显被解码。现在是时候进行一些微调了,现在我们将提供的EXE嵌入InstallUtil.exe。因此,我们在另一台计算机上使用certutil.exe对其进行编码:

39.png

为了让base64能覆盖多行,我们在每一行末尾添加一个反斜线:

40.png

在测试时,事实证明不能在一个脚本片段中嵌入整个编码的EXE。所以我们将其分成了4部分,并插入到单独的脚本片段中。每个脚本片段获取嵌入的Base64代码,并将其写入一个文件,如下所示:

41.png

执行显示正在写入的文件:

42.png

我们然后创建第五个脚本片段文件,该文件获取磁盘上的四个文件,并将这四个文件组合为一个文本文件,并继续调用certutil.exe来解码它并将EXE写入磁盘:

43.png

按如下方式运行所有的脚本片段:

44.png

产生一个Empire代理回调:

45.png

要压缩这个I,通过添加以下内容将对四个从脚本片段的调用嵌入主脚本片段:

46.png

再次运行时给出Empire代理回调:

47.png

回到HTA

现在我们终于有了一个我们可以调用的单一命令,这最终可以创建我们的Empire代理。要启动该命令,我们可以将其嵌入一个HTA文件(就像AppLocker不存在一样):

48.png

指向此文件的链接按通常的方式在钓鱼邮件中发送,最终在用户浏览器中的结果是:

49.png

运行后便给予了我们期望的Empire代理——即使AppLocker和“Powershell受限语言模式”为启用状态:

50.png

结论

总而言之,该方法提供了一个来自Web服务器的HTA,其调用Regsvr32.exe来执行五个脚本片段,这五个脚本片段下载并嵌入base64编码EXE,对它进行解码并将其写入磁盘。然后执行InstallUtil.exe绕过AppLocker,并依次执行EXE的卸载方法。EXE包含一个base64编码Powershell脚本,该脚本在由EXE创建的自定义Powershell运行空间中被解码并执行。Powershell脚本包含一个嵌入的base64编码DLL,DLL被Powershell脚本解码并反射加载到explorer进程中。反射加载的DLL包含一个嵌入式base64编码的Powershell脚本,该脚本在explorer进程中的自定义Powershell运行空间内被解码并执行。Powershell脚本是Powershell Empire代理的正常stager。

要使该攻击有效,以下二进制文件需要被AppLocker列入白名单:

MSHTA.EXE

REGSVR32.EXE

CERTUTIL.EXE

INSTALLUTIL.EXE

如果使用的是默认AppLocker规则或所有Microsoft签名的二进制文件是受信任的,则这四个文件都会被列入白名单。该攻击可绕过AppLocker、“Powershell受限语言模式”及AMSI,但不能绕过ScriptBlock Logging,因此可以被检测到,如下所示:

51.png

单独代码部分的代码见GitHub

参考网站:https://improsec.com/blog//babushka-dolls-or-how-to-bypass-application-whitelisting-and-constrained-powershell

*本文作者:华为未然实验室

未经允许不得转载:安全路透社 » 应用程序白名单和受限Powershell绕过方法详解

赞 (0)
分享到:更多 ()

评论 0

评论前必须登录!

登陆 注册