所以我试图制作一个暴力破解密码的程序。
首先,我制作了一个长度为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的变量,它包含密码长度的整数值?
答案 0 :(得分:10)
您可以使用以下递归功能:
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
评估为{{1} }})。当我们已经有一个字符串是目标的长度并且我们只想检查它是否正确时就是这种情况。
如果匹配,则返回字符串,否则返回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')
应该从哪个开始。如果您愿意,这只是您可以添加的内容,但功能无需工作。
答案 1 :(得分:10)
除了向您展示其工作原理的答案之外,我还想提请注意标准库具有此功能的事实,其形式为itertools.product
- 而不是{ {1}}因为这不允许重复,因此只会生成所有唯一字符的猜测:
itertools.permutations
答案 2 :(得分:4)
这是一个解决方案:
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's answer提醒。
现在,即使猜测的长度不合适,该功能也会检查正确的答案,这在某些情况下是浪费的。这是一个不能做到这一点的功能:
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
答案 3 :(得分:-3)
试试这个:
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)
不是使用嵌套循环,而是依次猜测每个字符。