elitepvpers

elitepvpers (https://www.elitepvpers.com/forum/)
-   CO2 Private Server (https://www.elitepvpers.com/forum/co2-private-server/)
-   -   Upgrading password encryption (https://www.elitepvpers.com/forum/co2-private-server/946384-upgrading-password-encryption.html)

Kiyono 01/10/2011 23:39

Upgrading password encryption
 
Might as well post it here. I'm trying to upgrade the password encryption from Hybrid's 5135 source to be used with a 5250 client but it's kinda giving me a headache.
Well I'm confused.

Some information:
Spoiler:
Code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConquerServer_v2.Client
{
    public sealed class RC5Exception : Exception
    {
        public RC5Exception(string message) : base(message) { }
    }

    public sealed class RC5
    {
        private readonly uint[] _bufKey = new uint[4];
        private readonly uint[] _bufSub = new uint[26];

        public RC5(byte[] data)
        {
            if (data.Length != 16) throw new RC5Exception("Invalid data length. Must be 16 bytes");
            const uint p32 = 0xB7E15163;
            const uint q32 = 0x61C88647;
            uint offsetA = 0, offsetB = 0, A = 0, B = 0;
            for (int i = 0; i < 4; i++)
                _bufKey[i] = (uint)(data[i * 4] + (data[i * 4 + 1] << 8) + (data[i * 4 + 2] << 16) + (data[i * 4 + 3] << 24));
            _bufSub[0] = p32;
            for (int i = 1; i < 26; i++)
            {
                _bufSub[i] = _bufSub[i - 1] - q32;
            }
            for (int s = 1; s <= 78; s++)
            {
                _bufSub[offsetA] = LeftRotate(_bufSub[offsetA] + A + B, 3);
                A = _bufSub[offsetA];
                offsetA = (offsetA + 1) % 0x1A;
                _bufKey[offsetB] = LeftRotate(_bufKey[offsetB] + A + B, (int)(A + B));
                B = _bufKey[offsetB];
                offsetB = (offsetB + 1) % 4;
            }
        }
        public byte[] Decrypt(byte[] data)
        {
            if (data.Length % 8 != 0) throw new RC5Exception("Invalid password length. Must be multiple of 8");
            int nLen = data.Length / 8 * 8;
            if (nLen <= 0) throw new RC5Exception("Invalid password length. Must be greater than 0 bytes.");
            uint[] bufData = new uint[data.Length / 4];
            for (int i = 0; i < data.Length / 4; i++)
                bufData[i] = (uint)(data[i * 4] + (data[i * 4 + 1] << 8) + (data[i * 4 + 2] << 16) + (data[i * 4 + 3] << 24));
            for (int i = 0; i < nLen / 8; i++)
            {
                uint ld = bufData[2 * i];
                uint rd = bufData[2 * i + 1];
                for (int j = 12; j >= 1; j--)
                {
                    rd = RightRotate((rd - _bufSub[2 * j + 1]), (int)ld) ^ ld;
                    ld = RightRotate((ld - _bufSub[2 * j]), (int)rd) ^ rd;
                }
                uint B = rd - _bufSub[1];
                uint A = ld - _bufSub[0];
                bufData[2 * i] = A;
                bufData[2 * i + 1] = B;
            }
            byte[] result = new byte[bufData.Length * 4];
            for (int i = 0; i < bufData.Length; i++)
            {
                result[i * 4] = (byte)bufData[i];
                result[i * 4 + 1] = (byte)(bufData[i] >> 8);
                result[i * 4 + 2] = (byte)(bufData[i] >> 16);
                result[i * 4 + 3] = (byte)(bufData[i] >> 24);
            }
            return result;
        }

        public byte[] Encrypt(byte[] data)
        {
            if (data.Length % 8 != 0) throw new RC5Exception("Invalid password length. Must be multiple of 8");
            int nLen = data.Length / 8 * 8;
            if (nLen <= 0) throw new RC5Exception("Invalid password length. Must be greater than 0 bytes.");
            uint[] bufData = new uint[data.Length / 4];
            for (int i = 0; i < data.Length / 4; i++)
                bufData[i] = (uint)(data[i * 4] + (data[i * 4 + 1] << 8) + (data[i * 4 + 2] << 16) + (data[i * 4 + 3] << 24));
            for (int i = 0; i < nLen / 8; i++)
            {
                uint A = bufData[i * 2];
                uint B = bufData[i * 2 + 1];
                uint le = A + _bufSub[0];
                uint re = B + _bufSub[1];
                for (int j = 1; j <= 12; j++)
                {
                    le = LeftRotate((le ^ re), (int)re) + _bufSub[j * 2];
                    re = LeftRotate((re ^ le), (int)le) + _bufSub[j * 2 + 1];
                }
                bufData[i * 2] = le;
                bufData[i * 2 + 1] = re;
            }
            byte[] result = new byte[bufData.Length * 4];
            for (int i = 0; i < bufData.Length; i++)
            {
                result[i * 4] = (byte)bufData[i];
                result[i * 4 + 1] = (byte)(bufData[i] >> 8);
                result[i * 4 + 2] = (byte)(bufData[i] >> 16);
                result[i * 4 + 3] = (byte)(bufData[i] >> 24);
            }
            return result;
        }

        internal static uint LeftRotate(uint dwVar, int dwOffset)
        {
            return (dwVar << (dwOffset & 0x1F) | dwVar >> 0x20 - (dwOffset & 0x1F));
        }

        internal static uint RightRotate(uint dwVar, int dwOffset)
        {
            return (dwVar >> (dwOffset & 0x1F) | dwVar << 0x20 - (dwOffset & 0x1F));
        }
    }
    public sealed class ConquerPasswordCryptpographer
    {
        private readonly byte[] key = new byte[0x200];
        private static byte[] scanCodeToVirtualKeyMap = new byte[] {
            0, 0x1b, 0x31, 50, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30, 0xbd, 0xbb, 8, 9,
            0x51, 0x57, 0x45, 0x52, 0x54, 0x59, 0x55, 0x49, 0x4f, 80, 0xdb, 0xdd, 13, 0x11, 0x41, 0x53,
            0x44, 70, 0x47, 0x48, 0x4a, 0x4b, 0x4c, 0xba, 0xc0, 0xdf, 0x10, 0xde, 90, 0x58, 0x43, 0x56,
            0x42, 0x4e, 0x4d, 0xbc, 190, 0xbf, 0x10, 0x6a, 0x12, 0x20, 20, 0x70, 0x71, 0x72, 0x73, 0x74,
            0x75, 0x76, 0x77, 120, 0x79, 0x90, 0x91, 0x24, 0x26, 0x21, 0x6d, 0x25, 12, 0x27, 0x6b, 0x23,
            40, 0x22, 0x2d, 0x2e, 0x2c, 0, 220, 0x7a, 0x7b, 12, 0xee, 0xf1, 0xea, 0xf9, 0xf5, 0xf3,
            0, 0, 0xfb, 0x2f, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 130, 0x83, 0x84, 0x85, 0x86, 0xed,
            0, 0xe9, 0, 0xc1, 0, 0, 0x87, 0, 0, 0, 0, 0xeb, 9, 0, 0xc2, 0
        };
        private static byte[] virtualKeyToScanCodeMap = new byte[] {
            0, 0, 0, 70, 0, 0, 0, 0, 14, 15, 0, 0, 0x4c, 0x1c, 0, 0,
            0x2a, 0x1d, 0x38, 0, 0x3a, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
            0x39, 0x49, 0x51, 0x4f, 0x47, 0x4b, 0x48, 0x4d, 80, 0, 0, 0, 0x54, 0x52, 0x53, 0x63,
            11, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 0, 0, 0, 0,
            0, 30, 0x30, 0x2e, 0x20, 0x12, 0x21, 0x22, 0x23, 0x17, 0x24, 0x25, 0x26, 50, 0x31, 0x18,
            0x19, 0x10, 0x13, 0x1f, 20, 0x16, 0x2f, 0x11, 0x2d, 0x15, 0x2c, 0x5b, 0x5c, 0x5d, 0, 0x5f,
            0x52, 0x4f, 80, 0x51, 0x4b, 0x4c, 0x4d, 0x47, 0x48, 0x49, 0x37, 0x4e, 0, 0x4a, 0x53, 0x35,
            0x3b, 60, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x57, 0x58, 100, 0x65, 0x66, 0x67,
            0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 110, 0x76, 0, 0, 0, 0, 0, 0, 0, 0,
            0x45, 70, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0x2a, 0x36, 0x1d, 0x1d, 0x38, 0x38, 0x6a, 0x69, 0x67, 0x68, 0x65, 0x66, 50, 0x20, 0x2e, 0x30,
            0x19, 0x10, 0x24, 0x22, 0x6c, 0x6d, 0x6b, 0x21, 0, 0, 0x27, 13, 0x33, 12, 0x34, 0x35,
            40, 0x73, 0x7e, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1a, 0x56, 0x1b, 0x2b, 0x29,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0x71, 0x5c, 0x7b, 0, 0x6f, 90, 0,
            0, 0x5b, 0, 0x5f, 0, 0x5e, 0, 0, 0, 0x5d, 0, 0x62, 0, 0, 0, 0
        };

        public ConquerPasswordCryptpographer(string key)
        {
            int num = 0;
            foreach (byte num2 in Encoding.ASCII.GetBytes(key))
            {
                num += num2;
            }
            MSVCRT.srand(num);
            byte[] buffer = new byte[0x10];
            for (int i = 0; i < 0x10; i++)
            {
                buffer[i] = (byte)MSVCRT.rand();
            }
            for (int j = 1; j < 0x100; j++)
            {
                this.key[j * 2] = (byte)j;
                this.key[(j * 2) + 1] = (byte)(j ^ buffer[j & 15]);
            }
            for (int k = 1; k < 0x100; k++)
            {
                for (int m = 1 + k; m < 0x100; m++)
                {
                    if (this.key[(k * 2) + 1] < this.key[(m * 2) + 1])
                    {
                        this.key[k * 2] = (byte)(this.key[k * 2] ^ this.key[m * 2]);
                        this.key[m * 2] = (byte)(this.key[m * 2] ^ this.key[k * 2]);
                        this.key[k * 2] = (byte)(this.key[k * 2] ^ this.key[m * 2]);
                        this.key[(k * 2) + 1] = (byte)(this.key[(k * 2) + 1] ^ this.key[(m * 2) + 1]);
                        this.key[(m * 2) + 1] = (byte)(this.key[(m * 2) + 1] ^ this.key[(k * 2) + 1]);
                        this.key[(k * 2) + 1] = (byte)(this.key[(k * 2) + 1] ^ this.key[(m * 2) + 1]);
                    }
                }
            }
        }

        public byte[] Decrypt(byte[] data)
        {
            byte[] buffer = new byte[data.Length];
            for (int i = 0; i < data.Length; i++)
            {
                bool flag = false;
                if (data[i] == 0)
                {
                    return buffer;
                }
                byte index = this.key[data[i] * 2];
                if (index > 0x80)
                {
                    index = (byte)(this.key[data[i] * 2] - 0x80);
                    flag = true;
                }
                buffer[i] = (byte)(buffer[i] + scanCodeToVirtualKeyMap[index]);
                if ((!flag && (buffer[i] >= 0x41)) && (buffer[i] <= 90))
                {
                    buffer[i] = (byte)(buffer[i] + 0x20);
                }
            }
            return buffer;
        }

        public byte[] Encrypt(byte[] data)
        {
            byte[] buffer = new byte[data.Length];
            for (int i = 0; i < data.Length; i++)
            {
                byte num2 = data[i];
                if ((data[i] >= 0x61) && (data[i] <= 0x7a))
                {
                    data[i] = (byte)(data[i] - 0x20);
                }
                byte num3 = virtualKeyToScanCodeMap[data[i]];
                if ((num2 >= 0x41) && (num2 <= 90))
                {
                    num3 = (byte)(num3 + 0x80);
                }
                for (byte j = 0; j <= 0xff; j = (byte)(j + 1))
                {
                    byte num5 = this.key[j * 2];
                    if (num5 == num3)
                    {
                        buffer[i] = j;
                        break;
                    }
                }
            }
            return buffer;
        }
    }
}

Password handling:
Spoiler:
Code:

case LoginPacket.cType: //1086 || 0x43E
                        {
                            LoginPacket* login = (LoginPacket*)pReceived;
                            if (Received.Length == LoginPacket.cSize)
                            {
      [b]I guess is what should be replaced [/b]                                PasswordCrypter.Decrypt((uint*)login->szPassword);

                                Client.Account = login->User;
                                Client.Password = login->Password;

                                Client.AuthID = ServerDatabase.ValidAccount(Client.Account, Client.Password);
                                int PermanentBan = ServerDatabase.PermanentBan(Client.Account);
                                AuthResponsePacket resp = AuthResponsePacket.Create();

                                if (PermanentBan == 2 && pReceived[131] == 0xFF)
                                {
                                    ServerDatabase.AddFullPermanentBan(Client.Account);
                                }
                                else if (PermanentBan == 4)
                                {
                                    ServerDatabase.RemovePermanentBan(Client.Account);
                                }

                                if (Client.AuthID != 0)
                                {
                                    if (PermanentBan == 2)
                                        resp.Type = 0x41E;
                                    else if (PermanentBan == 4)
                                    {
                                        resp.Type = 0x41D;
                                    }
                                    resp.IPAddress = "192.168.1.150";
                                    resp.Key1 = Client.AuthID;
                                    resp.Key2 = (uint)Client.Password.GetHashCode();
                                    resp.Port = 5816;
                                    ServerDatabase.AddAuthData(Client);
                                }
                                else
                                {
                                    resp.Key1 = 1;
                                    BruteforceProtection.AddWatch(nClient.IP);
                                }
                                Client.Send(&resp);
                            }
                            else
                            {
                                nClient.Disconnect(false);
                            }
                            break;
                        }

The original decrypting code:
Spoiler:
Code:

public unsafe static sbyte* Decrypt(uint* Password)
        {
            uint temp1, temp2;
            for (sbyte i = 1; i >= 0; i--)
            {
                temp1 = *((uint*)(Password + (i * 2 + 1)));
                temp2 = *((uint*)(Password + (i * 2)));
                for (sbyte i2 = 11; i2 >= 0; i2--)
                {
                    temp1 = (uint)Assembler.RollRight(temp1 - ConquerKeys.PasswordKey[i2 * 2 + 7], (byte)temp2, 32) ^ temp2;
                    temp2 = (uint)Assembler.RollRight(temp2 - ConquerKeys.PasswordKey[i2 * 2 + 6], (byte)temp1, 32) ^ temp1;
                }
                *((uint*)Password + (i * 2 + 1)) = temp1 - ConquerKeys.PasswordKey[5];
                *((uint*)Password + (i * 2)) = temp2 - ConquerKeys.PasswordKey[4];
            }
            return (sbyte*)Password;
        }

Kinshi's proxy and Immune's source decrypting code:
Spoiler:
Immune:
Code:

public string ToString(LoginRequest Request)
        {
            msvcrt.msvcrt.srand(this.GeneratedSeed);
            var rc5Key = new byte[0x10];
            for (int i = 0; i < 0x10; i++)
                rc5Key[i] = (byte)msvcrt.msvcrt.rand();
            string Password1 = Encoding.ASCII.GetString(Request.Packet, 132, 16).Trim((char)0x0000);
            this.EncryptedPassword = new byte[16];
            Buffer.BlockCopy(Request.Packet, 132, this.EncryptedPassword, 0, 16);
                return Encoding.ASCII.GetString(
                              (new ConquerPasswordCryptpographer(Request.Account).Decrypt(
                              (new RC5(rc5Key)).Decrypt(this.EncryptedPassword))));
        }

Kinshi:
Code:

public String DecryptPassword(UInt32 key, String account, Byte[] packet)
        {
            Native.srand((int)key);
            var rc5Key = new byte[0x10];
            for (int i = 0; i < 0x10; i++)
                rc5Key[i] = (byte)Native.rand();
            Byte[] originalPassword = new byte[16];
            Buffer.BlockCopy(packet, 132, originalPassword, 0, 16);
            return Encoding.ASCII.GetString(
                (new ConquerPasswordCryptpographer(account).Decrypt(
                    (new RC5(rc5Key)).Decrypt(originalPassword))));
        }

What I got after trying to convert their decrypting code:
Spoiler:
Code:

public string DecryptPassword(LoginPacket Request)
        {
            MSVCRT.srand(Seed);
            var rc5Key = new byte[0x10];
            for (int i = 0; i < 0x10; i++)
                rc5Key[i] = (byte)MSVCRT.rand();
            byte[] EncryptedPassword = new byte[16];
            [b]Can't seem to find an equivalent for this in the source[/b] Buffer.BlockCopy(Request.Packet, 132, EncryptedPassword, 0, 16);
            return Encoding.ASCII.GetString(
                          (new ConquerPasswordCryptpographer(Request.User).Decrypt(
                          (new RC5(rc5Key)).Decrypt(EncryptedPassword))));
        }


So can I get some help with the password decrypting code?
//edit I guess the title should be decryption... oh well.

pro4never 01/10/2011 23:59

Here's from my source using same kinda system.

byte[] Password = read from the packet.

Code:

string Pass;
            msvcrt.msvcrt.srand(Client.PassSeed);
            var rc5Key = new byte[0x10];
            for (int i = 0; i < 0x10; i++)
                rc5Key[i] = (byte)msvcrt.msvcrt.rand();
            ConquerPasswordCryptpographer A = new ConquerPasswordCryptpographer(User);
            Encryption.RC5 B = new Encryption.RC5(rc5Key);
            Pass = Encoding.ASCII.GetString(
                  (new ConquerPasswordCryptpographer(User).Decrypt(new Encryption.RC5(rc5Key).Decrypt(Password))));
            Pass = Pass.Replace("\0", "");

I just use the released liberate cryptography dll, msvcrt dll and then the following pass crypt class.

Code:

public sealed class RC5Exception : Exception
    {
        public RC5Exception(string message) : base(message) { }
    }

    public sealed class RC5
    {
        private readonly uint[] _bufKey = new uint[4];
        private readonly uint[] _bufSub = new uint[26];

        public RC5(byte[] data)
        {
            if (data.Length != 16) throw new RC5Exception("Invalid data length. Must be 16 bytes");
            const uint p32 = 0xB7E15163;
            const uint q32 = 0x61C88647;
            uint offsetA = 0, offsetB = 0, A = 0, B = 0;
            for (int i = 0; i < 4; i++)
                _bufKey[i] = (uint)(data[i * 4] + (data[i * 4 + 1] << 8) + (data[i * 4 + 2] << 16) + (data[i * 4 + 3] << 24));
            _bufSub[0] = p32;
            for (int i = 1; i < 26; i++)
            {
                _bufSub[i] = _bufSub[i - 1] - q32;
            }
            for (int s = 1; s <= 78; s++)
            {
                _bufSub[offsetA] = LeftRotate(_bufSub[offsetA] + A + B, 3);
                A = _bufSub[offsetA];
                offsetA = (offsetA + 1) % 0x1A;
                _bufKey[offsetB] = LeftRotate(_bufKey[offsetB] + A + B, (int)(A + B));
                B = _bufKey[offsetB];
                offsetB = (offsetB + 1) % 4;
            }
        }
        public byte[] Decrypt(byte[] data)
        {
            if (data.Length % 8 != 0) throw new RC5Exception("Invalid password length. Must be multiple of 8");
            int nLen = data.Length / 8 * 8;
            if (nLen <= 0) throw new RC5Exception("Invalid password length. Must be greater than 0 bytes.");
            uint[] bufData = new uint[data.Length / 4];
            for (int i = 0; i < data.Length / 4; i++)
                bufData[i] = (uint)(data[i * 4] + (data[i * 4 + 1] << 8) + (data[i * 4 + 2] << 16) + (data[i * 4 + 3] << 24));
            for (int i = 0; i < nLen / 8; i++)
            {
                uint ld = bufData[2 * i];
                uint rd = bufData[2 * i + 1];
                for (int j = 12; j >= 1; j--)
                {
                    rd = RightRotate((rd - _bufSub[2 * j + 1]), (int)ld) ^ ld;
                    ld = RightRotate((ld - _bufSub[2 * j]), (int)rd) ^ rd;
                }
                uint B = rd - _bufSub[1];
                uint A = ld - _bufSub[0];
                bufData[2 * i] = A;
                bufData[2 * i + 1] = B;
            }
            byte[] result = new byte[bufData.Length * 4];
            for (int i = 0; i < bufData.Length; i++)
            {
                result[i * 4] = (byte)bufData[i];
                result[i * 4 + 1] = (byte)(bufData[i] >> 8);
                result[i * 4 + 2] = (byte)(bufData[i] >> 16);
                result[i * 4 + 3] = (byte)(bufData[i] >> 24);
            }
            return result;
        }

        public byte[] Encrypt(byte[] data)
        {
            if (data.Length % 8 != 0) throw new RC5Exception("Invalid password length. Must be multiple of 8");
            int nLen = data.Length / 8 * 8;
            if (nLen <= 0) throw new RC5Exception("Invalid password length. Must be greater than 0 bytes.");
            uint[] bufData = new uint[data.Length / 4];
            for (int i = 0; i < data.Length / 4; i++)
                bufData[i] = (uint)(data[i * 4] + (data[i * 4 + 1] << 8) + (data[i * 4 + 2] << 16) + (data[i * 4 + 3] << 24));
            for (int i = 0; i < nLen / 8; i++)
            {
                uint A = bufData[i * 2];
                uint B = bufData[i * 2 + 1];
                uint le = A + _bufSub[0];
                uint re = B + _bufSub[1];
                for (int j = 1; j <= 12; j++)
                {
                    le = LeftRotate((le ^ re), (int)re) + _bufSub[j * 2];
                    re = LeftRotate((re ^ le), (int)le) + _bufSub[j * 2 + 1];
                }
                bufData[i * 2] = le;
                bufData[i * 2 + 1] = re;
            }
            byte[] result = new byte[bufData.Length * 4];
            for (int i = 0; i < bufData.Length; i++)
            {
                result[i * 4] = (byte)bufData[i];
                result[i * 4 + 1] = (byte)(bufData[i] >> 8);
                result[i * 4 + 2] = (byte)(bufData[i] >> 16);
                result[i * 4 + 3] = (byte)(bufData[i] >> 24);
            }
            return result;
        }

        internal static uint LeftRotate(uint dwVar, int dwOffset)
        {
            return (dwVar << (dwOffset & 0x1F) | dwVar >> 0x20 - (dwOffset & 0x1F));
        }

        internal static uint RightRotate(uint dwVar, int dwOffset)
        {
            return (dwVar >> (dwOffset & 0x1F) | dwVar << 0x20 - (dwOffset & 0x1F));
        }
    }


_tao4229_ 01/11/2011 00:05

Buffer.BlockCopy is a .NET method
[Only registered and activated users can see links. Click Here To Register...]

.Kinshi 01/11/2011 06:27

System.Buffer.BlockCopy(..);

Kiyono 01/11/2011 17:35

Quote:

Originally Posted by pro4never (Post 8606548)
Here's from my source using same kinda system.

byte[] Password = read from the packet.
Spoiler to make it smaller.
Spoiler:
Code:

string Pass;
            msvcrt.msvcrt.srand(Client.PassSeed);
            var rc5Key = new byte[0x10];
            for (int i = 0; i < 0x10; i++)
                rc5Key[i] = (byte)msvcrt.msvcrt.rand();
            ConquerPasswordCryptpographer A = new ConquerPasswordCryptpographer(User);
            Encryption.RC5 B = new Encryption.RC5(rc5Key);
            Pass = Encoding.ASCII.GetString(
                  (new ConquerPasswordCryptpographer(User).Decrypt(new Encryption.RC5(rc5Key).Decrypt(Password))));
            Pass = Pass.Replace("\0", "");

I just use the released liberate cryptography dll, msvcrt dll and then the following pass crypt class.

Code:

public sealed class RC5Exception : Exception
    {
        public RC5Exception(string message) : base(message) { }
    }

    public sealed class RC5
    {
        private readonly uint[] _bufKey = new uint[4];
        private readonly uint[] _bufSub = new uint[26];

        public RC5(byte[] data)
        {
            if (data.Length != 16) throw new RC5Exception("Invalid data length. Must be 16 bytes");
            const uint p32 = 0xB7E15163;
            const uint q32 = 0x61C88647;
            uint offsetA = 0, offsetB = 0, A = 0, B = 0;
            for (int i = 0; i < 4; i++)
                _bufKey[i] = (uint)(data[i * 4] + (data[i * 4 + 1] << 8) + (data[i * 4 + 2] << 16) + (data[i * 4 + 3] << 24));
            _bufSub[0] = p32;
            for (int i = 1; i < 26; i++)
            {
                _bufSub[i] = _bufSub[i - 1] - q32;
            }
            for (int s = 1; s <= 78; s++)
            {
                _bufSub[offsetA] = LeftRotate(_bufSub[offsetA] + A + B, 3);
                A = _bufSub[offsetA];
                offsetA = (offsetA + 1) % 0x1A;
                _bufKey[offsetB] = LeftRotate(_bufKey[offsetB] + A + B, (int)(A + B));
                B = _bufKey[offsetB];
                offsetB = (offsetB + 1) % 4;
            }
        }
        public byte[] Decrypt(byte[] data)
        {
            if (data.Length % 8 != 0) throw new RC5Exception("Invalid password length. Must be multiple of 8");
            int nLen = data.Length / 8 * 8;
            if (nLen <= 0) throw new RC5Exception("Invalid password length. Must be greater than 0 bytes.");
            uint[] bufData = new uint[data.Length / 4];
            for (int i = 0; i < data.Length / 4; i++)
                bufData[i] = (uint)(data[i * 4] + (data[i * 4 + 1] << 8) + (data[i * 4 + 2] << 16) + (data[i * 4 + 3] << 24));
            for (int i = 0; i < nLen / 8; i++)
            {
                uint ld = bufData[2 * i];
                uint rd = bufData[2 * i + 1];
                for (int j = 12; j >= 1; j--)
                {
                    rd = RightRotate((rd - _bufSub[2 * j + 1]), (int)ld) ^ ld;
                    ld = RightRotate((ld - _bufSub[2 * j]), (int)rd) ^ rd;
                }
                uint B = rd - _bufSub[1];
                uint A = ld - _bufSub[0];
                bufData[2 * i] = A;
                bufData[2 * i + 1] = B;
            }
            byte[] result = new byte[bufData.Length * 4];
            for (int i = 0; i < bufData.Length; i++)
            {
                result[i * 4] = (byte)bufData[i];
                result[i * 4 + 1] = (byte)(bufData[i] >> 8);
                result[i * 4 + 2] = (byte)(bufData[i] >> 16);
                result[i * 4 + 3] = (byte)(bufData[i] >> 24);
            }
            return result;
        }

        public byte[] Encrypt(byte[] data)
        {
            if (data.Length % 8 != 0) throw new RC5Exception("Invalid password length. Must be multiple of 8");
            int nLen = data.Length / 8 * 8;
            if (nLen <= 0) throw new RC5Exception("Invalid password length. Must be greater than 0 bytes.");
            uint[] bufData = new uint[data.Length / 4];
            for (int i = 0; i < data.Length / 4; i++)
                bufData[i] = (uint)(data[i * 4] + (data[i * 4 + 1] << 8) + (data[i * 4 + 2] << 16) + (data[i * 4 + 3] << 24));
            for (int i = 0; i < nLen / 8; i++)
            {
                uint A = bufData[i * 2];
                uint B = bufData[i * 2 + 1];
                uint le = A + _bufSub[0];
                uint re = B + _bufSub[1];
                for (int j = 1; j <= 12; j++)
                {
                    le = LeftRotate((le ^ re), (int)re) + _bufSub[j * 2];
                    re = LeftRotate((re ^ le), (int)le) + _bufSub[j * 2 + 1];
                }
                bufData[i * 2] = le;
                bufData[i * 2 + 1] = re;
            }
            byte[] result = new byte[bufData.Length * 4];
            for (int i = 0; i < bufData.Length; i++)
            {
                result[i * 4] = (byte)bufData[i];
                result[i * 4 + 1] = (byte)(bufData[i] >> 8);
                result[i * 4 + 2] = (byte)(bufData[i] >> 16);
                result[i * 4 + 3] = (byte)(bufData[i] >> 24);
            }
            return result;
        }

        internal static uint LeftRotate(uint dwVar, int dwOffset)
        {
            return (dwVar << (dwOffset & 0x1F) | dwVar >> 0x20 - (dwOffset & 0x1F));
        }

        internal static uint RightRotate(uint dwVar, int dwOffset)
        {
            return (dwVar >> (dwOffset & 0x1F) | dwVar << 0x20 - (dwOffset & 0x1F));
        }
    }


The thing is that I don't know how to read from the packet in fact that is the only problem I have.
//edit Incase you need it:

1086/0x43E packet handling:
Spoiler:
Code:

case LoginPacket.cType: //1086 || 0x43E
                        {
                            LoginPacket* login = (LoginPacket*)pReceived;
                            if (Received.Length == LoginPacket.cSize)
                            {
                              PasswordCrypter.Decrypt((uint*)login->szPassword);

                                Client.Account = login->User;
                                Client.Password = login->Password;

                                Client.AuthID = ServerDatabase.ValidAccount(Client.Account, Client.Password);
                                int PermanentBan = ServerDatabase.PermanentBan(Client.Account);
                                AuthResponsePacket resp = AuthResponsePacket.Create();

                                if (PermanentBan == 2 && pReceived[131] == 0xFF)
                                {
                                    ServerDatabase.AddFullPermanentBan(Client.Account);
                                }
                                else if (PermanentBan == 4)
                                {
                                    ServerDatabase.RemovePermanentBan(Client.Account);
                                }

                                if (Client.AuthID != 0)
                                {
                                    if (PermanentBan == 2)
                                        resp.Type = 0x41E;
                                    else if (PermanentBan == 4)
                                    {
                                        resp.Type = 0x41D;
                                    }
                                    resp.IPAddress = "192.168.1.150";
                                    resp.Key1 = Client.AuthID;
                                    resp.Key2 = (uint)Client.Password.GetHashCode();
                                    resp.Port = 5816;
                                    ServerDatabase.AddAuthData(Client);
                                }
                                else
                                {
                                    resp.Key1 = 1;
                                    BruteforceProtection.AddWatch(nClient.IP);
                                }
                                Client.Send(&resp);
                            }
                            else
                            {
                                nClient.Disconnect(false);
                            }
                            break;
                        }

1086/0x43E packet:
Spoiler:
Code:

public unsafe struct LoginPacket
    {
        public const ushort cSize = 0x114;
        public const ushort cType = 0x43E;

        public ushort Size;
        public ushort Type;
        public fixed sbyte szUser[128];
        public fixed uint szPassword[32];
        public fixed sbyte szServer[16];

        public string User { get { fixed (sbyte* ptr = szUser) { return new string(ptr); } } }
        public string Server { get { fixed (sbyte* ptr = szServer) { return new string(ptr); } } }
        public string Password { get { fixed (uint* ptr = szPassword) { return new string((sbyte*)ptr); } } }
    }


pro4never 01/11/2011 19:35

Well you have a few options..

#1: use buffer block copy to copy from the destination array into a new one.

#2: use a packet reading method from some other source or write your own...

Here's the readbytes method tannel made that iirc is what I used in my proxy.

Code:

public byte[] ReadBytes(int Count)
        {
            byte[] Val = new byte[Count];
            Buffer.BlockCopy(PData, Position, Val, 0, Count);
            Position += Count;
            return Val;
        }

Therefor you just readbytes the password section of the login packet and run that through the method.

Very simple really... just find the password offset in the packet and you're good to go.


<edit>

taking a glance at your password thing you are trying to read it as a string... that's not what you want to do.

What you need to be doing is reading the bytes of the password into an array, decrypting that array using password crypt and saving the output into a password string.

Kiyono 01/11/2011 20:04

Quote:

Originally Posted by pro4never (Post 8615853)
Well you have a few options..

#1: use buffer block copy to copy from the destination array into a new one.

#2: use a packet reading method from some other source or write your own...

Here's the readbytes method tannel made that iirc is what I used in my proxy.

Code:

public byte[] ReadBytes(int Count)
        {
            byte[] Val = new byte[Count];
            Buffer.BlockCopy(PData, Position, Val, 0, Count);
            Position += Count;
            return Val;
        }

Therefor you just readbytes the password section of the login packet and run that through the method.

Very simple really... just find the password offset in the packet and you're good to go.


<edit>

taking a glance at your password thing you are trying to read it as a string... that's not what you want to do.

What you need to be doing is reading the bytes of the password into an array, decrypting that array using password crypt and saving the output into a password string.

Well about Buffer.BlockCopy, I started but I simply couldn't find what had to be the first value (called Array src or in your case PData) which kinda had me confused.

Basser 01/11/2011 20:11

Quote:

Originally Posted by Kiyono (Post 8616485)
Well about Buffer.BlockCopy, I started but I simply couldn't find what had to be the first value (called Array src or in your case PData) which kinda had me confused.

Array Source perhaps?
Seriously, how can that not be the easiest thing to understand?

Kiyono 01/11/2011 20:30

Quote:

Originally Posted by Basser (Post 8616655)
Array Source perhaps?
Seriously, how can that not be the easiest thing to understand?

You misread? I wasn't asking what Array src meant.

Basser 01/11/2011 21:39

Quote:

Originally Posted by Kiyono (Post 8617040)
You misread? I wasn't asking what Array src meant.

Than what was your asking? Looks like your saying you didn't know what the first parameter is..

pro4never 01/11/2011 21:52

Buffer block copy works as follows iirc

(Source array (copy from main packet), Source offset(where to start reading from the main packet), Destination Array (where you are copying to. The password array), Destination Offset (where to start writing in destination packet), Count (how many bytes to copy over))

Kiyono 01/11/2011 22:22

Am I that bad in English?
I know how BlockCopy works...
Anyway I got something but it doesn't work >_>

1086/0x43E structure:
Spoiler:
Code:

public unsafe struct LoginPacket
    {
        public const ushort cSize = 0x114;
        public const ushort cType = 0x43E;

        public ushort Size;
        public ushort Type;
        public fixed sbyte szUser[128];
        public fixed uint szPassword[32];
        public fixed sbyte szServer[16];

        public string User { get { fixed (sbyte* ptr = szUser) { return new string(ptr); } } }
        public string Server { get { fixed (sbyte* ptr = szServer) { return new string(ptr); } } }
        public string Password { get { fixed (uint* ptr = szPassword) { return new string((sbyte*)ptr); } } }
    }

1086/0x43E handler:
Spoiler:
Code:

static unsafe void Auth_ClientReceive(NetworkClient nClient, byte[] Received)
        {
            AuthClient Client = nClient.Owner as AuthClient;
            Client.Crypto.Decrypt(Received, Received, Received.Length);

            fixed (byte* pReceived = Received)
            {
                ushort Type = *((ushort*)(pReceived + 2));
                switch (Type)
                {
                    case LoginPacket.cType: //1086 || 0x43E
                        {
                            LoginPacket* login = (LoginPacket*)pReceived;
                            if (Received.Length == LoginPacket.cSize)
                            {
                                Client.Decrypt(login->User, Received);
                                //PasswordCrypter.Decrypt((uint*)login->szPassword);
                                Client.Account = login->User;
                                Client.Password = login->Password;
                                Console.WriteLine(Client.Password);

                                Client.AuthID = ServerDatabase.ValidAccount(Client.Account, Client.Password);
                                int PermanentBan = ServerDatabase.PermanentBan(Client.Account);
                                AuthResponsePacket resp = AuthResponsePacket.Create();

                                if (PermanentBan == 2 && pReceived[131] == 0xFF)
                                {
                                    ServerDatabase.AddFullPermanentBan(Client.Account);
                                }
                                else if (PermanentBan == 4)
                                {
                                    ServerDatabase.RemovePermanentBan(Client.Account);
                                }

                                if (Client.AuthID != 0)
                                {
                                    if (PermanentBan == 2)
                                        resp.Type = 0x41E;
                                    else if (PermanentBan == 4)
                                    {
                                        resp.Type = 0x41D;
                                    }
                                    resp.IPAddress = "192.168.1.150";
                                    resp.Key1 = Client.AuthID;
                                    resp.Key2 = (uint)Client.Password.GetHashCode();
                                    resp.Port = 5816;
                                    ServerDatabase.AddAuthData(Client);
                                }
                                else
                                {
                                    resp.Key1 = 1;
                                    BruteforceProtection.AddWatch(nClient.IP);
                                }
                                Client.Send(&resp);
                            }
                            else
                            {
                                nClient.Disconnect(false);
                            }
                            break;
                        }
                }
            }


My decrypting:
Spoiler:
Code:

public string Decrypt(string User, byte[] Packet)
        {
            MSVCRT.srand(gSeed);
            var rc5Key = new byte[0x10];
            for (int i = 0; i < 0x10; i++)
                rc5Key[i] = (byte)MSVCRT.rand();
            Byte[] EncryptedPass = new byte[16];
            Buffer.BlockCopy(Packet, 132, EncryptedPass, 0, 16);
            return Encoding.ASCII.GetString(
                  (new ConquerPasswordCryptpographer(User).Decrypt(new RC5(rc5Key).Decrypt(EncryptedPass))));
        }


This should work but it's still giving me invalid password and it's not my seed being wrong either.

pro4never 01/12/2011 01:48

Quote:

Originally Posted by Kiyono (Post 8613275)
The thing is that I don't know how to read from the packet in fact that is the only problem I have.
//edit Incase you need it:



You say you don't know how to copy from the packet... I just said you make a array to store the password and then block copy to copy the relevant bytes into it and then run the password array through the decryption method to return a string.

Your problem is that at least in the first code you posted it appears as though you are using pointers to read the bytes and make them into a string format.

Keep in mind it's 16 bytes just like every single other non counted string in conquer lol.

samehvan 01/12/2011 09:57

i think the problem is with the szUser , the value u should receive for it is only 16 bytes starting from offset 4

Kiyono 01/12/2011 17:12

Quote:

Originally Posted by pro4never (Post 8620472)
You say you don't know how to copy from the packet... I just said you make a array to store the password and then block copy to copy the relevant bytes into it and then run the password array through the decryption method to return a string.

Your problem is that at least in the first code you posted it appears as though you are using pointers to read the bytes and make them into a string format.

Keep in mind it's 16 bytes just like every single other non counted string in conquer lol.

Well I can't really do anything about the pointer usage since it's what Hybrid coded and I don't know how to change it.
Quote:

Originally Posted by samehvan (Post 8621609)
i think the problem is with the szUser , the value u should receive for it is only 16 bytes starting from offset 4

No it's not the User, I printed it to the console and it showed the correct User.

//edit With:
Client.Password = Client.Decrypt(login->User, Received);
And entering password: 123456789
and the console prints: #<"%♀'$&! which are indeed 9 characters but not the correct ones.

pro4never 01/12/2011 19:17

Quote:

Originally Posted by Kiyono (Post 8626989)
Well I can't really do anything about the pointer usage since it's what Hybrid coded and I don't know how to change it.


No it's not the User, I printed it to the console and it showed the correct User.

//edit With:
Client.Password = Client.Decrypt(login->User, Received);
And entering password: 123456789
and the console prints: #<"%♀'$&! which are indeed 9 characters but not the correct ones.

Well that's your problem right there then. You need to use something else to read the packet into an array rather than into a string.


The simplest way is completely remove what you have there and then simply read from the packet using your own methods.


IE:

byte[] Pass = new byte[16];
Buffer.BlockCopy(Data, StartOfPass, Pass, 0, 16);

Then run pass through the decryption.


or just use any packet reading methods (impulses is sexy, Also a fan of tannel's)

Kiyono 01/12/2011 19:26

Quote:

Originally Posted by pro4never (Post 8629610)
Well that's your problem right there then. You need to use something else to read the packet into an array rather than into a string.


The simplest way is completely remove what you have there and then simply read from the packet using your own methods.


IE:

byte[] Pass = new byte[16];
Buffer.BlockCopy(Data, StartOfPass, Pass, 0, 16);

Then run pass through the decryption.


or just use any packet reading methods (impulses is sexy, Also a fan of tannel's)

I lost you there, how am I reading it into a string?

pro4never 01/12/2011 21:38

public string Password { get { fixed (uint* ptr = szPassword) { return new string((sbyte*)ptr); } } }


It's reading it as a string... for the password encryption to work you want it as a password array of 16 bytes.

I'd say just completely dump that handling of the code. All you really need to do for it is run 3 block copies (then convert two of them to strings using System.Encoding.ASCII.GetString(array); and the other one run through the decryption...

maybe when i'm home later I'll post how mine works (although mine is using tannel's packet reader)

Kiyono 01/12/2011 21:43

Quote:

Originally Posted by pro4never (Post 8632349)
public string Password { get { fixed (uint* ptr = szPassword) { return new string((sbyte*)ptr); } } }


It's reading it as a string... for the password encryption to work you want it as a password array of 16 bytes.

I'd say just completely dump that handling of the code. All you really need to do for it is run 3 block copies (then convert two of them to strings using System.Encoding.ASCII.GetString(array); and the other one run through the decryption...

maybe when i'm home later I'll post how mine works (although mine is using tannel's packet reader)

I'm not using that part at all, it was causing me trouble so I scrapped it.
//edit
PasswordCrypter.Decrypt((uint*)login->szPassword);
Client.Password = login->Password;
That uses szPassword crap, I simply changed it to:
Client.Password = Client.Decrypt(login->User, Received);

Decrypting:
Code:

public string Decrypt(string User, byte[] Packet)
        {
            MSVCRT.srand(gSeed);
            var rc5Key = new byte[0x10];
            for (int i = 0; i < 0x10; i++)
                rc5Key[i] = (byte)MSVCRT.rand();
            Byte[] EncryptedPass = new byte[16];
            Buffer.BlockCopy(Packet, 132, EncryptedPass, 0, 16);
            return Encoding.ASCII.GetString(
                (new ConquerPasswordCryptpographer(User).Decrypt(new RC5(rc5Key).Decrypt(EncryptedPass))));
        }


TaiZer 01/13/2011 02:31

Try to type "test" as password it will decrypt well. If you try "test1" you will get "test#" for the decrypted password.
I have the same problem but I wanted to solve it later -_- lol

Kiyono 01/13/2011 15:29

Quote:

Originally Posted by TaiZer (Post 8634418)
Try to type "test" as password it will decrypt well. If you try "test1" you will get "test#" for the decrypted password.
I have the same problem but I wanted to solve it later -_- lol

Just tried it and this seems to be the case, wonder why only numbers are affected.


All times are GMT +2. The time now is 17:31.

Powered by vBulletin®
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
SEO by vBSEO ©2011, Crawlability, Inc.