Xortool

From aldeid
Jump to navigation Jump to search

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

Comments