You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何防止多进程密码破解程序耗尽系统内存?

解决多进程密码破解的内存占用过高问题

你的问题核心在于提前生成了所有密码组合的列表,list(comb)会把itertools.product生成的所有可能密码一次性加载到内存里,当密码长度稍微大一点,组合数就是指数级增长,直接把内存撑爆。另外全局变量flag2在多进程环境下无法跨进程生效,还有进程划分的逻辑也有错误,我来一步步帮你修复:

问题分析

  1. 内存爆炸的元凶:list(comb)将惰性生成器转换成完整列表,比如当密码长度为4、字符集有94个字符时,组合数是94^4=78074896,每个字符串就算平均4字节,也要占用300MB以上内存,长度再增加内存直接就顶满了。
  2. 全局变量无效:多进程中每个子进程都有独立的内存空间,修改子进程的flag2不会同步到其他进程和主进程,导致找到密码后其他进程还在继续跑,浪费资源。
  3. 进程划分逻辑错误:len(usechar)^i是异或运算,不是幂运算(应该用**),而且没必要提前计算总长度,itertools的生成器可以用islice惰性分割。

修复后的解决方案代码

我重写了你的代码,针对性解决了这些问题:

import hashlib
import itertools
import time
import os
from multiprocessing import Process, Value

def getpass(comb_slice, pass_hash, found_flag):
    st = time.time()
    for guess_tuple in comb_slice:
        # 检查是否已经找到密码,提前退出
        if found_flag.value == 1:
            break
        guess = ''.join(guess_tuple)
        digest = hashlib.md5(guess.encode('utf-8').strip()).hexdigest()
        if digest == pass_hash:
            print(f"password is: {guess}")
            print(f"Process Time Completed(seconds): {time.time() - st:.2f}")
            # 设置共享标记,通知其他进程停止
            found_flag.value = 1
            break

if __name__ == '__main__':
    lower = [chr(ord('a') + i) for i in range(26)]
    upper = [chr(ord('A') + i) for i in range(26)]
    nums = [str(i) for i in range(10)]
    char = ["~", "`", "!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "_", "-", "+", "=", "[", "]", "{", "}", ":", ";", "'", "\"", "\\", "|", ",", ".", "<", ">", "?", "/"]
    
    pass_hash = input("Enter md5 hash: ")
    pass_type = input("Enter Password Type (a=all, l=letters, n=numbers): ")
    
    usechar = []
    if pass_type == "a":
        usechar = nums + lower + upper + char
    elif pass_type == "l":
        usechar = lower + upper
    elif pass_type == "n":
        usechar = nums
    else:
        usechar = nums + lower + upper + char

    # 先尝试字典破解
    flag_found = Value('i', 0)
    st_total = time.time()
    try:
        with open("Passwords.txt", "r") as pass_file:
            print("Accessing Passwords...")
            for word in pass_file:
                enc_word = word.encode('utf-8')
                digest = hashlib.md5(enc_word.strip()).hexdigest()
                if digest == pass_hash:
                    print("Password found in dictionary!")
                    print(f"Password is: {word.strip()}")
                    print(f"Total Time Completed(seconds): {time.time() - st_total:.2f}")
                    flag_found.value = 1
                    break
    except FileNotFoundError:
        print("No Passwords.txt file found, skipping dictionary attack.")

    if flag_found.value == 0:
        print("Password not in dictionary. Starting brute-force attack...")
        # 限制进程数为CPU核心数,避免过度占用资源
        num_processes = os.cpu_count() or 4
        print(f"Using {num_processes} processes")

        # 先尝试短密码(长密码暴力破解几乎不可能)
        for password_length in range(1, 7):
            if flag_found.value == 1:
                break
            print(f"\nTrying password length: {password_length}")
            # 生成惰性密码组合生成器,不占用额外内存
            comb_generator = itertools.product(usechar, repeat=password_length)
            total_combinations = len(usechar) ** password_length
            chunk_size = total_combinations // num_processes

            processes = []
            for i in range(num_processes):
                # 用islice分割生成器,不需要提前加载所有数据
                if i == num_processes - 1:
                    # 最后一个进程处理剩余的所有组合
                    slice_obj = itertools.islice(comb_generator, chunk_size * i, None)
                else:
                    slice_obj = itertools.islice(comb_generator, chunk_size * i, chunk_size * (i+1))
                p = Process(target=getpass, args=(slice_obj, pass_hash, flag_found))
                processes.append(p)
                p.start()

            # 等待所有进程结束
            for p in processes:
                p.join()

        if flag_found.value == 0:
            print("\nPassword is either longer than 6 characters or not in the tested character set.")

    print(f"\nTotal elapsed time: {time.time() - st_total:.2f} seconds")

关键优化点

  • 惰性分割任务:用itertools.islice直接分割生成器,不需要把所有组合转成列表,内存占用几乎为0。
  • 共享终止信号:使用multiprocessing.Value创建共享的整数标记,一旦某个进程找到密码,所有进程都会检测到并立即停止。
  • 合理设置进程数:用os.cpu_count()获取CPU核心数,避免创建过多进程导致系统调度压力过大。
  • 逐步增加密码长度:先尝试短密码,找到就立即停止,没必要一下子到20位(20位的组合数是天文数字,暴力破解几乎不可能)。
  • 优化文件操作:用with语句自动管理文件句柄,更安全简洁。

额外建议

  • 如果字典破解没找到,暴力破解长密码(比如超过8位)其实不现实,除非字符集非常小,建议优先扩展字典文件。
  • 可以考虑用multiprocessing.Pool来简化进程管理,代码会更简洁。
  • 避免在循环中重复创建进程,每个密码长度创建一次进程池即可。

内容的提问来源于stack exchange,提问作者user14783088

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 07:52:55