/// <summary>
        /// Initialize the experiment with some optional XML configutation data.
        /// </summary>
        public void Initialize(string name, XmlElement xmlConfig)
        {
            _name                = name;
            _populationSize      = XmlUtils.GetValueAsInt(xmlConfig, "PopulationSize");
            _specieCount         = XmlUtils.GetValueAsInt(xmlConfig, "SpecieCount");
            _activationScheme    = ExperimentUtils.CreateActivationScheme(xmlConfig, "Activation");
            _complexityThreshold = XmlUtils.TryGetValueAsInt(xmlConfig, "ComplexityThreshold");
            _description         = XmlUtils.TryGetValueAsString(xmlConfig, "Description");
            _parallelOptions     = ExperimentUtils.ReadParallelOptions(xmlConfig);

            _guesses          = XmlUtils.GetValueAsInt(xmlConfig, "Guesses");
            Hashed            = XmlUtils.TryGetValueAsBool(xmlConfig, "Hashed").HasValue ? XmlUtils.GetValueAsBool(xmlConfig, "Hashed") : false;
            ValidationGuesses = XmlUtils.GetValueAsInt(xmlConfig, "ValidationGuesses");

            // Load the passwords from file
            string pwdfile = XmlUtils.TryGetValueAsString(xmlConfig, "ValidationPasswordFile");

            if (pwdfile != null)
            {
                Console.Write("Loading passwords from [{0}]...", pwdfile);
                if (_passwords == null || _passwords.Count == 0)
                {
                    int?pwLength = XmlUtils.TryGetValueAsInt(xmlConfig, "PasswordLength");
                    if (pwLength.HasValue)
                    {
                        Console.Write("Filtering to {0}-character passwords...", pwLength.Value);
                    }
                    _passwords = PasswordUtil.LoadPasswords(pwdfile, pwLength);
                }
                else
                {
                    Console.WriteLine("WARNING: Not loading passwords for experiment (already set)");
                }
            }
            else
            {
                Console.WriteLine("WARNING: Not loading passwords for experiment (not provided in config file)");
            }
            _eaParams                                          = new NeatEvolutionAlgorithmParameters();
            _eaParams.SpecieCount                              = _specieCount;
            _neatGenomeParams                                  = new NeatGenomeParameters();
            _neatGenomeParams.FeedforwardOnly                  = false;
            _neatGenomeParams.AddNodeMutationProbability       = 0.03;
            _neatGenomeParams.AddConnectionMutationProbability = 0.05;

            // TODO: Load states from XML config file
            // Generates all the valid states in the MC using all viable ASCII characters
            var stateList = new List <string>();

            for (uint i = 32; i < 127; i++)
            {
                stateList.Add(((char)i).ToString());
            }
            stateList.Add(null);
            _states = stateList.ToArray();
            _activationFnLibrary = MarkovActivationFunctionLibrary.CreateLibraryMc(_states);
        }
예제 #2
0
        // Loads all the passwords and the configuration file.
        static void PrepareMarkovModelRuns(string results_file)
        {
            const string PASSWORD_OFFSET = @"../../../passwords/";

            _datasetFilenames = new PasswordDatasetInfo[]
            {
                new PasswordDatasetInfo()
                {
                    Filename = "faithwriters-withcount.txt", Name = "faithwriters"
                },
                new PasswordDatasetInfo()
                {
                    Filename = "myspace-filtered-withcount.txt", Name = "myspace"
                },
                new PasswordDatasetInfo()
                {
                    Filename = "phpbb-withcount.txt", Name = "phpbb"
                },
                new PasswordDatasetInfo()
                {
                    Filename = "rockyou-withcount.txt", Name = "rockyou"
                },
                new PasswordDatasetInfo()
                {
                    Filename = "singles.org-withcount.txt", Name = "singles.org"
                },
//                new PasswordDatasetInfo() { Filename = "morphed_english.txt", Name = "training" },
//                new PasswordDatasetInfo() { Filename = "forced_morphed_english.txt", Name = "testing" }
            };

            Console.WriteLine("Loading all {0} password datasets...", _datasetFilenames.Length);
            _passwords = new Dictionary <string, PasswordInfo> [_datasetFilenames.Length];
            for (int i = 0; i < _passwords.Length; i++)
            {
                Console.WriteLine(_datasetFilenames[i].Name);
                _passwords[i] = PasswordUtil.LoadPasswords(PASSWORD_OFFSET + _datasetFilenames[i].Filename);
            }
            Console.WriteLine("Done.");

            _experiment = new PasswordEvolutionExperiment();

            XmlDocument xmlConfig = new XmlDocument();

            xmlConfig.Load(CONFIG_FILE);
            _experiment.Passwords = _passwords[0];
            _experiment.Initialize("PasswordEvolution", xmlConfig.DocumentElement);

            using (TextWriter writer = new StreamWriter(results_file))
                writer.WriteLine("TrainingSet,TestingSet,Accounts Cracked,Passwords Cracked,% Accounts,% Passwords");
        }
예제 #3
0
        static void Main(string[] args)
        {
            /////////////////////////////////////////////////////////////////////////////////////////
            // Below are some examples of possible experiments and functions you may wish to call. //
            /////////////////////////////////////////////////////////////////////////////////////////


            // Morph an english word dictionary into a password database where 10% of passwords have a number
            // ToyProblemUtil.MorphEnglish(ENGLISH_WORDS, MORPHED_ENGLISH_WORDS);

            // Morph an english word dictionary into a password database where all passwords are at least 8 characters
            // and contain at least one number
            // ToyProblemUtil.MorphEnglish(ENGLISH_WORDS, FORCED_MORPHED_ENGLISH_WORDS, requireDigit: true, minLength: 8);

            // Train on the no-rule morphed english words db and evolve against the morphed english db with
            // the digit and length creation rules enforced.
            // RunExperiment(MORPHED_ENGLISH_WORDS, MORPHED_SEED_FILE, MORPHED_CONFIG_FILE, MORPHED_RESULTS_FILE, false);


            //Train on the phppb dataset and evolve against the rockyou dataset
            //RunExperiment(PHPBB_DATASET, PHPBB_SEED_FILE, PHPBB_CONFIG_FILE, PHPBB_RESULTS_FILE, false);

            //Train on the toyDistribution dataset and evolve against the toyDistribution dataset
            //RunExperiment(TOY_DISTRIBUTION_CONFIG_FILE, false);

            // Print some summary statistics about the distribution of passwords in the two morphed english dictionaries.
            // PasswordUtil.PrintStats(@"../../../passwords/morphed_english.txt"); // no creation rules
            // PasswordUtil.PrintStats(@"../../../passwords/forced_morphed_english.txt"); // digit and length rules

            // Run a really big analysis comparing the first-order Markov model to an 8-layered one.
            // PrepareMarkovModelRuns();
            // Parallel.For(0, _datasetFilenames.Length, i => RunAllMarkovModelPairs(i));

            // Check if a database of hashed passwords contains some common passwords (check for creation rules)
            // MD5HashChecker md5 = new MD5HashChecker(@"../../../passwords/stratfor_hashed.txt");
            // md5.PrintCounts();

            // Load the training set passwords from file
            var passwords = PasswordUtil.LoadPasswords(@"/Users/Wesley/Projects/password-evolution/passwords/morphed_english.txt", 8);

            // Create a Markov model from the passwords. This model will be used
            // as our seed for the evolution.
            int outputs = MarkovFilterCreator.GenerateFirstOrderMarkovFilter(
                @"/Users/Wesley/Projects/password-evolution/models/supervised/morphed_english.xml", passwords);

            Console.WriteLine("Outputs: {0}", outputs);
        }
예제 #4
0
        /// <summary>
        /// Takes in an English dictionary and morphs it so that some words contain numbers, and it looks more password-like.
        /// Note: this probably can be improved by using a Markov model to enforce the minimum length creation rule. It
        /// could also be enhanced with the ability to generate more rules or more realistic passwords.
        /// </summary>
        /// <param name="inFile">The English dictionary file.</param>
        /// <param name="outFile">The file in which to save the morphed dictionary.</param>
        /// <param name="counts">Whether to assume each password is in the dictionary once or to add counts.</param>
        /// <param name="minLength">The minimum length of a password in the dictionary. If a word isn't long enough, it will have number added until it is.</param>
        public static void MorphEnglish(string inFile, string outFile, bool requireDigit = false, bool counts = false, int minLength = 0)
        {
            // Load the passwords
            var english = PasswordUtil.LoadPasswords(inFile);

            // Morph the dictionary either with a required digit creation rule or not, depending on the requireDigit value
            var morphed = requireDigit
                            ? morphEnglish(english, defaultDigitProbs, requiredDigitPositionProbs, minLength) // Use a digit-required creation rule
                            : morphEnglish(english, defaultDigitProbs, defaultDigitPositionProbs, minLength); // No creation rule

            // Write the results to file.
            using (TextWriter writer = new StreamWriter(outFile))
                foreach (var kv in morphed)
                {
                    if (counts)
                    {
                        writer.WriteLine("{0} {1}", kv.Value, kv.Key);
                    }
                    else
                    {
                        writer.WriteLine(kv.Key);
                    }
                }
        }
        /// <summary>
        /// Creates a layered Markov filter. In this model, we have a layer of nodes
        /// for each character in the password. This enables us to capture more information
        /// the distribution than a simple first-order model.
        /// </summary>
        /// <param name="filename">The file in which to save the generated model.</param>
        /// <param name="corpus">The password database from which to build the model.</param>
        /// <param name="layers">The maximum number of layers (password length) to have in this model.</param>
        /// <returns>The number of output nodes for SharpNEAT.</returns>
        public static int GenerateLayeredMarkovFilter(string filename, string corpus, int layers)
        {
            var passwords = PasswordUtil.LoadPasswords(corpus);

            return(GenerateLayeredMarkovFilter(filename, passwords, layers));
        }
        /// <summary>
        /// Creates an adaptive Markov filter where we have a concept of "halting" nodes.
        /// In this model, each letter node contains a probability of transitioning to
        /// a halting node that simply returns the string. This removes the need to
        /// hard-code how long you want your string.
        /// </summary>
        /// <param name="filename">The file in which to save the generated model.</param>
        /// <param name="corpus">The password database from which to build the model.</param>
        /// <returns>The number of output nodes for SharpNEAT.</returns>
        public static int GenerateAdaptiveMarkovFilter(string filename, string corpus)
        {
            var passwords = PasswordUtil.LoadPasswords(corpus);

            return(GenerateAdaptiveMarkovFilter(filename, passwords));
        }
예제 #7
0
        /// <summary>
        /// Trains a Markov model on a the training set of passwords, then evolves it against the target password database
        /// specified in the config file. At the end of the evolution, the champion model is evaluated for a larger number
        /// of guesses.
        /// </summary>
        /// <param name="trainingSetFile">The file containing the passwords from which to build the initial Markov model.</param>
        /// <param name="seedFile">The file to which the initial Markov model will be saved.</param>
        /// <param name="configFile">The file containing all the configuration parameters of the evolution.</param>
        /// <param name="resultsFile">The file to which the results will be saved at each generation.</param>
        /// <param name="validateSeed">If true, the seed model will first be validated against a large number of guesses.</param>
        //private static void RunExperiment(string trainingSetFile, string seedFile, string configFile, string resultsFile, bool validateSeed = false)
        private static void RunExperiment(string configFile, bool validateSeed = false)
        {
            Console.Write("Building Markov model...");

            // Load the XML configuration file
            XmlDocument xmlConfig = new XmlDocument();

            xmlConfig.Load(configFile);
            XmlElement xmlConfigElement = xmlConfig.DocumentElement;

            // Set Training File
            string trainingSetFile = XmlUtils.GetValueAsString(xmlConfigElement, "TrainingFile");

            // Create seedFile
            string seedFile = XmlUtils.GetValueAsString(xmlConfigElement, "SeedFile");

            // Create results file.
            string resultsFile = XmlUtils.GetValueAsString(xmlConfigElement, "ResultsFile");

            Console.WriteLine("\nTraining File: {0}\nSeed File: {1}\nResults File: {2}", trainingSetFile, seedFile, resultsFile);


            // Load the training set passwords from file
            var passwords = PasswordUtil.LoadPasswords(trainingSetFile, 8);

            // Create a Markov model from the passwords. This model will be used
            // as our seed for the evolution.
            int outputs = MarkovFilterCreator.GenerateFirstOrderMarkovFilter(seedFile, passwords);

            // Free up the memory used by the passwords
            passwords = null;

            Console.WriteLine("Done! Outputs: {0}", outputs);

            _experiment             = new PasswordEvolutionExperiment();
            _experiment.OutputCount = outputs;

            // Initialize the experiment with the specifications in the config file.
            _experiment.Initialize("PasswordEvolution", xmlConfig.DocumentElement);

            // Set the passwords to be used by the fitness evaluator.
            // These are the passwords our models will try to guess.
            // PasswordsWithAccounts is the file used for validation. Its account values won't be changed.
            PasswordCrackingEvaluator.Passwords             = _experiment.Passwords;
            PasswordCrackingEvaluator.PasswordsWithAccounts = new Dictionary <string, double>(_experiment.Passwords); // Makes a deep copy

            Console.WriteLine("Loading seed...");

            // Load the seed model that we created at the start of this function
            var seed = _experiment.LoadPopulation(XmlReader.Create(seedFile))[0];

            // Validates the seed model by running it for a large number of guesses
            if (validateSeed)
            {
                Console.WriteLine("Validating seed model...");
                var seedModel = _experiment.CreateGenomeDecoder().Decode(seed);
                ValidateModel(seedModel, _experiment.Passwords, VALIDATION_GUESSES, _experiment.Hashed);
            }

            // Create evolution algorithm using the seed model to initialize the population
            Console.WriteLine("Creating population...");
            _ea = _experiment.CreateEvolutionAlgorithm(seed);

            // Attach an update event handler. This will be called at the end of every generation
            // to log the progress of the evolution (see function logEvolutionProgress below).
            _ea.UpdateEvent += new EventHandler(logEvolutionProgress);
            //_ea.UpdateScheme = new UpdateScheme(1);//.UpdateMode.

            // Setup results file
            using (TextWriter writer = new StreamWriter(resultsFile))
                writer.WriteLine("Generation,Champion Accounts,Champion Uniques,Average Accounts,Average Uniques,Total Accounts,Total Uniques");
            _generationalResultsFile = resultsFile;

            // Start algorithm (it will run on a background thread).
            Console.WriteLine("Starting evolution. Pop size: {0} Guesses: {1}", _experiment.DefaultPopulationSize, _experiment.GuessesPerIndividual);
            _ea.StartContinue();

            // Wait until the evolution is finished.
            while (_ea.RunState == RunState.Running)
            {
                Thread.Sleep(1000);
            }

            // Validate the resulting model.
            var decoder = _experiment.CreateGenomeDecoder();
            var champ   = decoder.Decode(_ea.CurrentChampGenome);

            ValidateModel(champ, _experiment.Passwords, VALIDATION_GUESSES, _experiment.Hashed);
        }
예제 #8
0
        /// <summary>
        /// Trains a Markov model on a the training set of passwords, then evolves it against the target password database
        /// specified in the config file. At the end of the evolution, the champion model is evaluated for a larger number
        /// of guesses.
        /// </summary>
        /// <param name="trainingSetFile">The file containing the passwords from which to build the initial Markov model.</param>
        /// <param name="seedFile">The file to which the initial Markov model will be saved.</param>
        /// <param name="configFile">The file containing all the configuration parameters of the evolution.</param>
        /// <param name="resultsFile">The file to which the results will be saved at each generation.</param>
        /// <param name="validateSeed">If true, the seed model will first be validated against a large number of guesses.</param>
        //private static void RunExperiment(string trainingSetFile, string seedFile, string configFile, string resultsFile, bool validateSeed = false)
        private static void RunExperiment(string configFile, bool validateSeed = false)
        {
            Console.WriteLine("Removing previous champions...");
            string[] oldChampionFiles = Directory.GetFiles(@"../../../experiments/champions/", "*.xml");
            foreach (string oldChampion in oldChampionFiles)
            {
                File.Delete(oldChampion);
            }

            Console.Write("Building Markov model...");

            // Load the XML configuration file
            XmlDocument xmlConfig = new XmlDocument();

            xmlConfig.Load(configFile);
            XmlElement xmlConfigElement = xmlConfig.DocumentElement;

            // Set Training File
            string trainingSetFile = XmlUtils.GetValueAsString(xmlConfigElement, "TrainingFile");

            // Create seedFile
            string seedFile = XmlUtils.GetValueAsString(xmlConfigElement, "SeedFile");

            // Create results file.
            string resultsFile = XmlUtils.GetValueAsString(xmlConfigElement, "ResultsFile");

            Console.WriteLine();
            Console.WriteLine("Training File: {0}", trainingSetFile);
            Console.WriteLine("Seed File: {0}", seedFile);
            Console.WriteLine("Results File: {0}", resultsFile);


            // Load the training set passwords from file
            var passwords = PasswordUtil.LoadPasswords(trainingSetFile, 8);

            // Create a Markov model from the passwords. This model will be used
            // as our seed for the evolution.
            int outputs = MarkovFilterCreator.GenerateFirstOrderMarkovFilter(seedFile, passwords);

            // Free up the memory used by the passwords
            passwords = null;

            Console.WriteLine("Done! Outputs: {0}", outputs);

            _experiment             = new PasswordEvolutionExperiment();
            _experiment.OutputCount = outputs;

            // Initialize the experiment with the specifications in the config file.
            _experiment.Initialize("PasswordEvolution", xmlConfig.DocumentElement);

            // Set the passwords to be used by the fitness evaluator.
            // These are the passwords our models will try to guess.
            // PasswordsWithAccounts is the file used for validation. Its account values won't be changed.
            PasswordCrackingEvaluator.Passwords = _experiment.Passwords;

            Console.WriteLine("Loading seed...");

            // Load the seed model that we created at the start of this function
            var seed = _experiment.LoadPopulation(XmlReader.Create(seedFile))[0];

            // Validates the seed model by running it for a large number of guesses
            if (validateSeed)
            {
                Console.WriteLine("Validating seed model...");
                var seedModel = _experiment.CreateGenomeDecoder().Decode(seed);
                ValidateModel(seedModel, _experiment.Passwords, VALIDATION_GUESSES, _experiment.Hashed);
            }

            // Create evolution algorithm using the seed model to initialize the population
            Console.WriteLine("Creating population...");
            _ea = _experiment.CreateEvolutionAlgorithm(seed);

            // Attach an update event handler. This will be called at the end of every generation
            // to log the progress of the evolution (see function logEvolutionProgress below).
            _ea.UpdateEvent += new EventHandler(logEvolutionProgress);
            //_ea.UpdateScheme = new UpdateScheme(1);//.UpdateMode.

            // Setup results file
            using (TextWriter writer = new StreamWriter(resultsFile))
                writer.WriteLine("Generation,Champion Accounts,Champion Uniques,Average Accounts,Average Uniques,Total Accounts,Total Uniques");
            _generationalResultsFile = resultsFile;

            // Start algorithm (it will run on a background thread).
            Console.WriteLine("Starting evolution. Pop size: {0} Guesses: {1}", _experiment.DefaultPopulationSize, _experiment.GuessesPerIndividual);
            _ea.StartContinue();

            // Wait until the evolution is finished.
            while (_ea.RunState == RunState.Running)
            {
                Thread.Sleep(1000);
            }

            if (VALIDATE_ALL_STAR)
            {
                // Validate the champions of each generation.
                List <MarkovChain> championModels = new List <MarkovChain>();
                string[]           championFiles  = Directory.GetFiles(@"../../../experiments/champions/", "*.xml");
                foreach (string championFile in championFiles)
                {
                    var currentChamp = _experiment.LoadPopulation(XmlReader.Create(championFile))[0];
                    var champModel   = _experiment.CreateGenomeDecoder().Decode(currentChamp);
                    championModels.Add(champModel);
                }
                ValidateForest(championModels, _experiment.Passwords, VALIDATION_GUESSES / championFiles.Length, _experiment.Hashed);

                // Validate a population made up of copies of the final champion.

                /*    List<MarkovChain> championCopyPop = new List<MarkovChain>();
                 *
                 *  Console.WriteLine();
                 *  Console.WriteLine("Validating the final champion population");
                 *  for (int i = 0; i < MAX_GENERATIONS; i++)
                 *  {
                 *      var decoder = _experiment.CreateGenomeDecoder();
                 *      var champ = decoder.Decode(_ea.CurrentChampGenome);
                 *      championCopyPop.Add(champ);
                 *  }
                 *  ValidateAllstarTeam(championCopyPop, _experiment.Passwords, VALIDATION_GUESSES, _experiment.Hashed);
                 */
            }
            else
            {
                // Validate the resulting model.
                var decoder = _experiment.CreateGenomeDecoder();
                var champ   = decoder.Decode(_ea.CurrentChampGenome);
                ValidateModel(champ, _experiment.Passwords, VALIDATION_GUESSES, _experiment.Hashed);
            }
        }