code hacking, zen coding

HackYou CTF – Epic Arc 300 – CTF.EXE Writeup

In this challenge we get a Win32 console binary which just display garbage when started.

Reversing it with IDA, we see it connects to a TCP server.

I had noticed previously that the file being transfered in the Epic Arc 200 challenge was an Erlang BEAM file (compiled erlang)

This BEAM file was a TCP server. You guessed it, this is the server part for this ctf.exe, but not quite exactly the same server that on the challenge box. I will spare you the Erlang disassembly, it’s not really interesting. You can obtain it with erts_debug:df(Module).

We can still reverse enough from this BEAM file to understand what the server is doing and the client is doing in reply.

What the server part will do:

– Send a banner (17 bytes)
– Send a session key (8 bytes)
– Send a CRLF (2 bytes)
– Send “IV” (4 random bytes)
– Wait for our handshake
– Reply in an encrypted form with an error message or the flag if your handshake is correct

A correct handshake needs to be:
– “FlagRequest:omkesey” + IV + “\n\r” (this string can be found in CTF.exe)
– XOR encrypted with “_hackme_” itself XORed with the session key sends by the server

To decrypt the server reply, you use this same XOR key.

import socket
import sys

host = sys.argv[1]

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

banner = s.recv(17) # banner
print "banner=", repr(banner)

key = s.recv(8)
print "key=", key.encode("hex"), "len=", len(key)

hackme = "_hackme_"

key2 = ''
i = 0
while i < 8:
  key2 = key2 + chr(ord(key[i]) ^ ord(hackme[i]))
  i = i +1

print "key2=", key2.encode("hex")

key = key2

crlf = s.recv(2)  # \n\r
print "CRLF=", repr(crlf)

iv = s.recv(4)  # random bytes
print "IV=", iv.encode("hex")

request = "FlagRequest:omkesey" + iv + "\n\r"

print "request=", repr(request), "len=", len(request)

handshake = ''

for i in xrange(0, len(request)):
  handshake = handshake + chr(ord(request[i]) ^ ord(key[i % 8]))

print "handshake=", repr(handshake), "len=", len(handshake)
print "handshake=", handshake.encode("hex")


reply = s.recv(128)

print "Raw=", repr(reply)
print "Raw=", reply.encode("hex")

message = ''
for i in xrange(0, len(reply)):
  message = message + chr(ord(reply[i]) ^ ord(key[i % len(key)]))

print "message=", repr(message)
print "message=", message.encode("hex")