关于 reversing-obfuscated-javascript
面向安全研究者的 JavaScript 混淆代码分析技能,指导识别转换类型、恢复源码结构并定位运行时关键函数。涵盖 sourcemap、反混淆工具、AST 处理和浏览器调试。
主要功能
- 01识别打包、混淆与反调试层
- 02检查并恢复 sourcemap 源码
- 03使用 webcrack 等工具拆包和反混淆
- 04通过 Babel AST 编写转换
- 05借助 DevTools 定位运行时函数
适用场景
- 01分析网页或扩展中的压缩 JavaScript
- 02恢复请求签名或加密例程
- 03检查客户端算法与许可逻辑
- 04评估生产环境泄露的 sourcemap
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ trilwu/ secskills --skill reversing-obfuscated-javascript安装后在 Claude Code 中输入/reversing-obfuscated-javascript确认已加载。
详细介绍
逆向混淆 JavaScript
客户端 JavaScript 会将整个程序交给读者——这里没有被剥离的二进制文件,只有刻意变得难以阅读的代码。这会改变工作方式:你几乎从来不是在恢复缺失的信息,而是在撤销某种变换。先识别变换,再用为此设计的工具将其逆转;只有针对没有现成工具支持的自定义层,才使用手写 AST 遍历。
适用场景
- 页面或扩展提供了一个需要阅读的大型压缩或打包
.js文件 - 代码中满是
_0x1234这样的标识符、一个大型字符串数组,以及顶部的旋转 IIFE——这是 obfuscator.io 的特征 - 可以访问
.js.mapsourcemap,或 webpack 留下了//# sourceMappingURL - 必须在运行中的 bundle 里定位请求签名、HMAC、令牌或加密密钥的计算位置
- 根据发布的代码复现客户端算法(反机器人信号、许可证检查、付费墙门控)
不适用场景
- React Native / Hermes 移动端 bundle(
index.android.bundle、main.jsbundle、Hermes 魔数)——请使用reversing-react-native-apps。 - 自定义字节码 VM 或虚拟化 JavaScript 混淆器,其控制流是通过解释执行而非简单扁平化实现的——这属于去虚拟化;请使用
unpacking-protected-binaries中的 VM 提升方法。 - 遭入侵的网站或 npm 包中的恶意 JS,如果目标是获取 IOC 和分析行为,而非提高可读性——针对植入的 Web payload,请使用
hunting-web-backdoors;针对恶意软件包,请使用auditing-supply-chain。 - 测试 Web 应用本身(JS 调用的端点、XSS、身份验证)——请使用
testing-web-applications;只有在需要恢复应用依赖的客户端算法时再回到这里。 - 页面加载的 WASM 模块——这属于
analyzing-binaries的范畴。
使用工具前先识别层
使用错误的反混淆工具会产生看似合理的垃圾代码。读取开头几百个字节并进行分类:
| 你看到的内容 | 变换 | 逆转方法 |
|---|---|---|
| 短名称、没有空白、字符串可读 | 仅压缩 | 使用反压缩工具 / prettier + 重命名 |
webpackChunk、模块映射 {123: function(e,t,n){…}} | Webpack/Rollup 打包 | 将 bundle 拆分为各模块文件 |
//# sourceMappingURL=… 或可访问的 .map | 无——源代码就在那里 | 恢复 sourcemap |
_0x 十六进制名称 + 一个大型字符串数组 + 旋转 IIFE | obfuscator.io 字符串数组 | 使用 webcrack / synchrony / restringer |
嵌套三元表达式、while(true){switch(_0x..)} 分发器 | 控制流扁平化 | 使用 AST 遍历重新连接 switch |
setInterval 中的 debugger、自我防护函数 | 反调试 / 自我防护 | 在其他处理前移除防护代码 |
大多数实际 bundle 都是分层的:外层是 webpack,几个模块经过 obfuscator.io 混淆,关键函数上还套有手写字符串密码。先剥离最外层。
Sourcemap:始终先试这个
可访问的 sourcemap 能让工作在开始前就结束——它包含变换前的原始源代码。每次都检查,因为有很大一部分被“混淆”的生产 bundle 都发布或泄露了 sourcemap:
- 检查 bundle 末尾的
//# sourceMappingURL=注释;即使注释被移除,也要检查同目录的.js.map(试试<bundle>.map)。 - 检查 webpack 开发产物,以及映射中
webpack://路径下的源代码。 - 使用 sourcemap 消费工具恢复文件——
unwebpack-sourcemap或一段简短的source-map脚本可以遍历sourcesContent,还原目录树。
评估应用时,应将泄露的生产 sourcemap 本身视为一项发现,而不只是便利条件。
拆包与反混淆
webcrack 是处理打包文件的首选工具,因为它可以一次完成其中三个环节:取消压缩、将 webpack/browserify 拆分为按模块组织的文件,以及还原 obfuscator.io 的字符串数组和控制流混淆。运行它之后,阅读它生成的模块树,而不是那个单体文件。
对于仅使用 obfuscator.io 混淆的打包文件,专用反混淆工具通常更简洁:synchrony 和 restringer 都能解析字符串数组、反转轮换、内联解码器调用,并展平简单的控制流。对比它们的输出——两者会在不同的边缘情况上失败。
如果没有工具能完全处理自定义混淆层,就用 Babel 编写 AST 处理流程:将代码解析为 AST,用 @babel/traverse 查找模式(特定的解码器调用、经过常量折叠的表达式、控制流展平分发器),转换节点,然后重新生成代码。这是一项经久实用的技能——混淆器会变化,但字符串数组解码、常量折叠和死分支消除每次都是相同的 AST 操作。在编写脚本之前,先在 AST Explorer 中用实际代码试验匹配器。
需要留意两种失效模式:
- 通过运行代码来“求值”字符串解码器的反混淆工具可能会执行载荷。对于不受信任或恶意的打包文件,请静态解析字符串,或在隔离沙箱中处理——切勿在本机对未知打包文件运行
eval来读取它。 - 自我防御/调试保护在代码被篡改时会重新混淆,或陷入
debugger循环。先移除保护函数(删除该节点,或覆盖setInterval),否则后续每个处理步骤都会受到干扰。
在运行中的打包文件中查找例程
当静态阅读效率很低时——例如,签名函数埋在数兆字节的模块中——改用 Chrome DevTools 驱动正在运行的页面:
- 在行为处设置断点,而不是在代码处。 XHR/fetch 断点会在签名请求发出时暂停;调用堆栈会直接回溯到签名函数。DOM 和事件监听器断点也能对 UI 触发的逻辑执行同样的操作。
- 在 Sources 面板中使用格式化(
{}),即可逐步调试压缩后的函数,无需进行任何离线处理。 - 在控制台中挂钩属性访问——对用于计算值的对象,使用
Object.defineProperty或Proxy,即可记录每次调用及其参数,并附带堆栈跟踪,因此无需阅读计算过程就能看到输入和输出。 - 使用本地、格式化且加入
console.log插桩的副本覆盖文件(DevTools Local Overrides),观察真实值在运行时如何流转。
运行时观察和静态阅读相辅相成:DevTools 会告诉你哪个函数重要;AST 处理则会告诉你它计算什么,这样你就能离线复现它。
范围与授权
阅读和反混淆你合法获取的打包文件属于分析。两方面需要谨慎。复现并重放针对源站的请求签名例程——这通常是逆向反机器人信号的原因——会对该服务产生影响,需要与任何其他测试相同的授权;请仅在你获准测试的系统上进行,并参见 testing-web-applications。此外,从第三方网站获取的源映射或打包文件属于该方的代码:为你受委托执行的安全评估而还原代码没有问题,但提取专有算法并复用则是另一回事。
应当摒弃的错误想法
- “代码经过混淆,所以只能靠人工慢慢处理。” 先分类——找到可用的 sourcemap,或顺利运行一次
webcrack,就能把数小时的工作缩短到几分钟。手动阅读是最后的手段,而不是第一步。 - “
webcrack的输出有个奇怪的地方,所以它失败了。” 分层混淆意味着,一个工具会清除外层,留下自定义的内层混淆。残留部分正是有趣的函数;对它执行 AST 处理即可,不要从头再来。 - “我直接 eval 字符串解码器来获取明文就行。” 面对不可信的 bundle,这会在你的主机上运行攻击者代码。应使用静态解析,或在沙箱中解析字符串。
- “变量名都没了,所以逻辑也没了。” 压缩和混淆会重命名并重塑代码,但不会删除代码。与经过剥离的原生二进制文件不同,完整程序仍然存在——你要做的是还原变换,而不是重建丢失的信息。
- “DevTools 是用来调试的,不是用来逆向的。” 设置 fetch 断点并挂钩属性,比阅读 bundle 更快地定位签名函数,还能免费获取实时输入和输出。
参考资料
reversing-react-native-apps— Hermes/RN 移动端 JS bundleunpacking-protected-binaries— 基于 VM / 虚拟化的混淆hunting-web-backdoors— 恶意植入的 Web JStesting-web-applications— 测试还原出的算法所调用的端点reviewing-cryptography— 还原客户端加密/签名函数后的后续工作