Basic xortool Usage and Flag Capturing

With all of my CTF posts, I have neglected to talk about xortool.

xortool - Introduction

If you've never used it before, xortool is great at analyzing multi-byte xor ciphers.

You can grab it from the GitHub repository, and it's simple to use.

I've solved many a CTF challenge with it and wanted to give a few quick examples of that.


Installation was straightforward, just a git clone and then a

root@kali:~/tools# git clone
Cloning into 'xortool'...
remote: Enumerating objects: 228, done.
remote: Total 228 (delta 0), reused 0 (delta 0), pack-reused 228
Receiving objects: 100% (228/228), 253.66 KiB | 4.03 MiB/s, done.
Resolving deltas: 100% (106/106), done.
root@kali:~/tools# cd xortool/
root@kali:~/tools/xortool# python install
/usr/local/Cellar/python@2/2.7.16/Frameworks/Python.framework/Versions/2.7/lib/python2.7/distutils/ UserWarning: Unknown distribution option: 'install_requires'
running install
running build

I also needed to install docopt, which I grabbed with pip.

root@kali:~/Documents/xor/xortool_out# pip install docopt

After those steps, I was able to run the tool, and check out the options.

root@kali:~/Documents/xor# xortool -h
  A tool to do some xor analysis:
  - guess the key length (based on count of equal chars)
  - guess the key (base on knowledge of most frequent char)

  xortool [-x] [-m MAX-LEN] [-f] [-t CHARSET] [FILE]
  xortool [-x] [-l LEN] [-c CHAR | -b | -o] [-f] [-t CHARSET] [FILE]
  xortool [-x] [-m MAX-LEN| -l LEN] [-c CHAR | -b | -o] [-f] [-t CHARSET] [FILE]
  xortool [-h | --help]
  xortool --version

  -x --hex                          input is hex-encoded str
  -l LEN, --key-length=LEN          length of the key
  -m MAX-LEN, --max-keylen=MAX-LEN  maximum key length to probe [default: 65]
  -c CHAR, --char=CHAR              most frequent char (one char or hex code)
  -b --brute-chars                  brute force all possible most frequent chars
  -o --brute-printable              same as -b but will only check printable chars
  -f --filter-output                filter outputs based on the charset
  -t CHARSET --text-charset=CHARSET target text character set [default: printable]
  -h --help                         show this help

  Text character set:
    * Pre-defined sets: printable, base32, base64
    * Custom sets:
      - a: lowercase chars
      - A: uppercase chars
      - 1: digits
      - !: special chars
      - *: printable chars

  xortool file.bin
  xortool -l 11 -c 20 file.bin
  xortool -x -c ' ' file.hex
  xortool -b -f -l 23 -t base64 message.enc

Encrypting the Message

First, I generated a random 16-byte hex string using this tool


Next, I grabbed the Hacker's Manifesto, to have some text to encrypt.

I used CyberChef to encrypt a flag and the manifesto with the key that I generated.

Xortool - CyberChet

As you can see, I successfully encrypted the text.

root@kali:~/Documents/xor# xxd encoded.txt 
00000000: 0e94 459e a9fa b711 fcf5 a486 889c de5a  ..E............Z
00000010: 3f95 5de6 f0bf f44a a4e5 f6d2 98ed dc53  ?.]....J.......S
00000020: 3f8a 459e daf0 ba0f a4a2 b986 98cf d349  ?.E............I
00000030: 2c8a 54cc 8ef0 b00b fde9 f69b cc8b c11c  ,.T.............
00000040: 2a8e 4ccc 95e9 b118 a4b1 be97 98dc d34c  *.L............L
00000050: 2e90 53c2 dabf f63e e1a0 b893 dfc9 c036  ..S....>.......6
00000060: 0a90 5289 89eb b10e a4ac b8d2 fbc3 df4c  ..R............L

Xortool Decryption

First, I ran xortool without any flags against the encoded.txt file. As you can see, without any flags it will try to detect the mostly likely key length.

root@kali:~/Documents/xor# xortool encoded.txt 
The most probable key lengths:
   2:   6.9%
   4:   10.9%
   6:   6.3%
   8:   16.6%
  12:   7.9%
  16:   20.8%
  20:   5.4%
  24:   8.1%
  32:   10.6%
  48:   6.4%
Key-length can be 4*n
Most possible char is needed to guess the key!

Next, I tried to brute-force the decryption key. I used a potential length of 16, as this was the mostly likely from the last command. I guessed that the most likely character would be a null-byte, as this is normally a safe bet (especially for binary files).

root@kali:~/Documents/xor# xortool -l 16 -c '\x00' encoded.txt 
1 possible key(s) of length 16:
Found 0 plaintexts with 95.0%+ valid characters
See files filename-key.csv, filename-char_used-perc_valid.csv

While the file almost decrypted, it was clearly not the exact decryption key.

root@kali:~/Documents/xor# cat xortool_out/0.out 

As the file appeared to be mostly plaintext, I figured that space may be an even more common character.

root@kali:~/Documents/xor# xortool -l 16 -c ' ' encoded.txt 
1 possible key(s) of length 16:
K\xe2 \xec\xfa\x9f\xd4j\x84\xc5\xd6\xf2\xb8\xac\xb2<
Found 1 plaintexts with 95.0%+ valid characters
See files filename-key.csv, filename-char_used-perc_valid.csv

When I looked at the newly decrypted file, it was completely readable, and I got the flag!

root@kali:~/Documents/xor# head -5 xortool_out/0.out 

        Another one got caught today, it's all over the papers.  "Teenager
Arrested in Computer Crime Scandal", "Hacker Arrested after Bank Tampering"...
        Damn kids.  They're all alike.

Brute Force Attack

Using the -b flag, xortool will try to brute force all potential keys.

root@kali:~/Documents/xor# xortool -b encoded.txt 
The most probable key lengths:
   2:   6.9%
   4:   10.9%
   6:   6.3%
   8:   16.6%
  12:   7.9%
  16:   20.8%
  20:   5.4%
  24:   8.1%
  32:   10.6%
  48:   6.4%
Key-length can be 4*n
256 possible key(s) of length 16:
Found 51 plaintexts with 95.0%+ valid characters
See files filename-key.csv, filename-char_used-perc_valid.csv

As you can see, the 000.out file matched the first attempt using the null byte.

root@kali:~/Documents/xor/xortool_out# head -1 000.out

Additionally, the 032.out file was the properly decoded file.

root@kali:~/Documents/xor/xortool_out# head -1 032.out

Looking at the filename-key.csv file, we can see the actual decryption keys that were used for each run.

root@kali:~/Documents/xor/xortool_out# cat filename-key.csv 



Unfortunately, the keys will convert any printable characters from hex to ASCII, but the 032.out matches our original key of "4be220ecfa9fd46a84c5d6f2b8acb23c".

To make things even simpler, I grepped all of the output files for potential strings from the probable-wordlists files, and 032.out came out a winner.

root@kali:~/Documents/xor/xortool_out# grep -ow -F -f ~/tools/Probable-Wordlists/Real-Passwords/Top207-probable-v2.txt *.out

Xortool - Conclusion

While this was just a simple demonstration, xortool is a great tool to have in your CTF belt.

I've also had it be useful once or twice for some home-rolled encryption during engagements.

Stay tuned for even more CTF posts, as I'm finally finishing some more write-ups!

doyler on Githubdoyler on Twitter
Ray Doyle is an avid pentester/security enthusiast/beer connoisseur who has worked in IT for almost 16 years now. From building machines and the software on them, to breaking into them and tearing it all down; he's done it all. To show for it, he has obtained an OSCE, OSCP, eCPPT, GXPN, eWPT, eWPTX, SLAE, eMAPT, Security+, ICAgile CP, ITIL v3 Foundation, and even a sabermetrics certification!

He currently serves as a Senior Staff Adversarial Engineer for Avalara, and his previous position was a Principal Penetration Testing Consultant for Secureworks.

When he's not figuring out what cert to get next or side project to work on, he enjoys playing video games, traveling, and watching sports.

As an Amazon Associate I earn from qualifying purchases.

Common passed on this blog, I made it to a jam.


Filed under Security Not Included

2 Responses to Basic xortool Usage and Flag Capturing

  1. Unity Pro.

    Hey, can you decrypt these files for me (removed)?

Leave a Reply

Your email address will not be published. Required fields are marked *


This site uses Akismet to reduce spam. Learn how your comment data is processed.