􃗁􌲔􇺟􊸉􁫞􄺷􄧻􃄏􊸉
Unicode substitution cipher.

Problem

Here's some enciphered text. Find the flag.

Solution

Parts of the ciphertext are ASCII, while the rest is not.
First, I wrote some scripts to understand the ciphertext more.
1
with open('ciphertext.md', 'rb') as f:
2
c = f.read()
3
4
freq_dict = {}
5
6
print(c)
7
cipher_chars = []
8
9
for char in c:
10
11
try:
12
assert chr(char).isascii()
13
14
except:
15
cipher_chars.append(char)
16
17
if char in freq_dict:
18
freq_dict[char] += 1
19
else:
20
freq_dict[char] = 1
21
22
print(freq_dict, len(freq_dict.items()))
Copied!
I found that there were 40 unique 'undecodable' characters in the cipher, and the frequency dictionary is as follows:
1
{244: 1013, 135: 170, 186: 105, 159: 99, 138: 152, 184: 138, 137: 241, 182: 37, 172: 14, 131: 82, 151: 196, 129: 137, 139: 67, 132: 140, 154: 29, 134: 236, 150: 71, 147: 91, 167: 66, 187: 66, 175: 20, 140: 72, 178: 29, 148: 29, 143: 54, 171: 117, 158: 93, 189: 131, 155: 91, 130: 43, 142: 19, 144: 38, 157: 38, 183: 26, 149: 25, 136: 25, 128: 3, 180: 26, 160: 3, 152: 20} 40
Copied!
There is a huge number of 244's, so I realised that the ciphertext was essentially characters seperated by \xf4.
1
print(c.split(b'\xf4'))
Copied!
I then found that there was a hyperlink beginning with https://. The bytes in question were
1
b'\x89\x82\xab', b'\x87\xbd\x9b', b'\x87\xbd\x9b', b'\x83\x84\x8f', b'\x81\xab\x9e://'
Copied!
So,
  • \x89\x82\xab = h
  • \x87\xbd\x9b = t
  • \x83\x84\x8f = p
  • \x81\xab\x9e = s
Further,
1
b'\x86\x9e\x8e', b'\x84\xba\xb7', b'\x84\xa7\xbb', b'\x84\xba\xb7', b'\x87\xbd\x9b', b'\x8c\xb6\xb4'
Copied!
is 'bcactf'.
The rest was really guesswork. I made use of text patterns and things like 'a' being the most common letter of the alphabet to guess the remaining characters.
1
new_c = b''
2
mapping = {
3
b'\x89\x82\xab': b'h',
4
b'\x87\xbd\x9b': b't',
5
b'\x83\x84\x8f': b'p',
6
b'\x81\xab\x9e': b's',
7
b'\x86\x9e\x8e': b'b',
8
b'\x84\xba\xb7': b'c',
9
b'\x84\xa7\xbb': b'a',
10
b'\x87\xbd\x9b': b't',
11
b'\x8c\xb6\xb4': b'f',
12
b'\x80\xb4\xa0': b'j',
13
b'\x8c\xb2\x94': b'u',
14
b'\x8a\xb8\x89': b'e',
15
b'\x86\x96\x93': b'o',
16
b'\x83\x97\x81': b'r',
17
b'\x87\xba\x9f': b'n',
18
b'\x8f\x95\x88': b'w',
19
b'\x86\x86\x97': b'i',
20
b'\x8f\x9f\x9f': b'k',
21
b'\x89\x97\xbd': b'd',
22
b'\x8b\x84\x9a': b'g',
23
b'\x8c\x98\x97': b'm',
24
b'\x89\xaf\x93': b'y'
25
}
26
27
freq_dict = {}
28
for char in c.split(b'\xf4'):
29
30
if char in freq_dict:
31
freq_dict[char] += 1
32
else:
33
freq_dict[char] = 1
34
35
for pattern in mapping:
36
char = char.replace(pattern, mapping[pattern])
37
new_c += char
38
print(char)
39
40
print(new_c)
41
print(freq_dict, len(freq_dict.items()))
Copied!
Last modified 5mo ago
Copy link