diff --git a/steganabara/steganabara-1.1.1.jar b/steganabara/steganabara-1.1.1.jar deleted file mode 100644 index f9c5399..0000000 Binary files a/steganabara/steganabara-1.1.1.jar and /dev/null differ diff --git a/stegsolve/Stegsolve.jar b/stegsolve/Stegsolve.jar deleted file mode 100644 index d829abb..0000000 Binary files a/stegsolve/Stegsolve.jar and /dev/null differ diff --git a/xortool/LICENSE b/xortool/LICENSE deleted file mode 100644 index 15dfde8..0000000 --- a/xortool/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2014 hellman ( hellman1908@gmail.com ) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/xortool/README.md b/xortool/README.md deleted file mode 100644 index 9a7de65..0000000 --- a/xortool/README.md +++ /dev/null @@ -1,109 +0,0 @@ -xortool.py -==================== - -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) - -Usage ---------------------- - -! *python3 is not supported, use python 2.x* - -``` - xortool [-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 ---------------------- - -```bash -# xor is xortool/xortool-xor -tests $ xor -f /bin/ls -s "secret_key" > binary_xored - -tests $ xortool binary_xored -The most probable key lengths: - 2: 5.0% - 5: 8.7% - 8: 4.9% - 10: 15.4% - 12: 4.8% - 15: 8.5% - 18: 4.8% - 20: 15.1% - 25: 8.4% - 30: 14.9% -Key-length can be 5*n -Most possible char is needed to guess the key! - -# 00 is the most frequent byte in binaries -tests $ xortool binary_xored -l 10 -c 00 -... -1 possible key(s) of length 10: -secret_key - -# decrypted ciphertexts are placed in ./xortool_out/Number_<key repr> -# ( have no better idea ) -tests $ md5sum xortool_out/0_secret_key /bin/ls -29942e290876703169e1b614d0b4340a xortool_out/0_secret_key -29942e290876703169e1b614d0b4340a /bin/ls -``` - -The most common use is to pass just the encrypted file and the most frequent character (usually 00 for binaries and 20 for text files) - length will be automatically chosen: - -```bash -tests $ xortool tool_xored -c 20 -The most probable key lengths: - 2: 5.6% - 5: 7.8% - 8: 6.0% - 10: 11.7% - 12: 5.6% - 15: 7.6% - 20: 19.8% - 25: 7.8% - 28: 5.7% - 30: 11.4% -Key-length can be 5*n -1 possible key(s) of length 20: -an0ther s3cret \xdd key -``` - -Here, the key is longer then default 32 limit: - -```bash -tests $ xortool ls_xored -c 00 -m 64 -The most probable key lengths: - 3: 3.3% - 6: 3.3% - 9: 3.3% - 11: 7.0% - 22: 6.9% - 24: 3.3% - 27: 3.2% - 33: 18.4% - 44: 6.8% - 55: 6.7% -Key-length can be 3*n -1 possible key(s) of length 33: -really long s3cr3t k3y... PADDING -``` - -So, if automated decryption fails, you can calibrate: - -- (`-m`) max length to try longer keys -- (`-l`) selected length to see some interesting keys -- (`-c`) the most frequent char to produce right plaintext - -Author: hellman ( hellman1908@gmail.com ) - -License: MIT License (opensource.org/licenses/MIT) diff --git a/xortool/setup.py b/xortool/setup.py deleted file mode 100644 index c94dc9f..0000000 --- a/xortool/setup.py +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env python -#-*- coding:utf-8 -*- - -from distutils.core import setup - -import xortool - -setup(name='xortool', - version=xortool.__version__, - - author='hellman', - author_email='hellman1908@gmail.com', - license="MIT", - - url='https://github.com/hellman/xortool', - description='Tool for xor cipher analysis', - long_description=open("README.md").read(), # not in rst, but something - keywords="xor xortool analysis", - - packages=['xortool'], - provides=['xortool'], - install_requires=['docopt>=0.6.1'], - scripts=["xortool/xortool", "xortool/xortool-xor"], - - classifiers=['Development Status :: 4 - Beta', - 'Intended Audience :: Science/Research', - 'Intended Audience :: Information Technology', - 'Natural Language :: English', - 'Operating System :: OS Independent', - 'Programming Language :: Python :: 2', - 'License :: OSI Approved :: MIT License', - 'Topic :: Scientific/Engineering :: Mathematics', - 'Topic :: Security :: Cryptography', - ], - ) diff --git a/xortool/test/data/binary_xored b/xortool/test/data/binary_xored deleted file mode 100644 index 7b70e97..0000000 Binary files a/xortool/test/data/binary_xored and /dev/null differ diff --git a/xortool/test/data/ls_xored b/xortool/test/data/ls_xored deleted file mode 100644 index 29ed4ee..0000000 Binary files a/xortool/test/data/ls_xored and /dev/null differ diff --git a/xortool/test/data/text_xored b/xortool/test/data/text_xored deleted file mode 100644 index 9ce69f1..0000000 --- a/xortool/test/data/text_xored +++ /dev/null @@ -1 +0,0 @@ -׍לщЀÞ۝ׁԞϷ݀Ҋȗ׍ׂ͛횄ڝΊלуɆʞϽЛМրȞϩ׌ȳߘϱːҊՊ˝ʇٞϧϬ΀ٞȞٞʊ֊ȐϧϽϸϱ˞͊ˈ҆ʎсȲʎҖϹߋϬ݊ϿΎԧ֊̀݊Ϸ؀ߛϿњܚޞʇΝҊڎ̞ϱ˞ȴԊِ֊Ȟ߁ߜʀ͊Л؎Ȟ׃Ҋԍ϶ʟ䂑̌ߝѝܚ׃̑䞘ҋΟ݆Ϸٞϳ݇ϧϽ˃Ȋؖ֊̀ۂߜћ۟ʊ܊̊ϲфϪ̀ϪϺʎ͊̊۟ʆʴˈҊϽیʇ͆ϷٞݚۜҜϲϱ˴܃ߛΞˎсԧ튨̆ԄυŃʀ免Ń͆ʞ̊эݛׁʎݎϲЄɞߝϳ͛Ϫۜێޞݝ֊ښЈ֊Ҁϖ̋ϸԧ֊ыלћϼϽێϊלϹʛϭјԞۋԍϼϻΊٞтʆϽ߁ϱÞ܆΃؀ϲՊҟ̐ϊϮی׀щ֊͆ЋϾ͆ˁ׀ڀћۊϼȞȞԧϒК̊րϼȞߖϮۙϺ؆Ј֊ǂᢟʇ˗ׂڊ؆ȐϹ׍כԍϷޞׁɞח҆ֆŞϰϳՊ֊ʇߴ͖уׁ҆ӆސߙҎԍυϲ܌߃ꇻ҆Ͼ߂̙ϸЌсיޞЈۜʜߛێٞߴԧ֊׍׊Ȟ߃ݛϹȊɝϬ͚ϸÓۈϭ݀ɞ߂۝免Ń۝dz͛ᄞҎсΊ؆ʆϿϼфÐ֊ыɇݚہϪ۝לϳ͛ߜޞ۝ۋ̀ʇѝׁրݎȞ̊ϿΊ؆ʆÞʇҀҊԍϸҊѝϺ؆ϫׁʇڊ˃ללЌڊԍϗÞԞϩȞȞ͆ʞѝʆÞ݀یʇ͟׉ߛԍϗ˞؞Ϫϭی׌׀؀ǀߞٚϼȞқ΃͊ԍϭЋ̞ѝɆŞʝʆÞɇٞ؆χϺȪ֎Ȟח֊Ί؆ʆÞ̜ԧ֊ߖϸЎϭњɞϲՊ׉֊ہ׌Ί؆ʆôלћѝݛݎ܊ۊׁ֊Ȱ螉Ͽ؊݇يϪϱ˞Ȟ۝Ξ݆ݎс߁ϳڊכ˛˟ݎсԍϱ˞ȞҊϺ͌Λԧтщ֊ˁ׀ޞ݇Ҝ֎ҊȞ̊Җ̀ԍϗЋҀ˟ь͆߃ԞΊɇÞٞڊϊלԍ϶ΟϷÞߋׁ–Ћۛӊ؀֎҆ʞ֊ȞݛМϑ枛ˈ߁ʇϿϮʌϿ߆܃ʀחԍϪϗыߜۃ̆ŞΟߴΟ֎݀ \ No newline at end of file diff --git a/xortool/test/data/tool_xored b/xortool/test/data/tool_xored deleted file mode 100644 index 572ae9d..0000000 Binary files a/xortool/test/data/tool_xored and /dev/null differ diff --git a/xortool/xortool/__init__.py b/xortool/xortool/__init__.py deleted file mode 100644 index 8a746ba..0000000 --- a/xortool/xortool/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env python -#-*- coding:utf-8 -*- - -__all__ = ["args", "colors", "libcolors", "routine"] -__version__ = "0.96" diff --git a/xortool/xortool/args.py b/xortool/xortool/args.py deleted file mode 100644 index 86bde2f..0000000 --- a/xortool/xortool/args.py +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env python -#-*- coding:utf-8 -*- - -from docopt import docopt - -from routine import parse_char - - -class ArgError(Exception): - pass - - -def parse_parameters(doc, version): - p = docopt(doc, version=version) - p = {k.lstrip("-"): v for k, v in p.items()} - try: - return { - "input_is_hex": bool(p["hex"]), - "max_key_length": int(p["max-keylen"]), - "known_key_length": int(p["key-length"]) if p["key-length"] else None, - "most_frequent_char": parse_char(p["char"]) if p["char"] else None, - "brute_chars": bool(p["brute-chars"]), - "brute_printable": bool(p["brute-printable"]), - "frequency_spread": 0, # to be removed - "filename": p["FILE"] if p["FILE"] else "-", # stdin by default - } - except ValueError as err: - raise ArgError(str(err)) diff --git a/xortool/xortool/colors.py b/xortool/xortool/colors.py deleted file mode 100644 index 04057c0..0000000 --- a/xortool/xortool/colors.py +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env python -#-*- coding:utf-8 -*- - -from libcolors import color - -C_RESET = color() -C_FATAL = color("red") -C_WARN = color("yellow") - -C_KEYLEN = color("green") -C_PROB = color("white", attrs="") -C_BEST_KEYLEN = color("green", attrs="bold") -C_BEST_PROB = color("white", attrs="bold") - -C_DIV = color(attrs="bold") - -C_KEY = color("red", attrs="bold") -C_BOLD = color(attrs="bold") -C_COUNT = color("yellow", attrs="bold") diff --git a/xortool/xortool/libcolors.py b/xortool/xortool/libcolors.py deleted file mode 100644 index 64a5c96..0000000 --- a/xortool/xortool/libcolors.py +++ /dev/null @@ -1,80 +0,0 @@ -#!/usr/bin/env python -#-*- coding:utf-8 -*- - -import os - - -BASH_ATTRIBUTES = {"regular": "0", - "bold": "1", "underline": "4", "strike": "9", - "light": "1", "dark": "2", - "invert": "7"} # invert bg and fg - -BASH_COLORS = {"black": "30", "red": "31", "green": "32", "yellow": "33", - "blue": "34", "purple": "35", "cyan": "36", "white": "37"} - -BASH_BGCOLORS = {"black": "40", "red": "41", "green": "42", "yellow": "43", - "blue": "44", "purple": "45", "cyan": "46", "white": "47"} - - -def _main(): - header = color("white", "black", "dark") - print - - print header + " " + "Colors and backgrounds: " + color() - for c in _keys_sorted_by_values(BASH_COLORS): - c1 = color(c) - c2 = color("white" if c != "white" else "black", bgcolor=c) - print (c.ljust(10) + - c1 + "colored text" + color() + " " + - c2 + "background" + color()) - print - - print header + " " + "Attributes: " + color() - for c in _keys_sorted_by_values(BASH_ATTRIBUTES): - c1 = color("red", attrs=c) - c2 = color("white", attrs=c) - print (c.ljust(13) + - c1 + "red text" + color() + " " + - c2 + "white text" + color()) - print - return - - -def color(color=None, bgcolor=None, attrs=None): - if not is_bash(): - return "" - - ret = "\x1b[0" - if attrs: - for attr in attrs.lower().split(): - attr = attr.strip(",+|") - if attr not in BASH_ATTRIBUTES: - raise ValueError("Unknown color attribute: " + attr) - ret += ";" + BASH_ATTRIBUTES[attr] - - if color: - if color in BASH_COLORS: - ret += ";" + BASH_COLORS[color] - else: - raise ValueError("Unknown color: " + color) - - if bgcolor: - if bgcolor in BASH_BGCOLORS: - ret += ";" + BASH_BGCOLORS[bgcolor] - else: - raise ValueError("Unknown background color: " + bgcolor) - - return ret + "m" - - -def is_bash(): - return os.environ.get("SHELL", "unknown").endswith("bash") - - -def _keys_sorted_by_values(adict): - """Return list of the keys of @adict sorted by values.""" - return sorted(adict, key=adict.get) - - -if __name__ == "__main__": - _main() diff --git a/xortool/xortool/routine.py b/xortool/xortool/routine.py deleted file mode 100644 index 3d9fae3..0000000 --- a/xortool/xortool/routine.py +++ /dev/null @@ -1,98 +0,0 @@ -#!/usr/bin/env python -#-*- coding:utf-8 -*- - -import os -import sys -import string - - -class MkdirError(Exception): - pass - - -def load_file(filename): - if filename == "-": - return sys.stdin.read() - fd = open(filename, "rb") - contents = fd.read() - fd.close() - return contents - - -def save_file(filename, data): - fd = open(filename, "wb") - fd.write(data) - fd.close() - return - - -def mkdir(dirname): - if os.path.exists(dirname): - return - try: - os.mkdir(dirname) - except BaseException as err: - raise MkdirError(str(err)) - return - - -def rmdir(dirname): - if dirname[-1] == os.sep: - dirname = dirname[:-1] - if os.path.islink(dirname): - return # do not clear link - we can get out of dir - files = os.listdir(dirname) - for f in files: - if f == '.' or f == '..': - continue - path = dirname + os.sep + f - if os.path.isdir(path): - rmdir(path) - else: - os.unlink(path) - os.rmdir(dirname) - return - - -def decode_from_hex(text): - only_hex_digits = "".join([c for c in text if c in string.hexdigits]) - return only_hex_digits.decode("hex") - - -def parse_char(ch): - """ - 'A' or '\x41' or '41' - """ - if len(ch) == 1: - return ord(ch) - if ch[0:2] == "\\x": - ch = ch[2:] - if not ch: - raise ValueError("Empty char") - return ord(chr(int(ch, 16))) - - -def dexor(text, key): - ret = list(text) - mod = len(key) - for index, char in enumerate(ret): - ret[index] = chr(ord(char) ^ ord(key[index % mod])) - return "".join(ret) - - -def die(exitMessage, exitCode=1): - print exitMessage - sys.exit(exitCode) - - -def is_linux(): - return sys.platform.startswith("linux") - - -def alphanum(s): - lst = list(s) - for index, char in enumerate(lst): - if char in (string.letters + string.digits): - continue - lst[index] = char.encode("hex") - return "".join(lst) diff --git a/xortool/xortool/xortool b/xortool/xortool/xortool deleted file mode 100755 index 829f150..0000000 --- a/xortool/xortool/xortool +++ /dev/null @@ -1,381 +0,0 @@ -#!/usr/bin/env python -#-*- coding:utf-8 -*- -""" -xortool - 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) - -Usage: - xortool [-x] [-m MAX-LEN] [FILE] - xortool [-x] [-l LEN] [-c CHAR | -b | -o] [FILE] - xortool [-x] [-m MAX-LEN| -l LEN] [-c CHAR | -b | -o] [FILE] - xortool [-h | --help] - xortool --version - -Options: - -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 - -h --help show this help - -Examples: - xortool file.bin - xortool -l 11 -c 20 file.bin - xortool -x -c ' ' file.hex -""" - -from operator import itemgetter - -import os -import string -import xortool -from xortool.colors import * - -from xortool.routine import * -from xortool.args import parse_parameters, ArgError - -DIRNAME = 'xortool_out' # here plaintexts will be placed -PARAMETERS = dict() - - -class AnalysisError(Exception): - pass - - -def main(): - global PARAMETERS - try: - PARAMETERS = parse_parameters(__doc__, xortool.__version__) - ciphertext = get_ciphertext() - update_key_length(ciphertext) - - if PARAMETERS["brute_chars"]: - try_chars = range(256) - elif PARAMETERS["brute_printable"]: - try_chars = map(ord, string.printable) - elif PARAMETERS["most_frequent_char"] != None: - try_chars = [PARAMETERS["most_frequent_char"]] - else: - die(C_WARN + - "Most possible char is needed to guess the key!" + - C_RESET) - - (probable_keys, - key_char_used) = guess_probable_keys_for_chars(ciphertext, try_chars) - - print_keys(probable_keys) - produce_plaintexts(ciphertext, probable_keys, key_char_used) - - except IOError as err: - print C_FATAL + "[ERROR] Can't load file:\n\t", err, C_RESET - except ArgError as err: - print C_FATAL + "[ERROR] Bad argument:\n\t", err, C_RESET - except MkdirError as err: - print C_FATAL + "[ERROR] Can't create directory:\n\t", err, C_RESET - except AnalysisError as err: - print C_FATAL + "[ERROR] Analysis error:\n\t", err, C_RESET - else: - return - cleanup() - - -# ----------------------------------------------------------------------------- -# LOADING CIPHERTEXT -# ----------------------------------------------------------------------------- - -def get_ciphertext(): - """ - Load ciphertext from a file or stdin and hex-decode if needed - """ - ciphertext = load_file(PARAMETERS["filename"]) - if PARAMETERS["input_is_hex"]: - ciphertext = decode_from_hex(ciphertext) - return ciphertext - - -# ----------------------------------------------------------------------------- -# KEYLENGTH GUESSING SECTION -# ----------------------------------------------------------------------------- - -def update_key_length(text): - """ - Guess length of the key if it's not set. (Updates PARAMETERS) - """ - global PARAMETERS - if PARAMETERS["known_key_length"]: - return - PARAMETERS["known_key_length"] = guess_key_length(text) - return - - -def guess_key_length(text): - """ - Try key lengths from 1 to max_key_length and print local maximums. - Set key_length to the most possible if it's not set by user. - """ - fitnesses = calculate_fitnesses(text) - if not fitnesses: - raise AnalysisError("No candidates for key length found! Too small file?") - - print_fitnesses(fitnesses) - guess_and_print_divisors(fitnesses) - return get_max_fitnessed_key_length(fitnesses) - - -def calculate_fitnesses(text): - """ - Calc. fitnesses for each keylen - """ - prev = 0 - pprev = 0 - fitnesses = [] - for key_length in range(1, PARAMETERS["max_key_length"] + 1): - fitness = count_equals(text, key_length) - - # smaller key-length with nearly the same fitness is preferable - fitness = (float(fitness) / - (PARAMETERS["max_key_length"] + key_length ** 1.5)) - - if pprev < prev and prev > fitness: # local maximum - fitnesses += [(key_length - 1, prev)] - - pprev = prev - prev = fitness - - if pprev < prev: - fitnesses += [(key_length - 1, prev)] - - return fitnesses - - -def print_fitnesses(fitnesses): - print "The most probable key lengths:" - - # top sorted by fitness, but print sorted by length - fitnesses.sort(key=itemgetter(1), reverse=True) - top10 = fitnesses[:10] - best_fitness = top10[0][1] - top10.sort(key=itemgetter(0)) - - fitness_sum = calculate_fitness_sum(top10) - - for key_length, fitness in top10: - s1 = str(key_length).rjust(4, " ") - s2 = str(round(100 * fitness * 1.0 / fitness_sum, 1)) + "%" - if fitness == best_fitness: - print (C_BEST_KEYLEN + s1 + C_RESET + ": " - + C_BEST_PROB + s2 + C_RESET) - else: - print (C_KEYLEN + s1 + C_RESET + ": " - + C_PROB + s2 + C_RESET) - return - - -def calculate_fitness_sum(fitnesses): - return sum([f[1] for f in fitnesses]) - - -def count_equals(text, key_length): - """ - count equal chars count for each offset and sum them - """ - equals_count = 0 - if key_length >= len(text): - return 0 - - for offset in range(key_length): - chars_count = chars_count_at_offset(text, key_length, offset) - equals_count += max(chars_count.values()) - 1 # why -1? don't know - return equals_count - - -def guess_and_print_divisors(fitnesses): - """ - Prints common divisors and returns the most common divisor - """ - divisors_counts = [0] * (PARAMETERS["max_key_length"] + 1) - for key_length, fitness in fitnesses: - for number in range(3, key_length + 1): - if key_length % number == 0: - divisors_counts[number] += 1 - max_divisors = max(divisors_counts) - - limit = 3 - ret = 2 - for number, divisors_count in enumerate(divisors_counts): - if divisors_count == max_divisors: - print "Key-length can be " + C_DIV + str(number) + "*n" + C_RESET - ret = number - limit -= 1 - if limit == 0: - return ret - return ret - - -def get_max_fitnessed_key_length(fitnesses): - max_fitness = 0 - max_fitnessed_key_length = 0 - for key_length, fitness in fitnesses: - if fitness > max_fitness: - max_fitness = fitness - max_fitnessed_key_length = key_length - return max_fitnessed_key_length - - -def chars_count_at_offset(text, key_length, offset): - chars_count = dict() - for pos in range(offset, len(text), key_length): - c = text[pos] - if c in chars_count: - chars_count[c] += 1 - else: - chars_count[c] = 1 - return chars_count - - -# ----------------------------------------------------------------------------- -# KEYS GUESSING SECTION -# ----------------------------------------------------------------------------- - -def guess_probable_keys_for_chars(text, try_chars): - """ - Guess keys for list of characters. - """ - probable_keys = [] - key_char_used = {} - - for c in try_chars: - keys = guess_keys(text, c) - for key in keys: - key_char_used[key] = c - if key not in probable_keys: - probable_keys.append(key) - - return probable_keys, key_char_used - - -def guess_keys(text, most_char): - """ - Generate all possible keys for key length - and the most possible char - """ - key_length = PARAMETERS["known_key_length"] - key_possible_bytes = [[] for _ in range(key_length)] - - for offset in range(key_length): # each byte of key< - chars_count = chars_count_at_offset(text, key_length, offset) - max_count = max(chars_count.values()) - for char in chars_count: - if chars_count[char] >= max_count: - key_possible_bytes[offset].append(chr(ord(char) ^ most_char)) - - return all_keys(key_possible_bytes) - - -def all_keys(key_possible_bytes, key_part="", offset=0): - """ - Produce all combinations of possible key chars - """ - keys = [] - if offset >= len(key_possible_bytes): - return [key_part] - for c in key_possible_bytes[offset]: - keys += all_keys(key_possible_bytes, key_part + c, offset + 1) - return keys - - -def print_keys(keys): - if not keys: - print "No keys guessed!" - return - - s1 = C_COUNT + str(len(keys)) + C_RESET - s2 = C_COUNT + str(len(keys[0])) + C_RESET - print "{} possible key(s) of length {}:".format(s1, s2) - for key in keys[:5]: - print C_KEY + repr(key)[1:-1] + C_RESET - if len(keys) > 10: - print "..." - - -# ----------------------------------------------------------------------------- -# RETURNS PERCENTAGE OF PRINTABLE CHARS -# ----------------------------------------------------------------------------- - -def percentage_printable(text): - x = 0.0 - for c in text: - if c in string.printable: - x += 1 - return x / len(text) - - -# ----------------------------------------------------------------------------- -# PRODUCE OUTPUT -# ----------------------------------------------------------------------------- - -def produce_plaintexts(ciphertext, keys, key_char_used): - """ - Produce plaintext variant for each possible key, - creates csv files with keys, percentage of printable - characters and used most frequent character - """ - cleanup() - mkdir(DIRNAME) - - # this is split up in two files since the - # key can contain all kinds of characters - - fn_key_mapping = "filename-key.csv" - fn_perc_mapping = "filename-char_used-perc_printable.csv" - - key_mapping = open(os.path.join(DIRNAME, fn_key_mapping), "w") - perc_mapping = open(os.path.join(DIRNAME, fn_perc_mapping), "w") - - key_mapping.write("file_name;key_repr\n") - perc_mapping.write("file_name;char_used;perc_printable\n") - - threshold_printable = 95 - count_printable = 0 - - for index, key in enumerate(keys): - key_index = str(index).rjust(len(str(len(keys) - 1)), "0") - key_repr = repr(key)[1:-1].replace("/", "\\x2f") - if not is_linux(): - key_repr = alphanum(key) - file_name = os.path.join(DIRNAME, key_index + ".out") - - dexored = dexor(ciphertext, key) - perc = round(100 * percentage_printable(dexored)) - if perc > threshold_printable: - count_printable += 1 - key_mapping.write("{};{}\n".format(file_name, key_repr)) - perc_mapping.write("{};{};{}\n".format(file_name, - repr(key_char_used[key]), - perc)) - f = open(file_name, "wb") - f.write(dexored) - f.close() - key_mapping.close() - perc_mapping.close() - - s1 = C_COUNT + str(count_printable) + C_RESET - s2 = C_COUNT + str(round(threshold_printable)) + C_RESET - - print "Found {} plaintexts with {}%+ printable characters".format(s1, s2) - print "See files {}, {}".format(fn_key_mapping, fn_perc_mapping) - return - - -def cleanup(): - if os.path.exists(DIRNAME): - rmdir(DIRNAME) - return - - -if __name__ == "__main__": - main() diff --git a/xortool/xortool/xortool-xor b/xortool/xortool/xortool-xor deleted file mode 100755 index e8248ad..0000000 --- a/xortool/xortool/xortool-xor +++ /dev/null @@ -1,116 +0,0 @@ -#!/usr/bin/env python -#-*- coding:utf-8 -*- - -""" -xor strings -options: - -s - string with \\xAF escapes - -r - raw string - -h - hex-encoded string (non-letterdigit chars are stripped) - -f - read data from file (- for stdin) - -n - no newline at the end - --no-cycle / --nc - pad smaller strings with null bytes -example: xor -s lol -h 414243 -f /etc/passwd - -author: hellman ( hellman1908@gmail.com ) -""" - -import sys -import string -import getopt - - -DATA_OPTS = "s:r:h:f:" -HEXES = set("0123456789abcdefABCDEF") - - -def main(): - nocycle = False - nonewline = False - try: - opts, args = getopt.getopt(sys.argv[1:], "n" + DATA_OPTS, ["no-cycle", "nc"]) - datas = [] - for c, val in opts: - if c in ("--no-cycle", "--nc"): - nocycle = True - elif c == "-n": - nonewline = True - else: - v = arg_data(c, val) - if v is None: - raise getopt.GetoptError("unknown option %s" % c) - datas.append(v) - if not datas: - raise getopt.GetoptError("no data given") - except getopt.GetoptError as e: - print >>sys.stderr, "error:", e - print >>sys.stderr, __doc__ - quit() - - sys.stdout.write(xor(datas, nocycle=nocycle)) - if not nonewline: - sys.stdout.write("\n") - - -def xor(args, nocycle=False): - maxlen = max(map(len, args)) - res = [0] * maxlen - if nocycle: - for s in args: - for i in xrange(len(s)): - res[i] ^= ord(s[i]) - else: - for s in args: - slen = len(s) - for i in xrange(maxlen): - res[i] ^= ord(s[i % slen]) - return "".join(map(chr, res)) - - -def from_str(s): - res = "" - i = 0 - while True: - if i + 4 > len(s): - break - - if s[i+1] == "x" and s[i+2] in HEXES and s[i+3] in HEXES: - res += chr(int(s[i+2:i+4], 16)) - i += 4 - else: - res += s[i] - i += 1 - res += s[i:] - return res - - -def from_hex(s): - res = "" - for c in s: - if c in HEXES: - res += c - elif c in string.ascii_letters: - raise ValueError("Bad splitters (alphanum)") - return res.decode("hex") - - -def from_file(s): - if s == "-": - return sys.stdin.read() - return open(s, "rb").read() - - -def arg_data(opt, s): - if opt == "-s": - return from_str(s) - elif opt == "-r": - return s - elif opt == "-h": - return from_hex(s) - elif opt == "-f": - return from_file(s) - return None - - -if __name__ == '__main__': - main()