巨量算数返回值解密思路
前景回顾
距离上一次算法更新已经有快两个月了,上次的解密很简单带大家回顾下吧
加密算法定位方法就不说了,因为已经更新了没有什么意义了,直接上加密核心截图
但是逆向后的解密方案利用NodeJs的Crypto-js直接解密,示例demo
var CryptoJS = require("crypto-js") // 解密函数 function decrypt(S, E) { var wordArray = CryptoJS.enc.Utf8.parse(S); var A = CryptoJS.enc.Base64.stringify(wordArray).repeat(3) , M = A.padEnd(40, A) , R = M.slice(0, 16) , D = M.slice(12, 28); const crypto = require('crypto'); let src = ''; const cipher = crypto.createDecipheriv('aes-128-cfb', R, D); src += cipher.update(E, 'base64', 'utf8'); src += cipher.final('utf8'); return src; } var dec = decrypt('get_multi_keyword_hot_trend', "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"); console.log(dec);
新版算法分析
首先我们确定逆向网址: https://trendinsight.oceanengine.com/arithmetic-index/analysis?keyword=微信小程序
可以看到数据是服务器返回的而且经过加密
分析原理
浏览器客户端向服务器发起请求,服务器返回响应。最终数据是要渲染到网页端的,但是我们看到的并不是明文的数据,说明解密工作是在浏览器端完成的。
定位加密位置
JS逆向最为关键的是快速定位到加密的位置,通常定位加密位置有以下几个方法:
1. 全局搜索关键字
2. XHR断点
3. DOM断点
4. 事件断点
一般清空下,我们搜索的关键字是返回的json数据中的key,一般的key都会出现的源代码中但是我们不能这么搜索,用脚趾头想想数据肯定很多.
那该如何定位到加密位置呢?既然数据肯定是需要解密的,我们可以尝试通过json.parse| decrypt此类的关键字去检索。
为什么是这些关键字呢,这就涉及到前后端的数据交互格式了,目前前后端主流的数据交互格式是json字符串。也就是说,后端返回给我们的数据其实是一个json字符串。如果js想操作的话,就需要先转化为js对象
这里通过decrypt这个关键字可以定位到代码的加密位置
通过打断点进行调试,最终定位到的加密文件是2221.68c6a8a4.js
断点断下来了,说明代码执行是经过这里的。但这里并没有加密数据,所以要跟进去函数的调用地方,同时查看函数的堆栈信息,这两步要结合着来。
跟进去之后,会发现明显的加密字眼
熟悉吗?aes-128-cfb,但是还是没有看到服务器返回的加密字符串。
这里说一下,为什么我们要找到加密的字符串,以免新手疑惑。一般情况下,加密数据都是经过解密函数解密返回明文数据的。
经过打断点调试,最终定位到加密函数的位置
到这里,我们解决了第一步也是最重要的一步,定位到代码的加密位置。
接下来分两步走
1. 直接确定本次加密的key和i 带入解密尝试赌一下是不是这个算法是写死的 (这个结果是写死的,所以直接想要结果的童鞋可以直接自己调试了,不必往下看了.)
2. 继续分析加密函数, 想学习下的童鞋可以继续往下看看
加密函数分析
接下来,我们需要分析加密函数,它内部调用了哪些函数,函数又传递了哪些参数。这里把代码扣下来,一起分析一下。
这个解密函数是绑定在a对象身上的,如果想查看函数的参数是什么,只需要把鼠标移动到变量上。
e: 是服务器返回的密文数据
t: "base64"
r: "utf8"
如何确定解密函数的返回值,只需要在函数return的时候打一个断点。
Webpack代码分析
按照常规的思路,只需要把解密函数所涉及到的函数全部扣取出来即可。但是你会发现,函数的调用链条真的太长了,如果真的一个一个去去扣取的话,会把自己累死。
下面介绍一种简单webpack逆向思路
1. 找到模块解析函数
2. 直接调用模块
在外层对象打上断点,ctrl + r 刷新整个网页,可以看到代码断下来了。为什么要重新刷新整个网页呢?因为模块解析函数(加载器)只加载一次,需要重新刷新整个网页才会断下来。
a函数就是模块解析函数
这样就好办了,先在浏览器运行扣取的JS代码
我们该如何获取到a函数呢?这里可以直接把a函数直接绑定到全局对象window上
这样就可以通过window.A调用模块解析函数了。
运行一下JS代码,在控制台打印输出window.A,可以看到正常打印。
下面只需要把加密的JS文件扣取出来
打印window.__LOADABLE_LOADED_CHUNKS__
拿到所有函数之后,就可以调用解密函数了
代码报错,说明还缺少模块,如何解决呢?可以通过插桩调试定位缺少的模块
可以看到,缺少的是39355,全局搜索39355
再次调用加密函数模块,打印window.A(71027),可以看到没有报错啦!
再次调用加密函数
这里报错提示是this指向的问题,我们需要搞清楚出this对象是谁。同样还是打断点调试
重新下断点,追溯函数栈信息
搞清楚this指向之后,那就好办了,我们采用函数改写的方式,完成调用。
控制台调用解密函数,输出结果。
总算把数据解密出来了,但只是万里长征的第一步,因为还需要在node端完成调用,在浏览器可以运行并不代表在node端也能运行。复制代码,新建一个js文件。
补浏览器环境Demo
window = { addEventListener: function(){}, navigator: { userAgent: "11" }, screen: { width: 100, height: 200 }, setTimeout: function(){} } window.location = { hash: "", host: "trendinsight.oceanengine.com", hostname: "trendinsight.oceanengine.com", href: "https://trendinsight.oceanengine.com/arithmetic-index/analysis?keyword=&tab=correlation", origin: "https://trendinsight.oceanengine.com", pathname: "/arithmetic-index/analysis", port: "", protocol: "https:" } location = { pathname: "/arithmetic-index/analysis" } Element = { prototype: { addEventListener: function(){} } } document = { createElement: function(ele){ return ele.style = "" }, getElementsByTagName: function(){ return '' }, addEventListener: function(){}, getElementById: function(){}, referrer: "" } Event = {} UIEvent = {} CustomEvent = {} Node = { prototype: "undefined" } Object.prototype = null navigator = "" IntersectionObserver = function(){} XMLHttpRequest = function(){}
经过删减代码和补浏览器环境大法,最终成功在node端运行代码,这部分基本操作就不上了
写在最后
关于接口请求的signature参数解决思路可以尝试使用无头浏览器. 自己逆向后的部分接口无法调取哈(作为过来人的一个忠告吧)
评论
aaa
回复大佬,我也是,是为什么呢,会出现有部分接口逆向得到的签名访问拿不到数据呢
流氓凡
回复@aaa Heder头中 计算签名传递的User-Agent和爬接口请求的User-Agent需要一致才行
aaa
回复signture 参数 求大佬指导
流氓凡
回复@aaa 最好使用 RPC做
白白嫩嫩
回复最新版加密值已经修改
菜鸡
回复@白白嫩嫩 大佬 搞定了吗
zhengsq
回复请教一下,最后一步this怎么弄的啊
班克西
回复老哥,方便加个微信或者QQ请教一下吗?
流氓凡
回复@班克西 qq:617498836
班克西
回复老哥,巨量算数这个爬虫,爬下来吗?