banner
ming5ming

ming5ming

⭐一起去追那遥不可及的星⭐ 正在赛马!

逆向日記0x1

最近在看女高中生的废度日常,然而 b 站的番剧画质压缩太大,所以找了一个解析网站。
結果發現網站的 js 代碼帶有混淆,遂逆向之。


逆向目標#

aHR0cHM6Ly9qeC5wbGF5ZXJqeS5jb20v

分析#

Pasted image 20230214195931

可以看出,視頻加載出來了,可是沒有看見任何有關視頻的請求。Pasted image 20230214200144

這幾個請求的響應數據沒法加載,但是可以猜測出應該是視頻片段。
打開文件後顯示如下:

Pasted image 20230214200551

那麼大致的請求過程是:

request

M3U8 file 是一個保存 video clip 的請求 url 的文本文件。
有了它我們就能拿到整個視頻文件的網址。

向上追溯,找到接受 m3u8 file 的請求:

Pasted image 20230214201749
Pasted image 20230214201851

https:// 省略 / 1676376933/4d140af4cb5d1c5466a7491918b43e5b/b3489f29121e97e6dd1dcb1957e5788c-20230214.m3u8?from=https://banyung.pw

請求網址的構成:
https:// 網址域名 / 時間戳 / 未知 / 未知.m3u8 + 固定參數

如果這裡不細心的話,很容易就下 xhr 斷點去追蹤 js 代碼了。我自己一開始分析的時候就進入了這個誤區,在繁雜的代碼和各種加密裡轉來轉去。

Pasted image 20230214202531

然而這個請求不用我們構造,它由上一個請求接受,甚至沒有加密,明文傳輸過來了!

Pasted image 20230214202715

再看這個請求的 playload:

Pasted image 20230214202821

兩個參數time, key
time 是時間戳,key 看樣子應該是 md5 密文。逆向 js 代碼後其實是 CBC 加密,然而讓我無語的是,幾乎在我分析完 js 代碼並開始用 python 模擬請求的時候,我發現 key 和 time 又在上一個請求被明文發過來了!!!

Pasted image 20230214203247

寫代碼#

#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)

反思#

  • 分析的思路像依託答辯,兜兜轉轉最後連請求過程都沒有好好分析,浪費了很多時間。逆向就像高中的數學題,開始只有模糊的方向,需要耐心慢慢追蹤。
  • 代碼寫的依託答辯,邏輯不是很清楚,提取子字符串想到很多種方法,最後選了最簡單但是可讀性極差的方式...
載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。