赞
踩
有的网站请求参数或者URL是明文的,但是有些是加密后的。接下来以易车网为例,巩固一下逆向思路。
使用接口获取汽车的参数配置,但是请求参数无法直接阅读,点击解码即可。
请求头里还有一下加密参数
估计重点就是X-Sign,其他的可能用处不大。
其实可以试试直接请求接口,看是否有返回值:
// https://mapi.yiche.com/web_api/car_model_api/api/v1/car/config_new_param?cid=508¶m=%7B%22cityId%22%3A%22201%22%2C%22carId%22%3A%22166210%22%7D
{
"message": "公共参数缺失",
"status": "11036"
}
所以重点来了,可能就是这个X-Sign起决定性因素。
只有两条记录,全部打上断点,进去哪个哪个就是。
看输出的值,有点像。
继续分析这句代码:
"headers" == e.encryptType && (n["x-sign"] = u(e, t));
执行规则:
总结:假前真后
所以有效的的值一定是u(e, t)
。
接下来分别看一下e和t这两个参数:
// t
{
"cid": "508",
"ver": "v10.80.0",
"timestamp": 1700192890484,
"gradeParam": {},
"uid": "",
"headerEncryptKeys": [
{
"name": "pc",
"value": "19DDD1FBDFF065D3A4DA777D2D7A81EC",
"cid": "508"
},
{
"name": "phone",
"value": "DB2560A6EBC65F37A0484295CD4EDD25",
"cid": "601"
},
{
"name": "h5",
"value": "745DFB2027E8418384A1F2EF1B54C9F5",
"cid": "601"
},
{
"name": "business_applet",
"value": "64A1071F6C3C3CC68DABBF5A90669C0A",
"cid": "601"
},
{
"name": "wechat",
"value": "AF23B0A6EBC65F37A0484395CE4EDD2K",
"cid": "601"
},
{
"name": "tencent",
"value": "1615A9BDB0374D16AE9EBB3BBEE5353C",
"cid": "750"
}
],
"paramsKey": "f48aa2d0-31e0-42a6-a7a0-64ba148262f0"
}
然后是e:
这不太对啊,接口地址不是这个,那就继续执行,当URL是config_new_param
再追踪。
果然有执行了几次才拿到了我们想要的结果。
也就是说如果开始找出了URL,那么后面的一切都是南辕北辙。
接下来就跳转到了s函数:
至此,我们找到了X-Sign的位置,之后使用JS来补环境就可以了吗?不要着急,执行一下没准能得到意想不到的结果。
好像恰巧获取的cid和param的值,而X-Sign就是加密后的密文。
刚才我们获取了cid=508¶m={"cityId":"201","carId":"166210"}19DDD1FBDFF065D3A4DA777D2D7A81EC1700201316661
这个值,把这个值传给h函数,并把相同作用域的函数全部复制过来就可以了。很顺利,一次就跑通了。
接下来思考一下如何获取这个参数变量。我们回到刚才的s函数,可以看到这个参数是由n提供的。
可以看到就是把n参数进行一个MD5的处理,这时候我们可以猜测一下是不是普通的MD5,可以用python或者js代码试试:
import hashlib
content = 'cid=508¶m={"cityId":"201","carId":"166210"}19DDD1FBDFF065D3A4DA777D2D7A81EC1700211170720'
md5_hash = hashlib.md5(content.encode()).hexdigest()
print(md5_hash)
# 输出 166cc7dd317a737794ecaa2bd795f37d
可以看到和结果中是一致的。这就简单很多了,大部分逻辑就分析完了。
根据前面的分析,可以确定以下参数是需要传值的:
{"cityId":"201","carId":"166210"}
其他值可以是固定或者处理过的。
全部代码如下,使用python将字符串进行MD5处理,然后发出请求。需要注意以下几个问题:
以下代码是请求一种车型的方式,如果是批量请求,提前准备好多个ID就可以了。
import json
import time
import hashlib
import requests
def start(city_data):
headers = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/119.0",
"Content-Type": "application/json;charset=UTF-8",
"X-Platform": "pc",
}
ts = str(int(time.time() * 1000))
new_data = json.dumps(city_data, separators=(',', ':'))
s1 = f'cid=508¶m={new_data}19DDD1FBDFF065D3A4DA777D2D7A81EC' + ts
print(s1)
md5_hash = hashlib.md5(s1.encode()).hexdigest()
print(md5_hash)
headers['Referer'] = 'https://car.yiche.com/biyadifsuv/m166210/peizhi/'
headers['X-Sign'] = md5_hash
headers['X-Timestamp'] = ts
headers['X-City-Id'] = "201"
headers['Cid'] = "508"
params = {
"cid": "508",
"param": json.dumps(city_data, separators=(',', ':'))
}
print(params)
# 注意要使用separators,否则会出现签名验证失败的问题,使用后间隔更小,符合网站中JS的要求
# 'cid=508¶m={"cityId":"201","carId":"166210"}19DDD1FBDFF065D3A4DA777D2D7A81EC1700211170720',
# 否则会出现后面的两种情况
# {'cid': '508', 'param': '{"cityId": "201", "carId": "166210"}'}
# {'cid': '508', 'param': '{"cityId":"201","carId":"166210"}'}
res = requests.get(
'https://mapi.yiche.com/web_api/car_model_api/api/v1/car/config_new_param', params=params,
headers=headers,
)
print(res.json()['message'])
if __name__ == '__main__':
city_data = {
"cityId": "201", "carId": "166210"
}
start(city_data)
返回结果:
今天分析JS逻辑的时候在md5这一块卡了很久,主要原因如下;
在HTTP协议中,请求头是不区分大小写的。这意味着,根据HTTP规范,请求头的字段名不应该被视为大小写敏感的。例如,
Content-Type
和content-type
在HTTP的角度来看是相同的。然而,实际上在某些情况下,服务器和浏览器的处理可能会导致大小写的差异。一些服务器可能会将请求头字段名视为大小写敏感,而另一些则可能不敏感。
此外,浏览器和其他HTTP客户端有时会以不同的方式处理请求头。有些浏览器可能会按照规范的方式处理,而另一些可能会将请求头字段名规范化为特定的形式。
为了确保在不同浏览器和服务器之间具有一致的行为,最好遵循HTTP规范,将请求头字段名视为不区分大小写。在编写代码时,最好使用规范的大小写形式。
因此,还是需要经验,多动手多动脑。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。