def verify_hash_type(hash_to_verify, least_likely=False, verbose=False): """ Attempt to verify a given hash by type (md5, sha1, etc..) > :param hash_to_verify: hash string > :param least_likely: show least likely options as well > :return: likely options, least likely options, or none Example: >>> verify_hash_type("098f6bcd4621d373cade4e832627b4f6", least_likely=True) [('md5', 'md4', 'md2'), ('double md5', 'lm', ... )] """ for regex, hash_types in HASH_TYPE_REGEX.items( ): # iter is not available in Python 3.x if verbose: LOGGER.debug("Testing: {}".format(hash_types)) if regex.match(hash_to_verify): return hash_types if least_likely else hash_types[0] error_msg = ( "Unable to find any algorithms to match the given hash. If you " "feel this algorithm should be implemented make an issue here: {}") LOGGER.fatal(error_msg.format(DAGON_ISSUE_LINK)) # hash_guarantee(hash_to_verify) LOGGER.warning("`hash_guarantee` has been turned off for the time being") shutdown(1)
def create_wordlist(warning=True, verbose=False, add=False): """ Create a bruteforcing wordlist > :param max_length: max amount of words to have > :param max_word_length: how long the words should be > :param warning: output the warning message to say that BF'ing sucks > :return: a wordlist """ max_length, max_word_length, dirname = 10000000, 10, "bf-dicts" if add: max_word_length += 2 warn_msg = ( "It is highly advised to use a dictionary attack over bruteforce. " "Bruteforce requires extreme amounts of memory to accomplish and " "it is possible that it could take a lifetime to successfully " "crack your hash. To run a dictionary attack all you need to do is" " pass the wordlist switch ('-w/--wordlist PATH') with the path to " "your wordlist. (IE: --bruteforce -w ~/dicts/dict.txt)") if warning: LOGGER.warning(warn_msg) if verbose: LOGGER.debug( "Creating {} words with a max length of {} characters".format( max_length, max_word_length)) create_dir(dirname, verbose=verbose) with open(dirname + "/" + WORDLIST_NAME, "a+") as lib: word = Generators().word_generator(length_max=max_word_length) lib.seek(0, 0) line_count = len(lib.readlines()) try: for _ in range(line_count, max_length): lib.write(next(word) + "\n") except StopIteration: # SHOULD NEVER GET HERE # if we run out of mutations we'll retry with a different word length lib.seek(0, 0) err_msg = ( "Ran out of mutations at {} mutations. You can try upping " "the max length or just use what was processed. If you " "make the choice not to continue the program will add +2 " "to the max length and try to create the wordlist again.." ).format(len(lib.readlines())) LOGGER.error(err_msg) q = prompt("Would you like to continue", "y/N") if not q.startswith(("y", "Y")): lib.truncate(0) create_wordlist(warning=False, add=True) LOGGER.info( "Wordlist generated, words saved to: {}. Please re-run the application, exiting.." .format(WORDLIST_NAME)) shutdown()
def hash_words(verify_hash, wordlist, algorithm, salt=None, placement=None, posx="", use_hex=False, verbose=False, rounds=10): """ Hash the words and verify if they match or not > :param verify_hash: the has to be verified > :param wordlist: the wordlist to be used > :param algorithm: the algorithm to be used > :param salt: the salt string > :param placement: where to place the salt if given > :return: the word that matched the hash when hashed, the hash, the amount of tries, and algorithm """ tries = 0 with codecs.open(wordlist, encoding="utf-8", mode="r") as words: for i, word in enumerate(words.readlines(), start=1): if type(word.strip()) is unicode: word = word.strip().encode("utf-8") if salt is not None: if placement == "front": hashed = FUNC_DICT[algorithm.lower()](word.strip(), salt=salt, front=True, posx=posx, use_hex=use_hex, rounds=rounds) else: hashed = FUNC_DICT[algorithm.lower()](word.strip(), salt=salt, back=True, posx=posx, use_hex=use_hex, rounds=rounds) else: hashed = FUNC_DICT[algorithm.lower()](word.strip(), posx=posx, use_hex=use_hex, rounds=rounds) tries += 1 if verbose and tries % 10000 == 0: LOGGER.debug("Testing against: '{}', attempt #{}..".format( hashed, tries)) if verify_hash.lower() == hashed.lower(): return word.strip(), hashed, tries, algorithm
def hash_words(verify_hash, wordlist, algorithm, salt=None, placement=None, posx="", use_hex=False, verbose=False): """ Hash the words and verify if they match or not > :param verify_hash: the has to be verified > :param wordlist: the wordlist to be used > :param algorithm: the algorithm to be used > :param salt: the salt string > :param placement: where to place the salt if given > :return: the word that matched the hash when hashed, the hash, the amount of tries, and algorithm """ tries = 0 with open(wordlist) as words: for i, word in enumerate(words.readlines(), start=1): if salt is not None: if placement == "front": hashed = FUNC_DICT[algorithm.lower()](word.strip(), salt=salt, front=True, posx=posx, use_hex=use_hex) else: hashed = FUNC_DICT[algorithm.lower()](word.strip(), salt=salt, back=True, posx=posx, use_hex=use_hex) else: hashed = FUNC_DICT[algorithm.lower()](word.strip(), posx=posx, use_hex=use_hex) tries += 1 if verify_hash == hashed: if verbose: LOGGER.debug("Testing against: {}".format(hashed)) return word.strip(), hashed, tries, algorithm
for i, _ in enumerate(sys.argv): if sys.argv[i] in required_args: args_in_params += 1 # If you provided an argument continue.. if args_in_params > 0: start_up(verbose=opt.runInVerbose) # Show the options being used at the time of the run if verbose is True if opt.runInVerbose: opts_being_used = [] for o, v in opt.__dict__.items(): if v is not None: opts_being_used.append((o, v)) LOGGER.debug("Options being used: {}..".format( dict(opts_being_used))) # Benchmark testing if opt.runBenchMarkTest: start_time = time.time() # Creating random salts and random placements if opt.randomSaltAndPlacement: salt, placement = random_salt_generator( opt.useCharsAsSalt, opt.useIntAsSalt, opt.saltSizeToUse) LOGGER.info( "Using random salt: '{}' and random placement: '{}'..." .format(salt, placement)) # If you provided your own salt and your own placements
def bruteforce_main(verf_hash, algorithm=None, wordlist=None, salt=None, placement=None, all_algs=False, posx="", use_hex=False, verbose=False, batch=False, rounds=10): """ Main function to be used for bruteforcing a hash """ wordlist_created = False if wordlist is None: create_dir("bf-dicts", verbose=verbose) for item in os.listdir(os.getcwd() + "/bf-dicts"): if WORDLIST_RE.match(item): wordlist_created = True wordlist = "{}/bf-dicts/{}".format(os.getcwd(), item) if not wordlist_created: LOGGER.info("Creating wordlist..") create_wordlist(verbose=verbose) else: LOGGER.info("Reading from, {}..".format(wordlist)) if algorithm is None: hash_type = verify_hash_type(verf_hash, least_likely=all_algs) LOGGER.info( "Found {} possible hash type(s) to run against: {} ".format( len(hash_type) - 1 if hash_type[1] is None else len(hash_type), hash_type[0] if hash_type[1] is None else hash_type)) for alg in hash_type: if alg is None: err_msg = ( "Ran out of algorithms to try. There are no more " "algorithms currently available that match this hashes " "length, and complexity.") LOGGER.fatal(err_msg.format(DAGON_ISSUE_LINK)) break else: if ":::" in verf_hash: LOGGER.debug( "It appears that you are trying to crack an '{}' hash, " "these hashes have a certain sequence to them that looks " "like this 'USERNAME:SID:LM_HASH:NTLM_HASH:::'. What you're " "wanting is the NTLM part, of the hash, fix your hash and try " "again..".format(alg.upper())) shutdown(1) LOGGER.info("Starting bruteforce with {}..".format( alg.upper())) bruteforcing = hash_words(verf_hash, wordlist, alg, salt=salt, placement=placement, posx=posx, use_hex=use_hex, verbose=verbose, rounds=rounds) if bruteforcing is None: LOGGER.warning( "Unable to find a match for '{}', using {}..".format( verf_hash, alg.upper())) else: match_found(bruteforcing) break else: LOGGER.info("Using algorithm, {}..".format(algorithm.upper())) results = hash_words(verf_hash, wordlist, algorithm, salt=salt, placement=placement, posx=posx, verbose=verbose) if results is None: LOGGER.warning("Unable to find a match using {}..".format( algorithm.upper())) if not batch: verify = prompt( "Would you like to attempt to verify the hash type automatically and crack it", "y/N") else: verify = "n" if verify.startswith(("y", "Y")): bruteforce_main(verf_hash, wordlist=wordlist, salt=salt, placement=placement, posx=posx, use_hex=use_hex, verbose=verbose) else: LOGGER.warning( "Unable to produce a result for given hash '{}' using {}.." .format(verf_hash, algorithm.upper())) else: match_found(results)
def bruteforce_main(verf_hash, algorithm=None, wordlist=None, salt=None, placement=None, all_algs=False, perms="", posx="", use_hex=False): """ Main function to be used for bruteforcing a hash """ wordlist_created = False if wordlist is None: for item in os.listdir(os.getcwd()): if WORDLIST_RE.match(item): wordlist_created = True wordlist = item if wordlist_created is True: pass else: LOGGER.info("Creating wordlist..") create_wordlist(perms=perms) else: LOGGER.info("Reading from, {}..".format(wordlist)) if algorithm is None: hash_type = verify_hash_type(verf_hash, least_likely=all_algs) LOGGER.info("Found {} possible hash types to run against: {} ".format( len(hash_type) - 1 if hash_type[1] is None else len(hash_type), hash_type[0] if hash_type[1] is None else hash_type)) for alg in hash_type: if alg is None: err_msg = "Ran out of algorithms to try. There are no more algorithms " err_msg += "currently available that match this hashes length, and complexity. " err_msg += "Please attempt to use your own wordlist (switch '--wordlist'), " err_msg += "download one (switch '--download'), use salt (switch '-S SALT'), " err_msg += "or find the algorithm type and create a issue here {}.. " LOGGER.fatal(err_msg.format(DAGON_ISSUE_LINK)) break else: if ":" in verf_hash: LOGGER.debug( "It appears that you are trying to crack an '{}' hash, " "these hashes have a certain sequence to them that looks " "like this 'USERNAME:SID:LM_HASH:NTLM_HASH:::'. What you're " "wanting is the NTLM part, of the hash, fix your hash and try " "again..".format(alg.upper())) shutdown(1) LOGGER.info("Starting bruteforce with {}..".format( alg.upper())) bruteforcing = hash_words(verf_hash, wordlist, alg, salt=salt, placement=placement, posx=posx, use_hex=use_hex) if bruteforcing is None: LOGGER.warning( "Unable to find a match for '{}', using {}..".format( verf_hash, alg.upper())) else: match_found(bruteforcing) break else: LOGGER.info("Using algorithm, {}..".format(algorithm.upper())) results = hash_words(verf_hash, wordlist, algorithm, salt=salt, placement=placement, posx=posx) if results is None: LOGGER.warning("Unable to find a match using {}..".format( algorithm.upper())) verifiy = prompt( "Would you like to attempt to verify the hash type automatically and crack it", "y/N") if verifiy.lower().startswith("y"): bruteforce_main(verf_hash, wordlist=wordlist, salt=salt, placement=placement, posx=posx, use_hex=use_hex) else: LOGGER.warning( "Unable to produce a result for given hash '{}' using {}.. Exiting.." .format(verf_hash, algorithm.upper())) else: match_found(results)