WelcomeCTF 2022
Foreword#
Second CTF from NUS Greyhats. Initially I do not have any intention of writing writeups as the time for the CTF is only a day, so the following writeups are based on my recollection of the event. The web challenges done are gone, as there is no file stored.
Challenges#
AmongUs#

This is a challenge involving image steganography. Not so difficult if you know the proper tooling for the challenge. AperiSolve should give a full overview of the file and make it trivial to solve this challenge.
A good list to consider for steganography challenges is this list of useful tools and resources for steganography by 0xRick. Hacktricks also provides a great list of tools to try out.
I did not know AperiSolve
beforehand, so solving this was a bit painful. After a bit of fiddling with zsteg
and other tooling for image steganography on Kali Linux
, I encountered the first tool needed for the challenge: foremost. binwalk
achieves the same - but the output is a bit messy. After running foremost
on the image given, we obtain the following output:
Foremost version 1.5.7 by Jesse Kornblum, Kris Kendall, and Nick Mikus
Audit File
Foremost started at Sat Aug 20 03:54:12 2022
Invocation: foremost -v amoonguss.png
Output directory: /home/kali/WelcomeCTF/AmongUs/output
Configuration file: /etc/foremost.conf
------------------------------------------------------------------
File: amoonguss.png
Start: Sat Aug 20 03:54:12 2022
Length: 237 KB (243493 bytes)
Num Name (bs=512) Size File Offset Comment
0: 00000000.png 152 KB 0 (475 x 475)
1: 00000305.png 85 KB 156264 (1800 x 1200)
Finish: Sat Aug 20 03:54:12 2022
2 FILES EXTRACTED
png:= 2
------------------------------------------------------------------
Foremost finished at Sat Aug 20 03:54:12 2022
The tool has found another image inside the original image. This image somewhat fits the title of the challenge.

Again, after a while of messing with image stegano tools, I eventually found out the solution of the problem. Looking at the Red channel of the image, we should be able see a hidden message - the flag of the challenge.

B#

A interesting challenge. We were provided with a GIF
of Nicholas Cage suffering from bees. Title of the challenge is also B
- so something has to do with the letter B. Only the GIF
is provided, hence this challenge should be a steganography challenge.
Using the steganography tools for GIF
does not return any usable data. But, when we look at the end of the output from the hexdump
of the GIF
, we can see something promising
001e9e00 3b bb 42 42 bb bb 42 42 42 bb 42 42 42 bb bb 42 |;.BB..BBB.BBB..B|
001e9e10 bb bb 42 42 bb bb 42 bb 42 bb 42 42 42 42 bb bb |..BB..B.B.BBBB..|
001e9e20 42 bb 42 42 bb 42 bb bb bb bb 42 42 bb bb bb bb |B.BB.B....BB....|
001e9e30 42 bb 42 42 42 bb 42 bb bb bb 42 42 42 bb bb 42 |B.BBB.B...BBB..B|
001e9e40 42 bb 42 42 42 42 bb 42 42 bb bb 42 42 bb bb bb |B.BBBB.BB..BB...|
001e9e50 bb bb 42 42 bb 42 bb bb bb bb 42 bb 42 42 42 42 |..BB.B....B.BBBB|
001e9e60 42 bb 42 42 bb 42 42 42 bb bb 42 bb bb 42 42 42 |B.BB.BBB..B..BBB|
001e9e70 42 bb 42 bb 42 42 42 42 42 bb 42 bb bb 42 42 42 |B.B.BBBBB.B..BBB|
001e9e80 bb bb 42 42 bb 42 42 42 42 bb bb 42 42 bb 42 42 |..BB.BBBB..BB.BB|
001e9e90 42 bb 42 bb 42 42 42 42 42 bb bb 42 42 bb 42 42 |B.B.BBBBB..BB.BB|
001e9ea0 42 bb 42 bb bb 42 bb bb bb bb bb 42 42 bb bb 42 |B.B..B.....BB..B|
001e9eb0 42 bb 42 bb 42 42 42 42 42 bb 42 bb bb bb bb 42 |B.B.BBBBB.B....B|
001e9ec0 bb bb 42 42 42 bb bb 42 42 bb bb 42 bb bb bb bb |..BBB..BB..B....|
001e9ed0 42 bb bb 42 bb bb bb bb 42 bb bb 42 bb bb bb bb |B..B....B..B....|
001e9ee0 42 bb 42 42 42 42 42 bb 42 |B.BBBBB.B|
001e9ee9
Seems like the letter B
(with hex value 42
), and the character .
(with hex value bb
) is alternating back and forth in the last bytes of the GIF
. This may suggest a binary string. A supposition we may have is that the character .
may represent the value 1
and the character B
may represent the value 0
in a binary string. If this does not provide any promising data, then we flip the value that each character represents.
Hence, from the above supposition, we obtain the following binary string:
0110011101110010011001010111100101101000011000010111010001110011011110110011000001101000010111110110111001001111010111110100111001101111001101110101111100110111010010000011001101011111010000100111001100100001001000010010000101111101
Putting this to CyberChef, we luckily found something meaningful - the flag itself.

Canon In D#
A misc challenge involving high-school level physics. We are tasked to solve the problem of free falling in 3D space of a object launched at a speed and orientation given by the server.
The only observation to solve the challenge is the fact that there is no forces acting on the cannonball other than gravity, hence the velocity in the x
and z
axis is the same. We can treat the velocity in the y
axis as a normal 1D problem of an object pulled by a force. Then it is just a matter of NOT messing up the signs of the velocity equations - very tricky without a solid understanding of Physics.
Solution Implementation
import math
from pwn import *
def solver(coord_1, coord_2):
g = -9.8
delta_time = coord_2[3] - coord_1[3]
v_x = (coord_2[0] - coord_1[0]) / delta_time
v_y = (coord_2[1] - coord_1[1]) / delta_time
z12_displacement = coord_2[2] - coord_1[2]
v_z1 = (2 * g * z12_displacement - (g * delta_time) ** 2) / (2 * g * delta_time)
v_z0 = v_z1 - g * coord_1[3]
z0_displacement = (v_z1 ** 2 - v_z0 ** 2) / (2 * g)
x = coord_1[0] - v_x * coord_1[3]
y = coord_1[1] - v_y * coord_1[3]
z = coord_1[2] - z0_displacement
v_zground = - math.sqrt(v_z0 ** 2 - 2 * g * z)
return ((x, y, z), (v_x, v_y, v_zground))
def main():
url = "34.143.157.242"
port = 8069
conn = remote(url, port)
while True:
line = conn.recvline()
if b'Round 1' in line:
break
coord_1 = eval(conn.recvline().decode())
coord_2 = eval(conn.recvline().decode())
result = solver(coord_1, coord_2)
conn.recvline() # Skip blank line
conn.sendline(bytes(str(result[0]), 'utf-8'))
conn.sendline(bytes(str(result[1]), 'utf-8'))
for i in range(99):
while True:
line = conn.recvline()
if b'Round' in line:
break
coord_1 = eval(conn.recvline().decode())
coord_2 = eval(conn.recvline().decode())
result = solver(coord_1, coord_2)
conn.sendline(bytes(str(result[0]), 'utf-8'))
conn.sendline(bytes(str(result[1]), 'utf-8'))
conn.recvline()
print(conn.recvline())
if __name__ == "__main__":
main()
Disney Endgame#
A simple challenge. Running diff
should give us the flag. The combined difference of the two files should yield the flag.
in the middle of third grade
in the middle of third ggrade.
And for our grand finale,
And for our grrand finale,
So, to you, Dale, my best friend,
So, to you, Dalee, my best friend,
- Yes, Ugly Sonic. That's the spirit.
- Yes, Uglyy Sonic. That's the spirit.
in the last two months...
in the last two monthhs...
Mad? No. I'd be pretty pathetic
Mad? No. I'd be pretty paathetic
after the show tonight?
aftter the show tonight?
- You are gross.
- You are grosss.
- "Case?"
- "{Case?"
And leave the top hat
And leave the toup hat
the Gouda, the Brie.
the GGouda, the Brie.
00:28:13,333 --> 00:28:14,684
00:28:113,333 --> 00:28:14,684
No! No. We just wanna buy
No! No. We just wanna buyy
00:28:34,541 --> 00:28:36,041
00:28:34,541 _-> 00:28:36,041
00:29:12,208 --> 00:29:14,625
00:29:12,208 --> 00:29:14,655
520
5200
Really? Meeting Sweet Pete, huh?
Really? Meeting Sweet Peten, huh?
00:30:24,416 --> 00:30:28,750
00:30:24,416 --> 00:30:28,751
- in the back of a truck!
- Cin the back of a truck!
00:30:51,541 --> 00:30:54,541
00:30:51,541 -_> 00:30:54,541
Oh, are you seeing someone?
Oh, are you seeingg someone?
00:31:06,666 --> 00:31:10,625
00:31:06,666 --> 00:31:10,620
- It could be my agent, Dave Bolinari!
- It could be my agent, Dave BoElinari!
00:37:36,958 --> 00:37:40,750
00:37:36,958 --> 00:37:40,755
00:38:28,208 --> 00:38:30,250
00:38:28,208 -->_00:38:30,250
So, if we could get a hold
SSo, if we could get a hold
00:39:57,333 --> 00:40:00,958
00:39:57,333 --> 00:40:01,958
of Rescue Rangers ever?
oof Rescue Rangers ever?
What? Of course I did.
WWhat? Of course I did.
00:42:18,750 --> 00:42:21,541
00:42:18,750_--> 00:42:21,541
looked exactly like... Oprah.
looked exactly like... BOprah.
00:42:49,958 --> 00:42:53,791
00:42:49,958 --> 00:42:53,794
of all of us together.
of all bof us together.
Okay, guys. Sweet Pete goes
Okay, guys. SweetY Pete goes
by all those goons?
by all those goons?!
Oh, come on! Episode 45!
Oh, come on! Episode_45!
00:43:40,291 --> 00:43:43,833
00:43:40,291 --> 00:43:43,831
for going behind my back, Steckler.
for going behind my bback, Steckler.
Flounder?
Fflounder?
00:51:02,166 --> 00:51:03,166
00:51:82,166 --> 00:51:03,166
00:54:36,333 --> 00:54:37,541
00:54:36,333 --> 00:54:37,540
Dale, we need to leave, now.
Ddale, we need to leave, now.
00:59:54,916 --> 00:59:57,291
00:59:54,916 --> 00:59:57,293
01:11:06,500 --> 01:11:09,458
01:11:06,500 --> 01:11:09,456
like you were second banana
like you were second bananaa
Gets solved
Gets solved}
It is too tedious to extract out the flag from eyeballing the diff
logs, so a Python script is used.
lines = [line.rstrip() for line in open('diff.txt')]
lines = list(filter(lambda a: a != "", lines))
original = lines[0::2]
alter = lines[1::2]
flag = ""
for i in range(len(original)):
o = original[i]
a = alter[i]
found_diff = False
for j in range(len(o)):
if o[j] != a[j]:
flag += a[j]
found_diff = True
break
if not found_diff:
flag += a[len(o)]
print(flag)
Grains#

A static-like image is given in the challenge. There is no information using AperiSolve
and binwalk
, or some image steganography techniques sometimes used in CTF like LSB steganography.
I did not solve this and only know the solution from looking at the chats of WelcomeCTF. This is a stereogram - commonly used for visual effect by deceiving the eye into thinking there is a 3D object created from overlaying two random pieces of colored pages.
The tool to solve this is magiceye. Dragging the image around a bit and we should be able to see the flag.

Multitrack Drifting#
We are given a soundtrack of the famous Yakuza 0
game. Only the soundtrack is given, and with a file with the extension of .aup
. Looking up the program associated with the file shows the result of Audacity.
Putting the given .aup
file to Audacity and open the spectrogram, then configuring the color and the timescale of the software, we should be able to see the text representation of the flag.

Single#
From the looks of the file given, we can immediately see this is a substitution cipher. A frequency analysis attack can be employed, using common letters, bigrams and trigrams from the English language.
There are tools online to automate this task. One such tool is at this link. Putting the content of single.txt
into the website should return the flag at the end of the file.
Triple#
We notice that the size of the three files given 1
, 2
, 3
and flag.pptx
is the same. And since the challenge is in the crypto
category, a guess for how we can solve this challenge is through the use of xor
-ing the files given.
A Python script can be written to xor
the files, but I was too lazy to do so. Hence, I found xor-files, a tool for XOR
for two or more files and get the result on a pipe.
We will XOR
the files that is given by the challenge, and the output after redirecting to a file and calling the command file
on the resultant file should tell us that it is a PowerPoint 2007+ file.
