import rarfile
import itertools
import string
import concurrent.futures

def extract_rar(rar_path, password):
"""尝试解压RAR文件,返回解压是否成功。"""
try:
with rarfile.RarFile(rar_path) as rf:
rf.extractall(pwd=password)
return True
except rarfile.BadRarFile:
print("这是一个无效的 RAR 文件。")
return False
except rarfile.PasswordRequired:
return False # 密码错误继续尝试
except rarfile.NeedFirstVolume:
print("需要第一个卷。")
return False
except rarfile.Error as e:
if "bad password" in str(e).lower():
return False
else:
print(f"发生错误: {e}")
return False
except Exception as e:
print(f"发生错误: {e}")
return False

BATCH_SIZE = 1000

def password_cracker(characters, min_length, max_length):
rar_file_path = input("请输入要破解的RAR文件路径:")

file_size = None
try:
    with rarfile.RarFile(rar_file_path) as rf:
        file_size = rf.filelist[0].file_size if rf.filelist else None
except Exception as e:
    print(f"获取文件大小失败: {e}")

for length in range(min_length, max_length + 1):
    password_generator = itertools.product(characters, repeat=length)
    passwords_to_try_batch = []
    for password_tuple in password_generator:
        password = ''.join(password_tuple)
        passwords_to_try_batch.append(password)
        if len(passwords_to_try_batch) == BATCH_SIZE:
            with concurrent.futures.ThreadPoolExecutor() as executor:
                future_to_password = {executor.submit(extract_rar, rar_file_path, password): password for password in passwords_to_try_batch}
                for future in concurrent.futures.as_completed(future_to_password):
                    password = future_to_password[future]
                    print(f"尝试密码: {password}")
                    print(f"尝试路径: {rar_file_path}")

                    try:
                        if extract_rar(rar_file_path, password):
                            if file_size is not None:
                                with rarfile.RarFile(rar_file_path) as rf:
                                    extracted_file_size = rf.filelist[0].file_size if rf.filelist else None
                                    if extracted_file_size == file_size:
                                        print(f"成功破解密码: {password}")
                                        return
                                    else:
                                        print("解压文件大小与原始文件不一致,可能密码错误或文件有问题。")
                            else:
                                print(f"extracted_file_size: {extracted_file_size}")
                                print(f"file_size: {file_size}")
                                print(f"成功破解密码: {password}")
                                return
                    except Exception as e:
                        print(f"尝试密码 {password} 时发生错误: {e}")
            passwords_to_try_batch = []
    if passwords_to_try_batch:
        with concurrent.futures.ThreadPoolExecutor() as executor:
            future_to_password = {executor.submit(extract_rar, rar_file_path, password): password for password in passwords_to_try_batch}
            for future in concurrent.futures.as_completed(future_to_password):
                password = future_to_password[future]
                print(f"尝试密码: {password}")
                print(f"尝试路径: {rar_file_path}")

                try:
                    if extract_rar(rar_file_path, password):
                        if file_size is not None:
                            with rarfile.RarFile(rar_file_path) as rf:
                                extracted_file_size = rf.filelist[0].file_size if rf.filelist else None
                                if extracted_file_size == file_size:
                                    print(f"成功破解密码: {password}")
                                    return
                                else:
                                    print("解压文件大小与原始文件不一致,可能密码错误或文件有问题。")
                        else:
                            print(f"extracted_file_size: {extracted_file_size}")
                            print(f"file_size: {file_size}")
                            print(f"成功破解密码: {password}")
                            return
                except Exception as e:
                    print(f"尝试密码 {password} 时发生错误: {e}")

if name == "main":
# 选择字符集:大小写字母和数字
characters = string.ascii_lowercase + string.ascii_uppercase + string.digits
min_length = int(input("请输入最小密码长度(例如 3):"))
max_length = int(input("请输入最大密码长度(例如 6):"))

# 开始密码破解  
password_cracker(characters, min_length, max_length)
posted on 2024-11-05 11:21  假装新手  阅读(11)  评论(0编辑  收藏  举报