如何防止多进程密码破解程序耗尽系统内存?
解决多进程密码破解的内存占用过高问题
你的问题核心在于提前生成了所有密码组合的列表,list(comb)会把itertools.product生成的所有可能密码一次性加载到内存里,当密码长度稍微大一点,组合数就是指数级增长,直接把内存撑爆。另外全局变量flag2在多进程环境下无法跨进程生效,还有进程划分的逻辑也有错误,我来一步步帮你修复:
问题分析
- 内存爆炸的元凶:
list(comb)将惰性生成器转换成完整列表,比如当密码长度为4、字符集有94个字符时,组合数是94^4=78074896,每个字符串就算平均4字节,也要占用300MB以上内存,长度再增加内存直接就顶满了。 - 全局变量无效:多进程中每个子进程都有独立的内存空间,修改子进程的
flag2不会同步到其他进程和主进程,导致找到密码后其他进程还在继续跑,浪费资源。 - 进程划分逻辑错误:
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
相关产品推荐
相关产品推荐

