[SHELLCTF] OX9OR2
Task source:
https://github.com/Tzion0/CTF/tree/master/ShellCTF/2022/OX9OR2
This challenge provided two files called encryption.py
and encrypted
. encrypted
file contains ciphertext produced by encryption.py
encryption.py
def xor(msg, key):
o = ''
for i in range(len(msg)):
o += chr(ord(msg[i]) ^ ord(key[i % len(key)]))
return o
with open('message', 'r') as f:
msg = ''.join(f.readlines()).rstrip('\n')
with open('key', 'r') as k:
key = ''.join(k.readlines()).rstrip('\n')
assert key.isalnum() and (len(key) == 9)
assert 'SHELL' in msg
with open('encrypted', 'w') as fo:
fo.write(xor(msg, key))
Looking at encryption.py, we can conclude that the script is basically doing XOR on message with a key where the key is alphanumeric (isalnum) with the length of 9 and contains “SHELL” string in it.
We can assume that the “SHELL{“ string is at beginning of the plaintext message since it is the flag format.
By using the XOR recipe in CyberChef with the key “SHELL{“, we get the first 6 plaintext key: XORISC
At this point we are left with remaining 3 characters to get the full key, we can achieve this by bruteforcing it. I created a python script to do this:
#!/usr/bin/env python3
from itertools import product
import string
import re
with open('encrypted', 'rb') as f:
ct = list(f.read())
pt = list("SHELL{")
perm = list(product(list(string.ascii_lowercase + string.ascii_uppercase + string.digits), repeat=3))
for p in perm:
flag = ""
key = list("XORISC") + list(p)
for c in range(len(ct)):
flag += chr(ct[c] ^ ord(key[c % len(key)]))
if re.match(r"^SHELL{X[A-Za-z0-9]R_1S_R3[A-Za-z0-9]{3}51BL3}", flag):
print("Flag: " + flag, "Key: " + "".join(key))
The regex match is basically obtained through trial and error where some of the trials produced some promising plaintext message.
Execute the script will get output below:
Just like that, we got the flag!
Flag:
SHELL{X0R_1S_R3VeR51BL3}