如何为暴力破解密码的所有排列?

How to make all of the permutations of a password for brute force?

所以我试图制作一个暴力破解密码的程序。

首先,我编写了一个长度为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 的变量,该变量包含密码长度的整数值?

试试这个:

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)

它不是使用嵌套循环,而是依次猜测每个字符。

您可以使用以下递归函数:

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'

为什么这样做?

我们总是使用三个变量调用每个函数:stringlengthgoal。变量 string 保存了到目前为止的猜测,因此在第一个示例中,string 将是 bob 之前的所有内容,例如 abbo等等

下一个变量 length 保存在 string 达到正确长度之前还有多少个字符。

下一个变量 goal 是我们刚刚通过并与之比较的正确密码。

在函数的主体中,我们需要首先检查 length0 的情况(通过检查 not length 来完成,因为 0 计算为 False).当我们已经有了一个作为目标长度的字符串并且我们只想检查它是否正确时就是这种情况。

如果匹配,则我们 return 字符串,否则我们 return False。我们 return 解决方案或 False 向调用我们的函数(堆栈中上面的调用)指示我们找到了正确的密码(或没有)。

我们现在已经完成了 length = 0 的案例,现在需要处理其他案例。

在这些情况下,目的是获取调用我们的字符串并循环遍历 chars 中的 all 个字符,每次调用brute_force 函数(递归),其结果是我们调用的字符串与该字符 (c) 的串联结果。

这将创建一个类似影响的树,其中检查 每个 字符串直到原始 length

我们还需要知道在调用下一个函数时如何处理 lengthgoal 变量。

好吧,为了处理这些,我们只需要考虑下一个函数需要知道什么。它已经有了 string(因为这是连接 chars 字符串中的下一个字符的结果)并且 length 只是少了一个,因为我们刚刚向string 通过连接和 goal 显然是相同的 - 我们仍在搜索相同的密码。

既然我们已经调用了这个函数,它将运行通过在它进行的每次后续调用中从长度中减去一个,直到它最终达到length == 0的情况。我们又回到了简单的情况,并且已经知道该怎么做!

因此,在调用它之后,该函数将 return 两种情况之一,或者 False 表明最后一个节点没有找到密码(所以这会发生在某些情况下例如 ab 在我们搜索 bob 时到达终点,因此 return 在未找到解决方案后编辑 False),或者,调用可以 return 实际 解决方案。

处理这些情况很简单,如果我们得到了实际的解决方案,我们只想 return 链上的那个,如果我们失败了 (False),我们只想 return False 这将向我们上面的节点表明我们没有成功并告诉它继续搜索。

所以现在,我们只需要知道如何调用该函数即可。我们只需要发送一个空 string 和一个目标 lengthgoal 值并让递归发生。


请注意最后一件事,如果您希望它更简洁,您可以将函数定义修改为:

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

并更改其中的递归调用。这样,您可以使用类似以下内容的函数来调用该函数:brute_force(3, 'bob') 并且不需要指定 string 应该从哪里开始。这只是您可以根据需要添加的内容,但不是该功能运行所必需的。

这是一种解决方案:

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 应该进行猜测,如果它有效,return 应该是一个真实值。函数 return 是第一个成功的猜测,或者 None 如果它找不到任何东西。

我承认我忘记了猜测的长度,提醒了我。


现在,即使猜测的长度还不正确,该函数也会检查正确答案,这在某些情况下很浪费。这是一个不这样做的函数:

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

除了向您展示其工作原理的答案外,我还想提请注意以下事实,即标准库具有用于此目的的函数,其形式为 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