JS逆向实战四:某查查请求头逆向解密
声明:本文章中所有内容仅供学习交流使用,不用于其他任何目的,不提供完整代码,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关!
网站概要
采集网站:www.qcc.com
逆向任务:破解请求头参数(key和value)
其他知识点
1.参数拼接
在进行参数拼接的时候,一般有两种方式:urlencode
和手动构建
urlencode
遵循标准的 URL 编码规范(RFC 3986),而手动构建的版本通常只做简单字符串拼接。
针对该数据data = {'name': 'John Doe', 'age': 25, 'special': '@#$'}
进行处理,对比如下:
urlencode | 手动拼接 | |
---|---|---|
方式 | urlencode(data) | '&'.join(f"{k}={v}" for k, v in data.items()) |
结果 | ‘name=John%20Doe&age=25&special=%40%23%24’ | ‘name=John Doe&age=25&special=@#$’ |
空格编码 | urlencode 将空格编码为 %20 | 手动拼接可能保留空格或错误编码为 + (表单编码风格) |
特殊字符 | urlencode 会编码所有非安全字符(如 !@#$%^&*() 等) | 手动拼接可能遗漏部分字符的编码 |
参数值类型处理 | urlencode` 会自动将非字符串类型(如整数、布尔值)转换为字符串 | 手动拼接需显式转换类型(如示例中的 str(value) ) |
2.JS语法简化
var i = (0, o.default)(t, e.data)
等同于var i = o.default(t, e.data)
var i = (0, o.default)(t, e.data)
作用是调用模块o
的默认导出函数default
,并传入参数t
和e.data
,然后将返回值赋给变量i
。其核心目的是通过间接调用确保函数执行时的上下文(this
)与原模块解绑。(0, o.default)
中的逗号操作符会依次执行所有表达式,并返回最后一个表达式的值。这里返回的是o.default
,即模块o
的默认导出(通常是一个函数)。- 直接调用
o.default()
时,函数内的this
可能指向o
的上下文。而(0, o.default)
会先将o.default
提取为一个独立的函数引用,再通过(0, o.default)(t, e.data)
调用它。这种写法确保函数执行时的this
指向全局对象(非严格模式)或undefined
(严格模式),而非原模块o
。
网站分析
加密参数定位
1. 确定加密参数
进入企查查网站之后,先登录,在随机搜索一个公司名称,在搜索的时候观察接口响应发现有一个接口是根据输入的内容实时变化的,进一步发现其请求头存在一直变化的key和value值,因此对该对键值对进行分析。
PS:一般,我们通过XHR进行断点分析加密参数,这里就不一一分析,感兴趣的朋友可以自行分析
具体可参考本博客最后参考学习的第一篇链接
2.确定加密参数的生成位置以及对应文件
知道加密的参数之后,这里直接进行定位搜索。headers[
进行搜索,确定加密方式所在位置,并把对应的js文件在源面板中打开,然后开始进行加密分析。
加密参数分析
以“京东”的分支机构为例进行翻页分析,https://www.qcc.com/api/datalist/branchelist?isNewAgg=true&keyNo=b40ecf6c3e7e4e0414c501f6ce53dd37&pageIndex=2
-
进行断点分析,发现t和n与接口链接有关
-
进行参数
i
的分析,需要进一步到o.default
函数和a.default
函数
-
o.default
函数计算,需要传入一个参数e是去掉域名之后的接口链接,得到计算后的值n
该函数转换为对应的Python代码为:
def getCodes(e): codeList = { "0": "W", "1": "l", "2": "k", "3": "B", "4": "Q", "5": "g", "6": "f", "7": "i", "8": "i", "9": "r", "10": "v", "11": "6", "12": "A", "13": "K", "14": "N", "15": "k", "16": "4", "17": "L", "18": "1", "19": "8" } e = e.lower() t = e + e codes = '' for k in t: a = ord(k) % len(codeList) codes += codeList[f'{a}'] return codes
a.default
函数计算,其中传入两个参数e和n,相比在o.default
函数计算中传入的e,需要拼接一个{}
,然后再进入到a.default
里面,发现是一个HMAC加密算法
借助HMAC加密破解网站发现是hmac的Sha512加密算法,python实现代码如下
def getHmacSha512(key, data): # 获取十六进制表示的哈希值 hmac_obj = hmac.new(key.encode(), data.encode(), digestmod=hashlib.sha512).digest() return hmac_obj.hex()
之后在对所得的结果变成小数再截取[8:28]位即可获得i值,用同样的方法可以计算value的值,其中tid,可以通过在控制台输入window.tid
获得
arg1 = reqUrl.lower()
# 获得key的编码值
arg2 = getCodes(arg1)
# 通过HMAC算法计算加密后的key的编码值
key = getHmacSha512(arg2,arg1+'{}').lower()[8:28]
# 拼接用于计算value的字段
arg3 = arg1 + "pathString{}" + tid
# 获得value的编码值
arg4 = getCodes(arg1)
val = getHmacSha512(arg4, arg3)
最终结果比对,得到正确的key和value值
后续分析使用
后续只需要更换接口和参数接口,其中需要注意参数拼接的时候直接手动拼接而不是使用urlencode
否则无法得到正确结果。
参考教程:
JS逆向入门案例-某查查网请求头-03_抖查查 逆向-CSDN博客该博客通过Python代码的方式进行解密
最新企查查headers动态加密逆向算法 - 亦辰博客该博客通过JS代码的方式进行解密