Showing Posts From

Electron

Electron asar 解包:资源为什么只有一部分以及各类资源的位置

解包 app.asar 后只看到"部分资源",通常不是工具有问题,而是资源本来就不全在 asar 里。 app.asar.unpacked 目录 很多 Electron 应用把资源拆成两部分: resources/ ├─ app.asar ← 打包进归档的前端代码 └─ app.asar.unpacked ← 不打包,直接放文件系统不能放进 asar 的资源通常在 unpacked:.node 原生模块 dll、exe 二进制 ffmpeg 大模型权重 WASM 文件 Chromium 扩展解包命令: npx asar extract app.asar out查看归档内容: npx asar list app.asar运行时动态下载 很多 AI 软件、IDE 首次启动后会在线下载:JS chunk 模型权重 WASM 模块 加密资源这些完全不在 asar 里。常见存放位置: # Windows %AppData%\Roaming\应用名\ ← 配置、数据库、历史记录 %AppData%\Local\应用名\ ← 缓存、大文件、模型webpack 打包合并 现代 Electron 应用几乎不会保留 src/pages/ 这样的目录结构,而是打成 bundle: main.js renderer.js chunk.abc123.js你以为"缺文件",其实文件已经被合并进 bundle 了。搜索以下关键词确认: webpackChunk __webpack_require__加密和混淆 部分商业应用会:存 .jsc / .bin V8 字节码(bytenode),无法直接还原源码 webpack chunk 内字符串 XOR 混淆 运行时解密:decrypt(buffer); eval(...) 拿到真正的代码各类资源的位置速查目标 位置前端源码(React/Vue) app.asar 解包后的 bundle配置、token、sqlite %AppData%\Roaming\应用名缓存、模型、大文件 %AppData%\Local\应用名原生模块、二进制 app.asar.unpacked内联图片 bundle 里 base64 编码关键 IPC 桥接逻辑 preload.jsElectron 默认缓存目录 Cache/ Code Cache/ ← 可能有 V8 字节码缓存 GPUCache/ IndexedDB/ ← 配置、文档、AI 数据 Local Storage/ blob_storage/完整逆向流程 # 1. 解包 npx asar extract app.asar out# 2. 找 webpack 入口 grep -r "__webpack_require__" out/# 3. 重点看 preload # out/main/preload.js 或 dist-electron/preload.js# 4. 如果有加密,搜解密关键词 grep -r "decrypt\|Buffer\|crypto\|atob" out/# 5. 找用户数据 ls %AppData%\Roaming\应用名常见真实目录结构 MyApp/ ├─ resources/ │ ├─ app.asar │ ├─ app.asar.unpacked/ │ │ ├─ native.node │ │ └─ ffmpeg.dll │ └─ ... └─ locales/AppData/Roaming/MyApp/ ├─ IndexedDB/ ├─ Local Storage/ ├─ settings.json └─ user.db

解包 Electron 的 app.asar 只有部分文件?六个原因

Electron 应用的 resources/app.asar 解开看,只有一部分源码 / 资源——很多明明代码里 require 过的模块或者用到的图片、模型完全找不到。不是解包工具坏,是 Electron 应用故意这么组织的。 1. 文件在 app.asar.unpacked 最常见。resources/ 目录下有两个: resources/ ├── app.asar # 归档 └── app.asar.unpacked/ # 不归档,直接文件系统electron-builder / electron-packager 有 asarUnpack 配置,指定哪些文件不打进 asar。原因:原生模块 .node:Node 加载 native addon 只认真实文件路径 可执行文件(ffmpeg.exe、外部工具) 大文件(模型、字体、图片)——放 asar 会导致启动时全部读到内存 需要写入的资源(缓存、配置模板)解决:同时解 asar 和 unpacked 目录,才能拿全资源。 npx asar extract app.asar out/ # 然后手动合并 app.asar.unpacked 里的内容2. 运行时动态下载 很多 AI / IDE / 客户端首次启动会拉模型或 SDK:Cursor / VSCode 下载语言服务 Notion / Figma 缓存 web 资源 Whisper.cpp 下运行 GGUF 模型 客户端更新组件到 %AppData%常见落地目录: Windows: %APPDATA%\<AppName>\ %LOCALAPPDATA%\<AppName>\macOS: ~/Library/Application Support/<AppName>/ ~/Library/Caches/<AppName>/Linux: ~/.config/<AppName>/ ~/.cache/<AppName>/这些目录不属于 asar,别在 asar 里找。 3. webpack chunk 打包 / 混淆 代码里看到: require("./modules/wallet.js")在 asar 里 modules/ 目录空空如也。原因是打包时被 webpack 摊平: (() => { var __webpack_modules__ = { 123: (e, t, r) => { /* wallet.js 的内容 */ }, 456: (e, t, r) => { /* something else */ }, }; // ... })();wallet.js 变成模块 ID 123,塞进主 bundle。名字都没了,找源文件是找不到的。 恢复思路:用 webcrack 或 react-native-decompiler 尝试还原模块结构 source map 有的话直接 .map 文件恢复 主 bundle 里搜函数名 / 字符串手工定位4. asar 完整性校验 Electron 的 --asar-integrity 特性(v22+)——启动时校验 asar 的 SHA-256,被改过就直接崩: Integrity check failed: 0x...有的应用还会自校验: const hash = crypto.createHash("sha256").update(fs.readFileSync(asarPath)).digest("hex"); if (hash !== EXPECTED_HASH) app.exit();改过 asar 塞回去,应用启动就退。想跑起来得同时改校验逻辑。 5. 资源加密 商业 Electron 应用常见做法: 方式 A:启动时解密 const encryptedBuffer = fs.readFileSync("./data.bin"); const source = decrypt(encryptedBuffer, KEY); new Function(source)(); // 或 eval, vm.runInNewContextasar 里只能看到加密后的 blob。想读得先拿到 KEY——通常在主 bundle 里硬编码或经过混淆。 方式 B:V8 Bytecode(bytenode) xxx.jsc xxx.bin这些是 bytenode 编译的 V8 字节码,普通反编译工具还原不了源码。只能在运行时逆向。 6. 解包工具版本太老 老的第三方解包工具不支持新版 asar 格式:新版 asar header 有 offset 大文件跨块 unicode 文件名编码变化永远优先用官方: # 官方 CLI npx @electron/asar extract app.asar out/ npx @electron/asar list app.asar或者装全局: npm i -g @electron/asar asar extract app.asar out/一张排查表 看到"资源缺",按这个顺序查:现象 大概率原因.node / ffmpeg 找不到 在 app.asar.unpacked模型 / 大图找不到 unpacked 或运行时下载require 的模块找不到源文件 webpack 打包混淆.jsc / .bin 打不开 V8 bytecode 或加密改了 asar 应用启动就退 完整性校验一部分目录空 / 文件小 解包工具太老,换 @electron/asar一句话总结 Electron 解包"少东西"是常态。先看 app.asar.unpacked、再看 %AppData% 用户目录、再考虑 webpack chunk / 加密 / bytecode。用 @electron/asar 官方工具,别用老的第三方版本。

electron 开发中运行失败

解决方案 pnpm exec node node_modules/electron/install.js