Post thumbnail

STACK the Flags 2020 Write-ups

Thursday, 10 Dec 2020
Authors:

STACK the Flags is a Cybersecurity Capture-the-Flag (CTF) competition organised by GovTech Cyber Security Group. 2020 marks the first year where this competition was held. It spanned 3 days, with the challenge portal opening from 2100h on Friday, 4 Dec 2020 up to 2245h on Sunday, 6 Dec 2020. Although initially intented to only last 48 hours, a 1h 45min extension was added to the total competition duration as the file-hosting server became unavailable due to quota limits.

Table of Contents

About our Team

I participated in the Junior College category under the team name 0x4841434b.

Challenges

There were 11 different categories of challenges, namely:

  • Binary Exploitation
  • Cloud
  • Cryptography
  • Forensics
  • Internet of things (IoT)
  • Miscellaneous
  • Mobile
  • Open Source Intelligence (OSINT)
  • Reverse Engineering (RE)
  • Social Engineering (SE)
  • Web

The challenges were not released all at once, but instead form a “prerequisite tree”. Hence, we were unable to view some challenges by the end of the competition. There was also dynamic scoring — the more teams solved a particular challenge, the less points it awards. The challenges we were able to solve are listed below:

Forensics

[Forensics-1] Walking down a colourful memory lane

“Walking down a colourful memory lane” is a challenge listed under the category “Forensics”. It was initially worth 1000 points, and by the end of the CTF, 6 teams had solved it and as a result it was down due to 992 points due to dynamic scoring.

Challenge Description

We are trying to find out how did our machine get infected. What did the user do?

How we did it

We were given a memory dump, forensics-challenge-1.mem. As such, I fired up my Ubuntu Virtual Machine and examined it using volatility -f forensics-challenge-1.mem imageinfo. This returned the profile of Win7SP1x64. Using this together with the pslist plugin, we were given a list of processes.

$ volatility -f forensics-challenge-1.mem --profile=Win7SP1x64 pslist
Volatility Foundation Volatility Framework 2.6
Offset(V)          Name                    PID   PPID   Thds     Hnds   Sess  Wow64 Start                          Exit
------------------ -------------------- ------ ------ ------ -------- ------ ------ ------------------------------ ------------------------------
0xfffffa8018dac040 System                    4      0     86      572 ------      0 2020-12-03 08:51:24 UTC+0000
0xfffffa8019355b30 smss.exe                240      4      2       29 ------      0 2020-12-03 08:51:24 UTC+0000
0xfffffa8019f07950 csrss.exe               324    316      9      458      0      0 2020-12-03 08:51:25 UTC+0000
0xfffffa8018db2060 wininit.exe             376    316      3       75      0      0 2020-12-03 08:51:25 UTC+0000
0xfffffa8018db15d0 csrss.exe               388    368     13      611      1      0 2020-12-03 08:51:25 UTC+0000
0xfffffa801a12c060 winlogon.exe            424    368      5      112      1      0 2020-12-03 08:51:25 UTC+0000
0xfffffa801a12fb30 services.exe            480    376      7      207      0      0 2020-12-03 08:51:25 UTC+0000
0xfffffa801a1797c0 lsass.exe               496    376      6      569      0      0 2020-12-03 08:51:25 UTC+0000
0xfffffa801a17db30 lsm.exe                 504    376     10      146      0      0 2020-12-03 08:51:25 UTC+0000
0xfffffa801a1c7b30 svchost.exe             612    480     10      356      0      0 2020-12-03 08:51:25 UTC+0000
0xfffffa801a1aa780 vm3dservice.ex          672    480      3       45      0      0 2020-12-03 08:51:25 UTC+0000
0xfffffa801a234060 svchost.exe             708    480      8      285      0      0 2020-12-03 08:51:25 UTC+0000
0xfffffa801a2592a0 svchost.exe             756    480     22      515      0      0 2020-12-03 08:51:25 UTC+0000
0xfffffa801a2cf5f0 svchost.exe             868    480     15      370      0      0 2020-12-03 08:51:26 UTC+0000
0xfffffa801a2fab30 svchost.exe             908    480     32      948      0      0 2020-12-03 08:51:26 UTC+0000
0xfffffa801a331230 svchost.exe             252    480     22      770      0      0 2020-12-03 08:51:26 UTC+0000
0xfffffa801a34cb30 svchost.exe             500    480     19      478      0      0 2020-12-03 08:51:26 UTC+0000
0xfffffa801a3ee4c0 spoolsv.exe            1184    480     13      261      0      0 2020-12-03 08:51:26 UTC+0000
0xfffffa801a408b30 taskhost.exe           1196    480      8      154      1      0 2020-12-03 08:51:26 UTC+0000
0xfffffa801a4158a0 svchost.exe            1244    480     19      313      0      0 2020-12-03 08:51:26 UTC+0000
0xfffffa801a51eb30 VGAuthService.         1448    480      3       84      0      0 2020-12-03 08:51:27 UTC+0000
0xfffffa801a55f630 vmtoolsd.exe           1472    480     10      270      0      0 2020-12-03 08:51:27 UTC+0000
0xfffffa801a4c4630 sppsvc.exe             1672    480      5      151      0      0 2020-12-03 08:51:27 UTC+0000
0xfffffa801a643b30 WmiPrvSE.exe           1852    612      9      196      0      0 2020-12-03 08:51:27 UTC+0000
0xfffffa801a6695e0 dllhost.exe            1912    480     13      185      0      0 2020-12-03 08:51:27 UTC+0000
0xfffffa801a6ae380 svchost.exe            2024    480      7       97      0      0 2020-12-03 08:51:28 UTC+0000
0xfffffa801a6ba060 msdtc.exe              1276    480     12      145      0      0 2020-12-03 08:51:29 UTC+0000
0xfffffa801917f060 WmiPrvSE.exe           2264    612      6      206      0      0 2020-12-03 08:51:47 UTC+0000
0xfffffa801a54e130 dwm.exe                2444    868      5      118      1      0 2020-12-03 08:51:58 UTC+0000
0xfffffa801a3dd7f0 explorer.exe           2460   2432     32      905      1      0 2020-12-03 08:51:58 UTC+0000
0xfffffa801a846b30 vm3dservice.ex         2548   2460      2       53      1      0 2020-12-03 08:51:59 UTC+0000
0xfffffa801a8ceb30 vmtoolsd.exe           2556   2460      8      166      1      0 2020-12-03 08:51:59 UTC+0000
0xfffffa801a91a060 SearchIndexer.         2704    480     13      648      0      0 2020-12-03 08:52:05 UTC+0000
0xfffffa801a9bfb30 wmpnetwk.exe           2876    480     15      226      0      0 2020-12-03 08:52:05 UTC+0000
0xfffffa801a9cab30 svchost.exe            2964    480     18      246      0      0 2020-12-03 08:52:05 UTC+0000
0xfffffa801a5d27c0 svchost.exe            1240    480     13      332      0      0 2020-12-03 08:53:27 UTC+0000
0xfffffa801a84e060 audiodg.exe            2376    756      5      126      0      0 2020-12-03 09:08:22 UTC+0000
0xfffffa80199e6a70 chrome.exe             2904   2460     33     1694      1      0 2020-12-03 09:10:20 UTC+0000
0xfffffa801a1d5b30 chrome.exe              852   2904     10      170      1      0 2020-12-03 09:10:20 UTC+0000
0xfffffa801998bb30 chrome.exe             1392   2904     10      274      1      0 2020-12-03 09:10:20 UTC+0000
0xfffffa801a91d630 chrome.exe              692   2904     13      225      1      0 2020-12-03 09:10:20 UTC+0000
0xfffffa8019989b30 chrome.exe             1628   2904      8      152      1      0 2020-12-03 09:10:21 UTC+0000
0xfffffa801a84cb30 chrome.exe             1340   2904     13      280      1      0 2020-12-03 09:10:24 UTC+0000
0xfffffa801acbeb30 chrome.exe             1112   2904     14      251      1      0 2020-12-03 09:10:27 UTC+0000
0xfffffa801acd8b30 chrome.exe              272   2904     14      239      1      0 2020-12-03 09:10:27 UTC+0000
0xfffffa801acd1060 chrome.exe             1648   2904     13      227      1      0 2020-12-03 09:10:28 UTC+0000
0xfffffa801acedb30 chrome.exe             3092   2904     13      212      1      0 2020-12-03 09:10:28 UTC+0000
0xfffffa801ad0eb30 chrome.exe             3160   2904     15      286      1      0 2020-12-03 09:10:29 UTC+0000
0xfffffa801ad3cb30 chrome.exe             3220   2904     15      295      1      0 2020-12-03 09:10:30 UTC+0000
0xfffffa801ad3ab30 chrome.exe             3240   2904     13      218      1      0 2020-12-03 09:10:30 UTC+0000
0xfffffa801ad8d060 chrome.exe             3320   2904     13      218      1      0 2020-12-03 09:10:32 UTC+0000
0xfffffa801ad9eb30 chrome.exe             3328   2904     13      231      1      0 2020-12-03 09:10:33 UTC+0000
0xfffffa801addfb30 chrome.exe             3380   2904     13      304      1      0 2020-12-03 09:10:34 UTC+0000
0xfffffa801ad9ab30 chrome.exe             3388   2904     13      283      1      0 2020-12-03 09:10:34 UTC+0000
0xfffffa801ae269e0 chrome.exe             3444   2904     13      231      1      0 2020-12-03 09:10:38 UTC+0000
0xfffffa801ae2e7d0 chrome.exe             3456   2904     12      196      1      0 2020-12-03 09:10:42 UTC+0000
0xfffffa801ae63060 chrome.exe             3568   2904     12      222      1      0 2020-12-03 09:10:44 UTC+0000
0xfffffa801ae89b30 chrome.exe             3584   2904      9      173      1      0 2020-12-03 09:10:45 UTC+0000
0xfffffa801aed8060 notepad.exe            3896   2460      5      286      1      0 2020-12-03 09:10:52 UTC+0000
0xfffffa801aeb5b30 chrome.exe             2492   2904     12      171      1      0 2020-12-03 09:10:58 UTC+0000
0xfffffa801af22b30 chrome.exe             1348   2904     12      171      1      0 2020-12-03 09:10:59 UTC+0000
0xfffffa801af63b30 chrome.exe             3232   2904     12      182      1      0 2020-12-03 09:11:00 UTC+0000
0xfffffa801af9d060 chrome.exe             4192   2904     12      168      1      0 2020-12-03 09:11:02 UTC+0000
0xfffffa801afaf630 chrome.exe             4268   2904     12      171      1      0 2020-12-03 09:11:04 UTC+0000
0xfffffa801afa6b30 chrome.exe             4324   2904     14      180      1      0 2020-12-03 09:11:04 UTC+0000
0xfffffa801afbeb30 chrome.exe             4380   2904     12      179      1      0 2020-12-03 09:11:04 UTC+0000
0xfffffa801ac4d060 RamCapture64.e         4832   2460      6       70      1      0 2020-12-03 09:11:24 UTC+0000
0xfffffa80199c3060 conhost.exe            4840    388      2       50      1      0 2020-12-03 09:11:24 UTC+0000
0xfffffa801ae055d0 dllhost.exe            4508    612      6 57728600      1      0 2020-12-03 09:12:23 UTC+0000

We see that there are a lot of chrome.exe processes. Given this is not normal of an idle machine, and the hint in the challenge description to find out “What did the user do?”, I did some online research, and discovered a Volatility plugin we can download called chromehistory. This gave us a list of visited URLs, among which, this MediaFire Link.

Downloading the PNG file gives us the following image:

The PNG file we downloaded after poking through the Chrome history.

(Yes, it is a really small image).

Judging from the small image, especially the fact that it is only 1 pixel high, I had the guess that the flag must be hidden inside this image, since poking around the rest of the memory dump did not give me anything.

So I fired up Python:

from PIL import Image
import numpy as np
pic = Image.open('This is a png file.png') file
pix = np.array(pic.getdata()).reshape(pic.size[0], pic.size[1], 3)
for pixel in pix:
    print(''.join([chr(o) for o in pixel[0].tolist()]), end = '')

Using some Python programming to convert the R, G and B values of the individual pixels into ASCII, we got the flag.

Flag: govtech-csg{m3m0ry_R3dGr33nBlu3z}

[Forensics-2] Voices in the head

“Voices in the head” is a challenge listed under the category “Forensics”. It was initially worth 2000 points, but by the end of the CTF, 26 teams had solved it and it was down due to 1692 points due to dynamic scoring, although it should be noted that almost no one got it for the first 2 days; it was only after they released a free hint on the morning on the last day that other teams started to be able to solve it.

Challenge Description

We found a voice recording in one of the forensic images but we have no clue what’s the voice recording about. Are you able to help?

How we did it

We were given a WAV file. Again with the voice recordings, much like Beep Boop, I don’t know what I was on that first day, but simply from hearing the WAV file we were given, I immediately knew we had to get a spectrogram of the image. After searching online for quite a while, we finally found this site, which gave us the following spectrogram:

The decoded WAV file

The = sign made it look like a Base64 code. Sure enough, copying the characters by hand and plugging it in into a Base64 decoder, we got https://pastebin.com/jETj2uUb as the decoded text.

However, the pastebin contents were:

++++++++++[>+>+++>+++++++>++++++++++<<<<-]>>>>++++++++++++++++.------------.+.++++++++++.----------.++++++++++.-----.+.+++++..------------.---.+.++++++.-----------.++++++.

It took us way too long to realise it was the Brainfuck programming language. I had had a hunch that it was a programming language just purely from its syntax, but I could not figure out which programming language it was. In fact, we only figured it out after the CTF was over.

Passing it through an online Brainfuck decoder, we get thisisnottheflag as the decoded string.

This is where the free hint came into play. It turns out, upon inspection using Xiao Steganography, we discovered that there was a hidden ZIP file inside our original WAV file given to us. Using thisisnottheflag as the extraction password, we got a ZIP file successfully extracted.

This ZIP file contained a Microsoft Word document, however it was unfortunately encrypted, but since we got the ZIP file already, we could try to run strings on it, and sure enough, it gave us the flag:

$ strings extracted.zip | grep -i govtech
govtech-csg{Th1sisn0ty3tthefl@g}PK

Flag: govtech-csg{Th1sisn0ty3tthefl@g}

Miscellaneous

[Misc-1] Welcome Challenge

Description

Welcome to STACK the Flags 2020! This is a welcome challenge to get you started. Can you find the flag hidden on our website? (Please DO NOT attack/scan the web service! The challenge does not require you to attack the site, subdomains, or root domain!)

Key points

  • The aim of the challenge was to find a flag hidden on the website: https://ctf.tech.gov.sg/. My first instinct was that the flag was hidden in a comment in the page’s source code, but a quick check revealed that this was not the case. Closer inspection of the source code revealed no suspicious links that could have been used to hide the flag.
  • The next thing I tried was looking for subpages on the website such as appending “/2020/welcome” to the end of the url, given that other subpages were in a similar format, but trying some common ones yielded nothing.
  • With the admins’ hint to treat this as an OSINT challenge and their phrasing of “find the flag hidden ‘on’ the website”, I began to suspect that the flag was not actually hidden on the website itself but another related website instead. Inspection of the website showed links to other websites under the “About Us” section, which did not seem to contain the flag. The bottom left of the home page also revealed that the website was built using Isomer. I then accessed the Isomer website to see if there was any information about the CTF website that I could exploit.
  • The guide to Isomer provided a few links, such as a Facebook group (which I concluded did not contain the flag) as well as a GitHub page. Scrolling through led to a repository titled `, which contained the flag in the README.

Flag: govtech-csg{W3lcom3_to_ST4CK_TH3_FL4GS_2o2o!}

[Misc-2] Beep Boop

“Beep Boop” is a challenge listed under the category “Miscellaneous”. It was initially worth 1000 points, but by the end of the CTF, 32 teams had solved it and it was down due to 730 points due to dynamic scoring.

Challenge Description

As part of forensic investigations into servers operated by COViD, an investigator found this sound file in a folder labeled “SPAAAAAAAAAAAAAAAAAACE”. Help us uncover the secret of the file.

How we did it

We were given an attached WAV file.

I solved this challenge almost immediately after the competition started. For some reason, the moment I played the WAV file and listened to it, I just knew that it was a Slow-Scan Television (SSTV) signal, and the description only made me a bit more confused. I knew that we could use the Robot36 Android App to decode such signals, so I immediately tried to load it on my phone. However, I couldn’t seem to find a way to open a file on Robot36, instead of just using the device microphone.

Eventually, after 10 minutes of searching online, trying to figure out how to do it, I still couldn’t figure out how to do it… and then I remembered I had a spare phone. Luckily, this competition was done online and not at a physical venue, so I could just blast the painful audio over the speakers and let my phone mic pick it up.

As expected, it decoded the signal and I got the flag.

We found this challenge was very easy

Flag: govtech-csg{C00L_SL0w_Sc4n_T3L3v1S1on_tR4nsM1ss10N}

P.S.: I only found out that SSTV was used in Space transmissions only later when I was researching more about the clue. Now that I think of it, the description would have made the chalenge much easier for those who were not familiar with slow-scan television signals.

[Misc-3] FWO FWF

Description

As part of forensic investigations into servers operated by COViD, an investigator found this web server containing a hidden secret. Help us find the contents of this secret.

Solution

Upon entering the link given in the challenge description, we can see the following letters :

https://lh5.googleusercontent.com/FhAKKTPXpukjGfkD1moiYJCRnGwU-SfgZn6qDp-TMcEpK7zM9Cp_3uIiZkae2W8taeRQzk4_JM_SAHO6g76g5HaQ8mn-A9Woa1zCVAM1Cn42b0UnnU99wxHDr1Dh48VBuZ85yeal

A quick inspection of the page source shows that there are three different font styles, with only the third being visible.

https://lh6.googleusercontent.com/9M7QphaUw_Sk0VfTXhFuV5CrBHE_4n3d0TmmuY4fhZLg8A7DGssa_RTCw-dtfKQ8pRGDr5KXBZ5bPym2yxrutBaScmgRBrVa2OpOX3YsMO3BZ7J-kOcIybOAxGLpIVmRDxCefx5G

When we edit it such that only selector .a is visible,

https://lh4.googleusercontent.com/Rn_etanJH52ZXkcZrPF8ACWqkoEtUmLFm64mrzdPa1LfceYE7NKuTNL3erXzdV7oMcoxt7aIJ-_iXjBeHFiLr3a7FE3AahfID9FW1fj8Ne4VXJCyiE4kzxVzsHGuhI_X8oGB4-gf

we get the message : THE FLAG IS HIDDEN IN A FILE

When we edit it such that only selector .b is visible, we get the message: CSG.TXT

Initially, we tried adding CSG.txt to the end of the URL (which did not work). However, upon adding CSG.TXT, we get the following: Rmo0Y19HdTNfZkdsWTNfaTFmMW8xWTFHbAo=.

The ‘=’ at the end of the string indicates that it is probably Base64 encoded. Hence, we decrypted it from Base64 using CyberChef to get : Fj4c_Gu3_fGlY3_i1f1o1Y1Gl.

We then carried out ROT13 to get the flag.

Flag: Sw4p_Th3_sTyL3_v1s1b1L1Ty

[Misc-5] Emmel

Note that this challenge involves a web server. It has been cloned to create a preview-only and non-functional mockup.

“Emmel” is a challenge listed under the category “Miscellaneous”. It was initially worth 2000 points, but by the end of the CTF, 39 teams had solved it and it was down due to 1216 points due to dynamic scoring.

Challenge Description

Investigators have found a curious login page on a server belonging to COViD. Can you get past the login screen? Login Page

How we did it

Upon clicking the link, we were greeted by the following page:

Login Page

As usual with web challenges, I started by trying out what the web page is like in order to get a sensing on how it functions. The website gives you a form where you can upload JPG files and a “Submit” button that’s greyed out. Trying to upload a JPG file will enable the “Submit” button, allowing us to upload the file, and returning us with a similarity score. I tried uploading a PNG file it resulted in a still greyed out button and a prompt “only .jpg files are allowed”.

Looking at the page sources in the Chrome DevTools panel, we can take a look inside the <script> tag in index.html and see that the check whether we are submitting a JPG file or not is done client-side, and the check is purely based on the file extension. With this knowledge, I tried to rename a PNG file as a JPG and it still works to give me the similarity score. However, trying to do the same with a text file of any kind will result in an internal server error. This led me to believe that the image comparison may be an actual algorithm that compares the two images.

At first, I tried to Google how image comparison algorithms in PHP work, but I realised that a lot of them involve a lot of their own code instead of one from predefined libraries, and each implementation seems to also be unique in how they actually do the image comparison. As such, this led me to believe that it is unlikely that the actual comparison algorith will be one that is easily found online. I also had guesses whether it has something to do with palindromes (as “Emmel” almost sounds like one–emmel~lemme~let me) but it was a bit far-fetched. Lastly, I had a hunch that this challenge had something to do with Machine Learning (ML) as Emmel sounds like ML (this turned out to be true as the challenge author subsequently mentioned as follows, but at that point in time, it was just a guess).

Regardless, after analysing the actual packets that were sent when I submit the form using Wireshark, I tried to create a Python program using PIL and requests to automate the same process and obtain the similarity score, using a bunch of grayscale images.

Version 1 - Grayscale Images

import requests
from PIL import Image

headers = {
    'Connection': 'keep-alive',
    'Cache-Control': 'max-age=0',
    'Upgrade-Insecure-Requests': '1',
    'Origin': 'http://yhi8bpzolrog3yw17fe0wlwrnwllnhic.alttablabs.sg:40751',
    'Referer': 'http://yhi8bpzolrog3yw17fe0wlwrnwllnhic.alttablabs.sg:40751/recognize',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36',
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
    'Accept-Encoding': 'gzip, deflate',
    'Host': 'yhi8bpzolrog3yw17fe0wlwrnwllnhic.alttablabs.sg:40751',
}

for val in range(256):
    print(f"testing val={val}...", end = '')
    img = Image.new('RGB', (256, 256), color = (val, val, val))
    img.save(f'test{val}.jpg')

    files = {
        'file': (f'test{val}.jpg', open(f'test{val}.jpg', 'rb'), 'image/jpeg'),
    }

    response = requests.post('http://yhi8bpzolrog3yw17fe0wlwrnwllnhic.alttablabs.sg:40751/recognize', files=files, headers=headers)
    print([l for l in response.text.splitlines() if 'Similarity' in l])

I saw that the accuracy finally got up from 0.0%, but not that high (at most 17.85%), as shown:

...
testing val=129...['      <p id="score">Error, you must get 50% or higher! Similarity: 15.95%</p>']
testing val=130...['      <p id="score">Error, you must get 50% or higher! Similarity: 16.66%</p>']
testing val=131...['      <p id="score">Error, you must get 50% or higher! Similarity: 17.25%</p>']
testing val=132...['      <p id="score">Error, you must get 50% or higher! Similarity: 17.6%</p>']
testing val=133...['      <p id="score">Error, you must get 50% or higher! Similarity: 17.78%</p>']
testing val=134...['      <p id="score">Error, you must get 50% or higher! Similarity: 17.85%</p>']
testing val=135...['      <p id="score">Error, you must get 50% or higher! Similarity: 17.68%</p>']
testing val=136...['      <p id="score">Error, you must get 50% or higher! Similarity: 17.25%</p>']
testing val=137...['      <p id="score">Error, you must get 50% or higher! Similarity: 16.63%</p>']
testing val=138...['      <p id="score">Error, you must get 50% or higher! Similarity: 15.66%</p>']
...

As such, I decided to change it to send an RGB image. However, with the way I initially coded it, it was just way too slow as it had to send all 256^3 = 16777216 possible images.

Version 2 - RGB Images (Sequential)

min = 127
max = 140
for r in range(min, max):
   for g in range(min, max):
       for b in range(min, max):
           print(f"testing ({r},{g},{b})...", end = '')
           img = Image.new('RGB', (512, 512), color = (r, g, b))
           img.save(f'test2_({r},{g},{b}).jpg')

However, this was just way too slow. I then tried to assign a random colour to each pixel as opposed to the whole image being the same colour, but this made it even slower and also less accurate (I was averaging 10%). But then, noticing that the required similarity threshold of 50% or higher is actually quite low, I decided to modify the code from Version 2, except that the program will generate images of random colours instead of trying each one sequentially:

Version 3 - RGB Images (Randomised)

import random
while True:
    r = random.randint(0,255)
    g = random.randint(0,255)
    b = random.randint(0,255)
    print(f"testing ({r},{g},{b})...", end = '')
    img = Image.new('RGB', (512, 512), color = (r, g, b))
    img.save(f'testrandom_({r},{g},{b}).jpg')

    ...

    print([l for l in response.text.splitlines() if 'Similarity' in l])

I ran the program for more than 10 minutes to no avail and nearly gave up. However, after taking a break, I decided to give it one more chance before I searched for another alternative means to solving the challenge. Luckily, not 10 seconds later, this happened in the output:

...
testing (199,82,111)...['      <p id="score">Error, you must get 50% or higher! Similarity: 0.16%</p>']
testing (16,43,4)...['      <p id="score">Error, you must get 50% or higher! Similarity: 0.01%</p>']
testing (71,255,194)...['      <p id="score">Error, you must get 50% or higher! Similarity: 0.07%</p>']
testing (106,44,107)...[]
testing (45,79,142)...['      <p id="score">Error, you must get 50% or higher! Similarity: 0.09%</p>']
testing (103,203,19)...['      <p id="score">Error, you must get 50% or higher! Similarity: 0.05%</p>']
...

Well hello there!

I then sent that exact image with values R=106, G=44, B=107 manually in the browser, and voila!

The image we sent

We got the flag!

Flag: govtech-csg{I_L0V3_G00D_D0GG0S!}

OSINT

[OSINT-1] What is he working on? Some high value project?

Description

The lead Smart Nation engineer is missing! He has not responded to our calls for 3 days and is suspected to be kidnapped! Can you find out some of the projects he has been working on? Perhaps this will give us some insights on why he was kidnapped…maybe some high-value projects! This is one of the latest works, maybe it serves as a good starting point to start hunting. Flag is the repository name!

Solution

Upon entering the given link, we proceed to view the page source. We can observe various comments within the page source, including this one (line 869):

https://lh3.googleusercontent.com/5l_KMhaiAbs64A_P1rSGEaz04GGG2AB6hg4LW7f2SdpbNKdayWMzj_3O2eu8G46IFsabwOE_2Dcm1t8rNdszX1r2vWvti7P9t_oI2F4dXS2cbcJ3IujTa_eRsVPoJxazRyLddMCm

We then go on to Gitlab and search for @joshhky. This gives us the user Josh Hong who works for KoroVax, indicating that we have found the correct account.

https://lh3.googleusercontent.com/-bUe2BSxACXUqokIbbycYNfIYiUIbM7kw6BQOkHlDZ2XqzYMJHhamYaHvXNgJbXxqfPDiH-4DUlcCvuQwjIZdT7iRsYX1PLRfzTT1Y5U52w0JvEvkSJyR9g28a9-OErQ6-pt7_BW

As the flag name is the project repository name, we went on to try the various projects shown above. However, they were not the flag.

As the description hints at a high value project, we go on to further inspect his various projects including the korovax-employee-wiki:

https://lh3.googleusercontent.com/csG2FdzBwfubol5hjjLwl0Y1pVbNdndxct6zXONH2fQOOKlE_AJT3GyeIwLepO3XiwXeXBip_WZL8TJPMuyNyshXXBcJazsrNBmWos4LkFbE7lOzAUUZcaA53IkLaYDAMzt6HVGW

We then come across the latest document added which mentions a ‘krs-admin-portal’ that is not in the list of public repositories, indicating that it is potentially high value.

The document

Upon trying govtech-csg{krs-admin-portal}, we find that it is indeed the flag!

Flag: govtech-csg{krs-admin-portal}

[OSINT-2] Where was he kidnapped?

Description

The missing engineer stores his videos from his phone in his private cloud servers. We managed to get hold of these videos and we will need your help to trace back the route taken he took before going missing and identify where he was potentially kidnapped!

You only have a limited number of flag submissions!

Flag Format: govtech-csg{postal_code}

Attached Files

Attached were 3 video files, which appeared to be Instagram stories taken by the missing engineer.

Write-up

https://lh4.googleusercontent.com/VVSJUWTcIsICOnpnjQlDUFWL-rHhghE45T1lDC9Nj-O8R6KDHBdY9e6iBOpXOSIUbxi5Qij2Tw-caSvMDWxqHCfRjPNUvfnBHtn8AU-AZOJzy9rnshMu8sq0DFlQLBnxUwPLpzQ6

Inspecting the first video, we noticed that:

  • The engineer took the bus 117 toward Punggol interchange
  • The bus stop was opposite an MRT station with the tracks above ground
  • The buildings in the background near the MRT station

Immediately, we searched for the route of bus 117 online. Looking at all the possible bus stops, we deduced that the bus stop could be:

  • Opp Sembawang Stn
  • Opp Canberra Stn
  • Opp Yishun Stn
  • Opp Khatib Stn
  • (And we kept Soo Tech Stn as a potential option)

Using Google Maps, we checked the street view of each of these bus stops, and found that Opp Khatib Stn was the bus stop we were looking for!!

https://lh4.googleusercontent.com/BCkjiPnF_AkN6UNyIoH5lkYP19Ut1l-R9bbFN0sY2NiBKjTmpeu3vEWdBjpZV3CCGye0mqWuRQ65UOnEyKRT1LZKp1iylxiAPJbHapr7U_OxATMTNizbwq95YlSLWmQDM5xW6AYh

Inspecting the second video, we immediately noticed:

  • These iconic yellow pillars
  • “Not even near the MRT…”
  • The location is at a HDB block
  • Looking at how the person was walking, it was likely that he/she just got off the bus and was leaving the bus stop

Using Google Maps street view once again, we followed the direction of the bus route and looked at the bus stops after Opp Khatib Stn. Upon spotting the iconic yellow pillars at bus stop Blk 871, we hollered in victory and moved on to the third video.

https://lh4.googleusercontent.com/tU64lxpI5Rq6dTMKy7Mc0pqufxTaNH4SWmFGauB_OdOydbJGKMn9pxVYaQeDyZRXLKuOwW1EuuU7peuG5i5mXEI3ZLfi4FtkmD95n71hrWr1plC_9NuPrfSdyKCgwMjVAb6oOrgk

Staring intensely at the third video, we observed that:

  • There was a framed community garden of sorts beside the location
  • There was a green expanse beside the garden
  • The flooring of the location was tiled and not normal concrete
  • The semicircle shape of the chair
  • The bench beside the chair

We inferred that the location was within walking distance of the bus stop and should be within the cluster of HDB blocks beside the bus stop. We tried to use Google Earth to inspect the HDB blocks but sadly it wasn’t made 3D yet.

Yet again, using our newfound best friend Google Maps street view, we jumped around the roads surrounding the HDB blocks. Voila!

https://lh3.googleusercontent.com/yGqdV2SUVpACUZTlR6exiZ-tjQNBtmbQIQ0CIIKSTpQYyTqgmoBYPMwDeD7hYcR3HxhRqSeUKtUTvHuCbj5hxj18LMb8M5S6Bt4bv1v6qbVh_tAa99UdeFzjojzcmxVvzkhzFfO7

https://lh5.googleusercontent.com/ypzMv83c-WclQtfGGZKe1GJ_ciMMWfE1CGSVtp-JPzj5a5nS4E5h3-kA1w6O9_udvSIljnPrympf4-pE34GqZPXpRvbGRVxsjTm58P6twcDAVUrAS52-PXKeBIB7sVZP-TNLDfmx

Indeed, looking at the block numbers, the place we were looking for was at Blk 870.

Flag: govtech-csg{760870}

[OSINT-6] Only Time Will Tell

Description

This picture was taken and 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 Example: govtech-csg{1.401146_103.927020_1990:12:30_2000-2200}

Flag Format: govtech-csg{lat_long_date_[two hour block format]}

Use this calculator!

This challenge:

  • Unlocks other challenge(s)
  • Is eligible for Awesome Write-ups Award
  • Prerequisite for Mastery Award - Intelligence Officer

Attached Files

https://lh6.googleusercontent.com/nmYGKDs4xGC15q5KeYQu99f1tiXdEImegkHuQalEWU2lMrOCv_uqrsrnYJ2CVIi1xSxORLK40MdJvpN3TQ4XNamtGKnLWozZvklbldV6ir0dHw18HlAF2lsfE8ptERE4ELkC8PEh

Write-up

I have no idea why but we initially thought that the sign was in the UK, but after some googling, we found that the picture was taken at the Speakers’ Corner at Hong Lim Park in Singapore.

Undoubtedly, our next instinct was to scan the barcode at the bottom left corner of the image. After all, when you see a barcode, you have to scan it!!!

We specifically cropped out the barcode to make sure that it can be scanned.

https://lh3.googleusercontent.com/JUKvFAzfy87PeCBhzkupj7mrDiA5FhJNW4FaZ8Aa_cnFp-rvCJ__PHC4ZwPDTscDPVlgwtu7iUwwqm1xhtycZHY-KuilPW_k2iUOLfVqKusgTCJr-BYgyA-u_xXmcmlXivv95KnD

Next, we then used an online barcode scanner https://online-barcode-reader.inliteresearch.com/, and obtained the date 25 October 2020.

After that, we used EXIF data to find the latitude and longitude. We tried to do this in a few ways:

First, uploading the cropped image to online EXIF data viewers gave us a latitude and longitude of 1.286648 degrees N and 103.846835 degrees E.

Second, right-clicking and looking at the properties of the downloaded image, also gave us the latitude and longitude as shown below.

https://lh6.googleusercontent.com/X6K4c3303O0FjuLthjxuhDk6jt0iCA5zDTkQCCW_Sg8RNVmvMsx00G-UMhbbvGK9icy0unHtpqg_VkxJaVwz2J-LacbjjNQGAmIRzJ5u2ANqzDoL1g1JNJxfoVOCgrpn0nFf4iLQ

After putting these values in the calculator linked in the challenge description, we also obtained a latitude of 1.286648 degrees and a longitude of 103.846835 degrees.

Looking at the direction of the sun, we deduced that the timing was in the afternoon, but we tried to key in the flag using all the possible combinations of 2 hour blocks.

However, we were confounded.

govtech-csg{1.286648_103.846835_2020:10:25_two hour time period} ⇒ WRONG

Despite checking many times, our flag was still incorrect. We clutched our heads, wondering what went wrong.

After a period of confusion, we used a command line tool called exiftool to extract the location. We finally figured out what the coordinates should be, and it turned out to be a difference in the 6th decimal place to our initial answer.

At long last, our flag was correct.

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

One of our teammates who solved the final part of the challenge said that technically the command line tool only gives the latitude and longitude up to two decimal places, making the result less precise compared to other tools which can give a more precise measurement. Hence, it is strange that the organisers would opt to use the less precise value.

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

[OSINT-7] Sounds of Freedom!

Description

In a recent raid on a suspected COViD hideout, we found this video in a thumbdrive on-site. We are not sure what this video signifies but we suspect COViD’s henchmen might be surveying a potential target site for a biological bomb. We believe that the attack may happen soon. We need your help to identify the water body in this video! This will be a starting point for us to do an area sweep of the vicinity! Flag is the postal code.

Solution

The task comes with a video file. Upon playing the video, we first notice a few things.

  1. The location looks to be a park with a circular lake/pond.
  2. There is a bus stop with a white roof below the filming location.
  3. There is a red building next to the pond.
  4. There are green/ blue HDB blocks in the background.
  5. There is the sound of fighter jet engines in the background. This along with the name suggests that the location is near an army air base.

A bus stop by the road

A small building and an HDB block in the background

A teammate who lived near Punggol Park commented that the location looked exceedingly like Punggol Park, before proceeding to convince herself and everyone else that the location could NOT be Punggol Park.

Hence, we went on to use Google Maps to look at the satellite images of parks near the main army air bases in Singapore (Changi Air Base (East and West), Paya Lebar, Sembawang and Tengah). However, there were no parks that could fit the above description.

We then decided to relook Punggol Park. Using Google Maps’ Street View function from the bus stop at Opp Blk 475B, we can see the following :

https://lh6.googleusercontent.com/_kzY-tZJu9mAa_3IojkSTWLp4mYKM4iLCb2JoJ1WMvx7wzMGDOXQH6zjHKKSC2RjUy0HUrwm4_ACGjBPuF0IwpPMcdls3bxL7P-4zhW1TZaWi8USdZkY9Rq27dlazcXIUHhoSY4g

https://lh5.googleusercontent.com/a80j6sd_HTURUCITZxAkFvBgPCqjylX8FwqfaE_GejWmv6Lf1P49GmrJepr0gAAUxpXgsQNUw-WHxx3dbsRUOTZFfN2BU2gZg-1qzGZFmISZll4DXY6x-4jaK8t_nmFUFneDXg7d

Since the features observed matched up with the ones in the video, we did a quick google search to find the postal code for Punggol Park and got the flag (as well as an existential crisis for the teammate who lived near Punggol Park).

Flag: govtech-csg{538768}