簡體   English   中英

使用現有的C#類讀取Protobuf TCP數據包

[英]Reading Protobuf TCP Packets with existing C# classes

這個問題看似簡單且可行,但是我一生無法使它正常工作。

我有:

  • 我知道有幾個數據包的PCAP文件是某種類型的ProtoBuf數據(可能是用protobuf-csharp-port創建的)
  • 程序集中所有可能的C#類都裝飾有:

     [DebuggerNonUserCode, CompilerGenerated, GeneratedCode("ProtoGen", "2.4.1.473")] public sealed class thing : GeneratedMessageLite<thing, thing.Builder> 

我要做的就是使用我從匯編文件中了解的信息來解析那些數據包。 簡單? 可能,但是無論我做什么,實際上都沒有得到解析。

這是許多可能的類之一的示例:

    [DebuggerNonUserCode, CompilerGenerated, GeneratedCode("ProtoGen", "2.4.1.473")]
    public sealed class Thing: GeneratedMessageLite<Thing, Thing.Builder>
    {
        // Fields
        private static readonly string[] _thingFieldNames = new string[] { "list" };
        private static readonly uint[] _thingFieldTags = new uint[] { 10 };

        ...

        public static Builder CreateBuilder()
        {
            return new Builder();
        }

        ...

        public static thing ParseFrom(ByteString data)
        {
            return CreateBuilder().MergeFrom(data).BuildParsed();
        }

        ...

        public override void WriteTo(ICodedOutputStream output)
        {
            int serializedSize = this.SerializedSize;
            string[] strArray = _thingFieldNames;
            if (this.list_.Count > 0)
            {
                output.WriteMessageArray<thingData>(1, strArray[0], this.list_);
            }
        }

        ...

        [DebuggerNonUserCode, GeneratedCode("ProtoGen", "2.4.1.473"), CompilerGenerated]
        public static class Types
        {
            // Nested Types
            [CompilerGenerated, GeneratedCode("ProtoGen", "2.4.1.473")]
            public enum PacketID
            {
                ID = 19
            }
        }
    }

有很多其他類似的東西。 我嘗試對每個數據包執行以下操作(使用protobuf-csharp-port):

    Console.WriteLine(Thing.ParseFrom(packet.Buffer).ToString());

我希望看到實際的文本數據。 但是我什么也沒得到,關於無效數據包標簽的錯誤,或者關於它為“ 0”的錯誤。

我也嘗試過使用protobuf-net,但這只是給我有關不兼容,意外類型等的隨機錯誤:

    Console.WriteLine(ProtoBuf.Serializer.Deserialize<Thing>(ms));

我到底在這做錯了什么? 有沒有更好的方法,可以在程序集中使用所有已知的類型,簡單地解碼Protobuf消息並查看其中的內容? 理想情況下,無需事先知道消息類型是什么?

非常感謝,如果您能解決這個問題!

從問題中概述的失敗嘗試中猜測,我相信您對pcap文件的內容有一些誤解。 特別是這條線

Console.WriteLine(Thing.ParseFrom(packet.Buffer).ToString());

讓我認為您在錯誤的假設下工作,即單個pcap數據包包含一個對象的序列化字節。 不幸的是,這種情況並非如此。

如您所知,TCP / IP網絡使用分層協議棧,其中每個層都添加了功能,並將上層協議與下層協議的細節隔離開了(反之亦然)。 這是通過封裝從高層發送到網絡的數據,並在數據沿接收方的堆棧向上傳輸時進行解封裝來完成的。 現在,您的pcap文件包含網絡接口看到的原始數據,即,序列化的有效負載以及應用程序,傳輸,Internet和鏈接層添加的所有數據。

現在,如果您要反序列化轉儲中包含的對象,則需要編寫一些代碼來刪除鏈接層和Internet協議的所有標頭,(取消)傳輸協議的工作並重新組合通過網絡發送的字節流。*

接下來,您將需要分析產生的字節轉儲,並對應用程序級別協議的設計做出一些復雜的猜測。 開始通信時是否實現握手? 它會與實際有效載荷一起發送校驗和嗎? 數據在通過網絡發送之前是否已被壓縮? 應用程序在發送數據之前會對其進行加密嗎? 如果將TCP用作傳輸協議,那么如何實現消息框架等。當然,如果您可以訪問生成數據的應用程序的源代碼(或至少是應用程序二進制文件),則只需閱讀代碼即可(或對二進制文件進行反向工程)以弄清楚這部分。

至此,您就可以解釋原始數據了。 剩下的就是編寫一些代碼來提取相關的字節,並將其提供給協議緩沖區解串器和voilà,讓您的對象回來!

(*當然還有其他一些小問題,例如碎片化的IP數據包,無序到達的TCP段和TCP重傳。)


總結一下:

  • 理論上講,有可能編寫一個工具來反序列化使用pcap轉儲中使用協議緩沖區進行序列化的對象,前提是轉儲包含兩個對等方之間的完整通信,即,生成轉儲的工具未將數據包截斷等。
  • 但是實際上 ,有許多克服的障礙,即使對於經驗豐富的本領域從業人員而言,也是微不足道的,因為這樣的工具必須:
    1. 能夠處理TCP / IP較低級協議的所有復雜問題,以重建對等方之間的數據流。
    2. 能夠了解用於傳輸序列化對象的應用程序級別協議。

請注意,僅上述第1點導致要求至少部分實現TCP / IP堆棧的功能。 實現此目的的最簡單方法可能是重用開放源代碼TCP / IP實現的代碼,例如在Linux或* BSD內核中發現的代碼。 許多執行類似操作的工具(例如從捕獲文件中重建HTTP流量)正是這樣做的。 (例如參見Justsniffer 。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM