Casting ein byte-array in eine verwaltete Struktur

Update: die Antworten auf diese Frage half mir code der open-Source-Projekt AlicanC Modern Warfare 2-Tool auf GitHub. Sie können sehen, wie lese ich diese Pakete in MW2Packets.cs und die Erweiterungen habe ich codiert zu Lesen, big-endian-Daten in Extensions.cs.

Ich bin capturing UDP-Pakete von Call of Duty: Modern Warfare 2 mit Pcap.Net in meiner C# - Anwendung. Ich erhalte eine byte[] aus der Bibliothek. Ich habe versucht zu analysieren wie ein string, aber das hat nicht gut funktioniert.

Den byte[] ich habe mit einem generischen Paket-header, dann ein anderes spezifischen header, um das Paket geben Sie dann Informationen über jeden Spieler in der lobby.

Eine hilfreiche person inspiziert, einige Pakete für mich an und kam mit diesen Strukturen:

//Fields are big endian unless specified otherwise.
struct packet_header
{
    uint16_t magic;
    uint16_t packet_size;
    uint32_t unknown1;
    uint32_t unknown2;
    uint32_t unknown3;
    uint32_t unknown4;
    uint16_t unknown5;
    uint16_t unknown6;
    uint32_t unknown7;
    uint32_t unknown8;
    cstring_t packet_type; //\0 terminated string
};

//Fields are little endian unless specified otherwise.
struct header_partystate //Header for the "partystate" packet type
{
    uint32_t unknown1;
    uint8_t unknown2;
    uint8_t player_entry_count;
    uint32_t unknown4;
    uint32_t unknown5;
    uint32_t unknown6;
    uint32_t unknown7;
    uint8_t unknown8;
    uint32_t unknown9;
    uint16_t unknown10;
    uint8_t unknown11;
    uint8_t unknown12[9];
    uint32_t unknown13;
    uint32_t unknown14;
    uint16_t unknown15;
    uint16_t unknown16;
    uint32_t unknown17[10];
    uint32_t unknown18;
    uint32_t unknown19;
    uint8_t unknown20;
    uint32_t unknown21;
    uint32_t unknown22;
    uint32_t unknown23;
};

//Fields are little endian unless specified otherwise.
struct player_entry
{
    uint8_t player_id;

    //The following fields may not actually exist in the data if it's an empty entry.
    uint8_t unknown1[3];
    cstring_t player_name;
    uint32_t unknown2;
    uint64_t steam_id;
    uint32_t internal_ip;
    uint32_t external_ip;
    uint16_t unknown3;
    uint16_t unknown4;
    uint32_t unknown5;
    uint32_t unknown6;
    uint32_t unknown7;
    uint32_t unknown8;
    uint32_t unknown9;
    uint32_t unknown10;
    uint32_t unknown11;
    uint32_t unknown12;
    uint16_t unknown13;
    uint8_t unknown14[???];     //Appears to be a bit mask, sometimes the length is zero, sometimes it's one. (First entry is always zero?)
    uint8_t unknown15;
    uint32_t unknown16;
    uint16_t unknown17;
    uint8_t unknown18[???];     //Most of the time this is 4 bytes, other times it is 3 bytes.
};

Ich neu die Paket-header-Struktur in meiner C# - Anwendung wie diese:

[StructLayout(LayoutKind.Sequential, Pack=1)]
struct PacketHeader
{
    public UInt16 magic;
    public UInt16 packetSize;
    public UInt32 unknown1;
    public UInt32 unknown2;
    public UInt32 unknown3;
    public UInt32 unknown4;
    public UInt16 unknown5;
    public UInt16 unknown6;
    public UInt32 unknown7;
    public UInt32 unknown8;
    public String packetType;
}

Dann habe ich versucht, eine Struktur für die "partystate" - header, aber ich habe Fehler sagen fixed Schlüsselwort ist unsicher:

[StructLayout(LayoutKind.Sequential, Pack=1)]
struct PartyStateHeader
{
    UInt32 unknown1;
    Byte unknown2;
    Byte playerEntryCount;
    UInt32 unknown4;
    UInt32 unknown5;
    UInt32 unknown6;
    UInt32 unknown7;
    Byte unknown8;
    UInt32 unknown9;
    UInt16 unknown10;
    Byte unknown11;
    fixed Byte unknown12[9];
    UInt32 unknown13;
    UInt32 unknown14;
    UInt16 unknown15;
    UInt16 unknown16;
    fixed UInt32 unknown17[10];
    UInt32 unknown18;
    UInt32 unknown19;
    Byte unknown20;
    UInt32 unknown21;
    UInt32 unknown22;
    UInt32 unknown23;
}

Ich konnte nicht alles tun für die Spieler, die Einträge wegen der unterschiedlichen Größe der unknown14 und unknown18. (Spieler-Einträge sind die wichtigsten.)

Nun, irgendwie habe ich das wirken des byte[] ich diese PacketHeader Strukturen. Leider, es ist nicht einfach, da (PacketHeader)bytes. Ich habe versucht, diese Methode, die ich gefunden habe im internet, aber es warf ein AccessViolationException:

GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
PacketHeader packetHeader = (PacketHeader)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(PacketHeader));

Wie kann ich das erreichen?

Meine Antwort nicht Marschall der Struktur direkt, sondern nimmt den Ansatz der Gewinnung von Feld Werte aus dem byte-array aus, das Sie Lesen aus dem Netz. Sie werden wahrscheinlich haben, um flip-die big-endian bits selbst wenn; die .NET-Basisklassen sind alle little-endian, soweit ich weiß.
+1 für das teilen des Ergebnisses

InformationsquelleAutor AlicanC | 2011-06-13

Schreibe einen Kommentar