The task
As a task we got a the archive onlythisprogram.tgz containing 9 files file[0-9].enc
and a script to encrypt and decrypt files.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
| #!/usr/bin/python
import os
import sys
import argparse
blocksize=256
parser = argparse.ArgumentParser(description="Custom encryption algorithm because a friend said that's the way to do it. Anyway, it's called 'Only This Program' since I'm pretty sure that only this program can securely decrypt the files as long as you don't give out your secret.dat file created when you encrypt something.")
parser.add_argument('--infile', metavar='i', nargs='?', type=argparse.FileType('r'), help='input file, defaults to standard in', default=sys.stdin)
parser.add_argument('--outfile', metavar='o', nargs='?', type=argparse.FileType('wb'), help='output file, defaults to standard out', default=sys.stdout)
parser.add_argument('--secretkey', metavar='s', nargs='?', type=argparse.FileType('a+'), help='output file, defaults to secretkey.dat', default='secretkey.dat')
args = parser.parse_args()
sys.stderr.write('\nReading random bytes from OS. If hung, please introduce entropy.\n')
args.secretkey.truncate()
while (args.secretkey.tell() < blocksize):
# maybe remove the next line for release since it makes it more obvious the key only generates once?
sys.stdout.write('.')
args.secretkey.write(os.urandom(1))
counter=0
args.secretkey.seek(0)
keydata = args.secretkey.read(blocksize)
while 1:
byte = args.infile.read(1)
if not byte:
break
args.outfile.write(chr(ord(keydata[counter % len(keydata)]) ^ ord(byte)))
counter+=1
sys.stderr.write('\nSecret keyfile: %s\nInput file: %s\nOutput file: %s\nTotal bytes: %d \n' % (args.secretkey.name, args.infile.name, args.outfile.name, counter))
|
The encryption is a simple xor encryption with a random 256 byte xor-key. To decrypt these files we xored the first block of each file with the first block every other file. Especially xors with file7.enc produces some readable output. So we selected file8.enc and xored it with each 256byte block of file7.enc. Expecting that the original file7 conains many 0-bytes, we counted the occurences of the bytes on each position of the 256byte block and reassembled the block with the most occuring bytes. This leads to an known plaintext for the first block and therefore also the key.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
| #!/usr/bin/env python
def xor(a,b):
return "".join(map(lambda c: chr((ord(c[0])^ord(c[1]))), zip(a,b)))
basedata = file("file8.enc").read(256)
f = file("file7.enc")
byte_log = []
for i in range(256):
byte_log.append({})
while True:
f7txt = f.read(256)
if not f7txt:
break
i = 0
for xor_byte in xor(basedata, f7txt):
if xor_byte not in byte_log[i]:
byte_log[i][xor_byte] = 0
byte_log[i][xor_byte]+=1
i+=1
known_plaintext = ""
for i in byte_log:
bytes = map(lambda a: (a[1], a[0]), i.items())
bytes.sort(reverse=True)
known_plaintext += bytes[0][1]
key = xor(known_plaintext, basedata)
for file_nr in range(9):
fin = file("file%d.enc" % file_nr)
fout = file("fout%d.out" % file_nr, "w")
while 1:
x = fin.read(256)
if not x:
break
fout.write(xor(x, key))
|
With this key we are able to decrypt all files:
fout0.out: Standard MIDI data (format 1) using 11 tracks at 1/384
fout1.out: JPEG image data, JFIF standard 1.01, comment: "Created with The GIMP??"
fout2.out: PNG image data, 400 x 208, 8-bit grayscale, non-interlaced
fout3.out: JPEG image data, JFIF standard 1.01
fout4.out: gzip compressed data, from Unix, last modified: Wed Sep 4 02:25:26 2013
fout5.out: PC bitmap, Windows 3.x format, 1452 x 1600 x 1
fout6.out: GIF image data, version 89a, 135 x 46
fout7.out: CDF V2 Document, Little Endian, Os: Windows, Version 5.2, Code page: 1252, Title: Attacks on the RSA Cryptosystem, Author: Scott, Template: Normal.dot, Last Saved By: Scott Nelson (IE), Revision Number: 161, Name of Creating Application: Microsoft Office Word, Total Editing Time: 1d+12:34:00, Last Printed: Mon Mar 6 18:13:00 2006, Create Time/Date: Fri Mar 3 20:49:00 2006, Last Saved Time/Date: Mon Mar 6 19:22:00 2006, Number of Pages: 1, Number of Words: 1424, Number of Characters: 8123, Security: 0
fout8.out: PDF document, version 1.2
The zip-file contains a txt-file with the following content:
_____ _ __ _ _ _ _ _ _ __ _ _ _ ___ _ _ _ _ _ _ _ _ _ __ _ _ _ _ _ _ _ _ _ _ _____ _ _ ___ _ _ _ _ _ _ _ _ _ _ _ _ ____ _ _ ___ __ ___ ____ _ ____ ___ _ _ _ _ _ _ ____ _ _
| ___|__ _ __ ___ ___ _ __ ___ ___ _ __ ___ __ _ ___ ___ _ __ _ __ ___(_)/ _| ___ _ __| |_ _____ __ _ __ ___ __ _| | |_ _ | (_) | _____ ___ / _(_) __ _| | ___| |_ ___ |_ _|_ __ | |_| |__ (_)___ ___ __ _ ___ ___ (_) |_( )___ _ __ ___ ___ ___ ___ ___ __ _ _ __ _ _ | |__ ___ ___ __ _ _ _ ___ ___ | |_| |__ ___ / _(_) | ___ ___(_)_______ ___| |__ ___ _ _| | __| | _ __ ___ | |_ | |__ ___ __ _ | |__ _ _ __ _ ___ __ _(_)_ _____ __ ___ ____ _ _ _ |_ _| |__ ___ _ _ __ _| |__ |_ _| ___ _ _ _ __ _ __ ___ ___ ___ (_)_ __ ___ __ _ __ _ ___ ___ __ _____ _ _| | __| | | |__ __ ___ _____ __ _____ _ __| | _____ __| | | |_ ___ ___ / \ _ __ _ ___ ____ _ _ _ | |_| |__ ___ | | _____ _ _ (_)___ _ | __ ) _ _(_) | __| \ \ / /__ _ _ _ __ / _ \__ ___ __ / ___|_ __ _ _ _ __ | |_ ___/ ___| ___ / _ \| |_| |__ ___ _ __ ___| | | | __ ___ _____ | | ___ | |__/ ___| ___ ___ _ _ _ __(_) |_ _ _
| |_ / _ \| '__| / __|/ _ \| '_ ` _ \ / _ \ | '__/ _ \/ _` / __|/ _ \| '_ \ | '_ \/ __| | |_ / _ \ '__| __/ _ \ \/ / | '__/ _ \/ _` | | | | | | | | | |/ / _ \/ __| | |_| |/ _` | |/ _ \ __/ __| | || '_ \ | __| '_ \| / __| / __/ _` / __|/ _ \ | | __|// __| | '_ \ / _ \/ __/ _ \/ __/ __|/ _` | '__| | | | | '_ \ / _ \/ __/ _` | | | / __|/ _ \ | __| '_ \ / _ \ | |_| | |/ _ \ / __| |_ / _ \ / __| '_ \ / _ \| | | | |/ _` | | '_ \ / _ \| __| | '_ \ / _ \ / _` | | '_ \| | | |/ _` |/ _ \ / _` | \ \ / / _ \/ _` \ \ /\ / / _` | | | | | | | '_ \ / _ \| | | |/ _` | '_ \ | | / __| | | | '_ \| '_ \ / _ \/ __|/ _ \ | | '_ ` _ \ / _` |/ _` |/ _ \/ __| \ \ /\ / / _ \| | | | |/ _` | | '_ \ / _` \ \ / / _ \ \ \ /\ / / _ \| '__| |/ / _ \/ _` | | __/ _ \ / _ \ / _ \ | '_ \| | | \ \ /\ / / _` | | | | | __| '_ \ / _ \ | |/ / _ \ | | | | / __(_) | _ \| | | | | |/ _` |\ V / _ \| | | | '__| | | \ \ /\ / / '_ \| | | '__| | | | '_ \| __/ _ \___ \ / _ \| | | | __| '_ \ / _ \ '__/ __| |_| |/ _` \ \ / / _ \_ | |/ _ \| '_ \___ \ / _ \/ __| | | | '__| | __| | | |
| _| (_) | | \__ \ (_) | | | | | | __/ | | | __/ (_| \__ \ (_) | | | | | |_) \__ \ | _| __/ | | || __/> < | | | __/ (_| | | | |_| | | | | < __/\__ \ | _| | (_| | | __/ |_\__ \_ | || | | | | |_| | | | \__ \ | (_| (_| \__ \ __/ | | |_ \__ \ | | | | __/ (_| __/\__ \__ \ (_| | | | |_| | | |_) | __/ (_| (_| | |_| \__ \ __/ | |_| | | | __/ | _| | | __/ \__ \ |/ / __/ \__ \ | | | (_) | |_| | | (_| | | | | | (_) | |_ | |_) | __/ | (_| | | | | | |_| | (_| | __/ | (_| | |\ V / __/ (_| |\ V V / (_| | |_| |_ | | | | | | (_) | |_| | (_| | | | | | | \__ \ |_| | |_) | |_) | (_) \__ \ __/ | | | | | | | (_| | (_| | __/\__ \ \ V V / (_) | |_| | | (_| | | | | | (_| |\ V / __/ \ V V / (_) | | | < __/ (_| | | || (_) | (_) | / ___ \| | | | |_| |\ V V / (_| | |_| |_ | |_| | | | __/ | < __/ |_| | | \__ \_ | |_) | |_| | | | (_| | | | (_) | |_| | | | |_| |\ V V /| | | | |___| | | |_| | |_) | || (_) |__) | (_) | |_| | |_| | | | __/ | \__ \ _ | (_| |\ V / __/ |_| | (_) | |_) |__) | __/ (__| |_| | | | | |_| |_| |
|_| \___/|_| |___/\___/|_| |_| |_|\___| |_| \___|\__,_|___/\___/|_| |_| | .__/|___/_|_| \___|_| \__\___/_/\_\ |_| \___|\__,_|_|_|\__, | |_|_|_|\_\___||___/ |_| |_|\__, |_|\___|\__|___(_) |___|_| |_| \__|_| |_|_|___/ \___\__,_|___/\___| |_|\__| |___/ |_| |_|\___|\___\___||___/___/\__,_|_| \__, | |_.__/ \___|\___\__,_|\__,_|___/\___| \__|_| |_|\___| |_| |_|_|\___| |___/_/___\___| |___/_| |_|\___/ \__,_|_|\__,_| |_| |_|\___/ \__| |_.__/ \___| \__,_| |_| |_|\__,_|\__, |\___| \__, |_| \_/ \___|\__,_| \_/\_/ \__,_|\__, (_) |_| |_| |_|\___/ \__,_|\__, |_| |_| |___| |___/\__,_| .__/| .__/ \___/|___/\___| |_|_| |_| |_|\__,_|\__, |\___||___/ \_/\_/ \___/ \__,_|_|\__,_| |_| |_|\__,_| \_/ \___| \_/\_/ \___/|_| |_|\_\___|\__,_| \__\___/ \___(_) /_/ \_\_| |_|\__, | \_/\_/ \__,_|\__, ( ) \__|_| |_|\___| |_|\_\___|\__, | |_|___(_) |____/ \__,_|_|_|\__,_| |_|\___/ \__,_|_| \___/ \_/\_/ |_| |_|\____|_| \__, | .__/ \__\___/____/ \___/ \___/ \__|_| |_|\___|_| |___/_| |_|\__,_| \_/ \___|\___/ \___/|_.__/____/ \___|\___|\__,_|_| |_|\__|\__, |
|_| |___/ |___/ |___/ |___/ |___/ |___/ |___/ |_| |_| |___/ |___/ |___/|/ |___/ |___/|_| |___/
For some reason psifertex really likes figlets. In this case it’s necessary because the file size should not be a huge giveaway. Though I suppose images would have worked to Anyway. the key is: BuildYourOwnCryptoSoOthersHaveJobSecurity