mouzhunwang webpack 逆向分析
PS: 本文仅供学习参考、仅供学习参考、仅供学习参考,不得用于商业用途。
请求分析
本次目标站点
aHR0cHM6Ly93d3cua2Fuemh1bi5jb20vZmlybS93YWdlLzFuVl8ydGt+Lmh0bWw/a2E9Y29tLXNhbGFyeS1tb2R1bGUtZXhwb3Nl
经过分析可以明显看到该请求的参数以及响应都是加密过的。
JS 分析
全局搜索大法,搜索关键词 kiv,最终仅有一个文件含有该关键词,进入该文件,再次搜索 kiv,发现共出现15次,好像有点多,继续往下看
在第二次出现 kiv 的地方发现了 400 和 200,这俩怎么看怎么像响应状态码,但是这里仅有参数 kiv 没有 参数 b,指定不是发请求的地方,继续往下看
经过多次寻找与测试,最终在1万3千来行附近找到了构造请求参数的地方,同样也是发请求的地方
为了方便调试,如下图所示打上一个条件断点
这个站点直接刷新是断不上断点的,需要点击其他板块,再点击需要分析的板块才能成功断上,如下图
参数 b 和 kiv
通过上图我们可以看到参数 kiv 就是 o,参数 b 就是 t,接下来我们挨个分析。
将关键代码扣下来,精简一下
可以看到 t 的生成需要 o,而 o 是由 P._A() 生成的。在控制台输出测试一下,发现每次执行的结果都不一样,P._A 这个方法很好扣,但是我们需要的不止这一点,因为不管是 o 的生成还是 t 的生成都需要 P,那我们往上找找 P 是怎么来的
P 是由 n(60591) 生成的,在这个位置打个断点刷新一下,跟进去
发现进入到了另一个 js 文件,这个文件仅有一百来行,加载器就在这,将其全部扣下里放进编辑器里
将之前第一次分析的 js 文件整个扣下来,放到编辑器另一个文件中,折叠一下代码,有11万行
掐头去尾将大括号里的所有模块都扣下来,放到加载器中,如下图,一定不要忘了大括号
接下来我们需要修改下这个自执行函数,因为我们需要在自执行函数外部调用,所以需要声明一个全局变量 get_P,并且自执行函数里的一些方法也都属于 t,所以在函数最后新增一行,在开头添加一个参数 r,并将在函数中声明的一些变量修改,如下图
运行一下,报错了 self is not defined,定位到错误的位置,将 self 修改为 window,并在最开头声明一个 window
再次运行,报错 P is not defined,利用全局变量 get_P 去声明一下 P
再次运行,打印参数 o,可以正常输出了。接下来分析 t,参数 t 还需要一个参数 n,回到控制台重新断点
执行到合适的位置,在控制台查看,发现 encCompanyId 的值有点眼熟,然后你抬头看了眼链接,😯哦!原来在链接里
然后发现代码少扣了一行,尴尬😅
将这行代码扣下来精简一下,然后打印,正常输出
通过 Postman 模拟一下请求,响应状态码 200 且有响应内容
响应加密
还记得上面在搜索 kiv 时,疑似状态码的地方吗!在这打上断点,成功断上
经过调试,发现在执行到 JSON.parse(t) 的时候响应明文就出来了,并且这边也有一个 P
将关键代码扣下来精简一下,上图中的 e.data 就是加密的响应,kiv 和上面生成的一致
精简代码
跟到上面这一步,修改一下就已经可以用 Python 调用了,但是这11万行实在是太多了,不优雅
在代码开头声明两个全局变量,并在加载器新增如下图代码
在代码尾部加上一个 debugger,并将加解密代码放开,保证都会运行
执行调试,并将控制台输出的内容清空,输入 codes 然后回车,然后将输出的内容全部复制下来,替换到自执行函数中
最后一大堆模块就剩两个了,再次运行,结果正常。11万行就剩下5千来行了,nice!
写在最后
至此整个加密分析与 webpack 加密代码扣取结束,将加解密逻辑封装一下就可以使用了,你要是想更优雅,可以考虑将整体逻辑使用 Python 或其他语言复现。如果觉得这篇文章有不足之处,欢迎您的留言。