Tags: xor crypto hex 

Rating: 3.0

Problem description:

Please select one of flowing options:
1 - You send me any message then I will give you corresponding cipher text
2 - I show you the challenge flag and you have 3 times to guess the plain text
Your choice: 1
Your message: a
The cipher text: TUVHQg==
...
Your choice: 2
Nice! Your challenge message: MHGCKGADMEGBIACFONEIIECBMJGMKPAKPPFKJFDAOHECNPHKLHBCPAFFLHBCONEIIJCMOLEOIDCGPGFDKDAGPJFMLIBNPNFILEBBNMHJJKDPNDHGJNDIMKGPIICNOCEHJHDCNEHBOFEALFBAOHECKGADOCEHIGCDMMGJLOBLNLHOJEDB
Your guess: 

The server provides 2 functions:

  1. encrypt any message you provided, output base64 encoded encryption result;
  2. given encrypted challenge message,

Solving:

start from basic length 1 string, I got following encryption result (after base64 decoding).

0 JFDA
1 JEDB
2 JHDC
3 JGDD
4 JBDE
5 JADF
6 JDDG
7 JCDH
8 JNDI
9 JMDJ
A OEEB
B OHEC
C OGED
D OBEE
E OAEF
F ODEG
G OCEH
H ONEI
I OMEJ
J OPEK
K OOEL
L OJEM
M OIEN
N OLEO
O OKEP
P PFFA
Q PEFB
R PHFC
S PGFD
T PBFE
U PAFF
V PDFG
W PCFH
X PNFI
Y PMFJ
Z PPFK
a MEGB
b MHGC
c MGGD
d MBGE
e MAGF
f MDGG
g MCGH
h MNGI
i MMGJ
j MPGK
k MOGL
l MJGM
m MIGN
n MLGO
o MKGP
p NFHA
q NEHB
r NHHC
s NGHD
t NBHE
u NAHF
v NDHG
w NCHH
x NNHI
y NMHJ
z NPHK

Some observations:

  1. all results are of length 4;
  2. all bytes of output are in range "ABCDEFGHIJKLMNOP"
  3. the last 2 bytes of each output are in ascending order.

Sounds like hex encoding? OK. replacing 'ABCDEFGHIJKLMNOP‘ with hexidecimal digits, we got:

0 9530
1 9431
...
A e441
B e742
...
a c461
b c762
  1. the output is hex encoding of 2 bytes, and the 2nd byte equals to the input byte.
  2. the xor of 2 bytes is 0xA5

Now for multi-byte input:

hello MNGIKIANMEGBKIANMHGC cd68a80dc461a80dc762
world NCHHLNBIMPGKKDAGMHGC d277bd18cf6aa306c762
  1. the output is in group of 4 bytes, 1 group for each input byte;
  2. each group has the same property as the 1 byte encryption output.

Dropping every other byte, we got:

hello  68 0d 61 0d 62
world  77 18 6a 06 62
  1. the 1st output byte gives (hex encoded) 1st input byte;
  2. xor of adjacent output bytes gives the subsequent input bytes.

So here is the decryption function:

# decoding one byte from 4 output bytes.
def dec4(w):
    w = w.decode('hex')
    assert len(w) == 2 and (ord(w[0])^ord(w[1])) == 0xa5
    return w[1]

import string
tr = string.maketrans('ABCDEFGHIJKLMNOP', '0123456789abcdef')

# decoding input string.
def decrypt(s):
    res = s.translate(tr)
    c = [dec4(res[i:i+4]) for i in range(0, len(res), 4)]
    o = [c[0]]*len(c)
    for i in range(1, len(o)):
        o[i] = chr(ord(c[i-1])^ord(c[i]))
    o = ''.join(o)
    return o

Now apply the decryption to the given flag, and send back the result, we got:

Awesome! Here is the final flag: Good fun with bad crypto