03 Feb 2017

AlexCTF Write-up

On Friday, I took part in AlexCTF. It was pretty good fun since nothing in it was related to web app security and more focused around reverse engineering and cryptography.

Warning: this write-up contains CTF quality code.

Cryptography 1: Ultracoded

We get given a text file with the words ZERO and ONE down and the message:

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 doesn’t handle any special character

I figured it would be worth converting the zeros and ones into actual binary so I wrote a quick script

f = open('zero_one', 'r')

data = ""
for line in f:
  for word in line.split():
    if word == "ZERO":
      data+="0"
    elif word == "ONE":
      data+="1"
			
print data

# from http://stackoverflow.com/a/11599702
x = ''.join(chr(int(data[i:i+8], 2)) for i in xrange(0, len(data), 8))

print x

which gives us:

Li0gLi0uLiAuIC0uLi0gLS4tLiAtIC4uLS4gLSAuLi4uIC4tLS0tIC4uLi4
uIC0tLSAuLS0tLSAuLi4gLS0tIC4uLi4uIC4uLSAuLS0uIC4uLi0tIC4tLi
AtLS0gLi4uLi4gLiAtLi0uIC4tLiAuLi4tLSAtIC0tLSAtIC0uLi0gLQ==

which looks like a base64 string due to the == at the end. I then converted that string to ASCII but it didn’t seem to return anything good. base64 decoding that string returns only special characters and spaces so I was confused. Here’s whats returned:

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

I have to admit, it too me a while to figure out that it’s Moores code. I ran it through an online converter and got the following flag:

ALEXCTFTH15O1SO5UP3RO5ECR3TOTXT  

because we don’t have any special characters we can substitute the 0’s for underscores and finally get our flag:

ALEXCTF{TH15_1S_5UP3R_5ECR3T_TXT}  

for 50 points.

Cryptography 2: Many time secrets

This challenge had a file with a few lines of hex and the following description:

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!

The problem

“but he new know why people call it one time pad” gave a pretty good hint to the problem, implementing the solution was slightly tougher.

In general msg xor key is good as long as it’s just used once. In this problem the key had been used multiple times which caused the issue.

def xors(a, b):
    return "".join(chr(ord(x) ^ ord(y)) for x, y in zip(a, b))


data = [
    '0529242a631234122d2b36697f13272c207f2021283a6b0c7908',
    '2f28202a302029142c653f3c7f2a2636273e3f2d653e25217908',
    '322921780c3a235b3c2c3f207f372e21733a3a2b37263b313012',
    '2f6c363b2b312b1e64651b6537222e37377f2020242b6b2c2d5d',
    '283f652c2b31661426292b653a292c372a2f20212a316b283c09',
    '29232178373c270f682c216532263b2d3632353c2c3c2a293504',
    '613c37373531285b3c2a72273a67212a277f373a243c20203d5d',
    '243a202a633d205b3c2d3765342236653a2c7423202f3f652a18',
    '2239373d6f740a1e3c651f207f2c212a247f3d2e65262430791c',
    '263e203d63232f0f20653f207f332065262c3168313722367918',
    '2f2f372133202f142665212637222220733e383f2426386b'
]

for line in data:
    print xors(line.decode('hex'), 'ALEXCTF{HERE_GOES_THE_KEY}')  

I for the flag ALEXCTF{HERE_GOES_THE_KEY} by manually “crib dragging” until the plain text made sense.

Plain text:

Dear Friend, This time I u
nderstood my mistake and u
sed One time pad encryptio
n scheme, I heard that it
is the only encryption met
hod that is mathematically
 proven to be not cracked
ever if the key is kept se
cure, Let Me know if you a
gree with me to use this e
ncryption scheme always.  

Scripting 1: Math bot

The instructions for this challenge were straight forward:

It is well known that computers can do tedious math faster than human.

When we use netcat to connect we get the following screen:

root@726a61e75cb8:/ctf# 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 :
1992697762612302550072538 + 2115286419135408893338581 =  

It looks like we have to script a bot to solve maths problems. I initially considered using the pwntools library for python but ended up going with plain sockets because it was easier.

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('195.154.53.62', 1337))

def count_lines(data):
	lines = 0
	for char in data:
		if char == "\n":
			lines=lines+1
	return lines


def get_final_line(data):
	counter = 0
	final_line = ""

	for char in data:
		if char == "\n":
			counter = counter+1

		if counter==(count_lines(data)-1):
			final_line+=x

	return final_line

def send_answer(answer):
	s.send(str(answer) + "\n")

def format_question(final_line):
	return final_line.replace("=", "")

def calculate_answer(question):
	# dangerous but running
	# inside docker so
	# its okay
	return eval(question)

while True:
	data = s.recv(4000)
	question = format_question(get_final_line(data))
	print question
	answer = calculate_answer(question)
	print answer
	send_answer(answer)

The script runs for a few seconds to solve 250 maths problems and finally we get the following message:

Tell your human operator flag is: ALEXCTF{1_4M_l33t_b0t}  

and we get the flag for a cool 100 points.

Reverse Engineering 1: Gifted

I got a binary, since the challenge was only 50 points I went ahead and tried:

strings gifted | grep AlexCTF  

which returned (along with other strings)

AlexCTF{Y0u_h4v3_45t0n15h1ng_futur3_1n_r3v3r5ing}

for easy 50 points.

I'm on twitter @_amanvir