最近在看女高中生的废度日常, 然而 b 站的番剧画质压缩太大,所以找了一个解析网站.
结果发现网站的 js 代码带有混淆,遂逆向之.
逆向目标#
aHR0cHM6Ly9qeC5wbGF5ZXJqeS5jb20v
分析#
可以看出,视频加载出来了,可是没有看见任何有关视频的请求.
这几个请求的响应数据没法加载,但是可以猜测出应该是视频片段.
打开文件后显示如下:
那么大致的请求过程是:
M3U8 file 是一个保存 video clip 的请求 url 的文本文件.
有了它我们就能拿到整个视频文件的网址.
向上追溯,找到接受 m3u8 file 的请求:
请求网址的构成:
https:// 网址域名 / 时间戳 / 未知 / 未知.m3u8 + 固定参数
如果这里不细心的话,很容易就下 xhr 断点去追踪 js 代码了。我自己一开始分析的时候就进入了这个误区,在繁杂的代码和各种加密里转来转去.
然而这个请求不用我们构造,它由上一个请求接受,甚至没有加密,明文传输过来了!
再看这个请求的 playload:
两个参数time, key
time 是时间戳,key 看样子应该是 md5 密文。逆向 js 代码后其实是 CBC 加密,然而让我无语的是,几乎在我分析完 js 代码并开始用 python 模拟请求的时候,我发现 key 和 time 又在上一个请求被明文发过来了!!!
写代码#
#getPram.py
import time
import requests as rq
from lxml import etree
from lxml import html
headers = {
"referer": "https://jx.playerjy.com/",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36",
"Cache-Control": "no-cache",
"Host": "jy.we-vip.com:5433"
}
def getHtml(ep):
url = "https://jy.we-vip.com:5433/?url=" + ep
return rq.get(url=url, headers=headers, verify=False).content
# get time and key
def getData(bili_url):
htmlString = html.fromstring(getHtml(bili_url))
result = htmlString.xpath('//body/script/text()')
#gettime
timebegin = result[0].index('time') + 8
timeend = int(str(result[0]).index('",', timebegin))
time = result[0][timebegin:timeend]
#getkey
keybegin = result[0].index('key') + 7
keyend = int(str(result[0]).index('",', keybegin))
key = result[0][keybegin:keyend]
return time, key
if __name__ == "__main__":
time, key = getData()
print(f"time is {time}, key is {key}")
import requests as rq
import getPram
time, key = getPram.getData(input("bilibili_url:"))
headers = {
"authority" : "jy.we-vip.com:5433",
"accept" : "application/json, text/javascript, */*; q=0.01",
"content-type" : "application/x-www-form-urlencoded; charset=UTF-8",
"user-agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36",
"Host" : "jy.we-vip.com:5433",
"Content-Length": "115",
"Cache-Control": "no-cache"
}
url = r"https://jy.we-vip.com:5433/API.php"
data = {
"url": "https://www.bilibili.com/bangumi/play/ep276690",
"time": time,
"key": key
}
rsp = rq.post(url, headers=headers, data=data, verify=False)
print(rsp.content)
反思#
- 分析的思路像依托答辩,兜兜转转最后连请求过程都没有好好分析,浪费了很多时间。逆向就像高中的数学题,开始只有模糊的方向,需要耐心慢慢溯源追踪.
- 代码写的依托答辩,逻辑不是很清楚,提取子字符串想到很多种方法,最后选了最简单但是可读性极差的方式...