2016 Palo Alto Labyrenth CTF Doc 03

Article Date

2016 Aug 15

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:

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

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

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:

object 11

and get:

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):

{
  ...

  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:

<< /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:

PAN{g0obygo0byd00wh3r3ru?}

enter it in and

BOOM

we get document #4