Skip to content

Commit be2ab53

Browse files
committed
uoftctf25
1 parent a20ff43 commit be2ab53

26 files changed

+140
-0
lines changed

_posts/2025-01-14-UofTCTF.md

+140
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
---
2+
title: UofTCTF 2025 Write up
3+
author: D_C4ptain
4+
date: 2025-01-14 10:15:00 +0300
5+
categories: [CTF, write up]
6+
tags: [UofTCTF, University of Toronto CTF, Zellic, Dataflow Security, jeopardy, Capture The Flag, fr334aks-mini, fr334aks, secure code, python, math, mathematics]
7+
---
8+
9+
10+
![image.png](/assets/img/posts/ctf/uoftctf25/1.png)
11+
12+
Hello there, over the Weekend we - [Fr334aks-mini](https://www.linkedin.com/company/83010158/) got a chance to play University of Toronto CTF and emerged at the 377th place.
13+
14+
UofTCTF 2025 was a jeopardy-style CTF that run from Sat, 11 Jan. 2025, 03:00 EAT — Mon, 13 Jan. 2025, 03:00 EAT. It was organized by the [UofTCTF team](https://ctftime.org/team/139261), [Dataflow security](https://dfsec.com/) and [Zellic](https://www.zellic.io/), with classic categories like web, pwn, crypto, rev, forensics, and misc.
15+
16+
Let’s look at one of the challenges we solved: this was particularly in the "Miscellaneous" category.
17+
18+
19+
<h1 data-toc-skip>Misc</h1>
20+
## Math Test
21+
22+
![mt1.png](/assets/img/posts/ctf/uoftctf25/mt1.png)
23+
24+
Looking at the given server, we are greeted with some easy math questions that I noticed I would spend the whole day solving.
25+
26+
![mt2.png](/assets/img/posts/ctf/uoftctf25/mt2.png)
27+
28+
![abort.gif](/assets/img/posts/ctf/uoftctf25/abort.gif)
29+
30+
Let's find what we have in the zip.
31+
We are given a zip file that upon extracting we get this python file.
32+
33+
```python
34+
import random
35+
from flag import FLAG
36+
37+
def genRandMath():
38+
eqn = f'{random.randint(-1000, 1000)}'
39+
eqn = f"{eqn} {random.choice(['+', '*', '-', '//'])} {random.randint(-1000, 1000)}"
40+
while random.randint(0, 3) != 1:
41+
eqn = f"{eqn} {random.choice(['+', '*', '-', '//'])} {random.randint(-1000, 1000)}"
42+
try:
43+
res = eval(eqn)
44+
return eqn, res
45+
except ZeroDivisionError:
46+
return genRandMath()
47+
48+
print("Welcome to a simple math test.")
49+
print("If you solve these basic math questions, I will give you the flag.")
50+
print("Good Luck")
51+
52+
for i in range(1000):
53+
eqn, correct = genRandMath()
54+
print(f"Question: {eqn}")
55+
res = int(input("Answer: "))
56+
if res != correct:
57+
print(f"Wrong!! Correct answer is {correct}")
58+
exit()
59+
60+
print(f"Correct {i+1}/1000")
61+
62+
print(f"Congratz! Here is the flag {FLAG}")
63+
```
64+
65+
66+
### Code analysis
67+
The script presents an interesting math challenge where a user must correctly solve 1,000 randomly generated math problems to receive the flag (stored FLAG variable in another module).
68+
69+
Key Features:
70+
71+
: Each problem is randomly unique, making it difficult to predict or automate.
72+
: The script provides instant feedback on whether the user's answer is correct or not.
73+
: Users must solve all 1,000 questions correctly without a single mistake to get a flag.
74+
75+
The challenges:
76+
77+
: There is a high likelihood of incorrectly solving over 1,000 questions with a single shot each.
78+
: I couldn't find a way to view the FLAG without answering all questions correctly.
79+
80+
### Solution
81+
82+
The questions were easy but the only way to do it swiftly is auto-ing the process.
83+
84+
I made a script that read the questions, computed the answers, and send them back to the server.
85+
86+
```python
87+
# Author: D_C4ptain
88+
89+
import socket
90+
91+
def Mtest(ip, port):
92+
# Connect to server
93+
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
94+
s.connect((ip, port))
95+
print(f"Connected to {ip}:{port}")
96+
97+
# Receive from server
98+
while True:
99+
data = s.recv(1024).decode()
100+
if not data:
101+
break
102+
print(data)
103+
104+
# Check for question
105+
if "Question:" in data:
106+
# Extract math challenge
107+
try:
108+
question = data.split("Question:")[1].split("\n")[0].strip()
109+
# Solve math
110+
answer = eval(question)
111+
except (ZeroDivisionError, IndexError, SyntaxError) as e:
112+
print(f"Error processing question: {e}")
113+
answer = 0
114+
115+
# Send the answer back
116+
s.sendall(f"{answer}\n".encode())
117+
elif "Congratz!" in data or "flag" in data:
118+
# Print flag and exit
119+
print(data)
120+
break
121+
122+
Mtest("34.66.235.106", 5000)
123+
```
124+
Running this:
125+
126+
![mt3.png](/assets/img/posts/ctf/uoftctf25/mt3.png)
127+
128+
This took a few minutes but totally worth it.
129+
130+
![mt4.png](/assets/img/posts/ctf/uoftctf25/mt4.png)
131+
132+
```
133+
uoftctf{7h15_15_b451c_10_7357_d16u153d_45_4_m47h_7357}
134+
```
135+
136+
See you in another CTF!
137+
138+
And remember, there are many ways of killing Jerry!
139+
140+
![jerry.webp](/assets/img/posts/ctf/uoftctf25/jerry.webp)

assets/img/posts/ctf/uoftctf25/1.png

24.1 KB
Loading
351 KB
Loading
267 KB
Binary file not shown.
20.1 KB
Loading
41.1 KB
Loading
128 KB
Loading
30.3 KB
Loading

0 commit comments

Comments
 (0)