巨量算数返回值解密思路

流氓凡 技术分享 2021-09-05 1.22 W 10

前景回顾

距离上一次算法更新已经有快两个月了,上次的解密很简单带大家回顾下吧

加密算法定位方法就不说了,因为已经更新了没有什么意义了,直接上加密核心截图

image.png

但是逆向后的解密方案利用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=微信小程序

image.png

可以看到数据是服务器返回的而且经过加密

分析原理

浏览器客户端向服务器发起请求,服务器返回响应。最终数据是要渲染到网页端的,但是我们看到的并不是明文的数据,说明解密工作是在浏览器端完成的。

image.png

定位加密位置

JS逆向最为关键的是快速定位到加密的位置,通常定位加密位置有以下几个方法:

    1. 全局搜索关键字

    2. XHR断点

    3. DOM断点

    4. 事件断点

一般清空下,我们搜索的关键字是返回的json数据中的key,一般的key都会出现的源代码中但是我们不能这么搜索,用脚趾头想想数据肯定很多.

那该如何定位到加密位置呢?既然数据肯定是需要解密的,我们可以尝试通过json.parse| decrypt此类的关键字去检索。


为什么是这些关键字呢,这就涉及到前后端的数据交互格式了,目前前后端主流的数据交互格式是json字符串。也就是说,后端返回给我们的数据其实是一个json字符串。如果js想操作的话,就需要先转化为js对象

这里通过decrypt这个关键字可以定位到代码的加密位置

image.png

通过打断点进行调试,最终定位到的加密文件是2221.68c6a8a4.js

image.png

断点断下来了,说明代码执行是经过这里的。但这里并没有加密数据,所以要跟进去函数的调用地方,同时查看函数的堆栈信息,这两步要结合着来。

image.png

跟进去之后,会发现明显的加密字眼

image.png

熟悉吗?aes-128-cfb,但是还是没有看到服务器返回的加密字符串。

这里说一下,为什么我们要找到加密的字符串,以免新手疑惑。一般情况下,加密数据都是经过解密函数解密返回明文数据的。

经过打断点调试,最终定位到加密函数的位置

image.png

到这里,我们解决了第一步也是最重要的一步,定位到代码的加密位置。

接下来分两步走

    1. 直接确定本次加密的key和i 带入解密尝试赌一下是不是这个算法是写死的 (这个结果是写死的,所以直接想要结果的童鞋可以直接自己调试了,不必往下看了.)

    2. 继续分析加密函数, 想学习下的童鞋可以继续往下看看

加密函数分析

接下来,我们需要分析加密函数,它内部调用了哪些函数,函数又传递了哪些参数。这里把代码扣下来,一起分析一下。

image.png

这个解密函数是绑定在a对象身上的,如果想查看函数的参数是什么,只需要把鼠标移动到变量上。

e: 是服务器返回的密文数据

t: "base64"

r: "utf8"

如何确定解密函数的返回值,只需要在函数return的时候打一个断点。

image.png

Webpack代码分析

按照常规的思路,只需要把解密函数所涉及到的函数全部扣取出来即可。但是你会发现,函数的调用链条真的太长了,如果真的一个一个去去扣取的话,会把自己累死。

下面介绍一种简单webpack逆向思路

    1. 找到模块解析函数

    2. 直接调用模块

在外层对象打上断点,ctrl + r 刷新整个网页,可以看到代码断下来了。为什么要重新刷新整个网页呢?因为模块解析函数(加载器)只加载一次,需要重新刷新整个网页才会断下来。

image.png

a函数就是模块解析函数

image.png

这样就好办了,先在浏览器运行扣取的JS代码

image.png

我们该如何获取到a函数呢?这里可以直接把a函数直接绑定到全局对象window上

image.png

这样就可以通过window.A调用模块解析函数了。

运行一下JS代码,在控制台打印输出window.A,可以看到正常打印。

image.png

下面只需要把加密的JS文件扣取出来

image.png

打印window.__LOADABLE_LOADED_CHUNKS__

image.png

拿到所有函数之后,就可以调用解密函数了

image.png

image.png

代码报错,说明还缺少模块,如何解决呢?可以通过插桩调试定位缺少的模块

image.png

image.png

可以看到,缺少的是39355,全局搜索39355

image.png

再次调用加密函数模块,打印window.A(71027),可以看到没有报错啦!

image.png

再次调用加密函数

image.png

这里报错提示是this指向的问题,我们需要搞清楚出this对象是谁。同样还是打断点调试

image.png

重新下断点,追溯函数栈信息

image.png

image.png

搞清楚this指向之后,那就好办了,我们采用函数改写的方式,完成调用。

image.png

控制台调用解密函数,输出结果。

image.png

总算把数据解密出来了,但只是万里长征的第一步,因为还需要在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端运行代码,这部分基本操作就不上了

image.png

写在最后

关于接口请求的signature参数解决思路可以尝试使用无头浏览器. 自己逆向后的部分接口无法调取哈(作为过来人的一个忠告吧)

评论

精彩评论
  • 2021-12-22 16:53:31

    大佬,我也是,是为什么呢,会出现有部分接口逆向得到的签名访问拿不到数据呢

    • 2022-02-11 13:05:18

      @aaa Heder头中 计算签名传递的User-Agent和爬接口请求的User-Agent需要一致才行

  • 2021-10-13 17:04:35

    请教一下,最后一步this怎么弄的啊

  • 2021-09-27 20:26:54

    老哥,巨量算数这个爬虫,爬下来吗?