前言
本文分析 好看视频的视频下载链接 是在北京时间 10/16/2023 22:35:10
,网站的数据解密过程将来可能会有所变动,本文可能也不会再去更改以适应网站的变动(要看动漫),所以尽可能分析得详细一些,至少以后网站变动之后也能自己解决问题。
另外,最后的 python
代码也许不尽人意,因为本文主要分析如何获取视频的下载链接,其它部分就没有那么多精力去优化了。
斗法的战场:windows 10
。
所用的凡阶法器:windows Edge、postman
(都为最新版本)
法力派别:python3.10
。
飞剑试敌
利用审查元素查看视频的链接,结果是一个 blob src
。关于 blob
此处不多讲述,具体见 MDN
文档:[Blob - Web API 接口参考 | MDN (mozilla.org)](https://developer.mozilla.org/zh-CN/docs/Web/API/Blob)
然后查看网页的 HTML
源码,发现了可疑的数据,毕竟很多网站都把一些东西都这里。
如下,这里发现了很多内容,更有名为 encrptedVideoMeta 的可疑数据,无论是其名字还是其内容,都给人一种 “此地无银三百两” 的感觉,这里先标记一下,将它称为 meta
数据,便于后文讨论。
以上只是初步试探,还需要去抓包界面看一看在视频请求之前的、可疑的请求。
最后需要记一下视频的 URL
(通过它可以下载视频,所以称之为视频下载链接,以便区分 “视频播放页链接”),如下:
// 这是当前视频的播放页链接
https://haokan.baidu.com/v?vid=7206460708751282010&tab=recommend
// 这个是视频的下载链接
https://vd3.bdstatic.com/mda-pimcdy4ke1y834ty/wzdash/bd265/1696524494778112663/mda-pimcdy4ke1y834ty/dash-default.mp4?cr=0&cd=1&abtest=112751_4-112954_1&logid=3284052574&pd=1&pt=3&vid=7206460708751282010
至此,分析到了这里有以下思路:
-
确定上面提到的 meta
是不是关键的数据
-
确定上面那个 abdr
请求的响应中的 data
字段是不是关键数据
-
根据视频下载链接的部分内容、如 vd3.bdstatic.com
等进行搜索
-
搜关键词大法,如搜索 flv、mp4、m3u8
等等,还可以搜索 decrypt、JSON
等等关键字来定位。
-
从视频请求的 Initiator
中找相关代码
当然是先从简单的来确认,所以开始确认 meta
数据…………!其实直接全局搜索一下 encrptedVideoMeta
就能定位到位置了,不过我更想说明以后碰到此类情况的处理方法,万一它的名字很短呢,比如取名为 d
,那全局搜索不知道搜到哪里去了。
祭出法器!确定关键数据的位置
在格式化好的 HTML
源码处看一看,发现了 encrptedVideoMeta
发现该位于对象 __PRELOADED_STATE__
然后在控制台输出 __PRELOADED_STATE__
来查看,不过其内容太多了,使用 copy()
将它复制到编辑器。
然后搜索 http
等等,尤其是上面抓到的视频下载链接!最终确认了视频链接果然在这里!
但是 meta
数据还是加密的形式,可惜~~~
不过发现了这个! 还是需要细心一些,所以现在只需要确定哪里给 curVideoMeta
即可。
可以通过 hook
来确定 curVideoMeta
赋值的地方,其实也可以搜索 JSON.parse
来确定其位置所在,因为一般而言都是通过一些字符串解密从而得到一个 json
字符串,然后利用 JSON.parse
将其转为 js
对象,然后赋值给 curVideoMeta
。诚然,事无绝对,这仅是一个一种思路。
hook
的代码如下:
!function () {
var _data = "";
Object.defineProperty(__PRELOADED_STATE__, "curVideoMeta", {
set(v) {
console.log("========== Set ==========");
debugger;
_data = v;
},
get() {
console.log("========== Get ==========");
return _data;
}
});
}()
最终,它还是指向了 encrptedVideoMeta
!!!
所以开始分析 encrptedVideoMeta
,源代码如下:
// 取自 https://hk.bdstatic.com/static/haokan-pc/js/videoland-v2.586aae.chunk.js`
var t = e || {}
, r = t.encrptedVideoMeta;
if (1 === t.encrypt)
try {
// 确定核心解密函数是 le.videoDataDecrypt
e.curVideoMeta = JSON.parse(Object(le.videoDataDecrypt)(r))
} catch (n) {}
return e
分析 videoDataDecrypt 函数
然后进入 le.videoDataDecrypt
函数,得到以下代码
整理一下格式已经添加注释。
// 取自 https://hk.bdstatic.com/static/haokan-pc/js/videoland-v2.586aae.chunk.js
function(e) {
var t = i;
return e = a[t(540)][t(737)][t(577)](a[t(540)][t(506)][t(582)](e)),
(0,
o[t(782)])(e, t(747))
}
// =======================
// 以下进行分析
// =======================
// e 是需要解密的值
function(e) {
var t = i;
// 在控制台经过测试,得到以下结果,这里是似乎是进行了 base64 解码,但还需要确认,见后文
e = a["enc"]["Utf8"]["stringify"] ( // 这里调用一个函数,以下部分都是参数
a["enc"]["Base64"]["parse"](e),
);
// 现在需要确定 o["xorCipher"] 函数的逻辑
return o["xorCipher"](e, "guanghui456")
}
关注上述代码中字符串 guanghui456 的来历:
确认是否为 Base64 decode
现在要确认第一次对 meta
的处理是否为 base64
。
- 首先生成字符串
12345
的 base64 encode
值
- 然后用它去测试上述的逻辑,最终确认为
base64 decode!!!
分析 o["xorCipher"]
通过调试得到其 js
代码如下:
// 只关注和参数 e、t 有关的部分,其它的都通过控制台一一测试处结果
function(e, t) {
// r(470) 是 length
for (var r = a, n = "", i = 0; i < e[r(470)]; i++) {
// r(517) 是 charCodeAt
var o = e[r(517)](i)
, s = t[r(517)](i % t[r(470)]);
// r(599) 是 fromCharCode
n += String[r(599)](o ^ s)
}
return n
}
BOSS 降临!决战于此
现在就可以得到获取好看视频的视频链接流程了:
- 访问视频首页,如
https://haokan.baidu.com/v?vid=7206460708751282010
,获取其 HTML
源码
# 对应 Python 代码
import requests
url = "https://haokan.baidu.com/v?vid=7206460708751282010"
# 不需要其它的请求头字段
headers = {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 Edg/118.0.2088.46",
}
html = requests.get(url, headers=headers).text
- 从
HTML
源码中提取出 encrptedVideoMeta
的值
# 对应 Python 代码
import re
meta = re.search(r'"encrptedVideoMeta":\s*"(.*?)"', html).group(1)
- 先对
meta
值进行 base64 decode
,然后按照上述 o["xorCipher"]
函数的逻辑处理
# 对应 Python 代码
import base64
def xor_cipher(meta: str, t: str) -> str:
result = ""
for i in range(len(meta)):
o = ord(meta[i])
s = ord(t[i % len(t)])
result += chr(o ^ s)
return result
meta = base64.b64decode(meta).decode()
meta = xor_cipher(meta, "guanghui456")
- 然后对数据进行处理
import json
from pprint import pprint
meta = json.loads(meta)
# 直接用浏览器可以打开其中的视频下载链接进行视频播放,说明不需要设置请求头 Referer 之类的
pprint(meta)
小结
本次逆向的难点主要在于定位解密的数据,解密的过程倒是不难,只要有耐心一点一点都能弄明白。
如果好几个网站都这么分析代码人也吃不消,代码多了更是头大,拿这个分析的时间学一学 AST
来统一处理好得多吧。
不过本文最重要的还是思考怎么找数据,方法有了网站再怎么变也差不多。
我也刚学 js 不久,文中有误、不妥的地方请……大家憋在心里别说!写文章比写回答累多了………