直接获取 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))
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于