Reputation: 1347
I am creating a Brute Force Algorithm (for educational purposes) on C#, and I have met an error.
My way of bruteforce is like a clock - last character in the string goes up from 0 to last character in a character array set in the beggining of the program, when it reaches the end - resets to 0 and increases the previous character by 1 and so on.
Yet, the code below prints only 0's:
// Array with characters to use in Brute Force Algorithm.
// You can remove or add more characters in this array.
private static char[] fCharList =
{
'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f','g','h','i','j' ,'k','l','m','n','o','p',
'q','r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H','I','J','C','L','M','N','O','P',
'Q','R','S','T','U','V','X','Y','Z','~','!','@','#','$','%','^','&','*','(',')','[',']','{','}','.',',','/','?','\'','|','"',';',':','<','>','\\','=','-','+','`','_'
};
private static String password;
static void Main(string[] args)
{
Console.WriteLine("Enter the password: ");
password = Console.ReadLine();
Bruteforce();
}
// The Bruteforce algorithm
// Goes like a clock cycle: Last index goes from fCharList[0] to fCharList[fCharList.Length - 1]
// then resets and last index -1 increases and so on.
public static String Bruteforce()
{
String currPass = fCharList[0].ToString();
bool foundPass = false;
for (int i = 1; !foundPass; i++)
{
// If there's a need to increase (foundd fCharList[fCharList.Length - 1] in the String)
if (currPass.Contains(fCharList[fCharList.Length - 1]))
{
//If no need to increase the whole length and reset all the characters
if (!(currPass.IndexOf(fCharList[fCharList.Length - 1]) == 0))
{
String updateCurrPass = "";
for (int j = currPass.Length - 1; j >= currPass.IndexOf(fCharList[fCharList.Length - 1]); j--)
{
updateCurrPass += fCharList[0].ToString();
}
currPass.Insert(currPass.IndexOf(fCharList[fCharList.Length - 1]) - 1, fCharList[Array.IndexOf(fCharList, currPass.ElementAt<char>(currPass.IndexOf(fCharList[fCharList.Length - 1]) - 1)) + 1].ToString() + updateCurrPass);
}
}
else // If no cycle ended - continue increasing last "digit"
{
currPass.Insert(currPass.Length - 1, fCharList[Array.IndexOf(fCharList, currPass.ElementAt(currPass.Length - 1)) + 1].ToString());
}
Console.Write(currPass + " ");
}
return "";
}
I tried all the possible issues with the currPass.Insert(currPass.Length - 1, fCharList[Array.IndexOf(fCharList, currPass.ElementAt(currPass.Length - 1)) + 1].ToString());
(as I suspected that the problem might occure in the printing process itself), but with no success.
I also tried to trace the code using breakpoints and paper, still nothing. It would be very pleasing if someone can help me solve this problem.
Edit:
Below, many suggested the updateCurrPass += fCharList[0].ToString();
should rather be updateCurrPass += fCharList[j].ToString();
. I haven't yet checked that option too deep, but to explain better my situation, I want it to work like a clock cycle - when the last digit is the latest character in fCharList
, the previous digit increases and so on. The code mentioned resets the digits that have reached the last character. (So, if the string currPass was "0aa___"
(_ is the last character), it will become 0ab000
) the updateCurrPass
adds the 3 0's, while the rest of the the function increases the a to b.
Upvotes: 1
Views: 578
Reputation: 4515
As noted by @VincentElbertBudiman, you have to use j
in your loop and not 0
. (or maybe not, I'm unsure if I understand well your algorithm)
But there's something more:
You have to note that in C#
, String
s are immutable, meaning currPass.Insert(...)
does nothing in itself, you have to reassign the result like currPass = currPass.Insert(...);
But hey, I think you are overcomplicating the algorithm.
What I would've done:
string currPass = fCharList[0].ToString();
bool found = false;
while(!found)
{
currPass = IncreasePassword(currPass);
found = CheckPass(currPass);
}
With IncreasePassword
:
public static string IncreasePassword(string pass)
{
bool changed = false;
StringBuilder sb = new StringBuilder(pass);
// loop through pass until we change something
// or we reach the end (what comes first)
for(int i = 0; i < pass.Length && !changed; i++)
//for(int i = pass.Length - 1; i >= 0 && !changed; i--)
{
int index = Array.IndexOf(fCharList, sb[i]);
// if current char can be increased
if(index < fCharList.Length - 1)
{
// if we have __012 then we'll go on 00112
// so here we replace the left __ with 00
for(int j = i - 1; j >= 0 && sb[j] == fCharList[fCharList.Length - 1]; j--)
//for(int j = i + 1; j < sb.Length && sb[j] == fCharList[fCharList.Length - 1]; j++)
{
sb[j] = fCharList[0];
}
// and here we increase the current char
sb[i] = fCharList[index + 1];
changed = true;
}
}
// if we didn't change anything, it means every char were '_'
// so we start with a fresh new full-of-0 string
if(!changed)
{
return "".PadLeft(pass.Length + 1, fCharList[0]);
}
return sb.ToString();
}
Explanations
This will work from left to right the following way:
Say our fCharList
is { '0','1','2' }
for simplifications.
We'll have:
0
1
2
00
10
20
01
11
21
02
12
22
000
100
200
010
110
210
020
....
Test results
This is what it gives with reversed inputs (as my solution goes the other way around) from Weeble's suggestions:
Input Output
0 1
1 2
P Q
_ 00
00 10
_0 01
__CBA 00DBA
____ 00000
Please note that your fCharList
is broken as there's a C
instead of K
!
Upvotes: 1
Reputation: 17930
While there are specific problems pointed out by the other answers, may I suggest that your broader problem is that you're trying to do too much at once? You may well be capable of writing this whole algorithm in one piece and tweaking it until it works, but it's both very hard to do this and hard to have confidence in the end that it's correct. You will find it easier to break down the algorithm into smaller functions and test those individually to confirm they do what you expect.
For example, you could break out the part of the algorithm that works out "given the last password I checked, what is the next password in sequence to consider"? This is the core of the algorithm, and it can be separated from the work of iterating through all the possible passwords and testing them against the current one. And it is much easier to test! For example, you can use test data like this:
Input Expected output
"0" "1"
"1" "2"
"P" "Q"
"_" "00"
"00" "01"
"0_" "10"
"ABC__" "ABD00"
"____" "00000"
When you find out that your function doesn't give the right answer for some or all of these tests, you have a much smaller and more specific job to do to figure out what's wrong than trying to debug the whole algorithm at once.
Upvotes: 0
Reputation: 309
Did you think because you assign updateCurrPass like this ? :
for (int j = currPass.Length - 1; j >= currPass.IndexOf(fCharList[fCharList.Length - 1]); j--)
{
updateCurrPass += fCharList[0].ToString();
}
I think it should be involving j or something :
for (int j = currPass.Length - 1; j >= currPass.IndexOf(fCharList[fCharList.Length - 1]); j--)
{
updateCurrPass += fCharList[j].ToString();
}
Added code :
This below code will do nothing because the function will return the function (instead of changing the object passed by parameters), you should add currPass = currPass.Insert(...) as noted by @Rafalon
else // If no cycle ended - continue increasing last "digit"
{
currPass.Insert(currPass.Length - 1, fCharList[Array.IndexOf(fCharList, currPass.ElementAt(currPass.Length - 1)) + 1].ToString());
}
Use this instead :
else // If no cycle ended - continue increasing last "digit"
{
currPass = currPass.Insert(currPass.Length - 1, fCharList[Array.IndexOf(fCharList, currPass.ElementAt(currPass.Length - 1)) + 1].ToString());
}
Upvotes: 1