JSC 文件的三种类型
.jsc 不是一种统一格式,常见有三类:
| 类型 | 本质 | 能否反编译 |
|---|---|---|
| bytenode 生成 | V8 字节码 | 基本不能还原源码 |
| JavaScriptCore(iOS/WebKit) | JSCore 缓存 | 无稳定通用工具 |
| 微信小程序 | V8 字节码或混淆加密体 | 几乎不可能还原 |
核心结论:JSC 是编译产物,不是源码压缩。变量名、结构、注释已丢失,不存在完美反编译。
View8 报错原因
RuntimeError: Failed to detect version for file index.jsc
View8 要先检测 V8 版本,失败通常是这几个原因:
- 文件不是 V8 cache——bytenode 生成的
.jsc结构与 V8 code cache 不同 .jsc被加了 header、base64 或 zip 包装- V8 版本超出 View8 支持范围(通常只支持 8.x~11.x)
用 Python 快速判断:
with open("index.jsc", "rb") as f:
print(f.read(32).hex())
V8 code cache 开头有固定的 magic bytes。如果头部是乱码或压缩特征,View8 直接放弃。
Python 提取可读字符串
不管是哪种 JSC,都可以先提取二进制文件中的可读字符串,判断是否有逆向价值:
import re
with open("index.jsc", "rb") as f:
data = f.read()
strings = re.findall(rb"[ -~]{6,}", data)
seen = set()
for s in strings:
text = s.decode("utf-8", errors="ignore")
if text not in seen:
seen.add(text)
print(text)
正则 [ -~]{6,} 匹配长度 >= 6 的 ASCII 可读字符串。
结果判断:
- 出现
/api/、token、userInfo等 → 文件未加密,有分析价值 - 全是乱码 → 已加密或压缩,需换思路
bytenode JSC 的运行时分析
bytenode 产物无法静态反编译,但可以在 Node.js 中加载后 hook:
require("bytenode");
// hook 所有函数调用
const originalCall = Function.prototype.call;
Function.prototype.call = function(...args) {
if (this.name) {
console.log("[call]", this.name, args.slice(0, 2));
}
return originalCall.apply(this, args);
};
require("./index.jsc");
或者用 Node.js inspect 调试:
node --inspect-brk -e "require('bytenode'); require('./index.jsc')"
然后用 Chrome DevTools 连接 chrome://inspect,可以打断点、查看调用栈。
三种方案对比
| 方案 | 成功率 | 适用场景 |
|---|---|---|
| Python strings 提取 | 高(未加密) | 快速判断有无价值 |
| 运行时 hook | 高 | bytenode 产物 |
| Node inspect 调试 | 高 | 有 require 入口 |
| 静态 V8 字节码分析 | 低 | 仅作辅助 |
对于加密 JSC(AES/RC4 加密,或微信小游戏自定义 VM),以上方法均不适用,需要先逆向解密逻辑。
