CyberSpace'24 : Writeups


CyberSpace CTF 2024

Team: WhatIsThis

Total Score: 351 points @ 262nd place

User Name Score
H4N5 251
ha1fdan 100

Solves:

Challenge Category Value User
Sanity Check misc 50 H4N5
key beginner 50 H4N5
Baby Pybash beginner 50 H4N5
ZipZone beginner 50 ha1fdan
encryptor beginner 50 ha1fdan
🅰️ 🦵 🌱 sponsor 50 H4N5
Feedback misc 1 H4N5
flagprinter crypto 50 H4N5

Score over time:

Score_over_Time.png


Sanity Check

Join our Discord!

https://discord.csc.tf/

CyberSpace 2024 Discord

Flag: CSCTF{54n17y_5ucc355fully_ch3ck3d!}


key

GDB is cool! Ghidra or IDA is helpful

File(s): key

Solution: Using https://dogbolt.org we can open the key file using angr. We find the variables v3 to v34 wich all contains a decimal number. We can use this information to write a script to find the key.

  • Original Solution code (C#):
using System;

class Program
{
    static void Main()
    {
        int[] v6 = new int[]
        {
            67, 164, 65, 174, 66, 252, 115, 176,
            111, 114, 94, 168, 101, 242, 81, 206,
            32, 188, 96, 164, 109, 70, 33, 64,
            32, 90, 44, 82, 45, 94, 45, 196
        };

        char[] s = new char[32];

        for (int i = 0; i < 32; i++)
        {
            if (i % 2 == 0)
            {
                s[i] = (char)(v6[i] ^ i);
            }
            else
            {
                s[i] = (char)((v6[i] / 2) ^ i);
            }
        }

        string key = new string(s);
        Console.WriteLine("The correct key is: " + key);
    }
}
  • Solution code rewritten in Python:
v6 = [
    67, 164, 65, 174, 66, 252, 115, 176,
    111, 114, 94, 168, 101, 242, 81, 206,
    32, 188, 96, 164, 109, 70, 33, 64,
    32, 90, 44, 82, 45, 94, 45, 196
]
s = [''] * 32

for i in range(32):
    if i % 2 == 0:
        s[i] = chr(v6[i] ^ i)
    else:
        s[i] = chr((v6[i] // 2) ^ i)

key = ''.join(s)
print(key)

Flag: CSCTF{u_g0T_it_h0OrAy6778462123}


Baby Pybash

I made a very secure bash terminal in Python. I don’t think anyone can break in!

nc baby-pybash.challs.csc.tf 1337

File(s): handout_baby_pybash.zip

Solution: The script uses a regular expression to block most characters, but it allows $ and 0. By combining these, we get $0, which refers to the first argument of the initial command (bash). This allows us to invoke a bash shell and execute cat flag.txt to retrieve the flag.

== proof-of-work: disabled ==
Welcome to Baby PyBash!

Enter a bash command: $0
cat flag.txt
CSCTF{b4sH_w1z4rd_0r_ju$t_ch33s3_m4st3r?_c1d4eeb2a}

Flag: CSCTF{b4sH_w1z4rd_0r_ju$t_ch33s3_m4st3r?_c1d4eeb2a}


ZipZone

I was tired of trying to find a good file server for zip files, so I made my own! It’s still a work in progress, but I think it’s pretty good so far.

https://zipzone-web.challs.csc.tf/

File(s): handout_zipzone.zip

Solution: The app.py uses subprocess.call to unzip our uploaded zip file, therefore we can create a symlink to /tmp/flag.txt using ln -s /tmp/flag.txt flag.txt and zip the symlink using zip --symlinks exploit.zip flag.txt. After uploading the zip file, we get: https://zipzone-web.challs.csc.tf/files/a58a980e-aeb8-4c33-888d-328280bb463f; append /flag.txt to the url and we get the content of /tmp/flag.txt.

Flag: CSCTF{5yml1nk5_4r3_w31rd}


encryptor

My friend sent me this app with an encoded flag, but he forgot to implement the decryption algorithm! Can you help me out?

File(s): encryptor.apk

Solution: Opening the file with Archive Manager we find /assets/enc.txt which contains encrypted flag OIkZTMehxXAvICdQSusoDP6Hn56nDiwfGxt7w/Oia4oxWJE3NVByYnOMbqTuhXKcgg50DmVpudg=. By using https://www.decompiler.com we can decompile the apk and under souces/com/example/encrypter/MainActivity.java. this class contains the encryption algorithm.

We can see a base64 string being decoded:

private String getKey() {
  return new String(Base64.decode("ZW5jcnlwdG9yZW5jcnlwdG9y".getBytes(), 0));
}

Decoding the base64 string gives us the key encryptorencryptor.

We can also find the encryption function:

private String encryptText(String str) throws InvalidKeyException, UnsupportedEncodingException, NoSuchPaddingException, NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException {
        SecretKeySpec secretKeySpec = new SecretKeySpec(getKey().getBytes("UTF-8"), "Blowfish");
        Cipher instance = Cipher.getInstance("Blowfish");
        if (instance != null) {
            instance.init(1, secretKeySpec);
            return Build.VERSION.SDK_INT >= 26 ? new String(Base64.encode(instance.doFinal(str.getBytes("UTF-8")), 0)) : "";
        }
        throw new Error();
    }

The encryption happends using Blowfish, we can write a simple script to decrypt our flag:

import base64
from Crypto.Cipher import Blowfish

def get_key():
    encoded_key = "ZW5jcnlwdG9yZW5jcnlwdG9y"
    return base64.b64decode(encoded_key)

encrypted_text = "OIkZTMehxXAvICdQSusoDP6Hn56nDiwfGxt7w/Oia4oxWJE3NVByYnOMbqTuhXKcgg50DmVpudg="
cipher = Blowfish.new(get_key(), Blowfish.MODE_ECB)
encrypted_bytes = base64.b64decode(encrypted_text)
decrypted_bytes = cipher.decrypt(encrypted_bytes)
padding_length = decrypted_bytes[-1]
decrypted_text = decrypted_bytes[:-padding_length].decode('utf-8')
print(decrypted_text)

Flag: CSCTF{3ncrypt0r_15nt_s4Fe_w1th_4n_h4Rdc0d3D_k3y!}


🅰️ 🦵 🌱

There’s a bug bounty program on Intigriti I wanted to revisit. The problem is I only speak emojis these days and completely forgot the name of the program! Can you remind me?

Emojis: 🅰️ 🦵 🌱

https://go.intigriti.com/programs/

Note: Flag format is CSCTF{name_of_program}

Solution: The emojis (🅰️ 🦵 🌱) can be broken down as follows: the first emoji represents the letter A, the second one is a leg, and the last one could stand for plant, seed, or grow. Putting these together, we can search the Programs page and find the word Allegro: A + leg + grow.

Flag: CSCTF{Allegro}


flagprinter

Instead of a challenge, here’s a solution. Hope you have plenty of RAM!

File(s): chall.py, out.py

Solution: The original code attempted to build a massive sequence, which caused it to run out of memory. The optimized solution bypasses this issue by using a recursive function to calculate only the specific values needed at each step, rather than storing the entire sequence. This reduces memory usage significantly. By calculating values as they are needed, the program avoids crashing and successfully decrypts the flag. This approach allows us to handle much larger data without running into memory limitations, making the decryption process both efficient and effective.

from out import enc, R
from math import prod

def get_a_value(index, depth):
    if depth == 0:
        return 0
    elif index < 3**(depth-1):  # First third
        return get_a_value(index, depth-1)
    elif index < 2*3**(depth-1):  # Second third
        return get_a_value(index - 3**(depth-1), depth-1) + 1
    else:  # Third third
        return get_a_value(index - 2*3**(depth-1), depth-1) + 2

def calculate_required_a_values(R_indices, depth):
    return [get_a_value(idx, depth) for idx in R_indices]

flag = ''
depth = 0

# Estimate the required depth of recursion based on the number of iterations
while 3**depth < max(max(R) for R in R) + 1:
    depth += 1

print(depth)

for i in range(355):
    if i % 5 == 0:
        required_values = calculate_required_a_values(R[i//5], depth)
        flag += chr(enc[i//5] ^ prod(required_values))
        print(flag)

Solution file: sol.py

Flag: CSCTF{2441d2f22fa1d5b9fc0a850dcfbbccf608cafbc22a1beaae0ac328ff6d218781}