最近在看女高中生的废度日常,然而 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)
反思#
- 分析的思路像依託答辯,兜兜轉轉最後連請求過程都沒有好好分析,浪費了很多時間。逆向就像高中的數學題,開始只有模糊的方向,需要耐心慢慢追蹤。
- 代碼寫的依託答辯,邏輯不是很清楚,提取子字符串想到很多種方法,最後選了最簡單但是可讀性極差的方式...