添加 Cash_Based/S_AiLQ_loader.py
This commit is contained in:
282
Cash_Based/S_AiLQ_loader.py
Normal file
282
Cash_Based/S_AiLQ_loader.py
Normal file
@@ -0,0 +1,282 @@
|
|||||||
|
# cron: 8 5 * * *
|
||||||
|
# const $ = new Env('爱路桥阅读');
|
||||||
|
"""
|
||||||
|
本工具仅用于学习 Python 加密与逆向工程技术,供研究和教学用途。
|
||||||
|
请勿将其用于任何非法用途,包括但不限于: 加密恶意脚本 | 逃避安全审计 | 攻击他人系统 | 商业软件加壳绕过
|
||||||
|
任何使用本工具所造成的直接或间接后果,包括但不限于法律责任、安全问题、数据损失,均由使用者自行承担,作者不对此承担任何责任。
|
||||||
|
如果您不同意此免责声明,请立即停止使用并删除本文件。
|
||||||
|
|
||||||
|
Developed by Python Vorto加密系统
|
||||||
|
|
||||||
|
所需要的变量名称及格式,请运行脚本查看!
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import hashlib
|
||||||
|
import json
|
||||||
|
import importlib.util
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Optional, Dict, Any
|
||||||
|
|
||||||
|
# 配置(请勿修改)
|
||||||
|
PROJECT_ID = "dd22bb8b-d9d5-4489-89e7-609fcbd4b697"
|
||||||
|
BASE_URL = "https://auth.vzvv.de"
|
||||||
|
SO_FILENAME = "S_ALQ"
|
||||||
|
SO_DIR = "S_SOFILE"
|
||||||
|
VERSION_FILE = os.path.join(SO_DIR, ".{0}_version.json".format("S_ALQ"))
|
||||||
|
ENTRY_FUNCTION = "main"
|
||||||
|
|
||||||
|
# 确保SO文件目录存在
|
||||||
|
if not os.path.exists(SO_DIR):
|
||||||
|
os.makedirs(SO_DIR)
|
||||||
|
|
||||||
|
|
||||||
|
def get_python_version() -> str:
|
||||||
|
return "{0}.{1}".format(sys.version_info.major, sys.version_info.minor)
|
||||||
|
|
||||||
|
|
||||||
|
def calculate_md5(file_path: str) -> str:
|
||||||
|
"""计算文件的MD5哈希值"""
|
||||||
|
md5_hash = hashlib.md5()
|
||||||
|
try:
|
||||||
|
with open(file_path, "rb") as f:
|
||||||
|
for chunk in iter(lambda: f.read(4096), b""):
|
||||||
|
md5_hash.update(chunk)
|
||||||
|
return md5_hash.hexdigest()
|
||||||
|
except Exception as ex:
|
||||||
|
print("计算MD5失败: {0}".format(ex))
|
||||||
|
return ""
|
||||||
|
|
||||||
|
|
||||||
|
def load_local_version() -> Optional[Dict[str, Any]]:
|
||||||
|
"""加载本地版本信息"""
|
||||||
|
if not os.path.exists(VERSION_FILE):
|
||||||
|
return None
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(VERSION_FILE, 'r', encoding='utf-8') as f:
|
||||||
|
return json.load(f)
|
||||||
|
except Exception as ex:
|
||||||
|
print("读取本地版本信息失败: {0}".format(ex))
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def save_local_version(version_info: Dict[str, Any]):
|
||||||
|
"""保存本地版本信息"""
|
||||||
|
try:
|
||||||
|
with open(VERSION_FILE, 'w', encoding='utf-8') as f:
|
||||||
|
json.dump(version_info, f, indent=2, ensure_ascii=False)
|
||||||
|
except Exception as ex:
|
||||||
|
print("保存版本信息失败: {0}".format(ex))
|
||||||
|
|
||||||
|
|
||||||
|
def check_server_version() -> Optional[Dict[str, Any]]:
|
||||||
|
"""检查服务器上的活跃版本信息"""
|
||||||
|
try:
|
||||||
|
import urllib.request
|
||||||
|
import urllib.error
|
||||||
|
|
||||||
|
url = "{0}/api/version/{1}".format(BASE_URL, PROJECT_ID)
|
||||||
|
|
||||||
|
try:
|
||||||
|
with urllib.request.urlopen(url, timeout=10) as response:
|
||||||
|
data = response.read()
|
||||||
|
return json.loads(data.decode('utf-8'))
|
||||||
|
except urllib.error.HTTPError as ex:
|
||||||
|
if ex.code == 404:
|
||||||
|
print("项目不存在或没有活跃版本")
|
||||||
|
else:
|
||||||
|
print("查询版本失败 (HTTP {0}): {1}".format(ex.code, ex.reason))
|
||||||
|
return None
|
||||||
|
except urllib.error.URLError as ex:
|
||||||
|
print("网络连接失败: {0}".format(ex.reason))
|
||||||
|
return None
|
||||||
|
|
||||||
|
except ImportError:
|
||||||
|
print("urllib模块不可用,无法检查更新")
|
||||||
|
return None
|
||||||
|
except Exception as ex:
|
||||||
|
print("检查服务器版本失败: {0}".format(ex))
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def fetch_changelog(version_id: str) -> Optional[str]:
|
||||||
|
"""获取指定版本的更新描述"""
|
||||||
|
try:
|
||||||
|
import urllib.request
|
||||||
|
import urllib.error
|
||||||
|
|
||||||
|
url = "{0}/api/changelog/{1}".format(BASE_URL, PROJECT_ID)
|
||||||
|
|
||||||
|
try:
|
||||||
|
with urllib.request.urlopen(url, timeout=10) as response:
|
||||||
|
data = response.read()
|
||||||
|
changelog_data = json.loads(data.decode('utf-8'))
|
||||||
|
|
||||||
|
# 查找匹配版本的描述
|
||||||
|
for item in changelog_data.get('changelog', []):
|
||||||
|
if item.get('version_id') == version_id:
|
||||||
|
return item.get('description', '')
|
||||||
|
return None
|
||||||
|
except Exception:
|
||||||
|
return None
|
||||||
|
except Exception:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def print_update_info(version_info: Dict[str, Any]):
|
||||||
|
"""打印更新信息"""
|
||||||
|
print("=" * 50)
|
||||||
|
print("【更新日志】版本 {0}".format(version_info['version_number']))
|
||||||
|
print("-" * 50)
|
||||||
|
|
||||||
|
# 尝试获取版本描述
|
||||||
|
desc = fetch_changelog(version_info['version_id'])
|
||||||
|
if desc:
|
||||||
|
print(desc)
|
||||||
|
else:
|
||||||
|
print("(无更新说明)")
|
||||||
|
|
||||||
|
print("-" * 50)
|
||||||
|
print("查看更多更新日志: {0}/changelog/{1}".format(BASE_URL, PROJECT_ID))
|
||||||
|
print("=" * 50)
|
||||||
|
|
||||||
|
|
||||||
|
def download_so_file(version_info: Dict[str, Any]) -> bool:
|
||||||
|
"""下载SO文件"""
|
||||||
|
try:
|
||||||
|
import urllib.request
|
||||||
|
|
||||||
|
python_ver = get_python_version()
|
||||||
|
version_id = version_info['version_id']
|
||||||
|
|
||||||
|
# 构建下载URL
|
||||||
|
url = "{0}/api/download/{1}/{2}/{3}".format(BASE_URL, PROJECT_ID, version_id, python_ver)
|
||||||
|
|
||||||
|
# 确定SO文件名(包含Python版本),保存到SO_DIR目录
|
||||||
|
so_file = os.path.join(SO_DIR, "{0}_{1}.so".format(SO_FILENAME, python_ver.replace('.', '')))
|
||||||
|
|
||||||
|
print("正在下载版本 {0}...".format(version_info['version_number']))
|
||||||
|
|
||||||
|
# 下载文件
|
||||||
|
urllib.request.urlretrieve(url, so_file)
|
||||||
|
|
||||||
|
# 验证文件完整性(使用对应Python版本的MD5)
|
||||||
|
md5_hashes = version_info.get('md5_hashes', {})
|
||||||
|
expected_md5 = md5_hashes.get(python_ver)
|
||||||
|
|
||||||
|
if expected_md5:
|
||||||
|
local_md5 = calculate_md5(so_file)
|
||||||
|
if local_md5 != expected_md5:
|
||||||
|
print("警告: 文件MD5校验失败")
|
||||||
|
print(" 期望: {0}".format(expected_md5))
|
||||||
|
print(" 实际: {0}".format(local_md5))
|
||||||
|
os.remove(so_file)
|
||||||
|
return False
|
||||||
|
print("MD5校验通过")
|
||||||
|
|
||||||
|
# 保存版本信息
|
||||||
|
save_local_version(version_info)
|
||||||
|
|
||||||
|
print("下载完成: {0}".format(so_file))
|
||||||
|
|
||||||
|
# 显示更新日志
|
||||||
|
print_update_info(version_info)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
except Exception as ex:
|
||||||
|
print("下载SO文件失败: {0}".format(ex))
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def need_update(local_version: Optional[Dict[str, Any]], server_version: Optional[Dict[str, Any]]) -> bool:
|
||||||
|
"""判断是否需要更新"""
|
||||||
|
if server_version is None:
|
||||||
|
# 服务器没有活跃版本
|
||||||
|
return False
|
||||||
|
|
||||||
|
if local_version is None:
|
||||||
|
# 本地没有版本信息
|
||||||
|
return True
|
||||||
|
|
||||||
|
# 比较version_id
|
||||||
|
if local_version.get('version_id') != server_version.get('version_id'):
|
||||||
|
return True
|
||||||
|
|
||||||
|
# 检查SO文件是否存在
|
||||||
|
python_ver = get_python_version()
|
||||||
|
so_file = os.path.join(SO_DIR, "{0}_{1}.so".format(SO_FILENAME, python_ver.replace('.', '')))
|
||||||
|
if not os.path.exists(so_file):
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def load_so_module():
|
||||||
|
"""加载SO模块"""
|
||||||
|
python_ver = get_python_version()
|
||||||
|
so_file = os.path.join(SO_DIR, "{0}_{1}.so".format(SO_FILENAME, python_ver.replace('.', '')))
|
||||||
|
|
||||||
|
# 检查本地版本
|
||||||
|
local_version = load_local_version()
|
||||||
|
|
||||||
|
# 检查服务器版本
|
||||||
|
server_version = check_server_version()
|
||||||
|
|
||||||
|
# 判断是否需要更新
|
||||||
|
if need_update(local_version, server_version):
|
||||||
|
if server_version:
|
||||||
|
print("发现新版本: {0}".format(server_version['version_number']))
|
||||||
|
if not download_so_file(server_version):
|
||||||
|
if not os.path.exists(so_file):
|
||||||
|
raise RuntimeError("SO文件不存在且下载失败: {0}".format(so_file))
|
||||||
|
print("下载失败,使用本地版本")
|
||||||
|
else:
|
||||||
|
if not os.path.exists(so_file):
|
||||||
|
raise RuntimeError("SO文件不存在或暂无可用版本: {0}".format(so_file))
|
||||||
|
else:
|
||||||
|
if local_version:
|
||||||
|
print("使用本地版本: {0}".format(local_version['version_number']))
|
||||||
|
|
||||||
|
# 检查SO文件是否存在
|
||||||
|
if not os.path.exists(so_file):
|
||||||
|
raise RuntimeError("SO文件不存在: {0}".format(so_file))
|
||||||
|
|
||||||
|
# 加载SO模块
|
||||||
|
try:
|
||||||
|
spec = importlib.util.spec_from_file_location("encrypted_module", so_file)
|
||||||
|
if spec is None or spec.loader is None:
|
||||||
|
raise RuntimeError("无法加载SO模块: {0}".format(so_file))
|
||||||
|
|
||||||
|
module = importlib.util.module_from_spec(spec)
|
||||||
|
spec.loader.exec_module(module)
|
||||||
|
|
||||||
|
return module
|
||||||
|
|
||||||
|
except Exception as ex:
|
||||||
|
raise RuntimeError("加载SO模块失败: {0}".format(ex))
|
||||||
|
|
||||||
|
|
||||||
|
# 自动加载模块并执行
|
||||||
|
try:
|
||||||
|
_module = load_so_module()
|
||||||
|
|
||||||
|
# 导出入口函数
|
||||||
|
if hasattr(_module, ENTRY_FUNCTION):
|
||||||
|
entry_func = getattr(_module, ENTRY_FUNCTION)
|
||||||
|
globals()[ENTRY_FUNCTION] = entry_func
|
||||||
|
|
||||||
|
# 如果作为主程序运行,自动执行入口函数
|
||||||
|
if __name__ == "__main__":
|
||||||
|
result = entry_func()
|
||||||
|
if result is not None:
|
||||||
|
print("返回值:", result)
|
||||||
|
else:
|
||||||
|
print("警告: SO模块中未找到入口函数 '{0}'".format(ENTRY_FUNCTION))
|
||||||
|
# 导出模块本身,允许用户手动访问
|
||||||
|
encrypted_module = _module
|
||||||
|
|
||||||
|
except Exception as ex:
|
||||||
|
print("加载器初始化失败: {0}".format(ex))
|
||||||
|
raise
|
||||||
Reference in New Issue
Block a user