ArticleReplaceBatch/deepseek-clien/machine_code.py
2025-08-06 15:57:14 +08:00

369 lines
12 KiB
Python

import hashlib
import platform
import subprocess
import sys
import os
import uuid
from pathlib import Path
class MachineCodeGenerator:
"""机器码生成器,支持多种方法生成唯一的机器标识"""
def __init__(self):
self.cache_file = Path.home() / ".exe_encrypt_machine_id"
self.system = platform.system()
def _run_command(self, cmd, shell=True):
"""安全执行系统命令"""
try:
if isinstance(cmd, str):
cmd_list = cmd.split() if not shell else cmd
else:
cmd_list = cmd
result = subprocess.run(
cmd_list,
shell=shell,
capture_output=True,
text=True,
timeout=10,
creationflags=subprocess.CREATE_NO_WINDOW if sys.platform == "win32" else 0
)
if result.returncode == 0:
return result.stdout.strip()
return None
except Exception:
return None
def get_windows_machine_code(self):
"""获取Windows系统的机器码"""
identifiers = []
# 方法1: 获取主板序列号
try:
output = self._run_command('wmic baseboard get serialnumber /value')
if output:
for line in output.split('\n'):
if 'SerialNumber=' in line:
serial = line.split('=')[1].strip()
if serial and serial.lower() not in ['to be filled by o.e.m.', '']:
identifiers.append(('motherboard', serial))
except:
pass
# 方法2: 获取CPU信息
try:
output = self._run_command('wmic cpu get processorid /value')
if output:
for line in output.split('\n'):
if 'ProcessorId=' in line:
cpu_id = line.split('=')[1].strip()
if cpu_id:
identifiers.append(('cpu', cpu_id))
except:
pass
# 方法3: 获取BIOS信息
try:
output = self._run_command('wmic bios get serialnumber /value')
if output:
for line in output.split('\n'):
if 'SerialNumber=' in line:
bios_serial = line.split('=')[1].strip()
if bios_serial and bios_serial.lower() not in ['to be filled by o.e.m.', '']:
identifiers.append(('bios', bios_serial))
except:
pass
# 方法4: 获取硬盘序列号
try:
output = self._run_command('wmic diskdrive get serialnumber /value')
if output:
for line in output.split('\n'):
if 'SerialNumber=' in line:
disk_serial = line.split('=')[1].strip()
if disk_serial and len(disk_serial) > 5:
identifiers.append(('disk', disk_serial))
break # 只取第一个有效的硬盘序列号
except:
pass
# 方法5: 获取网卡MAC地址
try:
output = self._run_command('getmac /v /fo csv')
if output:
lines = output.split('\n')
for line in lines[1:]: # 跳过标题行
if ',' in line and 'Physical Address' in line:
parts = line.split(',')
if len(parts) > 2:
mac = parts[2].strip('"').replace('-', ':')
if len(mac) == 17 and mac != "N/A":
identifiers.append(('mac', mac))
break
except:
pass
# 如果没有获取到硬件标识符,使用系统信息
if not identifiers:
identifiers.append(('system', f"{platform.node()}-{platform.processor()}"))
return identifiers
def get_linux_machine_code(self):
"""获取Linux系统的机器码"""
identifiers = []
# 方法1: 机器ID
try:
machine_id_file = Path('/etc/machine-id')
if machine_id_file.exists():
machine_id = machine_id_file.read_text().strip()
if machine_id:
identifiers.append(('machine_id', machine_id))
except:
pass
# 方法2: DMI信息
try:
output = self._run_command('dmidecode -s system-serial-number')
if output and output.lower() not in ['not specified', 'to be filled by o.e.m.']:
identifiers.append(('system_serial', output))
except:
pass
# 方法3: CPU信息
try:
cpuinfo = Path('/proc/cpuinfo')
if cpuinfo.exists():
content = cpuinfo.read_text()
for line in content.split('\n'):
if 'Serial' in line and ':' in line:
serial = line.split(':')[1].strip()
if serial and serial != '0000000000000000':
identifiers.append(('cpu_serial', serial))
break
except:
pass
# 方法4: MAC地址
try:
output = self._run_command('cat /sys/class/net/*/address')
if output:
for line in output.split('\n'):
mac = line.strip()
if len(mac) == 17 and mac != '00:00:00:00:00:00':
identifiers.append(('mac', mac))
break
except:
pass
# 备用方法: 使用hostname和架构
if not identifiers:
identifiers.append(('system', f"{platform.node()}-{platform.machine()}"))
return identifiers
def get_mac_machine_code(self):
"""获取macOS系统的机器码"""
identifiers = []
# 方法1: 硬件UUID
try:
output = self._run_command('system_profiler SPHardwareDataType | grep "Hardware UUID"')
if output and ':' in output:
uuid = output.split(':')[1].strip()
if uuid:
identifiers.append(('hardware_uuid', uuid))
except:
pass
# 方法2: 序列号
try:
output = self._run_command('system_profiler SPHardwareDataType | grep "Serial Number"')
if output and ':' in output:
serial = output.split(':')[1].strip()
if serial:
identifiers.append(('serial', serial))
except:
pass
# 方法3: MAC地址
try:
output = self._run_command('ifconfig en0 | grep ether')
if output:
mac = output.split()[1]
if mac:
identifiers.append(('mac', mac))
except:
pass
# 备用方法
if not identifiers:
identifiers.append(('system', f"{platform.node()}-{platform.processor()}"))
return identifiers
def get_cached_machine_code(self):
"""获取缓存的机器码"""
try:
if self.cache_file.exists():
cached_code = self.cache_file.read_text().strip()
if len(cached_code) == 16: # 验证格式
return cached_code
except:
pass
return None
def save_machine_code(self, machine_code):
"""保存机器码到缓存"""
try:
self.cache_file.parent.mkdir(parents=True, exist_ok=True)
self.cache_file.write_text(machine_code)
# 设置只读权限
if self.system == "Windows":
import stat
self.cache_file.chmod(stat.S_IREAD)
else:
os.chmod(self.cache_file, 0o444)
except:
pass
def generate_machine_code(self):
"""生成机器码"""
# 首先尝试从缓存读取
cached_code = self.get_cached_machine_code()
if cached_code:
return cached_code
# 根据系统获取硬件标识符
if self.system == "Windows":
identifiers = self.get_windows_machine_code()
elif self.system == "Linux":
identifiers = self.get_linux_machine_code()
elif self.system == "Darwin": # macOS
identifiers = self.get_mac_machine_code()
else:
# 未知系统,使用通用方法
identifiers = [('system', f"{platform.node()}-{platform.processor()}-{platform.system()}")]
# 组合所有标识符
combined_data = ""
for identifier_type, identifier_value in identifiers:
combined_data += f"{identifier_type}:{identifier_value}|"
# 添加一些系统固定信息作为增强
combined_data += f"os:{platform.system()}|"
combined_data += f"arch:{platform.machine()}|"
# 生成哈希
hash_obj = hashlib.sha256(combined_data.encode('utf-8'))
machine_code = hash_obj.hexdigest()[:16].upper()
# 保存到缓存
self.save_machine_code(machine_code)
return machine_code
def get_detailed_info(self):
"""获取详细的机器信息(用于调试)"""
info = {
"system": platform.system(),
"release": platform.release(),
"version": platform.version(),
"machine": platform.machine(),
"processor": platform.processor(),
"node": platform.node(),
"python_version": platform.python_version(),
}
# 获取硬件标识符
if self.system == "Windows":
identifiers = self.get_windows_machine_code()
elif self.system == "Linux":
identifiers = self.get_linux_machine_code()
elif self.system == "Darwin":
identifiers = self.get_mac_machine_code()
else:
identifiers = []
info["hardware_identifiers"] = identifiers
info["machine_code"] = self.generate_machine_code()
info["cache_file"] = str(self.cache_file)
info["cache_exists"] = self.cache_file.exists()
return info
# 全局实例
_machine_code_generator = MachineCodeGenerator()
def get_machine_code():
"""获取当前系统的机器码(主要接口函数)"""
return _machine_code_generator.generate_machine_code()
def get_machine_info():
"""获取详细的机器信息"""
return _machine_code_generator.get_detailed_info()
def reset_machine_code():
"""重置机器码缓存"""
try:
if _machine_code_generator.cache_file.exists():
_machine_code_generator.cache_file.unlink()
return True
except:
return False
def verify_machine_code_stability():
"""验证机器码的稳定性(多次生成应该相同)"""
codes = []
for _ in range(3):
# 清除缓存,重新生成
reset_machine_code()
code = get_machine_code()
codes.append(code)
# 检查是否都相同
stable = all(code == codes[0] for code in codes)
return stable, codes
if __name__ == "__main__":
print("=== 机器码生成器测试 ===")
# 获取机器码
machine_code = get_machine_code()
print(f"机器码: {machine_code}")
# 获取详细信息
info = get_machine_info()
print(f"\n=== 系统信息 ===")
print(f"系统: {info['system']} {info['release']}")
print(f"架构: {info['machine']}")
print(f"处理器: {info['processor']}")
print(f"主机名: {info['node']}")
print(f"Python版本: {info['python_version']}")
print(f"\n=== 硬件标识符 ===")
for identifier_type, identifier_value in info['hardware_identifiers']:
print(f"{identifier_type}: {identifier_value}")
print(f"\n=== 缓存信息 ===")
print(f"缓存文件: {info['cache_file']}")
print(f"缓存存在: {info['cache_exists']}")
# 稳定性测试
print(f"\n=== 稳定性测试 ===")
stable, codes = verify_machine_code_stability()
print(f"稳定性: {'通过' if stable else '失败'}")
print(f"测试结果: {codes}")
if not stable:
print("⚠️ 警告: 机器码不稳定,可能导致授权问题!")