Как я могу распараллелить этот алгоритм атаки грубой силы - PullRequest
2 голосов
/ 02 мая 2019

Я студент первого курса, изучающий компьютерную инженерию, у нас есть задание создать алгоритм грубой силы, который взломал бы пароль, предоставленный пользователем, я решил пройти лишнюю милю и использовать параллельное программирование, теперь это кодбез параллельного программирования:

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 ++, так какVisual Cipip не поддерживает OpenMP 3.0, теперь, когда я компилирую и делаю это такочень короткий проход, такой как 1, я вижу то, что кажется бесконечным циклом или просто потоками, делающими что-то, также стоит упомянуть, что я использую windows, а не linux.

1 Ответ

1 голос
/ 03 мая 2019

Даже успешные атаки методом "грубой силы" на что-либо, как правило, включают некое знание области или проникновение. Чтобы сдать экзамен, возьмите пароль из ящика на столе преподавателя.

Генератор

Если то, что предлагается во вступлении, не является вариантом, вы можете создать генератор паролей с итераторами. Это облегчит интеграцию со стандартными функциями, такими как for-loop и т. Д. Итератор с разыменованными ссылками затем вернет пароль. Имея в виду знание предметной области, можно было бы сделать так, чтобы он генерировал наиболее используемые пароли, а не менее часто используемые - но для тупой атаки нужно будет просто пройти через все возможные комбинации символов. operator++ сделает шаг итератора к следующему паролю. В моем примере я использую все символы ASCII от <space> до ~ (включительно).

Генератору также понадобятся границы, пароль запуска и остановки, чтобы можно было генерировать все пароли, например, от aaa до bbb. Это позволит параллельно запускать несколько генераторов, предоставляя им уникальные диапазоны паролей для генерации.

Локальный разделитель

Также необходим разделитель для разделения работы, чтобы вы могли дать всем генераторам уникальный диапазон паролей для генерации. Он также должен иметь пароль начала и остановки, но для гораздо большего диапазона, скажем, от no password до ~~~~~~~ (7 тильд, последний из 7-значных паролей в моем генераторе). Затем он будет использовать знания аппаратного обеспечения (сколько потоков было бы разумно запустить одновременно) и запустить столько потоков с одним генератором, каждый из которых даст уникальную часть полного диапазона паролей для тестирования.

Главный / Удаленный Разделитель

Чтобы иметь возможность сделать еще один шаг вперед, можно создать разделитель, использующий для тестирования неограниченное количество паролей. Он будет обслуживать кластер локальных разделителей и подавать им новые диапазоны, чтобы проверить, когда они закончатся без работы. Я не включил это в пример. Вместо этого я сделал локальный разделитель, чтобы он создавал новые диапазоны на лету.


Я предлагаю вам взглянуть на политики выполнения и find_if для запуска разделителя (который будет работать, но ...). Однако в этом примере я реализовал нечто похожее на политики выполнения, но с возможностью создания генераторов паролей в заранее определенном порядке, а также с возможностью прекращения зацикливания, когда ответ найден. Кроме того, не многие компиляторы поддерживают политики выполнения. Однако этот пример будет работать с Visual Studio, g ++ и clang ++ в режиме C ++ 17.

Немного обескураживающей статистики, собранной на Intel Core i9-7920X (12 ядер, 2 потока / ядро):

любой пароль длиной 0-6 символов найден менее чем за ~ 3,9 минуты
любой пароль длиной 0-7 символов найден менее чем за ~ 7,3 часа

Я не запускал его для 8-символьных паролей: -)

Полный пример @ Godbolt

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...