CREATIVE CHAOS   ▋ blog

My Magic Numbers (crypto)

PUBLISHED ON 16/02/2020 — EDITED ON 11/12/2023 — 247CTF, INFOSEC

Intro

This is my write-up of a Cryptography challenge My Magic Numbers on the CTF site 247CTF.com.

Instructions

Can you recover the secret XOR key we used to encrypt the flag?

Magic numbers

Magic numbers or magic bytes are usually used to tell the operating system what kind of a file it is dealing with.

https://en.wikipedia.org/wiki/Magic_number_(programming)#In_files https://en.wikipedia.org/wiki/List_of_file_signatures

A JPG file typically has magic number:

FF D8 DD E0
FF D8 FF DB
FF D8 FF E1
FF D8 FF E0 00 10 4A 46 49 46 00 01
FF D8 FF E0

XOR rules

https://en.wikipedia.org/wiki/Exclusive_or

A XOR B = C
C XOR B = A
A XOR C = B

So file XOR jpg magic bytes = key

Obtaining the key

FF D8 FF E0 00 10 4A 46 49 46 00 01 | jpg magic bytes |
b9 14 06 45 71 e0 b5 f7 37 07 cb 85 | encoded file    | XOR
46 cc f9 a5 71 f0 ff b1 7e 41 cb 84 | key             | =

Decoding the file

Dump the file to hex string file with xxd (xxd is a part of vim text editor package):

$ xxd -p my_magic_bytes.jpg.enc > hex

xxd has 16 octet limit per line by default in the output, so newlines will be present. There is -c parameter to control the number of octets per line, but max value is 256, so this would not help in our case.

So to remove the newlines:

$ tr -d '\n' < hex > hexoneline

Use the script to xor the hex with key (I have used it to guess the keys also, the commented out message var):

from itertools import cycle

def do_xor(key, message):
    message = message.replace(' ', '').decode('hex')
    key = ''.join(key.split()[::-1]).decode('hex')

    return ''.join([chr(ord(a) ^ ord(b)) for a,b in zip(message, cycle(key))])


with open('hexoneline', 'rb') as f:
    message  = f.read()
f.close()


#message = "FFD8FFE000104A4649460001"
key = "46ccf9a571f0ffb17e41cb84"

print do_xor(key,message).encode("hex")


#http://opentechnotes.blogspot.com/2014/08/xor-string-with-key-in-python.html

Command:

$python2.7 test.py > decodedhex

Revert hex back to binary

$ xxd -r -p decoded image.jpg

Check if image.jpg is really an image:

$ file image.jpg
image.jpg: JPEG image data, JFIF standard 1.01, aspect ratio, density 1x1, segment length 16, progressive, precision 8, 500x500, frames 3

Open it with your favourite image viewer and catch the flag.

$ open image.jpg

Thanks

Special thanks goes to @Razvieu for kind support when I got stuck.