Функция атаки C ++ Brute Force не возвращает результаты - PullRequest
0 голосов
/ 28 октября 2018

, так что в настоящее время я работаю над проектом злоумышленника грубой силы на C ++.Мне удалось заставить это работать, но одна проблема, с которой я сталкиваюсь, состоит в том, что если программе действительно удалось получить правильное предположение, функция все еще продолжается.Я думаю, что проблема в том, что программа не может вернуть предположение.Посмотрите на мой код: (извините за беспорядок, кстати, я не настолько опытен в C ++ - раньше я программировал на Python / JS.)

#include <iostream>
#include <cstdlib>
#include <string>

std::string chars = "abcdefghijklmnopqrstuvwxyz";
std::string iterateStr(std::string s, std::string guess, int pos);
std::string crack(std::string s);
std::string iterateChar(std::string s, std::string guess, int pos);

int main() {

    crack("bb");

    return EXIT_SUCCESS;
}

// this function iterates through the letters of the alphabet
std::string iterateChar(std::string s, std::string guess, int pos) {
    for(int i = 0; i < chars.length(); i++) {
        // sets the char to a certain letter from the chars variable
        guess[pos] = chars[i];
        // if the position reaches the end of the string
        if(pos == s.length()) {
            if(guess.compare(s) == 0) {
                break;
            } 
        } else {
            // else, recursively call the function
            std::cout << guess << " : " << s << std::endl;
            iterateChar(s, guess, pos+1);
        }
    }
    return guess;
}

// this function iterates through the characters in the string
std::string iterateStr(std::string s, std::string guess, int pos) {
    for(int i = 0; i < s.length(); i++) {
        guess = iterateChar(s, guess, i);
        if(s.compare(guess) == 0) {
            return guess;
        }
    }
    return guess;
}

std::string crack(std::string s) {
    int len = s.length();
    std::string newS(len, 'a');
    std::string newGuess;
    newGuess = iterateStr(s, newS, 0);
    return newGuess;
}

Редактировать: Обновлен код.

Ответы [ 2 ]

0 голосов
/ 29 октября 2018

Основной недостаток размещенного кода состоит в том, что рекурсивная функция возвращает строку (предполагаемый пароль) без четкого указания вызывающей стороне, что пароль был найден.

Передача всех строк по значению также является потенциальной проблемой эффективности, но ОП должны беспокоиться из-за таких отрывков:

guess[pos] = chars[i];  // 'chars' contains the alphabet

if(pos == s.length()) {
    if(guess.compare(s) == 0) {
        break;
    }
} 

Где guess и s - строки одинаковой длины. Если эта длина равна 2 (последний пример OP), guess[2] выходит за границы, но последующий вызов guess.compare(s) будет сравнивать только два символа "внутри".

Цикл внутри iterateStr тоже ничего полезного не делает, а параметр pos не используется.

Вместо того, чтобы исправлять эту попытку, лучше переписать ее с нуля

#include <iostream>
#include <string>
#include <utility>

// Sets up the variable and start the brute force search
template <class Predicate>
auto crack(std::string const &src, size_t length, Predicate is_correct)
    -> std::pair<bool, std::string>;

// Implements the brute force search in a single recursive function. It uses a
// lambda to check the password, instead of passing it directly
template <class Predicate>
bool recursive_search(std::string const &src, std::string &guess, size_t pos,
                      Predicate is_correct);

// Helper function, for testing purpouse
void test_cracker(std::string const &alphabet, std::string const &password);

int main()
{
    test_cracker("abcdefghijklmnopqrstuvwxyz", "dance");
    test_cracker("abcdefghijklmnopqrstuvwxyz ", "go on");
    test_cracker("0123456789", "42");
    test_cracker("0123456789", "one");     // <- 'Password not found.'
}

void test_cracker(std::string const &alphabet, std::string const &password)
{
    auto [found, pwd] = crack(alphabet, password.length(),
        [&password] (std::string const &guess) { return guess == password; });

    std::cout << (found ? pwd : "Password not found.") << '\n';
}

// Brute force recursive search 
template <class Predicate>
bool recursive_search(std::string const &src, std::string &guess, size_t pos,
                      Predicate is_correct)
{
    if ( pos + 1 == guess.size() )
    {
        for (auto const ch : src)
        {
            guess[pos] = ch;

            if ( is_correct(guess) )
                return true;
        }     
    }
    else
    {
        for (auto const ch : src)
        {
            guess[pos] = ch;

            if ( recursive_search(src, guess, pos + 1, is_correct) )
                return true;
        }              
    }
    return false;
}

template <class Predicate>
auto crack(std::string const &src, size_t length, Predicate is_correct)
    -> std::pair<bool, std::string>
{
    if ( src.empty() )
        return { length == 0 && is_correct(src), src };

    std::string guess(length, src[0]);

    return { recursive_search(src, guess, 0, is_correct), guess };
}
0 голосов
/ 28 октября 2018

Я пробовал ваш код даже с измененной версией вашей функции iterateStr().Я использовал слово abduct, так как его быстрее искать.Проходя через отладчик, я заметил, что ваша функция iterateChar() не возвращалась, когда совпадение было найдено.Также я заметил, что длина передаваемого string s была 6, однако строка предположения, которая обновляется на каждой итерации, имела длину 7.Возможно, вы захотите пройтись по своему коду и проверить это.

Например, на определенной итерации строка s содержит: abduct, но строка guess содержит aaaabjz, затем на следующей итерации строка guess содержит aaaabkz.Это может быть вашей проблемой, касающейся того, почему цикл или функция продолжается, даже если вы считаете, что совпадение найдено.

Разница в длине здесь может быть вашим виновником.

Также при переходе через измененныйкод:

for ( size_t i = 0; i < s.length(); i++ ) {
    guess = iterCh( s, guess, i );
    std::cout << "in the iterStr loop\n";
    if ( guess.compare( s ) == 0 ) {
        return guess;
    }
}
return guess;

в вашей функции iterateStr() рекурсия всегда вызывает guess = iterCh( s, guess, i );, а код никогда не печатает in the iterStr loop\n";.Ваша iterateChar функция завершает всю строку или последовательность символов, никогда не находя и не возвращая совпадение.Я даже попробовал слово abs, так как легче и быстрее пройти через отладчик, и я получаю такие же результаты.

...