CSAW CTF Qualification Round 2024 Writeups

This is the writeup for my competition. It includes the solutions to the problems I solved during the contest, as well as some problems I managed to solve after the event. It's meant to share some of my thought processes, the techniques I learned, and the skills I acquired through solving these problems.

Competition website link:

  • https://ctf.csaw.io/

Backup of competition problems:

  • https://github.com/osirislab/CSAW-CTF-2024-Quals

INTRO

Flag ( Question )

Join our discord to get the flag.

https://discord.gg/csaw24-quals

Flag ( Solution )

OSIRIS Trivia ( Question )

Weren't always known as the Offensive Security, Incidence Response, and Internet Security Lab! Can you find out what our old domain was? Do not include the network protocol. Wrap your answer with csawctf{} .

author: bbtc33

OSIRIS Trivia ( Solution )

The fastest way for now should be to directly go to CTF Time and find the links to past records.

OSINT

Rickshaw ( Question )

I saw this cool vehicle while traveling around India. Unfortunately, I lost most of the image. This is all I have! Can you find the phone number of whomever manages this vehicle so I can contact them? DO NOT MAKE ANY CALLS Flag Format: csawctf{PhoneNumber} Replace spaces with dashes. Include the + and country code.

Rickshaw ( Solution )

After some research, it was found that the license plate starting with 77CD belongs to a vehicle used by personnel of the U.S. Embassy in India. By finding the relevant phone number, the flag was obtained.

Authentic Chinese Food ( Question )

I visited this gourmet restaurant a while back, but I'm worried about the health and safety rating of it. Could you check it for me? Oh, and before I forget, could you tell me when the building was built, as well as the name of the LLC that owns it? Flag Format: csawctf{HealthGrade_YearBuilt_LLCName} (Name does not include LLC, replace all spaces with _ )

Authentic Chinese Food ( Solution )

First, by using an image search, the approximate address of the store can be determined:

By searching on NYC Health ABCEats-Restaurants , you can find that the HealthGrade is Grade_Pending :

By checking New York City's Zoning & Land Use Map , you can see that the building year is listed as 1920 . However, some articles indicate that the exact construction year of the building in the image is 1931 . It seems both answers are considered correct.

By checking New York City Department of Finance Office of the City Register DOCUMENT SEARCH OPTIONS , you can find that the LLCname is BNN FULTON FLUSHING OWNER

Plane Spotting ( Question )

My friend swears he saw a Russian plane in the US this June, but I don’t believe him. He also says he saw it was parked next to a plane owned by an infamous former president!

Can you find the registration number of this Russian plane, the FAA airport code of where the plane was spotted parked next to the other, as well as the registration number of the plane owned by that president?

My friend also tells me that a few days earlier, ANOTHER Russian plane flew to the US. Find the city that Russian plane was closest to at 21:07:40 Z during its flight to the US!

Flag format: csawctf{RegistrationNumberRUS_AirportCode_RegistrationNumberUS_CityName}

Do not include any special characters (dashes, etc)

author: lpv2013

Plane Spotting ( Solution )

From the phrase infamous former president , it can be inferred that it refers to Trump. Although I'm not entirely sure how to define infamous , at least I know that during the competition, he was indeed the former president .

After some research, two related news articles can be found:

  • A news article related to Trump and a Russian plane (which I will later refer to as news_1 ):

    • https://www.verifythis.com/article/news/verify/donald-trump/yes-a-photo-of-trumps-plane-next-to-a-russian-plane-at-washington-dulles-airport-is-real/536-724e14dc-4609-4000-82d7-32f646bbfe63
  • The Russian plane news before the "Trump" incident (which I will later refer to as news_2 ):

    • https://en.as.com/latest_news/russian-plane-is-headed-to-us-airspace-what-is-its-direction-and-what-kind-of-aircraft-is-n/

From news_1 , the following information can be found:

From the above, we can see that the news_1 event involves a total of three planes, and we know that the required AirportCode for the problem is IAD , and the required RegistrationNumberRUS is RA96018 . In addition to this information, we also find that one of the planes, Trump Force One , is likely the other plane we are looking for. After some research, we find its registration number is N757AF .

Now, the only remaining piece of information is the CityName .

From news_2 , the following information can be found:

It was found that the other Russian plane is RA96019 , and the task is to determine which U.S. city this flight was closest to at 21:07:40 Z ( Z refers to UTC ).

By visiting FlightAware , you can search for the flight history of RA96019 over the past three months. In June 2024, a flight record over U.S. airspace can be found. By observing the detailed time and location charts of this flight record, the required CityName for the problem can be determined.

The flight record I found is as follows:

After using the Dateful Time Zone Converter , we need to find the location approximately 12 to 13 minutes after takeoff:

By matching the chart with Google Maps, you can determine that the CityName is Trenton :

Now all the elements needed to form the flag are in hand, and this is where the problem ends.

FORENSICS

ZipZipZip ( Question )

Brighten up at last with the flag

author: knight_

The problem provided a zip file.

ZipZipZip ( Solution )

After extracting, you'll get a clue and another compressed file. Continue extracting and you'll get another clue and compressed file. Repeat this process until there are no more files to extract.

Since there are many steps, it's best to write a script. While writing the script, you may need to consider your hard drive's capacity, so you can delete unnecessary files as you go.

Once everything is extracted, connect all the clues and decode them using base64 to get an image. Carefully examining the image will reveal the flag (if it's not visible, you may need to adjust the brightness). The image below is a screenshot after some searching and zooming in, and is not the exact image you'll see after decoding the base64 directly:

WEB

Playing on the Backcourts ( Question )

yadayada playing tennis like pong yadayada someone's cheating yadayada at least the leaderboard is safe!

author: smallfoot

https://backcourts.ctf.csaw.io

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
from flask import Flask, render_template, request, session, jsonify, send_file
from hashlib import sha256
from os import path as path

app = Flask(__name__)
app.secret_key = 'safe'

leaderboard_path = 'leaderboard.txt'
safetytime = 'csawctf{i_look_different_in_prod}'

@app.route('/')
def index() -> str:
cookie = request.cookies.get('session')

if cookie:
token = cookie.encode('utf-8')
tokenHash = sha256(token).hexdigest()

if tokenHash == '25971dadcb50db2303d6a68de14ae4f2d7eb8449ef9b3818bd3fafd052735f3b':
try:
with open(leaderboard_path, 'r') as file:
lbdata = file.read()

except FileNotFoundError:
lbdata = 'Leaderboard file not found'

except Exception as e:
lbdata = f'Error: {str(e)}'

return '<br>'.join(lbdata.split('\n'))

open('logs.txt', mode='w').close()
return render_template("index.html")


@app.route('/report')
def report() -> str:
return render_template("report.html")


@app.route('/clear_logs', methods=['POST'])
def clear_logs() -> Flask.response_class:
try:
open('logs.txt', 'w').close()

return jsonify(status='success')

except Exception as e:
return jsonify(status='error', reason=str(e))


@app.route('/submit_logs', methods=['POST'])
def submit_logs() -> Flask.response_class:
try:
logs = request.json

with open('logs.txt', 'a') as logFile:
for log in logs:
logFile.write(f"{log['player']} pressed {log['key']}\n")

return jsonify(status='success')

except Exception as e:
return jsonify(status='error', reason=str(e))


@app.route('/get_logs', methods=['GET'])
def get_logs() -> Flask.response_class:
try:
if path.exists('logs.txt'):
return send_file('logs.txt', as_attachment=False)
else:
return jsonify(status='error', reason='Log file not found'), 404

except Exception as e:
return jsonify(status='error', reason=str(e))


@app.route('/get_moves', methods=['POST'])
def eval_moves() -> Flask.response_class:
try:
data = request.json
reported_player = data['playerName']
moves = ''
if path.exists('logs.txt'):
with open('logs.txt', 'r') as file:
lines = file.readlines()

for line in lines:
if line.strip():
player, key = line.split(' pressed ')
if player.strip() == reported_player:
moves += key.strip()

return jsonify(status='success', result=moves)

except Exception as e:
return jsonify(status='error', reason=str(e))


@app.route('/get_eval', methods=['POST'])
def get_eval() -> Flask.response_class:
try:
data = request.json
expr = data['expr']

return jsonify(status='success', result=deep_eval(expr))

except Exception as e:
return jsonify(status='error', reason=str(e))


def deep_eval(expr:str) -> str:
try:
nexpr = eval(expr)
except Exception as e:
return expr

return deep_eval(nexpr)


if __name__ == '__main__':
app.run(host='0.0.0.0')

Playing on the Backcourts ( Solution )

It was found that the /get_eval path executes code, so I just need to send the following payload to get the flag:

1
open('leaderboard.txt', 'r').read().strip()

REV

Baby Rev ( Question )

I stashed the flag under a rock. Still don't get all the grumbling about "Security Through Obscurity!"

author: gummiebear

The problem provided a binary file.

Baby Rev ( Solution )

When dynamically executing, the flag-related value will directly appear in memory. After reading it out and decoding it with base64, the flag can be obtained.

Magic Tricks ( Question )

The problem provided a binary file and a flag that has been modified by certain actions.

Magic Tricks ( Solution )

After reverse engineering, it was found that the program performs some replacement operations on the input, converting it into a string with a specific encoding. You just need to write a test program to test all ASCII printable characters, and then compare it with the modified flag provided in the problem to deduce the original flag.

PWN

Diving Into Null ( Question )

Oops, I rm -rf 'ed my binaries

author: sproutmaster

1
nc null.ctf.csaw.io 9191

Diving Into Null ( Solution )

After connecting, you will get a shell, but many basic commands cannot be used. Typically, you would need to use ls to find the flag and cat to print the flag. So far, I've found the following commands that can be used:

1
2
3
cd
pwd
echo

You can use echo to approximate the functionality of ls . The relevant usage is as follows:

1
2
echo *
echo .*

You can find the .flag file in the home directory, and then use echo to print it out:

1
echo "$( < .flag)"