├── .gitignore ├── README.md ├── audodecoder.py └── utils ├── atbash.py ├── autokey.py ├── baconian.py ├── base.py ├── beaufort.py ├── caesar.py ├── decoder.py ├── morsecode.py ├── playfair.py ├── rot13.py ├── rot47.py └── vigenere.py /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__ 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AutoDecoder.py 2 | Tool to automatically decode/decipher a message. The following decoders/deciphers have been implemented: 3 | 4 | - Base16 5 | - Base32 6 | - Base64 7 | - Base85 8 | - Autokey 9 | - Atbash 10 | - Baconian 11 | - Beaufort 12 | - Caesar 13 | - MorseCode 14 | - ROT13 15 | - ROT47 16 | - Playfair 17 | - Vigenère 18 | 19 | # Installation 20 | git clone https://github.com/oreosES/autodecoder.git 21 | 22 | # Dependencies 23 | Python3 argparse, colorama, pycipher and pyperclip libraries. To install them using pip3: 24 | 25 | pip3 install argparse colorama pycipher pyperclip 26 | 27 | # Usage 28 | python3 audodecoder.py -h 29 | 30 | usage: audodecoder.py [-h] [-l LEVELS] [-k KEY] [-p PATTERN] -m MESSAGE 31 | 32 | AutoDecoder.py 33 | 34 | optional arguments: 35 | - -h, --help show this help message and exit 36 | - -l LEVELS, --levels LEVELS 37 | Number of decoding levels [1-6], default = 2 38 | - -k KEY, --key KEY Key used to decode 39 | - -c CAESAR, --caesar CAESAR 40 | Caesar shift to use [0-25], default = 3 41 | - -s, --show_all Show chains with errors during decoding 42 | - -p PATTERN, --pattern PATTERN 43 | Search pattern in decoded string 44 | 45 | required named arguments: 46 | - -m MESSAGE, --message MESSAGE 47 | Message to decode 48 | 49 | # Example 50 | 51 | echo -n "TEST" | base64 | base64 52 | VkVWVFZBPT0K 53 | 54 | python3 autodecoder.py --message VkVWVFZBPT0K --levels 2 55 | - base64 > base64 > TEST 56 | - base64 > rot13 > IRIGIN== 57 | - base64 > rot47 > 't'%'pll 58 | - rot13 > base64 > # !m 59 | - rot13 > rot13 > VkVWVFZBPT0K 60 | - rot13 > rot47 > xIxyx$|~rv_) 61 | - rot47 > rot13 > '<'('h+d!%_m 62 | - rot47 > rot47 > VkVWVFZBPT0K 63 | 64 | # Contact 65 | https://www.twitter.com/oreos_es 66 | -------------------------------------------------------------------------------- /audodecoder.py: -------------------------------------------------------------------------------- 1 | try: 2 | from colorama import Fore 3 | import argparse 4 | import pycipher 5 | import pyperclip 6 | from utils.decoder import Decoder 7 | from itertools import product 8 | except: 9 | print("\ 10 | AutoDecoder.py - Error: Install required libraries\n\ 11 | pip3 install argparse colorama pycipher pyperclip") 12 | exit() 13 | 14 | def banner(): 15 | print(Fore.WHITE) 16 | print("\n\ 17 | ( \n\ 18 | ( ( )\ ) ( \n\ 19 | )\ ( )\ ) (()/( ( )\ ) ( ( \n\ 20 | ((((_)( ))\ (()/( ( /(_)) ))\ ( ( (()/( ))\ )( \n\ 21 | )\ _ )\ /((_) ((_)) )\(_))_ /((_) )\ )\ ((_))/((_)(()\ \n\ 22 | (_)_\(_)(_))( _| | ((_)| \ (_)) ((_)((_) _| |(_)) ((_) \n\ 23 | / _ \ | || |/ _` |/ _ \| |) |/ -_)/ _|/ _ \/ _` |/ -_) | '_| \n\ 24 | /_/ \_\ \_,_|\__,_|\___/|___/ \___|\__|\___/\__,_|\___| |_| \n\n\ 25 | Author: oreos | Twitter: @oreos_ES\n\n") 26 | 27 | def decodefunc(args): 28 | message = args.message 29 | key = args.key 30 | levels = args.levels 31 | pattern = args.pattern 32 | shift = args.caesar 33 | show_all = args.show_all 34 | 35 | decoder = Decoder() 36 | decoders = [ 37 | "base16", 38 | "base32", 39 | "base64", 40 | "base85", 41 | "autokey", 42 | "atbash", 43 | "baconian", 44 | "beaufort", 45 | "caesar", 46 | "morse", 47 | "rot13", 48 | "rot47", 49 | "playfair", 50 | "vigenere" 51 | ] 52 | combdecs = list(product(decoders, repeat=levels)) 53 | for arraydecs in combdecs: 54 | translated = message 55 | flow = "" 56 | for dec in arraydecs: 57 | translated = decoder.decode(dec, translated, shift, key) 58 | if translated is None: 59 | if show_all is not None and show_all: 60 | print(Fore.RED+" > ".join(arraydecs)) 61 | break 62 | if translated is not None: 63 | if pattern is None or (pattern and pattern in translated): 64 | print(Fore.WHITE+" > ".join(arraydecs)+": "+Fore.BLUE+translated) 65 | 66 | def main(): 67 | banner() 68 | parser = argparse.ArgumentParser(description='AutoDecoder.py') 69 | parser.add_argument("-l", "--levels", type=int, help='Number of decoding levels [1-6], default = 2', default=2) 70 | parser.add_argument("-k", "--key", type=str, help='Key used to decode') 71 | parser.add_argument("-c", "--caesar", type=int, help='Caesar shift to use [0-25], default = 3', default=3) 72 | parser.add_argument("-s", "--show_all", help='Show chains with errors during decoding', action='store_true') 73 | parser.add_argument("-p", "--pattern", type=str, help='Search pattern in decoded string') 74 | requiredNamed = parser.add_argument_group('required named arguments') 75 | requiredNamed.add_argument('-m', '--message', help='Message to decode', required=True) 76 | args = parser.parse_args() 77 | 78 | decodefunc(args) 79 | 80 | if __name__== "__main__": 81 | main() 82 | -------------------------------------------------------------------------------- /utils/atbash.py: -------------------------------------------------------------------------------- 1 | from pycipher import Atbash 2 | 3 | class AtBash: 4 | def decode(self, message): 5 | try: 6 | return Atbash().decipher(message) 7 | except: 8 | return None -------------------------------------------------------------------------------- /utils/autokey.py: -------------------------------------------------------------------------------- 1 | from pycipher import Autokey 2 | 3 | class AutoKey: 4 | def decode(self, message, key): 5 | try: 6 | return Autokey(key).decipher(message) 7 | except: 8 | return None -------------------------------------------------------------------------------- /utils/baconian.py: -------------------------------------------------------------------------------- 1 | from unicodedata import normalize 2 | import re 3 | 4 | class Baconian: 5 | def generate_dict(self): 6 | bacon_dict = {} 7 | for i in range(0, 26): 8 | tmp = bin(i)[2:].zfill(5) 9 | tmp = tmp.replace('0', 'a') 10 | tmp = tmp.replace('1', 'b') 11 | bacon_dict[tmp] = chr(65 + i) 12 | return bacon_dict 13 | 14 | def decode(self, message): 15 | try: 16 | translated = '' 17 | bacon_dict = self.generate_dict() 18 | message = message.lower() 19 | message = re.sub(r'[^ab]+', '', message) 20 | for i in range(0, int(len(message) / 5)): 21 | translated += bacon_dict.get(message[i * 5:i * 5 + 5], ' ') 22 | translated = translated if len(translated) > 0 else None 23 | return translated.rstrip('\n') 24 | except: 25 | return None 26 | -------------------------------------------------------------------------------- /utils/base.py: -------------------------------------------------------------------------------- 1 | import base64 2 | 3 | class Base(): 4 | def decode16(self, message): 5 | try: 6 | return base64.b16decode(message).decode("utf-8").rstrip('\n') 7 | except: 8 | return None 9 | 10 | def decode32(self, message): 11 | try: 12 | return base64.b32decode(message).decode("utf-8").rstrip('\n') 13 | except: 14 | return None 15 | 16 | def decode64(self, message): 17 | try: 18 | return base64.b64decode(message).decode("utf-8").rstrip('\n') 19 | except: 20 | return None 21 | 22 | def decode85(self, message): 23 | try: 24 | return base64.b85decode(message).decode("utf-8").rstrip('\n') 25 | except: 26 | return None -------------------------------------------------------------------------------- /utils/beaufort.py: -------------------------------------------------------------------------------- 1 | from pycipher import Beaufort 2 | 3 | class BeauFort: 4 | def decode(self, message, key): 5 | try: 6 | return Beaufort(key).decipher(message) 7 | except: 8 | return None -------------------------------------------------------------------------------- /utils/caesar.py: -------------------------------------------------------------------------------- 1 | class Caesar: 2 | a, z = ord('a'), ord('z') 3 | A, Z = ord('A'), ord('Z') 4 | def getShiftCh(self, ch, shift): 5 | result = dif = ord(ch) + shift 6 | if dif > self.Z: 7 | result = (dif - self.Z) % 26 - 1 + self.A 8 | elif dif < self.A: 9 | result = self.Z - ((self.A - dif) % 26 - 1) 10 | return chr(result) 11 | 12 | def decode(self, message, shift): 13 | try: 14 | translated = "" 15 | for ch in message: 16 | if ch.islower(): 17 | translated += self.getShiftCh(ch, shift) 18 | elif ch.isupper(): 19 | translated += self.getShiftCh(ch, shift) 20 | else: 21 | translated += ch 22 | translated = translated if len(translated) > 0 else None 23 | return translated.rstrip('\n') 24 | except: 25 | return None -------------------------------------------------------------------------------- /utils/decoder.py: -------------------------------------------------------------------------------- 1 | from utils.base import Base 2 | from utils.autokey import AutoKey 3 | from utils.atbash import AtBash 4 | from utils.beaufort import BeauFort 5 | from utils.baconian import Baconian 6 | from utils.caesar import Caesar 7 | from utils.morsecode import MorseCode 8 | from utils.rot13 import Rot13 9 | from utils.rot47 import Rot47 10 | from utils.playfair import PlayFair 11 | from utils.vigenere import Vigenere 12 | 13 | class Decoder(): 14 | def decode(self, decoder, message, shift, key=None): 15 | base = Base() 16 | autokey = AutoKey() 17 | atbash = AtBash() 18 | baconian = Baconian() 19 | beaufort = BeauFort() 20 | caesar = Caesar() 21 | morsecode = MorseCode() 22 | rot13 = Rot13() 23 | rot47 = Rot47() 24 | playfair = PlayFair() 25 | vigenere = Vigenere() 26 | 27 | if decoder == "base16": 28 | translated = base.decode16(message) 29 | elif decoder == "base32": 30 | translated = base.decode32(message) 31 | elif decoder == "base64": 32 | translated = base.decode64(message) 33 | elif decoder == "base85": 34 | translated = base.decode85(message) 35 | elif decoder == "autokey": 36 | translated = autokey.decode(message, key) 37 | elif decoder == "atbash": 38 | translated = atbash.decode(message) 39 | elif decoder == "baconian": 40 | translated = baconian.decode(message) 41 | elif decoder == "beaufort": 42 | translated = beaufort.decode(message, key) 43 | elif decoder == "caesar": 44 | translated = caesar.decode(message, shift) 45 | elif decoder == "morse": 46 | translated = morsecode.decode(message) 47 | elif decoder == "rot13": 48 | translated = rot13.decode(message) 49 | elif decoder == "rot47": 50 | translated = rot47.decode(message) 51 | elif decoder == "playfair": 52 | translated = playfair.decode(message, key) 53 | elif decoder == "vigenere": 54 | translated = vigenere.decode(message, key) 55 | else: 56 | translated = None 57 | return translated -------------------------------------------------------------------------------- /utils/morsecode.py: -------------------------------------------------------------------------------- 1 | class MorseCode(): 2 | dictionary = {'.-...': '&', '--..--': ',', '....-': '4', '.....': '5', 3 | '...---...': 'SOS', '-...': 'B', '-..-': 'X', '.-.': 'R', 4 | '.--': 'W', '..---': '2', '.-': 'A', '..': 'I', '..-.': 'F', 5 | '.': 'E', '.-..': 'L', '...': 'S', '..-': 'U', '..--..': '?', 6 | '.----': '1', '-.-': 'K', '-..': 'D', '-....': '6', '-...-': '=', 7 | '---': 'O', '.--.': 'P', '.-.-.-': '.', '--': 'M', '-.': 'N', 8 | '....': 'H', '.----.': "'", '...-': 'V', '--...': '7', '-.-.-.': ';', 9 | '-....-': '-', '..--.-': '_', '-.--.-': ')', '-.-.--': '!', '--.': 'G', 10 | '--.-': 'Q', '--..': 'Z', '-..-.': '/', '.-.-.': '+', '-.-.': 'C', '---...': ':', 11 | '-.--': 'Y', '-': 'T', '.--.-.': '@', '...-..-': '$', '.---': 'J', '-----': '0', 12 | '----.': '9', '.-..-.': '"', '-.--.': '(', '---..': '8', '...--': '3' 13 | } 14 | def decode(self, message): 15 | try: 16 | translated = [] 17 | for item in message.split(' '): 18 | translated.append(self.dictionary.get(item)) 19 | translated = translated if len(translated) > 0 else None 20 | return ''.join(translated).rstrip('\n') 21 | except: 22 | return None -------------------------------------------------------------------------------- /utils/playfair.py: -------------------------------------------------------------------------------- 1 | from pycipher import Playfair 2 | 3 | class PlayFair: 4 | def decode(self, message, key): 5 | try: 6 | return Playfair(key).decipher(message) 7 | except: 8 | return None -------------------------------------------------------------------------------- /utils/rot13.py: -------------------------------------------------------------------------------- 1 | from codecs import encode 2 | 3 | class Rot13(): 4 | def decode(self, message): 5 | return encode(message, 'rot13').rstrip('\n') -------------------------------------------------------------------------------- /utils/rot47.py: -------------------------------------------------------------------------------- 1 | class Rot47(): 2 | def decode(self, message): 3 | try: 4 | translated = [] 5 | for i in range(len(message)): 6 | j = ord(message[i]) 7 | if j >= 33 and j <= 126: 8 | translated.append(chr(33 + ((j + 14) % 94))) 9 | else: 10 | translated.append(message[i]) 11 | translated = translated if len(translated) > 0 else None 12 | return ''.join(translated).rstrip('\n') 13 | except: 14 | return None -------------------------------------------------------------------------------- /utils/vigenere.py: -------------------------------------------------------------------------------- 1 | import pyperclip 2 | 3 | class Vigenere: 4 | alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 5 | def decode(self, message, key): 6 | try: 7 | translated = [] 8 | keyIndex = 0 9 | key = key.upper() 10 | for symbol in message: 11 | num = self.alphabet.find(symbol.upper()) 12 | if num != -1: 13 | num -= self.alphabet.find(key[keyIndex]) 14 | num %= len(self.alphabet) 15 | if symbol.isupper(): 16 | translated.append(self.alphabet[num]) 17 | elif symbol.islower(): 18 | translated.append(self.alphabet[num].lower()) 19 | keyIndex += 1 20 | if keyIndex == len(key): 21 | keyIndex = 0 22 | else: 23 | translated.append(symbol) 24 | translated = translated if len(translated) > 0 else None 25 | return ''.join(translated).rstrip('\n') 26 | except: 27 | return None --------------------------------------------------------------------------------