mcpField
R
reversing-obfuscated-javascript

reversing-obfuscated-javascript

github.com/trilwu开发17760 次安装12 周前更新
代码仓库

关于 reversing-obfuscated-javascript

面向安全研究者的 JavaScript 混淆代码分析技能,指导识别转换类型、恢复源码结构并定位运行时关键函数。涵盖 sourcemap、反混淆工具、AST 处理和浏览器调试。

主要功能

  1. 01识别打包、混淆与反调试层
  2. 02检查并恢复 sourcemap 源码
  3. 03使用 webcrack 等工具拆包和反混淆
  4. 04通过 Babel AST 编写转换
  5. 05借助 DevTools 定位运行时函数

适用场景

  1. 01分析网页或扩展中的压缩 JavaScript
  2. 02恢复请求签名或加密例程
  3. 03检查客户端算法与许可逻辑
  4. 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.map sourcemap,或 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 十六进制名称 + 一个大型字符串数组 + 旋转 IIFEobfuscator.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 bundle
  • unpacking-protected-binaries — 基于 VM / 虚拟化的混淆
  • hunting-web-backdoors — 恶意植入的 Web JS
  • testing-web-applications — 测试还原出的算法所调用的端点
  • reviewing-cryptography — 还原客户端加密/签名函数后的后续工作

评论

支持 Markdown