vsCTF 2023

We participated in our vsCTF 2023 and we ended up being 1st! It was a day-long CTF but we solved 24 (out of 31) challenges. Some of the challenges were very interesting.

Cant wait to play the next vsCTF event as CyberSpace


Challenge → Sanity Check

Description → you know what to do.

Solution →

We are presented with a website that pretty much running nothing. I tried opening the source code by right click and Ctrl+u. None of them worked

We can view the source code by directly manupulating the url.

And we have our flag


Challenge → Canguard?

Description → The user of this PC was caught cheating on Valorant, can you figure out why his cheat was detected?

Solution →

After opening the ctf files we found bunch of folders related to valorant. One of them had logs by RiotVanguard.

We found this link where they have talked about decrypting the logs.


We have modified the code and made it so that it decode all the logs in current folder.

import struct
import sys
import os

def rc4(data, key):
    S = [i for i in range(256)]
    j = 0
    out = []
    for i in range(256):
        j = (j + S[i] + key[i % len(key)]) % 256
        S[i], S[j] = S[j], S[i]
    i = j = 0
    for char in data:
        i = (i + 1) % 256
        j = (j + S[i]) % 256
        S[i], S[j] = S[j], S[i]
        out.append(char ^ S[(S[i] + S[j]) % 256])
    return bytearray(out)

KEYMASK = [0xB1, 0x54, 0x45, 0x57, 0xA7, 0xC4, 0x64, 0x2E,
           0x98, 0xD8, 0xB1, 0x1A, 0x0B, 0xAA, 0xD8, 0x8E,
           0x7F, 0x1E, 0x5B, 0x8D, 0x08, 0x67, 0x96, 0xCB,
           0xAA, 0x11, 0x50, 0x84, 0x17, 0x46, 0xA3, 0x30]

# Get all log files in the current directory
log_files = [f for f in os.listdir('.') if os.path.isfile(f) and f.endswith('.log')]

# Open flag.txt for writing
with open("flag.txt", "wb") as output_file:
    for log_file in log_files:
        DATA = open(log_file, 'rb').read()
        DATA = DATA[4:]
        REAL_KEY = [DATA[i] ^ KEYMASK[i] for i in range(32)]
        DATA = DATA[32:]
        while len(DATA) > 0:
            BLOCK_LEN = struct.unpack('<L', DATA[:4])[0]
            DATA = DATA[4:]
            decrypted_data = rc4(DATA[:BLOCK_LEN], REAL_KEY).decode('utf-16')
            # Write the decrypted data to flag.txt
            DATA = DATA[BLOCK_LEN:]

After all the log file are decrypted we found the flag.

Challenge → RoRansom 1

Description → The user of this computer was tricked into joining a weird Roblox game. We suspect a newbie hacker used a fake account to host the malicious game. There might be some leftover code in the game (due to the hackers incompetency) that can help us find out who they really are.

Solution →

Searching throught the files we have found logs related to roblox.

In every log file there is a placeId which is game url. After searching though all the log files we have found the following ids. Except for one all the others are popular games in roblox.


After visiting the url we found the game.

ftcsvthrowaway’s Place

We opened the debugger menu and found the flag in error logs.

Challenge → RoRansom 2

Description → Intelligence informs us that the hacker has horrible memory, so they hid an asset in the game which has his passwords, and as far as we know, he has removed it from the game. Recover the asset.

Solution →

We found a lot of encrypted files inside roblox-player.

After unziping all the files we found a lot of assets. Looking through the files for a while we found pswdmgr.png which contains the flag.

Challenge -> RoRansom 3

Description → The hacker made a slip-up: they left a test game with malicious code on their main account. Sources indicate this game contains the ransomware. Your mission? Dive in, uncover the hidden code, and reverse the damage.

Solution →

This was solved after ctf was over.

When we search the username in the searchbar we can find the hacker profile.

Inside the profile we found a game which we can edit in roblox studio.


In ServerScript there is a script file. We used the password we found from previous challenge.

local A, B, C, D, E, F = "1a2a04302b173b15075426434179412a050c0658", "535f5d3324097548362716001d3f1c4f0125594b", "13015246554f3b7503275808355101470f015f17", "16505f0e2d49024149691608380b0a2f00532123", "171d7241051f0601475b40533b240c2001162c0a", "0713224a4e"
local G = A..B..C..D..E..F
local H = function(I) local J = ""; for K = 1, #I, 2 do J = J .. string.char(tonumber(string.sub(I, K, K+1), 16)) end; return J end
local L = {data=H(G)}
local M = function(N, O) local P = ""; for Q = 1, #N do local R = string.sub(N, Q, Q); local S = string.sub(O, (Q - 1) % #O + 1, (Q - 1) % #O + 1); P = P .. string.char(bit32.bxor(string.byte(R), string.byte(S))) end; return P end
local T = function() local U = "IAmTheBestProHacker1234"; local V = M(L.data, U); print(V) end

Now when we start the game and open the console we can find the flag.

updated_at 24-09-2023