我如何并行化这种蛮力攻击算法

时间:2019-05-02 19:29:18

标签: c++ parallel-processing

我是攻读计算机工程专业的一年级学生,我们的任务是创建一个蛮力算法,该算法将破解用户提供的密码,我决定再加倍努力并使用并行编程,现在这是代码没有并行编程:

EDIT:OLD CODE WAS HERE

它可以工作,但是我已经尝试过以多种方式实施OpenMP,要么我遇到了无法解决的非常混乱的比赛条件,要么就无法正常工作,我只是想问一些提示,我知道这是由我来完成任务。

编辑:这是新代码

#include <omp.h>
#include <iostream>
#include <ctime>
#include <string>
#include <stdio.h>




using namespace std;
void crackPassword(string pass);
long long int attempt;
clock_t start_t, end_t;
string test2[3];
string alphabet;
static int digit[7], alphabetSet = 1;

string test;

int main() {
    string password;

    std::cout << "Enter the password to crack : ";
    cin >> password;

    crackPassword(password);
    std::cout << "The number of attempts : " << attempt << endl;

    return 0;
}
void alphabets(int alphabetSet) {

    switch (alphabetSet) {
    case 1: alphabet = "-0123456789";
          break;
    case 2: alphabet = "-abcdefghijklmnopqrstuvwxyz";
          break;
    case 3: alphabet = "-ABCDEFGHIJKLMNOPQRSTUVWXYZ";
          break;
    case 4: alphabet = "-0123456789abcdefghijklmnopqrstuvwxyz";
          break;
    case 5: alphabet = "-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
          break;
    case 6: alphabet = "-abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
          break;
    case 7: alphabet = "-0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
          break;
    }
}


void cases7( int alphabetSet, string pass, int passwordLength) {
    while (alphabetSet < 8) {

        alphabets(alphabetSet);

            for (digit[6] = 0; digit[6] < alphabet.length() ; digit[6]++)
                for (digit[5] = 0; digit[5] < alphabet.length() ; digit[5]++)
                    for (digit[4] = 0; digit[4] < alphabet.length() ; digit[4]++)
                        for (digit[3] = 0; digit[3] < alphabet.length(); digit[3]++)
                            for (digit[2] = 0; digit[2] < alphabet.length() ; digit[2]++)
                                for (digit[1] = 0; digit[1] < alphabet.length() ; digit[1]++)
                                    for (digit[0] = 1; digit[0] < alphabet.length(); digit[0]++) {
                                        attempt++;
                                        if (attempt % 2500000 == 0) std::cout << ".";
                                        test = alphabet[digit[0]];
                                        for (int i = 1; i < passwordLength; i++)
                                            if (alphabet[digit[i]] != '-')test += alphabet[digit[i]];
                                        if (pass.compare(test) == 0) {
                                            end_t = clock(); std::cout << endl << endl << endl << ">\n>> CRACKED THE PASSWORD! >>\n>" << endl << endl << "The password : " << pass;
                                            std::cout << "The time duration  passed : " << (double)(end_t - start_t) / 1000 << " seconds" << endl << endl;
                                            system("pause");
                                        }
                                    }
        alphabetSet++;
    }
}
void cases6(int alphabetSet, string pass, int passwordLength) {
    while (alphabetSet < 8) {

        alphabets(alphabetSet);


                for (digit[5] = 0; digit[5] < alphabet.length() ; digit[5]++)
                    for (digit[4] = 0; digit[4] < alphabet.length(); digit[4]++)
                        for (digit[3] = 0; digit[3] < alphabet.length() ; digit[3]++)
                            for (digit[2] = 0; digit[2] < alphabet.length(); digit[2]++)
                                for (digit[1] = 0; digit[1] < alphabet.length() ; digit[1]++)
                                    for (digit[0] = 1; digit[0] < alphabet.length(); digit[0]++) {
                                        attempt++;
                                        if (attempt % 2500000 == 0) std::cout << ".";
                                        test = alphabet[digit[0]];
                                        for (int i = 1; i < passwordLength; i++)
                                            if (alphabet[digit[i]] != '-')test += alphabet[digit[i]];
                                        if (pass.compare(test) == 0) {
                                            end_t = clock(); std::cout << endl << endl << endl << ">\n>> CRACKED THE PASSWORD! >>\n>" << endl << endl << "The password : " << pass;
                                            std::cout << "The time duration  passed : " << (double)(end_t - start_t) / 1000 << " seconds" << endl << endl;
                                            system("pause");
                                        }
                                    }
        alphabetSet++;
    }
}
void cases5(int alphabetSet, string pass, int passwordLength) {

    while (alphabetSet < 8) {

        alphabets(alphabetSet);



                for (digit[4] = 0; digit[4] < alphabet.length(); digit[4]++)
                    for (digit[3] = 0; digit[3] < alphabet.length(); digit[3]++)
                        for (digit[2] = 0; digit[2] < alphabet.length(); digit[2]++)
                            for (digit[1] = 0; digit[1] < alphabet.length(); digit[1]++)
                                for (digit[0] = 1; digit[0] < alphabet.length(); digit[0]++) {
                                    attempt++;
                                    if (attempt % 2500000 == 0) std::cout << ".";
                                    test = alphabet[digit[0]];
                                    for (int i = 1; i < passwordLength; i++)
                                        if (alphabet[digit[i]] != '-')test += alphabet[digit[i]];
                                    if (pass.compare(test) == 0) {
                                        end_t = clock(); std::cout << endl << endl << endl << ">\n>> CRACKED THE PASSWORD! >>\n>" << endl << endl << "The password : " << pass;
                                        std::cout << "The time duration  passed : " << (double)(end_t - start_t) / 1000 << " seconds" << endl << endl;
                                        system("pause");
                                    }
                                }
        alphabetSet++;
    }
}
void cases4(int alphabetSet, string pass, int passwordLength) {
    while (alphabetSet < 8) {

        alphabets(alphabetSet);




                for (digit[3] = 0; digit[3] < alphabet.length(); digit[3]++)
                    for (digit[2] = 0; digit[2] < alphabet.length(); digit[2]++)
                        for (digit[1] = 0; digit[1] < alphabet.length(); digit[1]++)
                            for (digit[0] = 1; digit[0] < alphabet.length(); digit[0]++) {
                                attempt++;
                                if (attempt % 2500000 == 0) std::cout << ".";
                                test = alphabet[digit[0]];

                                for (int i = 1; i < passwordLength; i++)
                                    if (alphabet[digit[i]] != '-')test += alphabet[digit[i]];
                                if (pass.compare(test) == 0) {
                                    end_t = clock(); std::cout << endl << endl << endl << ">\n>> CRACKED THE PASSWORD! >>\n>" << endl << endl << "The password : " << pass;
                                    std::cout << "The time duration  passed : " << (double)(end_t - start_t) / 1000 << " seconds" << endl << endl;
                                    system("pause");
                                }
                            }
        alphabetSet++;
    }
}
void cases3(int alphabetSet, string pass, int passwordLength) {
    while (alphabetSet < 8) {

        alphabets(alphabetSet);





                for (digit[2] = 0; digit[2] < alphabet.length(); digit[2]++)
                    for (digit[1] = 0; digit[1] < alphabet.length(); digit[1]++)
                        for (digit[0] = 1; digit[0] < alphabet.length(); digit[0]++) {
                            attempt++;
                            if (attempt % 2500000 == 0) std::cout << ".";
                            test = alphabet[digit[0]];
                            for (int i = 1; i < passwordLength; i++)
                                if (alphabet[digit[i]] != '-')test += alphabet[digit[i]];
                            if (pass.compare(test) == 0) {
                                end_t = clock(); std::cout << endl << endl << endl << ">\n>> CRACKED THE PASSWORD! >>\n>" << endl << endl << "The password : " << pass;
                                std::cout << "The time duration  passed : " << (double)(end_t - start_t) / 1000 << " seconds" << endl << endl;
                                system("pause");
                            }
                        }
        alphabetSet++;
    }
}
void cases2(int alphabetSet, string pass,int passwordLength) {
    while (alphabetSet < 6) {

        alphabets(alphabetSet);


                for (digit[1] = 0; digit[1] < alphabet.length(); digit[1]++)
                    for (digit[0] = 1; digit[0] < alphabet.length(); digit[0]++) {
                        attempt++;
                        if (attempt % 2500000 == 0) std::cout << ".";
                        test = alphabet[digit[0]];
                        for (int i = 1; i < passwordLength; i++)
                            if (alphabet[digit[i]] != '-')test += alphabet[digit[i]];
                        if (pass.compare(test) == 0) {
                            end_t = clock(); std::cout << endl << endl << endl << ">\n>> CRACKED THE PASSWORD! >>\n>" << endl << endl << "The password : " << pass;
                            std::cout << "The time duration  passed : " << (double)(end_t - start_t) / 1000 << " seconds" << endl << endl;
                            system("pause");
                        }
                    }
        alphabetSet++;
    }
}
void cases1(int alphabetSet, string pass, int passwordLength) {

    while (alphabetSet < 4) {

        alphabets(alphabetSet);


            for (digit[1] = 0; digit[1] < alphabet.length(); digit[1]++)
                for (digit[0] = 1; digit[0] < alphabet.length(); digit[0]++) {
                    attempt++;
                    if (attempt % 2500000 == 0) std::cout << ".";
                    test = alphabet[digit[0]];
                    for (int i = 1; i < passwordLength; i++)
                        if (alphabet[digit[i]] != '-')test += alphabet[digit[i]];
                    if (pass.compare(test) == 0) {
                        end_t = clock(); std::cout << endl << endl << endl << ">\n>> CRACKED THE PASSWORD! >>\n>" << endl << endl << "The password : " << pass;
                        std::cout << "The time duration  passed : " << (double)(end_t - start_t) / 1000 << " seconds" << endl << endl;
                        system("pause");
                    }
                }
        alphabetSet++;
    }
}
void crackPassword(string pass) {

    start_t = clock();


    while (1) {
#pragma omp parallel num_threads(7)
#pragma omp parallel
        {
#pragma omp single
            {


#pragma omp task
                cases1(alphabetSet, pass, 1);
#pragma omp task
                cases2(alphabetSet, pass, 2);
#pragma omp task
                cases3(alphabetSet, pass, 3);
#pragma omp task
                cases4(alphabetSet, pass, 4);
#pragma omp task
                cases7(alphabetSet, pass, 7);
#pragma omp task
                cases5(alphabetSet, pass, 5);


#pragma omp task
                cases6(alphabetSet, pass, 6);

            }
        }
            }

        }

我现在使用的是g ++编译器,因为可视化studip不支持openMP 3.0,现在我编译时就这样做了

g++ Hello.cpp -o Hello.exe -fopenmp -lpthread

在我打开exe并输入密码后,它完全崩溃了,我还注意到,当我输入类似1的非常短的密码时,我看到似乎是无限循环或只是线程正在执行此操作,这也值得提到我使用的是Windows,而不是Linux。

1 个答案:

答案 0 :(得分:1)

即使是对任何事物的成功暴力破解通常也涉及某种领域知识或渗透。要通过考试,请从教师桌的抽屉中获取密码。

生成器

如果没有介绍中的建议,则可以使用迭代器构建密码生成器。这样可以轻松地与标准函数(例如for循环等)集成。取消引用的迭代器随后将返回密码。牢记领域知识,可以使它在使用次数较少的密码之前生成使用最多的密码-但是对于直截了当的攻击,只需逐步解决所有可能的字符组合。 operator++将使迭代器进入下一个密码。在我的示例中,我使用从<space>~(包括两端)的所有ASCII字符。

生成器还将需要边界,开始和停止密码,以便能够生成从aaabbb的所有密码。这样就可以并行运行许多生成器-为它们提供唯一的生成密码范围。

本地分区程序

还需要一个分区程序来划分工作,以便您可以为所有生成器分配其唯一的密码范围。它也应该有一个开始和停止密码,但是要设置更大的范围,例如,从no password~~~~~~~(7个波浪号,这是我生成器中7个字符密码的最后一个)。然后,它将使用硬件知识(可以同时运行多少个线程是合理的),并使用一个生成器启动那么多线程,每个生成器将提供要测试的整个密码范围的唯一部分。

主/远程分区程序

要使其更进一步,可以构建一个分区程序,并使用不限数量的密码进行测试。它会为本地分区程序集群提供服务,并为它们提供新的范围,以在它们用尽时进行测试。我没有在示例中包括它。相反,我制作了本地分区程序,以便它可以动态创建新范围。


我建议您研究execution policiesfind_if来运行分区程序(可以运行,但是...)。但是,在此示例中,我实现了一些与执行策略类似的方法,但是具有以预定顺序创建密码生成器的方式,并且还具有在找到答案后停止循环的方式。另外,还没有多少编译器支持执行策略。但是,此示例将在C ++ 17模式下与Visual Studio,g ++和clang ++一起使用。

在Intel Core i9-7920X(12核,2线程/核)上收集的一些令人沮丧的统计数据:

  

在不到3.9分钟的时间内即可找到任何0-6个字符的密码
  在不到7.3小时的时间内找到了0-7个字符的密码

我没有为8个字符的密码运行它:-)

Full example @ Godbolt