#!/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 # ============ 配置 ============ REG_KEY = r'SOFTWARE\Bandizip' REG_VALUE = 'Edition' REG_DATA = 'PRO' def find_bandizip_dir(): """自动查找 Bandizip 安装目录""" # 方法1: 注册表 HKLM\SOFTWARE\Bandizip\ProgramFolder try: with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, REG_KEY) as key: path, _ = winreg.QueryValueEx(key, 'ProgramFolder') if path and os.path.exists(os.path.join(path, 'Bandizip.exe')): return path.rstrip('\\') except Exception: pass # 方法2: 注册表卸载信息 for subkey in [r'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Bandizip', r'SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Bandizip']: try: with winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, subkey) as key: loc, _ = winreg.QueryValueEx(key, 'InstallLocation') if loc and os.path.exists(os.path.join(loc, 'Bandizip.exe')): return loc.rstrip('\\') except Exception: pass # 方法3: 常见安装路径 common_paths = [ os.path.join(os.environ.get('ProgramFiles', r'C:\Program Files'), 'Bandizip'), os.path.join(os.environ.get('ProgramFiles(x86)', r'C:\Program Files (x86)'), 'Bandizip'), os.path.join(os.environ.get('LOCALAPPDATA', ''), 'Programs', 'Bandizip'), r'D:\Apps\Bandizip', r'D:\Program Files\Bandizip', ] for p in common_paths: if os.path.exists(os.path.join(p, 'Bandizip.exe')): return p return None # 启动时自动检测(可通过环境变量 BANDIZIP_DIR 手动覆盖) BANDIZIP_DIR = os.environ.get('BANDIZIP_DIR') or find_bandizip_dir() EXE_PATH = os.path.join(BANDIZIP_DIR, 'Bandizip.exe') if BANDIZIP_DIR else None BACKUP_PATH = (EXE_PATH + '.bak') if EXE_PATH else None # 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 EXE_PATH and os.path.exists(EXE_PATH): print(' [OK] Bandizip.exe found: ' + EXE_PATH) else: print(' [!] Bandizip.exe not found!') print(' [!] Tried registry, uninstall info, and common paths.') print(' [!] Please pass install dir manually:') print(' [!] set BANDIZIP_DIR=C:\\path\\to\\Bandizip') 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 EXE_PATH or not os.path.exists(EXE_PATH): print(' [!] Bandizip.exe not found!') 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()