Как сделать все перестановки пароля для грубой силы?
Итак, я пытался сделать программу, которая перебирает пароли.
Во-первых, я сделал программу для пароля длиной 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 ответа:
Вы можете использовать следующую рекурсивную функцию :
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)
Вместо использования вложенных циклов он угадывает каждый символ по очереди.