2026-07-31 07:21:27 +08:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
"""
|
|
|
|
|
Honeycam Professional Patcher & Keygen
|
|
|
|
|
=======================================
|
|
|
|
|
一键补丁工具与注册码生成器。
|
|
|
|
|
|
|
|
|
|
使用方法:
|
|
|
|
|
python honeycam_patcher.py # 交互模式
|
|
|
|
|
python honeycam_patcher.py patch # 应用补丁
|
|
|
|
|
python honeycam_patcher.py restore # 恢复原始
|
|
|
|
|
python honeycam_patcher.py status # 检查状态
|
|
|
|
|
python honeycam_keygen.py email # 生成注册码
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
import os
|
|
|
|
|
import sys
|
|
|
|
|
import shutil
|
|
|
|
|
import random
|
|
|
|
|
import string
|
|
|
|
|
import hashlib
|
|
|
|
|
import winreg
|
|
|
|
|
|
|
|
|
|
# ============ 配置 ============
|
|
|
|
|
REG_KEY = r'SOFTWARE\Honeycam'
|
|
|
|
|
REG_VALUE = 'Edition'
|
|
|
|
|
REG_DATA = 'PRO'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def find_honeycam_dir():
|
|
|
|
|
"""自动查找 Honeycam 安装目录"""
|
|
|
|
|
# 方法1: 注册表
|
|
|
|
|
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, 'Honeycam.exe')):
|
|
|
|
|
return path.rstrip('\\')
|
|
|
|
|
except Exception:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
# 方法2: 卸载信息
|
|
|
|
|
for subkey in [r'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Honeycam',
|
|
|
|
|
r'SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Honeycam']:
|
|
|
|
|
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, 'Honeycam.exe')):
|
|
|
|
|
return loc.rstrip('\\')
|
|
|
|
|
except Exception:
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
# 方法3: 常见路径
|
|
|
|
|
common_paths = [
|
|
|
|
|
os.path.join(os.environ.get('ProgramFiles', r'C:\Program Files'), 'Honeycam'),
|
|
|
|
|
os.path.join(os.environ.get('ProgramFiles(x86)', r'C:\Program Files (x86)'), 'Honeycam'),
|
|
|
|
|
r'D:\Apps\Honeycam',
|
|
|
|
|
]
|
|
|
|
|
for p in common_paths:
|
|
|
|
|
if os.path.exists(os.path.join(p, 'Honeycam.exe')):
|
|
|
|
|
return p
|
|
|
|
|
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BANDIZIP_DIR = os.environ.get('HONEYCAM_DIR') or find_honeycam_dir()
|
|
|
|
|
EXE_PATH = os.path.join(BANDIZIP_DIR, 'Honeycam.exe') if BANDIZIP_DIR else None
|
|
|
|
|
BACKUP_PATH = (EXE_PATH + '.bak') if EXE_PATH else None
|
|
|
|
|
|
|
|
|
|
# Patch 定义: (文件偏移, 原始字节, 补丁字节, 描述)
|
|
|
|
|
PATCHES = [
|
|
|
|
|
(0x154EB0, b'\x48\x89\x54\x24\x10\x53', b'\xB0\x01\xC3',
|
|
|
|
|
'sub_1401558B0 (Edition read -> return 1)'),
|
|
|
|
|
(0x1577D0, b'\x4C\x89\x4C\x24\x20\x4C', b'\xB0\x01\xC3',
|
|
|
|
|
'sub_1401581D0 (online verify -> return 1)'),
|
|
|
|
|
(0x0F8F09, b'\x0F\x85\x51\x05\x00\x00', b'\x90\x90\x90\x90\x90\x90',
|
|
|
|
|
'NOP: key length check'),
|
|
|
|
|
(0x0F8F16, b'\x0F\x8C\x44\x05\x00\x00', b'\x90\x90\x90\x90\x90\x90',
|
|
|
|
|
'NOP: data validity check'),
|
|
|
|
|
(0x0F8F2B, b'\x0F\x84\x2F\x05\x00\x00', b'\x90\x90\x90\x90\x90\x90',
|
|
|
|
|
'NOP: @ symbol check'),
|
|
|
|
|
(0x0F8F39, b'\x0F\x8E\x21\x05\x00\x00', b'\x90\x90\x90\x90\x90\x90',
|
|
|
|
|
'NOP: @ position check'),
|
2026-07-31 07:26:45 +08:00
|
|
|
(0x0F8F54, b'\x74\x1B', b'\xEB\x1B',
|
|
|
|
|
'jz -> jmp (skip lm.dll key validation)'),
|
2026-07-31 07:21:27 +08:00
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def is_patched():
|
|
|
|
|
if not EXE_PATH or 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)
|
|
|
|
|
if f.read(len(patch)) != patch:
|
|
|
|
|
return False
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def is_backup_exists():
|
|
|
|
|
return BACKUP_PATH and os.path.exists(BACKUP_PATH)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def is_honeycam_running():
|
|
|
|
|
try:
|
|
|
|
|
import subprocess
|
|
|
|
|
result = subprocess.run(['tasklist', '/FI', 'IMAGENAME eq Honeycam.exe'],
|
|
|
|
|
capture_output=True, text=True, timeout=5)
|
|
|
|
|
return 'Honeycam.exe' in result.stdout
|
|
|
|
|
except Exception:
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def kill_honeycam():
|
|
|
|
|
try:
|
|
|
|
|
import subprocess
|
|
|
|
|
subprocess.run(['taskkill', '/F', '/IM', 'Honeycam.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')
|
|
|
|
|
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():
|
|
|
|
|
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] ' + desc)
|
|
|
|
|
continue
|
|
|
|
|
f.seek(offset)
|
|
|
|
|
f.write(patch)
|
|
|
|
|
print(' [OK] ' + desc)
|
|
|
|
|
return True
|
|
|
|
|
except PermissionError:
|
|
|
|
|
print(' [!] Permission denied. Close Honeycam 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')
|
|
|
|
|
return False
|
|
|
|
|
try:
|
|
|
|
|
shutil.copy2(BACKUP_PATH, EXE_PATH)
|
|
|
|
|
print(' [OK] Restored from backup')
|
|
|
|
|
return True
|
|
|
|
|
except PermissionError:
|
|
|
|
|
print(' [!] Permission denied. Close Honeycam and run as Administrator.')
|
|
|
|
|
return False
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print(' [!] Restore failed: ' + str(e))
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def set_registry():
|
|
|
|
|
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: Edition = ' + 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(' Honeycam Patcher - Status')
|
|
|
|
|
print('=' * 50)
|
|
|
|
|
|
|
|
|
|
if EXE_PATH and os.path.exists(EXE_PATH):
|
|
|
|
|
print(' [OK] Honeycam.exe: ' + EXE_PATH)
|
|
|
|
|
else:
|
|
|
|
|
print(' [!] Honeycam.exe not found!')
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
if is_backup_exists():
|
|
|
|
|
print(' [OK] Backup exists')
|
|
|
|
|
else:
|
|
|
|
|
print(' [!] No backup')
|
|
|
|
|
|
|
|
|
|
patched_count = 0
|
|
|
|
|
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('\n Patched: ' + str(patched_count) + '/' + str(len(PATCHES)))
|
|
|
|
|
|
|
|
|
|
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_honeycam_running():
|
|
|
|
|
print(' [WARNING] Honeycam is running!')
|
|
|
|
|
else:
|
|
|
|
|
print(' [OK] Honeycam is not running')
|
|
|
|
|
|
|
|
|
|
print('=' * 50)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def do_patch():
|
|
|
|
|
print('=' * 50)
|
|
|
|
|
print(' Honeycam Patcher - Apply')
|
|
|
|
|
print('=' * 50)
|
|
|
|
|
|
|
|
|
|
if not EXE_PATH or not os.path.exists(EXE_PATH):
|
|
|
|
|
print(' [!] Honeycam.exe not found!')
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
if is_honeycam_running():
|
|
|
|
|
print(' [..] Honeycam is running, closing...')
|
|
|
|
|
if not kill_honeycam():
|
|
|
|
|
print(' [!] Cannot close Honeycam.')
|
|
|
|
|
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!')
|
|
|
|
|
print('=' * 50)
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def do_restore():
|
|
|
|
|
print('=' * 50)
|
|
|
|
|
print(' Honeycam Patcher - Restore')
|
|
|
|
|
print('=' * 50)
|
|
|
|
|
|
|
|
|
|
if is_honeycam_running():
|
|
|
|
|
print(' [..] Honeycam is running, closing...')
|
|
|
|
|
if not kill_honeycam():
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
print('\n [1/1] Restoring...')
|
|
|
|
|
if restore():
|
|
|
|
|
print('\n' + '=' * 50)
|
|
|
|
|
print(' [DONE] Restored to original.')
|
|
|
|
|
print('=' * 50)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def generate_keygen(email):
|
2026-07-31 07:40:58 +08:00
|
|
|
"""生成注册码
|
|
|
|
|
|
|
|
|
|
Honeycam 注册码格式: 26 字符
|
|
|
|
|
- 前 8 位: 日期 YYYYMMDD (正则 [2][0-1][0-9][0-9][0-1][0-9][0-3][0-9])
|
|
|
|
|
- 后 18 位: 任意字符
|
|
|
|
|
"""
|
|
|
|
|
import datetime
|
2026-07-31 07:21:27 +08:00
|
|
|
seed = int(hashlib.md5(email.encode()).hexdigest()[:8], 16)
|
|
|
|
|
rng = random.Random(seed)
|
2026-07-31 07:40:58 +08:00
|
|
|
|
|
|
|
|
# 前 8 位: 日期 (2019-2021 年范围, 匹配正则 [2][0-1][0-9][0-9])
|
|
|
|
|
year = rng.randint(2019, 2021)
|
|
|
|
|
month = rng.randint(1, 12)
|
|
|
|
|
day = rng.randint(1, 28)
|
|
|
|
|
date_prefix = f"{year}{month:02d}{day:02d}"
|
|
|
|
|
|
|
|
|
|
# 后 18 位: 随机字符
|
|
|
|
|
charset = string.ascii_letters + string.digits
|
|
|
|
|
suffix = ''.join(rng.choices(charset, k=18))
|
|
|
|
|
|
|
|
|
|
return date_prefix + suffix
|
2026-07-31 07:21:27 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def do_keygen():
|
|
|
|
|
if len(sys.argv) > 2:
|
|
|
|
|
email = sys.argv[2]
|
|
|
|
|
else:
|
|
|
|
|
email = input(' Email: ').strip()
|
|
|
|
|
if not email:
|
|
|
|
|
email = 'user@honeycam.local'
|
|
|
|
|
|
|
|
|
|
key = generate_keygen(email)
|
|
|
|
|
print('\n Email: ' + email)
|
|
|
|
|
print(' Product Key: ' + key)
|
|
|
|
|
print(' Edition: PRO')
|
|
|
|
|
print('\n Open Honeycam -> Help -> Register')
|
|
|
|
|
print(' Enter the email and product key above.')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
|
print('=' * 50)
|
|
|
|
|
print(' Honeycam Professional Patcher v1.0')
|
|
|
|
|
print('=' * 50)
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
elif cmd == 'keygen':
|
|
|
|
|
do_keygen()
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
print('\n Commands:')
|
|
|
|
|
print(' 1. Patch - Apply all patches')
|
|
|
|
|
print(' 2. Restore - Restore original')
|
|
|
|
|
print(' 3. Status - Check status')
|
|
|
|
|
print(' 4. Keygen - Generate product key')
|
|
|
|
|
print(' 5. Exit')
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
choice = input('\n Select [1-5]: ').strip()
|
|
|
|
|
except EOFError:
|
|
|
|
|
choice = '1'
|
|
|
|
|
|
|
|
|
|
if choice == '1':
|
|
|
|
|
do_patch()
|
|
|
|
|
elif choice == '2':
|
|
|
|
|
do_restore()
|
|
|
|
|
elif choice == '3':
|
|
|
|
|
check_status()
|
|
|
|
|
elif choice == '4':
|
|
|
|
|
do_keygen()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
|
main()
|