Sounds weird

Aperi'CTF 2019 - Cryptography (100 pts).

Aperi’CTF 2019 - Sounds weird

Challenge details

Event Challenge Category Points Solves
Aperi’CTF 2019 Sounds weird Cryptography 100 10

Afin de protéger les fichiers de l’entreprise, un développeur a proposé une solution de chiffrement à sa DSI. Votre DSI vous a par conséquent demandé de tester la résistance de cette solution en vous fournissant un fichier chiffré.

Challenge: flag.ogg.crypt - md5sum: 0dbd09dc7546998c7d3fe230486be377

TL;DR

It was a xored ogg file. We applied “Known plaintext” xor technique by looking at ogg magic number.

File header

Looking at the file name, we see that we got an “ogg” cipher file. OGG is an audio file format.

If we look at our cipher file header we got:

xxd flag.ogg.crypt | head
00000000: 0e17 5421 3169 7562 6566 6c34 6721 5ec8  ..T!1iubefl4g!^.
00000010: b413 316b 7562 6237 8283 663f 4006 5c00  ..1kubb7..f?@.\.
00000020: 5302 0662 6566 6c35 4577 4170 3372 316b  S..befl5EwAp3r1k
00000030: f23d 6466 6c34 6721 e871 7c15 5638 7562  .=dfl4g!.q|.V8ub
00000040: 6566 6c34 6721 4170 2cca b60a 7462 6566  efl4g!Ap,...tbef
00000050: 1556 e9cc 4e1f cc8d ce94 8a9d 9a99 93cb  .V..N...........
00000060: 98de be90 3004 5e19 170b 164a 6c34 6779  ....0.^....Jl4gy
00000070: 2800 5b5c 7e19 1242 090f 0e62 0853 2319  (.[\~..B...b.S#.
00000080: 4052 784b 4752 5453 5c05 5714 6158 d1e9  @RxKGRTS\.W.aX..
00000090: b589 eee6 87fd e8d6 fca5 6873 3372 3162  ..........hs3r1b

We can clearly identify “fl4g!” and “Ap3r1k”. You can even guess the whole key: “Ap3r1kubefl4g!”.

The is due to xor or vigenere cipher. If we look at OGG magic number on internet we can see that there is a lot of null byte on the magic number: 4F 67 67 53 00 02 00 00 00 00 00 00 00 00. Note, this magic number can also be recovered by looking at a normal ogg file.

XOR

If we xor the 14 first bytes of our cypher file with the 14 bytes of OGG signature, we got the following:

b = "\x4F\x67\x67\x53\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00"  # Default file
a = "\x0e\x17\x54\x21\x31\x69\x75\x62\x65\x66\x6c\x34\x67\x21"  # Cipher

key = ""
for x in zip(a,b):
    key += chr(ord(x[0])^ord(x[1]))
print(key)
Ap3r1kubefl4g!

We got the xor key ! Now lets xor the whole cipher file with our key to recover the original file:

#### Decrypt
b = "\x4F\x67\x67\x53\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00"  # Default file
a = "\x0e\x17\x54\x21\x31\x69\x75\x62\x65\x66\x6c\x34\x67\x21"  # Cipher

key = ""
for x in zip(a,b):
    key += chr(ord(x[0])^ord(x[1]))  # Key Ap3r1kubefl4g!

with open("flag.ogg.crypt", 'rb') as f:
    file1 = f.read()

file2 = bytearray(len(file1))

for i in range(len(file1)):
    file2[i] = ord(file1[i]) ^ ord(key[i%len(key)])

# Write the XORd bytes to the output file
with open("flag_decrypt.ogg", 'wb') as f:
    f.write(file2)

Now we can listen to flag_decrypt.ogg:

Bravo le flag est: APRK{51MPL3_X0R_C0MMUNICATI0N}, le tout en majuscule.

Flag

APRK{51MPL3_X0R_C0MMUNICATI0N}

Zeecka