Алгоритм перебора только для печати 0 - PullRequest
0 голосов
/ 07 мая 2018

Я создаю алгоритм грубой силы (в образовательных целях) на C # и обнаружил ошибку.

Мой способ грубой силы подобен часам - последний символ в строке повышается с 0 до последнего символа в массиве символов, заданном в начале программы, когда он достигает конца - сбрасывается в 0 и увеличивает предыдущий символ на 1 и т. д.

Тем не менее, код ниже печатает только 0:

// 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 "";
    }

Я перепробовал все возможные проблемы с currPass.Insert(currPass.Length - 1, fCharList[Array.IndexOf(fCharList, currPass.ElementAt(currPass.Length - 1)) + 1].ToString()); (так как подозревал, что проблема может возникнуть в самом процессе печати), но безуспешно.

Я также пытался отследить код, используя точки останова и бумагу, но ничего не вышло. Было бы очень приятно, если бы кто-нибудь помог мне решить эту проблему.

Изменить: Ниже многие предположили, что updateCurrPass += fCharList[0].ToString(); должно быть updateCurrPass += fCharList[j].ToString();. Я еще не проверил эту опцию слишком глубоко, но чтобы лучше объяснить мою ситуацию, я хочу, чтобы она работала как тактовый цикл - когда последняя цифра является последним символом в fCharList, предыдущая цифра увеличивается и так далее. Упомянутый код сбрасывает цифры, которые достигли последнего символа. (Таким образом, если строка currPass была "0aa___" (_ является последним символом), она станет 0ab000) updateCurrPass добавляет 3 0, в то время как остальная часть функции увеличивает a до b.

Ответы [ 3 ]

0 голосов
/ 07 мая 2018

Как отмечает @ VincentElbertBudiman , вы должны использовать j в цикле, а не 0. (а может и нет, я не уверен, хорошо ли я понимаю ваш алгоритм)

Но есть кое-что еще:

Вы должны заметить, что в C#, String s являются неизменными, что означает, что currPass.Insert(...) ничего не делает само по себе, вы должны переназначить результат как currPass = currPass.Insert(...);

Но, эй, я думаю, вы слишком усложняете алгоритм.

Что бы я сделал:

string currPass = fCharList[0].ToString();
bool found = false;
while(!found)
{
    currPass = IncreasePassword(currPass);
    found = CheckPass(currPass);
}

С 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();
}

Живой пример .


Пояснения

Это будет работать слева направо следующим образом:
Скажите, что fCharList это { '0','1','2' } для упрощений.
У нас будет:

0
1
2
00
10
20
01
11
21
02
12
22
000
100
200
010
110
210
020
....

Результаты испытаний

Это то, что он дает с обратными входами (как мое решение идет наоборот) из предложений Уибла :

Input        Output
0            1
1            2
P            Q
_            00
00           10
_0           01
__CBA        00DBA
____         00000

Обратите внимание, что ваш fCharList сломан , поскольку вместо K!

есть C
0 голосов
/ 07 мая 2018

Хотя в других ответах есть конкретные проблемы, могу ли я предположить, что ваша более широкая проблема заключается в том, что вы пытаетесь сделать слишком много одновременно? Вполне возможно, что вы сможете написать весь этот алгоритм одним куском и настраивать его до тех пор, пока он не заработает, но сделать это очень сложно, и в конце концов трудно быть уверенным в его правильности. Вам будет проще разбить алгоритм на более мелкие функции и протестировать их по отдельности, чтобы убедиться, что они выполняют то, что вы ожидаете.

Например, вы могли бы выделить часть алгоритма, которая работает «учитывая последний пароль, который я проверил, какой следующий пароль в последовательности следует учитывать»? Это ядро ​​алгоритма, и его можно отделить от работы по итерации всех возможных паролей и проверке их на соответствие текущему. И это гораздо проще проверить! Например, вы можете использовать тестовые данные следующим образом:

Input             Expected output
"0"               "1"
"1"               "2"
"P"               "Q"
"_"               "00"
"00"              "01"
"0_"              "10"
"ABC__"           "ABD00"
"____"            "00000"

Когда вы обнаружите, что ваша функция не дает правильного ответа для некоторых или всех этих тестов, вам нужно выполнить гораздо меньшую и более конкретную работу, чтобы выяснить, в чем дело, чем пытаться отладить весь алгоритм сразу .

0 голосов
/ 07 мая 2018

Вы думали, потому что назначаете updateCurrPass вот так? :

for (int j = currPass.Length - 1; j >= currPass.IndexOf(fCharList[fCharList.Length - 1]); j--)
{
     updateCurrPass += fCharList[0].ToString();
}

Я думаю, что это должно включать j или что-то:

for (int j = currPass.Length - 1; j >= currPass.IndexOf(fCharList[fCharList.Length - 1]); j--)
{
     updateCurrPass += fCharList[j].ToString();
}

Добавлен код:

Этот приведенный ниже код ничего не сделает, потому что функция вернет функцию (вместо изменения объекта, переданного параметрами), вы должны добавить currPass = currPass.Insert (...), как отмечено @ 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());
}

Используйте это вместо:

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());
}
...