How to load a byte [] array into a structure in C #?

Consider the following structure, wherein both the length usernameand passwordequal to 17:

struct LoginPacket
{
    public int unk1;
    public string username;
    public string password;
}

Also this array of bytes

00 00 00 00 6A 6D 32 6D 65 00 72 00 7A 76 72 00 98 FD 18 00 A0 68 65 72 65 49 73
70 61 73 73 00 00 00 00 00 FF FF 31 2E 30 30 2E 30 30 00 00 00 C7 9D 72 00 04 00
00 31 2E 31 30 2E 32 37 00 0C 2C F6 24 16 2C F6 24 16

Is it possible to load this byte array into the above structure? There is something called Marshal, but that does not work for me.

+3
source share
4 answers

Here you are, this answer uses the .NET marshalling system. The structure itself contains a recipe on how to decrypt an array of bytes. If you cannot do this, you need a manual code.

void Main()
{
    byte[] bytes = new byte[]
    {
        0x00, 0x00, 0x00, 0x00, 0x6A, 0x6D, 0x32, 0x6D, 0x65, 0x00, 0x72, 0x00, 0x7A, 0x76, 0x72, 0x00, 0x98, 0xFD, 0x18, 0x00, 0xA0, 0x68, 0x65, 0x72, 0x65, 0x49, 0x73,
        0x70, 0x61, 0x73, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x31, 0x2E, 0x30, 0x30, 0x2E, 0x30, 0x30, 0x00, 0x00, 0x00, 0xC7, 0x9D, 0x72, 0x00, 0x04, 0x00,
        0x00, 0x31, 0x2E, 0x31, 0x30, 0x2E, 0x32, 0x37, 0x00, 0x0C, 0x2C, 0xF6, 0x24, 0x16, 0x2C, 0xF6, 0x24, 0x16
    };

    var packet = BytesToStructure<LoginPacket>(bytes);
    packet.Dump();
}

static T BytesToStructure<T>(byte[] bytes)
{
    int size = Marshal.SizeOf(typeof(T));
    if (bytes.Length < size)
        throw new Exception("Invalid parameter");

    IntPtr ptr = Marshal.AllocHGlobal(size);
    try
    {
        Marshal.Copy(bytes, 0, ptr, size);
        return (T)Marshal.PtrToStructure(ptr, typeof(T));
    }
    finally
    {
        Marshal.FreeHGlobal(ptr);
    }
}

[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet=CharSet.Ansi)]
struct LoginPacket
{
    public int unk1;

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst=17)]
    public string username;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst=17)]
    public string password;
}

When executed in LINQPad, you will get the following:

unk1: 0 
username: jm2me 
password: hereIspass
+5
source

, UTF8. , UTF8

struct LoginPacket
{
    public int unk1;
    public string username;
    public string password;

    public void Parse(byte[] b)
    {
        unk1 = BitConverter.ToInt32(b, 0);
        username = Encoding.UTF8.GetString(b, 4, 17);
        password = Encoding.UTF8.GetString(b, 4 + 17, 17);
    }
}
+4

, Encoding.GetString(byte[]) .

So, you need to present your bytes as byte[], and then use the method described above to convert it to a string.

LoginPacket packet;

byte[] mybytes = "..." //your bytes

packet.username = Encoding.GetBytes(mybytes);

etc...

You may need several byte arrays, each of which contains bytes for different structure fields. If (starting from the beginning) each field is 17 bytes, it should not be too complicated; if it is not, it will depend on how you know where each field begins in your byte array

0
source

One way is to use unsafe code:

        byte[] packetBytes;

        LoginPacket lp = new LoginPacket();
        lp.unk1 = BitConverter.ToInt32(packetBytes, 0);
        fixed (byte* buffer = &packetBytes[4])
        {
            lp.username = Marshal.PtrToStringUni((IntPtr)buffer);
            lp.password = Marshal.PtrToStringUni((IntPtr)buffer + (IntPtr)Encoding.Unicode.GetByteCount(lp.username));
        }
0
source

Source: https://habr.com/ru/post/1793813/


All Articles