上月游戏内资源还没被加密的,昨日维修后发现部分图片资源被加密无法用assetstudio打开。
通过查看文件内容发现文件头部还是“UnityFS”标识头。
请问有没有解密办法,谢谢
上月游戏内资源还没被加密的,昨日维修后发现部分图片资源被加密无法用assetstudio打开。
通过查看文件内容发现文件头部还是“UnityFS”标识头。
请问有没有解密办法,谢谢
這個版本可以開
謝謝
借問一下,有人知道怎麼解密資源路徑嗎?
感覺是放是在work.dgs.rel.mas,但不曉得怎麼解…
大佬,麻烦问一下立绘在那个路径里面啊,没找到立绘,就找到个小人动画,不知道怎么组合 ![]()
这游戏进去不会下载数据你是怎么下载完整数据的?
eventdata0000103.evsc.rar (7.0 KB)游戏里面的剧本好像是加密的,不知道有没有大佬能看看
谢谢各位大佬了
又看了一下,读取就这样,这只是一个简单解析,不展示具体细节。
import struct
import os
class EVSCCommandParam:
"""EVSC命令参数联合体"""
def __init__(self):
self.data = 0
self.instruction = None # EVSCCommandParamInstruction
self.integer = None # EVSCCommandParamInteger
self.float_val = None # EVSCCommandParamFloat
self.string = None # EVSCCommandParamString
self.stack_variable = None # EVSCCommandParamStackVariable
class EVSCCommandParamInstruction:
"""指令型参数"""
def __init__(self):
self.no = 0
self.argument_count = 0
class EVSCCommandParamInteger:
"""整数型参数"""
def __init__(self):
self.value = 0
class EVSCCommandParamFloat:
"""浮点型参数"""
def __init__(self):
self.value = 0.0
class EVSCCommandParamString:
"""字符串型参数(偏移索引)"""
def __init__(self):
self.string_offset = 0
class EVSCCommandParamStackVariable:
"""栈变量型参数"""
def __init__(self):
self.variable_offset = 0
class EVSCCommand:
"""EVSC命令结构"""
SIZE = 8 # 命令基础结构固定8字节
def __init__(self):
self.data_offset = 0
self.type = 0
self.debug_info_offset = 0
self.param = EVSCCommandParam()
class EVSCHeader:
"""EVSC头部信息"""
def __init__(self):
self.file_id = ""
self.version = ""
self.command_offset = 0
self.command_count = 0
self.string_offset = 0
self.string_size = 0
self.debug_info_offset = 0
self.debug_info_count = 0
self.debug_string_offset = 0
self.debug_string_size = 0
self.request_stack_size = 0
class EVSCData:
"""EVSC数据解析主类"""
EVSC_OFFSET_NONE = 4294967295
EVSC_OFFSET_24BIT_NONE = 16777215
def __init__(self):
self.binary = None
self.header = EVSCHeader()
self.commands = []
self.string_pool = b"" # 字符串池原始数据
def parse(self, file_path):
"""解析EVSC文件"""
try:
with open(file_path, "rb") as f:
self.binary = f.read()
self._parse_header()
self._parse_string_pool()
self._parse_commands()
return True
except Exception as e:
print(f"解析失败: {str(e)}")
return False
def _parse_header(self):
"""解析前44字节头部信息"""
if len(self.binary) < 44:
raise ValueError("文件太小,不包含完整的EVSC头部")
header_data = self.binary[:44]
self.header.file_id = header_data[0:4].decode('ascii').strip('\x00')
self.header.version = header_data[4:8].decode('ascii').strip('\x00')
self.header.command_offset = struct.unpack("<I", header_data[8:12])[0]
self.header.command_count = struct.unpack("<I", header_data[12:16])[0]
self.header.string_offset = struct.unpack("<I", header_data[16:20])[0]
self.header.string_size = struct.unpack("<I", header_data[20:24])[0]
self.header.debug_info_offset = struct.unpack("<I", header_data[24:28])[0]
self.header.debug_info_count = struct.unpack("<I", header_data[28:32])[0]
self.header.debug_string_offset = struct.unpack("<I", header_data[32:36])[0]
self.header.debug_string_size = struct.unpack("<I", header_data[36:40])[0]
self.header.request_stack_size = struct.unpack("<I", header_data[40:44])[0]
def _parse_string_pool(self):
"""解析字符串池"""
if self.header.string_offset == self.EVSC_OFFSET_NONE:
return
start = self.header.string_offset
end = start + self.header.string_size
if end > len(self.binary):
raise ValueError("字符串池超出文件范围")
self.string_pool = self.binary[start:end]
def _get_string_from_pool(self, offset):
"""从字符串池获取字符串"""
if not self.string_pool or offset >= len(self.string_pool):
return ""
end = offset
while end < len(self.string_pool) and self.string_pool[end] != 0:
end += 1
return self.string_pool[offset:end].decode('utf-8', errors='replace')
def _parse_commands(self):
"""解析命令列表"""
if self.header.command_offset == self.EVSC_OFFSET_NONE:
return
start_offset = self.header.command_offset
total_commands = self.header.command_count
if start_offset + total_commands * EVSCCommand.SIZE > len(self.binary):
raise ValueError("命令块超出文件范围")
self.commands = []
for i in range(total_commands):
cmd = EVSCCommand()
cmd_offset = start_offset + i * EVSCCommand.SIZE
cmd.data_offset = cmd_offset
first_4_bytes = struct.unpack("<I", self.binary[cmd_offset:cmd_offset+4])[0]
cmd.type = first_4_bytes & 0xFF
cmd.debug_info_offset = first_4_bytes >> 8
param_data = struct.unpack("<I", self.binary[cmd_offset+4:cmd_offset+8])[0]
self._parse_command_param(cmd, param_data)
self.commands.append(cmd)
def _parse_command_param(self, cmd, param_data):
"""根据命令类型解析参数"""
cmd.param.data = param_data
if cmd.type == 0:
cmd.param.instruction = EVSCCommandParamInstruction()
cmd.param.instruction.no = param_data & 0xFFFF
cmd.param.instruction.argument_count = (param_data >> 16) & 0xFFFF
elif cmd.type == 1:
cmd.param.integer = EVSCCommandParamInteger()
cmd.param.integer.value = struct.unpack("<i", struct.pack("<I", param_data))[0]
elif cmd.type == 2:
cmd.param.float_val = EVSCCommandParamFloat()
cmd.param.float_val.value = struct.unpack("<f", struct.pack("<I", param_data))[0]
elif cmd.type == 3:
cmd.param.string = EVSCCommandParamString()
cmd.param.string.string_offset = param_data
elif cmd.type == 4:
cmd.param.stack_variable = EVSCCommandParamStackVariable()
cmd.param.stack_variable.variable_offset = struct.unpack("<i", struct.pack("<I", param_data))[0]
def print_header(header):
"""打印头部信息"""
print("\n===== EVSC 头部信息 =====")
print(f"文件ID: {header.file_id}")
print(f"版本: {header.version}")
print(f"命令偏移: 0x{header.command_offset:X} ({header.command_offset})")
print(f"命令数量: {header.command_count}")
print(f"字符串偏移: 0x{header.string_offset:X} ({header.string_offset})")
print(f"字符串大小: {header.string_size} 字节")
print(f"调试信息偏移: 0x{header.debug_info_offset:X} ({header.debug_info_offset})")
print(f"调试信息数量: {header.debug_info_count}")
print(f"调试字符串偏移: 0x{header.debug_string_offset:X} ({header.debug_string_offset})")
print(f"调试字符串大小: {header.debug_string_size} 字节")
print(f"请求栈大小: {header.request_stack_size}")
# 指令解释映射表(保持不变)
INSTRUCTION_EXPLANATIONS = {
}
def print_commands(commands, evsc_data):
"""打印命令列表(包含中文指令解释)"""
if not commands:
print("\n===== 没有命令 =====")
return
print("\n===== 命令列表 =====")
print(f"共 {len(commands)} 条命令:")
print("-" * 150)
print(f"{'索引':<5} {'偏移':<10} {'类型':<5} {'调试偏移':<10} {'参数':<100}")
print("-" * 150)
for i, cmd in enumerate(commands):
param_str = ""
if cmd.param.instruction:
# 关键修改:用指令编号减30作为字典的键
mapped_key = cmd.param.instruction.no - 30
explain = INSTRUCTION_EXPLANATIONS.get(
mapped_key,
f"未知指令(原始编号: {cmd.param.instruction.no}, 映射键: {mapped_key})"
)
param_str = (f"指令(原始编号: {cmd.param.instruction.no}, 映射键: {mapped_key}, 解释: {explain}, "
f"参数数: {cmd.param.instruction.argument_count})")
elif cmd.param.integer:
param_str = f"整数: {cmd.param.integer.value}"
elif cmd.param.float_val:
param_str = f"浮点数: {cmd.param.float_val.value:.6f}"
elif cmd.param.string:
str_val = evsc_data._get_string_from_pool(cmd.param.string.string_offset)
param_str = f"字符串(偏移: {cmd.param.string.string_offset}, 值: '{str_val}')"
elif cmd.param.stack_variable:
param_str = f"栈变量(偏移: {cmd.param.stack_variable.variable_offset})"
else:
param_str = f"原始数据: 0x{cmd.param.data:X}"
print(f"{i:<5} 0x{cmd.data_offset:X}<{cmd.data_offset:>5} {cmd.type:<5} 0x{cmd.debug_info_offset:X} {param_str}")
def main():
print("=" * 60)
print(" EVSC 文件解析器(带中文指令解释)")
print("=" * 60)
file_path = input("请输入EVSC文件路径: ").strip()
if not os.path.exists(file_path):
print(f"错误: 文件 '{file_path}' 不存在")
return
if not os.path.isfile(file_path):
print(f"错误: '{file_path}' 不是一个文件")
return
evsc_data = EVSCData()
if evsc_data.parse(file_path):
print(f"\n成功解析文件: {os.path.abspath(file_path)}")
print_header(evsc_data.header)
print_commands(evsc_data.commands, evsc_data)
print("\n" + "=" * 60)
print("解析完成")
print("=" * 60)
input("按回车键退出...")
if __name__ == "__main__":
main()
十分感谢大佬帮助,如果能还原相关操作就好了
28598519a/ayarabu_AssetDL: Use to download all Ayakashi Rumble resources
这位大佬做了能获取所有资源路径的脚本,完全不理解这是怎么做到的,太离谱了。
话说对于这些游戏有大佬知道怎么获取索引文件吗,比如都有哪些角色,名字是什么,对应的id,以及各种详细文本能得到吗。还有妖怪我发现他的动态效果都是用的sprite studio做的,不是普通的atlas json和png,然后又转成了一种二进制文件,只有ssfb(记不清具体啥后缀了)和png文件,这种该怎么播放呢。
他有个ab包存储了大部分索引。
Github網址底下有個 sh0wer1ee,我看他的github.io有分析思路。
照他方式確實有看到遊戲資料庫,但目前不知道要怎麼讀取。
你可以看源码,用的是unitypy读取的,但是不知道为什么能读
想說有工具能直接用最好。
用了一下UnityPy,但抓不到AssetBundleManifest的資料,應該是Unity版本問題。
那是一个ab包,加载出来就是清单。自动搞不定手动下载然后扔assetstudio就行了。