picoctf/crypto/substitution2/solve.py

145 lines
2.7 KiB
Python
Raw Normal View History

2024-09-02 20:20:46 +02:00
#!/usr/bin/env nix-shell
#!nix-shell -i python -p python3
# NOTE: the colors are used to keep track of which letters have been
# already substituted, and which are still unknown.
def green(s):
return f"\033[42m{s}\033[0m"
def red(s):
return f"\033[41m{s}\033[0m"
def substitute(cipher_text, substitution_map):
for letter in cipher_text:
if letter.lower() in substitution_map:
if letter.isupper():
x = substitution_map[letter.lower()].upper()
else:
x = substitution_map[letter]
print(green(x), end="")
else:
print(red(letter), end="")
with open('message.txt', 'r') as file:
enc = file.read()
# Here, I will be slowly substituting the letters in the ciphertext
# based on what I believe the words to be. I have commented out the
# invocations of substitute, and commented the newly found letters
# after each invocation.
# Starting off, "sxzqZNV{...}" looks like "picoCTF{...}"
substitution_map = {
'0': '0',
'1': '1',
'2': '2',
'3': '3',
'4': '4',
'5': '5',
'6': '6',
'7': '7',
'8': '8',
'9': '9',
'_': '_',
'{': '{',
'}': '}',
's': 'p',
'x': 'i',
'z': 'c',
'q': 'o',
'n': 't',
'v': 'f',
}
# substitute(enc, substitution_map)
# Using frequency analysis (https://www.dcode.fr/frequency-analysis), we find that:
# F 175× 13.87%
# N 125× 9.9%
# X 103× 8.16%
# Q 102× 8.08%
# L 98× 7.77%
# E 83× 6.58%
# T 68× 5.39%
# Z 63× 4.99%
# Y 61× 4.83%
# A 56× 4.44%
# P 46× 3.65%
# W 42× 3.33%
# V 39× 3.09%
# G 35× 2.77%
# B 34× 2.69%
# S 28× 2.22%
# R 24× 1.9%
# U 20× 1.58%
# H 19× 1.51%
# K 16× 1.27%
# M 9× 0.71%
# C 9× 0.71%
# O 5× 0.4%
# I 2× 0.16%
# Based on this, and the frequency of letters in the english alphabet, we can guess for 'e'
substitution_map['f'] = 'e' # 13.87% ~= 12.7%
# 'petitiol' -> 'petition'
substitution_map['l'] = 'n'
# 'incpwbinr' -> 'including'
# 'effectiue' -> 'effective'
substitution_map['p'] = 'l'
substitution_map['w'] = 'u'
substitution_map['b'] = 'd'
substitution_map['r'] = 'g'
# 'encountey' -> 'encounter'
substitution_map['y'] = 'r'
# 'eecurith' -> 'security'
substitution_map['e'] = 's'
substitution_map['h'] = 'y'
# 'effectiuely' -> 'effectively'
substitution_map['u'] = 'v'
# 'cogputer' -> 'computer'
substitution_map['g'] = 'm'
# 'catllenge' -> 'challenge'
substitution_map['a'] = 'h'
substitution_map['t'] = 'a'
# 'thinc' -> 'think'
substitution_map['c'] = 'k'
# 'valuakle' -> 'valuable'
substitution_map['k'] = 'b'
# 'thereeoists' -> 'there exists'
substitution_map['o'] = 'x'
# 'homever' -> 'however'
substitution_map['m'] = 'w'
# 'techniiue' -b 'technique'
substitution_map['i'] = 'q'
substitute(enc, substitution_map)