上传文件至 /

This commit is contained in:
taiyi 2025-09-05 11:53:09 +08:00
parent 3211d7d999
commit e48e6bc314

247
wrapper.py Normal file
View File

@ -0,0 +1,247 @@
# wrapper_embed.py 由 PyInstaller 打包,运行时提取并解密原始 EXE
import os, sys, json, hashlib, tempfile, subprocess, struct
from datetime import datetime
import mysql.connector
import tkinter as tk
from tkinter import messagebox
import platform
MAGIC = b'ENC_MAGIC'
HEAD = 512
KEY = b'EXEWrapper#2024'
def xor(data):
return bytes(d ^ KEY[i % len(KEY)] for i, d in enumerate(data))
def get_machine_code():
import uuid
return hashlib.md5(str(uuid.getnode()).encode()).hexdigest()[:16].upper()
def validate(key, machine):
try:
conn = mysql.connector.connect(
host='taiyiagi.xyz', user='taiyi', password='taiyi1224',
database='filesend', connection_timeout=10, autocommit=True
)
cur = conn.cursor(dictionary=True)
cur.execute('SELECT * FROM license_keys WHERE key_code=%s', (key,))
print("验证激活码")
rec = cur.fetchone()
if not rec: return False, '激活码不存在'
if rec['status'] == 'banned': return False, '激活码被封禁'
if rec['end_time'] < datetime.now(): return False, '激活码已过期'
if rec['status'] == 'active':
return (True, '验证成功') if rec['machine_code'] == machine else (False, '激活码已绑定其他设备')
if rec['status'] == 'unused':
cur.execute('UPDATE license_keys SET status=%s, machine_code=%s, start_time=NOW() WHERE key_code=%s',
('active', machine, key))
return cur.rowcount > 0, '激活成功' if cur.rowcount else '激活失败'
return False, '激活码状态异常'
except Exception as e:
return False, str(e)
def get_bundled_data_path():
"""获取打包数据文件路径"""
if getattr(sys, 'frozen', False):
# 如果是打包后的exe数据文件在临时目录中
bundle_dir = sys._MEIPASS
else:
# 如果是脚本运行,数据文件在当前目录
bundle_dir = os.path.dirname(os.path.abspath(__file__))
# 查找 .dat 文件
for file in os.listdir(bundle_dir):
if file.endswith('.dat'):
return os.path.join(bundle_dir, file)
return None
def extract_exe():
"""从打包的数据文件中提取并解密原始EXE"""
try:
# 首先尝试从打包的数据文件中读取
data_file = get_bundled_data_path()
if data_file and os.path.exists(data_file):
with open(data_file, 'rb') as f:
data = f.read()
else:
# 如果没有找到数据文件尝试从当前exe文件末尾读取
if getattr(sys, 'frozen', False):
exe = sys.executable
with open(exe, 'rb') as f:
data = f.read()
else:
print("未找到加密数据文件")
return None
# 查找魔数位置
pos = data.find(MAGIC)
if pos == -1:
print("未找到加密数据标识")
return None
pos += len(MAGIC)
# 读取头部信息
if pos + HEAD > len(data):
print("数据文件损坏:头部信息不完整")
return None
header_data = data[pos:pos + HEAD].rstrip(b'\0')
try:
hdr = json.loads(header_data.decode())
except json.JSONDecodeError as e:
print(f"头部信息解析失败: {e}")
return None
pos += HEAD
# 解密数据
if pos >= len(data):
print("数据文件损坏:没有加密数据")
return None
encrypted_data = data[pos:]
if len(encrypted_data) == 0:
print("加密数据为空")
return None
dec = xor(encrypted_data)
# 验证文件完整性
if hashlib.sha256(dec).hexdigest() != hdr['hash']:
print("文件完整性校验失败")
return None
if len(dec) != hdr['size']:
print(f"文件大小不匹配,期望: {hdr['size']}, 实际: {len(dec)}")
return None
# 写入临时文件
temp_dir = tempfile.gettempdir()
filename = hdr['filename']
tmp = os.path.join(temp_dir, f"temp_{os.getpid()}_{filename}")
try:
with open(tmp, 'wb') as f:
f.write(dec)
# 设置可执行权限
if hasattr(os, 'chmod'):
os.chmod(tmp, 0o755)
print(f"成功提取文件到: {tmp}")
return tmp
except Exception as e:
print(f"写入临时文件失败: {e}")
return None
except Exception as e:
print(f"提取EXE文件时发生错误: {e}")
return None
def run(path):
"""运行解密后的程序"""
try:
if not os.path.exists(path):
print(f"文件不存在: {path}")
return False
print(f"正在启动程序: {path}")
if os.name == 'nt': # Windows
# 使用 CREATE_NEW_CONSOLE 标志在新窗口中启动
import subprocess
subprocess.Popen([path],
creationflags=subprocess.CREATE_NEW_CONSOLE,
close_fds=False)
else: # Linux/macOS
subprocess.Popen([path], close_fds=True)
# 给程序一些启动时间
import time
time.sleep(1)
return True
except Exception as e:
print(f"启动程序失败: {e}")
return False
def gui():
def ok():
k = e.get().strip()
if not k:
return messagebox.showerror('错误', '请输入激活码')
try:
m = get_machine_code()
success, msg = validate(k, m)
if success:
messagebox.showinfo('成功', '激活成功!正在启动程序...')
root.destroy()
# 提取并运行程序
exe = extract_exe()
if exe:
if run(exe):
print("程序启动成功")
# 延迟退出,给目标程序启动时间
import time
time.sleep(2)
sys.exit(0)
else:
messagebox.showerror('错误', '程序启动失败')
else:
messagebox.showerror('错误', '无法提取程序文件,请检查文件完整性')
else:
messagebox.showerror('失败', msg)
except Exception as e:
messagebox.showerror('错误', f'验证过程出错: {str(e)}')
root = tk.Tk()
root.title('软件激活')
root.geometry('400x200')
root.resizable(False, False)
# 居中显示窗口
root.eval('tk::PlaceWindow . center')
# 界面元素
tk.Label(root, text='请输入激活码', font=('', 13)).pack(pady=15)
e = tk.Entry(root, width=25)
e.pack()
e.focus()
tk.Button(root, text='验证并启动', command=ok).pack(pady=15)
# 显示机器码(用于调试)
machine_code = get_machine_code()
tk.Label(root, text=f'机器码: {machine_code}', font=('', 8), fg='gray').pack(pady=(10, 0))
root.bind('<Return>', lambda x: ok())
root.protocol('WM_DELETE_WINDOW', sys.exit)
root.mainloop()
if __name__ == '__main__':
# 添加调试信息
print("程序启动...")
print(f"Python版本: {sys.version}")
print(f"当前工作目录: {os.getcwd()}")
print(f"是否为打包环境: {getattr(sys, 'frozen', False)}")
if getattr(sys, 'frozen', False):
print(f"打包临时目录: {sys._MEIPASS}")
print(f"打包临时目录内容: {os.listdir(sys._MEIPASS)}")
gui()