Unfortunately I wasn’t able to attend BSides London this year - otherwise there would probably be a DFIR.IT on Tour entry somewhere on the blog. Recently I haven’t got a lot of time to play with any DFIR challenges but when one of the guys at work mentioned about BSides Toxic PDF I decided to give it a try.
The door
Toxic PDF instruction states: “Don’t be afraid to walk through the door (if you can)…”
After opening the crackme.pdf
the following screen appears:
Door would open only when correct key is entered. But where can we find the key?
Whenever I need to analyze maldocs, malicious scripts, phishing emails my go-to platform is REMnux. I can’t emphasize how cool it is to have all the tools for reversing and malware analysis at one place!
Let’s crack on with the PDF analysis. For this we’ll use great tool peepdf created by Jose Miguel Esparza.
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 |
|
Usually when analyzing malicious PDF documents objects like AcroForm, AA(Additional Actions) or JavaScript are the the most interesting to look at. As object 913
is on both AA and JS lists it seems to be a good starting point.
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 |
|
Based on the above output we can see that Click to open the door
action is handled by JavaScript object 904
. This may include some sort of password validation 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 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
|
Obfuscated code! That looks suspicious. Let’s dump it and look if we can deobfuscate the code.
1
|
|
The key
One of my favourite tools to analyze JavaScript is SpiderMonkey which is a JavaScript engine. It’s an easy way to run blocks of code to see what will be the result.
For instance in the above code, functions mmu7d()
and mz821a()
are used for string manipulation. You can put those functions into a file decode.js
, then load the file into SpiderMonkey.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
This makes our code more readable:
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 |
|
It seems that last line of the code invokes all the functions. Let’s break it down:
as6z + hanm4
concatenates string variablesh7()
invokesunescape()
enx(dstring,key)
decodesstring
with akey
my6()
invokeseval()
To see the results just comment out the following code and print()
the results instead of eval()
:
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Now run it in SpiderMonkey:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
Condition included in raven()
function reveals that the key is comprised of the value of the e
field and the word antistring
.
What is the e
field value and where we can find it?
Let’s go back to the object 913
. Fields name seem to be defined with /T
, for instance:
/T(door)
/T(msg)
/T(door2)
If we look closer /T(e)
is present in the output of the object 913
.
Next to it, there is a value /V
of 9053d91a70acfd6614f0243caac70ce2
.
1 2 3 4 |
|
Well, it turns out that 9053d91a70acfd6614f0243caac70ce2antistring
is our key.
Bonus
During the initial analysis peepdf
reported two JS objects (880, 904). We already know everything about object 904
. What about the other one?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
|
This object also includes an obfuscated string. It took me a while to realize what it is. whisper()
seems to be another decrypting routine that accepts string to be decrypted and key as parameters. We have the message (pluto
) and now we know the key right? What if…
1 2 3 4 5 6 7 8 9 10 |
|
Thank you BSides London and thank you Liviu Itoafă for creating this challenge. I am still not sure if this is the right way to solve the challenge but it was fun!