1

I have this code in C#:

Structure:

[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi, Size = 116)]
    public struct pLogin
    {
        public pHeader _header;

        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 12)]
        public string senha;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 12)]
        public string login;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
        public byte[] unk1;
        public int algo1;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 42)]
        public byte[] unk2;
        public short algo2;
        //versao do cliente
        public ushort cliver;
        public ushort unk3;
        public int umBool;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
        public byte[] mac;
    }
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi, Size = 12)]
    public struct pHeader
    {
        public ushort size;
        public byte key;
        public byte checksum;
        public ushort packetId;
        public ushort clientId;
        public uint timestamp;
    }

Login Func:

pLogin pLogin;
    public void iniciarLogin(string login, string senha, int cliver, string p_mac = "")
    {
        pLogin = new pLogin();
        pLogin._header = buildHeader(0x20D, 116);
        pLogin.senha = senha;
        pLogin.login = login;
        pLogin.cliver = (ushort)cliver;
        pLogin.umBool = 1;
        pLogin.algo1 = 132;
        pLogin.algo2 = 152;
        if (p_mac.Length == 0)
        {
            pLogin.mac = Encoding.ASCII.GetBytes(Functions.RandomString(16));
        }
        else
        {
            pLogin.mac = Functions.StringToByteArray(p_mac);
        }
        byte[] buffer = BufferConverter.StructureToBuffer<pLogin>(pLogin);
        EncDec.Encrypt(ref buffer);
        socket.Send(BufferConverter.StringToByteArray("11F3111F"));

        socket.Send(buffer);
        logger.Text += "[Cliente] Solicitando login...\n";

    }
pHeader packetHeader;
    private pHeader buildHeader(int _packetID, int size)
    {
        packetHeader = new pHeader();
        packetHeader.size = (ushort)size;
        packetHeader.key = EncDec.GetHashByte();
        packetHeader.checksum = 0;
        packetHeader.packetId = (ushort)_packetID;
        packetHeader.clientId = (ushort)serverData.playerMob.Mob.ClientId;
        packetHeader.timestamp = getCurrentTime();
        return packetHeader;
    }

Now the buffer converter class:

public static Byte[] StructureToBuffer<T>(T structure)
    {
        Byte[] buffer = new Byte[Marshal.SizeOf(typeof(T))];

        unsafe
        {
            fixed (byte* pBuffer = buffer)
            {
                Marshal.StructureToPtr(structure, new IntPtr((void*)pBuffer), true);
            }
        }

        return buffer;
    }

    public static T BufferToStructure<T>(Byte[] buffer, Int32 offset)
    {
        unsafe
        {
            fixed (Byte* pBuffer = buffer)
            {
                return (T)Marshal.PtrToStructure(new IntPtr((void*)&pBuffer[offset]), typeof(T));
            }
        }
    }

The code abocve create a byte array with a login data, from a structure. Is there a way to do serialize/deserialize a buffer array in python? - I have no idea how to do it in python, since I don't see a lot of articles dealing with byte array stuff.

3
  • Hi, I have a project in C# in work, where I saw the use of BufferConverter. I tried searching for information about it online and the only use of it I found is here. Do you know why there is no information about it anywhere? The particular function I am looking for is BufferConverter.ToObject. Thanks in advance :) Commented Nov 10, 2020 at 15:35
  • @Yass What are you trying to do, exactly? Commented Nov 10, 2020 at 15:49
  • Basically just find information / documentation about the BufferConverter. I am having hard time understanding how it works. Commented Nov 17, 2020 at 10:55

1 Answer 1

1

There's a couple ways, sure.

There's the built-in struct module, which requires a little bit of manual work to figure out the format string for your structures.

You can also use a higher-level 3rd party library such as construct (which I can recommend).

With Construct, your structures might look something like

Header = Struct(
    'size' / Int16ub,
    'key' / Int8ub,
    'checksum' / Int8ub,
    'packetId' / Int16ub,
    'clientId' / Int16ub,
    'timestamp' / Int32ub,
)
Login = Struct(
    "header" / Header,
    # ...
)

– a fairly straightforward translation of the C# originals, and given a buffer of data, you can then just do something like

login_data = Login.parse(buffer)
Sign up to request clarification or add additional context in comments.

4 Comments

Thank you! I have a question, when I do pBuffer = header.Header.parse(bytes.fromhex('2000')) I should get pBuffer.test = 32 (since 0020 base 16 = 32 base 10), but Im getting 8192 (0x2000 base 16), why?
You might want Int16ul instead for little-endian.
Oh. It works now. One last question, why i cant do this? I have a p20_Login struct, with Header inside, but when I try: login_buffer = login_struct.p20D_Login.build(dict(header=header, teste=1)) i get ValueError: too many values to unpack (expected 2)
You might wanna ask that as a separate question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.