☰
新版JSC解密工具实战:Cocos2d-x脚本还原与批量解密
2026/10/9 9:32:00 网站建设 项目流程

简介:针对开发与逆向调试中常见的新版 JSC 加密脚本,这份小巧工具包提供了现成的 Windows 解密方案,适合前端工程师、爬虫研究与软件安全分析人员快速处理 JSC 变种,免去手工搭建解密环境的麻烦。解压后可直接运行主程序,动态库负责压缩、网络请求与核心解密逻辑,配置文件和说明文档则覆盖参数调整与常见报错排查,用户无需逐个补齐依赖,适合不愿在环境搭建上浪费时间的使用者。资源共 112 个文件,以 103 个 dll 为主,另含 5 个 xml、2 个 txt、1 个 config、1 个 exe,整包仅 1.57MB,携带方便,也便于保存到工作环境或内网机器。已有 982 人学习下载,尤其适合负责 JSC 解密与逆向分析的前端开发者、爬虫工程师和安全测试人员收藏备用;对需要反复验证解密结果、离线处理 JSC 文件的场景,这个小工具包能明显缩短准备时间。

1. 新版JSC解密工具到底在解什么:先搞懂.jsc是怎么来的

拿到一份名叫“新版JSC解密工具.rar”的资源,先别急着双击解压,也别急着相信它一打开就能一键解密。JSC在 Cocos2d-x 项目里,是 js 脚本被 V8 或 JavaScriptCore 编译后的二进制产物,很多游戏把热更脚本、核心玩法逻辑都塞在 .jsc 文件里。JSC 解密工具的价值,就是把这些编译或加密过的文件还原成能读、能改、能排查问题的 JS 源码。新版工具通常解决了老版本不识别 Cocos 3.x 文件头、密钥搜索不全的问题。适合做游戏维护、资源恢复、热更问题定位的开发者。需要提前说明:所有解密操作,请只针对你拥有或已获授权的项目。

2. 解密前的三分钟鉴定:把JSC版本和封装方式认清楚

我把 .jsc 文件拿到手,第一件事不是找工具,而是先看十六进制。社区里流传的“新版JSC解密工具”大多只处理一种封装方式,搞不清版本直接用,翻车概率超过一半。下面这套鉴定流程,全程不需要依赖某个具体工具,用 Hex 编辑器或者一条命令就能完成。

2.1 用十六进制先验明正身:从文件头识别Cocos版本

先找一个最小的 jsc 文件,执行:

xxd -l 64 assets/main.jsc

注意前 16 字节。如果能看到可读的 ASCII 字符,比如JSC、jsb、V8这种三个字母的 magic,说明这个文件是引擎直接生成的 jsc 字节码,没有套常见的 XXTEA 壳。这类文件严格说不是“加密过的”,而是“编译过的”,很多通用解密工具会把它原样复制出来,或者只做字符串提取。

如果前 16 字节完全没有任何可读 ASCII,看起来像随机字节,就要怀疑外面套了自定义壳。绝大多数游戏资源包里出现的 jsc,并不是纯 V8 字节码,而是先用 XXTEA 把明文 JS 加密后再存成 .jsc 后缀。判断依据很简单:直接打开是乱码,但长度和明文 JS 差距不大,且文件大小基本都是 8 字节对齐。

Cocos 版本差异在文件头也很明显。Cocos 2.x 多用 JavaScriptCore,Cocos 3.x 在 Android 上默认走 V8。有些定制引擎还会改掉默认魔数,所以我一般不会只看三个字符,而是同时看第 4 到第 8 字节的版本区。新版 JSC 解密工具的一个重要改进,就是能识别 Cocos 3.x 的头部结构,而不像老工具那样一上来就按 2.x 的格式剥偏移。

想快速批量判断目录里所有 jsc 的类型,可以用一段 Python:

import pathlib import binascii for p in pathlib.Path("assets").rglob("*.jsc"): head = p.read_bytes()[:32] ascii_view = "".join(chr(b) if 32 <= b < 127 else "." for b in head) print(f"{p}\t{binascii.hexlify(head[:16]).decode()}\t{ascii_view[:16]}")

这段代码把每个 jsc 的前 32 字节打印成十六进制和可读字符,方便一眼筛出哪些是带魔数的标准 jsc、哪些是看不出结构的加密壳。binascii.hexlify负责把字节转成十六进制字符串,:16只取前 16 个字节防止输出太长。这一步的目的不是解密,而是给后面选择工具参数提供依据。

2.2 判断是否套了XXTEA壳:看熵和字符串密度

标准明文 JS 是文本,代码中有大量function、var、this这类可读字符串。引擎生成的 jsc 字节码至少还能看到函数名片段。而 XXTEA 加密后的数据会把这些信息全部打散,用strings扫不出几个有意义的词。

用strings快速检查:

strings assets/main.jsc | head -20

如果输出里只有零星几个路径或版本号,说明文件很可能被加密过。如果想更精确一点,可以计算文件的熵值,原理是加密后的字节分布更均匀,熵值徘徊在 7.9 左右;明文 JS 的熵一般 4 到 6 之间。注意这不是绝对标准,但作为快速筛查足够了。

import math import collections def entropy(data: bytes) -> float: if not data: return 0.0 total = len(data) counter = collections.Counter(data) return -sum((count / total) * math.log2(count / total) for count in counter.values()) sample = open("assets/main.jsc", "rb").read() print(f"entropy: {entropy(sample):.2f} bits/byte")

这段代码统计每个字节的出现频率,再按信息熵公式计算。熵越接近 8,说明数据越像随机密文;如果加密壳还做了 ECB 模式的分组对齐,熵值会非常高。新版 JSC 解密工具内部通常也有一层类似判断,用来决定“这个文件是直接抄出来还是进 XXTEA 解密流程”。所以你自己先跑一遍,能提前知道工具会走哪条分支,避免解密后对着乱码发呆。

2.3 去找密钥:配置文件里的xxteaKey

如果判断结果是 XXTEA 壳,下一步就是找 key。很多 Cocos 热更项目会在配置里显式写出密钥,常见位置包括project.json、game.js、src/settings.js,或者直接写死在 Android 的libcocos2dlua.so的字符串常量里。先用文本搜索在资源包内找一遍:

grep -r "xxtea" --include="*.json" --include="*.js" .

能找到xxteaKey或key字段最好。找不到也别急着放弃,很多游戏用的就是引擎源码里带的默认 XXTEA 密钥,只是换了个格式。新版工具做得比较省事的地方,就是内置了一份常见默认 key 列表,你只需要在命令行里指定-k参数覆盖它。如果没有可用的 key,后面所有解密动作都白搭,这一点请先记牢。

3. 把新版JSC解密工具跑起来:从RAR解压到批量还原的完整步骤

搞清楚封装类型之后,才轮到工具本身。实际操作里,第一道门槛往往不是解密,而是怎么把这套从 RAR 里解出来的工具跑起来。很多人卡在解压报错,连工具还没见到就结束了。

3.1 处理RAR分发包:伪加密与解压环境

RAR 是个很常见的分发格式,但拿到的“新版JSC解密工具.rar”未必都很规矩。分享者可能给压缩包加了伪加密,所谓伪加密,只是在 RAR 头部的加密标志位做了标记,数据区本身没加密。表现是:双击提示需要密码,7-Zip 打开却能看到完整文件列表,拖出来时又报错。遇到这种情况,先不要急着猜密码,先用 7-Zip 的命令行测试一下:

7z t "新版JSC解密工具.rar"

如果提示文件列表正常,只是某个文件校验失败,多半是伪加密或下载不完整。我再强调一句:如果是真密码保护,请找发布者要授权;不要用暴力破解工具去撞,既浪费时间,也容易踩到带木马的伪破解包。合法场景下,伪加密一般可以直接用 7-Zip 解出来。

确认 RAR 完整后,解压到工作目录:

mkdir -p work 7z x -y "新版JSC解密工具.rar" -owork/tool

解压后先看内容,优先找 Python 脚本而不是 exe。因为 exe 常被加壳、被杀毒软件误报,而且你没法知道它除了解密还做了什么。Python 版脚本可以一条条读,确认没有危险操作再用。

3.2 准备运行环境:venv和xxtea依赖

很多 jsc 解密工具都依赖 Python 的xxtea库,它是 XXTEA 算法的标准实现。我习惯单独建一个虚拟环境,防止污染系统 Python:

cd work python -m venv .venv source .venv/bin/activate pip install xxtea

在 Windows 上,激活虚拟环境的命令是.venv\Scripts\activate。装好后写一个简单的命令行入口脚本jsc_batch_decrypt.py,放在工具目录下。这样以后换机器,只要重新装一遍 xxtea 就能跑,不用依赖某个 GUI 工具。

3.3 最小批量解密脚本:递归处理整个资源目录

下面这段脚本是我常用做法的精简版,能处理两类情况:没有壳的标准 jsc 直接复制,套了 XXTEA 壳的尝试解密。保留相对路径,方便解密后对照原文件位置。

#!/usr/bin/env python3 # jsc_batch_decrypt.py # 批量还原 Cocos2d-x 的 .jsc 文件,支持无壳原样复制与 XXTEA 解密 import argparse import pathlib import sys try: import xxtea except ImportError: sys.exit("缺少 xxtea 依赖,请先执行: pip install xxtea") # 常见默认密钥,实际项目请用 -k 传入自己的 key DEFAULT_KEYS = [ b"2dxLua", b"cocos2d-x", ] def looks_like_raw_jsc(data: bytes) -> bool: """通过头部 magic 判断是否为引擎直接生成的 jsc""" for magic in (b"JSC", b"jsb", b"V8"): if data.startswith(magic): return True return False def decrypt_one(src: pathlib.Path, dst: pathlib.Path, key: bytes, offset: int) -> str: data = src.read_bytes() if offset: data = data[offset:] if looks_like_raw_jsc(data): dst.write_bytes(data) return "raw-copy" key_list = [key] if key else DEFAULT_KEYS for candidate in key_list: try: plain = xxtea.decrypt(data, candidate) except Exception: continue # 解密成功且像 JS 文本,就写入输出文件 if plain and plain[:3] in (b"var", b"let", b"con", b"fun", b"<!", b"\xef\xbb\xbf"): dst.write_bytes(plain) return "decrypted" return "failed" def main(): ap = argparse.ArgumentParser(description="批量还原 JSC 文件,仅限授权资源") ap.add_argument("input", type=pathlib.Path, help="输入目录,例如 assets") ap.add_argument("-o", "--output", type=pathlib.Path, default=pathlib.Path("out")) ap.add_argument("-k", "--key", default="", help="XXTEA 密钥,留空则尝试默认列表") ap.add_argument("--offset", type=int, default=0, help="自定义头字节数,默认0") args = ap.parse_args() key = args.key.encode("utf-8") if args.key else b"" files = list(args.input.rglob("*.jsc")) if not files: sys.exit(f"no .jsc files found under {args.input}") for src in files: rel = src.relative_to(args.input) dst = args.output / rel.with_suffix(".js") dst.parent.mkdir(parents=True, exist_ok=True) status = decrypt_one(src, dst, key, args.offset) print(f"{status}\t{rel}") print(f"done: {len(files)} files") if __name__ == "__main__": main()

脚本的逻辑很直接:rglob("*.jsc")递归拿全目录下所有 .jsc 文件;looks_like_raw_jsc先识别前几个字节,符合魔数就直接复制,因为这种文件本质是字节码,剥不剥壳都不会变成文本;不符合魔数再走 XXTEA 解密。xxtea.decrypt用的 key 是 bytes,所以命令行传来的字符串必须encode("utf-8")。解密成功的判断是看开头三个字节是不是var、let、fun这类 JS 文本特征;如果 key 不对,解密结果通常是随机乱码,也不会被写入。

--offset参数针对的是自定义头:有些游戏在 jsc 前面追加了自己的版本号、时间戳,正式数据被整体往后推。需要先用十六进制工具确认自定义头长度,比如看到前 8 字节是某个结构体,后面才是JSC魔数,那 offset 就设置为 8。

3.4 参数详解:版本、密钥、偏移和输出路径

实际执行时,我一般这样跑:

python jsc_batch_decrypt.py assets -o output -k "你的key" --offset 8

如果拿不准 key,先留空让脚本尝试默认列表:

python jsc_batch_decrypt.py assets -o output

输出里每一行会显示状态:decrypted表示成功;raw-copy表示原始 jsc;failed表示 key 不对或封装类型不在工具能力范围内。看到failed不要慌,后面避坑章节有专门排查流程。

下面这几个参数是最常调的:

参数作用调错会怎样
input资源根目录,脚本递归找 .jsc路径不存在会直接报错
-o输出目录,不写默认生成out输出和输入混一起,覆盖原文件
-kXXTEA 密钥key 错误时解密结果全是乱码
--offset跳过自定义头字节数偏移不对,magic 识别失败,可能被强行解密后坏掉

之前我吃过一次亏:以为所有 jsc 都是无壳的,把带壳文件直接扔给引擎加载,结果 Cocos 报了一堆SyntaxError。后来才养成先跑鉴定、再选参数的习惯。新版 JSC 解密工具虽然号称通用,但通用不等于自动,它仍然需要你告诉它文件的真实封装方式。

4. 解密结果的验证:还原出的JS能不能直接跑

解密脚本跑完,只算完成一半。更关键的是验证解密出来的 JS 是否可读、可执行。很多时候工具输出了一堆 .js 文件,但里面一半是乱码,另一半是套娃解出来的标准 jsc,这种情况直接交给 Node.js 跑必然报错。

4.1 解密后先看文件头:是明文JS还是另一个jsc

批量解密完成后,先抽样看几个输出文件:

file output/main.js head -c 200 output/main.js

如果file显示是ASCII text或Unicode text,并且开头是var、function、class,说明这一步成功了。如果显示data或者MS Windows这类奇怪结果,说明解密产物不是文本,需要进一步判断。

再用xxd看前 32 字节:

xxd -l 32 output/main.js

如果开头出现了JSC、jsb这类魔数,说明原来文件是先编译成 jsc、再套的 XXTEA。你的工具剥掉的是外层壳,里面还是引擎字节码。这种情况不要指望改成 .js 就能读,后面要换思路处理。新版 JSC 解密工具能准确识别这个状态,会提示你“已解密,但结果不是 JS 源码”。这属于工具边界,不是 bug。

4.2 用Node.js做语法冒烟和关键函数比对

输出文件疑似是明文 JS 后,最直接的验证办法是用 Node.js 做语法检查,不执行代码:

node --check output/main.js

--check只解析不执行,适合快速确认解密结果有没有语法错。Cocos 工程里的 JS 经常用到cc、require这类运行时对象,直接执行会因为找不到上下文而报错,但语法检查没有这个烦恼。

如果语法检查通过,再核对几个关键函数名是否还在:

grep -n "login\|init\|update\|onLoad" output/main.js | head -20

这一步是在验证核心逻辑有没有在解密过程中被截断或破坏。XXTEA 解密如果 key 正确,理论上恢复的是完整明文,函数名、字符串都会原样回来。如果你能搜到onLoad却搜不到login,可能是文件被拆分打包过,或者这个 jsc 本身只是某个模块,还需要和其他文件拼接。

也可以和备份的源码做 diff。手里有旧版 JS 的话,用diff -u old.js output/main.js看差异,能直观看出解密还原的准确度。没有旧版也没关系,至少确认语法和关键函数都正常,再考虑放回 Cocos 工程里跑。

4.3 解密后乱码的排查顺序

看到乱码不要马上怪工具,按下面顺序排查,九成能定位:

先看failed状态的文件是不是集中在某个子目录。如果是,说明这批 jsc 和主目录的封装方式不同,可能来自不同渠道包,或者个别文件被二次加密过。再尝试用不同的 offset 重新跑,从 0 开始,然后 2、4、8、16 逐个试,观察输出文件头部是否出现魔数或 JS 文本。最后检查 key 是否有隐藏字符,比如从网页复制密钥时带了个换行符,肉眼看不到,但 bytes 对比全部错位。

还有一种情况是解密后开头有\xef\xbb\xbf,也就是 UTF-8 BOM。脚本里我特意把\xef\xbb\xbf作为成功特征之一,因为很多 Windows 下打包的 JS 都有 BOM,它不影响 Node.js 执行,但会影响某些文本对比工具。

5. 避坑与常见问题:JSC解密工具翻车的五个现场

这一章写的是我见过、踩过最多的问题。每一条都按现象、原因、解决展开,方便你遇到时直接对号入座。

5.1 RAR伪加密:解压报错但能看到文件列表

现象:双击“新版JSC解密工具.rar”提示需要密码,用 7-Zip 打开又能看到完整文件列表,拖动解压时却报错。

原因:RAR 头部加密标志位为 1,但数据区并没有真实加密。这是发布者故意设置的伪加密,主要防止网页端直接预览下载内容,资源本身没有保护。

解决:先用7z t检查完整性,再用7z x尝试解压。如果最后还是报错,检查压缩包是不是通过网页在线传输工具下载的,文件大小是否为 0 或偏小。伪加密可以用修改 rar 头标志位的方式修复,但我更建议直接找发布者要一个没加密的版本。不要随便用网上流传的“rar密码移除”工具,这类工具经常打包木马。

5.2 工具版本与Cocos版本不匹配:前半段正常,后半段乱码

现象:解密后文件能用编辑器打开,开头能看到var和部分函数名,但读到中后部全是乱码,函数不完整。

原因:这是老版 JSC 解密工具最典型的缺陷。Cocos 3.x 对 XXTEA 的 padding 规则做了调整,或者自定义头从 8 字节变成 16 字节。老工具固定按 2.x 的偏移截断数据,导致起始位置错位,前半段碰巧可读,后半段全部错乱。

解决:换到新版工具,或者在脚本里把--offset从 0 开始逐级尝试。注意观察每次解密后文件头的变化,如果从乱码变成了以JSC或jsb开头,说明 offset 对了,剥到了原始 jsc 层;如果直接变成可读 JS,说明一层就解到了底。

5.3 密钥给错:所有文件都解密失败或输出乱码

现象:批量脚本跑完,80% 以上状态是failed,少量输出文件打开后是无规律的二进制。

原因:项目用的不是默认 XXTEA 密钥。引擎示例里的2dxLua只是默认值,很多游戏会在构建时改成随机字符串。工具内置的 key 字典覆盖不到。

解决:去资源包配置里搜xxteaKey、key、code等字段。搜不到就把 Android 版 apk 解包,在 so 文件里搜字符串。新版 JSC 解密工具一般会提供一个--key-file参数,作用是传入一个文本文件,里面按行放候选 key,脚本逐个尝试。这个方法很笨,但确实能解决大量实际项目。

5.4 二次封装:解密一次后仍然是二进制字节码

现象:脚本输出decrypted,但打开文件发现不是 JS 文本,而是以JSC魔数开头的字节码。

原因:游戏团队为了保证性能,先把明文 js 编译成引擎字节码,再对字节码做 XXTEA 加密。工具剥掉 XXTEA 后,得到的是标准 jsc。这是很多“通用解密工具”不处理的部分,因为反编译 V8 字节码是另一个技术方向。

解决:先确认输出文件头,如果是标准 jsc,那就把它当作无壳字节码。用支持 V8 bytecode 的逆向工具提取字符串、函数签名和常量。这个方案不能完整恢复源码,但能恢复大部分业务逻辑阅读价值。如果你真的只需要看可读 JS,只能去客户端包里找是否有未加密的 js 热更包,或者找项目的原始发布包。

5.5 工具本身被杀毒软件查杀或exe跑不起来

现象:解压后 exe 被杀毒软件隔离;双击提示缺少 DLL;命令行窗口一闪而过。

原因:这类分发工具为了减小体积,常用 UPX 或易语言加壳,杀软误报率高。旧版工具依赖老版本 VC++ 运行库,新系统上缺 DLL 很常见。

解决:优先选择 Python 脚本版,像前面写的那段脚本就能完成大部分场景。exe 版只在虚拟机或隔离环境里跑,跑之前先用7-Zip而不是 Windows 自带解压器打开,某些系统自带工具会拦截可执行文件。如果你只是要解密自己项目里的 jsc,强烈建议直接用 Python 脚本,不要依赖来路不明的 exe,毕竟这类工具本质上是要读取你工程里的核心文件,安全性怎么强调都不过分。

6. 把解密逻辑做成自己的工作流:批量处理与最小改动验证

上面这些步骤每次手动跑一遍很累,我现在的习惯是把它固化成一个固定流程:先备份、再鉴定、再批量解密、最后做差异对比。

值得投入做的一件事,是在解密脚本里增加一个--dry-run模式。这个模式下,脚本不解密,只打印每个 jsc 的封装类型、文件大小、建议参数。这样拿到新资源包后,先跑一遍 dry-run,确认所有文件都在能力范围内,再真正解密。加一个参数并不复杂,核心逻辑是在decrypt_one之前提前做头部判断:

python jsc_batch_decrypt.py assets --dry-run

输出会像这样:

xxtea assets/main.jsc offset=0 key=default raw assets/panel.jsc copy directly unknown assets/local.jsc need manual check

我用这个习惯之后,省了很多来回试错的时间。以前经常是批量解密完才发现有一半文件不在这套工具支持范围内,白白浪费十几分钟。现在 dry-run 先扫一遍,哪些能解、哪些要换方案,一目了然。

另一个建议是,每次解密前先对原始 .jsc 目录生成一份 MD5 清单,解密后再生成输出目录的 MD5。两份清单比对,能精确知道哪些文件被改动过,哪些是原样复制。尤其在工作需要交给别人复核时,这个清单比口头说明可靠得多。

我自己吃过一次亏:某次为了赶时间,手动指定了一个从论坛里抄的 key,结果那 key 是某个演示项目的,不是线上项目,解密出来的文件全部“成功”但全部不能跑。当时没有做 dry-run,也没有做解密前后比对,等发现问题时已经改动了十几个文件。后来我把 key 校验写成了硬性步骤:如果解密后文件中可读 ASCII 比例低于 5%,直接判定为 key 错误,不再向后处理。这个阈值你们可以根据项目实际情况调整。

做 JSC 解密,核心不是找到一把万能的工具,而是建立一套“识别——选择参数——验证——记录”的流程。新版工具能帮你省掉一部分重复劳动,但判断和处理边界,还得自己盯。希望这套流程和踩坑记录能帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询