直接获取 B 站视频 找到的都是分段的合成视频,于是乎在网上看到一个工具他做的视频解析可以解析出 mp4 的地址,遂转而直接研究从解析网站拿到视频地址,
分析思路:
-
首先模拟正常的请求,发现网址在这个地方,禁止 js 之后发现这个位置就空白了,很明显这段显示是 js 动态处理了
-
-
然后,我猜测是不是,有 ajax 请求发送,但是 network 之后发现,并没有 xhr 请求出现,突然在 ifream 请求中看到了 url,但是在网页源码中并没有发现这个网址,那么他是怎么来的?经大佬点播之后,明白了,网址最开始得 post 请求就已经拿到了,然后做了加密,js 渲染部分代码做了混淆,所以看不到请求操作。
-
继续查看网页源码,通过搜索 bvid,看到了两处很奇怪的代码,sojson.v4 sojson.v5 一种 sojson 字符串加密的方法
-
没见过这两种加密方法,网上百度,截图中的代码一看就是经过加密混淆的,所以首先反混淆解密一下看看
[https://jsdec.js.org/](https://jsdec.js.org/) 1. v4 /* *Progcessed By JSDec in 0.00s *JSDec - [JSDec.js.org](http://jsdec.js.org/) */ $("#mp4-url").attr("href",decrypt(hahaha)); $("#mp4-url2").text(decrypt(hahaha)); $("#player").attr("src", "[https://xbeibeix.com/api/player/?s=1&url=](https://xbeibeix.com/api/player/?s=1&url=)" + encodeURIComponent(decrypt($("#list").val()))); $("#list").change(function() { if ($("#list").val() != "false") { $("#player").attr("src", "[https://xbeibeix.com/api/player/?s=1&url=](https://xbeibeix.com/api/player/?s=1&url=)" + encodeURIComponent(decrypt($("#list").val()))); } }) 2. v5 /* *Progcessed By JSDec in 0.01s *JSDec - [JSDec.js.org](http://jsdec.js.org/) */ function encrypt(_0x336ffa) { var _0x456166 = { 'hhmwg': 'beibeidouyu12345', 'VlneJ': 'beibei1234567890' }; var _0x9fab4 = CryptoJS['enc']['Latin1']['parse'](_0x456166['hhmwg']); var _0x4cc587 = CryptoJS['enc']['Latin1']['parse'](_0x456166['VlneJ']); var _0x518a60 = CryptoJS['AES']['encrypt'](_0x336ffa, _0x9fab4, { 'iv': _0x4cc587, 'mode': CryptoJS['mode']['CBC'], 'adding': CryptoJS['pad']['ZeroPadding'] })['toString'](); return _0x518a60; } function decrypt(_0x55cd15) { var _0x2b29a5 = CryptoJS['enc']['Latin1']['parse']('beibeidouyu12345'); var _0x431fea = CryptoJS['enc']['Latin1']['parse']('beibei1234567890'); var _0x28806e = CryptoJS['AES']['decrypt'](_0x55cd15, _0x2b29a5, { 'iv': _0x431fea, 'mode': CryptoJS['mode']['CBC'], 'adding': CryptoJS['pad']['ZeroPadding'] })['toString'](CryptoJS['enc']['Utf8']); return _0x28806e; }; if (!(typeof encode_version !== 'undefined' && encode_version === 'sojson.v5')) { window['alert']('不能删除sojson.v5'); };
从代码和截图中我们可以很清楚的看到 hahaha 经过了调用 decrypt 方法进行了解密,生了 mp4 得网址,那么我们需要知道,hahaha 字符串是什么加密方法,搜索 decrypt 方法,我们看到了上方左边图片得一对代码,decrypt 就在其中不过全部被混淆了看不到,所以使用工具反混淆一下,看看到底是什么
对比一看原来是 aes 加密,并且使用得是 cbc 得模式,密钥我么都可以拿到了,接下来直接使用 python 得 AES 解密方法直接解密就可以了,安装 pycryptodomex 模块,好了至此完成一波,逆向破解
import requests import base64 from Crypto.Cipher import AES import re def get_encry_mp4(bvid): headers = { 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.116 Safari/537.36', } # bvid = "BV1qJ411c7pA" interface_ini = f"[https://www.bilibili.com/video/](https://www.bilibili.com/video/){bvid}" url = "[https://xbeibeix.com/api/bilibili/](https://xbeibeix.com/api/bilibili/)" data = { "bilibiliurl11081": interface_ini, "zengqiang": "true" } result = requests.post(url, data=data, verify=False, headers=headers) try: encry_mp4_url = re.search('var hahaha = (.*?);', result.text).group(1) return encry_mp4_url except Exception as e: print(e) # 密钥(key), 密斯偏移量(vi) CBC模式加密 def AES_Decrypt(data): key = 'beibeidouyu12345' vi = 'beibei1234567890' data = data.encode('utf8') encodebytes = base64.decodebytes(data) # 将加密数据转换位bytes类型数据 cipher = AES.new(key.encode('utf8'), AES.MODE_CBC, vi.encode('utf8')) text_decrypted = cipher.decrypt(encodebytes) text_decrypted = text_decrypted.rstrip(b'\0') # 去补位 text_decrypted = text_decrypted.decode('utf8') return text_decrypted if __name__ == '__main__': vid = 'BV16i4y1L7mw' encry_mp4_url = get_encry_mp4(vid) encry_mp4_url = mp4_decrypted = AES_Decrypt(encry_mp4_url).strip('\x0f') print(repr(mp4_decrypted))
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于