This challenge came with two files: a binary without an extension and a pcap file. The binary was probably going to be a Linux-executable, and indeed:

$ file aart_client
aart_client: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.24, BuildID[sha1]=220420b2d90546e195ca6df0119e299f3ad28514, stripped

Looking at the libraries used by the executable, I got the first clue:

$ ldd aart_client
        linux-vdso.so.1 =>  (0x000074f893b1b000)
        libprotobuf.so.8 => /usr/lib/x86_64-linux-gnu/libprotobuf.so.8 (0x000074f89380d000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x000074f893446000)
        /lib64/ld-linux-x86-64.so.2 (0x000074f893b1c000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x000074f893228000)
        libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x000074f89300e000)
        libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x000074f892c86000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x000074f89297b000)
        libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x000074f892764000)

The executable is using Google’s protocol buffers, a standardized format for serializing data.

The pcap file contains 4 HTTP POST-requests and responses. I tried to decode this data, but it turns out you need a .proto file which describes the data structure to be able to decode protocol buffer data, so that didn’t work.

Running the executable says Missing server address!, so I let it connect to netcat to see what happens.

~# nc -l 80 &
[1] 3802
~# ./aart_client 127.0.0.1
POST / HTTP/1.1
Host: 127.0.0.1
User-Agent: Roll
Accept: */*
Content-Length: 86
Content-Type: application/x-www-form-urlencoded

004C4C48451A057A76637663716F6A6C656F78657A7473626D696D6B617A71677A65726374727412200864

That’s the same request as the first request in the pcap file, so I wrote a little PHP script to play the response back to the client. First; the client kept crashing. Turns out, the client really wants CRLF line-endings (as shown in the pcap file) and after the first request, it immediately opens another connection to do another request. Once that was all set up, the client printed some ASCII-art:



             _     _
            /_|   |_\
           //||   ||\\
          // ||   || \\
         //  ||___||  \\
        /     |   |     \    _
       /    __|   |__    \  /_\
      / .--~  |   |  ~--. \|   |
     /.~ __\  |   |  /   ~.|   |
    .~  `=='\ |   | /   _.-'.  |
   /  /      \|   |/ .-~    _.-'
  |           +---+  \  _.-~  |
  `=----.____/  #  \____.----='
   [::::::::|  (_)  |::::::::]
  .=----~~~~~\     /~~~~~----=.
  |          /`---'\          |
   \  \     /       \     /  /
    `.     /         \     .'
      `.  /._________.\  .'
        `--._________.--'

Great, that’s something! But it’s not a flag.. I tried to replay the next two responses from the pcap file, and behold:

~$ ./aart_client 127.0.0.1
CTF{That-was-a-lot-of-monkey-foot-work?-Good-Job!}

There’s our flag! Solution code is on Github.