JavaScript逆向webpack
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;
那我们最终的逆向思路就转化为:
- 使用加载器加载A模块
- 构造请求对象t
- 调用全局的my函数得出加密参数analysis
综上所述webpack加载器及模块定位就成了我们整个逆向过程中的核心。
webpack加载器及模块定位
webpack加载器及模块的定位方法相对固定。
加载器定位
首先在上述模块A中第一行代码打上断点,然后刷新页面,模块是在页面刷新时加载的。当断点断住后,我们看调用堆栈,上一个栈即为加载器位置。我们把整段js代码拷贝下来。
加载器所在代码为一个自执行函数,大致分为两种类型,一种是多js文件加载模块,自执行函数中没有传入请求参数。
另一种类型是整体加载,模块执行通过自执行函数的请求参数传入。这里我们只介绍前者,后者相对简单。
模块定位
加载器只是用来加载模块的工具,我们需要实际获取到模块代码才能将该模块在本地加载。模块A我们不是已经定位到了吗,为什么要定位模块?因为模块A还依赖其他模块,其他模块还依赖其他其他的模块…我们需要把这些模块代码全部拷贝下来,那模块A才能正确加载,这是一个补环境的思想。定位模块大致分为以下几个步骤:
加载器断点
在浏览器的加载器代码加载模块的地方打上断点,并将程序运行到断点处,并且观察代码可以得出加载器存在一个m属性,其实保存了所有已加载的模块,即断点处的变量f。
本地代码加载模块A
我们修改加载器代码,将加载器通过全局变量导出,并且加上日志提示当前正在加载的模块。
本地执行代码加载模块A,根据报错日志我们可以得知当前本地环境中缺少的模块是什么。
那我们从哪里获取这个模块65165呢?上面第一步里的加载器断点就起到作用了,我们可以直接在浏览器调试工具的控制台中直接输入f[65165],即能获取到该模块,点击代码则能跳转到源代码处,我们一般将整个js都拷贝到本地。
重复以上步骤直到没有模块加载的报错。
补充缺少的环境
最后我们可能还需要补充一些缺少的浏览器环境。
逆向代码
逆向代码可以下载下来参考链接: JS逆向-webpack逆向-某麦