Wargame/Cryptohack

Encoding Challenge

wyv3rn 2023. 2. 15. 18:57
728x90
반응형

1. intro

코딩이 조금 귀찮긴 했지만 재밋는 문제였다.

 

2. code 및 분석

2.1.  code

#!/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()]


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"}


listener.start_server(port=13377)

 

2.2. 분석

서버의 파일에서 특정 문자열을 가져온 다음, base64, hex, rot13, bigint, utf-8로 encoding 한 뒤 출력해준다.

이를 decoding하여 json 형식으로 값을 보내주면 된다.

 

3. exploit

복호화야 어떻게든 하면 되는데, json 형식으로 값의 전송이 다소 힘들었다...

검색에 검색을 거듭한 뒤에야 할 수 있었음 ㅋ

from pwn import *
from Crypto.Util.number import *
import codecs
import json

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

dec = ''

def rcv():
    p.recvuntil(b': ')
    typ = p.recvuntil(b',')[:-1]
    p.recvuntil(b': ')
    enc = p.recvuntil(b'}')[:-1]
    return typ,enc

for i in range(100):
    typ,enc = rcv()
    dec = ''
    if b'base64' in typ:
        dec = base64.b64decode(enc[1:-1])
    if b'hex' in typ:
        dec = long_to_bytes(int(enc[1:-1],16))
    if b'rot' in typ:
        dec = codecs.decode((enc[1:-1]).decode(),'rot_13').encode()
    if b'big' in typ:
        dec = long_to_bytes(int(enc[1:-1],16))
    if b'utf' in typ:
        enc = eval(enc)
        for i in range(len(enc)):
            dec += chr(enc[i])
        dec = dec.encode()
    pay = {"type": typ[1:-1].decode(), "decoded":dec.decode()}
    p.send(json.dumps(pay))
    print(dec)

p.interactive()

 

┌──(kali㉿kali)-[~/Downloads]
└─$ python solve.py
[+] Opening connection to socket.cryptohack.org on port 13377: Done
/home/kali/Downloads/solve.py:34: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
  p.send(json.dumps(pay))
b'starter_headquarters_networks'
b'neighbor_translator_cassette'
b'internet_recipe_suffered'
...
b'dallas_analog_honest'
b'herb_moore_shoe'
b'bo_glucose_ultimate'
b'concentration_pdas_impressive'
[*] Switching to interactive mode

{"flag": "crypto{3nc0d3_d3c0d3_3nc0d3}"}
[*] Got EOF while reading in interactive

 

728x90
반응형