Xortool
Description
Xortool.py is a python based script that performs some xor analysis:
- guess the key length (based on count of equal chars)
- guess the key (based on knowledge of most probable char)
- decrypt a XOR encrypted file
Installation
xortool requires docopt python dependency:
$ sudo pip install docopt
Then install xortool:
$ cd /data/src/ $ git clone https://github.com/hellman/xortool.git $ cd xortool/ $ sudo python setup.py install
Usage
Syntax
xortool.py [-h|--help] [OPTIONS] [<filename>]
Options
- -l,--key-length
- length of the key (integer)
- -c,--char
- most possible char (one char or hex code)
- -m,--max-keylen=32
- maximum key length to probe (integer)
- -x,--hex
- input is hex-encoded str
- -b,--brute-chars
- brute force all possible characters
- -o,--brute-printable
- same as -b but will only use printable characters for keys
Example
Our XOR program
Let's create a small python based script that will encrypt a file using XOR:
#!/usr/bin/env python """ Xor tool to encrypt a file with XOR cypher using a key Inspired from http://www.daniweb.com/software-development/python/code/216632/text-encryptiondecryption-with-xor-python Usage: python xor.py plain_text_file 'secret_key' Will result in a *.xor file """ from sys import argv from StringIO import StringIO def crypt(t, k): old = StringIO(t) new = StringIO(t) for position in xrange(len(t)): bias = ord(k[position % len(k)]) old_char = ord(old.read(1)) new_char = chr(old_char ^ bias) new.seek(position) new.write(new_char) new.seek(0) return new.read() if len(argv) != 3: print "Usage: python xor.py plain_text_file 'secret_key'" else: f_in = open(argv[1], 'rb') f_out = open('%s.xor' % argv[1], 'wb') key = argv[2] f_out.write(crypt(f_in.read(), key)) f_in.close() f_out.close()
Encrypt a text file
Let's create a plain text file:
$ cat > test.txt << EOF > In English, the construct "either ... or" is usually used to indicate exclusive or and "or" generally used for inclusive. > But in Spanish, the word "o" (or) can be used in the form p o q (exclusive) or the form o p o q (inclusive). Some may > contend that any binary or other n-ary exclusive "or" is true if and only if it has an odd number of true inputs (this > is not, however, the only reasonable definition; for example, digital xor gates with multiple inputs typically do not > use that definition), and that there is no conjunction in English that has this general property. For example, Barrett > and Stenner contend in the 1971 article "The Myth of the Exclusive 'Or'" (Mind, 80 (317), 116–121) that no author > has produced an example of an English or-sentence that appears to be false because both of its inputs are true, > and brush off or-sentences such as "The light bulb is either on or off" as reflecting particular facts about the world > rather than the nature of the word "or". However, the "barber paradox"—Everybody in town shaves himself or is > shaved by the barber, who shaves the barber? -- would not be paradoxical if "or" could not be exclusive (although a > purist could say that "either" is required in the statement of the paradox). > EOF
Now, let's encrypt our plain text file using our previous tool:
$ ./xor.py test.txt "secret_key"
Here is how our encrypted file looks like:
$ head test.txt.xor : C7 3_ET< T} KZqK QE E,C;KS >Y6YC I QE - E S ,]1>C7 FTY C!1_ET(SG RE PE\0LY E7ERT0KY[ ,ZE E7ER
Guess key length
To guess the key length, just provide xor tool with just the encrypted file:
$ ./xortool.py test.txt.xor The most probable key lengths: 2: 10.7% 5: 15.5% 10: 20.7% 15: 9.7% 20: 12.4% 22: 5.4% 25: 6.7% 30: 8.3% 40: 5.9% 50: 4.7% Key-length can be 5*n Most possible char is needed to guess the key!
As you can see, xor tool has guessed the key length: 10 (secret_key).
Find the key
Now, let's provide xortool with 2 more arguments:
- -l 10: the key length
- -c 00: 00 is the most frequent byte in binaries
$ ./xortool.py test.txt.xor -l 10 -c 00 1 possible key(s) of length 10: SECRET\x7fKEY Found 0 plaintexts with 95.0%+ printable characters See files filename-key.csv, filename-char_used-perc_printable.csv
Xortool has successfully found the key.
Decrypt
Following files are created by xortool:
- xortool_out/filename-char_used-perc_printable.csv
- CSV file that contains the list of output files (decrypted files attempts) with the percentage of printable characters (e.g. 78%)
$ cat xortool_out/filename-char_used-perc_printable.csv file_name;char_used;perc_printable xortool_out/0.out;0;78.0
- xortool_out/filename-key.csv
- CSV file that contains the list of output files. For each file, the key used to decrypt the file is displayed
$ cat xortool_out/cat filename-key.csv file_name;key_repr xortool_out/0.out;MYSECRET
- xortool_out/{n}.out
- Decrypted text attempts
$ cat xortool_out/0.out iNeNGLISH DISCUSSbUTINsPANISHCTEITHERORISUSUALLYUSEDTOINDICATEEXCLUSIVEORANDORGENERALLYUSEDFORINCLUSIVEtEMPLATEdUBIOUS ARYEXCLUSIVEORISTRUEIFANDONLYIFITHASANODDNUMBEROFTRUEINPUTTHISISNOTHEFORMOPOINCLUSIVE sOMEMAYCONTENDTHATANYBINARYOROTHERN HOWEVER THEONLYREASONABLEDEFINITIONOREXAMPLE DIGITALXORGATESWITHMULTIPLEINPUTSTYPICALLYDONOTUSETHATDEFINITION ANDTHATTHEREISNOCONJUNCTIONINeNGLISHTHATHASTHISGENERALPROPERTYfOREXAMPLE bARRETTANDsTENNERCONTENDINTHEARTICLEtHEmYTHOFTHEeXCLUSIVEomIND ? THATNOAUTHORHASPRODUCEDANEXAMPLEOFANeSENTENCETHATAPPEARSTOBEFALSEBECAUSEBOTHOFITSINPUTSARETRUE SENTENCESSUCHAStHELIGHTBULBISEITHERONOROFFASREFLECTINGPARTICULARFACTSABOUTTHEWORLDRATHERTHANTHENATUREOFTHEWORDORhOWEVER THEBARBERPARADOX ?eVERYBODYINTOWNSHAVESHIMSELFORISSHAVEDBYTHEBARBER WOULDNOTBEPARADOXICALIFORCOULDNOTBEEXCLUSIVALTHOUGHAPURISTCOULDSAYTHATEITHERISREQUIREDINTHESTATEMENTOFTHEPARADOX
Limitations
Depending on the plain text length and the key used to encrypt the file, xortool efficiency can vary. Here is an example of total failure.
$ cat > test.txt << EOF > this is a test > EOF
$ ./xor.py test.txt "S3creT_k3Y"
$ ./xortool.py test.txt.xor The most probable key lengths: 1: 39.2% 5: 34.0% 10: 26.8% Key-length can be 5*n Most possible char is needed to guess the key!
$ ./xortool.py test.txt.xor -l 1 -c 00 1 possible key(s) of length 1: ' Found 0 plaintexts with 95.0%+ printable characters See files filename-key.csv, filename-char_used-perc_printable.csv
$ cat xortool_out/0.out |-&b lu^q7!H
$ cat xortool_out/filename-char_used-perc_printable.csv file_name;char_used;perc_printable xortool_out/0.out;0;80.0