dCTF 2021

I didn’t give this CTF much time because I actually had a go at these challenges a bit after the CTF had finished. The challenges that I attempted ended up being pretty simple, not that they all would have been. My favourite challenge was A Simple SP Box.

web

Simple Web - 100 points

Time to warm up!

I opened the link in firefox, ticked “I want flag” and then hit submit. It replied with “Not authorized”. I looked at the sources and was a bit confused by how little there was. However, the javascript did confirm there was a POST - this was after about 300 blank lines which I assume were intentional obfuscation. I then looked at the network requests that are made when I press the button, and saw the following request payload: flag=1&auth=0&Submit=Submit

I opened Insomnia and edited the auth value to 1.

Flag: dctf{w3b_c4n_b3_fun_r1ght?}

stego

Hidden message - 100 points

This image looks familiar…

Opened the image, there’s a picture of some flags and buildings. I assume it relates to the host of the CTF or its sponsors. Ran zsteg, it’s magic and it output the flag immediately.

zsteg fri.png 
b1,rgb,lsb,xy       .. text: "dctf{sTeg0noGr4Phy_101}"
b3,g,lsb,xy         .. text: "I@4I)$Xl"
b3,abgr,msb,xy      .. text: "v\rWv)WvM"
b4,r,lsb,xy         .. text: "\nfb@DHfBHH"
b4,r,msb,xy         .. text: "E`@Q'g3@D@tr"
b4,g,msb,xy         .. text: "ND@&B$rp"
b4,b,lsb,xy         .. text: "D\"$ \"\"\"$bN"
b4,b,msb,xy         .. text: "DDD$Fr0U3p@f"
b4,rgb,lsb,xy       .. text: "HDd(\"b(Dd\""
b4,rgb,msb,xy       .. text: "GpD@FdD#"
b4,bgr,lsb,xy       .. text: "H$b(\"dH$`"
b4,bgr,msb,xy       .. text: "t@@DFd$#"
b4,rgba,lsb,xy      .. text: "`OP/S/b/b?"
b4,abgr,msb,xy      .. text: "O@OdOdO2/"

Flag: dctf{sTeg0noGr4Phy_101}

Dragon - 100 points

Hiding in plain sight.

Found in stegsolve, just keep tapping the right arrow until you spot the flag. Note that it’s pretty easy to miss in stegsolve because the image is so big! Can’t see the whole thing on the screen :(

Flag: dctf{N0w_Y0u_s3e_m3}

rev

bell - 100 points

I found the main part of the program and ran it in C++ straight from the decompiler. It’s something I’d been wanting to try out since reading about it on Ghetto Forensics.

Here’s the code that I got running, the decompilation was ripped straight from IDA.

#include <iostream>
#include <windows.h>

__int64 __fastcall triangle(unsigned int a1, int a2)
{
    __int64 v3; // rbx

    if (a2 > (int)a1)
        return 0LL;
    if (a1 == 1 && a2 == 1)
        return 1LL;
    if (a2 == 1)
        return triangle(a1 - 1, a1 - 1);
    v3 = triangle(a1, (unsigned int)(a2 - 1));
    return v3 + triangle(a1 - 1, (unsigned int)(a2 - 1));
}

int main()
{
    std::cout << "Hello World!\n";
    int limit = 9;  // depends on server run/can re-run until this is the prompt
    for (int i = 1; i <= limit; i++) {
        std::cout << triangle(limit, i);
        std::cout << "\n";
    }
}

I was pretty happy with how easy it was to run. I didn’t need to have any understanding of what the function did really, and although I could have reimplemented it in something like python, it’s nice to also just be able to plug it straight in to run somewhere.

Flag: dctf{f1rst_step_t0wards_b3ll_l4bs}

crypto

A Simple SP Box - 300 points

It’s just a simple SP-box, 150 tries should be enough for you.

You get the source code and a host to connect to. I didn’t understand everything that was going on from skimming the source code, but from fuzzing it looked straight forward enough:

nc dctf1-chall-sp-box.westeurope.azurecontainer.io 8888
Here's the flag, please decrypt it for me:
s<nnNtoo@nEO02nOnC0}nstti0zO}n2CI<$#0@s=nI
> dctfaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
That doesn't look right, it encrypts to this:
;o;O;t;C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;n;
> dctfaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
That doesn't look right, it encrypts to this:
;;;;;;;o;;;;;;;O;;;;;;;t;;;;;;;C;;;;;;;;;;
> dctf{aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa    
That doesn't look right, it encrypts to this:
;;;;;;;o;;;;;;;O;;;;;;;t;;;;;;;C;;;;;;;=;;

The program will give the ciphertext of the flag and then the ciphertext of whatever you send. The challenge refers to an “SP-box”, which I figured is Subsitition-Position box - a substition cipher is used to encrypt each character, and the position of the characters gets jumbled up too.

The source noted you get to provide 150 inputs which is greater than the sum of both the length of the alphabet, and the password length, so I just gave two rounds of inputs. The first round figured out the S part, the second round figured out the P part.

from pwn import *
from string import ascii_letters, digits
from typing import Dict
import sys
from collections import Counter

ALPHABET = (ascii_letters + digits + "_!@#$%.'\"+:;<=}{").encode()

# connection stuff
host = sys.argv[1] if len(sys.argv) > 1 else 'dctf1-chall-sp-box.westeurope.azurecontainer.io'
port = int(sys.argv[2]) if len(sys.argv) > 2 else 8888
conn = remote(host, port)

# receive stuff plus prompt
_, encrypted_flag = conn.recvlines(2)
conn.recv(2)
encrypted_flag = encrypted_flag

# figure out mapping of each char, at each position
unsbox: Dict[bytes, bytes] = {}  # dict{ciphertext -> plaintext}
for _p in ALPHABET:
    p: bytes = bytes([_p])
    user_input = p * len(encrypted_flag)
    conn.sendline(user_input)
    _, ciphertext = conn.recvlines(2)
    conn.recv(2)
    first_char: bytes = bytes([ciphertext[0]])
    unsbox[first_char] = p

# figure out ordering by sending one different character and finding where it went
decrypted_flag = [b'*' for _ in range(len(encrypted_flag))]
for i in range(len(encrypted_flag)):
    payload = ('a'*i + 'X' + 'a'*(len(decrypted_flag) - 1 - i)).encode()
    conn.sendline(payload)
    _, resp = conn.recvlines(2)
    conn.recv(2)
    resp = resp.decode()
    index_of_x: int = resp.index(Counter(resp).most_common(2)[1][0])
    decrypted_flag[i] = unsbox[bytes([encrypted_flag[index_of_x]])]
    print(b''.join(decrypted_flag).decode())  # prints incrementally for fun

if __name__ == '__main__':
    pass

Flag: dctf{S0_y0u_f0und_th3_cycl3s_in_th3_s_b0x}