Ejemplo n.º 1
0
        public IPAddress GetRandomMaliciousIp()
        {
            int       randIndex = (int)StrongRandomNumberGenerator.Get32Bits(_maliciousIpAddresses.Count);
            IPAddress address   = _maliciousIpAddresses[randIndex];

            return(_maliciousIpAddresses[randIndex]);
        }
Ejemplo n.º 2
0
        public IPAddress GetNewRandomBenignIp()
        {
            IpAddressDebugInfo debugInfo;

            if (StrongRandomNumberGenerator.GetFraction() < _experimentalConfiguration.FractionOfBenignIPsBehindProxies)
            {
                lock (_proxyAddressLock)
                {
                    if (_currentProxyAddress == null || ++_numberOfClientsBehindTheCurrentProxy >=
                        _experimentalConfiguration.ProxySizeInUniqueClientIPs)
                    {
                        _currentProxyAddress                  = new IPAddress(StrongRandomNumberGenerator.Get32Bits());
                        debugInfo                             = GetIpAddressDebugInfo(_currentProxyAddress);
                        debugInfo.IsPartOfProxy               = true;
                        debugInfo.UsedByBenignUsers           = true;
                        _numberOfClientsBehindTheCurrentProxy = 0;
                        return(_currentProxyAddress);
                    }
                    else
                    {
                        return(_currentProxyAddress);
                    }
                }
            }
            else
            {
                IPAddress address = new IPAddress(StrongRandomNumberGenerator.Get32Bits());
                _ipAddresssesInUseByBenignUsers.Add(address);
                debugInfo = GetIpAddressDebugInfo(address);
                debugInfo.UsedByBenignUsers = true;
                return(address);
            }
        }
Ejemplo n.º 3
0
        public void GenerateAttackersIps()
        {
            List <IPAddress> listOfIpAddressesInUseByBenignUsers = _ipAddresssesInUseByBenignUsers.ToList();
            uint             numberOfOverlappingIps = (uint)
                                                      (_experimentalConfiguration.NumberOfIpAddressesControlledByAttacker *
                                                       _experimentalConfiguration.FractionOfMaliciousIPsToOverlapWithBenign);
            uint i;

            for (i = 0; i < numberOfOverlappingIps && listOfIpAddressesInUseByBenignUsers.Count > 0; i++)
            {
                int                randIndex = (int)StrongRandomNumberGenerator.Get32Bits(listOfIpAddressesInUseByBenignUsers.Count);
                IPAddress          address   = listOfIpAddressesInUseByBenignUsers[randIndex];
                IpAddressDebugInfo debugInfo = GetIpAddressDebugInfo(address);
                lock (debugInfo)
                {
                    debugInfo.UsedByAttackers = true;
                }
                _maliciousIpAddresses.Add(address);
                listOfIpAddressesInUseByBenignUsers.RemoveAt(randIndex);
            }
            for (; i < _experimentalConfiguration.NumberOfIpAddressesControlledByAttacker; i++)
            {
                IPAddress          address   = new IPAddress(StrongRandomNumberGenerator.Get32Bits());
                IpAddressDebugInfo debugInfo = GetIpAddressDebugInfo(address);
                lock (debugInfo)
                {
                    debugInfo.UsedByAttackers = true;
                }
                _maliciousIpAddresses.Add(address);
            }
        }
Ejemplo n.º 4
0
        public int DistributedStepAsync([FromRoute] string element, [FromQuery] int?heightOfLadderInRungs)
        {
            FilterArray shard = GetShard(element);
            // Get the set of rungs
            List <int> rungIndexes = shard.GetIndexesAssociatedWithAnElement(element, heightOfLadderInRungs ?? MaxLadderHeight).ToList();
            // Select the subset of rungs that have value zero (that are above the element in the ladder)
            List <int> rungsAbove = rungIndexes.Where(rung => !shard[rung]).ToList();

            // Identify an element of the array to set
            if (rungsAbove.Count > 0)
            {
                // If there are rungs with value value zero/false (rungs above the element), pick one at random
                shard.SetBitToOne(
                    rungsAbove[(int)(StrongRandomNumberGenerator.Get32Bits((uint)rungsAbove.Count))]);
            }
            else
            {
                // Set an average of one element by picking two random elements, each of which should have p=0.5
                // of being zero/false, and setting them to 1/true regardless of their previous value.
                FilterClient.AssignRandomBit(1);
                FilterClient.AssignRandomBit(1);
            }

            // Clear an average of one element by picking two random elements, each of which should have p=0.5
            // of being one/true, and setting them to 0/false regardless of their previous value.
            FilterClient.AssignRandomBit(0);
            FilterClient.AssignRandomBit(0);

            // Return the height of the ladder before the step
            return(rungIndexes.Count - rungsAbove.Count);
        }
        /// <summary>
        /// Add a typo to a password for simulating user typo errors
        /// </summary>
        /// <param name="originalPassword">The original password to add a typo to</param>
        /// <returns>The password modified to contain a typo</returns>
        public static string AddTypoToPassword(string originalPassword)
        {
            // Adding a character will meet the edit distance def. of typo, though if simulating systems that weigh
            // different typos differently one might want to create a variety of typos here
            const string typoAlphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ./";

            return(originalPassword + typoAlphabet[(int)StrongRandomNumberGenerator.Get32Bits(typoAlphabet.Length)]);
        }
Ejemplo n.º 6
0
        public int Step(string key, int?heightOfLadderInRungs = null)
        {
            List <int> rungs      = GetIndexesAssociatedWithAnElement(key, heightOfLadderInRungs).ToList();
            List <int> rungsAbove = rungs.Where(rung => !base[rung]).ToList();

            int indexOfElementToSet = (rungsAbove.Count > 0) ?
                                      rungsAbove[(int)(StrongRandomNumberGenerator.Get32Bits((uint)rungsAbove.Count))] :
                                      GetIndexOfRandomBitOfDesiredValue(false);

            int indexOfElementToClear = GetIndexOfRandomBitOfDesiredValue(true);

            SwapBits(indexOfElementToSet, indexOfElementToClear);

            return(rungs.Count - rungsAbove.Count);
        }
Ejemplo n.º 7
0
        /// <summary>
        /// When one Adds an element to a binomial sketch, a random bit among the subset of k that are currently 0 (false)
        /// will be set to 1 (true).
        /// To ensure roughly half the bits remain zero at all times, a random index from the subset of all k bits that
        /// are currently 1 (true) will be set to 0 (false).
        /// </summary>
        /// <param name="key">The element to add to the set.</param>
        /// <param name="heightOfLadderInRungs">Set if using a ladder shorter than the default for this sketch</param>
        /// <returns>Of the bits at the indices for the given element, the number of bits that were set to 1 (true)
        /// before the Step operation.  The maximum possible value to be returned, if all bits were already
        /// set to 1 (true) would be MaxLadderHeightInRungs.  If an element has not been seen before, the expected (average)
        /// result is MaxLadderHeightInRungs/2, but will vary with the binomial distribution.</returns>
        public int Step(string key, int?heightOfLadderInRungs = null)
        {
            // Get the set of rungs
            List <int> rungs = GetIndexesAssociatedWithAnElement(key, heightOfLadderInRungs).ToList();
            // Select the subset of rungs that have value zero (that are above the element in the ladder)
            List <int> rungsAbove = rungs.Where(rung => !base[rung]).ToList();

            // Identify an element of the array to set
            int indexOfElementToSet = (rungsAbove.Count > 0) ?
                                      // If there are rungs with value value zero/false (rungs above the element), pick one at random
                                      rungsAbove[(int)(StrongRandomNumberGenerator.Get32Bits((uint)rungsAbove.Count))] :
                                      // otherwise, pick an element with value zero/false from the entire array
                                      GetIndexOfRandomBitOfDesiredValue(false);

            // Identify an index to clear from the entire array (selected from those elements with value 1/true)
            int indexOfElementToClear = GetIndexOfRandomBitOfDesiredValue(true);

            // Swap the values of element to be set with the element to be cleared
            SwapBits(indexOfElementToSet, indexOfElementToClear);

            // Return the height of the ladder before the step
            return(rungs.Count - rungsAbove.Count);
        }
Ejemplo n.º 8
0
        public SimulatedLoginAttempt BenignLoginAttempt(DateTime eventTimeUtc)
        {
            lock (ScheduledBenignAttempts)
            {
                if (ScheduledBenignAttempts.Count > 0 &&
                    ScheduledBenignAttempts.First().TimeOfAttemptUtc < eventTimeUtc)
                {
                    SimulatedLoginAttempt result = ScheduledBenignAttempts.First();
                    ScheduledBenignAttempts.Remove(result);
                    return(result);
                }
            }

            string mistake = "";
            SimulatedUserAccount account = _simAccounts.BenignAccountSelector.GetItemByWeightedRandom();

            string cookie;

            if (account.Cookies.Count == 0 ||
                (account.Cookies.Count < _experimentalConfiguration.MaxCookiesPerUserAccount && StrongRandomNumberGenerator.GetFraction() > _experimentalConfiguration.ChanceOfCoookieReUse))
            {
                cookie = StrongRandomNumberGenerator.Get64Bits().ToString();
                account.Cookies.Add(cookie);
            }
            else
            {
                cookie = account.Cookies.ToArray()[(int)StrongRandomNumberGenerator.Get32Bits(account.Cookies.Count)];
            }

            IPAddress clientIp;

            if (account.ClientAddresses.Count == 0 ||
                (account.ClientAddresses.Count < _experimentalConfiguration.MaxIpPerUserAccount && StrongRandomNumberGenerator.GetFraction() < _experimentalConfiguration.ChanceOfIpReUse))
            {
                account.ClientAddresses.Add(clientIp = _ipPool.GetNewRandomBenignIp());
            }
            else
            {
                clientIp = account.ClientAddresses.ToArray()[(int)StrongRandomNumberGenerator.Get32Bits(account.ClientAddresses.Count)];
            }

            string password = account.Password;

            if (StrongRandomNumberGenerator.GetFraction() < _experimentalConfiguration.ChanceOfLongRepeatOfStalePassword)
            {
                string newPassword = _simPasswords.GetPasswordFromWeightedDistribution();
                _userAccountController.SetPassword(account, newPassword, account.Password);
                mistake += "StalePassword";

                lock (ScheduledBenignAttempts)
                {
                    double   additionalMistakes = 0;
                    DateTime currentTimeUtc     = eventTimeUtc;
                    for (additionalMistakes = 1; additionalMistakes < _experimentalConfiguration.LengthOfLongRepeatOfOldPassword; additionalMistakes++)
                    {
                        currentTimeUtc = currentTimeUtc.AddSeconds(_experimentalConfiguration.MinutesBetweenLongRepeatOfOldPassword);
                        ScheduledBenignAttempts.Add(new SimulatedLoginAttempt(
                                                        account, password, false, false, clientIp, cookie, mistake, currentTimeUtc));
                    }
                    for (uint correctLogins = 1; correctLogins < _experimentalConfiguration.LengthOfLongRepeatOfOldPassword; correctLogins++)
                    {
                        currentTimeUtc = currentTimeUtc.AddSeconds(_experimentalConfiguration.MinutesBetweenLongRepeatOfOldPassword);
                        ScheduledBenignAttempts.Add(new SimulatedLoginAttempt(
                                                        account, newPassword, false, false, clientIp, cookie, mistake, currentTimeUtc));
                    }
                }
            }

            if (StrongRandomNumberGenerator.GetFraction() < _experimentalConfiguration.ChanceOfBenignPasswordTypo)
            {
                mistake += "Typo";
                lock (ScheduledBenignAttempts)
                {
                    double additionalMistakes = 0;
                    while (StrongRandomNumberGenerator.GetFraction() < _experimentalConfiguration.ChanceOfRepeatTypo)
                    {
                        ScheduledBenignAttempts.Add(new SimulatedLoginAttempt(
                                                        account, AddTypoToPassword(password), false, false, clientIp, cookie, mistake,
                                                        eventTimeUtc.AddSeconds(_experimentalConfiguration.DelayBetweenRepeatBenignErrorsInSeconds * ++additionalMistakes)));
                    }
                    ScheduledBenignAttempts.Add(new SimulatedLoginAttempt(
                                                    account, password, false, false, clientIp, cookie, "", eventTimeUtc.AddSeconds(
                                                        _experimentalConfiguration.DelayBetweenRepeatBenignErrorsInSeconds * (1 + additionalMistakes))));
                }
                password = AddTypoToPassword(password);
            }

            if (StrongRandomNumberGenerator.GetFraction() < _experimentalConfiguration.ChanceOfAccidentallyUsingAnotherAccountPassword)
            {
                mistake += "WrongPassword";

                lock (ScheduledBenignAttempts)
                {
                    double additionalMistakes = 0;
                    while (StrongRandomNumberGenerator.GetFraction() < _experimentalConfiguration.ChanceOfRepeatUseOfPasswordFromAnotherAccount)
                    {
                        ScheduledBenignAttempts.Add(new SimulatedLoginAttempt(
                                                        account, _simPasswords.GetPasswordFromWeightedDistribution(), false, false, clientIp, cookie,
                                                        mistake, eventTimeUtc.AddSeconds(_experimentalConfiguration.DelayBetweenRepeatBenignErrorsInSeconds * ++additionalMistakes)));
                    }
                    ScheduledBenignAttempts.Add(new SimulatedLoginAttempt(
                                                    account, password, false, false, clientIp, cookie, "", eventTimeUtc.AddSeconds(
                                                        _experimentalConfiguration.DelayBetweenRepeatBenignErrorsInSeconds * (additionalMistakes + 1))));
                }

                password = _simPasswords.GetPasswordFromWeightedDistribution();
            }

            if (StrongRandomNumberGenerator.GetFraction() < _experimentalConfiguration.ChanceOfBenignAccountNameTypoResultingInAValidUserName)
            {
                mistake += "WrongAccountName";

                lock (ScheduledBenignAttempts)
                {
                    double additionalMistakes = 0;
                    while (StrongRandomNumberGenerator.GetFraction() < _experimentalConfiguration.ChanceOfRepeatWrongAccountName)
                    {
                        ScheduledBenignAttempts.Add(new SimulatedLoginAttempt(
                                                        _simAccounts.GetBenignAccountAtRandomUniform(), password, false, false, clientIp, cookie, mistake, eventTimeUtc.AddSeconds(
                                                            _experimentalConfiguration.DelayBetweenRepeatBenignErrorsInSeconds * ++additionalMistakes)));
                    }
                    ScheduledBenignAttempts.Add(new SimulatedLoginAttempt(
                                                    account, password, false, false, clientIp, cookie, "", eventTimeUtc.AddSeconds(
                                                        _experimentalConfiguration.DelayBetweenRepeatBenignErrorsInSeconds * (additionalMistakes + 1))));

                    account = _simAccounts.GetBenignAccountAtRandomUniform();
                }
            }

            return(new SimulatedLoginAttempt(account, password, false, false, clientIp, cookie, mistake, eventTimeUtc));
        }
Ejemplo n.º 9
0
        public static string AddTypoToPassword(string originalPassword)
        {
            const string typoAlphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ./";

            return(originalPassword + typoAlphabet[(int)StrongRandomNumberGenerator.Get32Bits(typoAlphabet.Length)]);
        }
Ejemplo n.º 10
0
 public SimulatedUserAccount GetMaliciousAccountAtRandomUniform()
 {
     return(AttackerAccounts[(int)StrongRandomNumberGenerator.Get32Bits(AttackerAccounts.Count)]);
 }
Ejemplo n.º 11
0
 public SimulatedUserAccount GetBenignAccountAtRandomUniform()
 {
     return(BenignAccounts[(int)StrongRandomNumberGenerator.Get32Bits(BenignAccounts.Count)]);
 }
Ejemplo n.º 12
0
 public int GetRandomShardIndex()
 {
     return((int)StrongRandomNumberGenerator.Get32Bits(NumberOfShards));
 }
Ejemplo n.º 13
0
 /// <summary>
 /// Assign the value of either zero or one to a randomly-selected bit of the filter array.
 /// </summary>
 /// <param name="value">The value to be assigned.  Passing 0 causes a value 0 (false) to be stored
 /// and passing any other value causes a one (true) to be stored in the randomly-selected bit.</param>
 public void AssignRandomBit(int value)
 {
     AssignBit((int)StrongRandomNumberGenerator.Get32Bits((uint)BitArray.Length), value != 0);
 }
Ejemplo n.º 14
0
 /// <summary>
 /// Set a randomly-selected bit of the filter array to one.
 /// </summary>
 public void SetRandomBitToOne()
 {
     SetBitToOne((int)StrongRandomNumberGenerator.Get32Bits((uint)BitArray.Length));
 }
Ejemplo n.º 15
0
 /// <summary>
 /// Clear a randomly-selected bit of the filter array to zero.
 /// </summary>
 public void ClearRandomBitToZero()
 {
     ClearBitToZero((int)StrongRandomNumberGenerator.Get32Bits((uint)BitArray.Length));
 }
        /// <summary>
        /// Get a benign login attempt to simulate
        /// </summary>
        /// <returns></returns>
        public SimulatedLoginAttempt BenignLoginAttempt(DateTime eventTimeUtc)
        {
            // If there is a benign login attempt already scheduled to occur by now,
            // send it instaed
            lock (ScheduledBenignAttempts)
            {
                if (ScheduledBenignAttempts.Count > 0 &&
                    ScheduledBenignAttempts.First().TimeOfAttemptUtc < eventTimeUtc)
                {
                    SimulatedLoginAttempt result = ScheduledBenignAttempts.First();
                    ScheduledBenignAttempts.Remove(result);
                    return(result);
                }
            }

            string mistake = "";
            //1. Pick a user at random
            SimulatedUserAccount account = _simAccounts.BenignAccountSelector.GetItemByWeightedRandom();

            //2. Deal with cookies
            string cookie;

            // Add a new cookie if there are no cookies, or with if we haven't reached the max number of cookies and lose a roll of the dice
            if (account.Cookies.Count == 0 ||
                (account.Cookies.Count < _experimentalConfiguration.MaxCookiesPerUserAccount && StrongRandomNumberGenerator.GetFraction() > _experimentalConfiguration.ChanceOfCoookieReUse))
            {
                // We'll use the decimal represenation of a 64-bit unsigned integer as our cookie
                cookie = StrongRandomNumberGenerator.Get64Bits().ToString();
                account.Cookies.Add(cookie);
            }
            else
            {
                // Use one of the user's existing cookies selected at random
                cookie = account.Cookies.ToArray()[(int)StrongRandomNumberGenerator.Get32Bits(account.Cookies.Count)];
            }

            //Console.WriteLine("The user currently has " + account.Cookies.Count + " cookies.  Using: " + cookie);

            //3. Choose an IP address for the login
            // 1/3 of times login with the primary IP address, otherwise, choose an IP randomly from the benign IP pool
            IPAddress clientIp;

            if (account.ClientAddresses.Count == 0 ||
                (account.ClientAddresses.Count < _experimentalConfiguration.MaxIpPerUserAccount && StrongRandomNumberGenerator.GetFraction() < _experimentalConfiguration.ChanceOfIpReUse))
            {
                // Use a new IP for the user
                account.ClientAddresses.Add(clientIp = _ipPool.GetNewRandomBenignIp());
            }
            else
            {
                // Use one of the user's existing IP Addresses selected at random
                clientIp = account.ClientAddresses.ToArray()[(int)StrongRandomNumberGenerator.Get32Bits(account.ClientAddresses.Count)];
            }

            string password = account.Password;

            //
            // Add benign failures

            // An automated client begins a string of login attempts using an old (stale) password
            if (StrongRandomNumberGenerator.GetFraction() < _experimentalConfiguration.ChanceOfLongRepeatOfStalePassword)
            {
                // To cause this client to be out of date, we'll change the password here.
                string newPassword = _simPasswords.GetPasswordFromWeightedDistribution();
                _userAccountController.SetPassword(account, newPassword, account.Password);
                mistake += "StalePassword";

                // Schedule all the future failed attempts a fixed distance aparat
                lock (ScheduledBenignAttempts)
                {
                    double   additionalMistakes = 0;
                    DateTime currentTimeUtc     = eventTimeUtc;
                    for (additionalMistakes = 1; additionalMistakes < _experimentalConfiguration.LengthOfLongRepeatOfOldPassword; additionalMistakes++)
                    {
                        currentTimeUtc = currentTimeUtc.AddSeconds(_experimentalConfiguration.MinutesBetweenLongRepeatOfOldPassword);
                        ScheduledBenignAttempts.Add(new SimulatedLoginAttempt(
                                                        account, password, false, false, clientIp, cookie, mistake, currentTimeUtc));
                    }
                    for (uint correctLogins = 1; correctLogins < _experimentalConfiguration.LengthOfLongRepeatOfOldPassword; correctLogins++)
                    {
                        currentTimeUtc = currentTimeUtc.AddSeconds(_experimentalConfiguration.MinutesBetweenLongRepeatOfOldPassword);
                        ScheduledBenignAttempts.Add(new SimulatedLoginAttempt(
                                                        account, newPassword, false, false, clientIp, cookie, mistake, currentTimeUtc));
                    }
                }
            }

            // The benign user may mistype her password causing a typo
            if (StrongRandomNumberGenerator.GetFraction() < _experimentalConfiguration.ChanceOfBenignPasswordTypo)
            {
                mistake += "Typo";
                // Typos tend to come in clusters, and are hopefully followed by a correct login
                // Add additional typos to the schedule of future benign attempts and then a submission of the correct password
                lock (ScheduledBenignAttempts)
                {
                    double additionalMistakes = 0;
                    while (StrongRandomNumberGenerator.GetFraction() < _experimentalConfiguration.ChanceOfRepeatTypo)
                    {
                        ScheduledBenignAttempts.Add(new SimulatedLoginAttempt(
                                                        account, AddTypoToPassword(password), false, false, clientIp, cookie, mistake,
                                                        eventTimeUtc.AddSeconds(_experimentalConfiguration.DelayBetweenRepeatBenignErrorsInSeconds * ++additionalMistakes)));
                    }
                    // Add a correct login after the string of typos
                    ScheduledBenignAttempts.Add(new SimulatedLoginAttempt(
                                                    account, password, false, false, clientIp, cookie, "", eventTimeUtc.AddSeconds(
                                                        _experimentalConfiguration.DelayBetweenRepeatBenignErrorsInSeconds * (1 + additionalMistakes))));
                }
                // Put the typo into the password for the first typo failure, to be returned by this function.
                password = AddTypoToPassword(password);
            }

            // The benign user may mistakenly use a password for another of her accounts, which we draw from same distribution
            // we used to generate user account passwords
            if (StrongRandomNumberGenerator.GetFraction() < _experimentalConfiguration.ChanceOfAccidentallyUsingAnotherAccountPassword)
            {
                mistake += "WrongPassword";

                // Choices of the wrong account password may come in clusters, and are hopefully followed by a correct login
                // Add additional typos to the schedule of future benign attempts and then a submission of the correct password
                lock (ScheduledBenignAttempts)
                {
                    double additionalMistakes = 0;
                    while (StrongRandomNumberGenerator.GetFraction() < _experimentalConfiguration.ChanceOfRepeatUseOfPasswordFromAnotherAccount)
                    {
                        ScheduledBenignAttempts.Add(new SimulatedLoginAttempt(
                                                        account, _simPasswords.GetPasswordFromWeightedDistribution(), false, false, clientIp, cookie,
                                                        mistake, eventTimeUtc.AddSeconds(_experimentalConfiguration.DelayBetweenRepeatBenignErrorsInSeconds * ++additionalMistakes)));
                    }
                    // Add a correct login after mistakes
                    ScheduledBenignAttempts.Add(new SimulatedLoginAttempt(
                                                    account, password, false, false, clientIp, cookie, "", eventTimeUtc.AddSeconds(
                                                        _experimentalConfiguration.DelayBetweenRepeatBenignErrorsInSeconds * (additionalMistakes + 1))));
                }

                // Make the current request have the wrong password
                password = _simPasswords.GetPasswordFromWeightedDistribution();
            }

            // The benign user may mistype her account name, and land on someone else's account name
            if (StrongRandomNumberGenerator.GetFraction() < _experimentalConfiguration.ChanceOfBenignAccountNameTypoResultingInAValidUserName)
            {
                mistake += "WrongAccountName";

                // Choices of the wrong account password may come in clusters, and are hopefully followed by a correct login
                // Add additional typos to the schedule of future benign attempts and then a submission of the correct password
                lock (ScheduledBenignAttempts)
                {
                    double additionalMistakes = 0;
                    while (StrongRandomNumberGenerator.GetFraction() < _experimentalConfiguration.ChanceOfRepeatWrongAccountName)
                    {
                        ScheduledBenignAttempts.Add(new SimulatedLoginAttempt(
                                                        _simAccounts.GetBenignAccountAtRandomUniform(), password, false, false, clientIp, cookie, mistake, eventTimeUtc.AddSeconds(
                                                            _experimentalConfiguration.DelayBetweenRepeatBenignErrorsInSeconds * ++additionalMistakes)));
                    }
                    // Add a correct login after mistakes
                    ScheduledBenignAttempts.Add(new SimulatedLoginAttempt(
                                                    account, password, false, false, clientIp, cookie, "", eventTimeUtc.AddSeconds(
                                                        _experimentalConfiguration.DelayBetweenRepeatBenignErrorsInSeconds * (additionalMistakes + 1))));

                    // Make the current request have the wrong account name
                    account = _simAccounts.GetBenignAccountAtRandomUniform();
                }
            }

            return(new SimulatedLoginAttempt(account, password, false, false, clientIp, cookie, mistake, eventTimeUtc));
        }