Initial commit: Bandizip Professional Patcher & Keygen
- bandizip_patcher.py: one-click patcher (backup/patch/restore/status) - bandizip_keygen.py: product key generator - 8 patches, 35 bytes total
This commit is contained in:
@@ -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()
|
||||
Reference in New Issue
Block a user