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 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): """ 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
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 word_generator(length_min=7, length_max=15, perms=False): """ Generate the words to be used for bruteforcing > :param length_min: minimum length for the word > :param length_max: max length for the word > :param perms: permutations, True or False > :return: a word Example: >>> word_generator() aaaaaa aaaaab aaaaac ... """ chrs = 'abc' for n in range(length_min, length_max + 1): for xs in itertools.product(chrs, repeat=n): if perms is False: yield ''.join(xs) else: LOGGER.fatal("Permutations are not supported yet") break
def verify_hash_type(hash_to_verify, least_likely=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 in HASH_TYPE_REGEX: if regex.match(hash_to_verify) and least_likely: return HASH_TYPE_REGEX[regex] elif regex.match(hash_to_verify) and not least_likely: return HASH_TYPE_REGEX[regex][0] else: pass error_msg = "Unable to find any algorithms to match the given hash. " error_msg += "If you feel this algorithm should be implemented make " error_msg += "an issue here: {}" LOGGER.fatal(error_msg.format(DAGON_ISSUE_LINK)) exit(1)
def create_wordlist(max_length=10000000, max_word_length=10, warning=True, perms=""): """ 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 """ warn_msg = "It is highly advised to use a dictionary attack over bruteforce. " warn_msg += "Bruteforce requires extreme amounts of memory to accomplish and " warn_msg += "it is possible that it could take a lifetime to successfully crack " warn_msg += "your hash. To run a dictionary attack all you need to do is pass " warn_msg += "the wordlist switch ('--wordlist PATH') with the path to your wordlist. " warn_msg += "(IE: --bruteforce --wordlist ~/dicts/dict.txt)" if warning is True: LOGGER.warning(warn_msg) with open(WORDLIST_NAME, "a+") as lib: word = word_generator(length_max=max_word_length, perms=perms) lib.seek(0, 0) line_count = len(lib.readlines()) try: for _ in range(line_count, max_length): lib.write(next(word) + "\n") except StopIteration: # 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 ".format( len(lib.readlines())) err_msg += "or just use what was processed. If you make the choice not to continue " err_msg += "the program will add +2 to the max length and try to create the wordlist again.." LOGGER.error(err_msg) q = prompt("Would you like to continue", "y/N") if q.lower().startswith("y"): pass else: lib.truncate(0) create_wordlist(max_word_length=max_length + 2, warning=False) LOGGER.info( "Wordlist generated, words saved to: {}. Please re-run the application, exiting.." .format(WORDLIST_NAME)) shutdown()
# Pay no attention to the _ it's required.. opt, _ = parser.parse_args() verify_python_version() required_args = [ "-c", "--crack", "-l", "--hash-list", "-v", "--verify", "--download" ] args_in_params = 0 show_banner() if opt.hideBanner is not True else show_hidden_banner() if len(sys.argv) <= 1: LOGGER.fatal( "You have failed to provide a flag for to the application and have been " "redirected to the help menu.") time.sleep(1.7) subprocess.call("python dagon.py --help") else: try: # Check that you provided a mandatory argument 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: if opt.downloadWordList is True: download_rand_wordlist()
# Pay no attention to the _ it's required.. opt, _ = parser.parse_args() verify_python_version() required_args = [ "-c", "--crack", "-l", "--hash-list", "-v", "--verify", "-V", "--verify-list" ] args_in_params = 0 show_banner() if opt.hideBanner is not True else show_hidden_banner() if len(sys.argv) <= 1: LOGGER.fatal( "You have failed to provide a flag to the application and have been redirected to the help menu." ) time.sleep(1.7) subprocess.call("python dagon.py --help", shell=True) else: try: # Download a random wordlist if opt.downloadWordList is True: download_rand_wordlist() exit(0) # Output all supported algorithms if opt.showAvailableAlgorithms is True: show_available_algs(show_all=opt.showAllAlgorithms) exit(0)
def bruteforce_main(verf_hash, algorithm=None, wordlist=None, salt=None, placement=None, all_algs=False, perms="", posx=""): """ 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: LOGGER.info("Starting bruteforce with {}..".format(alg.upper())) bruteforcing = hash_words(verf_hash, wordlist, alg, salt=salt, placement=placement, posx=posx) 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) else: LOGGER.warning( "Unable to produce a result for given hash '{}' using {}.. Exiting.." .format(verf_hash, algorithm.upper())) else: match_found(results)
# Pay no attention to the _ it's required.. opt, _ = parser.parse_args() verify_python_version(verbose=opt.runInVerbose) # need this again :| required_args = [ "-c", "--crack", "-l", "--hash-list", "-v", "--verify", "-V", "--verify-list" ] args_in_params = 0 show_banner() if opt.hideBanner else show_hidden_banner() if len(sys.argv) <= 1: LOGGER.fatal( "You have failed to provide a flag to the application and have been redirected to the help menu." ) time.sleep(1.7) subprocess.call("python dagon.py --help", shell=True) else: try: if opt.testProgramIntegrity: status = integrity_check() if status: LOGGER.info( "Integrity check has passed successfully, there are no updates " "available at the moment and you are running the latest version." ) exit(0) # Download a random wordlist
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)