Skip to main content

Encoding challenge

Now you've got the hang of the various encodings you'll be encountering, let's have a look at automating it.

Can you pass all 100 levels to get the flag?

Connect at nc socket.cryptohack.org 13377

13377.py
#!/usr/bin/env python3

from Crypto.Util.number import bytes_to_long, long_to_bytes
from utils import listener # this is cryptohack's server-side module and not part of python
import base64
import codecs
import random

FLAG = "crypto{????????????????????}"
ENCODINGS = ["base64","hex","rot13","bigint","utf-8"]
with open('/usr/share/dict/words') as f:
WORDS = [line.strip().replace("'", "") for line in f.readlines()]
WORDS = ["hello", "world", "crypto", "flag", "cryptohack"]

class Challenge():
def __init__(self):
self.challenge_words = ""
self.stage = 0

def create_level(self):
self.stage += 1
self.challenge_words = "_".join(random.choices(WORDS, k=3))
encoding = random.choice(ENCODINGS)

if encoding == "base64":
encoded = base64.b64encode(self.challenge_words.encode()).decode() # wow so encode
elif encoding == "hex":
encoded = self.challenge_words.encode().hex()
elif encoding == "rot13":
encoded = codecs.encode(self.challenge_words, 'rot_13')
elif encoding == "bigint":
encoded = hex(bytes_to_long(self.challenge_words.encode()))
elif encoding == "utf-8":
encoded = [ord(b) for b in self.challenge_words]

return {"type": encoding, "encoded": encoded}

#
# This challenge function is called on your input, which must be JSON
# encoded
#
def challenge(self, your_input):
if self.stage == 0:
return self.create_level()
elif self.stage == 100:
self.exit = True
return {"flag": FLAG}

if self.challenge_words == your_input["decoded"]:
return self.create_level()

return {"error": "Decoding fail"}

if __name__ == "__main__":
c= Challenge()

listener.start_server(port=13377)

Solution

This WriteUp Solution is password protected by the flag of the challenge.

We have to just decode the encoded string and send it back to the server. The server will send us the next encoded string. We have to decode it and send it back to the server. We have to do this 100 times to get the flag.

solve.py
from pwn import *
import json
import base64
import codecs
from Crypto.Util.number import long_to_bytes

conn = remote('socket.cryptohack.org',13377)

for i in range(101):
en=json.loads(conn.recvline().decode())
if i==100:
print(en["flag"])
break
type = en['type']
if type == 'base64':
decoded = base64.b64decode(en['encoded']).decode()
elif type == 'hex':
decoded = bytes.fromhex(en['encoded']).decode()
elif type == 'rot13':
decoded = codecs.decode(en['encoded'], 'rot_13')
elif type == 'bigint':
decoded = long_to_bytes(int(en['encoded'], 16)).decode()
elif type == 'utf-8':
decoded = ''.join([chr(i) for i in en['encoded']])
conn.sendline(json.dumps({'decoded': decoded}).encode())

Flag after 100 iterations: crypto{3nc0d3_d3c0d3_3nc0d3}