RSS

Leetmore CTF 2012: Crypto 200 (XOROWblu Wbl(I)P)

This entry was posted on Oct 18 2012

What all we had was an encrypted file.

The “XOR” part of the challenge title suggests that we need to do some xorring.

XORing with “XOROWbIu WbI(|)P” or parts of it, don’t give any
interesting results.

Lets do some frequency based analysis.

We used xortool to do this for us.

xortool can:
  –  guess the key length (based on count of equal chars)
  –  guess the key (base on knowledge of most frequent char)

Because the cry200 file is 194 bytes, it is probably a xored sentence,
so a space (= 0×20) should be a frequent character.

$ ./xortool.py -c 20 cry200
The most probable key lengths:
3: 15.7%
6: 20.4%
9: 11.4%
12: 13.8%
15: 7.2%
18: 9.3%
21: 4.6%
24: 7.8%
26: 5.6%
30: 4.3%

Key-length can be 3*n
1 possible key(s) of length 6:
\x96\xa4*\xc3\xc4:
Found 1 plaintexts with 95.0%+ printable characters
See files filename-key.csv, filename-char_used-perc_printable.csv

The output file ‘xortool_out/0.out’ contains the dexored text when
xoring the input file with “\x96\xa4*\xc3\xc4″

>>> open('xortool_out/0.out','r').read()
'Cong (tula& ons!r\x1ehiler=he q\' ck b &wn f=1 jum": ove ithe >(zy
d=., th7iplai sho =er t:(n th7imess3.e. Y=nd'

Though the key was not completely guessed correctly by xortools, nut we can read most of the text now:
  – “Congratuations!”
  – “The quick brown fox jumps over the lazy dog.” ==> standard font
display sentence.

So now we can find the correct xor key, by xoring the input data with ”Congratuations!

>>> from itertools import izip, cycle
>>>
... def xor_crypt_string(data, key):
... return ''.join(chr(ord(x) ^ ord(y)) for (x,y) in izip(data, cycle(key)))
...
>>>
>>> data=open('cry200','r').read()
>>> data
'\xd5\xcbD\xa4\xe4\x12\xe2\xd1F\xa2\xe2\x1a\xf9\xcaY\xe2\xb6$\xfe\xcdF\xa6\xb6\x07\xfe\xc1\n\xb2\xe3\x1a\xf5\xcf\n\xa1\xe4\x1c\xe1\xca\n\xa5\xf9\x0b\xb6\xce_\xae\xe6\x00\xb6\xcb\\\xa6\xe4S\xe2\xccO\xe3\xfa\x12\xec\xdd\n\xa7\xf9\x14\xba\x84^\xab\xf3S\xe6\xc8K\xaa\xf8S\xee\xcbX\xe3\xf5\x1a\xe6\xccO\xb1\xb6\x1a\xe5\x84Y\xb7\xff\x1f\xfa\x84\\\xa6\xe4\n\xb6\xd1D\xb0\xf3\x10\xe3\xd6O\xe3\xe1\x1b\xf3\xca\n\xb7\xfe\x16\xb6\xcfO\xba\xb6\x1a\xe5\x84G\xb6\xf5\x1b\xb6\xd7B\xac\xe4\x07\xf3\xd6\n\xb7\xfe\x12\xf8\x84^\xab\xf3S\xfb\xc1Y\xb0\xf7\x14\xf3\x8a\n\x9a\xf9\x06\xe4\x84L\xaf\xf7\x14\xac\x84l\xac\xee\x1a\xf3\x84n\xac\xf1\t\xff\xc1\n\x80\xe4\n\xe6\xd0E\xe3\xc6\x04\xf8\xc0'
>>> xor_crypt_string(data, 'Congratuations!')
"\x96\xa4*\xc3\x96s\x96\xa4'\xd6\x8bu\x97\xb9x\xa1\xd9J\x99\xbf'\xd2\xc3f\x8a\xa8e\xdc\x90;\xb6\xa0d\xc6\x96}\x95\xbfk\xd1\x90d\xd8\xbd~\xed\x89n\xd1\xb9=\xd2\x912\x96\xa5
\x8d\x893\xaf\xb2d\xc0\x8bu\xce\xf1?\xdf\x9a<\x88\xbbj\xe9\x97=\x89\xb99\x97\x80{\x92\xa5
\xdf\xc5;\xa6\xeb7\xd0\x8d~\x8e\xf1=\xd2\x8de\xd8\xa2e\xf3\x9c~\x84\xa4.\x97\x94z\x87\xa3e\xd9\x8d7\xf5\xa0!\xdd\xc4{\x91\xf1&\xc2\x9ct\xd8\xa4c\xef\x8bi\x94\xa4k\xc3\x8bs\x8c\xed1\xc5\x80r\xb8\xae7\xd7\x85u\x87\xffk\xee\x90i\x8a\xf7m\xec\x98z\xcb\xf6\r\xd8\x9b{\x87\xed\x01\xc2\x82(\xbc\xaed\xe7\x96k\x92\xa5$\x97\xafk\x96\xb3"

The correct key is: "\x96\xa4*\xc3\x96s

>>> xor_crypt_string(data, '\x96\xa4*\xc3\x96s')
'Congratulations! While the quick brown fox jumps over the lazy dog,
the plain xor cipher is still very unsecure when the key is much
shorter than the message. Your flag: Foxie Dogzie Crypto Pwnd'

Solution: Foxie Dogzie Crypto Pwnd

Post a Comment