原理说明 程序分成两个py文件,
一个利用 itertools 标准库,用生成器生成密码,解决密码文件占用过多内存的问题。
一个用多进程+多线程来百分百利用CPU进行密码历遍。
解压 zip 文件用到 zipfile 标准库, 解压 rar 文件用到 rarfile 库,需用 pip install rarfile 进行安装。
其中 rar 库需要调用 UnRAR.exe 文件,该文件在 winRAR 安装目录中,只要把这个文件拷贝到代码目录中就可以了。如果没有这个文件,运行时会报错提示 UnRAR 未安装。
首先创建 generate_pass_word.py 文件
from itertools import chain, product, permutations, combinations_with_replacement
class Generate_pass_word:
def __init__(self):
self.num = [str(i) for i in range(0, 10)]
self.lower_letter = 'abcdefghijklmnopqrstuvwxyz'
self.upper_letter = self.lower_letter.upper()
self.simple_char = '@#$&%^*!'
self.minority_char = ",./?;:\'\"\\|,。;:”“‘~·`()(){}[]【】"
def num_password_1_6(self, n=6): # 生成1~6位数的数字密码组合。
num_password = ''
for i in range(1, n + 1):
num_password = chain(num_password, product(self.num, repeat=i))
for i in num_password:
yield ''.join(i)
def num_password_n(self, n): # 生成n位数的数字密码组合。
num_password = product(self.num, repeat=n)
for i in num_password:
yield ''.join(i)
def low_letter_password_1_6(self, n=6): # 生成1~6位数的小写字母密码组合。
low_letter_password = ''
for i in range(1, n + 1):
low_letter_password = chain(low_letter_password, product(self.lower_letter, repeat=i))
for i in low_letter_password:
yield ''.join(i)
def low_letter_password_n(self, n): # 生成n位数的小写字母密码组合。
low_letter_password = product(self.lower_letter, repeat=n)
for i in low_letter_password:
yield ''.join(i)
def upper_letter_password(self, n=6): # 生成1~6位数的大写字母密码组合。
for i in self.low_letter_password_1_6(n):
yield i.upper()
# ================= 所有字符的密码组合 ======================
def all_letter_password_1_4(self, simple=True): # 由数字、字母、字符组成的 1到4位 密码。
dic = {'num': self.num,
"lower_letter": self.lower_letter,
"upper_letter": self.upper_letter,
"char": self.simple_char,
}
if simple:
pass
else:
dic['char'] = self.simple_char + self.minority_char
gene_password_1 = self.simple_char + self.minority_char # 1 位数密码
gene_password_2 = '' # 2 位数密码
group = [] # 存放密码类型的组成
for i in combinations_with_replacement(dic.keys(), 2): # 先有放回的取出两种类型的密码。
for r in permutations(i): # 对取出的密码进行排列组合。
group.append(r)
pass_group = set(group) # 去除重复项。
pass_group.discard(('num', 'num')) # 去除纯数字和纯字母的。
pass_group.discard(('lower_letter', 'lower_letter'))
pass_group.discard(('upper_letter', 'upper_letter'))
for i in pass_group:
x, y = i
gene_password_2 = chain(gene_password_2, product(dic[x],dic[y]))
gene_password_3 = ''
group = [] # 存放密码类型的组成
for i in combinations_with_replacement(dic.keys(), 3): # 先有放回的取出两种类型的密码。
for r in permutations(i): # 对取出的密码进行排列组合。
group.append(r)
pass_group = set(group) # 去除重复项。
pass_group.discard(('num',)*3) # 去除纯数字和纯字母的。
pass_group.discard(('lower_letter',)*3)
pass_group.discard(('upper_letter',)*3)
for i in pass_group:
x, y, z = i
gene_password_3 = chain(gene_password_3, product(dic[x], dic[y], dic[z]))
gene_password_4 = ''
group = [] # 存放密码类型的组成
for i in combinations_with_replacement(dic.keys(), 4): # 先有放回的取出两种类型的密码。
for r in permutations(i): # 对取出的密码进行排列组合。
group.append(r)
pass_group = set(group) # 去除重复项。
pass_group.discard(('num',)*4) # 去除纯数字和纯字母的。
pass_group.discard(('lower_letter',)*4)
pass_group.discard(('upper_letter',)*4)
for i in pass_group:
x, y, z, n = i
gene_password_4 = chain(gene_password_4, product(dic[x], dic[y], dic[z], dic[n]))
for i in chain(gene_password_1,gene_password_2,gene_password_3,gene_password_4):
yield ''.join(i)
def all_letter_password_n(self, n, simple=True,): # 由数字、字母、字符组成的 n 位密码。
dic = {'num': self.num,
"lower_letter": self.lower_letter,
"upper_letter": self.upper_letter,
"char": self.simple_char,
}
if simple:
pass
else:
dic['char'] = self.simple_char + self.minority_char
for i in combinations_with_replacement(dic.keys(), n): # 先有放回的取出 n 种类型的密码。
g = set(permutations(i)) # 先对n种类型密码排列组合,然后去除排列组合中的重复项。
g.discard(('num',) * n) # 去除纯数字的组合,discard()即使去除元素不存在,也不报错。
g.discard(('lower_letter',) * n) # 去除纯小写字母的组合。
g.discard(('upper_letter',) * n) # 去除纯大写字母的组合。
for i in g: # 历遍组合。
for r in product(*[dic[d] for d in i]):
yield ''.join(r)
创建 运行文件 unpack.py
from zipfile import is_zipfile, ZipFile
from rarfile import is_rarfile, RarFile, RarCRCError
from multiprocessing import Manager, Pool, freeze_support, cpu_count
from itertools import chain, cycle
from threading import Thread
import os, time
from generate_pass_word import Generate_pass_word
def unpack(flg, password, read_path, save_path):
if is_zipfile(read_path): # 先判断该文件是不是zip压缩文件。
compress_file = ZipFile(read_path)
while flg.run:
try:
pwd = next(password) # 获取一个密码。
# print(pwd)
compress_file.extractall(path=save_path, pwd=pwd.encode('utf-8')) # 密码需要编码
print(f'\n解压密码为:{pwd}')
with open(os.path.join(save_path, '密码.txt'), 'w') as f:
f.write(f'解压密码为:{pwd}')
compress_file.close()
flg.run = False
# except BadZipFile as e:
# flg.run = False
# print('11压缩文件损坏, 程序退出……', e)
except StopIteration:
break
except Exception as e:
pass
#print(e, f' {pwd}')
else: # 判断该文件是不是rar压缩文件。
compress_file = RarFile(read_path)
while flg.run:
try:
pwd = next(password) # 获取一个密码。
# print(pwd)
compress_file.extractall(path=save_path, pwd=pwd) # 密码不需要编码。
print(f'\n解压密码为:{pwd}')
with open(os.path.join(save_path, '密码.txt'), 'w') as f:
f.write(f'解压密码为:{pwd}')
compress_file.close()
flg.run = False
except RarCRCError:
flg.run = False
print('压缩文件损坏, 程序退出……')
except StopIteration:
break
except Exception as e:
pass
# print(e)
def process_num(flg, dict_file):
# print('process_num 已运行')
read_path = dict_file['read_path']
save_path = dict_file['save_path']
g = Generate_pass_word()
gen_pwd_1_6 = g.num_password_1_6()
gen_pwd_7_8 = chain(g.num_password_n(7), g.num_password_n(8))
gen_pwd_9 = g.num_password_n(9)
gen_pwd_10 = g.num_password_n(10)
t1 = Thread(target=unpack, args=(flg, gen_pwd_1_6, read_path, save_path))
t2 = Thread(target=unpack, args=(flg, gen_pwd_7_8, read_path, save_path))
t3 = Thread(target=unpack, args=(flg, gen_pwd_9, read_path, save_path))
t4 = Thread(target=unpack, args=(flg, gen_pwd_10, read_path, save_path))
t1.start()
t2.start()
t3.start()
t4.start()
t1.join()
t2.join()
t3.join()
t4.join()
def process_letter(flg, dict_file):
# print('process_letter 已运行')
read_path = dict_file['read_path']
save_path = dict_file['save_path']
g = Generate_pass_word()
let_pwd_1_6 = g.low_letter_password_1_6()
let_pwd_7_8 = chain(g.low_letter_password_n(7), g.low_letter_password_n(8))
let_pwd_9 = g.low_letter_password_n(9)
let_pwd_10 = g.low_letter_password_n(10)
let_up_pwd = g.upper_letter_password()
t1 = Thread(target=unpack, args=(flg, let_pwd_1_6, read_path, save_path))
t2 = Thread(target=unpack, args=(flg, let_pwd_7_8, read_path, save_path))
t3 = Thread(target=unpack, args=(flg, let_pwd_9, read_path, save_path))
t4 = Thread(target=unpack, args=(flg, let_pwd_10, read_path, save_path))
t5 = Thread(target=unpack, args=(flg, let_up_pwd, read_path, save_path))
t1.start()
t2.start()
t3.start()
t4.start()
t5.start()
t1.join()
t2.join()
t3.join()
t4.join()
t5.join()
def process_mixture_1_8(flg, dict_file):
# print('process_mixture_1_8 已运行')
read_path = dict_file['read_path']
save_path = dict_file['save_path']
g = Generate_pass_word()
pwd_1_4 = g.all_letter_password_1_4()
pwd_5_6 = chain(g.all_letter_password_n(5), g.all_letter_password_n(6))
pwd_7 = g.all_letter_password_n(7)
pwd_8 = g.all_letter_password_n(8)
t1 = Thread(target=unpack, args=(flg, pwd_1_4, read_path, save_path))
t2 = Thread(target=unpack, args=(flg, pwd_5_6, read_path, save_path))
t3 = Thread(target=unpack, args=(flg, pwd_7, read_path, save_path))
t4 = Thread(target=unpack, args=(flg, pwd_8, read_path, save_path))
t1.start()
t2.start()
t3.start()
t4.start()
t1.join()
t2.join()
t3.join()
t4.join()
def process_mixture_9_10(flg, dict_file):
# print('process_mixture_9_10 已运行')
read_path = dict_file['read_path']
save_path = dict_file['save_path']
g = Generate_pass_word()
pwd_9 = g.all_letter_password_n(9)
pwd_10 = g.all_letter_password_n(10)
t1 = Thread(target=unpack, args=(flg, pwd_9, read_path, save_path))
t2 = Thread(target=unpack, args=(flg, pwd_10, read_path, save_path))
t1.start()
t2.start()
t1.join()
t2.join()
def schedule(flg):
for i in cycle(['|', '/', '—', '\\']):
if flg.run:
print(f'{i} {i} {i} {i} {i} {i}', flush=True, end='')
time.sleep(0.6)
print('\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b', flush=True, end='')
else:
print('\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b', flush=True, end='')
break
if __name__ == '__main__':
freeze_support()
print('该程序可破解10位之内的密码。\n联系:yan-dream@qq.com')
path = input('\n请输入压缩文件的完整路径名:\n>>> ')
read_path = os.path.abspath(path)
print(read_path)
if not os.path.exists(read_path) or (not is_zipfile(read_path) and not is_rarfile(read_path)):
print('该文件不是ZIP、ARA压缩文件!\n\
程序 3秒后 退出……')
time.sleep(3)
os._exit(1)
# 先创建一个存放的目录。
dir_path = os.path.dirname(path)
file_name = os.path.basename(path)
save_path = os.path.join(dir_path, file_name.split('.')[0])
dict_file = {'read_path': read_path,
'dir_path': dir_path,
'file_name': file_name,
'save_path': save_path}
if not os.path.isdir(save_path):
os.makedirs(save_path)
Flg = Manager().Namespace()
Flg.run = True
print(f'{time.ctime()} 开始对 《{file_name}》 进行密码破解,请等待……')
Thread(target=schedule, args=(Flg,), daemon=True).start()
if cpu_count() <= 4:
cpu_num = cpu_count()
else:
cpu_num = 4
pool = Pool(processes=cpu_num)
pool.apply_async(process_num, args=(Flg, dict_file))
pool.apply_async(process_letter, args=(Flg, dict_file))
pool.apply_async(process_mixture_1_8, args=(Flg, dict_file))
pool.apply_async(process_mixture_9_10, args=(Flg, dict_file))
pool.close()
pool.join()
if not Flg.run:
print('\n解压密码保存在 密码.txt 文件中。\n')
print('单击右上角 X,退出程序。')
time.sleep(300)
print('程序结束。')
time.sleep(3)