为什么解包只有部分资源
1. 文件在 app.asar.unpacked 而不在 asar 里
Electron 会把不适合打包进 asar 的文件放到同级目录:
resources/
├─ app.asar ← 前端代码、JS bundle
└─ app.asar.unpacked/ ← 原生模块、大文件
通常放在 unpacked 里的有:
.node原生扩展ffmpeg.dll/ffmpeg.so- AI 模型、WASM 文件
- 浏览器内核组件
解包时要把 app.asar 和 app.asar.unpacked 都看一遍。
2. webpack 把所有代码打成了 bundle
现代 Electron 应用几乎都用 webpack 打包,解包后看到的不是:
src/pages/index.js
src/components/Button.js
而是:
main.js
renderer.js
chunk.a1b2c3.js
所有模块都合并进了 bundle,没有”缺文件”,只是代码被合并了。
3. 资源在运行时从网络下载
部分 AI 软件、IDE 工具首次启动时会在线下载:
- 语言包
- 插件资源
- 模型文件
- JS chunk
下载后存到用户目录,不在安装包里:
Windows:
%AppData%\应用名\ ← 配置、sqlite、token
%LocalAppData%\应用名\ ← 缓存、大文件、下载资源
4. JS 被编译为 V8 字节码(.jsc)
商业 Electron 应用常用 bytenode 把 JS 编译成 .jsc:
main.js → main.jsc
普通 asar 解包后可以看到文件,但无法读取源码。
5. 应用对资源做了加密
运行时解密:
// 应用内部流程(无法直接看到)
const encrypted = fs.readFileSync('xxx.bin');
const code = decrypt(encrypted, key);
eval(code);
解包后只能看到加密的 .bin 文件。
解包工具
# 查看 asar 文件列表
npx asar list app.asar
# 解包到指定目录
npx asar extract app.asar ./out
解包后搜索这些关键字找 webpack 入口:
webpackChunk
__webpack_require__
Electron 应用资源分布
| 位置 | 通常存放 |
|---|---|
resources/app.asar | 前端页面、JS bundle、html、css |
resources/app.asar.unpacked/ | .node 模块、dll、ffmpeg、WASM |
%AppData%/应用名/ | 用户配置、sqlite、历史记录 |
%LocalAppData%/应用名/ | 缓存、下载的大文件、模型 |
%AppData%/.../Code Cache/ | V8 字节码缓存 |
%AppData%/.../IndexedDB/ | 结构化数据 |
逆向流程
1. 解包 asar
npx asar extract app.asar ./out
2. 检查 app.asar.unpacked
ls resources/app.asar.unpacked/
3. 找 preload.js
preload 是 Electron 主进程和渲染进程之间的桥梁,通常包含 IPC 通信和权限暴露逻辑:
out/main/preload.js
out/dist-electron/preload.js
4. 找用户数据目录
# Windows
dir %AppData%\应用名
dir %LocalAppData%\应用名
5. Hook fs 抓解密内容
对于运行时解密的资源,hook fs.readFileSync 把解密后的结果 dump 出来:
const fs = require('fs');
const orig = fs.readFileSync;
fs.readFileSync = function (path, options) {
const result = orig.apply(this, arguments);
if (path.includes('.bin') || path.includes('.jsc')) {
console.log('[readFileSync]', path, result.toString('hex').slice(0, 64));
}
return result;
};
6. 检查是否是 V8 字节码
.jsc 文件开头有 V8 magic bytes,可以用 bytenode 的 wrap 机制在运行时拿到原始代码,但需要和目标 Node.js/Electron 版本完全匹配。
