大多数 Electron 应用把 JavaScript、HTML 和各种资源打进一个叫 app.asar 的文件里,放在应用的 resources 目录下。ASAR 是一种很简单的归档格式:开头是一段描述目录树的 JSON 头,后面把各个文件的内容不压缩地依次拼接起来。里面装着决定 Electron 应用安全模型的三部分:拥有完整 Node.js 能力的 main 进程代码;决定网页能碰到什么的 preload 脚本;以及 renderer 页面。三者之间通过 IPC 通道通信。
这个工具在浏览器里打开 app.asar,列出全部文件,可以单独下载或预览其中任何一个已打包的文件,并且把代码里注册和调用的 IPC 通道整理成一张表。归档文件自始至终不会上传。
能做什么
输入。 一个 ASAR 归档,通常是 resources/app.asar。页面一开始只读 16 字节的前缀和 JSON 头,文件内容用到时才读,所以再大的归档,开销也差不多只是读一个头。上限:头部最大 32 MiB,最多 100 万个条目,目录最多嵌套 128 层,分析超时时间 2 分钟。
归档内容。 你会看到:
- 文件树:每个文件、目录和符号链接,以可折叠、可搜索的树形展示,带大小。导出的 JSON 里还有每个文件的偏移、可执行标志;归档里有逐文件的
integrity记录时,也包含它的算法和哈希。 - 统计:文件、目录、链接、unpacked 文件各有多少,总大小,按扩展名的分布,以及最大的 20 个文件。
- 下载和预览:任何存放在归档里面的文件,都可以单独下载或以文本方式查看,不用把整个归档解开。符号链接会自动跟随。
app.asar.unpacked条目:标为 unpacked 的文件会列出来,但它们的字节并不在.asar文件里,Electron 把它们放在旁边的app.asar.unpacked/目录中。原生模块通常就放在那里。
Electron 分析。 报告还包括:
- package.json:
name、version和main。main 入口按 Node 的规则解析,默认是index.js。 - preload 脚本:赋给
preload属性的字符串,例如webPreferences: { preload: path.join(__dirname, 'preload.js') },解析成归档里的文件,并注明它是在哪个文件的哪一行配置的。 - renderer 入口:归档中 HTML 文件里的
<script src>,解析成归档内的路径;远程 URL 会被忽略。 - IPC 通道表:所有对
ipcMain.handle、ipcMain.on、ipcMain.once、ipcRenderer.invoke、ipcRenderer.send、ipcRenderer.sendSync、ipcRenderer.on和webContents.send的调用(win.webContents.send这种写法也算)。每一行给出通道名、API、方向(renderer 到 main,或 main 到 renderer)、所属进程,以及文件:行号。通道不是单纯的字符串字面量时,这一行标为动态,并显示原始表达式。 - contextBridge 暴露:每个
contextBridge.exposeInMainWorld(name, { ... }),列出暴露的名字和 API 对象的键。这正是网页能调用的全部接口。 - 原生模块:
.node文件(编译成 Mach-O、ELF 或 PE 的 Node 扩展),带大小和是否 unpacked。 - source map:归档里的
.map文件,以及被扫描的 JavaScript 文件中有多少个以sourceMappingURL注释结尾。 - 警告:名字可疑的条目(含
..、斜杠或绝对路径)、指向归档外部的链接、格式不对的条目、超出归档末尾的文件,以及只扫描了一部分的 JavaScript 文件。
原理
归档开头是两个 Chromium 的 “pickle” 记录:第一个给出头部的大小,第二个把头部存成一个 JSON 字符串。页面先检查这些长度是否互相吻合,再解析 JSON,遍历其中的 files 树。已打包文件的位置是“数据区起点 + offset”,而 ASAR 把 offset 存成十进制字符串。格式处理对照 @electron/asar 4.3.1 核对过,前缀检查参考了 REA(morluto 的开源项目,MIT 许可)。
IPC 表的来源是:用一个轻量的 JavaScript 词法分析器(tokenizer)扫描归档里所有 .js、.cjs、.mjs 文件,先扫应用自己的文件,node_modules 放在最后。词法分析会跳过注释、字符串内容和正则表达式,所以字符串里出现的 "ipcMain.handle('x')" 这种文字不会被误报。然后匹配 ipcRenderer.invoke( 这样的成员调用,读取第一个参数。只有当这个参数是单个字符串,或者不含插值的模板字符串时,通道才算字面量。
判断一个文件属于哪个进程:页面从 main 入口、已解析的 preload 脚本和 renderer 脚本出发,沿着相对路径的 require 和 import 往下走。没被这样走到的文件,就根据它用的 API 推断:ipcMain 和 webContents 只存在于 main 进程;调用了 contextBridge 的文件当作 preload。都不满足的,进程显示为未知。
隐私是怎么保证的
归档文件不会被上传:
- 解析、扫描和每一次文件下载,都在你设备上的 Web Worker 里进行。Worker 通过浏览器的文件 API,只读取头部和需要的那几段字节。
- 统计事件只有粗粒度信息:成功或错误码、文件数量区间(例如
11-100)、文件大小区间、耗时区间,绝不包含文件名、文件路径、通道名或任何其他内容。完整清单见隐私政策。 - 工具页不展示广告。
如何自己验证
- 在选择文件之前,打开浏览器开发者工具,切到 Network(网络) 面板。分析一个归档,再从中下载一个文件。出现的请求只有页面资源和 worker 脚本
/_astro/asar-worker-*.js,没有任何一条带着你的归档。 - 或者先打开本页,然后断开网络(关闭 Wi-Fi,或在 Network 面板勾选 Offline),再分析文件,照样能完成。
- Worker 运行在
default-src 'none'; script-src 'self'; connect-src 'none'这条内容安全策略之下,浏览器根本不允许它发出网络请求。
局限
- 是词法扫描,不是完整的语法分析。 只认
ipcMain、ipcRenderer、webContents这几个名字后面直接跟方法调用的写法。别名不会被追踪:const { ipcRenderer: r } = require('electron'); r.send(...),或者const r = ipcRenderer,都识别不了;ipc[name](...)、ipcMain['handle'](...)这种计算属性调用也识别不了。把这些对象改了名的压缩(minify)代码,大部分行都会丢失。 - 只覆盖上面列出的 API。
ipcRenderer.once、ipcRenderer.postMessage、ipcRenderer.sendToHost、ipcMain.removeHandler,以及基于 MessagePort 的通道,都不在表里。 - 动态通道不会被求值。 由变量拼出来的通道只显示表达式,不会算出具体的值。
- 扫描预算。 每个 JavaScript 文件只扫描前 4 MiB,整个归档总共最多扫描 128 MiB。超出预算的文件(通常在
node_modules里)会在警告里列出。 - 不扫描的内容。 unpacked 的 JavaScript(字节不在归档里)、HTML 里的内联
<script>代码块、TypeScript 源文件,以及超过 1 MiB 的 package.json 或 HTML 文件。 - integrity 只显示,不校验。 导出的 JSON 里带有头部记录的每个文件的哈希,但不会重新计算核对,也不检查 Electron 的 ASAR integrity fuse 或应用包里保存的哈希。
- 进程归属是推断的。 不会追踪裸包名的导入,所以只能通过某个 npm 包到达的代码,可能显示为未知进程。
- 原生代码不在范围内。
.node文件只列出来,请用 Ghidra 这类原生工具分析。
常见问题
能把整个归档解出来吗?
页面一次下载一个文件。要完整解包,请在自己的电脑上运行 npx @electron/asar extract app.asar out/。
标为 unpacked 的文件为什么下载不了?
它的字节不在 .asar 文件里,请到旁边的 app.asar.unpacked/ 目录里找。
为什么某个通道显示为动态?
第一个参数不是单个字符串字面量,例如 `user:${id}`,或者是在别处定义的常量。打开对应文件的那一行,看它最终是什么值。
应用明明用了 IPC,表却是空的?
多半是代码被压缩、对象改了名,或者 IPC 调用位于 unpacked 的文件或超大的文件里。看一下警告和扫描统计。
它能直接找出安全漏洞吗?
它画出的是攻击面:暴露了哪些接口、有哪些通道和对应的处理函数。处理函数有没有校验输入,需要你自己去读代码判断。
合规说明
请只分析你自己开发的应用、你获得授权评估的应用,或者开源应用。请遵守所分析软件的许可协议(包括其中限制逆向工程的条款)以及适用于你的法律法规。本工具不提供任何绕过授权或其他保护措施的建议。另见免责声明。
相关教程
- 用 REA 逆向分析 Electron 应用:ASAR、preload 与 IPC 全流程:从
app.asar一路走到 IPC 处理函数的完整流程,命令行里用的是基于语法树的分析。 - 用 REA 追踪网站 API 调用:浏览器捕获、HAR 与前端 bundle:很多 Electron 应用也会调用 Web API,抓包后可以用 HAR 分析器归纳。
- WASM 转 WAT 在线工具与 WebAssembly 模块分析:分析在归档里找到的
.wasm模块。 - ASAR 解包:提取并查看 Electron 应用里的文件:各平台上
app.asar的位置、用npx @electron/asar完整解包,以及打开后先看什么。