S4CTF 2021: Baby-XoR

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!!!}

Privacy Policy
luc © 2021