protobuf流的反解析Message
0x01 protobuf的基本概念
protobuf通過定義".proto"文件來描述數據的結構。.proto文件中用"Message"所表示所需要序列化的數據的格式。Message由field組成,Field類似Java或者C++中成員變量,通常一個field的定義包含修飾符、類型、名稱和ID。下面看一個簡單的.proto文件的例子:
[plain]?view plaincopy
[cpp]?view plaincopy
[plain]?view plaincopy
0x02 ?protobuf流的反解析
2.1 ?Varint編碼
Protobuf的二進制使用Varint編碼。Varint 是一種緊湊的表示數字的方法。它用一個或多個字節來表示一個數字,值越小的數字使用越少的字節數。這能減少用來表示數字的字節數。
Varint 中的每個 byte 的最高位 bit 有特殊的含義,如果該位為 1,表示后續的 byte 也是該數字的一部分,如果該位為 0,則結束。其他的 7 個 bit 都用來表示數字。因此小于 128 的數字都可以用一個 byte 表示。
例如:十六進制流里面其中兩個字節:0x95 0x01,則其轉換運算為:(0x95 & 0x7F) ?| (0x01 << 0x7) = 0x5 | 0x80 = 0x95。
若其中四個字節:0x9D 0xF4 0xC1 0xCB 0x05,則其轉換運算為:
(0x9D & 0x7F) | (0xF4 & 0x7F)<<7 | (0xC1 & 0x7F)<<E | (0xCB & 0x7F)<<0x15 | 05<<0x1C?
=?1D | 3A00 | 104000 | 9600000 | 50000000?
= 59707A1D
2.2 數值類型
Protobuf經序列化后以二進制數據流形式存儲,這個數據流是一系列key-Value對。Key用來標識具體的Field,在解包的時候,Protobuf根據 Key 就可以知道相應的 Value 應該對應于消息中的哪一個 Field。
Key 的定義如下:
(field_number << 3) | wire_type
Key由兩部分組成。第一部分是 field_number,比如消息chatTest.content1中 的 field_number 為 1。第二部分為 wire_type。表示 Value 的傳輸類型。Wire Type 可能的類型如下表所示:
| type | Meaning | Used For |
| 0 | Varint | int32, int64, uint32, uint64, sint32, sint64, bool, enum |
| 1 | 64-bit | fixed64, sfixed64, double |
| 2 | Length-delimi | string, bytes, embedded messages, packed repeated fields |
| 3 | Start group | Groups (deprecated) |
| 4 | End group | Groups (deprecated) |
| 5 | 32-bit | fixed32, sfixed32, float |
| ? | ? | ? |
以上面生成的十六進制流我們可以開始分析
required和optional不會有任何字節來表示這個修飾符。
repeated會存在相同的field_number。
[plain]?view plaincopy
05 -> 代表字符串長度05
[plain]?view plaincopy
20->value=0x20;
[plain]?view plaincopy
06->結構體長度06
0a->field_num=1,type=2;
04->字符串長度04
61 61 61 61 ->value="aaaa"
1a->field_num=3, type=2;
05->結構體長度05
0a->field_num=1,type=2;
03->字符串長度03
61 61 61 61 ->value="bbb"
2.3 protoc 進行反序列化
上面的步驟是手動解析的過程,而利用google提供的工具可以幫助我們自動化的解析以上過程,在面對復雜的protobuf結構的時候能達到事半功倍的效果。按下面步驟來做:
首先配置java環境
其次安裝jython,這里
然后編寫Python腳本,protobuf.py
[python]?view plaincopy
其中testprotobuf.bin是我們的protobuf流文件。
最后運行腳本
[plain]?view plaincopy
利用反序列化的結構來推測.proto的message的結構及每個字段的含義,就能達到protobuf流反解析的目的了。
上述方案是采用python調用protoc的命令,由于protobuf是開源的,是在牛逼可以看他的源碼,看他怎么解析出來的,我看了下他的源碼,由于太菜和項目時間比較緊,每太看明白,暫時采用上述方法。
總結
以上是生活随笔為你收集整理的protobuf流的反解析Message的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Burpsuite中protobuf数据
- 下一篇: send函数阻塞