369 lines
12 KiB
Python
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("⚠️ 警告: 机器码不稳定,可能导致授权问题!") |