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


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

Во-первых, я сделал программу для пароля длиной 1:

password = input('What is your password?n')
chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'

def brute_force():
    for char in chars:
        if char == password:
            return char

print(brute_force())

Затем я отредактировал его для пароля длиной 2:

def brute_force():
    guess = [None, None]
    for char in chars:
        guess[0] = char
        for char2 in chars:
            guess[1] = char2
            if ''.join(guess) == password:
                return ''.join(guess)

Наконец, я сделал то же самое для пароля длиной 3:

def brute_force():
    guess = [None, None, None]
    for char in chars:
        guess[0] = char
        for char2 in chars:
            guess[1] = char2
            for char3 in chars:
                guess[2] = char3
                if ''.join(guess) == password:
                    return ''.join(guess)

Как я могу обобщить это для переменной под названием length, которая содержит целое значение длины пароля?

4 9

4 ответа:

Вы можете использовать следующую рекурсивную функцию :

def brute_force(string, length, goal):
    if not length:
        if string == goal:
            return string
        return False
    for c in chars:
         s = brute_force(string + c, length - 1, goal)
         if s:
             return s
    return False

, который можно вызвать с помощью синтаксиса, например:

>>> brute_force('', 3, 'bob')
'bob'
>>> brute_force('', 2, 'yo')
'yo'

Почему это работает?

Мы всегда вызываем каждую функцию с тремя переменными: string, length и goal. Переменная string удерживает текущую догадку до этого момента, поэтому в первом примере string будет все до bob, например ab, bo и т.д.

Следующая переменная length содержит количество символов идти до string - это правильная длина.

Следующая переменная goal - это правильный пароль,который мы просто проходим и сравниваем.

В основном теле функции нам нужно сначала проверить случай, когда length является 0 (выполняется путем проверки not length, поскольку 0 вычисляется как False). Это тот случай, когда у нас уже есть строка, которая является длиной цели, и мы просто хотим проверить, правильно ли это.

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

Теперь мы закончили дело, где length = 0 и теперь нужно заняться другими делами.

В этих случаях цель состоит в том, чтобы взять строку, с которой мы были вызваны, и выполнить цикл через все символов в chars, каждый раз вызывая функцию brute_force (рекурсивную) с результатом из конкатенации строки, с которой мы были вызваны, и этого символа (c).

Это создаст дерево, подобное аффекту, гдепроверяется каждая строка вплоть до исходной length.

Нам также нужно знать, что делать с переменными length и goal при вызове следующей функции.

Ну, чтобы справиться с ними, нам просто нужно подумать, что должна знать следующая функция. Он уже имеет string (так как это было результатом объединения следующего символа в строка chars) и length просто будет на один меньше, так как мы только что добавили один к string через конкатенацию, и goal явно будет таким же - мы все еще ищем тот же пароль. Теперь, когда мы вызвали эту функцию, она будет выполнять вычитание единицы из длины при каждом последующем вызове, пока в конечном итоге не достигнет случая, когда length == 0. И мы снова в легком деле и уже знаем, что делать!

Итак, после вызывая его, функция вернет одно из двух: либо False, указывающее, что последний узел не нашел пароль (так что это произойдет в том случае, когда что-то вроде ab достигло конца в нашем поиске bob, поэтому вернулось False после того, как решение не было найдено), либо вызов может вернуть фактическое решение.

Обработка этих случаев проста, если мы получили фактическое решение, мы просто хотим вернуть его вверх по цепочке, и если мы получили сбой (False), мы просто хотим верните False, и это укажет узлу над нами, что мы не добились успеха, и попросит его продолжить поиск.

Так что теперь нам просто нужно знать, как вызвать функцию. Нам просто нужно отправить пустое string и целевое length и goal значение и позволить рекурсии иметь место.

Обратите внимание, что если вы хотите, чтобы это было еще аккуратнее, вы можете изменить определение функции на:

def brute_force(length, goal, string=''):
    ...

И измените рекурсивный вызов внутри. Сюда, ты можно было бы вызвать функцию с чем-то вроде: brute_force(3, 'bob') и не нужно было бы указывать, с чего string следует начинать. Это просто то, что вы можете добавить, если хотите, но не обязательно для работы функции.

В дополнение к ответу, который показывает вам, как это работает, я хотел бы обратить внимание на то, что стандартная библиотека имеет функцию именно для этого, в форме itertools.product-Не itertools.permutations, потому что это не позволяет повторений и поэтому будет генерировать только догадки со всеми уникальными символами:

]}
from itertools import product

def brute_force():
    for length in range(min_length, max_length + 1):
        for p in product(chars, repeat=length):
            guess = ''.join(p)
            if guess == password:
                return guess

Вот одно решение:

password = input('What is your password? ')
chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'

def brute_force(length, check_callback, guess = ""):
    if check_callback(guess):
        return guess
    elif len(guess) == length: #Reached maximum length and didn't find the password
        return None
    for char in chars:
        retval = brute_force(length, check_callback, guess = guess + char)
        if retval is not None:
            return retval
    return None #Couldn't find anything

print(brute_force(len(password), lambda guess: (guess == password))) #len(password) => cheating just for this example

length это максимальная длина догадки, до которой будет идти функция. check_callback должен принять предположение и вернуть истинное значение, если оно сработало. Функция возвращает первое удачное предположение, или None, если она ничего не смогла найти.

Признаюсь, я забыл о длине догадки и был напомнен ответом@Joe Iddon .


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

def brute_force(length, check_callback, guess = ""):
    if len(guess) == length: #Reached maximum length
        return (guess if check_callback(guess) else None)
    for char in chars:
        retval = brute_force(length, check_callback, guess = guess + char)
        if retval is not None:
            return retval
    return None #Couldn't find anything
print(brute_force(len(password), lambda guess: guess == password)) #len(password) => cheating just for this example

Попробуйте это:

password = input('What is your password?\n')
chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'

answer = ''
for i in range(len(password)):
    for char in chars:
        if char==password[i]:
            answer += char

print(answer)

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