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:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
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:

1
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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
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.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
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.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
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.