MagpieCTF 2023

Our third annual CTF will be a hybrid SPACE themed CTF where you will be responsible for stopping OmniFlag Corporation.

MagpieCTF 2023 was a jeapordy-style CTF team game. Teams consisted of five members, and I was on /etc/sudoers team, along with @rooted, @chickadee, @saccharide, and @chatgpt.

All assets for challenges are on my GitHub. University of Calgary (hosts of MagpieCTF) also have a repository for the challenges.

Web Exploitation

Chocolate Chips with Zero-G

Recon has found an old website from OmniFlags. We think there may be an insecure admin portal somewhere. See if there is anything you can find! They never did hire the best developers.

We can first start by checking robots.txt. This is a very common file to check during web exploitation challenges because websites use robots.txt to prevent crawlers from indexing certain files or directories. Our robots.txt mentions Disallow admin.html. Visiting /admin.html reveals a login panel. We can try to login, but no luck. Fortunately, it seems the website sets an admin cookie to false. Setting the cookie to true manually and then refreshing /admin.html will reveal the flag.

Education Comes First

An OmniFlags educational website has been hacked by one of the captives in the space prison, who we believe has left a message for us. Can you find it?

No writeup.

Binary Exploitation

No Password Here

Here is one of the vaults that have a flag we need. There's a message associated with the vault, written as follows:

Don't even think about trying the password because I do not know the password either. I already informed my employees not to use "gets" when writing programs so what could possibly go wrong?

Looking at the source, we can notice a few things off the bat:

char Test[20];
srand(time(0));
sprintf(Test, "%d",rand());	

char input[20];
scanf("%s",input);

First, the "password" is random and put into a char array with a size of 20. Then, the user's input is put into another char array of size 20. Because scanf is being used without specifying a string length (ie: %3s), we can buffer overflow input[] and get our input to flow into Test[]. This can be done by just typing a lot of 'a' into stdin, or more programmatically:

python3 -c "print('a'*40)" | ./code

This outta be large enough, right?

We've identified an OmniFlags service that seems to be running on a satelite somewhere. We were able to get a copy of the program, and we suspect that it may be exploitable for identifying a flag. See if you can find it.

No writeup.

OSINT

Space Span

As you know, OmniFlags is back on their high horse and think they can claim the rest of humanity and the solar system for themselves. We, of course, will not let that happen. Our recon squads have found a file of theirs leaked by someone named Rhonda Hooper and believe this can help stop them.

Searching Twitter for "Rhonda Hooper", and sorting by latest, reveals some tweets from @RhondaOmni. (https://twitter.com/search?q=Rhonda%20Hooper&src=typed_query&f=live). Specifically, there is a link to http://srv1.2023.magpiectf.ca:26233/, which contains the flag.

Do it Again

One of our recon squads has managed to sabotage the headquarters and recover a flag under a Twitter account that is made up of a name and a number. The person made a full report on the process of discovering the flag and sent it to us. However, the communication is disrupted and we do not know how much of the report got delivered and we also do not know where the message ended up at. Fortunately, it looks like one of their employees received part of the message and posted it on Twitter. Let's see if we can do something about it.

The challenge prompt links to a Twitter thread (https://twitter.com/JohnDoe20418691/status/1617755100549902339). The thread contains "1/4, 2/4, 3/4", but the fourth tweet of the thread appears to be missing. Checking WaybackMachine, there is a snapshot on Jan 24, that contains the missing reply.

"I received this strange image with the number 1248 next to it. Does anyone know what this means?"

Some basic Googling shows us that this screenshot was taken from the Wikipedia page for Alan Shepard. Following the name and number format, https://twitter.com/AlanShepard1248 takes us to the Twitter account with the flag.

Cryptography

Momma Says to Play Fair

We received an encrypted message from deep space. We think that someone is trying to smuggle a flag away from Omni-Flags. Decrypt the following message to get us one step closer to success:

The challenge includes two assets: enc.py and key_table.png. Just from the name, we assumed it was related to a Playfair cipher. You can write a decryption script by doing the inverse of enc.py: reverse the positions of the pairs in the ciphertext.

import string
import re

def decrypt(key, c):
    #Breaking the ciphertext down into pairs
    c=re.findall('.'*2,c)

    #Creating plaintext
    m=""
    for p in c:
        p0Index=(-1,-1)
        p1Index=(-1,-1)
        for x in range(len(key)):
            for y in range(len(key[0])):
                if key[x][y]==p[0]:
                    p0Index=(x,y)
                if key[x][y]==p[1]:
                    p1Index=(x,y)

        # if they are on the same row, append the character on its left to the plaintext
        if p0Index[0]==p1Index[0]:
            if(p0Index[1]!=0):
                m+=key[p0Index[0]][p0Index[1]-1]
            else:
                m+=key[p0Index[0]][len(key[0])-1]

            if(p1Index[1]!=0):
                m+=key[p1Index[0]][p1Index[1]-1]
            else:
                m+=key[p1Index[0]][len(key[0])-1]

        # if they are on the same column, append the character above to the plaintext
        elif p0Index[1]==p1Index[1]:
            if(p0Index[0]!=0):
                m+=key[p0Index[0]-1][p0Index[1]]
            else:
                m+=key[len(key)-1][p0Index[1]]

            if(p1Index[0]!=0):
                m+=key[p1Index[0]-1][p1Index[1]]
            else:
                m+=key[len(key)-1][p1Index[1]]

        # if they are not on the same row or column, copy the letter in the coloum of the other letter in the same row to the plaintext
        else:
            m+=key[p0Index[0]][p1Index[1]]+key[p1Index[0]][p0Index[1]]

    #Removing the appended Xs
    m=m.replace("X","")

    return(m)


key="TIME"
ext=string.ascii_letters+string.digits+"{}_"

# Taking out the characters in key
for chr in key:
    ext=ext.replace(chr,"")

# key table is compost of key, alphabets, digits from 0 to 9 and {}_
key+=ext

# break the key down into groups of 13
key=re.findall('.'*13,key)

ciphertext = "nEctTfwcH8P08nv4w{K0jT3Zn2K2A88k{Y"

plaintext = decrypt(key, ciphertext)

print("Plaintext:", plaintext)pyth3

Rubis

During our investigation of Omniflags, we came across a cluster of ships called Rubis that was used to store top-secret information randomly in one of the ships and would rotate this secret every few days to stop attackers from finding the secret. It has been long since Rubric was deprecated however, we found out Rubis still contains a key component that will assist in the rescue of the prisoners from the space prison. We managed to get the source code that was used to run Rubis and for better or for worse, Rubis is still running at srv2.2023.magpiectf.ca:20000. We need you to unlock the ship that contains the flag so we can save the prisoners.

No writeup.

Forensics

Space Exploration

We've intercepted a suspicious image file from an OmniFlags channel known to discretely transport flags. See if you can find anything of value here.

This challenge contained an image, Flag.png. I first the low-hanging fruits like strings and exiftool to see if there was anything noticable. Yielding no results, and knowing steghide doesn't support PNG, I uploaded it to Aperi'Solve, which runs a bunch of tools on uploaded images (exiftool, steghide, zsteg, outguess, etc). Further, it will extract specific color channels and superimpose. Looking at the superimposed images reveals the flag in the upper left corner.

So Meta

A member of ours involved in salvaging the many failed Omni-Flags projects has brought us these files. She found it in a half-destroyed computer from one of Omni-Flags deep space probes. They must have been experimenting with flag degredation during deep space flight, but it looks like we should still be able to recover the data.

No writeup.

There Is No Flag

One of our other branches has been working on finding a key flag from here, but weren't able to report anything back. They claim there is no flag to be found. We need you to confirm their findings, or ideally, prove them wrong.

We are given a Github repository, here https://github.com/Admin-is-here-GG/React. There are three previous commits. The first adds README.md, and the second added a binary called program. The third is the current state of the repository (a React app). We downloaded program and ran binwalk -eM program on it to try and carve out any files that might be hidden. This revealed 418C.zip, which when unzipped, extracted Flag.PNG. Trying to open Flag.PNG resulted in an error, and running file Flag.PNG yields:

file Flag.PNG
Flag.PNG: data

Looking at a hexdump of the file, we notice the first few bytes is 00504E47. The proper magic bytes for .png are 89 50 4E 47 0D 0A 1A 0A. Thus, we can see the first byte is incorrect. Instead of 00, it should 89 to be a proper png format. We can modify the bytes in any hex editor like ghex and then the image is no longer corrupted, revealing the flag.

Like An Onion II

One of the prisoners sent us this picture. See what you can find.

No writeup.

Reverse Engineering

Shredded

We found a batch of what seems to be a shredded document in the dumpster behind Omniflags headquarters. Can you put the pieces back together and find what the document says?

Missing Flag

We found an ancient Word document left off on one of the OmniFlags' computers. Does it contains any information useful to us?

We are provided a Microsoft Word document, with the extension .docm. This initially sets off intuition regarding VBA macros, because .docm is a macro-enabled Word document. Using oletools, you can use olevba to extract VBA macros from the document.

olevba where-is-the-flag.docm

This will reveal a VBA macro, galf():

Sub galf()
    Dim ajaofaer, faheior, vusirht, iruthvb, akjrhoeifr, nvritwh
    vusirht = Array("m", "a", "g", "p", "i", "e", "{", "f", "a", "k", "e", "f", "l", "a", "g", "}")
    iruthvb = 0
    For Each urhuerb In vusirht
        Selection.TypeText Text:=Asc(vusirht(iruthvb)) * 10
        iruthvb = iruthvb + 1
    Next
    
End Sub

The interesting things to note are that "Selection.TypeText" appends text to the Word document, and "Asc()" will get the ASCII representation of the character. This macro helps hint to what the original document text means:

1090970103011201050101012301190104012109501000490100095049095048011205101100950116010404901150950109052099011404809508408708401250

We can split the number into groups, and then get convert from ASCII to text. For example, the first few groups would be:

109 -> m
097 -> a
0103 -> g
0112 -> p
0105 -> i
0101 -> e

Take a Wild Guess

Recon has acquired for us a copy of the code to a top secret vault. Unfortunately we do not have the password. Try to unlock it, and possibly reveal a flag on the way.

No writeup.

Satshell

During one of the planned scavenges within the desolate Martian Omniflags headquarters, the team that was sent out located one of Omniflags' communication server rooms. Although greatly damaged from the The War of the Martians in 2189, a team of technicians were able to restart their server and hijack its network to be under our control. We understand that this server room once transmitted crucial data to the interplanetary operations of Omniflags and wish to retrieve it.

Upon further investigation, no vital information could be found within the server itself. However, as the scouting team were highly meticulous, they managed to find and scan pages of the attached internal user manual. Although we do not have the client program that the user manual discusses, the data recovery team was able to recover a binary program which seems to be associated with it.

We trust that you will be able to determine methods to use what we have given you to determine a way to read the secrets that Omniflags has been holding onto all this time. Please connect to :, the address where the program is hosted when you are ready.

Networks

Eavesdropper

According to recon, one of the captives has been sending flags discretely to our endpoints, and the key flag is going to have something to do with her favourite food. Unfortunately, you just can't remember what it was...

She's got a sweet tooth, so research has determined that it has to do with some kind of dessert, like cookies or cakes. What was her favourite flavour? vanilla? oreo? chocolate chip? Or maybe pistachio?

We are provided a packet capure (.pcapng). We can open this with Wireshark, and see a bunch of POST requests to localhost. All of these post requests contain a flag in the body of the request. However, they are all fake flags, and we have to somehow extract the real one. The issue is that there are over 10,000 packets.

We can use tshark to extract all of the POST bodies:

tshark -r nothing_to_see_here.pcapng -Y "http.request" -T fields -e http.file_data

This list can be parsed multiple ways, such as using regular expressions. However, @rooted used Nostril, which is a Python entropy-based string evaluator, and can determine if a string is meaningful or nonsense. Using this, we can lower the flags we have to check through, and we will find the correct flag.

What is the password?

Recon managed to capture some web traffic from OmniFlags and think they are onto something. It looks like they are transferring something but we cannot read it.

The pcap file provided shows HTTP traffic. We can use a nifty feature in Wireshark to extract any files that were sent over HTTP. File > Export Objects > HTTP will show Password.PNG, which we can save and reveal the flag.

Last updated