Upgrading password encryption

01/10/2011 23:39 Kiyono#1
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:
Password handling:
The original decrypting code:
Kinshi's proxy and Immune's source decrypting code:
What I got after trying to convert their decrypting code:

So can I get some help with the password decrypting code?
//edit I guess the title should be decryption... oh well.
01/10/2011 23:59 pro4never#2
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));
        }
    }
01/11/2011 00:05 _tao4229_#3
Buffer.BlockCopy is a .NET method
[Only registered and activated users can see links. Click Here To Register...]
01/11/2011 06:27 .Kinshi#4
System.Buffer.BlockCopy(..);
01/11/2011 17:35 Kiyono#5
Quote:
Originally Posted by pro4never View Post
Here's from my source using same kinda system.

byte[] Password = read from the packet.
Spoiler to make it smaller.
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:
1086/0x43E packet:
01/11/2011 19:35 pro4never#6
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.
01/11/2011 20:04 Kiyono#7
Quote:
Originally Posted by pro4never View Post
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.
01/11/2011 20:11 Basser#8
Quote:
Originally Posted by Kiyono View Post
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?
01/11/2011 20:30 Kiyono#9
Quote:
Originally Posted by Basser View Post
Array Source perhaps?
Seriously, how can that not be the easiest thing to understand?
You misread? I wasn't asking what Array src meant.
01/11/2011 21:39 Basser#10
Quote:
Originally Posted by Kiyono View Post
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..
01/11/2011 21:52 pro4never#11
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))
01/11/2011 22:22 Kiyono#12
Am I that bad in English?
I know how BlockCopy works...
Anyway I got something but it doesn't work >_>

1086/0x43E structure:
1086/0x43E handler:

My decrypting:

This should work but it's still giving me invalid password and it's not my seed being wrong either.
01/12/2011 01:48 pro4never#13
Quote:
Originally Posted by Kiyono View Post
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.
01/12/2011 09:57 samehvan#14
i think the problem is with the szUser , the value u should receive for it is only 16 bytes starting from offset 4
01/12/2011 17:12 Kiyono#15
Quote:
Originally Posted by pro4never View Post
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 View Post
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.