We solved 9 challenges in this CTF.

Gifted

gifted

The challenge is simply a link to an ELF binary. After downloading the binary, I ran strings to look for anything interesting.

$ strings gifted
/lib/ld-linux.so.2
libc.so.6
_IO_stdin_used
exit
...
[^_]
AlexCTF{Y0u_h4v3_45t0n15h1ng_futur3_1n_r3v3r5ing}
Enter the flag:
You got it right dude!
Try harder!
;*2$"
...

The flag is quickly found as a plaintext string in the binary. For further investigation, I disassembled the binary in radare2. The flag is being pushed as a string onto the stack just before the call to strcmp.

Flag from radare2

The flag is AlexCTF{Y0u_h4v3_45t0n15h1ng_futur3_1n_r3v3r5ing}.

Ultracoded

Fady didn’t understand well the difference between encryption and encoding, so instead of encrypting some secret message to pass to his friend, he encoded it!
Hint: Fady’s encoding doens’t handly any special character
zero_one

zero_one is a text file containing only the words ZERO and ONE in some kind of repeating pattern. I figured this must be converted into a binary representation, so I wrote a small python script.

#!/usr/bin/python2.7
import binascii
import base64

data = open("zero_one").read()
dataArr = data.split()
binaryBuffer = ""

for w in dataArr:
  if "ZERO" in w:
    binaryBuffer += "0"
  if "ONE" in w:
    binaryBuffer += "1"

I converted the buffer string to an integer and used binascii.unhexlify to return the ASCII plaintext.

n = int(binaryBuffer, 2)
binDecoded = binascii.unhexlify('%x' % n)

Printing binDecoded reveals a base64-encoded string.

Li0gLi0uLiAuIC0uLi0gLS4tLiAtIC4uLS4gLSAuLi4uIC4tLS0tIC4uLi4uIC0tLSAuLS0tLSAuLi4gLS0tIC4uLi4uIC4uLSAuLS0uIC4uLi0tIC4tLiAtLS0gLi4uLi4gLiAtLi0uIC4tLiAuLi4tLSAtIC0tLSAtIC0uLi0gLQ==

Let’s decode it!

base64Decoded = base64.b64decode(binDecoded)

Printing this output produces something resembling morse code.

.- .-.. . -..- -.-. - ..-. - .... .---- ..... --- .---- ... --- ..... ..- .--. ...-- .-. --- ..... . -.-. .-. ...-- - --- - -..- -

I couldn’t find a library to decode morse code, so I built the decoded string from a python dictionary.

CODE = {'.-': 'A',    '-...': 'B',  '-.-.': 'C',
        '-..': 'D',   '.': 'E',     '..-.': 'F',
        '--.': 'G',   '....': 'H',  '..': 'I',
        '.---': 'J',  '-.-': 'K',   '.-..': 'L',
        '--': 'M',    '-.': 'N',    '---': 'O',
        '.--.': 'P',  '--.-': 'Q',  '.-.': 'R',
        '...': 'S',   '-': 'T',     '..-': 'U',
        '...-': 'V',  '.--': 'W',   '-..-': 'X',
        '-.--': 'Y',  '--..': 'Z',

        '-----': '0', '.----': '1', '..---': '2',
        '...--': '3', '....-': '4', '.....': '5',
        '-....': '6', '--...': '7', '---..': '8',
        '----.': '9'
        }

morseDecoded = ''.join(CODE.get(i) for i in base64Decoded.split())

Printing this output gave me something closely resembling the flag format.

ALEXCTFTH15O1SO5UP3RO5ECR3TOTXT

The hint in the challenge description mentioned that special characters weren’t handled. After some experimentation, I determined that the O’s were underscores and that the curly brackets were simply missing. Here’s the final part of the python script.

morseList = list(morseDecoded.lower())

alexCTF = ''.join(morseList[0:7])
flag = ""

for l in morseList[7:]:
    if "o" in l:
        flag += "_"
    else:
        flag += l

print "The flag is: " + alexCTF + "{" + flag + "}"

This yields the flag.

The flag is: alexctf{th15_1s_5up3r_5ecr3t_txt}

Many time secrets

This time Fady learned from his old mistake and decided to use onetime pad as his encryption technique, but he never knew why people call it one time pad!
msg

The challenge description states that Fady is using OTP encryption. As the name implies, the secret key in OTP encryption can only be used once, otherwise the complete key and plaintext can be recovered using a many time pad attack (aka crib drag). Assuming that each line in the msg file is a line of text encrypted with the same OTP key, we can begin the crib drag by xor-ing 2 lines together and guessing possible letters.

I used the cribdrag tool from SpiderLabs to recover the plaintext.

$ python xorstrings.py 0529242a631234122d2b36697f13272c207f2021283a6b0c7908 2f28202a302029142c653f3c7f2a2636273e3f2d653e25217908
2a01040053321d06014e09550039011a07411f0c4d044e2d0000

$ python cribdrag.py 2a01040053321d06014e09550039011a07411f0c4d044e2d0000
Your message is currently:
0   __________________________
Your key is currently:
0   __________________________
Please enter your crib:

After a couple dozen guesses, I was able to decrypt the message as such.

Your message is currently:
0   Dear Friend, This time I u
Your key is currently:
0   nderstood my mistake and u
Please enter your crib:

Now that we have some plaintext, we can recover the key by simply xoring a plaintext string together with it’s corresponding ciphertext. This can be done by modifying xorstrings.py slightly.

s1 = "0529242a631234122d2b36697f13272c207f2021283a6b0c7908".decode('hex')
s2 = "Dear Friend, This time I u"

s3 = sxor(s1, s2)

print s3

Running the modified xorstring.py script produces the flag: ALEXCTF{HERE_GOES_THE_KEY}.

Hit the core

fore1.core

Running the ‘strings’ command against the downloaded file gives a bunch of random-looking output, but one line in particular stands out.

$ strings fore1.core
CORE
code
./code
...
AWAVA
AUATL
[]A\A]A^A_
cvqAeqacLtqazEigwiXobxrCrtuiTzahfFreqc{bnjrKwgk83kgd43j85ePgb_e_rwqr7fvbmHjklo3tews_hmkogooyf0vbnk0ii87Drfgh_n kiwutfb0ghk9ro987k5tfb_hjiouo087ptfcv}
;*3$"
(q9e
...

Judging by the curly brackets in one of the lines, I figured the flag might be extracted from this. Upon closer inspection it becomes clear that every fifth character starting from the first A spells ALEXCTF, perhaps this correlation continues throughout? I wrote a python script to check.

#!/usr/bin/python2.7
data = "cvqAeqacLtqazEigwiXobxrCrtuiTzahfFreqc{bnjrKwgk83kgd43j85ePgb_e_rwqr7fvbmHjklo3tews_hmkogooyf0vbnk0ii87Drfgh_n kiwutfb0ghk9ro987k5tfb_hjiouo087ptfcv}"
flag = ""

for i in range(len(data)):
  if (i-3)%5 == 0:
    flag += data[i]
  else:
    continue

print flag

Sure enough the flag is returned: ALEXCTF{K33P_7H3_g00D_w0rk_up}.

Math bot

It is well known that computers can do tedious math faster than humans.
nc 195.154.53.62 1337

$ nc 195.154.53.62 1337
                __________
         ______/ ________ \______
       _/      ____________      \_
     _/____________    ____________\_
    /  ___________ \  / ___________  \
   /  /XXXXXXXXXXX\ \/ /XXXXXXXXXXX\  \
  /  /############/    \############\  \
  |  \XXXXXXXXXXX/ _  _ \XXXXXXXXXXX/  |
__|\_____   ___   //  \\   ___   _____/|__
[_       \     \  X    X  /     /       _]
__|     \ \                    / /     |__
[____  \ \ \   ____________   / / /  ____]
     \  \ \ \/||.||.||.||.||\/ / /  /
      \_ \ \  ||.||.||.||.||  / / _/
        \ \   ||.||.||.||.||   / /
         \_   ||_||_||_||_||   _/
           \     ........     /
            \________________/

Our system system has detected human traffic from your IP!
Please prove you are a bot
Question  1 :
50489238639188063698070072981610 * 1364107478925961178712787264169 =

I reconnected a few times to confirm that the server handed out random equations to be solved. After solving one manually, I was prompted with a new math problem. At this point, I wrote a python script to automate the process.

#!/usr/bin/python2.7
import socket

host = '195.154.53.62'
port = 1337

bot = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
bot.connect((host,port))

while True:

    data = bot.recv(1024)

    if "=" in str.split(data)[-1]:    
        equation = str.split(data)[-4] + " " + str.split(data)[-3] + " " + str.split(data)[-2]

        print "Solving equation..."
        print equation

        result = repr(eval(equation))

        print "Sending result..."
        bot.send(result + "\n")

    else:
        print data
        break

Running the script returns the flag after a few seconds.

Solving equation...
77570593763924035994006787070091 * 156048715378978225422935000952364
Sending result...
Well no human got time to solve 500 ridiculous math challenges
Congrats MR bot!
Tell your human operator flag is: ALEXCTF{1_4M_l33t_b0t}

Hello there

Why not drop us a few lines and say hi :).

Upon connecting to the AlexCTF IRC channel, the banner displayed the flag in plaintext.

The flag is ALEXCTF{W3_w15h_y0u_g00d_luck}.

SSL 0day

It lead to memory leakage between servers and clients rending large number of private keys accessible. (one word)

The answer is the Heartbleed vulnerability (CVE-2014-0160).

The flag is Heartbleed.

CA

What is the CA that issued Alexctf https certificate (flag is lowercase with no spaces)

Inspect the CA certificate in Firefox.

CA

The flag is letsencrypt.

Doesn’t our logo look cool

Doesn’t our logo look cool?

Take a closer look at the logo of AlexCTF on the front page.

Alexflag

The flag is hidden in plain sight. It would be possible to use a python script or even sed to extract the flag, but you can also do it by hand.

The flag is ALEXCTF{0UR_L0G0_R0CKS}.

[Back to Top]