A pretty simple crypto challenge, but the technique is applicable to more complex problems.
The smart home system has the function of remote monitoring of what is happening in the home and every few minutes sends pictures of the surveillance cameras to the owner of the house. You successfully intercepted the network traffic of this system, however, its creators took care of the security of their users data and encrypted the pictures. Decrypt the provided image and you will find the flag.
We’re told that this is a PNG file. It isn’t recognised by viewer utilities so we’re probably dealing with full file encryption.
Most encryption schemes use an XOR operation on the source data with a key made up from a fixed block or deterministic stream of data. In order to break the encryption, we need to recover that key.
A nice property of XOR is that if A XOR B = C. Then C XOR B = A and C XOR A = B. So if we have any two of the values, we can calculate the third.
We have the ciphertext of the file, we don’t have the key, but we do know what the header of a PNG looks like.
The PNG Spec tells us that a PNG file starts with the following bytes:
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a
So we can get the first 8 bytes of the key used on the file by XORing the known header against the ciphertext.
klctf $ xxd -g 1 secret_encrypted.png | head -n 1 0000000: 76 af b1 b8 f2 f5 e5 f5 ff ff ff f2 b6 b7 bb ad v............... klctf $ python Python 2.7.12 (default, Jun 29 2016, 14:05:02) >>> hex(0x76 ^ 0x89) '0xff' >>> hex(0xaf ^ 0x50) '0xff' >>> hex(0xb1 ^ 0x4e) '0xff'
After a few characters, we seem to be getting 0xff for every result. This actually caused me some doubt in my calculations.
Lets try a quick bit of Python to XOR 0xff against the whole file…
enc = open('secret_encrypted.png').read() dec = open('decoded.png', 'w') for b in enc: dec.write((chr(ord(b) ^ 0xff)))
Unbelievably, that did the trick.
The key was a single 0xff byte.