TechWeekend CTF: A Writeup
Table of Contents
1 Misc
1.1 Discord
Server announcements.
1.2 Song
Ran the text in a whitespace (programming language) interpreter.
1.3 Invisible Ink
Couldn’t solve but highly likely it involves the zero width non joiners in document.xml
1.4 Amogus
Couldn’t solve, tried Morse code. “impostor to scan on their TV” could be a clue but visualisation didn’t work.
2 Web
2.1 Bargain
Our wallet is empty but the flag is too costly. Inspected HTML, took the value of param price from flag item’s href, decoded it from base64, modified it t0 zero, encrypted it again and appended to root url.
2.2 Biscuit
Similiar to induction ctf, biscuit ~ cookie, so I modified the cookie and set ADMIN to true.
2.3 Boogie
SQL injection with payload: 1 or 1.
2.4 reffffffffffferer
Title clearly refers (no pun intended) to Referer header in GET request. Changed it to www.google.com and got lucky.
2.5 Smartest Brick On The Planet
curl --user-agent 'Supreme Smart Brick' https://cte.bitskrieg.org/web_chall3/flag
2.6 Return to Monke
Couldn’t solve but tried lots of JWT tools on the token.
3 Rev
3.1 Raincheck?
Using strings gave me the flag now when I tried to solve it again, but if I remember correctly, I used buffer overflow back then to set id.
3.2 FILEFIBDOWNLOADERROR
We know the encoding process, and we know some of the cleartext (TECHWKND{}) so using that I fixed the missing symbols to match ciphertext, and then reversed the encoding process
flag = "TFDJZPVQ{S ÃŁǘʖПځႩ⫲䕽灐땑}" x = len(flag) def somefunc(i): a = 0 b = 1 if i == 0: return 0 if i == 1: return 1 if i >= 2: c = 0 for ctr in range(1, i): c = a + b a = b b = c return c for i in range(0, x): if flag[i] == '{' or flag[i] == '}': print(flag[i], end='') else: print(chr(ord(flag[i]) - somefunc(i)), end='')
3.3 h0me
Similiar to one of the induction CTF problems, all you had to do was keep spamming A’s till our location’s pointer got filled with the hex for A. Then, take into consideration little endian and a hex to ascii table to modify the last four letters to fill it with HOME’s hex instead of A’s hex 4 times.
3.4 Suspended
strings and done.
3.5 Ruthless, merciless, pitiless malware
Running file on the exe told me that it was a .NET executable. So I used Jetbrains dotPeek to decompile it to C#. The function that checked for the key was comparing the input to the reverse of the concat of 4 strings which were being initialised in the constructor. I added them, used Reverse + decode from Base64 recipe on Cyberchef which gave the flag.
3.6 Rogue
You expect me to decrypt 16-bit AES? No, thanks.
4 Crypto
4.1 Hero of the Village
“You realize Steve must have used a fine cipher”. “a fine cipher”. “affine cipher”. Decoded using “affine cipher”.
4.2 ArrghSA
Reasonably Secure Algorithm -> RSA. The text file contains the parameters for the RSA algorithm for which I found https://stackoverflow.com/questions/49878381/rsa-decryption-using-only-n-e-and-c.
4.3 Vitty-Fabian Dialogue Exchange
Nice pun on Hell. I looked for shared key generating mechanisms and found the Diffie-Hellman algorithm which used the same parameter names. I then found http://index-of.es/Miscellanous/How%20To%20Backdoor%20Diffie-Hellman.pdf which I implemented in the following Python script:
a = 1 p = 104729 g = 23 A = 69625 while True: if ((g**a) % p) == A: print(a) break a += 1 # used the above to find a and b, which came to be 6 and 9 print(g**(6*9) % p) # shared key
4.4 Unbreakable
Used the fact that if ciphertxt = msg ^ key, then key = msg ^ ciphertxt (XOR’s property). Thus, flag = ciphertxt2 ^ key.
4.5 h4xXOR
Reversed the encryption process of the Python script:
def main(): outputfile = open("output.txt", "r") output = outputfile.read() OUT_LENGTH = len(output) flag = ['']*32 for i in reversed(range(OUT_LENGTH)): # output[i] = chr(ord(flag[i]) ^ (1337 - ord(flag[(i + 1) % 32]))) # ord(output[i]) = ord(flag[i]) ^ (1337 - ord(flag[(i + 1) % 32]) # ord(flag[i]) = ord(output[i]) ^ (1337 - ord(flag[(i + 1) % 32])) if i == 31: flag[i] = '}' else: flag[i] = chr(ord(output[i]) ^ (1337 - ord(flag[i+1]))) flagfile = open("flag.txt", "w") flagfile.write(''.join(flag)) if __name__ == "__main__": main()
5 Forensics
5.1 The Mask
xcf file, so open it in GIMP. There’s a layer mask (nice pun again) which hides the layer, so fill it with white to make it visible. It was a QR code which gave the flag on scanning.
5.2 Weird Music
Sonic (pun pun pun) Visualiser. Use spectrogram to get a QR code. Improve contrast by switching to black on white and turning the dials all the way UP and scan it.
5.3 Oh Boy!
Run the Gameboy ROM in VisualBoyAdvance and then inspect the tiles one by one.
5.4 .pcapn00b
Open the file in Wireshark, Statistics > Protocol Hierarchy. Apply http text filter and go through the contents one by one. The text/plain line has the flag in Base64.
5.5 .pcapn00b2
Same as before but now we’ll need to save a zip file, unzip it and decode from base64 the flag in the docx file.
5.6 Experiment669
Run
steghide extract -sf experiment_669.jpg
and use 669 as the password. This gives a text file which on running in a Brainfuck interpreter gives the flag.