├── README.md ├── capitalize_letters.py ├── combinator2.py ├── combinator3.py ├── combinator4.py ├── complexity_sorter.py ├── date_rule.py ├── example_md5_hashes.txt ├── get_pot_passwords.py ├── hash_generator.py ├── idiom_getter.py ├── leet_gen.py ├── leet_rule_generator.py ├── mask_finder.py ├── md5_hashgen.py ├── phrase_cleaner.py ├── phrase_combiner.py ├── positional_character_frequency.py ├── pot.py ├── quote_parser_001.py ├── quote_parser_002.py ├── quote_parser_003.py ├── remove_duplicates.py ├── seclist_password_combiner.py ├── wordlist_cleaner.py └── wordlist_searcher.py /README.md: -------------------------------------------------------------------------------- 1 | # Password Scripts 2 | 3 | ### mask_finder.py 4 | > Analyzes a password list to find frequency of password character masks. 5 | 6 | ### positional_character_frequency.py 7 | > Analyzes a password list to find frequency of characters per position. 8 | 9 | ### seclist_password_combiner.py 10 | > Combines, sorts, and uniques the passwords contained in files located at https://github.com/danielmiessler/SecLists. 11 | 12 | ### get_pot_passwords.py 13 | > Extracts the plain passwords from a hashcat or jtr pot file. 14 | 15 | ### md5_hashgen.py 16 | > Reads a plain password file, MD5s each password, and writes the hashes to a new file. 17 | 18 | ### remove_duplicates.py 19 | > Reads a file, removes duplicates, writes to a new file 20 | 21 | ### wordlist_cleaner.py 22 | > Reads a file, converts to lowercase, strips everything but lowercase letters, writes to new file. 23 | 24 | ### leet_gen.py 25 | > Reads a string or file, and creates a ridiculous amount of permutations using leet subsitutions. This will produce a LOT of output per word. 26 | 27 | ### capitalize_letters.py 28 | > Reads a file and capitalizes letters specified by index. If no index provided, will capitalize the first letter. 29 | 30 | ### wordlist_searcher.py 31 | > Searches a dictionary to see if a word exists. You can search for a single word, multiple words, or a words in a file. 32 | 33 | ### pot.py 34 | > Combines get_pot_passwords.py with wordlist_cleaner.py. 35 | 36 | ### combinator2.py 37 | > Combines two dictionaries. Can also title-case each word. 38 | 39 | ### combinator3.py 40 | > Combines three dictionaries. Can also title-case each word. 41 | 42 | ### combinator4.py 43 | > Combines four dictionaries. Can also title-case each word. 44 | -------------------------------------------------------------------------------- /capitalize_letters.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | __author__ = 'Jake Miller (@LaconicWolf)' 4 | __date__ = '20180924' 5 | __version__ = '0.01' 6 | __description__ = """Convert all words to lowercase and capitalizes letters at 7 | specified indexes. Can write output to a new file.""" 8 | 9 | import argparse 10 | import os 11 | 12 | def main(): 13 | print('[*] Reading file: {}...'.format(filename)) 14 | with open(filename, encoding="utf8", errors='ignore') as fh: 15 | words = fh.read().splitlines() 16 | print('[*] Processing {} words...'.format(len(words))) 17 | print('[*] Changing all words to lowercase...') 18 | words = [word.lower() for word in words] 19 | if args.all: 20 | print('[*] Capitalizing all letters...') 21 | capitalized_words = [word.upper() for word in words] 22 | elif args.index: 23 | print('[*] Capitalizing letters at specified indexes...') 24 | capitalized_words = [] 25 | for word in words: 26 | if not word: continue 27 | list_word = list(word) 28 | for pos in args.index: 29 | try: 30 | list_word[pos] = list_word[pos].capitalize() 31 | except IndexError as e: 32 | continue 33 | capitalized_words.append(''.join(list_word)) 34 | else: 35 | print('[*] Capitalizing first letter of each word...') 36 | capitalized_words = [word.title() for word in words] 37 | if args.outfile: 38 | print('[*] Writing to {}...'.format(args.outfile)) 39 | with open(args.outfile, 'w', encoding="utf8", errors='ignore') as fh: 40 | for word in capitalized_words: 41 | fh.write(word + '\n') 42 | else: 43 | for word in capitalized_words: 44 | print(word) 45 | 46 | if __name__ == '__main__': 47 | parser = argparse.ArgumentParser() 48 | parser.add_argument("-f", "--filename", 49 | help="Specify a file containing words.") 50 | parser.add_argument("-o", "--outfile", 51 | help="Writes the output to a specified file.") 52 | parser.add_argument("-a", "--all", 53 | action="store_true", 54 | help="Capitalizes all letters.") 55 | parser.add_argument("-i", "--index", 56 | nargs='*', 57 | type=int, 58 | help="Specify one or more integers to be used as positions (zero index) to capitalize a letter or letters.") 59 | args = parser.parse_args() 60 | if not args.filename: 61 | parser.print_help() 62 | print("\n[-] Please specify an input file containing words (-f).\n") 63 | exit() 64 | else: 65 | filename = args.filename 66 | if not os.path.exists(filename): 67 | print("\n[-] The file {} cannot be found or you do not have permission to open the file. Please check the path and try again\n".format(filename)) 68 | exit() 69 | main() 70 | -------------------------------------------------------------------------------- /combinator2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | __author__ = "Jake Miller (@LaconicWolf)" 4 | __date__ = "20181216" 5 | __version__ = "0.01" 6 | __description__ = """Combines two wordlists.""" 7 | 8 | import os 9 | import argparse 10 | 11 | def combine_words(wordlists): 12 | combined_words = [] 13 | d1 = wordlists[0] 14 | d2 = wordlists[1] 15 | for h in range(len(d1)): 16 | w1 = d1[h].title() if args.title_case else d1[h] 17 | for i in range(len(d2)): 18 | w2 = d2[i].title() if args.title_case else d2[i] 19 | combined_words.append(w1 + w2) 20 | return combined_words 21 | 22 | def main(): 23 | combined_words = combine_words(wordlists) 24 | if args.outfile: 25 | with open(args.outfile, 'w', encoding="utf8", errors='ignore') as fh: 26 | for word in combined_words: 27 | fh.write(word + '\n') 28 | else: 29 | for word in combined_words: 30 | print(word) 31 | 32 | if __name__ == '__main__': 33 | parser = argparse.ArgumentParser() 34 | parser.add_argument("-d", "--dictionaries", 35 | nargs="*", 36 | help="Specify a file or files containing words.") 37 | parser.add_argument("-o", "--outfile", 38 | help="Writes the output to a specified file.") 39 | parser.add_argument("-t", "--title_case", 40 | action="store_true", 41 | help="Capitalizes the first letter and lowercases the remaining letters of a word.") 42 | args = parser.parse_args() 43 | if not args.dictionaries: 44 | parser.print_help() 45 | print("\n[-] Please specify 2 dictionaries (-d dict1.txt dict2.txt).\n") 46 | exit() 47 | if len(args.dictionaries) != 2: 48 | parser.print_help() 49 | print("\n[-] You must specify 2 dictionaries (-d dict1.txt dict2.txt). No more, no less.\n") 50 | exit() 51 | wordlists = [] 52 | for file in args.dictionaries: 53 | if not os.path.exists(file): 54 | print("\n[-] The file {} cannot be found or you do not have permission to open the file. Please check the path and try again\n".format(file)) 55 | exit() 56 | with open(file, encoding="utf8", errors='ignore') as fh: 57 | words = fh.read().splitlines() 58 | wordlists.append(words) 59 | main() -------------------------------------------------------------------------------- /combinator3.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | __author__ = "Jake Miller (@LaconicWolf)" 4 | __date__ = "20181216" 5 | __version__ = "0.01" 6 | __description__ = """Combines three wordlists.""" 7 | 8 | import os 9 | import argparse 10 | 11 | def combine_words(wordlists): 12 | combined_words = [] 13 | d1 = wordlists[0] 14 | d2 = wordlists[1] 15 | d3 = wordlists[2] 16 | for h in range(len(d1)): 17 | w1 = d1[h].title() if args.title_case else d1[h] 18 | for i in range(len(d2)): 19 | w2 = d2[i].title() if args.title_case else d2[i] 20 | for j in range(len(d3)): 21 | w3 = d3[j].title() if args.title_case else d3[j] 22 | combined_words.append(w1 + w2 + w3) 23 | return combined_words 24 | 25 | def main(): 26 | combined_words = combine_words(wordlists) 27 | if args.outfile: 28 | with open(args.outfile, 'w', encoding="utf8", errors='ignore') as fh: 29 | for word in combined_words: 30 | fh.write(word + '\n') 31 | else: 32 | for word in combined_words: 33 | print(word) 34 | 35 | if __name__ == '__main__': 36 | parser = argparse.ArgumentParser() 37 | parser.add_argument("-d", "--dictionaries", 38 | nargs="*", 39 | help="Specify a file or files containing words.") 40 | parser.add_argument("-o", "--outfile", 41 | help="Writes the output to a specified file.") 42 | parser.add_argument("-t", "--title_case", 43 | action="store_true", 44 | help="Capitalizes the first letter and lowercases the remaining letters of a word.") 45 | args = parser.parse_args() 46 | if not args.dictionaries: 47 | parser.print_help() 48 | print("\n[-] Please specify 3 dictionaries (-d dict1.txt dict2.txt dict3.txt).\n") 49 | exit() 50 | if len(args.dictionaries) != 3: 51 | parser.print_help() 52 | print("\n[-] You must specify 3 dictionaries (-d dict1.txt dict2.txt dict3.txt). No more, no less.\n") 53 | exit() 54 | wordlists = [] 55 | for file in args.dictionaries: 56 | if not os.path.exists(file): 57 | print("\n[-] The file {} cannot be found or you do not have permission to open the file. Please check the path and try again\n".format(file)) 58 | exit() 59 | with open(file, encoding="utf8", errors='ignore') as fh: 60 | words = fh.read().splitlines() 61 | wordlists.append(words) 62 | main() -------------------------------------------------------------------------------- /combinator4.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | __author__ = "Jake Miller (@LaconicWolf)" 4 | __date__ = "20181216" 5 | __version__ = "0.01" 6 | __description__ = """Combines four wordlists.""" 7 | 8 | import os 9 | import argparse 10 | 11 | def combine_words(wordlists): 12 | combined_words = [] 13 | d1 = wordlists[0] 14 | d2 = wordlists[1] 15 | d3 = wordlists[2] 16 | d4 = wordlists[3] 17 | for h in range(len(d1)): 18 | w1 = d1[h].title() if args.title_case else d1[h] 19 | for i in range(len(d2)): 20 | w2 = d2[i].title() if args.title_case else d2[i] 21 | for j in range(len(d3)): 22 | w3 = d3[j].title() if args.title_case else d3[j] 23 | for k in range(len(d4)): 24 | w4 = d4[k].title() if args.title_case else d4[k] 25 | combined_words.append(w1 + w2 + w3 + w4) 26 | return combined_words 27 | 28 | def main(): 29 | combined_words = combine_words(wordlists) 30 | if args.outfile: 31 | with open(args.outfile, 'w', encoding="utf8", errors='ignore') as fh: 32 | for word in combined_words: 33 | fh.write(word + '\n') 34 | else: 35 | for word in combined_words: 36 | print(word) 37 | 38 | if __name__ == '__main__': 39 | parser = argparse.ArgumentParser() 40 | parser.add_argument("-d", "--dictionaries", 41 | nargs="*", 42 | help="Specify a file or files containing words.") 43 | parser.add_argument("-o", "--outfile", 44 | help="Writes the output to a specified file.") 45 | parser.add_argument("-t", "--title_case", 46 | action="store_true", 47 | help="Capitalizes the first letter and lowercases the remaining letters of a word.") 48 | args = parser.parse_args() 49 | if not args.dictionaries: 50 | parser.print_help() 51 | print("\n[-] Please specify 4 dictionaries (-d dict1.txt dict2.txt dict3.txt dict4.txt).\n") 52 | exit() 53 | if len(args.dictionaries) != 4: 54 | parser.print_help() 55 | print("\n[-] You must specify 4 dictionaries (-d dict1.txt dict2.txt dict3.txt dict4.txt). No more, no less.\n") 56 | exit() 57 | wordlists = [] 58 | for file in args.dictionaries: 59 | if not os.path.exists(file): 60 | print("\n[-] The file {} cannot be found or you do not have permission to open the file. Please check the path and try again\n".format(file)) 61 | exit() 62 | with open(file, encoding="utf8", errors='ignore') as fh: 63 | words = fh.read().splitlines() 64 | wordlists.append(words) 65 | main() -------------------------------------------------------------------------------- /complexity_sorter.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | __author__ = 'Jake Miller (@LaconicWolf)' 4 | __date__ = '20190401' 5 | __version__ = '0.01' 6 | __description__ = """Reads a file containing plain text words, accepts user input 7 | specifying the number of charsets present, and prints to new file words that meet 8 | the charset requirement.""" 9 | 10 | import argparse 11 | import string 12 | import os 13 | 14 | def get_complexity(word): 15 | """Analyzes a word and returns a tuple containing the 16 | word, along with a complexity number of the number of 17 | charsets present.""" 18 | complexity = 0 19 | lowercase = False 20 | uppercase = False 21 | special = False 22 | digits = False 23 | 24 | string.punctuation += ' ' 25 | 26 | for char in string.ascii_lowercase: 27 | if char in word: 28 | lowercase = True 29 | 30 | for char in string.ascii_uppercase: 31 | if char in word: 32 | uppercase = True 33 | 34 | for char in string.punctuation: 35 | if char in word: 36 | special = True 37 | 38 | for char in string.digits: 39 | if char in word: 40 | digits = True 41 | if lowercase: 42 | complexity += 1 43 | if uppercase: 44 | complexity += 1 45 | if special: 46 | complexity += 1 47 | if digits: 48 | complexity += 1 49 | return (word,complexity) 50 | 51 | 52 | def main(): 53 | sorted_words = [] 54 | print('[*] Reading file: {}...',format(filename)) 55 | with open(filename) as fh: 56 | words = fh.read().splitlines() 57 | print('[*] Getting word complexity...') 58 | word_tuple = [get_complexity(word) for word in words] 59 | for item in word_tuple: 60 | word = item[0] 61 | complexity = item[1] 62 | if complexity in [int(number) for number in args.complexity]: 63 | sorted_words.append(word) 64 | print('[+] Writing words to {}...'.format(outfile)) 65 | with open(outfile, 'w') as fh: 66 | for word in sorted_words: 67 | fh.write(word + '\n') 68 | print('[+] Complete!') 69 | 70 | if __name__ == '__main__': 71 | parser = argparse.ArgumentParser() 72 | parser.add_argument("-f", "--filename", 73 | help="Specify a file containing plain text passwords.") 74 | parser.add_argument("-o", "--outfile", 75 | help="Writes the output to a file, masks.txt, in the current directory.") 76 | parser.add_argument("-c", "--complexity", 77 | nargs='*', 78 | default=['1','2','3','4'], 79 | choices=['1','2','3','4'], 80 | help="Specify the the number of charsets the must be present.") 81 | parser.add_argument("-i", "--include_less_complex", 82 | help="Specify a file containing plain text passwords.") 83 | args = parser.parse_args() 84 | 85 | if not args.filename: 86 | parser.print_help() 87 | print("\n[-] Please specify a file containing plaintext passwords.\n") 88 | exit() 89 | filename = args.filename 90 | if not os.path.exists(filename): 91 | parser.print_help() 92 | print("\n[-] The file {}, does not exist or you lack permissions to open it. Please try again.\n".format(filename)) 93 | exit() 94 | 95 | outfile = args.outfile if args.outfile else "complexity_sorter_outfile.txt" 96 | main() -------------------------------------------------------------------------------- /date_rule.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | __author__ = 'Jake Miller (@LaconicWolf)' 4 | __date__ = '20190316' 5 | __version__ = '0.01' 6 | __description__ = """Creates a rule file that will append digits that may 7 | map to dates in popular formats that may be appended to files. You can also 8 | append or prepend characters or words, capitalize the first character of the 9 | words, and double the word. Dates are currently MDY, but can be DMY or YMD""" 10 | 11 | import argparse 12 | import time 13 | try: 14 | import pandas as pd 15 | except ImportError: 16 | print("This script requires Pandas. Try 'pip install pandas', or 'python -m pip install pandas', or do an Internet search for installation instructions.") 17 | exit() 18 | 19 | def create_2_digit_year(): 20 | """Returns a list of strings from 00-99.""" 21 | string_year_range = [] 22 | for i in range(0, 100): 23 | i = str(i) 24 | if len(i) < 2: 25 | i = '0' + i 26 | string_year_range.append(i) 27 | return string_year_range 28 | 29 | def create_month_day(start_year, end_year): 30 | """Returns a list of from 0101-1231.""" 31 | month_day_list = [] 32 | times = pd.date_range('01-01-{}'.format(start_year), '12-31-{}'.format(end_year)) 33 | for time in times: 34 | month_day_list.append(''.join(str(time).split(' ')[0].split('-')[1:])) 35 | return list(set(month_day_list)) 36 | 37 | def create_month_day_2_dig_year(start_year, end_year): 38 | """Returns a list of from 010100-123199.""" 39 | month_day_year = [] 40 | times = pd.date_range('01-01-{}'.format(start_year), '12-31-{}'.format(end_year)) 41 | for time in times: 42 | year = str(time).split('-')[0][-2:] 43 | month_day = ''.join(str(time).split(' ')[0].split('-')[1:]) 44 | month_day_year.append(month_day + year) 45 | return list(set(month_day_year)) 46 | 47 | def create_month_day_4_dig_year(start_year, end_year): 48 | """Returns a list of from 01011900-12312099.""" 49 | month_day_year = [] 50 | times = pd.date_range('01-01-{}'.format(start_year), '12-31-{}'.format(end_year)) 51 | for time in times: 52 | year = ''.join(str(time).split('-')[0]) 53 | month_day = ''.join(str(time).split(' ')[0].split('-')[1:]) 54 | month_day_year.append(month_day + year) 55 | return list(set(month_day_year)) 56 | 57 | def create_day_month(start_year, end_year): 58 | """Returns a list of from 0101-3112.""" 59 | day_month_list = [] 60 | times = pd.date_range('01-01-{}'.format(start_year), '12-31-{}'.format(end_year)) 61 | for time in times: 62 | day = str(time).split(' ')[0].split('-')[2] 63 | month = str(time).split(' ')[0].split('-')[1] 64 | day_month_list.append(day + month) 65 | return list(set(day_month_list)) 66 | 67 | def create_day_month_2_dig_year(start_year, end_year): 68 | """Returns a list of from 010100-311299.""" 69 | day_month_year = [] 70 | times = pd.date_range('01-01-{}'.format(start_year), '12-31-{}'.format(end_year)) 71 | for time in times: 72 | day = str(time).split(' ')[0].split('-')[2] 73 | month = str(time).split(' ')[0].split('-')[1] 74 | year = str(time).split('-')[0][-2:] 75 | day_month_year.append(day + month + year) 76 | return list(set(day_month_year)) 77 | 78 | def create_day_month_4_dig_year(start_year, end_year): 79 | """Returns a list of from 01011900-31122099.""" 80 | day_month_year = [] 81 | times = pd.date_range('01-01-{}'.format(start_year), '12-31-{}'.format(end_year)) 82 | for time in times: 83 | day = str(time).split(' ')[0].split('-')[2] 84 | month = str(time).split(' ')[0].split('-')[1] 85 | year = str(time).split('-')[0] 86 | day_month_year.append(day + month + year) 87 | return list(set(day_month_year)) 88 | 89 | def create_2_dig_year_month_day(start_year, end_year): 90 | """Returns a list of from 000101-991231.""" 91 | year_month_day = [] 92 | times = pd.date_range('01-01-2000', '12-31-2099') 93 | for time in times: 94 | year = str(time).split('-')[0][-2:] 95 | month_day = ''.join(str(time).split(' ')[0].split('-')[1:]) 96 | year_month_day.append(year + month_day) 97 | return list(set(year_month_day)) 98 | 99 | def create_4_dig_year_month_day(start_year, end_year): 100 | """Returns a list of from 19000101-20991231.""" 101 | year_month_day = [] 102 | times = pd.date_range('01-01-{}'.format(start_year), '12-31-{}'.format(end_year)) 103 | for time in times: 104 | year_month_day.append(str(time).split(' ')[0].replace('-', '')) 105 | return list(set(year_month_day)) 106 | 107 | def main(): 108 | print("[*] Generating dates...") 109 | 110 | # 00-99 111 | two_dig_year = create_2_digit_year() 112 | 113 | # 0101-1231 114 | month_day = create_month_day(start_year, end_year) 115 | 116 | # 010100-123199 117 | month_day_2_dig_year = create_month_day_2_dig_year(start_year, end_year) 118 | 119 | # 01011900-12312099 120 | month_day_4_dig_year = create_month_day_4_dig_year(start_year, end_year) 121 | 122 | # 0101-3112 123 | day_month = create_day_month(start_year, end_year) 124 | 125 | # 010100-311299 126 | day_month_2_dig_year = create_day_month_2_dig_year(start_year, end_year) 127 | 128 | # 01011900-31122099 129 | day_month_4_dig_year = create_day_month_4_dig_year(start_year, end_year) 130 | 131 | # 000101-991231 132 | two_dig_year_month_day = create_2_dig_year_month_day(start_year, end_year) 133 | 134 | # 19000101-20991231 135 | four_dig_year_month_day = create_4_dig_year_month_day(start_year, end_year) 136 | 137 | all_dates = two_dig_year 138 | if date_time_format == 'MDY': 139 | all_dates += month_day 140 | all_dates += month_day_2_dig_year 141 | all_dates += month_day_4_dig_year 142 | 143 | if date_time_format == 'YMD': 144 | all_dates += month_day 145 | all_dates += two_dig_year_month_day 146 | all_dates += four_dig_year_month_day 147 | 148 | if date_time_format == 'DMY': 149 | all_dates += month_day 150 | all_dates += two_dig_year_month_day 151 | all_dates += four_dig_year_month_day 152 | 153 | # Write to rule file 154 | print("[*] Writing rules...") 155 | with open(filename, 'w') as fh: 156 | for date in all_dates: 157 | # Dates only 158 | fh.write('${}\n'.format('$'.join(list(date)))) 159 | 160 | if args.title: 161 | # Capitalizes first letter then dates 162 | fh.write('c${}\n'.format('$'.join(list(date)))) 163 | 164 | if args.title and args.double: 165 | # Capitalizes first letter, doubles, then dates 166 | fh.write('cd${}\n'.format('$'.join(list(date)))) 167 | 168 | # Doubles, dates, then capitalizes first letter 169 | fh.write('d${}c\n'.format('$'.join(list(date)))) 170 | 171 | if appensions: 172 | for item in appensions: 173 | # Writes dates with items 174 | fh.write('${}${}\n'.format('$'.join(list(date)), '$'.join(list(item)))) 175 | 176 | if args.title: 177 | # Capitalizes, dates, and writes with items 178 | fh.write('c${}${}\n'.format('$'.join(list(date)), '$'.join(list(item)))) 179 | 180 | if args.double: 181 | # Capitalizes first letter, doubles, then dates with items 182 | fh.write('cd${}${}\n'.format('$'.join(list(date)), '$'.join(list(item)))) 183 | 184 | if args.title and args.double: 185 | # Capitalizes first letter, then doubles, dates and items 186 | fh.write('cd${}${}\n'.format('$'.join(list(date)), '$'.join(list(item)))) 187 | 188 | # Doubles, dates and items, then capitalizes first letter 189 | fh.write('d${}${}c\n'.format('$'.join(list(date)), '$'.join(list(item)))) 190 | 191 | if prepensions: 192 | for item in appensions: 193 | # Writes items with dates 194 | fh.write('^{}${}\n'.format('^'.join(list(item)[::-1]), '$'.join(list(date)) )) 195 | 196 | if args.title: 197 | # Capitalizes, dates, and writes with items 198 | fh.write('c^{}${}\n'.format('^'.join(list(item)[::-1]), '$'.join(list(date)) )) 199 | 200 | if args.double: 201 | # Capitalizes first letter, doubles, then dates with items 202 | fh.write('cd^{}${}\n'.format('^'.join(list(item)[::-1]), '$'.join(list(date)) )) 203 | 204 | if args.title and args.double: 205 | # Capitalizes first letter, then doubles, dates and items 206 | fh.write('cd^{}${}\n'.format('^'.join(list(item)[::-1]), '$'.join(list(date)) )) 207 | 208 | # Doubles, dates and items, then capitalizes first letter 209 | fh.write('d^{}${}c\n'.format('^'.join(list(item)[::-1]), '$'.join(list(date)) )) 210 | 211 | print("[+] Complete! Rule file written to {}".format(filename)) 212 | 213 | if __name__ == '__main__': 214 | parser = argparse.ArgumentParser() 215 | parser.add_argument("-f", "--format", 216 | nargs='?', 217 | const='MDY', 218 | default='MDY', 219 | choices=['DMY', 'MDY', 'YMD'], 220 | help="Choose date/time format. Default MDY") 221 | parser.add_argument("-d", "--double", 222 | help="Double word before appending date", 223 | action="store_true") 224 | parser.add_argument("-t", "--title", 225 | help="title case word", 226 | action="store_true") 227 | parser.add_argument("-a", "--append", 228 | nargs="*", 229 | help="Specify characters or words to add to end of dates, separated by spaces. (-a ! !! !!! !@#$") 230 | parser.add_argument("-p", "--prepend", 231 | nargs="*", 232 | help="Specify characters or words to add to the beginning of the word, separated by spaces. (-p ! !! !!! !@#$") 233 | parser.add_argument("-s", "--start_year", 234 | help="Specify 4 digit year as a starting date range. Default is 1970.") 235 | parser.add_argument("-e", "--end_year", 236 | help="Specify 4 digit year as a starting date range. Default is current year + 1.") 237 | parser.add_argument("-o", "--filename", 238 | help="Specify a filename to write to. Default is date_rule.rule") 239 | args = parser.parse_args() 240 | if args.start_year: 241 | if not args.start_year.isdigit() or len(args.start_year) != 4: 242 | print('[-] Start year must be a 4 digit year (-s 2005). Default is 1970') 243 | exit() 244 | start_year = args.start_year if args.start_year else '1970' 245 | if args.end_year: 246 | if not args.end_year.isdigit() or len(args.end_year) != 4: 247 | print('[-] End year must be a 4 digit year (-e 2019). Default is current year + 1') 248 | exit() 249 | 250 | date_time_format = args.format 251 | end_year = args.end_year if args.end_year else str(time.localtime().tm_year + 1) 252 | appensions = args.append if args.append else None 253 | prepensions = args.prepend if args.prepend else None 254 | filename = args.filename if args.filename else 'date_rule.rule' 255 | 256 | main() 257 | -------------------------------------------------------------------------------- /example_md5_hashes.txt: -------------------------------------------------------------------------------- 1 | 699cb5b6b8a56b9cd25cef37d199d4ac 2 | 260263760ece559fe365589d6c11eba9 3 | 2637051b051cfc5ade8a9a85f28a25cf 4 | fa45ce2768b3bcacf084cfcb08991e8b 5 | 37fe46e1fd7ce80760835d5ae7868bfc 6 | 70b7f532c9452004bf6a475b64a009c3 7 | b85bfe1a3e7b5e200dc806f221019d28 8 | 828113e6a780593648b5ca2c34da42da 9 | 8ba013fd99cdc64ee07d6b1dc98eb73f 10 | 6df8751a6a45bc56c4c834faac7925ee 11 | e309bdf1de5640f114fddfe5eac9ccf8 12 | 3f334b240048a0f6fc9546765d331922 13 | 178f2d3fbe316aa8a50417b17cb0a305 14 | 8c8539414e9a3cbde319212a99e7fb55 15 | 722c5acd147dccf514e9f8d43c4f1bf5 16 | 358df8ac69d9280117cbeaf7c93311d5 17 | 934cb4ea55342ef59e0a6f353fe75f22 18 | ec3a0498fda303aaa660ed775f13241e 19 | 4f3c3fc1575af79c32fcb2f096bda18f 20 | 0c8fda55b15fec3cdbe7a4ef96e93e68 21 | 14839d5c2c0465919e1c88e96ea7fcf9 22 | 08925418198cc8c94fadd5cc375355b1 23 | 083611c2b56aa90a7492471853c99446 24 | 4c3089589918649c8044a08a02d709ac 25 | 85eaccc021a9390c7d4965d6f3ce84bd 26 | 97435782796621bb14ede6f6bd04a940 27 | 74a32f9daf45084b0ea955ed06dd9c41 28 | cd17666830b55097a331e1e23175ba13 29 | 752aa8693aebd2d1c62f792c27959617 30 | c4d8676f8918542fb96b1ba34488a7e6 31 | 9fa6a7b1a11abed8c26125604db90727 32 | 3d461a885ea7115e1caf632c4dec4b96 33 | 85746df6be17313d0ff067a1b489dc43 34 | 3ecd86e03725554d6fc8138971c40d3f 35 | d9faa0dd65085891c66eb394b5a0dcb9 36 | e285a588711dd510afa6f416408b9edf 37 | 142853074e899f704f66624b7957caa1 38 | 2ea53aa3f3f3e64bf2e80c44eaf9c86d 39 | f59017ec3fad4abba289f856d640adf3 40 | 67ef6e0f615dd378572e42833dc2e3f2 41 | a4f2dcf6a952d8e5c0c1347eedc12024 42 | fa89a344f345a6c910ad3e158093ce1d 43 | 09ad2dc99adca85d7c7c746afe40cee5 44 | 55c72bf24748405d4129d994a6db2ae4 45 | 354a6305e24b52d1bacac1be01f36a26 46 | ad9d55297954e63f65451949b86d7d63 47 | cab43e4a2055f220c4685022fc44ef94 48 | 13ee3fa82956feb92ba06d9ab74811d6 49 | 0280abda9613ab7d99c5d7a6c5ca0ecf 50 | 24665528da7a9add56fe66c8414e3c8a 51 | -------------------------------------------------------------------------------- /get_pot_passwords.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | 4 | __author__ = 'Jake Miller (@LaconicWolf)' 5 | __date__ = '20180921' 6 | __version__ = '0.01' 7 | __description__ = """Extracts the plain passwords from a hashcat or jtr pot file.""" 8 | 9 | 10 | import argparse 11 | 12 | 13 | def decode_hashcat_hexstring(hexstring): 14 | """Parses a hex encoded password string ($HEX[476f6f646669676874343a37]) 15 | and returns the decodes the hex. 16 | """ 17 | index_1 = hexstring.index("[")+1 18 | index_2 = len(hexstring)-1 19 | hexdata = hexstring[index_1:index_2] 20 | return bytes.fromhex(hexdata).decode() 21 | 22 | 23 | def decode_hashcat_hex(data): 24 | """Calls the decoded_hashcat_hexstring on an encoded hex represented password 25 | ($HEX[476f6f646669676874343a37]). Occasionally the string will be encoded 26 | multiple times, so a loop is used until the $HEX prefix no longer remains. 27 | Returns the decodes the hexstring. 28 | """ 29 | while data.startswith('$HEX['): 30 | data = decode_hashcat_hexstring(data) 31 | return data 32 | 33 | 34 | def main(): 35 | 36 | # Reads in the potfile 37 | with open(potfile) as fh: 38 | lines = fh.read().splitlines() 39 | try: 40 | # Both JTR and Hashcat potfiles are colon delimited. In JTR pot files, 41 | # a colon in the password will mess up the split, so it must be split 42 | # from the first colon until the end of line. 43 | pt_passwords = [line.split(':')[1:] for line in lines] 44 | fixed_passwords = [] 45 | for line in pt_passwords: 46 | if len(line) > 1: 47 | fixed_passwords.append(':'.join(line)) 48 | else: 49 | fixed_passwords.append(''.join(line)) 50 | except IndexError as e: 51 | print('Error detected:') 52 | print(e) 53 | passwords = [] 54 | for password in fixed_passwords: 55 | 56 | # Hashcat will encode passwords containing colons or non-ascii characters. 57 | # This will decode those passwords if they are there. 58 | if password.startswith('$HEX['): 59 | passwords.append(decode_hashcat_hex(password)) 60 | else: 61 | passwords.append(password) 62 | 63 | # Output to file or print to terminal 64 | if args.outfile: 65 | with open(args.outfile, 'w') as fh: 66 | for password in passwords: 67 | fh.write(password + '\n') 68 | else: 69 | for password in passwords: 70 | print(password) 71 | 72 | 73 | if __name__ == '__main__': 74 | parser = argparse.ArgumentParser() 75 | parser.add_argument('-f', '--filename') 76 | parser.add_argument('-o', '--outfile') 77 | args = parser.parse_args() 78 | if not args.filename: 79 | parser.print_help() 80 | print("\n[-] Please specify the filename of the potfile\n") 81 | exit() 82 | else: 83 | potfile = args.filename 84 | main() 85 | -------------------------------------------------------------------------------- /hash_generator.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | 4 | __author__ = 'Jake Miller (@LaconicWolf)' 5 | __date__ = '20190102' 6 | __version__ = '0.01' 7 | __description__ = """Reads a plain text file and hashes each line. The hashes are written 8 | to a new file. The purpose of this tool is to generate sample hashes for testing password 9 | cracking.""" 10 | 11 | 12 | import hashlib 13 | import argparse 14 | import os 15 | 16 | def md5_hash(string_value): 17 | """Returns a md5 hash of the supplied string.""" 18 | return hashlib.md5(string_value.encode()).hexdigest() 19 | 20 | def ntlm_hash(string_value): 21 | """Returns an ntlm hash of the supplied string.""" 22 | return hashlib.new('md4', string_value.encode('utf-16le')).hexdigest() 23 | 24 | def main(): 25 | with open(filename, encoding="utf8", errors='ignore') as fh: 26 | words = fh.read().splitlines() 27 | if algo == 'md5': 28 | hashes = [md5_hash(word) for word in words] 29 | elif algo == 'ntlm': 30 | hashes = [ntlm_hash(word) for word in words] 31 | else: 32 | hashes = '' 33 | with open(outfile, 'w', encoding="utf8", errors='ignore') as fh: 34 | for digest in hashes: 35 | print(digest) 36 | fh.write(digest + '\n') 37 | 38 | if __name__ == '__main__': 39 | parser = argparse.ArgumentParser() 40 | parser.add_argument("-f", "--filename", 41 | help="Specify a file containing words.") 42 | parser.add_argument("-o", "--outfile", 43 | help="Writes the output to a specified file.") 44 | parser.add_argument("-a", "--algorithm", 45 | choices=('md5', 'ntlm'), 46 | help="Selects an algorithm to generate hashes.") 47 | args = parser.parse_args() 48 | if not args.filename: 49 | parser.print_help() 50 | print("\n[-] Please specify an input file containing words (-f).\n") 51 | exit() 52 | else: 53 | filename = args.filename 54 | if not os.path.exists(filename): 55 | print("\n[-] The file {} cannot be found or you do not have permission to open the file. Please check the path and try again\n".format(filename)) 56 | exit() 57 | if not args.algorithm: 58 | parser.print_help() 59 | print("\n[-] Please specify an algorithm (-a ntlm).\n") 60 | exit() 61 | else: 62 | algo = args.algorithm 63 | if args.outfile: 64 | outfile = args.outfile 65 | else: 66 | outfile = 'hashed_values.txt' 67 | main() -------------------------------------------------------------------------------- /idiom_getter.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | __author__ = 'Jake Miller (@LaconicWolf)' 4 | __date__ = '20181227' 5 | __version__ = '0.01' 6 | __description__ = """Retrieves all idioms listed at https://www.theidioms.com 7 | and writes to a file""" 8 | 9 | import re 10 | import requests 11 | 12 | idioms = [] 13 | for num in range(1, 132): 14 | url = "https://www.theidioms.com/list/page/{}".format(num) 15 | contents = requests.get(url).text 16 | idioms += re.findall( 17 | r'
(.*?)
', 18 | contents 19 | ) 20 | 21 | with open('idioms.txt', 'w') as fh: 22 | for idiom in idioms: 23 | if '’' in idiom: 24 | idiom = idiom.replace('’', "'") 25 | print(idiom.lower()) 26 | fh.write(idiom.lower() + '\n') 27 | 28 | print('[*] File written to idioms.txt!') -------------------------------------------------------------------------------- /leet_gen.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | 4 | __author__ = 'Jake Miller (@LaconicWolf). Credit @aswsec for the idea and the leet_dict' 5 | __date__ = '20180924' 6 | __version__ = '0.01' 7 | __description__ = """Generates leet words""" 8 | 9 | 10 | import argparse 11 | import os 12 | 13 | 14 | leet_dict = { 15 | 'a': ['a','A','/-\\', '/\\', '4', '@'], 16 | 'b': ['b','B','|3', '8', '|o'], 17 | 'c': ['c','C','(', '<', 'K', 'S'], 18 | 'd': ['d','D','|)', 'o|', '|>', '<|'], 19 | 'e': ['e','E','3'], 20 | 'f': ['f','F','|=', 'ph'], 21 | 'g': ['g','G','(', '9', '6'], 22 | 'h': ['h','H','|-|', ']-[','}-{', '(-)', ')-(', '#'], 23 | 'i': ['i','I','l', '1', '|', '!', ']['], 24 | 'j': ['j','J','_|'], 25 | 'k': ['k','K','|<', '/<', '\\<', '|{'], 26 | 'l': ['l','L','|_', '|', '1'], 27 | 'm': ['m','M','|\\/|', '/\\/\\', '|\'|\'|', '(\\/)', '/|\\', '/v\\'], 28 | 'n': ['n','N','|\\|', '/\\/', '|\\|', '/|/'], 29 | 'o': ['o','O','0', '()', '[]', '{}'], 30 | 'p': ['p','P','|2', '|D'], 31 | 'q': ['q','Q','(,)', 'kw'], 32 | 'r': ['r','R','|2', '|Z', '|?'], 33 | 's': ['s','S','5', '$'], 34 | 't': ['t','T','+', '\'][\'', '7'], 35 | 'u': ['u','U','|_|'], 36 | 'v': ['v','V','|/', '\\|', '\\/', '/'], 37 | 'w': ['w','W','\\/\\/', '\\|\\|', '|/|/', '\\|/', '\\^/', '//'], 38 | 'x': ['x','X','><', '}{'], 39 | 'y': ['y','Y','`/', '\'/', 'j'], 40 | 'z': ['z','Z','2', '(\\)'] 41 | } 42 | 43 | 44 | def permute(dict_word): 45 | """Looks up each letter of a word to its leet equivalent and 46 | returns a list of words permutated with the leet values. 47 | Adapted from: https://github.com/madglory/permute_wordlist/blob/master/permuteWordlist.py 48 | """ 49 | if len(dict_word) > 0: 50 | current_letter = dict_word[0] 51 | rest_of_word = dict_word[1:] 52 | if current_letter in leet_dict: 53 | substitutions = leet_dict[current_letter] + [current_letter] 54 | else: 55 | substitutions = [current_letter] 56 | if len(rest_of_word) > 0: 57 | perms = [s + p for s in substitutions for p in permute(rest_of_word)] 58 | else: 59 | perms = substitutions 60 | return perms 61 | 62 | 63 | def main(): 64 | """Generates all possible combination or leet letters for 65 | a given word or wordlist. 66 | """ 67 | global words 68 | words = [word.lower() for word in words] 69 | 70 | for word in words: 71 | permuted = permute(word) 72 | unique_list=set(permuted) 73 | if args.outfile: 74 | print("[*] Writing to {}...".format(args.outfile)) 75 | with open(args.outfile, 'w', encoding="utf8", errors='ignore') as fh: 76 | for item in unique_list: 77 | fh.write(item + '\n') 78 | else: 79 | for item in unique_list: 80 | print(item) 81 | 82 | 83 | if __name__ == '__main__': 84 | parser = argparse.ArgumentParser() 85 | parser.add_argument("-f", "--file", 86 | help="Specify a file containing words.") 87 | parser.add_argument("-w", "--word", 88 | help="Specify a single word.") 89 | parser.add_argument("-o", "--outfile", 90 | help="Writes the output to a specified file.") 91 | args = parser.parse_args() 92 | 93 | if not args.word and not args.file: 94 | parser.print_help() 95 | print("\n[-] Please specify a word (-w) or an input file containing words (-f).\n") 96 | exit() 97 | 98 | if args.word and args.file: 99 | parser.print_help() 100 | print("\n[-] Please specify a word (-w) or an input file containing words (-f). Not both\n") 101 | exit() 102 | 103 | if args.file: 104 | file = args.file 105 | if not os.path.exists(file): 106 | print("\n[-] The file cannot be found or you do not have permission to open the file. Please check the path and try again\n") 107 | exit() 108 | with open(file, encoding="utf8", errors='ignore') as fh: 109 | words = fh.read().splitlines() 110 | 111 | if args.word: 112 | words = [args.word] 113 | main() 114 | -------------------------------------------------------------------------------- /leet_rule_generator.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | __author__ = 'Jake Miller (@LaconicWolf). Inspired by work from Adam Willard (@aswsec)' 4 | __date__ = '20190323' 5 | __version__ = '0.01' 6 | __description__ = """Generates leet word rules""" 7 | 8 | import argparse 9 | import itertools 10 | 11 | small_leet_dict = { 12 | 'a': ['4', '@'], 13 | 'b': ['8', '6'], 14 | 'c': ['(', '<', '{', 'k'], 15 | 'e': ['3'], 16 | 'g': ['9', '6'], 17 | 'h': ['#'], 18 | 'i': ['l','1','|','!'], 19 | 'l': ['|','1'], 20 | 'o': ['0'], 21 | 'q': ['9'], 22 | 's': ['5','$'], 23 | 't': ['+','7'], 24 | 'x': ['%'], 25 | 'z': ['2'] 26 | } 27 | 28 | # Uppercase letters omitted due to memory error when 29 | # creating the combined list of dictionaries. 30 | large_leet_dict = { 31 | 'a': ['a', '4', '@'], 32 | 'b': ['b', '8', '6'], 33 | 'c': ['c', '(', '<', '{'], 34 | 'd': ['d'], 35 | 'e': ['e','3'], 36 | 'f': ['f'], 37 | 'g': ['g', '9', '6'], 38 | 'h': ['h','#'], 39 | 'i': ['i','l','1','|','!'], 40 | 'j': ['j'], 41 | 'k': ['k'], 42 | 'l': ['l','|','1'], 43 | 'm': ['m'], 44 | 'n': ['n'], 45 | 'o': ['o','0'], 46 | 'p': ['p'], 47 | 'q': ['q','9'], 48 | 'r': ['r'], 49 | 's': ['s','5','$'], 50 | 't': ['t','+','7'], 51 | 'u': ['u'], 52 | 'v': ['v'], 53 | 'w': ['w'], 54 | 'x': ['x','%'], 55 | 'z': ['2'] 56 | } 57 | 58 | 59 | def main(): 60 | """Permutates a dictionary to write hashcat rules.""" 61 | if args.size == 'large': 62 | leet_mappings = large_leet_dict 63 | else: 64 | leet_mappings = small_leet_dict 65 | print('[*] Generating rules...') 66 | 67 | # https://codereview.stackexchange.com/questions/171173/list-all-possible-permutations-from-a-python-dictionary-of-lists 68 | keys, values = zip(*leet_mappings.items()) 69 | leet_dict_list = [dict(zip(keys, v)) for v in itertools.product(*values)] 70 | 71 | all_lines = [] 72 | for leet_dict in leet_dict_list: 73 | subruleline = [] 74 | for key in leet_dict: 75 | subruleline.append('s{}{}'.format(key,leet_dict.get(key))) 76 | all_lines.append(subruleline) 77 | 78 | print('[*] Writing rules...') 79 | 80 | with open(outfilename, 'w') as fh: 81 | for line in all_lines: 82 | fh.write('{}\n'.format(' '.join(line))) 83 | 84 | if args.title: 85 | fh.write('l {} c\n'.format(' '.join(line))) 86 | 87 | if args.double and not args.title: 88 | fh.write('d {}\n'.format(' '.join(line))) 89 | 90 | if args.double and args.title: 91 | fh.write('d {} c\n'.format(' '.join(line))) 92 | fh.write('c d {}\n'.format(' '.join(line))) 93 | 94 | if appensions: 95 | for item in appensions: 96 | fh.write('{}${}\n'.format(' '.join(line), '$'.join(list(item)))) 97 | 98 | if args.title: 99 | fh.write('l {} ${} c\n'.format(' '.join(line), '$'.join(list(item)))) 100 | 101 | if args.double and not args.title: 102 | fh.write('{} ${} d\n'.format(' '.join(line), '$'.join(list(item)))) 103 | 104 | if args.double and args.title: 105 | fh.write('l d {} ${} c\n'.format(' '.join(line), '$'.join(list(item)))) 106 | fh.write('l c d {} ${}\n'.format(' '.join(line), '$'.join(list(item)))) 107 | 108 | if prepensions: 109 | for item in prepensions: 110 | fh.write('^{}{}\n'.format('^'.join(list(item)[::-1]), ' '.join(line))) 111 | 112 | if args.title: 113 | fh.write('l ^{} {} c\n'.format('^'.join(list(item)[::-1]), ' '.join(line))) 114 | 115 | if args.double and not args.title: 116 | fh.write('^{} {} d\n'.format('^'.join(list(item)[::-1]), ' '.join(line))) 117 | 118 | if args.double and args.title: 119 | fh.write('l d ^{} {} c\n'.format('^'.join(list(item)[::-1]), ' '.join(line))) 120 | fh.write('l c d ^{} {}\n'.format('^'.join(list(item)[::-1]), ' '.join(line))) 121 | 122 | print('[+] Complete! Rules written to {}'.format(outfilename)) 123 | 124 | if __name__ == '__main__': 125 | parser = argparse.ArgumentParser() 126 | parser.add_argument("-o", "--outfile", 127 | help="Output file name") 128 | parser.add_argument("-s", "--size", 129 | nargs='?', 130 | choices=["small", "large"], 131 | const="small", 132 | default="small", 133 | help="'small' uses a dictionary of only leet mappings. 'large' uses the lowercase character, and the leet mappings, which results in a MUCH larger rule file. ") 134 | parser.add_argument("-d", "--double", 135 | action="store_true", 136 | help="Double word and leet") 137 | parser.add_argument("-t", "--title", 138 | action="store_true", 139 | help="title case word") 140 | parser.add_argument("-a", "--append", 141 | nargs="*", 142 | help="Specify characters or words to add to end of the word, separated by spaces. (-a ! !! !!! !@#$") 143 | parser.add_argument("-p", "--prepend", 144 | nargs="*", 145 | help="Specify characters or words to add to the beginning of the word, separated by spaces. (-p ! !! !!! !@#$") 146 | args = parser.parse_args() 147 | 148 | appensions = args.append if args.append else None 149 | prepensions = args.prepend if args.prepend else None 150 | outfilename = args.outfile if args.outfile else "5UP3R_1337.rule" 151 | 152 | main() 153 | -------------------------------------------------------------------------------- /mask_finder.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | 4 | __author__ = 'Jake Miller (@LaconicWolf)' 5 | __date__ = '20180914' 6 | __version__ = '0.02' 7 | __description__ = """Reads in a plain-text password lists to find the frequency 8 | of password character masks. Will display all character masks found""" 9 | 10 | 11 | import argparse 12 | import string 13 | import os 14 | from collections import Counter 15 | 16 | 17 | def generate_char_mask(word): 18 | """Analyzes the characters of a word and generates a mask per character. 19 | Returns the mask of a word as a string.""" 20 | mask = '' 21 | for char in word: 22 | try: 23 | if char in string.uppercase: 24 | mask += '?u' 25 | elif char in string.lowercase: 26 | mask += '?l' 27 | elif char in string.digits: 28 | mask += '?d' 29 | elif char in string.punctuation or char == ' ': 30 | mask += '?s' 31 | else: 32 | if args.verbose: 33 | print('Encountered an non-standard character: {}. It will appear in a mask as ?X '.format(char)) 34 | mask += '?X' 35 | except AttributeError: 36 | if char in string.ascii_uppercase: 37 | mask += '?u' 38 | elif char in string.ascii_lowercase: 39 | mask += '?l' 40 | elif char in string.digits: 41 | mask += '?d' 42 | elif char in string.punctuation or char == ' ': 43 | mask += '?s' 44 | else: 45 | if args.verbose: 46 | print('Encountered an non-standard character: {}. It will appear in a mask as ?X '.format(char)) 47 | mask += '?X' 48 | return mask 49 | 50 | 51 | def sort_char_masks(mask_list): 52 | """Returns a listed tuple of a character masks, where the mask is the first ([0]) element 53 | and the number of times the mask occurs is the second element ([1]). For example: 54 | [('?l?l?l?l?l', 4)] 55 | """ 56 | mask_dict = dict(Counter(mask_list)) 57 | sorted_counted_mask = [(k, mask_dict[k]) for k in sorted(mask_dict, key=mask_dict.get, reverse=True)] 58 | return sorted_counted_mask 59 | 60 | 61 | def arrange_words_by_length(list_of_words): 62 | """Takes a list of words and returns a list of multiple lists 63 | arranged by the word length. 64 | """ 65 | list_of_words.sort(key=len) 66 | return list_of_words 67 | 68 | 69 | def sort_dict_by_key_len(dict_obj): 70 | """Takes a dictionary and returns a list of tuples sorted by the length of 71 | the dictionary's keys. 72 | """ 73 | return [(k, dict_obj[k]) for k in sorted(dict_obj, key=len)] 74 | 75 | 76 | def sort_tuple_list_by_two_elements(tuple_list): 77 | """sorts a list of tuples that contain two values, first by the first value, 78 | then by the second value. The -x[1] sorts in reverse. 79 | #https://stackoverflow.com/questions/14466068/sort-a-list-of-tuples-by-second-value-reverse-true-and-then-by-key-reverse-fal 80 | """ 81 | return sorted(tuple_list, key=lambda x: (len(x[0]), -x[1])) 82 | 83 | 84 | def main(): 85 | """Reads in a plain-text password lists to find the frequency 86 | of password character masks. Will display all character masks found. 87 | """ 88 | # Initialize variable to hold a list of all sorted mask dictionaries for a file 89 | file_mask_list = [] 90 | for filename in args.filename: 91 | print("[*] Processing {}".format(filename)) 92 | # Read the file into memory. 93 | words = open(filename, encoding="utf8", errors='ignore').read().splitlines() 94 | 95 | # Initialize a list per file to store lists of words sorted by length. 96 | file_word_list = [] 97 | sorted_word_list = [] 98 | 99 | # Generate the masks for each word and sort them by count. 100 | masks = [generate_char_mask(word) for word in words] 101 | sorted_masks = sort_char_masks(masks) 102 | 103 | # Add masks to he list for all files 104 | file_mask_list.append(sorted_masks) 105 | 106 | # Converts tuples to a dictionary to combine values of the same mask 107 | # across the different input files 108 | file_mask_list = [dict(l) for l in file_mask_list] 109 | 110 | # Gets all the unique masks from the input files 111 | mask_keys = [] 112 | for mask_dictionary in file_mask_list: 113 | dict_keys = list(mask_dictionary.keys()) 114 | for k in dict_keys: 115 | mask_keys.append(k) 116 | mask_keys = list(set(mask_keys)) 117 | 118 | # Adds the number of occurences of mask from each input file 119 | # by combining dictionary values of the same key 120 | results = {} 121 | for k in mask_keys: 122 | sums = [] 123 | for item in file_mask_list: 124 | if item.get(k): 125 | sums.append(item.get(k)) 126 | results[k] = sum(sums) 127 | 128 | # Sorts the result by mask length, converting it to a list of tuples 129 | sorted_results = sort_dict_by_key_len(results) 130 | 131 | # Sorts the tuples first by length, then by value 132 | sorted_results = sort_tuple_list_by_two_elements(sorted_results) 133 | 134 | # Output to terminal and file. 135 | if args.outfile: 136 | 137 | # Opens the outfile. 138 | with open(args.outfile, 'a') as outfile: 139 | 140 | # Records the files processed. 141 | outfile.write('Processed files:\n') 142 | for f in args.filename: 143 | outfile.write(f + '\n') 144 | 145 | # Stores the starting word length to control printing word length. 146 | # Length is divided by 2 because the masks are measured, so they 147 | # include ? before each character. 148 | word_length = int(len(sorted_results[0][0]) / 2) 149 | 150 | print("\n[+] Mask for {} letter words".format(word_length)) 151 | outfile.write("\n[+] Mask for {} letter words\n".format(word_length)) 152 | 153 | # Iterates through the results, checking the mask length to control 154 | # the printed output 155 | for k, v in sorted_results: 156 | new_word_length = int(len(k) / 2) 157 | if new_word_length != word_length: 158 | print("\n[+] Mask for {} letter words".format(new_word_length)) 159 | outfile.write("\n[+] Mask for {} letter words\n".format(new_word_length)) 160 | word_length = new_word_length 161 | if args.charset: 162 | if all(char in k for char in args.charset.lower()): 163 | print("{} : {}".format(k, v)) 164 | outfile.write("{} : {}\n".format(k, v)) 165 | else: 166 | print("{} : {}".format(k, v)) 167 | outfile.write("{} : {}\n".format(k, v)) 168 | else: 169 | word_length = int(len(sorted_results[0][0]) / 2) 170 | print("\n[+] Mask for {} letter words".format(word_length)) 171 | for k, v in sorted_results: 172 | new_word_length = int(len(k) / 2) 173 | if new_word_length != word_length: 174 | print("\n[+] Mask for {} letter words".format(new_word_length)) 175 | word_length = new_word_length 176 | if args.charset: 177 | if all(char in k for char in args.charset.lower()): 178 | print("{} : {}".format(k, v)) 179 | else: 180 | print("{} : {}".format(k, v)) 181 | 182 | 183 | if __name__ == '__main__': 184 | parser = argparse.ArgumentParser() 185 | parser.add_argument("-v", "--verbose", 186 | action='store_true', 187 | help="Increase output verbosity.") 188 | parser.add_argument("-f", "--filename", 189 | nargs='*', 190 | help="Specify a file containing plain text passwords.") 191 | parser.add_argument("-o", "--outfile", 192 | help="Writes the output to a file, masks.txt, in the current directory.") 193 | parser.add_argument("-c", "--charset", 194 | help="Specify the charset that must be present in mask for. Example -c ?d?u?l") 195 | args = parser.parse_args() 196 | 197 | if not args.filename: 198 | parser.print_help() 199 | print("\n[-] Please specify one or more password files to analyze. For multiple input files, separate with a space.\n") 200 | exit() 201 | for filename in args.filename: 202 | if not os.path.exists(filename): 203 | parser.print_help() 204 | print("\n[-] The file {}, does not exist or you lack permissions to open it. Please try again.\n".format(filename)) 205 | exit() 206 | 207 | main() -------------------------------------------------------------------------------- /md5_hashgen.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | 4 | __author__ = 'Jake Miller (@LaconicWolf)' 5 | __date__ = '20180921' 6 | __version__ = '0.01' 7 | __description__ = """Reads a plain text file and hashes each line. The hashes are written 8 | to a new file. The purpose of this tool is to generate sample hashes for testing password 9 | cracking.""" 10 | 11 | 12 | import hashlib 13 | import sys 14 | 15 | def md5(string): 16 | """Returns a md5 hash of the supplied parameter""" 17 | return hashlib.md5(string.encode()).hexdigest() 18 | 19 | def main(): 20 | hashes = [md5(word) for word in words] 21 | with open(outfile, 'w', encoding="utf8", errors='ignore') as fh: 22 | for hash in hashes: 23 | print(hash) 24 | fh.write(hash + '\n') 25 | 26 | if __name__ == '__main__': 27 | if len(sys.argv) != 3: 28 | print("\n[*] Usage: python3 {} \n".format(sys.argv[0])) 29 | exit() 30 | filename = sys.argv[1] 31 | outfile = sys.argv[2] 32 | with open(filename, encoding="utf8", errors='ignore') as fh: 33 | words = fh.read().splitlines() 34 | main() -------------------------------------------------------------------------------- /phrase_cleaner.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | __author__ = 'Jake Miller (@LaconicWolf)' 4 | __date__ = '20190102' 5 | __version__ = '0.01' 6 | __description__ = """Combines files containing phrases. Converts lines to lowercase and removes punctuation except spaces.""" 7 | 8 | import argparse 9 | import os 10 | import string 11 | 12 | def main(): 13 | all_lines = [] 14 | for filename in files: 15 | print('[*] Reading file: {}...'.format(filename)) 16 | with open(filename, encoding="utf8", errors='ignore') as fh: 17 | lines = fh.read().splitlines() 18 | print('[*] Processing {} lines...'.format(len(lines))) 19 | for line in lines: 20 | line = line.lower() 21 | 22 | # Remove punctuation except spaces 23 | # https://stackoverflow.com/questions/34293875/how-to-remove-punctuation-marks-from-a-string-in-python-3-x-using-translate 24 | translator = str.maketrans('', '', string.punctuation) 25 | line = line.translate(translator) 26 | 27 | all_lines.append(line) 28 | 29 | if args.outfile: 30 | print('[*] Writing to {}...'.format(args.outfile)) 31 | with open(args.outfile, 'w', encoding="utf8", errors='ignore') as fh: 32 | for line in all_lines: 33 | fh.write(line + '\n') 34 | else: 35 | for line in all_lines: 36 | print(line) 37 | 38 | if __name__ == '__main__': 39 | parser = argparse.ArgumentParser() 40 | parser.add_argument("-f", "--filename", 41 | nargs='*', 42 | help="Specify a file containing phrases.") 43 | parser.add_argument("-o", "--outfile", 44 | help="Writes the output to a specified file.") 45 | args = parser.parse_args() 46 | if not args.filename: 47 | parser.print_help() 48 | print("\n[-] Please specify an input file containing words (-f).\n") 49 | exit() 50 | else: 51 | files = args.filename 52 | for filename in files: 53 | if not os.path.exists(filename): 54 | print("\n[-] The file {} cannot be found or you do not have permission to open the file. Please check the path and try again\n".format(filename)) 55 | exit() 56 | main() -------------------------------------------------------------------------------- /phrase_combiner.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | __author__ = 'Jake Miller (@LaconicWolf)' 4 | __date__ = '20190102' 5 | __version__ = '0.01' 6 | __description__ = """Combines files containing phrases. Can capitalize, manipulate the phrases, etc.""" 7 | 8 | import argparse 9 | import os 10 | 11 | def main(): 12 | all_lines = [] 13 | for filename in files: 14 | print('[*] Reading file: {}...'.format(filename)) 15 | with open(filename, encoding="utf8", errors='ignore') as fh: 16 | lines = fh.read().splitlines() 17 | print('[*] Processing {} lines...'.format(len(lines))) 18 | for line in lines: 19 | line = line.strip('.') 20 | line = line.strip(',') 21 | line = line.strip('\'') 22 | words = line.split(' ') 23 | base_words = [word.lower() for word in words] 24 | 25 | all_lines.append(''.join(base_words)) 26 | all_lines.append(' '.join(base_words)) 27 | all_lines.append('-'.join(base_words)) 28 | all_lines.append('_'.join(base_words)) 29 | 30 | words = [word.title() for word in base_words] 31 | all_lines.append(''.join(words)) 32 | all_lines.append(' '.join(words)) 33 | all_lines.append('-'.join(words)) 34 | all_lines.append('_'.join(words)) 35 | 36 | words = [word for word in base_words] 37 | all_lines.append(''.join(words).title()) 38 | all_lines.append(' '.join(words).title()) 39 | all_lines.append('-'.join(words).title()) 40 | all_lines.append('_'.join(words).title()) 41 | 42 | if args.outfile: 43 | print('[*] Writing to {}...'.format(args.outfile)) 44 | with open(args.outfile, 'w', encoding="utf8", errors='ignore') as fh: 45 | for line in all_lines: 46 | fh.write(line + '\n') 47 | else: 48 | for line in all_lines: 49 | print(line) 50 | 51 | if __name__ == '__main__': 52 | parser = argparse.ArgumentParser() 53 | parser.add_argument("-f", "--filename", 54 | nargs='*', 55 | help="Specify a file containing phrases.") 56 | parser.add_argument("-o", "--outfile", 57 | help="Writes the output to a specified file.") 58 | args = parser.parse_args() 59 | if not args.filename: 60 | parser.print_help() 61 | print("\n[-] Please specify an input file containing words (-f).\n") 62 | exit() 63 | else: 64 | files = args.filename 65 | for filename in files: 66 | if not os.path.exists(filename): 67 | print("\n[-] The file {} cannot be found or you do not have permission to open the file. Please check the path and try again\n".format(filename)) 68 | exit() 69 | main() -------------------------------------------------------------------------------- /positional_character_frequency.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | 4 | __author__ = 'Jake Miller (@LaconicWolf)' 5 | __date__ = '20180914' 6 | __version__ = '0.02' 7 | __description__ = """Analyzes a password list to find frequency of characters per position.""" 8 | 9 | 10 | import argparse 11 | import os 12 | import string 13 | import itertools 14 | 15 | 16 | def get_freq(word): 17 | """docstring 18 | #https://stackoverflow.com/questions/43693018/python-position-frequency-dictionary-of-letters-in-words 19 | """ 20 | l = len(word) - word.count(None) 21 | return {n: word.count(n)/l for n in charset} 22 | 23 | 24 | def arrange_words_by_length(list_of_words): 25 | """Takes a list of words and returns a list arranged by the word length.""" 26 | list_of_words.sort(key=len) 27 | return list_of_words 28 | 29 | 30 | def sort_frequency_list(frequency_dict): 31 | """Returns a listed tuple of a frequencies, sorted by the key that occurs 32 | most. 33 | """ 34 | sorted_frequencies = [(k, frequency_dict[k]) for k in sorted(frequency_dict, key=frequency_dict.get, reverse=True)] 35 | return sorted_frequencies 36 | 37 | def group_words_by_length(word_list): 38 | d={} 39 | for word in word_list: 40 | d.setdefault(len(word), []).append(word) 41 | return [d[n] for n in sorted(d)] 42 | 43 | 44 | def main(): 45 | for filename in args.filename: 46 | wordlist = open(filename, encoding="utf8", errors='ignore').read().splitlines() 47 | grouped_words = group_words_by_length(wordlist) 48 | for words in grouped_words: 49 | print("\n[*] {} letter words - Total words: {}\n".format(len(words[0]), len(words))) 50 | frequency_list = [get_freq(word) for word in itertools.zip_longest(*words)] 51 | pos_counter = 1 52 | for item in frequency_list: 53 | sorted_freq = sort_frequency_list(item) 54 | print('[*] Character position {}'.format(pos_counter)) 55 | for k, v in sorted_freq: 56 | if v: 57 | print(k,v) 58 | pos_counter += 1 59 | 60 | 61 | if __name__ == '__main__': 62 | parser = argparse.ArgumentParser() 63 | parser.add_argument("-v", "--verbose", 64 | action='store_true', 65 | help="Increase output verbosity.") 66 | parser.add_argument("-f", "--filename", 67 | nargs='*', 68 | help="Specify a file containing plain text passwords.") 69 | parser.add_argument("-o", "--outfile", 70 | help="Writes the output to a specified file in the current directory.") 71 | args = parser.parse_args() 72 | 73 | if not args.filename: 74 | parser.print_help() 75 | print("\n[-] Please specify one or more password files to analyze. For multiple input files, separate with a space.\n") 76 | exit() 77 | for filename in args.filename: 78 | if not os.path.exists(filename): 79 | parser.print_help() 80 | print("\n[-] The file {}, does not exist or you lack permissions to open it. Please try again.\n".format(filename)) 81 | exit() 82 | charset = string.ascii_letters + string.digits + string.punctuation + ' ' 83 | main() -------------------------------------------------------------------------------- /pot.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | __author__ = 'Jake Miller (@LaconicWolf)...Written for Adam' 4 | __date__ = '20180921' 5 | __version__ = '0.01' 6 | __description__ = """Extracts the plain passwords from a hashcat or jtr pot file. Cleans them if specified.""" 7 | 8 | import argparse 9 | import re 10 | 11 | def clean_words(words): 12 | """Passes a wordlist through a series of functions to generate 13 | a rule file. 14 | """ 15 | print("[*] Processing {} words.".format(len(words))) 16 | print("[*] Changing all words to lowercase...") 17 | words = [word.lower() for word in words] 18 | print("[*] Removing numbers and special characters...") 19 | words = [re.sub(r'[^a-z]+', '', word) for word in words] 20 | print("[*] Removing duplicate words...") 21 | words = list(set(words)) 22 | return words 23 | 24 | def decode_hashcat_hexstring(hexstring): 25 | """Parses a hex encoded password string ($HEX[476f6f646669676874343a37]) 26 | and returns the decodes the hex. 27 | """ 28 | index_1 = hexstring.index("[")+1 29 | index_2 = len(hexstring)-1 30 | hexdata = hexstring[index_1:index_2] 31 | return bytes.fromhex(hexdata).decode() 32 | 33 | def decode_hashcat_hex(data): 34 | """Calls the decoded_hashcat_hexstring on an encoded hex represented password 35 | ($HEX[476f6f646669676874343a37]). Occasionally the string will be encoded 36 | multiple times, so a loop is used until the $HEX prefix no longer remains. 37 | Returns the decodes the hexstring. 38 | """ 39 | while data.startswith('$HEX['): 40 | data = decode_hashcat_hexstring(data) 41 | return data 42 | 43 | def main(): 44 | 45 | # Reads in the potfile 46 | with open(potfile) as fh: 47 | lines = fh.read().splitlines() 48 | try: 49 | # Both JTR and Hashcat potfiles are colon delimited. In JTR pot files, 50 | # a colon in the password will mess up the split, so it must be split 51 | # from the first colon until the end of line. 52 | pt_passwords = [line.split(':')[1:] for line in lines] 53 | fixed_passwords = [] 54 | for line in pt_passwords: 55 | if len(line) > 1: 56 | fixed_passwords.append(':'.join(line)) 57 | else: 58 | fixed_passwords.append(''.join(line)) 59 | except IndexError as e: 60 | print('Error detected:') 61 | print(e) 62 | passwords = [] 63 | for password in fixed_passwords: 64 | 65 | # Hashcat will encode passwords containing colons or non-ascii characters. 66 | # This will decode those passwords if they are there. 67 | if password.startswith('$HEX['): 68 | passwords.append(decode_hashcat_hex(password)) 69 | else: 70 | passwords.append(password) 71 | 72 | if args.clean: 73 | passwords = clean_words(passwords) 74 | 75 | # Output to file or print to terminal 76 | if args.outfile: 77 | with open(args.outfile, 'w') as fh: 78 | for password in passwords: 79 | fh.write(password + '\n') 80 | else: 81 | for password in passwords: 82 | print(password) 83 | 84 | if __name__ == '__main__': 85 | parser = argparse.ArgumentParser() 86 | parser.add_argument('-f', '--filename') 87 | parser.add_argument('-o', '--outfile') 88 | parser.add_argument('-c', '--clean', 89 | action="store_true") 90 | args = parser.parse_args() 91 | if not args.filename: 92 | parser.print_help() 93 | print("\n[-] Please specify the filename of the potfile\n") 94 | exit() 95 | else: 96 | potfile = args.filename 97 | main() -------------------------------------------------------------------------------- /quote_parser_001.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | __author__ = 'Jake Miller (@LaconicWolf)' 4 | __date__ = '20190102' 5 | __version__ = '0.01' 6 | __description__ = """Retrieves data listed at https://gist.githubusercontent.com/signed0/d70780518341e1396e11/raw/2a7f4af8d181a714f9d49105ed57fafb3f450960/quotes.json, 7 | parses, and writes to a file.""" 8 | 9 | import requests 10 | import ast 11 | 12 | url = "https://gist.githubusercontent.com/signed0/d70780518341e1396e11/raw/2a7f4af8d181a714f9d49105ed57fafb3f450960/quotes.json" 13 | contents = requests.get(url).text.split('\n') 14 | 15 | lines = [] 16 | for line in contents: 17 | try: 18 | line = ast.literal_eval(line) 19 | except SyntaxError: 20 | input(line) 21 | continue 22 | lines.append(line[0]) 23 | 24 | with open('short_quotes.txt', 'a') as fh: 25 | s_lines = [l for l in lines if len(l) < 33] 26 | for line in s_lines: 27 | print(line.lower()) 28 | fh.write(line.lower() + '\n') 29 | 30 | print('[*] File written to short_quotes.txt!') 31 | 32 | with open('medium_quotes.txt', 'a') as fh: 33 | m_lines = [l for l in lines if len(l) > 32 and len(l) < 128] 34 | for line in m_lines: 35 | print(line.lower()) 36 | fh.write(line.lower() + '\n') 37 | 38 | print('[*] File written to medium_quotes.txt!') 39 | 40 | with open('long_quotes.txt', 'a') as fh: 41 | l_lines = [l for l in lines if len(l) < 127] 42 | for line in l_lines: 43 | print(line.lower()) 44 | fh.write(line.lower() + '\n') 45 | 46 | print('[*] File written to long_quotes.txt!') -------------------------------------------------------------------------------- /quote_parser_002.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | __author__ = 'Jake Miller (@LaconicWolf)' 4 | __date__ = '20190102' 5 | __version__ = '0.01' 6 | __description__ = """Retrieves words listed at https://raw.githubusercontent.com/alvations/Quotables/master/author-quote.txt, 7 | parses, and writes to three files.""" 8 | 9 | import requests 10 | 11 | url = "https://raw.githubusercontent.com/alvations/Quotables/master/author-quote.txt" 12 | contents = requests.get(url).text.split('\n') 13 | 14 | lines = [] 15 | for line in contents: 16 | try: 17 | lines.append(line.split('\t')[1]) 18 | except IndexError: 19 | continue 20 | 21 | 22 | with open('short_quotes.txt', 'a') as fh: 23 | s_lines = [l for l in lines if len(l) < 33] 24 | for line in s_lines: 25 | print(line.lower()) 26 | fh.write(line.lower() + '\n') 27 | 28 | print('[*] File written to short_quotes.txt!') 29 | 30 | with open('medium_quotes.txt', 'a') as fh: 31 | m_lines = [l for l in lines if len(l) > 32 and len(l) < 128] 32 | for line in m_lines: 33 | print(line.lower()) 34 | fh.write(line.lower() + '\n') 35 | 36 | print('[*] File written to medium_quotes.txt!') 37 | 38 | with open('long_quotes.txt', 'a') as fh: 39 | l_lines = [l for l in lines if len(l) < 127] 40 | for line in l_lines: 41 | print(line.lower()) 42 | fh.write(line.lower() + '\n') 43 | 44 | print('[*] File written to long_quotes.txt!') 45 | -------------------------------------------------------------------------------- /quote_parser_003.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | __author__ = 'Jake Miller (@LaconicWolf)' 4 | __date__ = '20190102' 5 | __version__ = '0.01' 6 | __description__ = """Retrieves words listed at https://www.phrases.org.uk/meanings/phrases-and-sayings-list.html, 7 | parses, and writes to a file.""" 8 | 9 | import requests 10 | import re 11 | 12 | url = "https://www.phrases.org.uk/meanings/phrases-and-sayings-list.html" 13 | contents = requests.get(url).text 14 | 15 | lines = re.findall(r'

(.*?)

', contents) 16 | 17 | with open('phrases_and_sayings.txt', 'w') as fh: 18 | for line in lines: 19 | print(line.lower()) 20 | fh.write(line.lower() + '\n') 21 | 22 | print('[*] File written to phrases_and_sayings.txt!') -------------------------------------------------------------------------------- /remove_duplicates.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | 4 | __author__ = 'Jake Miller (@LaconicWolf)' 5 | __date__ = '20180921' 6 | __version__ = '0.01' 7 | __description__ = """Reads a file, removes duplicate lines, and writes to a new file.""" 8 | 9 | 10 | import argparse 11 | 12 | 13 | def main(): 14 | print('[*] Reading file: {}'.format(filename)) 15 | with open(filename, encoding="utf8", errors='ignore') as fh: 16 | lines = fh.read().splitlines() 17 | print("[*] Processing {} words.".format(len(lines))) 18 | print('[*] Removing duplicate words...') 19 | unique_lines = list(set(lines)) 20 | if args.outfile: 21 | print('[*] Writing to file: {}'.format(args.outfile)) 22 | with open(args.outfile, 'w', encoding="utf8", errors='ignore') as fh: 23 | for line in unique_lines: 24 | fh.write(line + '\n') 25 | else: 26 | for line in unique_lines: 27 | print(line) 28 | 29 | if __name__ == '__main__': 30 | parser = argparse.ArgumentParser() 31 | parser.add_argument('-f', '--filename') 32 | parser.add_argument('-o', '--outfile') 33 | args = parser.parse_args() 34 | if not args.filename: 35 | parser.print_help() 36 | print("\n[-] Please specify the filename of the wordlist.\n") 37 | exit() 38 | else: 39 | filename = args.filename 40 | main() -------------------------------------------------------------------------------- /seclist_password_combiner.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | 4 | __author__ = 'Jake Miller (@LaconicWolf)' 5 | __date__ = '20180921' 6 | __version__ = '0.01' 7 | __description__ = """Combines, sorts, and uniques the passwords contained in files located at 8 | https://github.com/danielmiessler/SecLists.""" 9 | 10 | 11 | import argparse 12 | import os 13 | 14 | 15 | def main(): 16 | combined = [] 17 | for root, dirnames, filenames in os.walk(root_dir): 18 | for filename in filenames: 19 | filepath = os.path.join(root, filename) 20 | if filepath.endswith('.txt') or filepath.endswith('.csv'): 21 | print("[*] Processing file: {}".format(filepath)) 22 | with open(filepath, encoding="utf8", errors='ignore') as fh: 23 | contents = fh.read().splitlines() 24 | 25 | # This dir includes files containing username and password combos 26 | # delimited usually by a colon, but some are csv files. 27 | if os.sep + "Default-Credentials" in filepath: 28 | if filepath.endswith('csv'): 29 | 30 | # Annoying to parse so I'm not doing it. 31 | if 'scada-pass.csv' in filepath: 32 | pass 33 | # This one is easier to parse. 34 | if 'default-passwords.csv' in filepath: 35 | passwords = [line.split(',')[2] for line in contents if line.split(',')[2] != ""] 36 | else: 37 | try: 38 | passwords = [line.split(':')[1] for line in contents] 39 | except IndexError: 40 | passwords = contents 41 | combined += passwords 42 | else: 43 | combined += contents 44 | print("[*] Sorting list and removing duplicates words...") 45 | combined.sort() 46 | unique_combined = list(set(combined)) 47 | 48 | if args.outfile: 49 | print("[*] Writing to {}...".format(args.outfile)) 50 | with open(args.outfile, 'w', encoding="utf8", errors='ignore') as fh: 51 | for word in unique_combined: 52 | fh.write(word + '\n') 53 | else: 54 | for word in unique_combined: 55 | print(word) 56 | 57 | if __name__ == '__main__': 58 | parser = argparse.ArgumentParser() 59 | parser.add_argument("-d", "--directory", 60 | nargs='?', 61 | const='.', 62 | help="Specify the directory. You'll want to run this in the Passwords folder.") 63 | parser.add_argument("-o", "--outfile", 64 | help="Writes the output to a specified file.") 65 | args = parser.parse_args() 66 | 67 | if args.directory: 68 | root_dir = args.directory 69 | else: 70 | root_dir = '.' 71 | main() -------------------------------------------------------------------------------- /wordlist_cleaner.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | 4 | __author__ = 'Jake Miller (@LaconicWolf)' 5 | __date__ = '20180924' 6 | __version__ = '0.01' 7 | __description__ = """Removes case, digits, and special characters for a wordlist 8 | and uniques it.""" 9 | 10 | import argparse 11 | import re 12 | import os 13 | 14 | 15 | def main(): 16 | """Passes a wordlist through a series of functions to generate 17 | a rule file. 18 | """ 19 | global words 20 | print("[*] Processing {} words.".format(len(words))) 21 | print("[*] Changing all words to lowercase...") 22 | words = [word.lower() for word in words] 23 | print("[*] Removing numbers and special characters...") 24 | words = [re.sub(r'[^a-z]+', '', word) for word in words] 25 | print("[*] Removing duplicate words...") 26 | words = list(set(words)) 27 | print("[*] Printing cleaned words to {}".format(outfile)) 28 | with open(outfile, 'w') as fh: 29 | for word in words: 30 | fh.write(word + '\n') 31 | 32 | 33 | if __name__ == '__main__': 34 | parser = argparse.ArgumentParser() 35 | parser.add_argument("-f", "--file", 36 | help="Specify a file containing words.") 37 | parser.add_argument("-o", '--outfile', 38 | help="Writes the words to a specified outfile name") 39 | args = parser.parse_args() 40 | 41 | if not args.file and not args.outfile: 42 | parser.print_help() 43 | print("\n[-] Please specify an input file containing words (-f) and the name of an output file to write to (-o out.txt).\n") 44 | exit() 45 | else: 46 | file = args.file 47 | outfile = args.outfile 48 | if not os.path.exists(file): 49 | print("\n[-] The file cannot be found or you do not have permission to open the file. Please check the path and try again\n") 50 | exit() 51 | print('[*] Reading file: {}'.format(file)) 52 | with open(file, encoding="utf8", errors='ignore') as fh: 53 | words = fh.read().splitlines() 54 | 55 | main() -------------------------------------------------------------------------------- /wordlist_searcher.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | 4 | __author__ = 'Jake Miller (@LaconicWolf)' 5 | __date__ = '20180921' 6 | __version__ = '0.01' 7 | __description__ = """Searches for specified words in a dictionary.""" 8 | 9 | 10 | import argparse 11 | import os 12 | 13 | 14 | def main(): 15 | global words 16 | dict_words = {} 17 | print('[*] Reading dictionary file: {}'.format(filename)) 18 | dict_file = open(filename, encoding="utf8", errors='ignore') 19 | for line in dict_file.read().split('\n'): 20 | dict_words[line] = True 21 | dict_file.close() 22 | print('[*] Searching...') 23 | words = [word for word in words] 24 | unique_words = [] 25 | for word in words: 26 | if not dict_words.get(word): 27 | unique_words.append(word) 28 | if unique_words: 29 | if args.outfile: 30 | print("[*] Writing words that do not appear in {} to {}...".format(filename, args.outfile)) 31 | with open(args.outfile, 'w', encoding="utf8", errors='ignore') as fh: 32 | for word in unique_words: 33 | fh.write(word + '\n') 34 | else: 35 | for word in unique_words: 36 | print("[*] {} does not appear in {}".format(word, filename)) 37 | else: 38 | print("[*] All words from {} appeared in {}".format(args.wordlist, filename)) 39 | 40 | 41 | if __name__ == '__main__': 42 | parser = argparse.ArgumentParser() 43 | parser.add_argument('-d', '--dictionary', 44 | help="Specify the dictionary you would like to search in.") 45 | parser.add_argument('-w', '--word', 46 | nargs="*", 47 | help="Specify the word or words you'd like to search for.") 48 | parser.add_argument('-wl', '--wordlist', 49 | help="Specify the filename containing the list of words you'd like to search for.") 50 | parser.add_argument("-o", "--outfile", 51 | help="Writes the output to a specified file.") 52 | args = parser.parse_args() 53 | if not args.dictionary: 54 | parser.print_help() 55 | print("\n[-] Please specify the filename of the dictionary you would like to search in.\n") 56 | exit() 57 | else: 58 | filename = args.dictionary 59 | if not args.word and not args.wordlist: 60 | parser.print_help() 61 | print("\n[-] Please specify a word you would like to search for (-w) or specify a filename containing a list of words you'd like to search for (-wl).\n") 62 | exit() 63 | if args.word and args.wordlist: 64 | parser.print_help() 65 | print("\n[-] Please specify a word (-w) or specify a filename containing a list of words (-wl). Not both.\n") 66 | exit() 67 | if args.word: 68 | words = args.word 69 | if args.wordlist: 70 | if not os.path.exists(args.wordlist): 71 | print("\n[-] The file cannot be found or you do not have permission to open the file. Please check the path and try again\n") 72 | exit() 73 | with open(args.wordlist, encoding="utf8", errors='ignore') as fh: 74 | words = fh.read().splitlines() 75 | main() 76 | --------------------------------------------------------------------------------