⭐⭐⭐彻底攻克JavaScript逆向中的webpack

254 阅读4分钟

webpack逆向分析

webpack是一个现代 JavaScript 应用程序的静态模块打包器(module bundler),负责分析翻译压缩打包代码。我们js逆向过程中会经常遇到,这里借助某麦数据的例子,介绍下webpack逆向的通用方法。

接口分析

首先我们分析接口,不难得出请求参数中analysis是我们需要破解的核心加密参数

​​​​在这里插入图片描述

定位加密位置

加密位置定位不是本文重点,可以通过xhr断点等多种手段定位到加密位置如下图所示。

在这里插入图片描述 分析上下文不难得出,该段代码处于webpack的其中一个模块中,这里先称之为A模块。函数的参数t为请求相关的对象,函数中的e即我们需要的加密参数analysis。有很多人在这里会想办法将这段代码解混淆,我这边的思路是在该A模块中自定义一个新函数my,并全局导出,该函数直接复制这段加密代码,但是最终的返回值修改为我们需要的e。

function my(t) {
  var n;
  f ||
    $ != s ||
    ((n = (0, i[Zt])(m)),
    (s = c[x][k][Rt] = -(0, i[Zt])(l) || +new R[K]() - r2 * n));
  var e,
    r = +new R[K]() - (s || H) - 1661224081041,
    a = [];
  return (
    void 0 === t[Ot] && (t[Ot] = {}),
    R[W][o7](t[Ot])[M](function (n) {
      if (n == v) return !B;
      t[Ot][_2](n) && a[b](t[Ot][n]);
    }),
    (a = a[jt]()[I5](N)),
    (a = (0, i[Jt])(a)),
    (a = (a += p + t[qt][T](t[Tt], N)) + (p + r) + (p + 3)),
    (e = (0, i[Jt])((0, i[Qt])(a, d)))
  );
}
window.my = my;

那我们最终的逆向思路就转化为:

  1. 使用加载器加载A模块
  2. 构造请求对象t
  3. 调用全局的my函数得出加密参数analysis

综上所述webpack加载器及模块定位就成了我们整个逆向过程中的核心。

webpack加载器及模块定位

webpack加载器及模块的定位方法相对固定。

加载器定位

首先在上述模块A中第一行代码打上断点,然后刷新页面,模块是在页面刷新时加载的。当断点断住后,我们看调用堆栈,上一个栈即为加载器位置。我们把整段js代码拷贝下来。

在这里插入图片描述 加载器所在代码为一个自执行函数,大致分为两种类型,一种是多js文件加载模块,自执行函数中没有传入请求参数。

在这里插入图片描述 另一种类型是整体加载,模块执行通过自执行函数的请求参数传入。这里我们只介绍前者,后者相对简单。

模块定位

加载器只是用来加载模块的工具,我们需要实际获取到模块代码才能将该模块在本地加载。模块A我们不是已经定位到了吗,为什么要定位模块?因为模块A还依赖其他模块,其他模块还依赖其他其他的模块...我们需要把这些模块代码全部拷贝下来,那模块A才能正确加载,这是一个补环境的思想。定位模块大致分为以下几个步骤:

加载器断点

在浏览器的加载器代码加载模块的地方打上断点,并将程序运行到断点处,并且观察代码可以得出加载器存在一个m属性,其实保存了所有已加载的模块,即断点处的变量f。

在这里插入图片描述

本地代码加载模块A

我们修改加载器代码,将加载器通过全局变量导出,并且加上日志提示当前正在加载的模块。

在这里插入图片描述 本地执行代码加载模块A,根据报错日志我们可以得知当前本地环境中缺少的模块是什么。

在这里插入图片描述 那我们从哪里获取这个模块65165呢?上面第一步里的加载器断点就起到作用了,我们可以直接在浏览器调试工具的控制台中直接输入f[65165],即能获取到该模块,点击代码则能跳转到源代码处,我们一般将整个js都拷贝到本地。

在这里插入图片描述 重复以上步骤直到没有模块加载的报错。

补充缺少的环境

最后我们可能还需要补充一些缺少的浏览器环境。

逆向代码

逆向代码可以下载下来参考链接: JS逆向-webpack逆向-某麦