UofTCTF 2024

forensics/Illusion Writeup

We’re given a PCAP file with a lot of traffic to and from one IP address. Looking into it, its mainly http traffic, with some calls to a cloned Google.com page, and a get request for an image. The requests to the images caught my interest, as they don’t return any image data, just a 200OK.

Wireshark traffic The GUID string looks like base64, but doesn’t decode to anything.

After a bit of Googling I came across this Medium blog talking about the trevorC2 Framework. In this post it mentions how the C2 framework will clone a webpage like Google.com, then it will send the C2 server data through the /images?guid parameter. Heres the config for the C2 Server.

URL = ("https://www.google.com")  # URL to clone to house a legitimate website
USER_AGENT = ("User-Agent: Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko")
ROOT_PATH_QUERY = ("/")
# THIS FLAG IS WHERE THE CLIENT WILL SUBMIT VIA URL AND QUERY STRING GET PARAMETER
SITE_PATH_QUERY = ("/images")
# THIS IS THE QUERY STRING PARAMETER USED
QUERY_STRING = ("guid=")
# THIS IS THE NAME USED IN THE COOKIE FOR THE COMMUNICATION SESSIONID
COOKIE_SESSIONID_STRING = ("sessionid")
# THIS IS THE LENGTH OF THE COMMUNICATION SESSIONID
COOKIE_SESSIONID_LENGTH = (15)
# STUB FOR DATA - THIS IS USED TO SLIP DATA INTO THE SITE, WANT TO CHANGE THIS SO ITS NOT STATIC
STUB = ("oldcss=")
# Turn to True for SSL support
SSL = False
CERT_FILE = ("")  # Your Certificate for SSL
# THIS IS OUR ENCRYPTION KEY - THIS NEEDS TO BE THE SAME ON BOTH SERVER AND CLIENT FOR APPROPRIATE DECRYPTION. RECOMMEND CHANGING THIS FROM THE DEFAULT KEY
CIPHER = ("Tr3v0rC2R0x@nd1s@w350m3#TrevorForget")
# Response for website when browsing directories that do not exist if directly going to SITE_PATH_QUERY
NOTFOUND=("Page not found.")
# Redirect the victim if browsing website to the cloned URL instead of presenting it. ON/OFF
REDIRECT =("ON")

This all matches what we found in the PCAP. So it’s safe to assume its using the TrevorC2 to communicate.

Looking at the source code we can see that to decode the transferred data we need to base64 decode it, then decrypt the AES.

def __init__(self, key):
        self.bs = 16
        self.key = hashlib.sha256(AESCipher.str_to_bytes(key)).digest()
...
def decrypt(self, enc):
        enc = base64.b64decode(enc)
        iv = enc[:AES.block_size]
        cipher = AES.new(self.key, AES.MODE_CBC, iv)
        return self._unpad(cipher.decrypt(enc[AES.block_size:])).decode('utf-8')

From this snippet we know that the IV is the first 16 bytes of the data, and the cipher is the sha256 of the key, which was Tr3v0rC2R0x@nd1s@w350m3#TrevorForget.

Using this information we can use cyberchef to make a recipe to decode the GUID data, we had to use 2 Base64 decodes rather than one. I’m assuming this is from the client base64 encoding it to send over HTTP. However, the flag is not in any of the exfil data. We do find that a flag.txt was created on the analysts desktop. As well as other traffic showing that there was a reverse shell on the system. CyberchefRecipe

The next step was the decode the instructions from the C2, to see if any of the commands contain the flag. The instructions from the C2 are taken from a commented stub at the bottom of the cloned Google pages. oldcss tag

The C2 Instructions are encoded similar to the the guid data, but there is only 1 base64 encoding. There’s a lot of requests with the oldcss stub, so I exported all the HTML objects, and then used grep to find all the matches. Grepping oldcss

The longest string caught my attention so I tried that first, and got the flag. getting the flag uoftctf{Tr3V0r_C2_1s_H4rd_T0_D3t3c7}