2016 Palo Alto Labyrenth CTF Doc 04

Article Date

2016 Aug 15

Ok, so the fourth challenge is again a zip file (hash: 1A2570D5CC6E2C3A185E939DC49CB4B908B867E02AC84BF7ABB532B3395FB01A) and it contains a file fun.docm (hash: 4AE794A701D2F28BA7E6292F0463444F6A567CB7C26188A518270544252877FB). Now the first thing you need to know about the newer office file formats is that they are all zip files. So yes a DOCM and a XLSX and a PPTX, etc are all ZIP files with various contents pieces inside (see here for other zip based documents)

SIDENOTE: this is one of the very reasons that I wrote my FileId tool to begin with. Most file identification apps don’t go very much beyond magic headers. If we understand that the magic header gives us a container format (i.e. Ole Structured Storage [OLESS], ZIP, and many others), then we can parse that container and gain much more information. This is exactly what FileId does it understands OLESS files and ZIP files and has some ideas what to look for inside to figure out its true file type.

SIDE-SIDENOTE: Of course since its a container then we can do nasty things that were never intended to be done…like having a DOC, XLS, PPT all in a single file and all open completely different content depending on which app is opening it.

ok, back to the challenge at hand and DOCM file! we can verify its a DOCM by running it through FileId or we can simply run 7zip and extract the contents…which is what I did. Since its truly a DOCM we will find a file inside the WORD subfolder named vbaProject.bin (it actually doesn’t have to be named this, but I digress). I also happen to know that this is also an OLESS file, so again we can run it through FileId, but there is a known bug in FileId here…

So here we have a couple of choices as what to do next, but the underlying principle is to get to the VBA…here are several options (I did them all):

  1. use olevba.py in OleTools by Philippe Lagadec
  2. use the office object model to open and save the file in the DOC format (won’t run macro, but will maintain them)
  3. unzip the DOCM, edit the vbaProject.bin to remove the protections and alter the autorun functionname (how to do this will be covered in the DOC 05 writeup)

So lets assume you did one of those, you’d get the following macro parts:

=ThisDocument=

#If VBA7 And Win64 Then
Private Declare PtrSafe Function jFlnz8 Lib "winmm.dll" Alias "sndPlaySoundA" _
       (ByVal lpszSoundName As String, ByVal uFlags As Long) As Long
#Else
Private Declare Function jFlnz8 Lib "winmm.dll" Alias "sndPlaySoundA" _
       (ByVal lpszSoundName As String, ByVal uFlags As Long) As Long
#End If

Public cMSuxt As Variant
Public gkKg As Object
Public cN3r As String
Public kZ4gU8sc As String
Public qa317 As Integer

Sub znOIKcDsLlMKQVsnFfWaE2bHu18RdOmKFoVb()
    Selection.WholeStory
    Selection.Font.ColorIndex = (Selection.Font.ColorIndex + 1) Mod 15
    If Selection.Font.ColorIndex Mod 2 = 0 Then
        Set gkKg = CreateObject("Excel.Application")
        gkKg.Speech.speak NpuXrzgq.Label1, True
        gkKg.Quit
    ElseIf Selection.Font.ColorIndex Mod 2 = 1 Then
        adk49an = Environ("tmp") & "\" & "asdf"
        jFlnz8 adk49an, 1
    End If
    Application.OnTime Now + TimeValue("00:00:01"), "znOIKcDsLlMKQVsnFfWaE2bHu18RdOmKFoVb"
End Sub

Private Sub UxKo3LivfGHxI2OtWa3KtqOgY6cRb5yrbR00(m4dYL, fviLw9)
    On Error GoTo NavnYIF0:
    Dim fjGeMmP8Z() As Byte
    fjGeMmP8Z = Z1yiWeP.t5ksdVMEuR2gVAPtbKyAxgbL2dy0UBt64qQG(m4dYL)
    Z1yiWeP.pZVZ0Q8ygfA6jcSJRLEKZSyv40IDQzErCpah fjGeMmP8Z, fviLw9
NavnYIF0:
    GoTo VadXU4
VadXU4:

End Sub

Private Function BqNFmKCS7cTPv9XNFOd2mCLrdqCfmdNm6HBz(dd) As Boolean
    BqNFmKCS7cTPv9XNFOd2mCLrdqCfmdNm6HBz = False
    On Error GoTo B3A:
    Dim A4xcPiKtrr() As Byte
    A4xcPiKtrr = Z1yiWeP.t5ksdVMEuR2gVAPtbKyAxgbL2dy0UBt64qQG(dd)
    BqNFmKCS7cTPv9XNFOd2mCLrdqCfmdNm6HBz = Z1yiWeP.Cj2XBWUOfIP7E9oOZKQEB0zFWe2Cf4NbfApB(A4xcPiKtrr)
B3A:
End Function

Private Function zoycqKJvqznJMeMpHe7Z61xYJfLLmbObxBVy()
    zoycqKJvqznJMeMpHe7Z61xYJfLLmbObxBVy = None
    For Each ok0I11 In ActiveDocument.VBProject.VBComponents
        l = 1
        Set gjvhSFe = ok0I11.CodeModule
        Do While l < gjvhSFe.CountOfLines
            za29rx = gjvhSFe.ProcOfLine(l, 0)
            If za29rx <> "" Then
                If BqNFmKCS7cTPv9XNFOd2mCLrdqCfmdNm6HBz(za29rx) Then
                    zoycqKJvqznJMeMpHe7Z61xYJfLLmbObxBVy = za29rx
                    GoTo CfHFE
                End If
                l = l + gjvhSFe.ProcCountLines(za29rx, 0)
            Else
                l = l + 1
            End If
        Loop
    Next ok0I11
CfHFE:
End Function

Private Sub XiqyXdC809pP5esSrC633ag92w0x6otQylY0()
    sN2l0P = zoycqKJvqznJMeMpHe7Z61xYJfLLmbObxBVy
    If Not IsNull(sN2l0P) Then
        For Each LHKwfvbUC In ActiveDocument.VBProject.VBComponents
            If LHKwfvbUC.Type = 1 Then
                HKwfvbU = 1
                Set cm = LHKwfvbUC.CodeModule
                Do While HKwfvbU < cm.CountOfLines
                    pn = cm.ProcOfLine(HKwfvbU, 0)
                    If pn <> "" Then
                        UxKo3LivfGHxI2OtWa3KtqOgY6cRb5yrbR00 pn, sN2l0P
                        HKwfvbU = HKwfvbU + cm.ProcCountLines(pn, 0)
                    Else
                        HKwfvbU = HKwfvbU + 1
                    End If
                Loop
            End If
        Next LHKwfvbUC
    End If
    zkceuV405Q5LjUp587OYxTI7OR9zTyPdvz8k
End Sub

Private Function OcbCTRJiqmq8ZHdtwfA1hsuje7UPUwkL1TcL(e2qBnJA1D, GNheMViA)
    df = Environ("tmp") & "\" & e2qBnJA1D
    Dim CiuxGXWXyEUw4() As Byte
    CiuxGXWXyEUw4 = Z1yiWeP.t5ksdVMEuR2gVAPtbKyAxgbL2dy0UBt64qQG(GNheMViA)
    Open df For Binary Access Write As #1
    Put #1, , CiuxGXWXyEUw4
    Close #1
    OcbCTRJiqmq8ZHdtwfA1hsuje7UPUwkL1TcL = df
End Function

Private Sub zkceuV405Q5LjUp587OYxTI7OR9zTyPdvz8k()
    yRQaQqmn4iZIgFxTHSbChaoJt9SxKmV7T1L5
    Selection.WholeStory
    Selection.Delete
    Selection.TypeText NpuXrzgq.Label1
    Selection.WholeStory
    Selection.Font.Size = 72
    znOIKcDsLlMKQVsnFfWaE2bHu18RdOmKFoVb
End Sub

Private Sub yRQaQqmn4iZIgFxTHSbChaoJt9SxKmV7T1L5()
    cMSuxt = Array(OcbCTRJiqmq8ZHdtwfA1hsuje7UPUwkL1TcL("asdf", NpuXrzgq.assda))
    kZ4gU8sc = NpuXrzgq.Label1
End Sub

Public Sub Document_Open()
    On Error GoTo sjjQMD:
    If ActiveDocument.VBProject.VBComponents.Count > 4 Then
        XiqyXdC809pP5esSrC633ag92w0x6otQylY0
    Else
        zkceuV405Q5LjUp587OYxTI7OR9zTyPdvz8k
    End If
sjjQMD:
    If err.Number = 6068 Or err.Number = 50289 Then
        zkceuV405Q5LjUp587OYxTI7OR9zTyPdvz8k
    Else
        Resume Next
    End If
End Sub


=Z1yiWeP=

Attribute VB_Name = "Z1yiWeP"
Function d7KRoSK5UEDh35jJNkj0TtcJjOIbmBZlyCql(JwFeyAb5x, AgkWcn As Byte) As Variant
    Dim bzTec() As Byte
    ReDim bzTec(UBound(JwFeyAb5x))
    For cz9vzhBR = 0 To UBound(JwFeyAb5x)
        bzTec(cz9vzhBR) = JwFeyAb5x(cz9vzhBR) Xor AgkWcn
    Next
    d7KRoSK5UEDh35jJNkj0TtcJjOIbmBZlyCql = bzTec
End Function

Private Sub ir0a6FeeF0LUThieRM7v6qxfWFJD1dT6BzDH()
    Dim opy7ej As VBIDE.VBProject
    Dim PiO3rcWe As VBIDE.VBComponent
    Set opy7ej = ActiveDocument.VBProject
    Set PiO3rcWe = opy7ej.VBComponents("IadnoxRap3")
    opy7ej.VBComponents.Remove PiO3rcWe
End Sub

Function YhGEH9M4EBM4CJgXjOsrcHsa(u48G As Byte, G6NK) As Variant
    YhGEH9M4EBM4CJgXjOsrcHsa = d7KRoSK5UEDh35jJNkj0TtcJjOIbmBZlyCql(G6NK, u48G)
End Function

Function lT6fYsPEvHPdOsRZuM6Mn5DTumMvEfSGHnSo(sHZF70G) As String
    TPjEpV = ""
    For cz9vzhBR = 1 To UBound(sHZF70G)
        TPjEpV = TPjEpV & StrConv(sHZF70G(cz9vzhBR), 64)
    Next
    lT6fYsPEvHPdOsRZuM6Mn5DTumMvEfSGHnSo = StrConv(sHZF70G, 64)
End Function

Function oDF26uAC8jD8UVkZDlzov3c05bVN8upeerTR(Rfn10hWpA, XPbV8Rj5Q) As Boolean
    If UBound(Rfn10hWpA) = UBound(XPbV8Rj5Q) Then
        oDF26uAC8jD8UVkZDlzov3c05bVN8upeerTR = True
        For z5PQAfu9 = 0 To UBound(Rfn10hWpA)
            If (Rfn10hWpA(z5PQAfu9) <> XPbV8Rj5Q(z5PQAfu9)) Then
                oDF26uAC8jD8UVkZDlzov3c05bVN8upeerTR = False
                z5PQAfu9 = UBound(Rfn10hWpA)
            End If
        Next z5PQAfu9
    Else
        oDF26uAC8jD8UVkZDlzov3c05bVN8upeerTR = False
    End If
End Function

Private Sub DGOoR0P7MooO533jiHhTv1sgIoOtbjkzd57H()
    Dim yQnfle As VBIDE.VBProject
    Dim TQhuHj As VBIDE.VBComponent
    Set yQnfle = ActiveDocument.VBProject
    Set TQhuHj = yQnfle.VBComponents.Add(1)
    TQhuHj.CodeModule.InsertLines 1, lT6fYsPEvHPdOsRZuM6Mn5DTumMvEfSGHnSo( _
    d7KRoSK5UEDh35jJNkj0TtcJjOIbmBZlyCql(t5ksdVMEuR2gVAPtbKyAxgbL2dy0UBt64qQG(U8pblvDZuAh8GY.TextBox1 _
    ), U8pblvDZuAh8GY.TextBox1.Left))
    TQhuHj.Name = "IadnoxRap3"
End Sub

Function bSaj5R3JtfzBByy8fhXtaHSvTG2C9luMFjIk(ToEZKjU, qSFa4f) As Variant
    Dim Qteou7() As Byte
    ReDim Qteou7(UBound(ToEZKjU))
    For Uvhtuj = 0 To UBound(ToEZKjU)
        Qteou7(Uvhtuj) = ToEZKjU(Uvhtuj) Xor qSFa4f(Uvhtuj)
    Next
    bSaj5R3JtfzBByy8fhXtaHSvTG2C9luMFjIk = Qteou7
End Function

Function Cj2XBWUOfIP7E9oOZKQEB0zFWe2Cf4NbfApB(nuQXoad42c5)
    Cj2XBWUOfIP7E9oOZKQEB0zFWe2Cf4NbfApB = False
    Dim yTV2li() As Byte
    yTV2li = Z1yiWeP.d7KRoSK5UEDh35jJNkj0TtcJjOIbmBZlyCql(nuQXoad42c5, U8pblvDZuAh8GY.HelpContextId)
    Dim VGmMTyf() As Byte
    VGmMTyf = Z1yiWeP.YhGEH9M4EBM4CJgXjOsrcHsa(Int(U8pblvDZuAh8GY.ScrollHeight), yTV2li)
    If oDF26uAC8jD8UVkZDlzov3c05bVN8upeerTR(VGmMTyf, t5ksdVMEuR2gVAPtbKyAxgbL2dy0UBt64qQG(U8pblvDZuAh8GY.Label1.Caption)) Then
        Cj2XBWUOfIP7E9oOZKQEB0zFWe2Cf4NbfApB = True
    End If
End Function

Function t5ksdVMEuR2gVAPtbKyAxgbL2dy0UBt64qQG(qqZUlc9)
    aexjT = Trim(qqZUlc9)
    Set vW3zM = CreateObject(StrReverse("tnemucoDMOD.2LMXSM"))
    Set ugBi6C = vW3zM.createElement("b64")
    ugBi6C.dataType = "bin.base" + CStr(vbUnicode)
    ugBi6C.Text = aexjT
    t5ksdVMEuR2gVAPtbKyAxgbL2dy0UBt64qQG = ugBi6C.nodeTypedValue
    Set ugBi6C = Nothing
    Set vW3zM = Nothing
End Function

Sub XWn5TNdoykQb0QoitVEG7sLOxIRSi97XmqmM(EZ9KcDzT, pNRoZP57xLx)
    Dim ang8rjzwn() As Byte
    ang8rjzwn = Z1yiWeP.d7KRoSK5UEDh35jJNkj0TtcJjOIbmBZlyCql(EZ9KcDzT, U8pblvDZuAh8GY.ScrollWidth)
    Dim upnFZMT9P() As Byte
    upnFZMT9P = Z1yiWeP.YhGEH9M4EBM4CJgXjOsrcHsa(U8pblvDZuAh8GY.Zoom, ang8rjzwn)
    Dim s06() As Byte
    s06 = Z1yiWeP.bSaj5R3JtfzBByy8fhXtaHSvTG2C9luMFjIk(upnFZMT9P, t5ksdVMEuR2gVAPtbKyAxgbL2dy0UBt64qQG(pNRoZP57xLx))
    If Z1yiWeP.oDF26uAC8jD8UVkZDlzov3c05bVN8upeerTR(s06, Z1yiWeP.t5ksdVMEuR2gVAPtbKyAxgbL2dy0UBt64qQG(StrReverse(U8pblvDZuAh8GY.Tag))) Then
        MsgBox Z1yiWeP.lT6fYsPEvHPdOsRZuM6Mn5DTumMvEfSGHnSo(EZ9KcDzT)
    End If
End Sub

Sub pZVZ0Q8ygfA6jcSJRLEKZSyv40IDQzErCpah(tnfbhVCs, AjkbXE)
    XWn5TNdoykQb0QoitVEG7sLOxIRSi97XmqmM tnfbhVCs, AjkbXE
End Sub

so there’s a bunch of stuff…now what. Well I spent waaayyy to much time deobfuscating & renaming every function to something more meaningful and useful. So I have a DOCM that is cleanedup and safe to open (i.e. no Document_Open subroutine, no passwords or anything). Get it here: 19E8BE71029D5900C54EB2213E097BC442003C1F4F5E7940B71F9902A00270FB.

like I said I spent too much time going over each function, figuring out what it does and renaming it (yes I wrote some tools for this, but they’re not ready to share).

If you look at the code in the clean-up document take a look at the last few functions in the `mod1’ module:

Sub fnCheck(fnB64Arry, customKey)
    Dim tmp1() As Byte
    tmp1 = mod1.fnSimpleXor(fnB64Arry, frm2.ScrollWidth)
    Dim tmp2() As Byte
    tmp2 = mod1.fnSimpleXor_wrapper(frm2.Zoom, tmp1)
    Dim tmp3() As Byte
    tmp3 = mod1.fnCustomXor(tmp2, fnToBase64Ary(customKey))
    
    Dim a1 As String: a1 = mod1.toString(fnB64Arry)
    Dim a2 As String: a2 = mod1.toString(tmp3)
    Dim a3 As String: a3 = mod1.toString(mod1.fnToBase64Ary(StrReverse(frm2.Tag)))
    
    If mod1.fnIsB64Identicals(tmp3, mod1.fnToBase64Ary(StrReverse(frm2.Tag))) Then
        MsgBox a2
    End If
End Sub

Sub test()
    b64 = Split("A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,0,1,2,3,4,5,6,7,8,9,+,/", ",")
    customKey = "yRQaQqmn4iZIgFxTHSbChaoJt9SxKmV7T1L5"
    Dim tmp() As Byte
    Dim strBase As String: strBase = "XJCR/DogZt7bduvvusJgAQu6QX9DmtKN+bZB"
    fnB64Arry = mod1.fnToBase64Ary(strBase)
    
    Dim tmp1() As Byte
    tmp1 = mod1.fnSimpleXor(fnB64Arry, frm2.ScrollWidth)
    Dim tmp2() As Byte
    tmp2 = mod1.fnSimpleXor_wrapper(frm2.Zoom, tmp1)
    Dim tmp3() As Byte
    tmp3 = mod1.fnCustomXor(tmp2, fnToBase64Ary(customKey))
        
    MsgBox mod1.toString(tmp3)
End Sub

The test subroutine is something that I put in to get the key out, but I figured all the parts and peices by going through each function and figuring out what they do, where it was pulling values from and what the values were in some cases. The only suggestion I have is get good at debugging!

After that I noticed an oddity in this fnCheck function (orginally it was named XWn5TNdoykQb0QoitVEG7sLOxIRSi97XmqmM) - it would do a check and then show a message box. Hmm, I wonder what the value would have to be in order to have the message box show? Well since I had just done a brute force exercise a few minutes eairler (see DOC 02) I started using the brute force routine to get out the expected value….but after a few minutes it hit me…wait I have the exact value its looking for… the value of ‘frm2.Tag’

so we take that value:

BZb+NKtmD9XQ6uQAgJsuvvudb7tZgoD/RCJX

reverse it and run it through and we get:

PAN{VBA=V3ryb!gAdv3n7ur3s!}

type it in the submission box

BOOM

and we get DOC 05