有人做过微信小游戏资源解密?小游戏平台的
有大佬做过小游戏资源加密后的解密步骤的?帮看一下,谢谢
这个你得出钱,才有人帮你,而且价格还不低吧
没必要,解密代码肯定也在代码里面。现在AI逆向拆包解密,一分钟都不要内裤都给你扒干净
当然,防一些用不起AI的人还是有点用。这种东西确实,不花钱没人会好心告诉你完整方案。反正整体不难
web和native 我自己已经搞定上线, 剩下小程序。ai年代了,这玩意门槛不高。我小程序搞一下,直接免费公布
…这种只要知道在哪里做解密。就能搞,估摸应该和web一样。web和native 我自己已经搞定上线, 剩下小程序。我小程序搞一下,直接免费公布
别人辛苦做的项目,这样反编译一下换成自己的 这样能行?ai这么强了,自己发挥创意不好吗?
分享一下web的方案老哥
那你还来问

人性就是这样,他就是要占你便宜!
笑死,国内环境纯自研的有几个人?不都是靠“借鉴”。某些大企业都带头,都懒得喷了
哈哈,借鉴没有错,但是你搞别人的代码 还很光荣,别人一样搞你,搞来搞去
?理解问题?我是加密自己公司的游戏项目的资源
没弄过微信小游戏加密。本意想问做过的能直接点一下哪里做解密.省的琢磨
这台点电脑只有ios相关的。贴一下xor加密。 不过你问ai就有
“”"
Cocos资源加密工具 - 纯XOR版本(跨平台一致)
强制使用XOR加密,不依赖任何外部库
适用于微信小游戏、Web、iOS、Android全平台
“”"
import os
import sys
import struct
import hashlib
import time
import shutil
from pathlib import Path
print(“✓ 使用纯XOR加密(跨平台一致,无依赖)”)
class XorOnlyEncryptor:
"""纯XOR加密器,Windows/Mac/Linux/微信小游戏完全兼容"""
def __init__(self, key="my_secret_key_123"):
self.key = self._process_key(key)
self.backup_dir = ".backup_encrypt"
def _process_key(self, key):
"""处理密钥,生成固定长度的密钥流种子"""
if isinstance(key, str):
key = key.encode('utf-8')
# 使用SHA256生成32字节密钥(作为XOR的重复密钥)
return hashlib.sha256(key).digest()
def _xor_crypt(self, data, iv=None):
"""
XOR加密/解密函数(对称操作)
使用密钥流进行XOR,IV用于增加随机性
"""
if iv is None:
iv = os.urandom(16)
# 将密钥和IV混合生成密钥流种子
seed = self.key + iv
# 生成与数据等长的密钥流(通过重复哈希)
key_stream = self._generate_keystream(seed, len(data))
# XOR操作
result = bytearray(len(data))
for i in range(len(data)):
result[i] = data[i] ^ key_stream[i]
return bytes(result), iv
def _generate_keystream(self, seed, length):
"""生成伪随机密钥流(基于SHA256的CTR模式)"""
keystream = bytearray()
counter = 0
while len(keystream) < length:
# 将种子和计数器组合
data = seed + struct.pack('<Q', counter)
# 使用SHA256生成伪随机块
block = hashlib.sha256(data).digest()
keystream.extend(block)
counter += 1
return bytes(keystream[:length])
def encrypt_data(self, data):
"""加密数据 - 强制使用XOR"""
try:
# 格式: [CCXE][原始长度4字节][IV16字节][加密数据]
magic = b'CCXE' # XOR加密标识
# 生成随机IV(增加安全性,即使相同明文也不同密文)
iv = os.urandom(16)
# XOR加密
encrypted_data, _ = self._xor_crypt(data, iv)
# 打包原始长度
size = struct.pack('<I', len(data))
return magic + size + iv + encrypted_data
except Exception as e:
print(f"加密出错: {e}")
raise
def decrypt_data(self, data):
"""解密数据"""
if len(data) < 8:
return data
magic = data[:4]
if magic == b'CCXE':
try:
original_size = struct.unpack('<I', data[4:8])[0]
iv = data[8:24]
encrypted = data[24:]
# XOR解密(与加密相同的操作)
original_data, _ = self._xor_crypt(encrypted, iv)
if len(original_data) != original_size:
print(f" 警告: 解密后长度不匹配")
return original_data[:original_size] # 确保长度正确
except Exception as e:
print(f"XOR解密失败: {e}")
return data
elif magic == b'CCEN':
print(f" 警告: 检测到旧AES格式文件,尝试兼容解密...")
# 尝试兼容旧AES格式(简单XOR解密,可能不完整)
try:
original_size = struct.unpack('<I', data[4:8])[0]
if len(data) > 24:
# 跳过IV,尝试XOR解密
encrypted = data[24:]
else:
encrypted = data[8:]
# 简单XOR解密(使用原始密钥)
result = bytearray(encrypted)
key_len = len(self.key)
for i in range(len(result)):
result[i] ^= self.key[i % key_len]
return bytes(result[:original_size])
except:
pass
# 不是加密文件或解密失败
return data
def is_encrypted_file(self, filepath):
"""检查文件是否已加密"""
try:
with open(filepath, 'rb') as f:
header = f.read(8)
if len(header) >= 8:
magic = header[:4]
return magic in [b'CCXE', b'CCEN']
except:
pass
return False
def _backup_file(self, filepath):
"""备份文件"""
try:
backup_dir = os.path.join(os.path.dirname(filepath), self.backup_dir)
os.makedirs(backup_dir, exist_ok=True)
with open(filepath, 'rb') as f:
data = f.read()
filename = os.path.basename(filepath)
timestamp = int(time.time())
backup_name = f"{filename}.{timestamp}.bak"
backup_path = os.path.join(backup_dir, backup_name)
with open(backup_path, 'wb') as f:
f.write(data)
return backup_path
except Exception as e:
print(f"备份失败 {filepath}: {e}")
return None
def _find_latest_backup(self, filepath):
"""查找最新的备份"""
try:
backup_dir = os.path.join(os.path.dirname(filepath), self.backup_dir)
if not os.path.exists(backup_dir):
return None
filename = os.path.basename(filepath)
backups = []
for f in os.listdir(backup_dir):
if f.startswith(filename + ".") and f.endswith(".bak"):
parts = f.split('.')
if len(parts) >= 2:
try:
backup_time = int(parts[-2])
backups.append((backup_time, os.path.join(backup_dir, f)))
except ValueError:
continue
if backups:
backups.sort(reverse=True)
return backups[0][1]
except:
pass
return None
def encrypt_file(self, filepath, backup=True):
"""加密单个文件(原地加密)"""
try:
if not os.path.exists(filepath):
print(f"文件不存在: {filepath}")
return False
if self.is_encrypted_file(filepath):
print(f"⏭️ 已加密: {os.path.basename(filepath)}")
return True
backup_path = None
if backup:
backup_path = self._backup_file(filepath)
if backup_path:
print(f" 📁 备份: {os.path.basename(backup_path)}")
with open(filepath, 'rb') as f:
original_data = f.read()
original_size = len(original_data)
encrypted_data = self.encrypt_data(original_data)
encrypted_size = len(encrypted_data)
with open(filepath, 'wb') as f:
f.write(encrypted_data)
size_info = f"{original_size/1024:.1f}KB → {encrypted_size/1024:.1f}KB"
change = f"+{(encrypted_size-original_size)/1024:.1f}KB"
print(f"✅ 加密: {os.path.basename(filepath)} ({size_info}, {change})")
return True
except Exception as e:
print(f"❌ 加密失败 {filepath}: {e}")
if backup:
latest_backup = self._find_latest_backup(filepath)
if latest_backup and os.path.exists(latest_backup):
try:
with open(latest_backup, 'rb') as f:
backup_data = f.read()
with open(filepath, 'wb') as f:
f.write(backup_data)
print(f" 🔄 已从备份恢复")
except:
pass
return False
def decrypt_file(self, filepath, restore_backup=False):
"""解密单个文件"""
try:
if not os.path.exists(filepath):
print(f"文件不存在: {filepath}")
return False
if not self.is_encrypted_file(filepath):
print(f"⏭️ 未加密: {os.path.basename(filepath)}")
return False
if restore_backup:
latest_backup = self._find_latest_backup(filepath)
if latest_backup and os.path.exists(latest_backup):
try:
with open(latest_backup, 'rb') as f:
backup_data = f.read()
with open(filepath, 'wb') as f:
f.write(backup_data)
print(f"✅ 从备份恢复: {os.path.basename(filepath)}")
return True
except Exception as e:
print(f"备份恢复失败: {e}")
with open(filepath, 'rb') as f:
encrypted_data = f.read()
original_size = len(encrypted_data)
decrypted_data = self.decrypt_data(encrypted_data)
decrypted_size = len(decrypted_data)
with open(filepath, 'wb') as f:
f.write(decrypted_data)
size_info = f"{original_size/1024:.1f}KB → {decrypted_size/1024:.1f}KB"
change = f"-{(original_size-decrypted_size)/1024:.1f}KB"
print(f"✅ 解密: {os.path.basename(filepath)} ({size_info}, {change})")
return True
except Exception as e:
print(f"❌ 解密失败 {filepath}: {e}")
return False
def process_directory(self, directory, extensions=None, recursive=True):
"""处理目录"""
if extensions is None:
# 统一使用小写,避免大小写问题
extensions = {'.png', '.jpg', '.jpeg'}
if not os.path.exists(directory):
print(f"❌ 目录不存在: {directory}")
return []
if not os.path.isdir(directory):
print(f"❌ 不是目录: {directory}")
return []
print(f"📁 处理目录: {directory}")
print(f"📄 文件类型: {', '.join(sorted(extensions))}")
print(f"🔍 模式: XOR加密(跨平台一致)")
print("=" * 60)
processed_files = []
if recursive:
for root, dirs, files in os.walk(directory):
if self.backup_dir in root:
continue
for file in files:
file_ext = os.path.splitext(file)[1].lower()
if file_ext in extensions:
filepath = os.path.join(root, file)
relative_path = os.path.relpath(filepath, directory)
if self.encrypt_file(filepath, backup=True):
processed_files.append(relative_path)
else:
for item in os.listdir(directory):
filepath = os.path.join(directory, item)
if os.path.isfile(filepath):
file_ext = os.path.splitext(item)[1].lower()
if file_ext in extensions:
if self.encrypt_file(filepath, backup=True):
processed_files.append(item)
return processed_files
def clean_all_backup_folders(root_path="."):
"""
递归删除root_path下所有名为.backup_encrypt的文件夹及其内容
"""
deleted_count = 0
error_count = 0
print(f"\n🧹 开始清理所有 .backup_encrypt 文件夹...")
print(f"🔍 扫描路径: {os.path.abspath(root_path)}")
print("-" * 60)
for root, dirs, files in os.walk(root_path, topdown=False):
for dir_name in dirs:
if dir_name == ".backup_encrypt":
backup_path = os.path.join(root, dir_name)
if not os.path.exists(backup_path):
continue
try:
backup_files = [f for f in os.listdir(backup_path) if f.endswith('.bak')]
file_count = len(backup_files)
shutil.rmtree(backup_path)
print(f"🗑️ 已删除: {backup_path} ({file_count} 个备份文件)")
deleted_count += 1
except PermissionError:
print(f"❌ 权限不足,无法删除: {backup_path}")
error_count += 1
except Exception as e:
print(f"❌ 删除失败 {backup_path}: {e}")
error_count += 1
print("-" * 60)
if deleted_count > 0:
print(f"✅ 清理完成!共删除 {deleted_count} 个备份文件夹")
else:
print(f"ℹ️ 未发现 .backup_encrypt 文件夹")
if error_count > 0:
print(f"⚠️ 清理过程中出现 {error_count} 个错误")
return deleted_count, error_count
def main():
"""主函数"""
# 检查是否只清理模式
clean_only_mode = "--clean-only" in sys.argv
# 固定设置
FIXED_KEY = "my_secret_key_123"
# 获取当前脚本所在目录
script_dir = os.path.dirname(os.path.abspath(__file__))
# 构建目标路径: 当前脚本目录/build
target_path = os.path.join(script_dir, "build")
# 如果build目录不存在,尝试使用当前目录
if not os.path.exists(target_path):
print(f"⚠️ build目录不存在,使用当前目录: {script_dir}")
target_path = script_dir
os.chdir(target_path)
print("🔐 资源加密工具 - XOR专用版(跨平台一致)")
print(f"🔑 密钥: {FIXED_KEY}")
print(f"📁 目标路径: {target_path}")
# 如果是只清理模式
if clean_only_mode:
print("🧹 模式: 仅清理备份文件夹")
print("=" * 60)
clean_all_backup_folders(target_path)
print("\n✅ 清理操作完成!")
return
print("=" * 60)
# 创建加密器(强制XOR)
encryptor = XorOnlyEncryptor(FIXED_KEY)
# 自动加密目标路径
processed_files = encryptor.process_directory(
target_path,
extensions={'.png', '.jpg', '.jpeg'},
recursive=True
)
# 显示结果
print("\n" + "=" * 60)
print(f"✅ 加密完成!")
print(f"📊 已加密文件数: {len(processed_files)}")
if processed_files:
print(f"\n📄 已加密的文件:")
for i, file in enumerate(processed_files[:20]):
print(f" {i+1:3d}. {file}")
if len(processed_files) > 20:
print(f" ... 还有 {len(processed_files)-20} 个文件")
# 显示备份信息
backup_dir = os.path.join(target_path, encryptor.backup_dir)
if os.path.exists(backup_dir):
backup_files = [f for f in os.listdir(backup_dir) if f.endswith('.bak')]
backup_count = len(backup_files)
if backup_count > 0:
print(f"\n📁 备份目录: {backup_dir}")
print(f"📦 备份文件数: {backup_count}")
print(f"💡 如需恢复,备份文件已保存在以上目录中")
# 自动清理所有.backup_encrypt文件夹
print("\n" + "=" * 60)
print("🧹 开始清理所有备份文件夹...")
deleted, errors = clean_all_backup_folders(target_path)
if deleted > 0:
print(f"\n✅ 已自动清理 {deleted} 个备份文件夹")
if errors == 0:
print("💡 所有备份文件已删除,无法再恢复原始文件")
else:
print("\nℹ️ 未发现需要清理的备份文件夹")
if name == “main”:
main()
解密就是在读取图片的位置,我这电脑只有native的代码了,你满看着自己做一下web
void Image::initEncryptionKey() {
if (s_keyInitialized) {
return;
}
// 设置默认密钥
setEncryptionKey("my_secret_key_123");
}
bool Image::isEncryptedData(const unsigned char* data, uint32_t dataLen) {
if (!data || dataLen < 8) {
return false;
}
// 检查魔术头
if (memcmp(data, MAGIC_AES, 4) == 0) {
return true; // AES加密
}
if (memcmp(data, MAGIC_XOR, 4) == 0) {
return true; // XOR加密
}
return false;
}
uint32_t Image::getOriginalSizeFromHeader(const unsigned char* header) {
if (!header) {
return 0;
}
// 小端序读取原始大小
uint32_t size = 0;
size = header[4];
size |= (uint32_t)header[5] << 8;
size |= (uint32_t)header[6] << 16;
size |= (uint32_t)header[7] << 24;
return size;
}
unsigned char* Image::xorDecrypt(const unsigned char* encryptedData, uint32_t dataLen, uint32_t& outLen) {
outLen = dataLen;
if (!encryptedData || dataLen == 0 || s_encryptionKey.empty()) {
CC_LOG_ERROR("[Image] XOR decrypt invalid params");
return nullptr;
}
unsigned char* result = (unsigned char*)malloc(dataLen);
if (!result) {
CC_LOG_ERROR("[Image] XOR decrypt malloc failed");
return nullptr;
}
// XOR解密
for (uint32_t i = 0; i < dataLen; ++i) {
result[i] = encryptedData[i] ^ s_encryptionKey[i % s_encryptionKey.size()];
}
return result;
}
unsigned char* Image::aesDecrypt(const unsigned char* encryptedData, uint32_t dataLen,
const unsigned char* iv, uint32_t& outLen) {
outLen = 0;
if (!encryptedData || dataLen == 0 || !iv || s_encryptionKey.size() < 16) {
CC_LOG_ERROR("[Image] AES decrypt invalid params");
return nullptr;
}
#if CC_TARGET_PLATFORM == CC_PLATFORM_IOS || CC_TARGET_PLATFORM == CC_PLATFORM_MAC
// iOS/Mac使用CommonCrypto
unsigned char* result = (unsigned char*)malloc(dataLen + kCCBlockSizeAES128);
if (!result) {
CC_LOG_ERROR("[Image] AES decrypt malloc failed");
return nullptr;
}
size_t decryptedLen = 0;
CCCryptorStatus status = CCCrypt(kCCDecrypt,
kCCAlgorithmAES,
kCCOptionPKCS7Padding,
s_encryptionKey.data(),
s_encryptionKey.size(),
iv,
encryptedData,
dataLen,
result,
dataLen + kCCBlockSizeAES128,
&decryptedLen);
if (status != kCCSuccess) {
CC_LOG_ERROR("[Image] AES decrypt failed: %d", status);
free(result);
return nullptr;
}
outLen = static_cast<uint32_t>(decryptedLen);
return result;
#else
// 其他平台暂时只支持XOR加密
CC_LOG_ERROR("[Image] AES decrypt not supported on this platform");
return nullptr;
#endif
}
unsigned char* Image::decryptImageData(const unsigned char* data, uint32_t dataLen, uint32_t& outLen) {
outLen = 0;
if (!data || dataLen < 8 || !s_keyInitialized) {
CC_LOG_ERROR("[Image] Decrypt invalid parameters");
return nullptr;
}
// 检查加密类型
if (memcmp(data, MAGIC_AES, 4) == 0) {
// AES加密格式: [CCEN][size][IV16][encrypted data]
if (dataLen < 24) { // 至少需要魔术头4 + 大小4 + IV16
CC_LOG_ERROR("[Image] AES data too short: %u", dataLen);
return nullptr;
}
// 获取原始大小
uint32_t originalSize = getOriginalSizeFromHeader(data);
// 提取IV和数据
const unsigned char* iv = data + 8;
const unsigned char* encryptedData = data + 24;
uint32_t encryptedLen = dataLen - 24;
// AES解密
unsigned char* result = aesDecrypt(encryptedData, encryptedLen, iv, outLen);
if (result && outLen != originalSize) {
CC_LOG_WARNING("[Image] AES decrypted size mismatch: expected %u, got %u",
originalSize, outLen);
}
return result;
} else if (memcmp(data, MAGIC_XOR, 4) == 0) {
// XOR加密格式: [CCXE][size][encrypted data]
if (dataLen < 8) {
CC_LOG_ERROR("[Image] XOR data too short: %u", dataLen);
return nullptr;
}
// 获取原始大小
uint32_t originalSize = getOriginalSizeFromHeader(data);
// XOR解密
const unsigned char* encryptedData = data + 8;
uint32_t encryptedLen = dataLen - 8;
unsigned char* result = xorDecrypt(encryptedData, encryptedLen, outLen);
if (result && outLen != originalSize) {
CC_LOG_WARNING("[Image] XOR decrypted size mismatch: expected %u, got %u",
originalSize, outLen);
}
return result;
}
CC_LOG_ERROR("[Image] Not encrypted data");
return nullptr;
}
// 修改initWithImageData函数
bool Image::initWithImageData(const unsigned char *data, uint32_t dataLen) { //NOLINT(misc-no-recursion)
bool ret = false;
do {
CC_BREAK_IF(!data || dataLen <= 0);
// 初始化密钥
initEncryptionKey();
unsigned char *processedData = const_cast<unsigned char *>(data);
uint32_t processedDataLen = dataLen;
unsigned char *decryptedData = nullptr;
// 检查是否需要解密
if (isEncryptedData(data, dataLen)) {
CC_LOG_DEBUG("[Image] Detected encrypted image data, decrypting...");
uint32_t decryptedLen = 0;
decryptedData = decryptImageData(data, dataLen, decryptedLen);
if (decryptedData && decryptedLen > 0) {
processedData = decryptedData;
processedDataLen = decryptedLen;
//printf("[Image] 解密成功: %u -> %u 字节\n", dataLen, decryptedLen);
CC_LOG_DEBUG("[Image] Decrypted: %u -> %u bytes", dataLen, decryptedLen);
} else {
//printf("[Image] 解密失败!\n");
CC_LOG_ERROR("[Image] Failed to decrypt image data");
// 解密失败,尝试使用原始数据
}
}else {
//printf("[Image] 非加密文件,直接处理\n");
}
unsigned char *unpackedData = nullptr;
uint32_t unpackedLen = 0;
// 检测并解压压缩文件
if (ZipUtils::isCCZBuffer(processedData, processedDataLen)) {
unpackedLen = ZipUtils::inflateCCZBuffer(processedData, processedDataLen, &unpackedData);
} else if (ZipUtils::isGZipBuffer(processedData, processedDataLen)) {
unpackedLen = ZipUtils::inflateMemory(processedData, processedDataLen, &unpackedData);
} else {
unpackedData = processedData;
unpackedLen = processedDataLen;
}
_fileType = detectFormat(unpackedData, unpackedLen);
switch (_fileType) {
case Format::PNG:
ret = initWithPngData(unpackedData, unpackedLen);
break;
case Format::JPG:
ret = initWithJpgData(unpackedData, unpackedLen);
break;
#if CC_USE_WEBP
case Format::WEBP:
ret = initWithWebpData(unpackedData, unpackedLen);
break;
#endif
case Format::PVR:
ret = initWithPVRData(unpackedData, unpackedLen);
break;
case Format::ETC:
ret = initWithETCData(unpackedData, unpackedLen);
break;
case Format::ETC2:
ret = initWithETC2Data(unpackedData, unpackedLen);
break;
case Format::ASTC:
ret = initWithASTCData(unpackedData, unpackedLen);
break;
case Format::COMPRESSED:
ret = initWithCompressedMipsData(unpackedData, unpackedLen);
break;
default:
break;
}
// 清理内存
if (unpackedData != processedData) {
free(unpackedData);
}
// 如果解密了数据,需要释放解密内存
if (decryptedData != nullptr) {
free(decryptedData);
}
} while (false);
return ret;
}
这是只能获取素材么
好像你说的对