C ++蛮力攻击功能不返回结果

时间:2018-10-28 02:19:37

标签: c++ for-loop recursion brute-force

所以我目前正在使用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 :(得分:1)

发布的代码的主要缺陷是递归函数返回一个字符串(猜测的密码),而没有向调用者提供明确的密码提示。

按值传递所有字符串,这也是一个潜在的效率问题,但是OP应该受到如下代码片段的担心:

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

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

其中guesss是相同长度的字符串。如果该长度为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 };
}

答案 1 :(得分:0)

即使修改了iterateStr()函数的版本,我也尝试过使用您的代码。我使用了abduct一词,因为它可以更快地进行搜索。逐步调试程序时,我发现找到匹配项后,您的iterateChar()函数未返回。我还注意到传入的string s的长度为6,但是每次迭代中更新的猜测字符串的长度为7。您可能需要单步执行代码并进行检查。

例如,在特定迭代中,s字符串包含:abductguess字符串包含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一词,因为它更容易,更快捷地调试程序,并且得到相同的结果。