Ejemplo n.º 1
0
def run_statistical_crack_mode(pJTR: JohnTheRipper, pPercentile: float,
                               pMaxAllowedCharactersToBruteForce: int) -> None:

    # The JTR POT file is the source of passwords
    Printer.print("Parsing JTR POT file at {}".format(pJTR.jtr_pot_file_path),
                  Level.INFO)
    lListOfPasswords = pJTR.parse_passwords_from_pot()

    if pJTR.verbose:
        lCountPasswords = lListOfPasswords.__len__()
        Printer.print(
            "Using {} passwords in statistical analysis: ".format(
                str(lCountPasswords)), Level.INFO)
        if lCountPasswords > 1000000:
            Printer.print(
                "That is a lot of passwords. Statistical analysis may take a while.",
                Level.WARNING)

    # Let PasswordStats class analyze most likely masks
    Printer.print("Beginning statistical analysis", Level.INFO)
    lPasswordStats = PasswordStats(lListOfPasswords)
    Printer.print(
        "Parsed {} passwords into {} masks".format(
            lPasswordStats.count_passwords, lPasswordStats.count_masks),
        Level.INFO)

    # Calculate masks most likely need to crack X% of the password hashes
    lMasks = lPasswordStats.get_popular_masks(pPercentile)
    Printer.print(
        "Password masks ({} percentile): {}".format(pPercentile, lMasks),
        Level.INFO)

    run_smart_mask_mode(
        pJTR=pJTR,
        pMasks=lMasks,
        pMaxAllowedCharactersToBruteForce=pMaxAllowedCharactersToBruteForce)
Ejemplo n.º 2
0
def perform_statistical_cracking(pHashFile: str, pPercentile: float,
                                 pHashFormat: str, pVerbose: bool,
                                 pDebug: bool, pPassThrough: str,
                                 pNumberHashes: int) -> None:

    # The JTR POT file is the source of passwords
    if pVerbose:
        print("[*] Parsing JTR POT file at {}".format(JTR_POT_FILE_PATH))
    lListOfPasswords = parse_jtr_pot(pVerbose, True)

    if pVerbose:
        lCountPasswords = lListOfPasswords.__len__()
        print("[*] Using {} passwords in statistical analysis: ".format(
            str(lCountPasswords)))
        if lCountPasswords > 1000000:
            print(
                "[*] That is a lot of passwords. Statistical analysis may take a while."
            )

    # Let PasswordStats class analyze most likely masks
    if pVerbose: print("[*] Beginning statistical analysis")
    lPasswordStats = PasswordStats(lListOfPasswords)
    if pVerbose:
        print("[*] Parsed {} passwords into {} masks".format(
            lPasswordStats.count_passwords, lPasswordStats.count_masks))

    # Calculate masks most likely need to crack X% of the password hashes
    lMasks = lPasswordStats.get_popular_masks(lPercentile)
    if pVerbose:
        print("[*] Password masks ({} percentile): {}".format(
            pPercentile, lMasks))

    # For each mask, try high probability guesses
    lUndefinedMasks = []
    for lMask in lMasks:
        if pVerbose: print("[*] Processing mask: {}".format(lMask))

        # If the number of characters in the mask is "small" as defined by
        # MAX_CHARS_TO_BRUTEFORCE, then use brute-force on the pattern.
        # If there are more characters than the limit, use "smart brute-force"
        # which is a hybrid between dictionary and mask mode.
        lCountCharacters = int(len(lMask) / 2)
        if lCountCharacters <= MAX_CHARS_TO_BRUTEFORCE:
            lWordlist = ""
            run_jtr_mask_mode(pHashFile=pHashFile,
                              pMask=lMask,
                              pWordlist=lWordlist,
                              pHashFormat=pHashFormat,
                              pVerbose=pVerbose,
                              pDebug=pDebug,
                              pPassThrough=pPassThrough,
                              pNumberHashes=pNumberHashes)
        else:

            # All lowercase letters
            if re.match('^(\?l)+$', lMask):
                lCountLetters = lMask.count('?l')
                if lCountLetters > MAX_CHARS_TO_BRUTEFORCE:
                    lWordlist = "dictionaries/{}-character-words.txt".format(
                        str(lCountLetters))
                    lRule = ""
                    run_jtr_wordlist_mode(pHashFile=pHashFile,
                                          pWordlist=lWordlist,
                                          pRule=lRule,
                                          pHashFormat=pHashFormat,
                                          pVerbose=pVerbose,
                                          pDebug=pDebug,
                                          pPassThrough=pPassThrough,
                                          pNumberHashes=pNumberHashes)

            # All uppercase
            elif re.match('^(\?u)+$', lMask):
                lCountLetters = lMask.count('?u')
                lWordlist = "dictionaries/{}-character-words.txt".format(
                    str(lCountLetters))
                lRule = "uppercase"
                run_jtr_wordlist_mode(pHashFile=pHashFile,
                                      pWordlist=lWordlist,
                                      pRule=lRule,
                                      pHashFormat=pHashFormat,
                                      pVerbose=pVerbose,
                                      pDebug=pDebug,
                                      pPassThrough=pPassThrough,
                                      pNumberHashes=pNumberHashes)

            # Uppercase followed by lowercase (assume only leading letter is uppercase)
            elif re.match('^(\?u)(\?l)+$', lMask):
                lCountLetters = lMask.count('?u') + lMask.count('?l')
                lWordlist = "dictionaries/{}-character-words.txt".format(
                    str(lCountLetters))
                lRule = "capitalize"
                run_jtr_wordlist_mode(pHashFile=pHashFile,
                                      pWordlist=lWordlist,
                                      pRule=lRule,
                                      pHashFormat=pHashFormat,
                                      pVerbose=pVerbose,
                                      pDebug=pDebug,
                                      pPassThrough=pPassThrough,
                                      pNumberHashes=pNumberHashes)

            # Lowercase ending with digits
            elif re.match('^(\?l)+(\?d)+$', lMask):
                lCountLetters = lMask.count('?l')
                lCountDigits = lMask.count('?d')
                lWordlist = "dictionaries/{}-character-words.txt".format(
                    str(lCountLetters))
                lRule = "append{}digits".format(str(lCountDigits))
                run_jtr_wordlist_mode(pHashFile=pHashFile,
                                      pWordlist=lWordlist,
                                      pRule=lRule,
                                      pHashFormat=pHashFormat,
                                      pVerbose=pVerbose,
                                      pDebug=pDebug,
                                      pPassThrough=pPassThrough,
                                      pNumberHashes=pNumberHashes)

            # Uppercase followed by digits
            elif re.match('^(\?u)+(\?d)+$', lMask):
                lCountLetters = lMask.count('?u')
                lCountDigits = lMask.count('?d')
                lWordlist = "dictionaries/{}-character-words.txt".format(
                    str(lCountLetters))
                lRule = "uppercaseappend{}digits".format(str(lCountDigits))
                run_jtr_wordlist_mode(pHashFile=pHashFile,
                                      pWordlist=lWordlist,
                                      pRule=lRule,
                                      pHashFormat=pHashFormat,
                                      pVerbose=pVerbose,
                                      pDebug=pDebug,
                                      pPassThrough=pPassThrough,
                                      pNumberHashes=pNumberHashes)

            # Uppercase, lowercase, then digits (assume only leading letter is uppercase)
            elif re.match('^(\?u)(\?l)+(\?d)+$', lMask):
                lCountLetters = lMask.count('?u') + lMask.count('?l')
                lCountDigits = lMask.count('?d')
                lWordlist = "dictionaries/{}-character-words.txt".format(
                    str(lCountLetters))
                lRule = "capitalizeappend{}digits".format(str(lCountDigits))
                run_jtr_wordlist_mode(pHashFile=pHashFile,
                                      pWordlist=lWordlist,
                                      pRule=lRule,
                                      pHashFormat=pHashFormat,
                                      pVerbose=pVerbose,
                                      pDebug=pDebug,
                                      pPassThrough=pPassThrough,
                                      pNumberHashes=pNumberHashes)

            # Low number of digits. We do not cover large numbers of digits because
            # precomputing dictionary files would be huge and running mask mode takes a long time.
            # Right now we support 4-6 digits only. Recall we cover 4 and 6 digits specifically in
            # "prayer" mode so we do not repeat those two masks here.
            elif re.match('^(\?d)+$', lMask):
                lCountDigits = lMask.count('?d')
                if lCountDigits == 5:
                    lWordlist = "dictionaries/{}-digit-numbers.txt".format(
                        str(lCountDigits))
                    run_jtr_wordlist_mode(pHashFile=pHashFile,
                                          pWordlist=lWordlist,
                                          pRule="",
                                          pHashFormat=pHashFormat,
                                          pVerbose=pVerbose,
                                          pDebug=pDebug,
                                          pPassThrough=pPassThrough,
                                          pNumberHashes=pNumberHashes)
                else:
                    print(
                        "[*] WARNING: Did not process mask {} because it is out of policy"
                        .format(lMask))

            # Lowercase ending with something other than the masks already accounted for. If the
            # ending pattern is longer than 4 characters, we do not try because it takes a long time
            # to test that many hashes
            elif re.match('^(\?l)+', lMask):
                lPrefix = re.search('^(\?l)+', lMask).group()
                lCountLetters = lPrefix.count("?l")
                lSuffix = lMask[lCountLetters * 2:]
                if len(lSuffix) <= 4:
                    lWordlist = "dictionaries/{}-character-words.txt".format(
                        str(lCountLetters))
                    lMaskParam = "--mask=?w{}".format(lSuffix)
                    run_jtr_mask_mode(pHashFile=pHashFile,
                                      pMask=lMaskParam,
                                      pWordlist=lWordlist,
                                      pHashFormat=pHashFormat,
                                      pVerbose=pVerbose,
                                      pDebug=pDebug,
                                      pPassThrough=pPassThrough,
                                      pNumberHashes=pNumberHashes)
                else:
                    print(
                        "[*] WARNING: Did not process mask {} because it is out of policy"
                        .format(lMask))

            else:
                lUndefinedMasks.append(lMask)
                print(
                    "[*] WARNING: No policy defined for mask {}".format(lMask))

    # List masks that did not match a pattern so that a pattern can be added
    if lUndefinedMasks:
        print(
            "[*] WARNING: There was no policy defined for the following masks: {}"
            .format(lUndefinedMasks))
Ejemplo n.º 3
0
    # Count passwords imported
    if lArgs.verbose:
        lCountPasswords = lListOfPasswords.__len__()
        print("[*] Passwords imported: " + str(lCountPasswords))
        if lCountPasswords > 1000000:
            print("[*] That is a lot of passwords. Parsing may take a while.")

    # Calculate password statistics and store in PasswordStats object
    if lArgs.verbose: print("[*] Parsing input file " + lArgs.input_file)
    lPasswordStats = PasswordStats(lListOfPasswords)
    if lArgs.verbose:
        print("[*] Finished parsing input file " + lArgs.input_file)
        print("[*] Parsed {} passwords into {} masks".format(
            lPasswordStats.count_passwords, lPasswordStats.count_masks))

    if lArgs.analyze_passwords:
        lPasswordStats.get_analysis(lPercentile)

    if lArgs.list_masks:
        if lArgs.verbose:
            print("[*] Password masks ({} percentile):".format(lPercentile),
                  end='')
        print(lPasswordStats.get_popular_masks(lPercentile))

    if lArgs.output_file:
        lPasswordStats.export_password_counts_to_csv(lArgs.output_file)
        if lArgs.verbose:
            print(
                "[*] Finished writing password counts per mask to output file "
                + lArgs.output_file)