now think about what you've done

2018-01-22
New HTML Experiments

So I’ve recently had a few automation random ideas. The problem was that it was such a small automation and I wanted it to be useable anywhere, so I wrote it in a single HTML page and the code is in Javascript.

Read More

2016-08-21
My First ScreenSaver - an obsession in VB6

So back when I first started writing code, I was had this obsession with screen savers. I don’t really know why but I loved screen savers that were not repetitive, ones that changed over time and did something. Like any of the following:

…and my personal favorite:

but nowadays I don’t download screen savers unless I can compile from source…

anyways, at one time I attempted to create my own in VB (why VB…well that’s a post in itself) based on the Space Combat screen saver, but I didn’t have fancy graphics. So I used basic sprites and freely available images found on various corners of the InterTubes:

AGX-04 Deathstar Easter Bunny Ghost 2 H2o Happy Face Hitchhiker's Guy LOMPSTER M Falcon MA-04X Pac Ghost Radish RB-79 Slave 1 Space Ship Sunburst

If you want to take a look you can download it, or with the VB source

Read More

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