Baby-XoR
Category: crypto
61 points
The first technique one should learn, in order to enter the fun world of modern cryptography, is XoR. Have you learned it well?
flag.enc
xxd flag.enc
00000000: 1c0d 4546 0a0d 0647 491a 491a 7367 7717 ..EF...GI.I.sgw.
00000010: 123d 2317 1d0d 2748 422d 0737 3d0d 0768 .=#...'HB-.7=..h
00000020: 422d 2737 3d53 0000 5c09 B-'7=S..\.
baby_xor.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from flag import flag
def xor(u, v):
return ''.join(chr(ord(cu) ^ ord(cv)) for cu, cv in zip(u, v))
u = flag
v = flag[1:] + flag[0]
enc = open('flag.enc', 'w')
enc.write(xor(u, v))
enc.close()
Solution
Ok, so it seemed that flag is xored by the same flag, but shifted. From the code it can be deducted the shift equals to
1
, but it’s not a true. I had to check more options. And that’s why the below script has been created.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from pwn import xor
encrypted_flag = open('flag.enc', 'rb').read()
shift = None
for i in range(len(encrypted_flag)):
key = b'S4CTF{'
xored = xor(encrypted_flag[i:i+6], b'S4CTF{')
if b'S4CTF' in xored:
shift = i + xored.index(b'S4CTF')
decrypted_flag = [i for i in b'\xff' * shift + b'S4CTF{' + b'\xff' * (len(encrypted_flag) - 6 - shift)]
for i in range(shift, len(encrypted_flag)):
j = i + 1 if i < len(decrypted_flag) - 1 else 0
decrypted_flag[j] = decrypted_flag[i] ^ encrypted_flag[i]
print(''.join(chr(i) for i in decrypted_flag))
Output is messy, but it’s ok :-)
tÿÿÿÿÿÿÿÿÿÿÿÿS4CTF{XOR_x0r_XoR_X0r_xOr!!!}
Flag
S4CTF{XOR_x0r_XoR_X0r_xOr!!!}