文章目录
- 1. 写在前面
- 2. 接口分析
- 3. 断点分析
- 4. 扣代码补环境
- 5. 数据解密
【🏠作者主页】:吴秋霖
【💼作者介绍】:擅长爬虫与JS加密逆向分析!Python领域优质创作者、CSDN博客专家、阿里云博客专家、华为云享专家。一路走来长期坚守并致力于Python与爬虫领域研究与开发工作!
【🌟作者推荐】:对爬虫领域以及JS逆向分析感兴趣的朋友可以关注《爬虫JS逆向实战》《深耕爬虫领域》
未来作者会持续更新所用到、学到、看到的技术知识!包括但不限于:各类验证码突防、爬虫APP与JS逆向分析、RPA自动化、分布式爬虫、Python领域等相关文章
作者声明:文章仅供学习交流与参考!严禁用于任何商业与非法用途!否则由此产生的一切后果均与作者无关!如有侵权,请联系作者本人进行删除!
1. 写在前面
在去年的时候,作者有分析过关于巨量的msToken、X-Bogus、_signature三个参数的加密,本次有读者找到作者寻求解决最新的加密算法,算法相比于之前有细微的变化,参数加密的话重新分析扣JS出来补个环境能搞定,数据解密需要分析讲解一下!
2. 接口分析
打开网站,我这里的话也是按照上面读者的阐述,主要去分析了两个接口,这里我们直接看get_multi_keyword_hot_trend就行,如下所示:
可以看到有三个参数,我们需要重点关注分析的是X-Bogus、_signature,msToken参数的话也许是它会是一个埋点校验的参数,可能会在大量的请求中被检测,这里的话我们直接先固值就好或者用Cookie内的测试均可!当然动态的也可以自己使用算法去生成
msToken参数的话在签名加密的时候需要参与加密,所以暂时是不能不要的!另外我们可以看到巨量目前的话,接口响应数据以密文的方式返回,如下所示:
所以我们需要正常的抓取数据,不仅需要解决加密参数的问题!同样需要解密接口密文数据
3. 断点分析
根据之前的分析,以及对某系X-bogus的早期版本分析,直接看调用栈不难看出,基本上参数的核心加密逻辑就在这个JS内,采用补环境的话就比较简单了!如下所示:
我们先来分析X-Bogus参数,进去开始断点跟栈分析,可以看到_0x4d83e6就是生成这个参数的方法,它接受两个参数,_0x2a5467是msToken,_0xbe4f85则是请求参数,直接在控制台查看一下,如下所示:
找到了X-Bogus参数生成的方法,现在我们继续找_signature是如何生成的,跟栈来到_0x2657c0,接受三个参数!如下所示:
可以在控制打印一下参数,如下所示:
4. 扣代码补环境
直接把webmssdk.js文件全部扣出来,拿到本地开始进行调试,如下所示:
缺什么补什么,完整的环境头如下所示,href地址自己把接口的地址放上即可,如下所示:
window = global;
document = {}
addEventListener = function (){}
document.addEventListener = addEventListener
canvas = {}
createElement = function (){
return canvas
}
document.createElement = createElement
location = {}
location.href = '' # 自行获取
location.protocol = 'https:'
navigator = {}
navigator.userAgent = '' # 自行获取
document.referrer = ""
setInterval = function (){}
setTimeout = function (){}
现在我们接下来需要做的就是,封装加密方法,以便调用!将生成X-Bogus参数的_0x4d83e6方法跟生成_signature的加密方法_0x2657c0全部导出,实现如下:
// 确保get_xbogus跟get_sign以经导出加密方法!!!
function get_sign_params(msToken, api, params) {
const _params = JSON.stringify(params);
const xbogus = get_xbogus(`msToken=${msToken}`, _params);
const url = `${api}msToken=${msToken}&X-Bogus=${xbogus}`;
const _signature = get_sign({ body: params, url }, undefined, 'forreal');
return {
msToken,
'X-Bogus': xbogus,
_signature
};
}
上面注释请注意,加密函数已经导出使用!我们测试一下加密算法效果,如下所示:
我们这里直接先写一个Demo,测试一下算法生成的参数是否可以正常拿到数据,如下所示:
很好,证明算法是没有问题的。正常拿到了接口的密文数据,接下来我们就需要对接口返回的加密数据进行解密!
5. 数据解密
关于接口响应数据加密,作者的文章有过很多案例了!如果去分析定位!这里就不再重复的去西说,直接先Hook一下,Hook到之后可以再看跟栈去调试分析,如下所示:
Hook到解密位置,直接跟栈,断点分析+插桩+追日志…各种分析手法结合使用,直接把气势先拉满再说!找到解密方式如下所示:
如上!既然现在知道了是AES加密,那么就需要获取到密钥跟初始向量!密钥如下所示:
初始向量iv,如下所示:
最后根据插桩日志跟断点分析,来梳理一下明文数据的整个加密流程,如下所示:
1、UTF-8编码
2、AES加密
3、Base64编码
从而根据上面的加密流程反推解密算法,编写解密函数!算法实现如下所示:
import base64
from Crypto.Cipher import AES
# 数据解密算法
def decrypt(ciphertext):
key = "SjXbYTJb7zXoUToSicUL3A=="
iv = "OekMLjghRg8vlX/PemLc+Q=="
decoded_key = base64.b64decode(key)
decoded_iv = base64.b64decode(iv)
cipher = AES.new(decoded_key, AES.MODE_CBC, decoded_iv)
decoded_ciphertext = base64.b64decode(ciphertext)
plaintext = cipher.decrypt(decoded_ciphertext)
padding_length = plaintext[-1]
plaintext = plaintext[:-padding_length]
plaintext = plaintext.decode('utf-8')
return plaintext
编写程序来调用解密算法测试一下密文数据解密后的效果,如下所示:
非常好!最终我们编写一个完整的抓取Demo,来看看抓取效果,如下所示:
import re
import json
import execjs
import requests
from loguru import logger
headers = {} # 自行获取
cookies = {} # 自行获取
url = "https://trendinsight.oceanengine.com/api/v2/index/get_multi_keyword_hot_trend"
data = {
"keyword_list": [
"小米su7"
],
"start_date": "20240501",
"end_date": "20240510",
"app_name": "toutiao",
"region": []
}
with open('./juliang.js', 'r') as f:
js_code = f.read()
ctx = execjs.compile(js_code)
params_dict = ctx.call('get_param', '', url, data)
x_bogus = params_dict['X-Bogus']
_signature = params_dict['_signature']
params = {
"msToken": cookies['msToken'],
"X-Bogus": x_bogus,
"_signature":_signature
}
data = json.dumps(data, separators=(',', ':'))
response = requests.post(url, headers=headers, cookies=cookies, params=params, data=data).json()
result = decrypt(response['data'])
logger.info(f'解密数据: {result}')