JS逆向之x宝h5视频sign逆向分析
篇幅有限
完整内容及源码关注公众号:ReverseCode,发送 冲
需求
最近需要抓取一些淘宝商品的首图视频,比如https://item.taobao.com/item.htm?spm=a230r.1.14.31.7ebfcec2qmczgd&id=641116554739&ns=1&abbucket=2#detail,该页面首图视频页面元素是blob协议加密,该协议返回大多是m3u8格式的视频,并被切分为多个ts格式的小段视频集合。
image-20210425195135891分析
通过chrome抓包果然找到了m3u8视频请求,第一个请求返回ts文件列表,紧接着发起视频请求返回ts视频数据。
image-20210425195624728# EXTM3U:.m3u8文件的格式定义
# EXT-X-KEY: 密钥的信息
# METHOD: 加密的方法,这里采用的是AES-128的加密方式
# URI: 密钥的地址,需要获取访问得到密钥的信息
# IV: 偏移量,AES加密的方法,通过这个密钥就可以解密,获取正确的视频信息
数据来源找到了,那么紧跟着就是找到这些链接的组成字段,如首个链接https://tbm-auth.alicdn.com/e99361edd833010b/1Ptetzs7wLumqr8DVXj/IZAAx7ivPbWWLLDYpm0_275076925941___hd.m3u8?auth_key=1619353994-0-0-7eac2e2d00d26717d7aad9746575f99f
中大部分url参数都是加密串,通过搜索其中的1Ptetzs7wLumqr8DVXj
,找到了多条符合条件的请求。
第一条请求中返回的数据中有两个参数的video_url,分别是hlsResources和mp4Resources,返回了m3u8和mp4格式,好家伙,这样省去了合并m3u8个流程,直接拿mp4格式的视频即可。
逆向
拿到返回video_url的请求的参数,通过逐条过滤参数发现,最终生效的参数只有四个,分别是appKey,t,sign,data,每次请求都有失效时间。
image-20210425203715490其中appKey固定为12574478,t为精确到毫秒的时间戳,sign是今天的逆向主角参数,data动态内容为'{"videoId": "%s","from":"detail"}' % "301079547561"
,其中301079547561
作为videoId在页面请求时直接返回在页面js中。
sign
无痕浏览器清空页面缓存,搜索sign,从众多页面中找到可能出现的位置,sign就是j,而j = h(d.token + "&" + i + "&" + g + "&" + c.data)
,其中d.token是加密字符串,i为时间戳,g为固定值12574478,c.data为{"videoId":"275076925941","from":"detail"}
在控制台中调用h函数返回32位字符串,猜测是md5加密,就不扣h函数的js了。
image-20210425210755226接下来就是分析这些参数中唯一变的参数d.token的来源。
d.token
第一次断点时d.token为undefined。
放开断点后搜索d.token的值0027f0b395e6356158d06d22da238855
,第一次出现在了返回video_url的请求返回时set-cookie中,作为Response Cookie返回了两个cookie,一个是_m_h5_tk,一个是_m_h5_tk_enc,_分割的前面一段就是d.token的值。
第二次进入断点时d.token=0027f0b395e6356158d06d22da238855
,放开断点后搜索0027f0b395e6356158d06d22da238855
出现在了同一个请求的Request Cookie中。
逻辑梳理
大概思路清晰了,对同一个请求多次访问,第一次返回cookie作为第二次请求的cookie,cookie中的_m_h5_tk_enc通过_分割的前半段字符串作为d.token,根据d.token + "&" + i + "&" + g + "&" + c.data
进行md5得到sign,请求时加上两个cookie,完成video_url的请求,从而实现淘宝商品首图的视频抓取。
爬虫
APPKEY = '12574478'
DATA = '{"videoId": "%s","from":"detail"}' % "301079547561"
URL = 'https://h5api.m.taobao.com/h5/mtop.taobao.cloudvideo.video.queryforh5/1.0/'
params = {'jsv': '2.4.11', 'appKey': APPKEY, 't': int(time.time() * 1000),
'sign': 'FAKE_SIGN_WITH_ANYTHING', 'api': 'mtop.wdetail.getItemDescx', 'callback': 'mtopjsonp1','v': '4.9',
'type': 'jsonp', 'dataType': 'jsonp',
'data': DATA}
headers = {
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 9_3_4 like Mac OS X) AppleWebKit/601.1.46 ' + \
'(KHTML, like Gecko) Version/9.0 Mobile/13G35 Safari/601.1',
}
images = []
# get token in first request
r1 = requests.get(URL, params=params, headers=headers)
token_with_time = r1.cookies.get('_m_h5_tk')
token = token_with_time.split('_')[0]
enc_token = r1.cookies.get('_m_h5_tk_enc')
# get results in second request
t2 = str(int(time.time() * 1000))
c = '&'.join([token, t2, APPKEY, DATA])
m = hashlib.md5()
m.update(c.encode('utf-8'))
params.update({'t': t2, 'sign': m.hexdigest()})
cookies = {'_m_h5_tk': token_with_time, '_m_h5_tk_enc': enc_token}
r2 = requests.get(URL, params=params, headers=headers, cookies=cookies)
results=json.loads(re.match(r' mtopjsonp1\((.*?)\)', r2.text).group(1))
video_url = jsonpath(results, '$..video_url')[1]
print(video_url)
完整源码请关注微信公众号:ReverseCode,回复:JS逆向
本文由博客群发一文多发等运营工具平台 OpenWrite 发布