diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e2e5d02 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +__pycache__/ +*.pyc +*.bak +bandizip_license.txt +.DS_Store diff --git a/bandizip_keygen.py b/bandizip_keygen.py new file mode 100644 index 0000000..eccda9d --- /dev/null +++ b/bandizip_keygen.py @@ -0,0 +1,194 @@ +#!/usr/bin/env python3 +""" +Bandizip Professional Keygen +============================= +生成 Bandizip Professional 注册码。 + +注意:需要配合 patch 后的 Bandizip.exe 使用。 +Patch 内容: + - sub_1400D18F0 (在线验证) -> return 1 + - sub_1400CF980 (写注册表) -> return 1 + - sub_1400CF470 (读 Edition) -> return 1 + - 4x NOP (注册码格式检查) + - 版本号默认值 0x98 -> 0x3D4 (Standard -> Professional) + +使用方法: + python bandizip_keygen.py + python bandizip_keygen.py user@example.com +""" + +import random +import string +import hashlib +import time +import sys +import os + + +# ============ 注册码格式 ============ +# Bandizip 注册码格式: XXXXXXXX-XXXXXXXX-XXXXXXXX-XXXXXXXX +# 每段 8 个十六进制字符,共 4 段 +# 原始验证流程已被 patch,任意格式均可通过 + +def generate_product_key(seed=None): + """ + 生成 Bandizip 产品密钥 + 格式: XXXXXXXX-XXXXXXXX-XXXXXXXX-XXXXXXXX + """ + if seed: + # 使用种子生成确定性密钥 + rng = random.Random(seed) + else: + rng = random.Random() + + segments = [] + for _ in range(4): + seg = ''.join(rng.choices('0123456789ABCDEF', k=8)) + segments.append(seg) + + return '-'.join(segments) + + +def generate_license_data(email): + """ + 生成完整的许可证数据 + """ + # 基于 email 生成种子 + seed = int(hashlib.md5(email.encode()).hexdigest()[:8], 16) + + # 生成产品密钥 + product_key = generate_product_key(seed) + + # 生成 GUID(模拟服务器返回的) + guid = '%08X-%04X-%04X-%04X-%012X' % ( + seed & 0xFFFFFFFF, + (seed >> 8) & 0xFFFF, + (seed >> 16) & 0xFFFF, + (seed >> 24) & 0xFFFF, + seed & 0xFFFFFFFFFFFF + ) + + # 生成硬件 ID(模拟) + hid = '%08X' % (seed ^ 0xDEADBEEF) + + # 产品 ID (1000 = Professional) + product_id = 1000 + + return { + 'email': email, + 'productKey': product_key, + 'guid': guid, + 'hid': hid, + 'productID': product_id, + 'edition': 'PRO', + 'timestamp': seed % 0x7FFFFFFF, # 稳定值,基于 email 种子 + } + + +def format_license(data): + """ + 格式化许可证信息 + """ + lines = [ + '==================================================', + ' Bandizip Professional License ', + '==================================================', + f' Email: {data["email"]}', + f' Product Key: {data["productKey"]}', + f' Edition: {data["edition"]}', + f' Product ID: {data["productID"]}', + f' GUID: {data["guid"]}', + f' HID: {data["hid"]}', + '==================================================', + ] + return '\n'.join(lines) + + +def write_registry(data): + """ + 写入 Windows 注册表(需要管理员权限) + """ + try: + import winreg + except ImportError: + print(' [!] 非 Windows 系统,跳过注册表写入') + return False + + key_path = r'SOFTWARE\Bandizip' + + try: + # 写入 Edition + with winreg.CreateKeyEx(winreg.HKEY_LOCAL_MACHINE, key_path, 0, winreg.KEY_SET_VALUE) as key: + winreg.SetValueEx(key, 'Edition', 0, winreg.REG_SZ, data['edition']) + + print(f' [OK] Edition = {data["edition"]}') + return True + except PermissionError: + print(' [!] 需要管理员权限写入注册表') + print(f' 请手动执行:') + print(f' reg add "HKLM\\{key_path}" /v Edition /t REG_SZ /d "{data["edition"]}" /f') + return False + except Exception as e: + print(f' [!] 注册表写入失败: {e}') + return False + + +def main(): + print('==================================================') + print(' Bandizip Professional Keygen v1.0 ') + print('==================================================') + print() + + # 获取 email + if len(sys.argv) > 1: + email = sys.argv[1] + else: + email = input('请输入邮箱地址: ').strip() + if not email: + email = 'user@bandizip.local' + + print(f'\n[Email] {email}') + print(f'[Keygen] 生成注册码...\n') + + # 生成许可证数据 + data = generate_license_data(email) + + # 显示许可证 + print(format_license(data)) + print() + + # 询问是否写入注册表 + if sys.platform == 'win32': + print('是否写入注册表? (y/n): ', end='') + try: + choice = input().strip().lower() + if choice == 'y': + write_registry(data) + except EOFError: + pass + + print(f'\n[Steps] Registration:') + print(f' 1. Open Bandizip') + print(f' 2. Menu -> Help -> Register') + print(f' 3. Email: {data["email"]}') + print(f' 4. Product Key: {data["productKey"]}') + print(f' 5. Click Register') + print() + + # 保存到文件 + license_file = os.path.join(os.path.dirname(__file__), 'bandizip_license.txt') + with open(license_file, 'w', encoding='utf-8') as f: + f.write(format_license(data) + '\n') + f.write(f'\nEmail: {data["email"]}\n') + f.write(f'Product Key: {data["productKey"]}\n') + f.write(f'Edition: {data["edition"]}\n') + f.write(f'Product ID: {data["productID"]}\n') + f.write(f'GUID: {data["guid"]}\n') + f.write(f'HID: {data["hid"]}\n') + f.write(f'Timestamp: {data["timestamp"]}\n') + + print(f' [Save] 许可证已保存到: {license_file}') + + +if __name__ == '__main__': + main() diff --git a/bandizip_patcher.py b/bandizip_patcher.py new file mode 100644 index 0000000..c3441ea --- /dev/null +++ b/bandizip_patcher.py @@ -0,0 +1,328 @@ +#!/usr/bin/env python3 +""" +Bandizip Professional Patcher +============================= +一键补丁器:备份、patch、验证、恢复。 + +Patch 内容(共 8 处,35 字节): + 1. sub_1400D18F0 @ 0xD0CF0 -> B0 01 C3 (mov al,1; ret) 在线验证跳过 + 2. sub_1400CF980 @ 0xCED80 -> B0 01 C3 (mov al,1; ret) 写注册表跳过 + 3. sub_1400CF470 @ 0xCE870 -> B0 01 C3 (mov al,1; ret) Edition 检查返回 true + 4. sub_140133648 @ 0x132A48 -> 90*6 (NOP) 注册码长度检查跳过 + 5. sub_140133655 @ 0x132A55 -> 90*6 (NOP) 数据有效性检查跳过 + 6. sub_14013366A @ 0x132A6A -> 90*6 (NOP) @ 符号检查跳过 + 7. sub_140133678 @ 0x132A78 -> 90*6 (NOP) @ 位置检查跳过 + 8. sub_14013180B @ 0x130C0B -> D4 03 00 00 版本号 Standard->Professional + +使用方法: + python bandizip_patcher.py # 交互模式 + python bandizip_patcher.py patch # 直接 patch + python bandizip_patcher.py restore # 恢复原始 + python bandizip_patcher.py status # 检查状态 +""" + +import os +import sys +import shutil +import winreg + +# ============ 配置 ============ +BANDIZIP_DIR = r'D:\Apps\Bandizip' +EXE_PATH = os.path.join(BANDIZIP_DIR, 'Bandizip.exe') +BACKUP_PATH = EXE_PATH + '.bak' +REG_KEY = r'SOFTWARE\Bandizip' +REG_VALUE = 'Edition' +REG_DATA = 'PRO' + +# Patch 定义: (文件偏移, 原始字节, 补丁字节, 描述) +PATCHES = [ + (0xD0CF0, b'\x48\x89\x5C\x24\x08\x55', b'\xB0\x01\xC3', + 'sub_1400D18F0 (online verify -> return 1)'), + (0xCED80, b'\x48\x89\x5C\x24\x18\x55', b'\xB0\x01\xC3', + 'sub_1400CF980 (registry write -> return 1)'), + (0xCE870, b'\x4C\x8B\xDC\x49\x89\x5B', b'\xB0\x01\xC3', + 'sub_1400CF470 (Edition check -> return 1)'), + (0x132A48, b'\x0F\x85\x4B\x06\x00\x00', b'\x90\x90\x90\x90\x90\x90', + 'NOP: register code length check'), + (0x132A55, b'\x0F\x8C\x3E\x06\x00\x00', b'\x90\x90\x90\x90\x90\x90', + 'NOP: data validity check'), + (0x132A6A, b'\x0F\x84\x29\x06\x00\x00', b'\x90\x90\x90\x90\x90\x90', + 'NOP: @ symbol check'), + (0x132A78, b'\x0F\x8E\x1B\x06\x00\x00', b'\x90\x90\x90\x90\x90\x90', + 'NOP: @ position check'), + (0x130C0B, b'\x98\x00\x00\x00', b'\xD4\x03\x00\x00', + 'Version: Standard(0x98) -> Professional(0x3D4)'), +] + + +def is_patched(): + """检查是否已 patch""" + if not os.path.exists(EXE_PATH): + return False + with open(EXE_PATH, 'rb') as f: + for offset, orig, patch, desc in PATCHES: + f.seek(offset) + current = f.read(len(patch)) + if current != patch: + return False + return True + + +def is_backup_exists(): + """检查备份是否存在""" + return os.path.exists(BACKUP_PATH) + + +def is_bandizip_running(): + """检查 Bandizip 是否正在运行""" + try: + import subprocess + result = subprocess.run(['tasklist', '/FI', 'IMAGENAME eq Bandizip.exe'], + capture_output=True, text=True, timeout=5) + return 'Bandizip.exe' in result.stdout + except Exception: + return False + + +def kill_bandizip(): + """关闭 Bandizip 进程""" + try: + import subprocess + subprocess.run(['taskkill', '/F', '/IM', 'Bandizip.exe'], + capture_output=True, timeout=5) + import time + time.sleep(2) + return True + except Exception: + return False + + +def backup(): + """备份原始文件""" + if is_backup_exists(): + print(' [OK] Backup already exists: ' + BACKUP_PATH) + return True + try: + shutil.copy2(EXE_PATH, BACKUP_PATH) + print(' [OK] Backup created: ' + BACKUP_PATH) + return True + except PermissionError: + print(' [!] Permission denied. Run as Administrator.') + return False + except Exception as e: + print(' [!] Backup failed: ' + str(e)) + return False + + +def apply_patches(): + """应用所有 patch""" + try: + with open(EXE_PATH, 'r+b') as f: + for offset, orig, patch, desc in PATCHES: + f.seek(offset) + current = f.read(len(patch)) + if current == patch: + print(' [SKIP] Already patched: ' + desc) + continue + f.seek(offset) + f.write(patch) + print(' [OK] ' + desc) + return True + except PermissionError: + print(' [!] Permission denied. Close Bandizip and run as Administrator.') + return False + except Exception as e: + print(' [!] Patch failed: ' + str(e)) + return False + + +def restore(): + """恢复原始文件""" + if not is_backup_exists(): + print(' [!] No backup found: ' + BACKUP_PATH) + return False + try: + shutil.copy2(BACKUP_PATH, EXE_PATH) + print(' [OK] Restored from backup: ' + EXE_PATH) + return True + except PermissionError: + print(' [!] Permission denied. Close Bandizip and run as Administrator.') + return False + except Exception as e: + print(' [!] Restore failed: ' + str(e)) + return False + + +def set_registry(): + """设置注册表 Edition = PRO""" + try: + with winreg.CreateKeyEx(winreg.HKEY_LOCAL_MACHINE, REG_KEY, 0, + winreg.KEY_SET_VALUE) as key: + winreg.SetValueEx(key, REG_VALUE, 0, winreg.REG_SZ, REG_DATA) + print(' [OK] Registry: HKLM\\' + REG_KEY + '\\' + REG_VALUE + ' = ' + REG_DATA) + return True + except PermissionError: + print(' [!] Registry write denied. Run as Administrator.') + return False + except Exception as e: + print(' [!] Registry write failed: ' + str(e)) + return False + + +def check_status(): + """检查当前状态""" + print('=' * 50) + print(' Bandizip Patcher - Status') + print('=' * 50) + + # 文件存在 + if os.path.exists(EXE_PATH): + print(' [OK] Bandizip.exe found: ' + EXE_PATH) + else: + print(' [!] Bandizip.exe not found: ' + EXE_PATH) + return + + # 备份状态 + if is_backup_exists(): + print(' [OK] Backup exists') + else: + print(' [!] No backup') + + # Patch 状态 + patched_count = 0 + total = len(PATCHES) + if os.path.exists(EXE_PATH): + with open(EXE_PATH, 'rb') as f: + for offset, orig, patch, desc in PATCHES: + f.seek(offset) + current = f.read(len(patch)) + if current == patch: + patched_count += 1 + status = '[PATCHED]' + elif current == orig: + status = '[ORIGINAL]' + else: + status = '[UNKNOWN]' + print(' ' + status + ' 0x{:06X}: '.format(offset) + desc) + + print('') + print(' Patched: ' + str(patched_count) + '/' + str(total)) + + # 注册表状态 + try: + with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, REG_KEY) as key: + val, _ = winreg.QueryValueEx(key, REG_VALUE) + print(' [Registry] Edition = ' + val) + except Exception: + print(' [Registry] Edition not set') + + # 进程状态 + if is_bandizip_running(): + print(' [WARNING] Bandizip is running! Close it before patching.') + else: + print(' [OK] Bandizip is not running') + + print('=' * 50) + + +def do_patch(): + """执行完整 patch 流程""" + print('=' * 50) + print(' Bandizip Patcher - Apply') + print('=' * 50) + + if not os.path.exists(EXE_PATH): + print(' [!] Bandizip.exe not found: ' + EXE_PATH) + return False + + if is_bandizip_running(): + print(' [..] Bandizip is running, closing...') + if not kill_bandizip(): + print(' [!] Cannot close Bandizip. Close it manually.') + return False + + print('\n [1/3] Backup...') + if not backup(): + return False + + print('\n [2/3] Patching...') + if not apply_patches(): + return False + + print('\n [3/3] Registry...') + set_registry() + + print('\n' + '=' * 50) + print(' [DONE] All patches applied successfully!') + print(' Use keygen to generate a product key.') + print('=' * 50) + return True + + +def do_restore(): + """执行恢复流程""" + print('=' * 50) + print(' Bandizip Patcher - Restore') + print('=' * 50) + + if is_bandizip_running(): + print(' [..] Bandizip is running, closing...') + if not kill_bandizip(): + print(' [!] Cannot close Bandizip. Close it manually.') + return False + + print('\n [1/1] Restoring...') + if restore(): + print('\n' + '=' * 50) + print(' [DONE] Restored to original.') + print('=' * 50) + return True + return False + + +def main(): + print('=' * 50) + print(' Bandizip Professional Patcher v1.0') + print('=' * 50) + print('') + + if len(sys.argv) > 1: + cmd = sys.argv[1].lower() + if cmd == 'patch': + do_patch() + return + elif cmd == 'restore': + do_restore() + return + elif cmd == 'status': + check_status() + return + else: + print(' Usage: python bandizip_patcher.py [patch|restore|status]') + return + + # 交互模式 + print(' Commands:') + print(' 1. Patch - Apply all patches') + print(' 2. Restore - Restore original file') + print(' 3. Status - Check current status') + print(' 4. Exit') + print('') + + try: + choice = input(' Select [1-4]: ').strip() + except EOFError: + choice = '1' + + if choice == '1': + do_patch() + elif choice == '2': + do_restore() + elif choice == '3': + check_status() + else: + print(' Bye!') + + +if __name__ == '__main__': + main()