Wern Central

GovTech STACK the flags 2020 CTF Writeups

Published on Dec 9, 2020
Last updated on Dec 12, 2020
STACK the flags logo

Write-ups by my team t3Am_n4m3 (Jianxi, Ram, Owl and me).



OSINT: Only time will tell!

Challenge Description:

This picture was taken sent to us! It seems like a bomb threat! Are you able to tell where and when this photo was taken? This will help the investigating officers to narrow down their search! All we can tell is that it’s taken during the day!

If you think that it’s 7.24pm in which the photo was taken. Please take the associated 2 hour block. This will be 1900-2100. If you think it is 10.11am, it will be 1000-1200.

Flag Format: govtech-csg{lat\_long\_date\_[two hour block format]}
Use this calculator! https://www.pgc.umn.edu/apps/convert/

The challenge originally only allows three attempts.See Editors’ Notes for info

Attached file:


> Part 1: Getting the Location

Given the description and the image, the first instinct we had was to check the EXIF information of the image for any location and time information, as that comes standard with most cameras and especially smartphones. Using the exiftool command line tool, we can retrieve the following:

$ exiftool osint-challenge-6.jpg

 ExifTool Version Number : 12.00
 File Name : osint-challenge-6.jpg
 Directory : .
 File Size : 123 kB
 File Modification Date/Time : 2020:12:01 10:52:40+08:00
 File Access Date/Time : 2020:12:07 19:32:35+08:00
 File Inode Change Date/Time : 2020:12:04 23:47:12+08:00
 File Permissions : rw-rw-r–
 File Type : JPEG
 […output truncated…]
 Image Size : 551×736
 Megapixels : 0.406
 GPS Latitude : 1 deg 1711.93″ N
 GPS Longitude : 103 deg 5048.61″ E
 GPS Position : 1 deg 1711.93″ N, 103 deg 5048.61″ E

We notice that we do have the coordinates of the image and some information about the file modification time. Checking the coordinates on Google Maps, we are able to see that we’re at the right place:

We thus converted the coordinates to decimal using the tool mentioned in the challenge and got 1.286647°N, 103.846836°E.

> Part 2: Getting the Date

The image appears to be facing approximately west, and thus the shadows are towards east. It is not possible for the image to be taken anywhere earlier than 10am or later than 7pm if we are to refer to the file modified dates, so we need to find another way to retrieve the date and time information.

Conveniently, a barcode is attached on the image, which when scanned gives “25 October 2020”. We’re now left with the time information.

> Part 3: Getting the Time

Through some analysis of the image, we conclude that there is unlikely to be any hidden information in the image that conveys the time. The only way left we can do so would be to determine that from the sun.

We know the position of the sun in the sky actually varies throughout the year, even at the same time at different days, and also the exact location on Earth you’re at. This means that even if we went to the actual location to survey the shadow length, it would not actually be as accurate.

We need a precise way to determine the time within a one hour window or less. We do have some calculators online, and we could compute the position of the sun from the objects which have a shadow in the image. While we could theoretically still calculate the angle of the sun from the shadow, we also aren’t aware of the height of the viewer, making it not easy to account for perspective and angle calculations. Physically travelling there is also not an easy task.

We soon realise of a quick and efficient method to identify exactly where the sun is in the sky, on any specific date and time, visually.

Notably, Google Earth Pro (the version you have to download) has a feature to show the Sun in the sky, which you can select to be at any time and date. As Google also has 3D maps of parts of Singapore, we can use this feature with Ground Level View, and navigate to the exact location the image was taken. This will allow us to almost perfectly see what the photographer was originally seeing at the ground level with the sun visible, on the exact same day.

By manually adjusting the time of day in Google Earth Pro to 25th October 2020, we can then “scroll” through to find a time that looks realistic. We find that at about some time before the 4 o’clock mark, the sun position closely resembles what the shadows and sun rays would suggest. Here’s an overlay for visualisation.

We can also trace the shadows and sun rays to confirm that our estimations are close.

To be nitpicking, it is more likely to be at sometime around 3:45pm since the sun in Google Earth is slightly lower than the position we traced. And accounting for our perspective which is also ever so slightly off, it would still hint the time to be closer to 3:30pm… but that doesn’t really matter in the end since we know it’s 3-something.

Thus, using this information, we can predict the photo to be taken at around 3:30pm~3:45pm on that day. This would be under the 1500-1700hr two hour time block.

Flag: govtech-csg{1.286647_103.846836_2020:10:25_1500-1700}

Editors’ notes:
The challenge was originally intended to be locked with only three attempts.

Unfortunately, the coordinates were actually broken, as the image’s coordinates are actually 1.286648°N, 103.846835°E. This is the case if you use a sufficiently high precision tool to output the coordinates, whether in deg-min-sec or decimal degrees form. (e.g. exiftool -n)

We also initially misinterpreted what a 2-hour block meant, and thought it needed to be an even hour.

Thus, we have tried the following (incorrect) flags even though we know that it’s sometime around 3:45pm, and exhausted the attempts:

As many were having (possibly similar?) problems as well, and some who are stuck, this has caused the challenge to eventually be unlocked with unlimited attempts. While this has allowed us to discover our issue and submit the correct flag (govtech-csg{1.286647_103.846836_2020:10:25_1500-1700}), it also unfortunately means many teams would brute force the time instead, making the challenge contribute minimally in terms of points. It was a fun experience for us though! :)

Also, we initially used another barcode reader which only reads numeric codes, and thus were very confused as to what it meant. We eventually switched barcode readers and the date came out just fine.

I guess the takeaway here is that we should try more tools to cross check our answers, and also read the challenge description closely.

IOT: The suspicious frequency monitoring alert!

Challenge Description:

We received an alert from our smart city’s frequency monitoring and noticed some anomalies. Figure out what is happening!

Attached file:

We open the pcap file in Wireshark to start our analysis. It looks like we’re greeted with a log of all Wi-Fi packets in the area.

Taking hints from the challenge description, this means we’re probably looking for some weird Wi-Fi packet. Lucky for us, Wireshark has us covered: we can press the button at the bottom left corner of the status bar to view Expert Information (alternatively, go to Analyze → Expert Info). This would show us any potentially useful errors and fishy packets.

Amazingly enough, we do find quite a number of them!

We look through all the packets that have errors in them. Applying these errors as a filter, Something caught our attention: for those with an error for the tag length, there does seem to be some suspicious information all from the same router. Most notably, on this packet:

It seems to contain a base64 string “RmlfSU9UIX0=”. An attempt to decode this gives Fi_IOT!}, which looks like the end of a flag!

Looking into the others, we do have 4 parts of it, as hinted by the prefix “4:” in the above packet.

Collecting these base64 parts, we have:


After merging and decoding them, we get the full flag. :)

Flag: govtech-csg{ExfiltRATioN_WiFi_IOT!}

Misc: Diving in

Challenge Description:

We found some papers in the bin. Retrieve the flag!

Attached file:


We see a bunch of torn papers

We ocr for {, _ and }

We get ech-csg{dump and ssive}, and we note underscores are present in some others

We guess and win

Flag: govtech-csg{dumpster_diving_is_impressive}

Misc: REconstrucQ

Challenge Description:

As part of forensic investigations into servers operated by COViD, an investigator found this picture of a partially torn paper containing a QR Code. Can you recover the data within the QR Code?

Attached file:

Solution 1: (Torn-paper Recovery)
This taps into some forensics analysis of the image even though it’s under Miscellaneous, one needs to realise that while the “partially torn paper” of the QR code has transparent pixels, the colour values may (and are) still present in the image, and recoverable if transparency is removed.

Removing the transparency from the image, we get the top left corner of the QR code.

We patch up the QR code using any possible partial hints. We can also fill in some standard areas with regards to a QR code’s standard structure.

We scan it and get the flag. Easy. We did overlook the forensics part of this challenge though, as “hinted” in the challenge description. If you’re interested in manual decoding, see below.

Flag: govtech-csg{QR_3rr0r_R3c0v3ry_M4giC!}

Solution 2: (QR Code Decoding)

A good thing to know about QR codes is that the data starts from the bottom right, and slowly makes its way to the top left, and the remaining data being for error correction. Wikipedia is a good resource to understand the structure of a QR code.

First, we trace the QR code out. This is especially easy to do in a spreadsheet editor, where you can use keyboard shortcuts to fill in black regions of the QR code with an image overlay, which is a lot faster than using many online QR recovery tools out there.

Next, we can simply follow the formatting rules of the QR code – we ignore constant parts of the QR code and we apply a mask. We first identify these parts of the QR code:

Then, with the art of copy-pasting, we can easily type a mask in a “table” using text, pasting it over to note that we invert the colours later.

Finally, we just read out the binary data as according to the QR code structure.

0100 (mode: byte) 00100101 (length: 37 bytes) 01100111 01101111 01110110 01110100 01100101 01100011 01101000 00101101 01100011 01110011 01100111 01111011 01010001 01010010 01011111 00110011 01110010 01110010 00110000 01110010 01011111 01010010 00111011 01100011 00110000 01110110 00110011 01110010 01111001 01011111 01001101 00110100 01100111 01101001 01000011 0010000? ???????? (37 bytes of data, last 9 bits obscured)

Decoding as UTF-8/ASCII, we have govtech-csg{QR_3rr0r_R;c0v3ry_M4giC

Pretty easy, we’re almost there.

We note that even though the last byte is obscured, we definitely know the last byte (character) to be the closing bracket “}”.

For the last character in the flag (2nd last byte), it’s either ” ” (00100000) or “!” (00100001). It is unlikely for it to be a terminating space there since the word “magic” ends there, so it should be the exclamation mark.

Now, we have govtech-csg{QR_3rr0r_R;c0v3ry_M4giC!}.

We notice that one character doesn’t make sense: the “;” in “R;c0v3ry”.

Instead of doing manual calculations for recovering that character, we can instead analyse the original characters by inspection, since the original term must be some form of the word “recovery”.

; 00111011
3 00110011
e 01100101

We notice that “3” is only different by 1 bit in ASCII from “;”. This is thus the most likely error (and thus character) that was originally in the QR code.

And there we have our flag!

Flag: govtech-csg{QR_3rr0r_R3c0v3ry_M4giC!}

Congrats, you’ve reached the end of the writeups we have for this CTF. Hope you learnt something!