Standardized on speed, rewrote statsgen, many bug fixes.
This commit is contained in:
		
							
								
								
									
										62
									
								
								maskgen.py
									
									
									
									
									
								
							
							
						
						
									
										62
									
								
								maskgen.py
									
									
									
									
									
								
							@@ -46,12 +46,15 @@ class MaskGen:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        self.minlength  = None
 | 
					        self.minlength  = None
 | 
				
			||||||
        self.maxlength  = None
 | 
					        self.maxlength  = None
 | 
				
			||||||
 | 
					        self.mintime    = None
 | 
				
			||||||
        self.maxtime    = None
 | 
					        self.maxtime    = None
 | 
				
			||||||
 | 
					        self.mincomplexity = None
 | 
				
			||||||
        self.maxcomplexity = None
 | 
					        self.maxcomplexity = None
 | 
				
			||||||
        self.minoccurrence = None
 | 
					        self.minoccurrence = None
 | 
				
			||||||
 | 
					        self.maxoccurrence = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # PPS (Passwords per Second) Cracking Speed
 | 
					        # PPS (Passwords per Second) Cracking Speed
 | 
				
			||||||
        self.pps = 10000000000
 | 
					        self.pps = 1000000000
 | 
				
			||||||
        self.showmasks = False
 | 
					        self.showmasks = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Counter for total masks coverage
 | 
					        # Counter for total masks coverage
 | 
				
			||||||
@@ -81,20 +84,25 @@ class MaskGen:
 | 
				
			|||||||
            mask_occurrence = int(occurrence)
 | 
					            mask_occurrence = int(occurrence)
 | 
				
			||||||
            mask_length = len(mask)/2
 | 
					            mask_length = len(mask)/2
 | 
				
			||||||
            mask_complexity = self.getcomplexity(mask)
 | 
					            mask_complexity = self.getcomplexity(mask)
 | 
				
			||||||
 | 
					            mask_time = mask_complexity/self.pps
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            self.total_occurrence += mask_occurrence
 | 
					            self.total_occurrence += mask_occurrence
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # Apply filters based on occurrence, length, complexity and time
 | 
					            # Apply filters based on occurrence, length, complexity and time
 | 
				
			||||||
            if (not self.minoccurrence or mask_occurrence >= self.minoccurrence) and \
 | 
					            if (self.minoccurrence == None or mask_occurrence >= self.minoccurrence) and \
 | 
				
			||||||
               (not self.maxcomplexity or mask_complexity <= self.maxcomplexity) and \
 | 
					               (self.maxoccurrence == None or mask_occurrence <= self.maxoccurrence) and \
 | 
				
			||||||
               (not self.maxlength or mask_length <= self.maxlength) and \
 | 
					               (self.mincomplexity == None or mask_complexity <= self.mincomplexity) and \
 | 
				
			||||||
               (not self.minlength or mask_length >= self.minlength):
 | 
					               (self.maxcomplexity == None or mask_complexity <= self.maxcomplexity) and \
 | 
				
			||||||
 | 
					               (self.mintime == None or mask_time <= self.mintime) and \
 | 
				
			||||||
 | 
					               (self.maxtime == None or mask_time <= self.maxtime) and \
 | 
				
			||||||
 | 
					               (self.maxlength == None or mask_length <= self.maxlength) and \
 | 
				
			||||||
 | 
					               (self.minlength == None or mask_length >= self.minlength):
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
                self.masks[mask] = dict()
 | 
					                self.masks[mask] = dict()
 | 
				
			||||||
                self.masks[mask]['length'] = mask_length
 | 
					                self.masks[mask]['length'] = mask_length
 | 
				
			||||||
                self.masks[mask]['occurrence'] = mask_occurrence
 | 
					                self.masks[mask]['occurrence'] = mask_occurrence
 | 
				
			||||||
                self.masks[mask]['complexity'] = 1 - mask_complexity
 | 
					                self.masks[mask]['complexity'] = 1 - mask_complexity
 | 
				
			||||||
                self.masks[mask]['time'] = mask_complexity/self.pps
 | 
					                self.masks[mask]['time'] = mask_time
 | 
				
			||||||
                self.masks[mask]['optindex'] = 1 - mask_complexity/mask_occurrence
 | 
					                self.masks[mask]['optindex'] = 1 - mask_complexity/mask_occurrence
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def generate_masks(self,sorting_mode):
 | 
					    def generate_masks(self,sorting_mode):
 | 
				
			||||||
@@ -132,13 +140,18 @@ class MaskGen:
 | 
				
			|||||||
        print "    Masks runtime:   %s" % time_human
 | 
					        print "    Masks runtime:   %s" % time_human
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def getmaskscoverage(self, checkmasks):
 | 
					    def getmaskscoverage(self, checkmasks):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        sample_count = 0
 | 
					        sample_count = 0
 | 
				
			||||||
        sample_time = 0
 | 
					 | 
				
			||||||
        sample_occurrence = 0
 | 
					        sample_occurrence = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        total_complexity = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if self.showmasks: print "[L:] Mask:                          [ Occ:  ] [ Time:  ]" 
 | 
					        if self.showmasks: print "[L:] Mask:                          [ Occ:  ] [ Time:  ]" 
 | 
				
			||||||
        for mask in checkmasks:
 | 
					        for mask in checkmasks:
 | 
				
			||||||
            mask = mask.strip()
 | 
					            mask = mask.strip()
 | 
				
			||||||
 | 
					            mask_complexity = self.getcomplexity(mask)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            total_complexity += mask_complexity
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if mask in self.masks:
 | 
					            if mask in self.masks:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -150,17 +163,18 @@ class MaskGen:
 | 
				
			|||||||
                    self.output_file.write("%s\n" % mask)
 | 
					                    self.output_file.write("%s\n" % mask)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                sample_occurrence += self.masks[mask]['occurrence']
 | 
					                sample_occurrence += self.masks[mask]['occurrence']
 | 
				
			||||||
                sample_time += self.masks[mask]['time']
 | 
					 | 
				
			||||||
                sample_count += 1
 | 
					                sample_count += 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if self.target_time and sample_time > self.target_time:
 | 
					            if self.target_time and total_complexity/self.pps > self.target_time:
 | 
				
			||||||
                    print "[!] Target time exceeded."
 | 
					                print "[!] Target time exceeded."
 | 
				
			||||||
                    break
 | 
					                break
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # TODO: Something wrong here, complexity and time doesn't match with estimated from policygen
 | 
				
			||||||
 | 
					        total_time = total_complexity/self.pps
 | 
				
			||||||
 | 
					        time_human = ">1 year" if total_time > 60*60*24*365 else str(datetime.timedelta(seconds=total_time))
 | 
				
			||||||
        print "[*] Finished matching masks:"
 | 
					        print "[*] Finished matching masks:"
 | 
				
			||||||
        print "    Masks matched: %s" % sample_count
 | 
					        print "    Masks matched: %s" % sample_count
 | 
				
			||||||
        print "    Masks coverage:  %d%% (%d/%d)" % (sample_occurrence*100/self.total_occurrence,sample_occurrence,self.total_occurrence)
 | 
					        print "    Masks coverage:  %d%% (%d/%d)" % (sample_occurrence*100/self.total_occurrence,sample_occurrence,self.total_occurrence)
 | 
				
			||||||
        time_human = ">1 year" if sample_time > 60*60*24*365 else str(datetime.timedelta(seconds=sample_time))
 | 
					 | 
				
			||||||
        print "    Masks runtime:   %s" % time_human
 | 
					        print "    Masks runtime:   %s" % time_human
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -182,11 +196,14 @@ if __name__ == "__main__":
 | 
				
			|||||||
    parser.add_option("-o", "--outputmasks", dest="output_masks", metavar="masks.hcmask",     help="Save masks to a file")
 | 
					    parser.add_option("-o", "--outputmasks", dest="output_masks", metavar="masks.hcmask",     help="Save masks to a file")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    filters = OptionGroup(parser, "Individual Mask Filter Options")
 | 
					    filters = OptionGroup(parser, "Individual Mask Filter Options")
 | 
				
			||||||
    filters.add_option("--minlength",     dest="minlength",     type="int", metavar="8", help="Minimum password length")
 | 
					    filters.add_option("--minlength",     dest="minlength",     type="int", metavar="8",    help="Minimum password length")
 | 
				
			||||||
    filters.add_option("--maxlength",     dest="maxlength",     type="int", metavar="8", help="Maximum password length")
 | 
					    filters.add_option("--maxlength",     dest="maxlength",     type="int", metavar="8",    help="Maximum password length")
 | 
				
			||||||
    filters.add_option("--maxtime",       dest="maxtime",       type="int", metavar="3600",  help="Maximum runtime (seconds)")
 | 
					    filters.add_option("--mintime",       dest="mintime",       type="int", metavar="3600", help="Minimum mask runtime (seconds)")
 | 
				
			||||||
    filters.add_option("--maxcomplexity", dest="maxcomplexity", type="int", metavar="",  help="Maximum complexity")
 | 
					    filters.add_option("--maxtime",       dest="maxtime",       type="int", metavar="3600", help="Maximum mask runtime (seconds)")
 | 
				
			||||||
    filters.add_option("--minoccurrence", dest="minoccurrence", type="int", metavar="",  help="Minimum occurrence")
 | 
					    filters.add_option("--mincomplexity", dest="mincomplexity", type="int", metavar="1",    help="Minimum complexity")
 | 
				
			||||||
 | 
					    filters.add_option("--maxcomplexity", dest="maxcomplexity", type="int", metavar="100",  help="Maximum complexity")
 | 
				
			||||||
 | 
					    filters.add_option("--minoccurrence", dest="minoccurrence", type="int", metavar="1",    help="Minimum occurrence")
 | 
				
			||||||
 | 
					    filters.add_option("--maxoccurrence", dest="maxoccurrence", type="int", metavar="100",  help="Maximum occurrence")
 | 
				
			||||||
    parser.add_option_group(filters)
 | 
					    parser.add_option_group(filters)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sorting = OptionGroup(parser, "Mask Sorting Options")
 | 
					    sorting = OptionGroup(parser, "Mask Sorting Options")
 | 
				
			||||||
@@ -228,16 +245,21 @@ if __name__ == "__main__":
 | 
				
			|||||||
        maskgen.output_file = open(options.output_masks, 'w')
 | 
					        maskgen.output_file = open(options.output_masks, 'w')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Filters
 | 
					    # Filters
 | 
				
			||||||
    if options.minlength: maskgen.minlength = options.minlength
 | 
					    if options.minlength:     maskgen.minlength     = options.minlength
 | 
				
			||||||
    if options.maxlength: maskgen.maxlength = options.maxlength
 | 
					    if options.maxlength:     maskgen.maxlength     = options.maxlength
 | 
				
			||||||
    if options.maxtime:   maskgen.maxtime = options.maxtime
 | 
					    if options.mintime:       maskgen.mintime       = options.mintime
 | 
				
			||||||
 | 
					    if options.maxtime:       maskgen.maxtime       = options.maxtime
 | 
				
			||||||
 | 
					    if options.mincomplexity: maskgen.mincomplexity = options.mincomplexity
 | 
				
			||||||
    if options.maxcomplexity: maskgen.maxcomplexity = options.maxcomplexity
 | 
					    if options.maxcomplexity: maskgen.maxcomplexity = options.maxcomplexity
 | 
				
			||||||
    if options.minoccurrence: maskgen.minoccurrence = options.minoccurrence
 | 
					    if options.minoccurrence: maskgen.minoccurrence = options.minoccurrence
 | 
				
			||||||
 | 
					    if options.maxoccurrence: maskgen.maxoccurrence = options.maxoccurrence
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Misc
 | 
					    # Misc
 | 
				
			||||||
    if options.pps: maskgen.pps = options.pps
 | 
					    if options.pps: maskgen.pps = options.pps
 | 
				
			||||||
    if options.showmasks: maskgen.showmasks = options.showmasks
 | 
					    if options.showmasks: maskgen.showmasks = options.showmasks
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    print "[*] Using {:,d} keys/sec for calculations.".format(maskgen.pps)
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    # Load masks
 | 
					    # Load masks
 | 
				
			||||||
    for arg in args:
 | 
					    for arg in args:
 | 
				
			||||||
        maskgen.loadmasks(arg)
 | 
					        maskgen.loadmasks(arg)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										18
									
								
								policygen.py
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								policygen.py
									
									
									
									
									
								
							@@ -35,13 +35,6 @@ import itertools
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
VERSION = "0.0.2"
 | 
					VERSION = "0.0.2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# PPS (Passwords per Second) Cracking Speed
 | 
					 | 
				
			||||||
pps = 1000000000
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Global Variables
 | 
					 | 
				
			||||||
sample_time = 0
 | 
					 | 
				
			||||||
total_time = 0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class PolicyGen:    
 | 
					class PolicyGen:    
 | 
				
			||||||
    def __init__(self):
 | 
					    def __init__(self):
 | 
				
			||||||
        self.output_file = None
 | 
					        self.output_file = None
 | 
				
			||||||
@@ -57,7 +50,6 @@ class PolicyGen:
 | 
				
			|||||||
        self.maxupper   = None
 | 
					        self.maxupper   = None
 | 
				
			||||||
        self.maxspecial = None
 | 
					        self.maxspecial = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
        # PPS (Passwords per Second) Cracking Speed
 | 
					        # PPS (Passwords per Second) Cracking Speed
 | 
				
			||||||
        self.pps = 1000000000
 | 
					        self.pps = 1000000000
 | 
				
			||||||
        self.showmasks = False
 | 
					        self.showmasks = False
 | 
				
			||||||
@@ -82,7 +74,7 @@ class PolicyGen:
 | 
				
			|||||||
        sample_count = 0
 | 
					        sample_count = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # NOTE: It is better to collect total complexity
 | 
					        # NOTE: It is better to collect total complexity
 | 
				
			||||||
        # in order not to lose precision when dividing by pps
 | 
					        #       not to lose precision when dividing by pps
 | 
				
			||||||
        total_complexity = 0
 | 
					        total_complexity = 0
 | 
				
			||||||
        sample_complexity = 0
 | 
					        sample_complexity = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -92,6 +84,7 @@ class PolicyGen:
 | 
				
			|||||||
            total_length_count = 0
 | 
					            total_length_count = 0
 | 
				
			||||||
            sample_length_count = 0
 | 
					            sample_length_count = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            total_length_complexity = 0
 | 
					            total_length_complexity = 0
 | 
				
			||||||
            sample_length_complexity = 0
 | 
					            sample_length_complexity = 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -177,11 +170,11 @@ if __name__ == "__main__":
 | 
				
			|||||||
    group = OptionGroup(parser, "Password Policy", "Define the minimum (or maximum) password strength policy that you would like to test")
 | 
					    group = OptionGroup(parser, "Password Policy", "Define the minimum (or maximum) password strength policy that you would like to test")
 | 
				
			||||||
    group.add_option("--minlength", dest="minlength", type="int", metavar="8", default=8, help="Minimum password length")
 | 
					    group.add_option("--minlength", dest="minlength", type="int", metavar="8", default=8, help="Minimum password length")
 | 
				
			||||||
    group.add_option("--maxlength", dest="maxlength", type="int", metavar="8", default=8, help="Maximum password length")
 | 
					    group.add_option("--maxlength", dest="maxlength", type="int", metavar="8", default=8, help="Maximum password length")
 | 
				
			||||||
    group.add_option("--mindigit", dest="mindigit", type="int", metavar="1", help="Minimum number of digits")
 | 
					    group.add_option("--mindigit",  dest="mindigit",  type="int", metavar="1", help="Minimum number of digits")
 | 
				
			||||||
    group.add_option("--minlower",  dest="minlower",  type="int", metavar="1", help="Minimum number of lower-case characters")
 | 
					    group.add_option("--minlower",  dest="minlower",  type="int", metavar="1", help="Minimum number of lower-case characters")
 | 
				
			||||||
    group.add_option("--minupper",  dest="minupper",  type="int", metavar="1", help="Minimum number of upper-case characters")
 | 
					    group.add_option("--minupper",  dest="minupper",  type="int", metavar="1", help="Minimum number of upper-case characters")
 | 
				
			||||||
    group.add_option("--minspecial",dest="minspecial",type="int", metavar="1", help="Minimum number of special characters")
 | 
					    group.add_option("--minspecial",dest="minspecial",type="int", metavar="1", help="Minimum number of special characters")
 | 
				
			||||||
    group.add_option("--maxdigit", dest="maxdigit", type="int", metavar="3", help="Maximum number of digits")
 | 
					    group.add_option("--maxdigit",  dest="maxdigit",  type="int", metavar="3", help="Maximum number of digits")
 | 
				
			||||||
    group.add_option("--maxlower",  dest="maxlower",  type="int", metavar="3", help="Maximum number of lower-case characters")
 | 
					    group.add_option("--maxlower",  dest="maxlower",  type="int", metavar="3", help="Maximum number of lower-case characters")
 | 
				
			||||||
    group.add_option("--maxupper",  dest="maxupper",  type="int", metavar="3", help="Maximum number of upper-case characters")
 | 
					    group.add_option("--maxupper",  dest="maxupper",  type="int", metavar="3", help="Maximum number of upper-case characters")
 | 
				
			||||||
    group.add_option("--maxspecial",dest="maxspecial",type="int", metavar="3", help="Maximum number of special characters")
 | 
					    group.add_option("--maxspecial",dest="maxspecial",type="int", metavar="3", help="Maximum number of special characters")
 | 
				
			||||||
@@ -202,6 +195,7 @@ if __name__ == "__main__":
 | 
				
			|||||||
        print "[*] Saving generated masks to [%s]" % options.output_masks
 | 
					        print "[*] Saving generated masks to [%s]" % options.output_masks
 | 
				
			||||||
        policygen.output_file = open(options.output_masks, 'w')
 | 
					        policygen.output_file = open(options.output_masks, 'w')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Password policy
 | 
					    # Password policy
 | 
				
			||||||
    if options.minlength  != None: policygen.minlength  = options.minlength
 | 
					    if options.minlength  != None: policygen.minlength  = options.minlength
 | 
				
			||||||
    if options.maxlength  != None: policygen.maxlength  = options.maxlength
 | 
					    if options.maxlength  != None: policygen.maxlength  = options.maxlength
 | 
				
			||||||
@@ -218,6 +212,8 @@ if __name__ == "__main__":
 | 
				
			|||||||
    if options.pps: policygen.pps = options.pps
 | 
					    if options.pps: policygen.pps = options.pps
 | 
				
			||||||
    if options.showmasks: policygen.showmasks = options.showmasks
 | 
					    if options.showmasks: policygen.showmasks = options.showmasks
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    print "[*] Using {:,d} keys/sec for calculations.".format(policygen.pps)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Print current password policy
 | 
					    # Print current password policy
 | 
				
			||||||
    print "[*] Password policy:"
 | 
					    print "[*] Password policy:"
 | 
				
			||||||
    print "    Pass Lengths: min:%d max:%d" % (policygen.minlength, policygen.maxlength)
 | 
					    print "    Pass Lengths: min:%d max:%d" % (policygen.minlength, policygen.maxlength)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,7 +5,7 @@
 | 
				
			|||||||
#
 | 
					#
 | 
				
			||||||
# This tool is part of PACK (Password Analysis and Cracking Kit)
 | 
					# This tool is part of PACK (Password Analysis and Cracking Kit)
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# VERSION 0.0.1
 | 
					# VERSION 0.0.2
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# Copyright (C) 2013 Peter Kacherginsky
 | 
					# Copyright (C) 2013 Peter Kacherginsky
 | 
				
			||||||
# All rights reserved.
 | 
					# All rights reserved.
 | 
				
			||||||
@@ -44,8 +44,7 @@ from optparse import OptionParser, OptionGroup
 | 
				
			|||||||
VERSION = "0.0.1"
 | 
					VERSION = "0.0.1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Testing rules with hashcat --stdout
 | 
					# Testing rules with hashcat --stdout
 | 
				
			||||||
import subprocess
 | 
					HASHCAT_PATH = "hashcat/"
 | 
				
			||||||
HASHCAT_PATH = "hashcat-0.42/"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Rule Generator class responsible for the complete cycle of rule generation
 | 
					# Rule Generator class responsible for the complete cycle of rule generation
 | 
				
			||||||
class RuleGen:
 | 
					class RuleGen:
 | 
				
			||||||
@@ -713,7 +712,6 @@ class RuleGen:
 | 
				
			|||||||
        if self.verbose: print "[*] Analyzing password: %s" % password
 | 
					        if self.verbose: print "[*] Analyzing password: %s" % password
 | 
				
			||||||
        if self.verbose: start_time = time.clock()
 | 
					        if self.verbose: start_time = time.clock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
        # Skip all numeric passwords
 | 
					        # Skip all numeric passwords
 | 
				
			||||||
        if password.isdigit(): 
 | 
					        if password.isdigit(): 
 | 
				
			||||||
            if self.verbose: print "[!] %s => {skipping numeric} => %s" % (password,password)
 | 
					            if self.verbose: print "[!] %s => {skipping numeric} => %s" % (password,password)
 | 
				
			||||||
@@ -836,7 +834,7 @@ class RuleGen:
 | 
				
			|||||||
if __name__ == "__main__":
 | 
					if __name__ == "__main__":
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    header  = "                       _ \n"
 | 
					    header  = "                       _ \n"
 | 
				
			||||||
    header += "     RuleGen 0.0.1    | |\n"  
 | 
					    header += "     RuleGen %s    | |\n"  % VERSION
 | 
				
			||||||
    header += "      _ __   __ _  ___| | _\n"
 | 
					    header += "      _ __   __ _  ___| | _\n"
 | 
				
			||||||
    header += "     | '_ \ / _` |/ __| |/ /\n"
 | 
					    header += "     | '_ \ / _` |/ __| |/ /\n"
 | 
				
			||||||
    header += "     | |_) | (_| | (__|   < \n"
 | 
					    header += "     | |_) | (_| | (__|   < \n"
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										286
									
								
								statsgen.py
									
									
									
									
									
								
							
							
						
						
									
										286
									
								
								statsgen.py
									
									
									
									
									
								
							@@ -30,79 +30,157 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import sys
 | 
					import sys
 | 
				
			||||||
import re, operator, string
 | 
					import re, operator, string
 | 
				
			||||||
from optparse import OptionParser
 | 
					from optparse import OptionParser, OptionGroup
 | 
				
			||||||
 | 
					
 | 
				
			||||||
VERSION = "0.0.2"
 | 
					VERSION = "0.0.2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
password_counter = 0
 | 
					class StatsGen:
 | 
				
			||||||
 | 
					    def __init__(self):
 | 
				
			||||||
 | 
					        self.output_file = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Constants
 | 
					        # Filters
 | 
				
			||||||
chars_regex = list()
 | 
					        self.minlength   = None
 | 
				
			||||||
chars_regex.append(('numeric',re.compile('^[0-9]+$')))
 | 
					        self.maxlength   = None
 | 
				
			||||||
chars_regex.append(('loweralpha',re.compile('^[a-z]+$')))
 | 
					        self.simplemasks = None
 | 
				
			||||||
chars_regex.append(('upperalpha',re.compile('^[A-Z]+$')))
 | 
					        self.charsets    = None
 | 
				
			||||||
chars_regex.append(('mixedalpha',re.compile('^[a-zA-Z]+$')))
 | 
					 | 
				
			||||||
chars_regex.append(('loweralphanum',re.compile('^[a-z0-9]+$')))
 | 
					 | 
				
			||||||
chars_regex.append(('upperalphanum',re.compile('^[A-Z0-9]+$')))
 | 
					 | 
				
			||||||
chars_regex.append(('mixedalphanum',re.compile('^[a-zA-Z0-9]+$')))
 | 
					 | 
				
			||||||
chars_regex.append(('special',re.compile('^[^a-zA-Z0-9]+$')))
 | 
					 | 
				
			||||||
chars_regex.append(('loweralphaspecial',re.compile('^[^A-Z0-9]+$')))
 | 
					 | 
				
			||||||
chars_regex.append(('upperalphaspecial',re.compile('^[^a-z0-9]+$')))
 | 
					 | 
				
			||||||
chars_regex.append(('mixedalphaspecial',re.compile('^[^0-9]+$')))
 | 
					 | 
				
			||||||
chars_regex.append(('loweralphaspecialnum',re.compile('^[^A-Z]+$')))
 | 
					 | 
				
			||||||
chars_regex.append(('upperalphaspecialnum',re.compile('^[^a-z]+$')))
 | 
					 | 
				
			||||||
chars_regex.append(('mixedalphaspecialnum',re.compile('.*')))
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
masks_regex = list()
 | 
					        # Constants
 | 
				
			||||||
masks_regex.append(('alldigit',re.compile('^\d+$', re.IGNORECASE)))
 | 
					        self.chars_regex = list()
 | 
				
			||||||
masks_regex.append(('allstring',re.compile('^[a-z]+$', re.IGNORECASE)))
 | 
					        self.chars_regex.append(('numeric',re.compile('^[0-9]+$')))
 | 
				
			||||||
masks_regex.append(('stringdigit',re.compile('^[a-z]+\d+$', re.IGNORECASE)))
 | 
					        self.chars_regex.append(('loweralpha',re.compile('^[a-z]+$')))
 | 
				
			||||||
masks_regex.append(('digitstring',re.compile('^\d+[a-z]+$', re.IGNORECASE)))
 | 
					        self.chars_regex.append(('upperalpha',re.compile('^[A-Z]+$')))
 | 
				
			||||||
masks_regex.append(('digitstringdigit',re.compile('^\d+[a-z]+\d+$', re.IGNORECASE)))
 | 
					        self.chars_regex.append(('mixedalpha',re.compile('^[a-zA-Z]+$')))
 | 
				
			||||||
masks_regex.append(('stringdigitstring',re.compile('^[a-z]+\d+[a-z]+$', re.IGNORECASE)))
 | 
					        self.chars_regex.append(('loweralphanum',re.compile('^[a-z0-9]+$')))
 | 
				
			||||||
masks_regex.append(('allspecial',re.compile('^[^a-z0-9]+$', re.IGNORECASE)))
 | 
					        self.chars_regex.append(('upperalphanum',re.compile('^[A-Z0-9]+$')))
 | 
				
			||||||
masks_regex.append(('stringspecial',re.compile('^[a-z]+[^a-z0-9]+$', re.IGNORECASE)))
 | 
					        self.chars_regex.append(('mixedalphanum',re.compile('^[a-zA-Z0-9]+$')))
 | 
				
			||||||
masks_regex.append(('specialstring',re.compile('^[^a-z0-9]+[a-z]+$', re.IGNORECASE)))
 | 
					        self.chars_regex.append(('special',re.compile('^[^a-zA-Z0-9]+$')))
 | 
				
			||||||
masks_regex.append(('stringspecialstring',re.compile('^[a-z]+[^a-z0-9]+[a-z]+$', re.IGNORECASE)))
 | 
					        self.chars_regex.append(('loweralphaspecial',re.compile('^[^A-Z0-9]+$')))
 | 
				
			||||||
masks_regex.append(('stringspecialdigit',re.compile('^[a-z]+[^a-z0-9]+\d+$', re.IGNORECASE)))
 | 
					        self.chars_regex.append(('upperalphaspecial',re.compile('^[^a-z0-9]+$')))
 | 
				
			||||||
masks_regex.append(('specialstringspecial',re.compile('^[^a-z0-9]+[a-z]+[^a-z0-9]+$', re.IGNORECASE)))
 | 
					        self.chars_regex.append(('mixedalphaspecial',re.compile('^[^0-9]+$')))
 | 
				
			||||||
 | 
					        self.chars_regex.append(('loweralphaspecialnum',re.compile('^[^A-Z]+$')))
 | 
				
			||||||
 | 
					        self.chars_regex.append(('upperalphaspecialnum',re.compile('^[^a-z]+$')))
 | 
				
			||||||
 | 
					        self.chars_regex.append(('mixedalphaspecialnum',re.compile('.*')))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def length_check(password): 
 | 
					        self.masks_regex = list()
 | 
				
			||||||
    return len(password)
 | 
					        self.masks_regex.append(('alldigit',re.compile('^\d+$', re.IGNORECASE)))
 | 
				
			||||||
 | 
					        self.masks_regex.append(('allstring',re.compile('^[a-z]+$', re.IGNORECASE)))
 | 
				
			||||||
 | 
					        self.masks_regex.append(('stringdigit',re.compile('^[a-z]+\d+$', re.IGNORECASE)))
 | 
				
			||||||
 | 
					        self.masks_regex.append(('digitstring',re.compile('^\d+[a-z]+$', re.IGNORECASE)))
 | 
				
			||||||
 | 
					        self.masks_regex.append(('digitstringdigit',re.compile('^\d+[a-z]+\d+$', re.IGNORECASE)))
 | 
				
			||||||
 | 
					        self.masks_regex.append(('stringdigitstring',re.compile('^[a-z]+\d+[a-z]+$', re.IGNORECASE)))
 | 
				
			||||||
 | 
					        self.masks_regex.append(('allspecial',re.compile('^[^a-z0-9]+$', re.IGNORECASE)))
 | 
				
			||||||
 | 
					        self.masks_regex.append(('stringspecial',re.compile('^[a-z]+[^a-z0-9]+$', re.IGNORECASE)))
 | 
				
			||||||
 | 
					        self.masks_regex.append(('specialstring',re.compile('^[^a-z0-9]+[a-z]+$', re.IGNORECASE)))
 | 
				
			||||||
 | 
					        self.masks_regex.append(('stringspecialstring',re.compile('^[a-z]+[^a-z0-9]+[a-z]+$', re.IGNORECASE)))
 | 
				
			||||||
 | 
					        self.masks_regex.append(('stringspecialdigit',re.compile('^[a-z]+[^a-z0-9]+\d+$', re.IGNORECASE)))
 | 
				
			||||||
 | 
					        self.masks_regex.append(('specialstringspecial',re.compile('^[^a-z0-9]+[a-z]+[^a-z0-9]+$', re.IGNORECASE)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def masks_check(password):
 | 
					        # Stats dictionaries
 | 
				
			||||||
    for (name,regex) in masks_regex:
 | 
					        self.stats_length = dict()
 | 
				
			||||||
        if regex.match(password):
 | 
					        self.stats_simplemasks = dict()
 | 
				
			||||||
            return name
 | 
					        self.stats_advancedmasks = dict()
 | 
				
			||||||
    else:
 | 
					        self.stats_charactersets = dict()
 | 
				
			||||||
        return "othermask"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
def chars_check(password):
 | 
					        self.hiderare = False
 | 
				
			||||||
    for (name,regex) in chars_regex:
 | 
					 | 
				
			||||||
        if regex.match(password):
 | 
					 | 
				
			||||||
            return name
 | 
					 | 
				
			||||||
    else:
 | 
					 | 
				
			||||||
        return "otherchar"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
def advmask_check(password):
 | 
					        self.filter_counter = 0
 | 
				
			||||||
    advmask = list()
 | 
					        self.total_counter = 0
 | 
				
			||||||
    for letter in password:
 | 
					 | 
				
			||||||
        if letter in string.digits: advmask.append("?d")
 | 
					 | 
				
			||||||
        elif letter in string.lowercase: advmask.append("?l")
 | 
					 | 
				
			||||||
        elif letter in string.uppercase: advmask.append("?u")
 | 
					 | 
				
			||||||
        else: advmask.append("?s")
 | 
					 | 
				
			||||||
    return "".join(advmask)     
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
def main():
 | 
					    def simplemasks_check(self, password):
 | 
				
			||||||
    password_length = dict()
 | 
					        for (name,regex) in self.masks_regex:
 | 
				
			||||||
    masks = dict()
 | 
					            if regex.match(password):
 | 
				
			||||||
    advmasks = dict()
 | 
					                return name
 | 
				
			||||||
    chars = dict()
 | 
					        else:
 | 
				
			||||||
    filter_counter = 0
 | 
					            return "othermask"
 | 
				
			||||||
    total_counter = 0
 | 
					
 | 
				
			||||||
 | 
					    def characterset_check(self, password):
 | 
				
			||||||
 | 
					        for (name,regex) in self.chars_regex:
 | 
				
			||||||
 | 
					            if regex.match(password):
 | 
				
			||||||
 | 
					                return name
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            return "otherchar"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def advancedmask_check(self, password):
 | 
				
			||||||
 | 
					        mask = list()
 | 
				
			||||||
 | 
					        for letter in password:
 | 
				
			||||||
 | 
					            if letter in string.digits: mask.append("?d")
 | 
				
			||||||
 | 
					            elif letter in string.lowercase: mask.append("?l")
 | 
				
			||||||
 | 
					            elif letter in string.uppercase: mask.append("?u")
 | 
				
			||||||
 | 
					            else: mask.append("?s")
 | 
				
			||||||
 | 
					        return "".join(mask)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def generate_stats(self, filename):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        f = open(filename,'r')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for password in f:
 | 
				
			||||||
 | 
					            password = password.rstrip('\r\n')
 | 
				
			||||||
 | 
					            self.total_counter += 1  
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					            pass_length = len(password)
 | 
				
			||||||
 | 
					            characterset = self.characterset_check(password)
 | 
				
			||||||
 | 
					            simplemask   = self.simplemasks_check(password)
 | 
				
			||||||
 | 
					            advancedmask = self.advancedmask_check(password)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (self.charsets == None    or characterset in self.charsets) and \
 | 
				
			||||||
 | 
					               (self.simplemasks == None or simplemask in self.simplemasks) and \
 | 
				
			||||||
 | 
					               (self.maxlength == None   or pass_length <= self.maxlength) and \
 | 
				
			||||||
 | 
					               (self.minlength == None   or pass_length >= self.minlength):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                self.filter_counter += 1         
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if pass_length in self.stats_length:
 | 
				
			||||||
 | 
					                    self.stats_length[pass_length] += 1
 | 
				
			||||||
 | 
					                else:
 | 
				
			||||||
 | 
					                    self.stats_length[pass_length] = 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if characterset in self.stats_charactersets:
 | 
				
			||||||
 | 
					                    self.stats_charactersets[characterset] += 1
 | 
				
			||||||
 | 
					                else:
 | 
				
			||||||
 | 
					                    self.stats_charactersets[characterset] = 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if simplemask in self.stats_simplemasks:
 | 
				
			||||||
 | 
					                    self.stats_simplemasks[simplemask] += 1
 | 
				
			||||||
 | 
					                else:
 | 
				
			||||||
 | 
					                    self.stats_simplemasks[simplemask] = 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if advancedmask in self.stats_advancedmasks:
 | 
				
			||||||
 | 
					                    self.stats_advancedmasks[advancedmask] += 1
 | 
				
			||||||
 | 
					                else:
 | 
				
			||||||
 | 
					                    self.stats_advancedmasks[advancedmask] = 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        f.close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def print_stats(self):
 | 
				
			||||||
 | 
					        print "[+] Analyzing %d%% (%d/%d) of passwords" % (self.filter_counter*100/self.total_counter, self.filter_counter, self.total_counter)
 | 
				
			||||||
 | 
					        print "    NOTE: Statistics below is relative to the number of analyzed passwords, not total number of passwords"
 | 
				
			||||||
 | 
					        print "\n[*] Line Count Statistics..."
 | 
				
			||||||
 | 
					        for (length,count) in sorted(self.stats_length.iteritems(), key=operator.itemgetter(1), reverse=True):
 | 
				
			||||||
 | 
					            if self.hiderare and not count*100/self.filter_counter > 0: continue
 | 
				
			||||||
 | 
					            print "[+] %25d: %02d%% (%d)" % (length, count*100/self.filter_counter, count)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        print "\n[*] Charset statistics..."
 | 
				
			||||||
 | 
					        for (char,count) in sorted(self.stats_charactersets.iteritems(), key=operator.itemgetter(1), reverse=True):
 | 
				
			||||||
 | 
					            if self.hiderare and not count*100/self.filter_counter > 0: continue
 | 
				
			||||||
 | 
					            print "[+] %25s: %02d%% (%d)" % (char, count*100/self.filter_counter, count)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        print "\n[*] Simple Mask statistics..."
 | 
				
			||||||
 | 
					        for (simplemask,count) in sorted(self.stats_simplemasks.iteritems(), key=operator.itemgetter(1), reverse=True):
 | 
				
			||||||
 | 
					            if self.hiderare and not count*100/self.filter_counter > 0: continue
 | 
				
			||||||
 | 
					            print "[+] %25s: %02d%% (%d)" % (simplemask, count*100/self.filter_counter, count)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        print "\n[*] Advanced Mask statistics..."
 | 
				
			||||||
 | 
					        for (advancedmask,count) in sorted(self.stats_advancedmasks.iteritems(), key=operator.itemgetter(1), reverse=True):
 | 
				
			||||||
 | 
					            if count*100/self.filter_counter > 0:
 | 
				
			||||||
 | 
					                print "[+] %25s: %02d%% (%d)" % (advancedmask, count*100/self.filter_counter, count)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if self.output_file:
 | 
				
			||||||
 | 
					                self.output_file.write("%s,%d\n" % (advancedmask,count))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if __name__ == "__main__":
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    header  = "                       _ \n"
 | 
					    header  = "                       _ \n"
 | 
				
			||||||
    header += "     StatsGen 0.0.2   | |\n"  
 | 
					    header += "     StatsGen %s   | |\n"  % VERSION
 | 
				
			||||||
    header += "      _ __   __ _  ___| | _\n"
 | 
					    header += "      _ __   __ _  ___| | _\n"
 | 
				
			||||||
    header += "     | '_ \ / _` |/ __| |/ /\n"
 | 
					    header += "     | '_ \ / _` |/ __| |/ /\n"
 | 
				
			||||||
    header += "     | |_) | (_| | (__|   < \n"
 | 
					    header += "     | |_) | (_| | (__|   < \n"
 | 
				
			||||||
@@ -111,11 +189,18 @@ def main():
 | 
				
			|||||||
    header += "     |_| iphelix@thesprawl.org\n"
 | 
					    header += "     |_| iphelix@thesprawl.org\n"
 | 
				
			||||||
    header += "\n"
 | 
					    header += "\n"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    parser = OptionParser("%prog [options] passwords.txt", version="%prog "+VERSION)
 | 
					    parser = OptionParser("%prog [options] passwords.txt\n\nType --help for more options", version="%prog "+VERSION)
 | 
				
			||||||
    parser.add_option("-l", "--length", dest="length_filter",help="Password length filter.",metavar="8")
 | 
					
 | 
				
			||||||
    parser.add_option("-c", "--charset", dest="char_filter", help="Password charset filter.", metavar="loweralpha")
 | 
					    filters = OptionGroup(parser, "Password Filters")
 | 
				
			||||||
    parser.add_option("-m", "--mask", dest="mask_filter",help="Password mask filter", metavar="stringdigit")
 | 
					    filters.add_option("--minlength", dest="minlength", type="int", metavar="8", help="Minimum password length")
 | 
				
			||||||
    parser.add_option("-o", "--masksoutput", dest="mask_output",help="Generate and save masks db to a file", metavar="masks.csv")
 | 
					    filters.add_option("--maxlength", dest="maxlength", type="int", metavar="8", help="Maximum password length")
 | 
				
			||||||
 | 
					    filters.add_option("--charset", dest="charsets", help="Password charset filter (comma separated)", metavar="loweralpha,numeric")
 | 
				
			||||||
 | 
					    filters.add_option("--simplemask", dest="simplemasks",help="Password mask filter (comma separated)", metavar="stringdigit,allspecial")
 | 
				
			||||||
 | 
					    parser.add_option_group(filters)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    parser.add_option("-o", "--output", dest="output_file",help="Save masks and stats to a file", metavar="password.masks")
 | 
				
			||||||
 | 
					    parser.add_option("--hiderare", action="store_true", dest="hiderare", default=False, help="Hide statistics covering less than 1% of the sample")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    parser.add_option("-q", "--quiet", action="store_true", dest="quiet", default=False, help="Don't show headers.")
 | 
					    parser.add_option("-q", "--quiet", action="store_true", dest="quiet", default=False, help="Don't show headers.")
 | 
				
			||||||
    (options, args) = parser.parse_args()
 | 
					    (options, args) = parser.parse_args()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -127,65 +212,20 @@ def main():
 | 
				
			|||||||
        parser.error("no passwords file specified")
 | 
					        parser.error("no passwords file specified")
 | 
				
			||||||
        exit(1)
 | 
					        exit(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    print "[*] Analyzing passwords: %s" % args[0]
 | 
					    print "[*] Analyzing passwords in [%s]" % args[0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    f = open(args[0],'r')
 | 
					    statsgen = StatsGen()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for password in f:
 | 
					    if not options.minlength   == None: statsgen.minlength   = options.minlength
 | 
				
			||||||
        password = password.strip()
 | 
					    if not options.maxlength   == None: statsgen.maxlength   = options.maxlength
 | 
				
			||||||
        total_counter += 1  
 | 
					    if not options.charsets    == None: statsgen.charsets    = [x.strip() for x in options.charsets.split(',')]
 | 
				
			||||||
 | 
					    if not options.simplemasks == None: statsgen.simplemasks = [x.strip() for x in options.simplemasks.split(',')]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        pass_len = length_check(password)
 | 
					    if options.hiderare: statsgen.hiderare = options.hiderare
 | 
				
			||||||
        mask_set = masks_check(password)
 | 
					 | 
				
			||||||
        char_set = chars_check(password)
 | 
					 | 
				
			||||||
        advmask = advmask_check(password)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (not options.length_filter or str(pass_len) in options.length_filter.split(',')) and \
 | 
					    if options.output_file:
 | 
				
			||||||
           (not options.char_filter or char_set in options.char_filter.split(',')) and \
 | 
					        print "[*] Saving advanced masks and occurrences to [%s]" % options.output_file
 | 
				
			||||||
           (not options.mask_filter or mask_set in options.mask_filter.split(',')):         
 | 
					        statsgen.output_file = open(options.output_file, 'w')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            filter_counter += 1         
 | 
					    statsgen.generate_stats(args[0])
 | 
				
			||||||
 | 
					    statsgen.print_stats()
 | 
				
			||||||
            try: password_length[pass_len] += 1
 | 
					 | 
				
			||||||
            except: password_length[pass_len] = 1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            try: masks[mask_set] += 1
 | 
					 | 
				
			||||||
            except: masks[mask_set] = 1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            try: chars[char_set] += 1
 | 
					 | 
				
			||||||
            except: chars[char_set] = 1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            try: advmasks[advmask] += 1
 | 
					 | 
				
			||||||
            except: advmasks[advmask] = 1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    f.close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    print "[+] Analyzing %d%% (%d/%d) passwords" % (filter_counter*100/total_counter, filter_counter, total_counter)
 | 
					 | 
				
			||||||
    print "    NOTE: Statistics below is relative to the number of analyzed passwords, not total number of passwords"
 | 
					 | 
				
			||||||
    print "\n[*] Line Count Statistics..."
 | 
					 | 
				
			||||||
    for (length,count) in sorted(password_length.iteritems(), key=operator.itemgetter(1), reverse=True):
 | 
					 | 
				
			||||||
        if count*100/filter_counter > 0:
 | 
					 | 
				
			||||||
            print "[+] %25d: %02d%% (%d)" % (length, count*100/filter_counter, count)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    print "\n[*] Charset statistics..."
 | 
					 | 
				
			||||||
    for (char,count) in sorted(chars.iteritems(), key=operator.itemgetter(1), reverse=True):
 | 
					 | 
				
			||||||
        print "[+] %25s: %02d%% (%d)" % (char, count*100/filter_counter, count)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    print "\n[*] Mask statistics..."
 | 
					 | 
				
			||||||
    for (mask,count) in sorted(masks.iteritems(), key=operator.itemgetter(1), reverse=True):
 | 
					 | 
				
			||||||
        print "[+] %25s: %02d%% (%d)" % (mask, count*100/filter_counter, count)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    print "\n[*] Advanced Mask statistics..."
 | 
					 | 
				
			||||||
    for (advmask,count) in sorted(advmasks.iteritems(), key=operator.itemgetter(1), reverse=True):
 | 
					 | 
				
			||||||
        if count*100/filter_counter > 0:
 | 
					 | 
				
			||||||
            print "[+] %25s: %02d%% (%d)" % (advmask, count*100/filter_counter, count)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if options.mask_output:
 | 
					 | 
				
			||||||
        print "\n[*] Saving Mask statistics to %s" % options.mask_output
 | 
					 | 
				
			||||||
        fmask = open(options.mask_output, "w")
 | 
					 | 
				
			||||||
        for (advmask,count) in sorted(advmasks.iteritems(), key=operator.itemgetter(1), reverse=True):
 | 
					 | 
				
			||||||
            fmask.write("%s,%d\n" % (advmask,count))
 | 
					 | 
				
			||||||
        fmask.close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
if __name__ == "__main__":
 | 
					 | 
				
			||||||
    main()
 | 
					 | 
				
			||||||
		Reference in New Issue
	
	Block a user