有点怀疑人生,感觉加密,但是搜不到解密函数,也具有png标识尾
感觉没加密,但里面数据又不是png。
目前感觉应该是cocos2d处理过的。
但是没见过,也不知道怎么办。
头
尾
从cocos2dx_lua_loader调用luaL_loadbuffer的地方入手没有发现明显的解密函数
这个函数名字比较可疑存在一个32字节长的字符串也可疑
其他的还没仔细看
ida9.0 Beta的分析文件(已完全解析)
直接找fread
我也注意到了这个mdecode但是我这个IDA里甚至无法定位到汇编位置
import argparse
from pathlib import Path
from typing import Iterable
KEY = b"quantaninjagirl24"
HEADER = bytes([0xEF, 0xFE, 0x80])
CHUNK_DECRYPT = 128
def rc4_init(key: bytes) -> list[int]:
s = list(range(256))
j = 0
for i in range(256):
j = (j + s[i] + key[i % len(key)]) & 0xFF
s[i], s[j] = s[j], s[i]
return s
def rc4_crypt(key_state: list[int], data: bytes) -> bytes:
s = key_state.copy()
i = j = 0
out = bytearray()
for byte in data:
i = (i + 1) & 0xFF
j = (j + s[i]) & 0xFF
s[i], s[j] = s[j], s[i]
k = s[(s[i] + s[j]) & 0xFF]
out.append(byte ^ k)
return bytes(out)
def decrypt_texture(buf: bytes) -> bytes | None:
if not buf.startswith(HEADER):
return None
payload = buf[3:]
to_dec = payload[:CHUNK_DECRYPT]
rest = payload[len(to_dec):]
state = rc4_init(KEY)
dec_first = rc4_crypt(state, to_dec)
return dec_first + rest
def process_file(path: Path, out_dir: Path | None):
raw = path.read_bytes()
dec = decrypt_texture(raw)
if dec is None:
return False
out_path = (
out_dir / path.name if out_dir
else path.with_suffix(".dec.png")
)
out_path.parent.mkdir(parents=True, exist_ok=True)
out_path.write_bytes(dec)
return True
def walk_inputs(targets: Iterable[Path]):
for p in targets:
if p.is_dir():
yield from p.rglob("*.png")
elif p.is_file():
yield p
def main():
ap = argparse.ArgumentParser(
description="decrypt")
ap.add_argument("input")
ap.add_argument("-o", type=Path)
args = ap.parse_args()
hits = 0
for f in walk_inputs(Path(i) for i in args.input):
if process_file(f, args.o):
hits += 1
if __name__ == "__main__":
main()
意思就是套用rc4解密
那同理文本或者其他文件是使用下面那个rc4documentbuffer?
电脑不在身边依目前看到的图片猜测?
应该吧,大概看了下只有个.cbbi后缀的加密了,解完图片没问题就卸载了
那我下午回去看看我记得这个游戏去年11月有人问来着不过我当时在日本h365对日本IP屏蔽了部分游戏就没怎么看
反正是判断第三个字节是128还是255判断用哪个函数,你看看其他文件第三个字节是不是,至少.cbbi文件是FF
那就对了图片和文本文件只有前两个字节一样应该是不同的加密方式
感谢大佬,回去试试。
为什么我运行.PY闪退,库没有安装准确吗?
ai会告诉你要安哪些外部库。
安装的python3.13版本,问了AI不需要库,但是运行不起。你解密成功没?分享下
可以用
解密函数就在上面,我自己写的用了别的库。
?报错文本你是一点没提上来就伸手?
要带上输入文件
代码喂ai,然后拿出资本家使唤牛马的本事,比什么都好使。
除了使用方法,还可以下发任务,让ai在大佬的代码基础上增加功能,比如实现输出文件夹保持与输入文件夹一样相对路径。
感谢yjzyl9008大佬给的解密代码 ,这个确实有些门槛。
import argparse
from pathlib import Path
from typing import Iterable
KEY = b"quantaninjagirl24"
HEADER = bytes([0xEF, 0xFE, 0x80])
CHUNK_DECRYPT = 128
def rc4_init(key: bytes) -> list[int]:
s = list(range(256))
j = 0
for i in range(256):
j = (j + s[i] + key[i % len(key)]) & 0xFF
s[i], s[j] = s[j], s[i]
return s
def rc4_crypt(key_state: list[int], data: bytes) -> bytes:
s = key_state.copy()
i = j = 0
out = bytearray()
for byte in data:
i = (i + 1) & 0xFF
j = (j + s[i]) & 0xFF
s[i], s[j] = s[j], s[i]
k = s[(s[i] + s[j]) & 0xFF]
out.append(byte ^ k)
return bytes(out)
def decrypt_texture(buf: bytes) -> bytes | None:
if not buf.startswith(HEADER):
return None
payload = buf[3:]
to_dec = payload[:CHUNK_DECRYPT]
rest = payload[len(to_dec):]
state = rc4_init(KEY)
dec_first = rc4_crypt(state, to_dec)
return dec_first + rest
def process_file(path: Path, out_dir: Path | None, root_dir: Path | None = None) -> bool:
try:
raw = path.read_bytes()
except Exception as e:
print(f"Error reading {path}: {e}")
return False
dec = decrypt_texture(raw)
if dec is None:
return False
if out_dir:
# 计算相对路径并保留目录结构
rel_path = path.relative_to(root_dir) if root_dir else path.name
out_path = out_dir / rel_path
else:
# 未指定输出目录时添加.dec.png后缀
out_path = path.with_suffix(".dec.png")
try:
out_path.parent.mkdir(parents=True, exist_ok=True)
out_path.write_bytes(dec)
print(f"Decrypted: {path} -> {out_path}")
return True
except Exception as e:
print(f"Error writing {out_path}: {e}")
return False
def walk_inputs(targets: Iterable[Path]) -> Iterable[Path]:
for p in targets:
if p.is_dir():
yield from p.rglob("*.png")
elif p.is_file():
yield p
def main():
ap = argparse.ArgumentParser(description="Decrypt PNG textures")
ap.add_argument("input", help="Input file or directory")
ap.add_argument("-o", "--output", type=Path, help="Output directory")
args = ap.parse_args()
input_path = Path(args.input)
if not input_path.exists():
print(f"Error: Input path '{args.input}' does not exist")
return
root_dir = input_path.parent if input_path.is_file() else input_path
hits = 0
total = 0
# 第一遍扫描统计总数
all_files = list(walk_inputs([input_path]))
total = len(all_files)
# 第二遍处理文件
for i, f in enumerate(all_files):
print(f"Processing {i+1}/{total}: {f}")
if process_file(f, args.output, root_dir):
hits += 1
print(f"Successfully decrypted {hits} of {total} files")
if __name__ == "__main__":
main()
我一般都是让ai写多线程。
简单的可以交给ai,复杂点的还是要自己写的。
其实可以直接把伪c修改一下变成可用的c代码的,只是c没有py方便。
from Crypto.Cipher import ARC4
import os
import sys
import concurrent.futures
from pathlib import Path
import multiprocessing
def rc4_texture_decrypt(encrypted_data):
"""
对加密的纹理数据进行RC4解密
:param encrypted_data: 加密的二进制数据
:return: 解密后的二进制数据
"""
if not encrypted_data:
return b''
# 计算解密后数据的大小
data_length = len(encrypted_data) - 3
# RC4密钥
key = b"quantaninjagirl24"
# 分配内存存储解密后的数据
decrypted_data = bytearray(data_length)
# 从偏移3开始获取实际加密数据
encrypted_part = encrypted_data[3:]
# 初始化RC4密码器
cipher = ARC4.new(key)
# 解密处理
if data_length > 128:
# 解密前128字节
decrypted_data[:128] = cipher.encrypt(encrypted_part[:128])
# 复制剩余数据
decrypted_data[128:] = encrypted_part[128:]
else:
# 解密全部数据
decrypted_data[:data_length] = cipher.encrypt(encrypted_part[:data_length])
return bytes(decrypted_data)
def decrypt_file(input_file, output_file):
"""解密单个文件并保存"""
try:
with open(input_file, 'rb') as f:
encrypted_data = f.read()
decrypted_data = rc4_texture_decrypt(encrypted_data)
with open(output_file, 'wb') as f:
f.write(decrypted_data)
return True, f"✓ 已解密: {input_file}"
except Exception as e:
return False, f"✗ 解密失败 [{input_file}]: {e}"
def process_directory(input_dir, output_dir, overwrite):
"""多线程处理目录中的所有PNG文件"""
if not os.path.exists(output_dir) and not overwrite:
os.makedirs(output_dir)
# 收集所有PNG文件
png_files = []
for root, _, files in os.walk(input_dir):
for file in files:
if file.lower().endswith('.png'):
input_path = os.path.join(root, file)
if overwrite:
output_path = input_path
else:
# 保持目录结构
relative_path = os.path.relpath(input_path, input_dir)
output_path = os.path.join(output_dir, relative_path)
# 确保输出目录存在
output_subdir = os.path.dirname(output_path)
if not os.path.exists(output_subdir):
os.makedirs(output_subdir)
png_files.append((input_path, output_path))
total_files = len(png_files)
success_files = 0
# 获取CPU核心数作为线程数
cpu_count = multiprocessing.cpu_count()
thread_count = max(1, cpu_count) # 至少使用1个线程
print(f"\n开始多线程处理,使用 {thread_count} 个线程,共 {total_files} 个文件")
# 使用线程池进行多线程处理
with concurrent.futures.ThreadPoolExecutor(max_workers=thread_count) as executor:
# 提交所有任务
future_to_path = {executor.submit(decrypt_file, in_file, out_file): (in_file, out_file)
for in_file, out_file in png_files}
# 处理结果
for i, future in enumerate(concurrent.futures.as_completed(future_to_path)):
input_path, _ = future_to_path[future]
try:
success, message = future.result()
if success:
success_files += 1
print(f"[{i+1}/{total_files}] {message}")
except Exception as e:
print(f"[{i+1}/{total_files}] ✗ 处理失败 [{input_path}]: {e}")
return total_files, success_files
def main():
while True:
print("\n" + "="*40)
print(" RC4纹理解密工具 (多线程版) ".center(40, '='))
print("="*40)
target = input("\n请输入文件路径或文件夹路径 (输入q退出): ").strip()
if target.lower() == 'q':
break
if not os.path.exists(target):
print(f"错误: 路径不存在 - {target}")
continue
overwrite = input("是否覆盖原文件? (y/n): ").strip().lower() == 'y'
output_base = ""
if not overwrite:
output_base = input("请输入输出位置 (直接回车则在原路径添加'_decrypted'后缀): ").strip()
if os.path.isfile(target):
# 处理单个文件
if overwrite:
output_base = target
elif not output_base:
output_base = os.path.splitext(target)[0] + "_decrypted.png"
success, message = decrypt_file(target, output_base)
print(message)
elif os.path.isdir(target):
# 处理文件夹
if overwrite:
output_base = target
elif not output_base:
output_base = target.rstrip(os.sep) + "_decrypted"
total, success = process_directory(target, output_base, overwrite)
print(f"\n处理完成: 共{total}个PNG文件,成功解密{success}个")
else:
print(f"错误: 无法识别的路径类型 - {target}")
choice = input("\n是否继续? (y/n): ").strip().lower()
if choice != 'y':
break
if __name__ == "__main__":
main()