This is my solution to the NACTF2020 Challenge “World Trip”.
Challenge Text:
Will has been travelling the world! Here’s a list of the coordinates of the places he’s been to. There might be a secret message hidden in the first letter of all of the countries.
Note: The flag is all uppercase without spaces or “_”
The challenge also requires download of a text file from the challenge page that I cannot host here.
The challenge is solved with the following Python code, which uses an API from geonames.org. Initially, the program reads the provided text file (a string of bracketed coordinates) and sanitises them into a list of coordinates. However, my initial draft ran into a problem: some of the coordinates are in the middle of the sea. I therefore programmatically flagged these in the string with “??” and manually checked the URLs, finding that the nearest island countries were J(amaica), T(onga), N(auru) and K(iribati).
I swapped these in for the ??, but the flag still didn’t work. I knew I must be close as I had a decrypted message at the start of the flag. Having tried a few different flag formats, I contacted an admin, as I saw a few people were having trouble. He told me my flag was correct except for character 111. I edited my program to print out the url for character 111 and put ** into the string, then checked the coordinates manually. On geonames, the country is returned as M(exico). However, on Google with same lat/long it comes back as B(elize). Making this change at character position 111 I got the correct flag.
So I guess the moral of this story is to always try more than one data source, although you’d never be sure that there wasn’t a border discrepancy unless you were using the exact same data set as the challenge author. Perhaps they could have made the correct dataset one of the hints!
import requests
rawfile = open("c:\\NACTF\\enc.txt", "r")
r = rawfile.read()
rawCoordSet = r.split(')')
coordSet = [i.strip('(') for i in rawCoordSet]
coordSet = [i.split(', ') for i in coordSet]
coordSet = coordSet[:-1]
outputString = ''
count = 0
for j in coordSet:
# change username 'demo' for geonames user with activated webservices
url = 'http://api.geonames.org/countryCode?lat=' + j[0] + '&lng=' + j[1] + '&username=demo&type=JSON'
r = requests.get(url)
if count == 111:
print(url)
outputString += '**'
count += 1
continue
try:
country = r.json()['countryName']
outputString += country[0]
except:
print(url)
outputString += "??"
count += 1
print(outputString)
The flag, after performing the necessary manual substitutions, is:
nactf{IHOPEYOUENJOYEDGOINGONTHATREALLYLONGGLOBALTOURIBOFAIQFUSETZOROPZNQTLENFLFSEMOGMHDBEEIZOIUOCGSLCDYMQYIRLBZKNHHFGBPDIVNBUQQYPDCQIAVDYTRFOCESEQUOUUMSKYJOVKVJGMRGNATNIRESHRKHCEDHHZYQRZVOGCHSBAYUBTRU}