Exemple #1
0
 public void Add(string session, string hash, string text, HashingMethod method)
 {
     using (var reader = ExecReader (SELECT_COLLISION_ID, hash.ToSQLiteParam ("@hash"))) {
         if (!reader.HasRows) {
             ExecNonQuery (
                 INSERT_COLLISION,
                 hash.ToSQLiteParam ("@hash"),
                 text.ToSQLiteParam ("@text"),
                 session.ToSQLiteParam ("@session"),
                 method.Algorithm.ToString ().ToSQLiteParam ("@type")
             );
         }
         else {
             using (var reader2 = ExecReader (SELECT_SESSION_ID, session.ToSQLiteParam ("@session"))) {
                 if (!reader2.HasRows) {
                     ExecNonQuery (
                         INSERT_COLLISION_FROM_SESSION,
                         session.ToSQLiteParam ("@session"),
                         hash.ToSQLiteParam ("@hash")
                     );
                 }
             }
         }
     }
 }
Exemple #2
0
 public void Add(string session, string hash, string text, HashingMethod method)
 {
     using (var reader = ExecReader(SELECT_COLLISION_ID, hash.ToSQLiteParam("@hash"))) {
         if (!reader.HasRows)
         {
             ExecNonQuery(
                 INSERT_COLLISION,
                 hash.ToSQLiteParam("@hash"),
                 text.ToSQLiteParam("@text"),
                 session.ToSQLiteParam("@session"),
                 method.Algorithm.ToString().ToSQLiteParam("@type")
                 );
         }
         else
         {
             using (var reader2 = ExecReader(SELECT_SESSION_ID, session.ToSQLiteParam("@session"))) {
                 if (!reader2.HasRows)
                 {
                     ExecNonQuery(
                         INSERT_COLLISION_FROM_SESSION,
                         session.ToSQLiteParam("@session"),
                         hash.ToSQLiteParam("@hash")
                         );
                 }
             }
         }
     }
 }
        public static void Run(string[] hashes, HashingMethod method, string alphabet, int length = 6)
        {
            #if LIBNOTIFYNET
            Notification.Send ("Hashlecter", "Started bruteforce attack.", 5000);
            #endif

            // Stopwatch for measuring time
            var watch = Stopwatch.StartNew ();

            if (!MainClass.options.silent) {

                // Update_Screen task
                var update = Task.Factory.StartNew (() => Update_Screen (watch));

                // Update_Stats task
                var update_avg = Task.Factory.StartNew (Update_Stats);
            }

            string output;
            var alphabet_first = alphabet.First ();
            var alphabet_last = alphabet.Last ();

            for (var ihash = 0; ihash < hashes.Length; ihash++) {

                // Skip comments
                if (hashes [ihash].StartsWith ("#"))
                    continue;

                current_hash = hashes [ihash];

                // Incremental bruteforce
                if (MainClass.options.incremental) {

                    // Calculate maximum
                    for (var i = 1; i <= length; i++)
                        bruteforce_max += Math.Pow (i, alphabet.Length);

                    for (var curlen = 1; curlen <= length; ++curlen) {

                        // Initialize buffer
                        var accum = new StringBuilder (new String (alphabet_first, curlen));

                        while (true) {

                            ++generated;
                            ++avg_tmp;
                            var value = accum.ToString ();
                            current_str = value;

                            var success = method.CheckHash (current_hash, value, out output);
                            if (success) {
                                ++cracked;
                                MainClass.db.Add (MainClass.session, current_hash, value, method);

                                #if LIBNOTIFYNET
                                var _libnotifynet_format = string.Format ("Successfully cracked {0} hash:\n{1}\nValue was: {2}", method.Name, current_hash, output);
                                Notification.Send ("Hashlecter", _libnotifynet_format, 7500, 250, 100);
                                #endif

                                done = true;
                                goto end;
                            }

                            if (value.All (val => val == alphabet_last))
                                break;

                            // TODO: Parallelize this
                            for (var i = curlen - 1; i >= 0; --i) {
                                if (accum [i] != alphabet_last) {
                                    accum [i] = alphabet [alphabet.IndexOf (accum [i]) + 1];
                                    break;
                                } else
                                    accum [i] = alphabet_first;
                            }
                        }
                    }
                }

            // Fixed-length bruteforce
            else {

                    // Calculated maximum
                    bruteforce_max = Math.Pow (length, alphabet.Length);

                    // Initialize buffer
                    var accum = new StringBuilder (new String (alphabet_first, length));

                    while (true) {

                        ++generated;
                        ++avg_tmp;
                        var value = accum.ToString ();
                        current_str = value;

                        var success = method.CheckHash (current_hash, value, out output);
                        if (success) {
                            ++cracked;
                            MainClass.db.Add (MainClass.session, current_hash, value, method);

                            #if LIBNOTIFYNET
                            var _libnotifynet_format = string.Format ("Successfully cracked {0} hash:\n{1}\nValue was: {2}", method.Name, current_hash, output);
                            Notification.Send ("Hashlecter", _libnotifynet_format, 7500, 250, 100);
                            #endif

                            done = true;
                            goto end;
                        }

                        if (value.All (val => val == alphabet_last))
                            break;

                        // TODO: Parallelize this
                        for (var i = length - 1; i >= 0; --i) {
                            if (accum [i] != alphabet_last) {
                                accum [i] = alphabet [alphabet.IndexOf (accum [i]) + 1];
                                break;
                            } else
                                accum [i] = alphabet_first;
                        }
                    }
                }

                end: {}
            }

            watch.Stop ();

            // Display the correct stats after exiting
            if (!MainClass.options.silent) {

                Update_Screen (watch, force: true);
            }
        }
Exemple #4
0
        public static void Run(string[] hashes, HashingMethod method, string dictionary_path)
        {
                        #if LIBNOTIFYNET
            Notification.Send("Hashlecter", "Started dictionary attack.", 5000);
                        #endif

            // Dictionary buffer
            string[] dict = new string[BUFFER_SZ];

            // Stopwatch for measuring time
            var watch = Stopwatch.StartNew();

            if (!MainClass.options.silent)
            {
                // Update_Screen task
                var update = Task.Factory.StartNew(() => Update_Screen(watch));

                // Update_Stats task
                var update_avg = Task.Factory.StartNew(Update_Stats);
            }

            // Open dictionary file for reading
            using (var fdict = File.OpenRead(dictionary_path))
                using (var reader = new StreamReader(fdict)) {
                    // Iterate over all hashes in the array
                    for (var i = 0; i < hashes.Length; i++)
                    {
                        // Skip comments
                        if (hashes[i].StartsWith("#"))
                        {
                            continue;
                        }

                        current_hash = hashes[i];

                        // Check if there is still something in the dictionary to read
                        while (reader.BaseStream.Position < reader.BaseStream.Length)
                        {
                            // Iterate over all values in [0..BUFFER_SZ]
                            for (var j = 0; j < BUFFER_SZ; j++)
                            {
                                // Add the next line from the dictionary to the buffer
                                dict[j] = reader.ReadLine();

                                // Increment the loaded variable if the line is valid
                                if (dict[j] != null)
                                {
                                    dict[j] = dict[j].Replace("\r", "");
                                    loaded++;
                                }
                            }

                            var breakout = false;

                            // Use parallel processing to iterate over all entries in the dictionary buffer
                            Parallel.ForEach <string> (dict, (dict_entry, loopstate_inner) => {
                                // Get the current hash
                                var hash = hashes[i];

                                // Create a variable for storing the output (if valid)
                                string output;

                                // Get the current dictionary entry
                                // (for the Update_Screen task)
                                dict_current = dict_entry;

                                // Try to collide the hashes
                                var success = method.CheckHash(hash, dict_entry, out output);

                                // Increment the statistically relevant variables
                                ++processed;
                                ++avg_tmp;

                                // Check if the collision succeeded
                                if (success)
                                {
                                    // Increment the amount of successfully collided hashes
                                    // (for the Update_Screen task)
                                    ++cracked;

                                    // Add the collision to the database
                                    MainClass.db.Add(MainClass.session, hash, output, method);

                                                                #if LIBNOTIFYNET
                                    var _libnotifynet_format = string.Format("Successfully cracked {0} hash:\n{1}\nValue was: {2}", method.Name, hash, output);
                                    Notification.Send("Hashlecter", _libnotifynet_format, 7500, 250, 100);
                                                                #endif

                                    if (!MainClass.options.exp_single_cont)
                                    {
                                        // Break out of the loop
                                        breakout = true;
                                        loopstate_inner.Stop();
                                    }
                                }
                            });

                            if (breakout)
                            {
                                break;
                            }
                        }

                        // Reset the dictionary position to 0
                        // for processing the next hash
                        reader.BaseStream.Position = 0;

                        // Reset the
                        loaded = 0;
                    }

                    // We're done!
                    // Tell all tasks to stop
                    done = true;
                    watch.Stop();
                }

            // Display the correct stats after exiting
            if (!MainClass.options.silent)
            {
                Update_Screen(watch, force: true);
            }
        }
Exemple #5
0
        //
        // This is an experimental method.
        // Enable using the --exp-lazy-eval switch
        //
        public static void RunLazy(string[] hashes, HashingMethod method, string dictionary_path)
        {
            // Dictionary buffer
            IEnumerable <string> dict;

            // Stopwatch for measuring time
            var watch = Stopwatch.StartNew();

            if (!MainClass.options.silent)
            {
                // Update_Screen task
                var update = Task.Factory.StartNew(() => Update_Screen(watch));

                // Update_Stats task
                var update_avg = Task.Factory.StartNew(Update_Stats);
            }

            // Lazy approach
            var dictionary       = File.ReadLines(dictionary_path);
            var dictionary_pos   = 0;
            var dictionary_count = dictionary.Count();

            // Iterate over all hashes in the array
            for (var i = 0; i < hashes.Length; i++)
            {
                // Skip comments
                if (hashes[i].StartsWith("#"))
                {
                    continue;
                }

                current_hash = hashes[i];

                //while (dictionary_pos <= dictionary_count) {
                while (dictionary_pos < dictionary_count)
                {
                    dict            = dictionary.Skip(dictionary_pos).Take(BUFFER_SZ);
                    dictionary_pos += BUFFER_SZ;
                    loaded          = dictionary_pos;

                    var breakout = false;

                    // Use parallel processing to iterate over all entries in the dictionary buffer
                    Parallel.ForEach <string> (dict, (dict_entry, loopstate_inner) => {
                        // Get the current hash
                        var hash = hashes[i];

                        // Create a variable for storing the output (if valid)
                        string output;

                        // Get the current dictionary entry
                        // (for the Update_Screen task)
                        dict_current = dict_entry;

                        // Try to collide the hashes
                        var success = method.CheckHash(hash, dict_entry, out output);

                        // Increment the statistically relevant variables
                        ++processed;
                        ++avg_tmp;

                        // Check if the collision succeeded
                        if (success)
                        {
                            // Increment the amount of successfully collided hashes
                            // (for the Update_Screen task)
                            ++cracked;

                            // Add the collision to the database
                            MainClass.db.Add(MainClass.session, hash, output, method);

                            // Break out of the loop
                            breakout = true;
                            loopstate_inner.Stop();
                        }
                    });

                    if (breakout)
                    {
                        break;
                    }
                }

                dictionary_pos = 0;
            }

            done = true;
            watch.Stop();

            // Display the correct stats after exiting
            if (!MainClass.options.silent)
            {
                Update_Screen(watch, force: true);
            }
        }
Exemple #6
0
        /// <summary>
        /// The entry point of the program, where the program control starts and ends.
        /// </summary>
        /// <param name="args">The command-line arguments.</param>
        public static void Main(string[] args)
        {
            foreach (var x in args)
            {
                Console.WriteLine(x);
            }

            // Create a hashset for storing the hashing methods
            methods = new HashSet <HashingMethod> {
                                #if MD5
                HashingMethod.New <hMD5> (),
                HashingMethod.New <hMD5_Double> (),
                HashingMethod.New <hMD5_Salted> (),
                HashingMethod.New <hMD5_Salted2> (),
                HashingMethod.New <hMD5_MyBB> (),
                                #endif

                                #if SHA1
                HashingMethod.New <hSHA1> (),
                HashingMethod.New <hSHA1_Double> (),
                                #endif

                                #if SHA256
                HashingMethod.New <hSHA256> (),
                HashingMethod.New <hSHA256_Double> (),
                                #endif

                                #if SHA384
                HashingMethod.New <hSHA384> (),
                                #endif

                                #if SHA512
                HashingMethod.New <hSHA512> (),
                                #endif

                                #if RIPEMD160
                HashingMethod.New <hRIPEMD160> (),
                                #endif

                                #if WHIRLPOOL
                HashingMethod.New <hWhirlpool> (),
                                #endif

                                #if JHASH
                HashingMethod.New <hJHash> (),
                                #endif
            };

            // Parse command-line arguments using libArgument
            options = ArgumentParser.Parse <Options> (args);

            // Use wizard if lecter was started directly
            options.wizard |= args.Length == 0;

            // Get or create a session identifier
            session = string.IsNullOrEmpty(options.session) ? GenerateSession() : options.session;

            // Connect to the SQLite database
            db = Database.Factory.CreateSQLite(SQLITE_DB);

            // Return if the user just wanted to make
            // sure that the db got created
            if (options.create_db)
            {
                Environment.Exit(0);
            }

            // Display help
            else if (options.help)
            {
                PreHelp();
                ArgumentParser.Help();
                Help();
                Environment.Exit(0);
            }

            // Show all the cracked hashes
            else if (options.show)
            {
                db.Show(string.IsNullOrEmpty(options.session) ? string.Empty : session);
                Environment.Exit(0);
            }

            // Call the magician
            else if (options.wizard)
            {
                Wizard();
            }

            // Null-check the method
            if (string.IsNullOrEmpty(options.method))
            {
                // Fall back to MD5
                options.method = "md5";
            }

            // Get the method used for cracking the hashes
            var method = methods.FirstOrDefault(m => m.Name == options.method.ToLowerInvariant());

            // Check if the cracking method is valid
            if (method == null || method == default(HashingMethod))
            {
                Console.Error.WriteLine("Please specify a valid hashing method.");
                Console.Error.WriteLine("Run lecter --help to get a list of valid hashing methods.");
                Environment.Exit(0);
            }

            // Check if we need to generate a hash
            if (options.gen)
            {
                // Read input string from -i/--input argument
                if (!string.IsNullOrEmpty(options.input_file))
                {
                    Console.WriteLine(method.Hash(options.input_file));
                }

                // Hash an empty string if no string is given
                else
                {
                    Console.WriteLine(method.Hash(string.Empty));
                }

                // Exit
                Environment.Exit(0);
            }

            string[] input_hashes = null;

            // Grab input from stdin
            if (options.input_stdin)
            {
                input_hashes = FromStdin();
            }

            // Grab input from file
            else if (!string.IsNullOrEmpty(options.input_file))
            {
                input_hashes = FromFile(options.input_file);
            }

            // Perform dictionary attack
            if (!string.IsNullOrEmpty(options.input_dict))
            {
                // Null-check the input file
                if (input_hashes == null)
                {
                    Console.Error.WriteLine("No input was specified.");
                    Environment.Exit(0);
                }

                // Experimental lazy evaluation
                if (options.exp_lazy_eval)
                {
                    DictionaryAttack.RunLazy(input_hashes, method, options.input_dict);
                }

                // Stable evaluation
                else
                {
                    DictionaryAttack.Run(input_hashes, method, options.input_dict);
                }
            }

            // Perform bruteforce attack
            else
            {
                // Null-check the input file
                if (input_hashes == null)
                {
                    Console.Error.WriteLine("No input was specified.");
                    Environment.Exit(0);
                }

                string default_alphabet =
                    BruteforceAttack.NUMERIC +
                    BruteforceAttack.LOWER_ALPHANUMERIC;

                if (options.len == 0)
                {
                    options.len = 6;
                }

                if (!string.IsNullOrEmpty(options.alphabet))
                {
                    // Build alphabet
                    var alphabet = options.alphabet
                                   .Replace("$$", "\0")
                                   .Replace("$n", BruteforceAttack.NUMERIC)
                                   .Replace("$l", BruteforceAttack.LOWER_ALPHANUMERIC)
                                   .Replace("$u", BruteforceAttack.UPPER_ALPHANUMERIC)
                                   .Replace("$s+", BruteforceAttack.SPECIAL_ADVANCED)
                                   .Replace("$s", BruteforceAttack.SPECIAL_BASIC)
                                   .Replace("\0", "$")
                                   .ToList();
                    options.alphabet = new string (alphabet.ToArray());
                }
                else
                {
                    options.alphabet = default_alphabet;
                }

                BruteforceAttack.Run(input_hashes, method, options.alphabet, options.len);
            }

            if (!options.silent)
            {
                db.Show(session);

                if (options.wizard)
                {
                    Console.Read();
                }
            }

                        #if LIBNOTIFYNET
            Task.Factory.StartNew(() => {
                NotificationManager.Instance.ShutdownWait();
            }).Wait(7500);
                        #endif
        }
        public static void Run(string[] hashes, HashingMethod method, string dictionary_path)
        {
            #if LIBNOTIFYNET
            Notification.Send ("Hashlecter", "Started dictionary attack.", 5000);
            #endif

            // Dictionary buffer
            string[] dict = new string[BUFFER_SZ];

            // Stopwatch for measuring time
            var watch = Stopwatch.StartNew ();

            if (!MainClass.options.silent) {

                // Update_Screen task
                var update = Task.Factory.StartNew (() => Update_Screen (watch));

                // Update_Stats task
                var update_avg = Task.Factory.StartNew (Update_Stats);
            }

            // Open dictionary file for reading
            using (var fdict = File.OpenRead (dictionary_path))
            using (var reader = new StreamReader (fdict)) {

                // Iterate over all hashes in the array
                for (var i = 0; i < hashes.Length; i++) {

                    // Skip comments
                    if (hashes[i].StartsWith ("#"))
                        continue;

                    current_hash = hashes[i];

                    // Check if there is still something in the dictionary to read
                    while (reader.BaseStream.Position < reader.BaseStream.Length) {

                        // Iterate over all values in [0..BUFFER_SZ]
                        for (var j = 0; j < BUFFER_SZ; j++) {

                            // Add the next line from the dictionary to the buffer
                            dict[j] = reader.ReadLine ();

                            // Increment the loaded variable if the line is valid
                            if (dict[j] != null) {
                                dict[j] = dict[j].Replace ("\r", "");
                                loaded++;
                            }
                        }

                        var breakout = false;

                        // Use parallel processing to iterate over all entries in the dictionary buffer
                        Parallel.ForEach<string> (dict, (dict_entry, loopstate_inner) => {

                            // Get the current hash
                            var hash = hashes[i];

                            // Create a variable for storing the output (if valid)
                            string output;

                            // Get the current dictionary entry
                            // (for the Update_Screen task)
                            dict_current = dict_entry;

                            // Try to collide the hashes
                            var success = method.CheckHash (hash, dict_entry, out output);

                            // Increment the statistically relevant variables
                            ++processed;
                            ++avg_tmp;

                            // Check if the collision succeeded
                            if (success) {

                                // Increment the amount of successfully collided hashes
                                // (for the Update_Screen task)
                                ++cracked;

                                // Add the collision to the database
                                MainClass.db.Add (MainClass.session, hash, output, method);

                                #if LIBNOTIFYNET
                                var _libnotifynet_format = string.Format ("Successfully cracked {0} hash:\n{1}\nValue was: {2}", method.Name, hash, output);
                                Notification.Send ("Hashlecter", _libnotifynet_format, 7500, 250, 100);
                                #endif

                                if (!MainClass.options.exp_single_cont) {

                                    // Break out of the loop
                                    breakout = true;
                                    loopstate_inner.Stop ();
                                }
                            }
                        });

                        if (breakout)
                            break;
                    }

                    // Reset the dictionary position to 0
                    // for processing the next hash
                    reader.BaseStream.Position = 0;

                    // Reset the
                    loaded = 0;
                }

                // We're done!
                // Tell all tasks to stop
                done = true;
                watch.Stop ();
            }

            // Display the correct stats after exiting
            if (!MainClass.options.silent) {

                Update_Screen (watch, force: true);
            }
        }
        //
        // This is an experimental method.
        // Enable using the --exp-lazy-eval switch
        //
        public static void RunLazy(string[] hashes, HashingMethod method, string dictionary_path)
        {
            // Dictionary buffer
            IEnumerable<string> dict;

            // Stopwatch for measuring time
            var watch = Stopwatch.StartNew ();

            if (!MainClass.options.silent) {

                // Update_Screen task
                var update = Task.Factory.StartNew (() => Update_Screen (watch));

                // Update_Stats task
                var update_avg = Task.Factory.StartNew (Update_Stats);
            }

            // Lazy approach
            var dictionary = File.ReadLines (dictionary_path);
            var dictionary_pos = 0;
            var dictionary_count = dictionary.Count ();

            // Iterate over all hashes in the array
            for (var i = 0; i < hashes.Length; i++) {

                // Skip comments
                if (hashes[i].StartsWith ("#"))
                    continue;

                current_hash = hashes[i];

                //while (dictionary_pos <= dictionary_count) {
                while (dictionary_pos < dictionary_count) {

                    dict = dictionary.Skip (dictionary_pos).Take (BUFFER_SZ);
                    dictionary_pos += BUFFER_SZ;
                    loaded = dictionary_pos;

                    var breakout = false;

                    // Use parallel processing to iterate over all entries in the dictionary buffer
                    Parallel.ForEach<string> (dict, (dict_entry, loopstate_inner) => {

                        // Get the current hash
                        var hash = hashes[i];

                        // Create a variable for storing the output (if valid)
                        string output;

                        // Get the current dictionary entry
                        // (for the Update_Screen task)
                        dict_current = dict_entry;

                        // Try to collide the hashes
                        var success = method.CheckHash (hash, dict_entry, out output);

                        // Increment the statistically relevant variables
                        ++processed;
                        ++avg_tmp;

                        // Check if the collision succeeded
                        if (success) {

                            // Increment the amount of successfully collided hashes
                            // (for the Update_Screen task)
                            ++cracked;

                            // Add the collision to the database
                            MainClass.db.Add (MainClass.session, hash, output, method);

                            // Break out of the loop
                            breakout = true;
                            loopstate_inner.Stop ();
                        }
                    });

                    if (breakout)
                        break;
                }

                dictionary_pos = 0;

            }

            done = true;
            watch.Stop ();

            // Display the correct stats after exiting
            if (!MainClass.options.silent) {

                Update_Screen (watch, force: true);
            }
        }
        public static void Run(string[] hashes, HashingMethod method, string alphabet, int length = 6)
        {
                        #if LIBNOTIFYNET
            Notification.Send("Hashlecter", "Started bruteforce attack.", 5000);
                        #endif

            // Stopwatch for measuring time
            var watch = Stopwatch.StartNew();

            if (!MainClass.options.silent)
            {
                // Update_Screen task
                var update = Task.Factory.StartNew(() => Update_Screen(watch));

                // Update_Stats task
                var update_avg = Task.Factory.StartNew(Update_Stats);
            }

            string output;
            var    alphabet_first = alphabet.First();
            var    alphabet_last  = alphabet.Last();

            for (var ihash = 0; ihash < hashes.Length; ihash++)
            {
                // Skip comments
                if (hashes [ihash].StartsWith("#"))
                {
                    continue;
                }

                current_hash = hashes [ihash];

                // Incremental bruteforce
                if (MainClass.options.incremental)
                {
                    // Calculate maximum
                    for (var i = 1; i <= length; i++)
                    {
                        bruteforce_max += Math.Pow(i, alphabet.Length);
                    }

                    for (var curlen = 1; curlen <= length; ++curlen)
                    {
                        // Initialize buffer
                        var accum = new StringBuilder(new String(alphabet_first, curlen));

                        while (true)
                        {
                            ++generated;
                            ++avg_tmp;
                            var value = accum.ToString();
                            current_str = value;

                            var success = method.CheckHash(current_hash, value, out output);
                            if (success)
                            {
                                ++cracked;
                                MainClass.db.Add(MainClass.session, current_hash, value, method);

                                                                #if LIBNOTIFYNET
                                var _libnotifynet_format = string.Format("Successfully cracked {0} hash:\n{1}\nValue was: {2}", method.Name, current_hash, output);
                                Notification.Send("Hashlecter", _libnotifynet_format, 7500, 250, 100);
                                                                #endif

                                done = true;
                                goto end;
                            }

                            if (value.All(val => val == alphabet_last))
                            {
                                break;
                            }

                            // TODO: Parallelize this
                            for (var i = curlen - 1; i >= 0; --i)
                            {
                                if (accum [i] != alphabet_last)
                                {
                                    accum [i] = alphabet [alphabet.IndexOf(accum [i]) + 1];
                                    break;
                                }
                                else
                                {
                                    accum [i] = alphabet_first;
                                }
                            }
                        }
                    }
                }

                // Fixed-length bruteforce
                else
                {
                    // Calculated maximum
                    bruteforce_max = Math.Pow(length, alphabet.Length);

                    // Initialize buffer
                    var accum = new StringBuilder(new String(alphabet_first, length));

                    while (true)
                    {
                        ++generated;
                        ++avg_tmp;
                        var value = accum.ToString();
                        current_str = value;

                        var success = method.CheckHash(current_hash, value, out output);
                        if (success)
                        {
                            ++cracked;
                            MainClass.db.Add(MainClass.session, current_hash, value, method);

                                                        #if LIBNOTIFYNET
                            var _libnotifynet_format = string.Format("Successfully cracked {0} hash:\n{1}\nValue was: {2}", method.Name, current_hash, output);
                            Notification.Send("Hashlecter", _libnotifynet_format, 7500, 250, 100);
                                                        #endif

                            done = true;
                            goto end;
                        }

                        if (value.All(val => val == alphabet_last))
                        {
                            break;
                        }

                        // TODO: Parallelize this
                        for (var i = length - 1; i >= 0; --i)
                        {
                            if (accum [i] != alphabet_last)
                            {
                                accum [i] = alphabet [alphabet.IndexOf(accum [i]) + 1];
                                break;
                            }
                            else
                            {
                                accum [i] = alphabet_first;
                            }
                        }
                    }
                }

                end : {}
            }


            watch.Stop();

            // Display the correct stats after exiting
            if (!MainClass.options.silent)
            {
                Update_Screen(watch, force: true);
            }
        }