Rating: 5.0

## Unvreakable Vase

Ah shoot, I dropped this data and now it's all squished and flat. Can you make any sense of this?

In this challenge, we're also given a text file prompt.txt:


This looks like Base64, but where are all the upper-case letters? Base64 encoding `flag{` gives us `ZmxhZ3s=`, from that we can deduce that the problem lies with all the upper-case letters being turned to lower case. As a result, decoding the ciphertext results in `ÎlaÏ{dokóÇzèk.ßÏ.ån_co{îuÿas_crypv.oo}`, mostly gibberish, but you can see fragments of the flag. At my first attempt at this, I simply went through all the letters and tested, slowly revealing the flag, but for the purposes of this writeup, I think it's beneficial to look at a more algorithmic solution. Here's a python script that solves for the flag, it's richly commented such that it's easy to follow:

import base64

#declare ciphertext (could do open("prompt.txt","r").read(), but just easier to paste the string)
ct = "zmxhz3tkb2vzx3roaxnfzxzlbl9jb3vudf9hc19jcnlwdg9vb30="
#decode base64
def dec(n):
return base64.b64decode(n)
#change the casing of a block
def tryCase(n,i):
#get i as 4-bit binary number
b =format(i, '#06b')[2:]
#declare a variable for each character in chunk
#set them to upper if their respective bit is 1
if b[0]=='1':
if b[1]=='1':
if b[2]=='1':
if b[3]=='1':
#return the result
return c1+c2+c3+c4
#check if the decoded b64 falls within valid flag-characters
def isValid(n):
#try to decode, if n contains non-ASCII characters, will automatically return false
#interate through decoded n
for i in b:
#if decoded n is less than 32 i.e. where pritable characters start, return false
if ord(i)<32:
return False
#if n gets here, we can be sure it's a good character and we can return true
return True
return False
#split the ciphertext into 4 character blocks (aka 3-character chunks in plaintext)
blocks = [ct[i:i+4] for i in range(0, len(ct), 4)]
#declares plaintext
#iterates blocks
for i in blocks:
#iterates the 16 possible states a block can have (4 characters each either upper- or lower-case)
for j in range(16):
#define c as a test-case for the state of the block
c = dec(tryCase(i,j))
#check if c is valid
if isValid(c):
#if yes, append decoded chunk to plaintext and continue to the next block
#print the plaintext


Running this script returns the flag:


Original writeup (https://github.com/williamsolem/NahamCon-CTF-2020-Writeup).