B 站彈幕 protobuf 協議還原分析

     時間過得飛快,轉眼間本公衆號文章已經連續更新了四個月。感恩這三個月裏結交了很多志同道合的朋友;我也會持之以恆,繼續創造更好的文章給各位讀者朋友。廢話不多說,今天給大家帶來 B 站彈幕 protobuf 協議分析,全程高能,在閱讀的同時不要忘記點贊 + 關注哦⛽️

特別聲明:本公衆號文章只作爲學術研究,不用於其它用途。

 目錄

一、什麼是 protobuf?

二、網站調試分析

三、protobuf 協議還原

四、完整代碼實現

五、心得分享及總結

趣味模塊

      小紅是一名數據分析工程師,自從上次小紅解決了字體反爬的問題後,小紅還未遇到過有難度的問題。但是天有不測風雲,今天小紅在分析彈幕君的時候,遇到了新的問題。數據亂碼無規律,據說是 protobuf,那麼今天我們去分析下小紅同學遇到的新問題吧!

一、什麼是 protobuf 協議?

**前言:**Protobuf (Protocol Buffers) 是谷歌開發的一款無關平臺,無關語言,可擴展,輕量級高效的序列化結構的數據格式,用於將自定義數據結構序列化成字節流,和將字節流反序列化爲數據結構。所以很適合做數據存儲和爲不同語言,不同應用之間互相通信的數據交換格式,只要實現相同的協議格式,即後綴爲 proto 文件被編譯成不同的語言版本,加入各自的項目中,這樣不同的語言可以解析其它語言通過 Protobuf 序列化的數據。目前官方提供 c++,java,go 等語言支持。

二、網站調試分析

1、首先打開我們本次分析的網站,搜索指定彈幕內容,截圖如下所示:

**說明:**由於彈幕內容使用了 protobuf 協議,所以無法直接搜索定位,我們需要分析數據包請求,去定位具體的 url 鏈接。

2、分析數據包請求,定位到彈幕鏈接,截圖如下所示:

**說明:**從截圖中我們可以清楚看出,這就是彈幕的內容。但是畢竟使用了 protobuf 協議編碼,我們如果想還原出明文信息,接下來需要去進行 JS 斷點調試分析了。

3、使用 xhr/fetch 對該請求打斷點調試,截圖如下所示:

**說明:**因爲該請求是對 response 進行了 protobuf 協議編碼,所以我們在定位到該請求發包位置後,只需要關注後面的解碼邏輯即可。

4、執行斷點操作按鈕後,截圖如下所示:

**說明:**此刻 r 變量即爲我們要訪問的彈幕 url 地址;接下來繼續執行斷點。

5、繼續執行斷點,持續更近,截圖如下所示:

此刻我們打印變量 r 的值,截圖如下所示:

**說明:**這不就是我們想要的明文信息麼?接下來,我們只需要找到 protobuf 協議初始化參數 id 定義就可以還原明文了。

6、經過 JS 斷點調試,最終定位到 protobuf 協議初始化參數如下:

**7、**將 Console 中的數據複製後進行 JSON 在線格式化解析,截圖如下:

**總結:**知道 response 明文及 protobuf 協議定義的參數及 id 後,接下來我們只需要構建 proto 文件即可完成對整個明文信息的還原。

三、protobuf 協議還原

1、還原 protobuf 協議,編輯代碼結構如下:

2、執行如下命令,編譯爲 python protobuf 可執行文件:

protoc  --python_out=. *.proto

3、運行命令後,生成 protobuf 文件,截圖如下所示:

**總結:**走到這裏 protobuf 協議就完全還原了,接下來讓我們進入完整代碼實現環節吧。

四、完整代碼實現

1、整個項目完整代碼如下

# -*- coding: utf-8 -*-
# --------------------------------------
# @author : 公衆號:逆向與爬蟲的故事
# --------------------------------------
import requests
from feed_pb2 import Feed
from google.protobuf.json_format import MessageToDict
def start_requests():
    cookies = {
        'rpdid': '|(J~RkYYY|k|0J\'uYulYRlJl)',
        'buvid3': '794669E2-CEBC-4737-AB8F-73CB9D9C0088184988infoc',
        'buvid4': '046D34538-767A-526A-8625-7D1F04E0183673538-022021413-+yHNrXw7i70NUnsrLeJd2Q%3D%3D',
        'DedeUserID': '481849275',
        'DedeUserID__ckMd5': '04771b27fae39420',
        'sid': 'ij1go1j8',
        'i-wanna-go-back': '-1',
        'b_ut': '5',
        'CURRENT_BLACKGAP': '0',
        'buvid_fp_plain': 'undefined',
        'blackside_state': '0',
        'nostalgia_conf': '-1',
        'PVID': '2',
        'b_lsid': '55BA153F_18190A78A34',
        'bsource': 'search_baidu',
        'innersign': '1',
        'CURRENT_FNVAL': '4048',
        'b_timer': '%7B%22ffp%22%3A%7B%22333.1007.fp.risk_794669E2%22%3A%2218190A78B5F%22%2C%22333.788.fp.risk_794669E2%22%3A%2218190A797FF%22%2C%22333.42.fp.risk_794669E2%22%3A%2218190A7A6C5%22%7D%7D',
    }
    headers = {
        'authority': 'xxxxxx',
        'accept': '*/*',
        'accept-language': 'zh-CN,zh;q=0.9',
        'cache-control': 'no-cache',
        'origin': 'https://www.xxxxx.com',
        'pragma': 'no-cache',
        'referer': 'https://www.xxxxxx.li.com/video/BV1434y1L7rb?spm_id_from=333.851.b_7265636f6d6d656e64.1&vd_source=8d45ec9ed78652f966b3625afe95e904',
        'sec-ch-ua': '".Not/A)Brand";v="99", "Google Chrome";v="103", "Chromium";v="103"',
        'sec-ch-ua-mobile': '?0',
        'sec-ch-ua-platform': '"macOS"',
        'sec-fetch-dest': 'empty',
        'sec-fetch-mode': 'cors',
        'sec-fetch-site': 'same-site',
        'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36',
    }
    params = {
        'type': '1',
        'oid': '729126061',
        'pid': '896926231',
        'segment_index': '1',
    }
    response = requests.get('https://xxxx.xxxx.com/x/v2/dm/web/seg.so', params=params, cookies=cookies,
                            headers=headers)
    info = Feed()
    info.ParseFromString(response.content)
    _data = MessageToDict(info, preserving_proto_field_name=True)
    messages = _data.get("message") or []
    for message in messages:
        print(message.get("content"))
if __name__ == '__main__':
    start_requests()

2、運行代碼後,截圖如下所示:

五、心得分享及總結

回顧整個分析流程,本次難點主要概括爲以下幾點:

今天分享到這裏就結束了,歡迎大家關注下期文章,我們不見不散⛽️

逆向與爬蟲的故事 不止於爬蟲開發,還有 Js 逆向、App 逆向!

    我是 TheWeiJun,有着執着的追求,信奉終身成長,不定義自己,熱愛技術但不拘泥於技術,愛好分享,喜歡讀書和樂於結交朋友,歡迎加我微信與我交朋友。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/pmDGL5r1Pv14KB2etuyx7w