Register for your free account! | Forgot your password?

Go Back   elitepvpers > MMORPGs > Archlord
You last visited: Today at 13:39

  • Please register to post and access all features, it's quick, easy and FREE!

Advertisement



Client Server Cryptography?

Discussion on Client Server Cryptography? within the Archlord forum part of the MMORPGs category.

Reply
 
Old   #1
 
elite*gold: 0
Join Date: Jun 2009
Posts: 72
Received Thanks: 16
Client Server Cryptography?

i was wondering, the communication between alefcient and the game server is encrypted, and alefclient binary seems to use Cryptography API (CNG) with most of its functions like:

BCryptCloseAlgorithmProvider
BCryptCreateHash
BCryptDecrypt
BCryptDeriveKey
BCryptDestroyHash
BCryptDestroyKey
BCryptDestroySecret
BCryptDuplicateHash
BCryptDuplicateKey
BCryptEncrypt
BCryptExportKey
BCryptFinalizeKeyPair
BCryptFinishHash
BCryptFreeBuffer
BCryptGenerateKeyPair
BCryptGenerateSymmetricKey
BCryptGenRandom
BCryptGetProperty
BCryptHashData
BCryptImportKey
BCryptImportKeyPair
BCryptOpenAlgorithmProvider
BCryptSecretAgreement
BCryptSetProperty
BCryptSignHash
BCryptVerifySignature

so do they use SSL with the login process only? to secure the user name - passoword? or do they actually use SSL with all communicated packets?

i used to think that since its an mmorg they wouldnt use SSL with all SEND-RECIVE operations, since that creates a bit of performance issue especially that its not that of a big deal.

its obvious that the packets are encrypted and that the encryption key changes with each (character login) but what kind of encryption is it? the algorithm used? r they using DES? or something else?

i saw that many times upon login i receive a whisper from an RMT site, which is C formatted (and since we receive packets from all players within a certain range that includes info of these players like name-armor ids... i thought that someone already decrypted this thing and uses this packet distribution to whisper the players....)

i thought that many of u who checked this game already would have an idea bout this, i stumbled upon it only yesterday and im curious abit to know.

tx.
_Villain_ is offline  
Old 06/09/2009, 11:15   #2
 
_Emme_'s Avatar
 
elite*gold: 1142
Join Date: Aug 2006
Posts: 2,464
Received Thanks: 1,161
Quote:
byte[] addKey1 = new byte[4];
byte[] addKey2 = new byte[4];
byte[] addResult = new byte[4];
//addKey1.i = 0;
//addKey2.i = 0;
byte[] tempKey = new byte[4];

long LMULer;
// InKey1[0] = 0x20;
// InKey1[1] = 0x5c;
// InKey1[2] = 0x48;
// InKey1[3] = 0xf4;
// InKey2[0] = 0x00;
// InKey2[1] = 0x44;
// InKey2[2] = 0xa6;
// InKey2[3] = 0x2e;

//if (Key3) delete [] Key3;
//if (Key4) delete [] Key4;
Monitor.Enter(this);
m_Key3 = new Byte[256];
m_Key4 = new Byte[256];
for (int x = 0; x < 4; x++)
{
addKey1[x] = InKey1[3 - x];
addKey2[x] = InKey2[3 - x];
}
//cout << "Key1: " << addKey1.i << endl;
//cout << "Key2: " << addKey2.i << endl;
uint Adder1;
uint Adder2;
uint Adder3;
Adder1 = (uint)((addKey1[3] << 24) | (addKey1[2] << 16) | (addKey1[1] << 8) | (addKey1[0]));
Adder2 = (uint)((addKey2[3] << 24) | (addKey2[2] << 16) | (addKey2[1] << 8) | (addKey2[0]));
Adder3 = Adder1 + Adder2;
addResult[0] = (byte)(Adder3 & 0xff);
addResult[1] = (byte)((Adder3 >> 8) & 0xff);
addResult[2] = (byte)((Adder3 >> 16) & 0xff);
addResult[3] = (byte)((Adder3 >> 24) & 0xff);
for (int b = 3; b >= 0; b--)
{
// printf("%.2x ", addResult.c[b]);
tempKey[3 - b] = addResult[b];
}
tempKey[2] = (byte)(tempKey[2] ^ (byte)0x43);
tempKey[3] = (byte)(tempKey[3] ^ (byte)0x21);

for (int b = 0; b < 4; b++)
{
tempKey[b] = (byte)(tempKey[b] ^ InKey1[b]);
}

//Build the 3rd Key
for (int b = 0; b < 256; b++)
{
m_Key3[b] = (byte)(tempKey[3 - (b % 4)] ^ m_Key1[b]);
}


for (int x = 0; x < 4; x++)
{
addResult[x] = tempKey[3 - x];
}
Adder3 = (uint)((addResult[3] << 24) | (addResult[2] << 16) | (addResult[1] << 8) | (addResult[0]));
LMULer = Adder3 * Adder3;
LMULer = LMULer << 32;
LMULer = LMULer >> 32;

Adder3 = Convert.ToUInt32(LMULer & 0xffffffff);

addResult[0] = (byte)(Adder3 & 0xff);
addResult[1] = (byte)((Adder3 >> 8) & 0xff);
addResult[2] = (byte)((Adder3 >> 16) & 0xff);
addResult[3] = (byte)((Adder3 >> 24) & 0xff);

for (int b = 3; b >= 0; b--)
{
tempKey[3 - b] = addResult[b];
}
//Build the 4th Key
for (int b = 0; b < 256; b++)
{
m_Key4[b] = Convert.ToByte(tempKey[3 - (b % 4)] ^ m_Key2[b]);
}
Monitor.Exit(this);

//cout << "Int representation: " << charadd.i << endl;
}

public void ResetCounter()
{
//Monitor.Enter(this);
m_OutCounter = 0;
m_InCounter = 0;
//Monitor.Exit(this);
Found this while I was debugging, hope it helps in some way.
_Emme_ is offline  
Old 06/09/2009, 17:33   #3
 
elite*gold: 0
Join Date: Jun 2009
Posts: 72
Received Thanks: 16
Quote:
Originally Posted by EmmeTheCoder View Post
Found this while I was debugging, hope it helps in some way.
debugging what? i found this match for ur code!!!! (c#)! and it looks more like simple XOR decryption [m_key1-2 seems to be 256 bytes of fixed values] (i used to thinK that they should use XOR since its easier to implement and produces higher performance!!! but the packets in Archlord are encrypted upon each login with random keys, so...!

Code:
public void Encrypt(ref byte[] Data){
	try
            {
            //Monitor.Enter(this);
	for (int b = 0; b < Data.Length; b++)
	{
	        Data[b] = (byte)(Data[b] ^ 0xab);
	        Data[b] = (byte)(Data[b] << 4 | Data[b] >> 4);
	        Data[b] = (byte)(m_Key2[m_OutCounter >> 8] ^ Data[b]);
	        Data[b] = (byte)(m_Key1[m_OutCounter & 0x00ff] ^ Data[b]);
	        m_OutCounter++;
	}        
	//Monitor.Exit(this);
        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }

}

public void Decrypt(ref byte[] Data)
		{
			try
            {
            byte [] Key1;
			byte [] Key2;
			if (m_UseAlt)
			{
				Key1 = m_Key3;
				Key2 = m_Key4;
			}
			else
			{
				Key1 = m_Key1;
				Key2 = m_Key2;
			}
			//Monitor.Enter(this);
			for (int b = 0; b < Data.Length; b++)
			{
				Data[b] = (byte)(Data[b] ^ 0xab);
				Data[b] = (byte)(Data[b] << 4 | Data[b] >> 4);
				Data[b] = (byte)(Key2[m_InCounter >> 8] ^ Data[b]);
				Data[b] = (byte)(Key1[(m_InCounter & 0x00ff)] ^ Data[b]);
				m_InCounter++;
			}
			//Monitor.Exit(this);
        }
        catch (Exception e)
        {
            Console.WriteLine(e.ToString());
        }
		}
_Villain_ is offline  
Old 06/10/2009, 09:29   #4
 
_Emme_'s Avatar
 
elite*gold: 1142
Join Date: Aug 2006
Posts: 2,464
Received Thanks: 1,161
Quote:
public class Cryptographer : object
{
ushort m_InCounter = 0;
ushort m_OutCounter = 0;
bool m_UseAlt = false;
private byte[] m_Key1 = {
0x9D, 0x90, 0x83, 0x8A, 0xD1, 0x8C, 0xE7, 0xF6, 0x25, 0x28, 0xEB, 0x82, 0x99, 0x64, 0x8F, 0x2E,
0x2D, 0x40, 0xD3, 0xFA, 0xE1, 0xBC, 0xB7, 0xE6, 0xB5, 0xD8, 0x3B, 0xF2, 0xA9, 0x94, 0x5F, 0x1E,
0xBD, 0xF0, 0x23, 0x6A, 0xF1, 0xEC, 0x87, 0xD6, 0x45, 0x88, 0x8B, 0x62, 0xB9, 0xC4, 0x2F, 0x0E,
0x4D, 0xA0, 0x73, 0xDA, 0x01, 0x1C, 0x57, 0xC6, 0xD5, 0x38, 0xDB, 0xD2, 0xC9, 0xF4, 0xFF, 0xFE,
0xDD, 0x50, 0xC3, 0x4A, 0x11, 0x4C, 0x27, 0xB6, 0x65, 0xE8, 0x2B, 0x42, 0xD9, 0x24, 0xCF, 0xEE,
0x6D, 0x00, 0x13, 0xBA, 0x21, 0x7C, 0xF7, 0xA6, 0xF5, 0x98, 0x7B, 0xB2, 0xE9, 0x54, 0x9F, 0xDE,
0xFD, 0xB0, 0x63, 0x2A, 0x31, 0xAC, 0xC7, 0x96, 0x85, 0x48, 0xCB, 0x22, 0xF9, 0x84, 0x6F, 0xCE,
0x8D, 0x60, 0xB3, 0x9A, 0x41, 0xDC, 0x97, 0x86, 0x15, 0xF8, 0x1B, 0x92, 0x09, 0xB4, 0x3F, 0xBE,
0x1D, 0x10, 0x03, 0x0A, 0x51, 0x0C, 0x67, 0x76, 0xA5, 0xA8, 0x6B, 0x02, 0x19, 0xE4, 0x0F, 0xAE,
0xAD, 0xC0, 0x53, 0x7A, 0x61, 0x3C, 0x37, 0x66, 0x35, 0x58, 0xBB, 0x72, 0x29, 0x14, 0xDF, 0x9E,
0x3D, 0x70, 0xA3, 0xEA, 0x71, 0x6C, 0x07, 0x56, 0xC5, 0x08, 0x0B, 0xE2, 0x39, 0x44, 0xAF, 0x8E,
0xCD, 0x20, 0xF3, 0x5A, 0x81, 0x9C, 0xD7, 0x46, 0x55, 0xB8, 0x5B, 0x52, 0x49, 0x74, 0x7F, 0x7E,
0x5D, 0xD0, 0x43, 0xCA, 0x91, 0xCC, 0xA7, 0x36, 0xE5, 0x68, 0xAB, 0xC2, 0x59, 0xA4, 0x4F, 0x6E,
0xED, 0x80, 0x93, 0x3A, 0xA1, 0xFC, 0x77, 0x26, 0x75, 0x18, 0xFB, 0x32, 0x69, 0xD4, 0x1F, 0x5E,
0x7D, 0x30, 0xE3, 0xAA, 0xB1, 0x2C, 0x47, 0x16, 0x05, 0xC8, 0x4B, 0xA2, 0x79, 0x04, 0xEF, 0x4E,
0x0D, 0xE0, 0x33, 0x1A, 0xC1, 0x5C, 0x17, 0x06, 0x95, 0x78, 0x9B, 0x12, 0x89, 0x34, 0xBF, 0x3E};

private byte[] m_Key2 = {
0x62, 0x4F, 0xE8, 0x15, 0xDE, 0xEB, 0x04, 0x91, 0x1A, 0xC7, 0xE0, 0x4D, 0x16, 0xE3, 0x7C, 0x49,
0xD2, 0x3F, 0xD8, 0x85, 0x4E, 0xDB, 0xF4, 0x01, 0x8A, 0xB7, 0xD0, 0xBD, 0x86, 0xD3, 0x6C, 0xB9,
0x42, 0x2F, 0xC8, 0xF5, 0xBE, 0xCB, 0xE4, 0x71, 0xFA, 0xA7, 0xC0, 0x2D, 0xF6, 0xC3, 0x5C, 0x29,
0xB2, 0x1F, 0xB8, 0x65, 0x2E, 0xBB, 0xD4, 0xE1, 0x6A, 0x97, 0xB0, 0x9D, 0x66, 0xB3, 0x4C, 0x99,
0x22, 0x0F, 0xA8, 0xD5, 0x9E, 0xAB, 0xC4, 0x51, 0xDA, 0x87, 0xA0, 0x0D, 0xD6, 0xA3, 0x3C, 0x09,
0x92, 0xFF, 0x98, 0x45, 0x0E, 0x9B, 0xB4, 0xC1, 0x4A, 0x77, 0x90, 0x7D, 0x46, 0x93, 0x2C, 0x79,
0x02, 0xEF, 0x88, 0xB5, 0x7E, 0x8B, 0xA4, 0x31, 0xBA, 0x67, 0x80, 0xED, 0xB6, 0x83, 0x1C, 0xE9,
0x72, 0xDF, 0x78, 0x25, 0xEE, 0x7B, 0x94, 0xA1, 0x2A, 0x57, 0x70, 0x5D, 0x26, 0x73, 0x0C, 0x59,
0xE2, 0xCF, 0x68, 0x95, 0x5E, 0x6B, 0x84, 0x11, 0x9A, 0x47, 0x60, 0xCD, 0x96, 0x63, 0xFC, 0xC9,
0x52, 0xBF, 0x58, 0x05, 0xCE, 0x5B, 0x74, 0x81, 0x0A, 0x37, 0x50, 0x3D, 0x06, 0x53, 0xEC, 0x39,
0xC2, 0xAF, 0x48, 0x75, 0x3E, 0x4B, 0x64, 0xF1, 0x7A, 0x27, 0x40, 0xAD, 0x76, 0x43, 0xDC, 0xA9,
0x32, 0x9F, 0x38, 0xE5, 0xAE, 0x3B, 0x54, 0x61, 0xEA, 0x17, 0x30, 0x1D, 0xE6, 0x33, 0xCC, 0x19,
0xA2, 0x8F, 0x28, 0x55, 0x1E, 0x2B, 0x44, 0xD1, 0x5A, 0x07, 0x20, 0x8D, 0x56, 0x23, 0xBC, 0x89,
0x12, 0x7F, 0x18, 0xC5, 0x8E, 0x1B, 0x34, 0x41, 0xCA, 0xF7, 0x10, 0xFD, 0xC6, 0x13, 0xAC, 0xF9,
0x82, 0x6F, 0x08, 0x35, 0xFE, 0x0B, 0x24, 0xB1, 0x3A, 0xE7, 0x00, 0x6D, 0x36, 0x03, 0x9C, 0x69,
0xF2, 0x5F, 0xF8, 0xA5, 0x6E, 0xFB, 0x14, 0x21, 0xAA, 0xD7, 0xF0, 0xDD, 0xA6, 0xF3, 0x8C, 0xD9};
private byte[] m_Key3;
private byte[] m_Key4;

public Cryptographer()
{
}

public void SetKeys(byte[] InKey1, byte[] InKey2)
{
byte[] addKey1 = new byte[4];
byte[] addKey2 = new byte[4];
byte[] addResult = new byte[4];
//addKey1.i = 0;
//addKey2.i = 0;
byte[] tempKey = new byte[4];

long LMULer;
// InKey1[0] = 0x20;
// InKey1[1] = 0x5c;
// InKey1[2] = 0x48;
// InKey1[3] = 0xf4;
// InKey2[0] = 0x00;
// InKey2[1] = 0x44;
// InKey2[2] = 0xa6;
// InKey2[3] = 0x2e;

//if (Key3) delete [] Key3;
//if (Key4) delete [] Key4;
Monitor.Enter(this);
m_Key3 = new Byte[256];
m_Key4 = new Byte[256];
for (int x = 0; x < 4; x++)
{
addKey1[x] = InKey1[3 - x];
addKey2[x] = InKey2[3 - x];
}
//cout << "Key1: " << addKey1.i << endl;
//cout << "Key2: " << addKey2.i << endl;
uint Adder1;
uint Adder2;
uint Adder3;
Adder1 = (uint)((addKey1[3] << 24) | (addKey1[2] << 16) | (addKey1[1] << 8) | (addKey1[0]));
Adder2 = (uint)((addKey2[3] << 24) | (addKey2[2] << 16) | (addKey2[1] << 8) | (addKey2[0]));
Adder3 = Adder1 + Adder2;
addResult[0] = (byte)(Adder3 & 0xff);
addResult[1] = (byte)((Adder3 >> 8) & 0xff);
addResult[2] = (byte)((Adder3 >> 16) & 0xff);
addResult[3] = (byte)((Adder3 >> 24) & 0xff);
for (int b = 3; b >= 0; b--)
{
// printf("%.2x ", addResult.c[b]);
tempKey[3 - b] = addResult[b];
}
tempKey[2] = (byte)(tempKey[2] ^ (byte)0x43);
tempKey[3] = (byte)(tempKey[3] ^ (byte)0x21);

for (int b = 0; b < 4; b++)
{
tempKey[b] = (byte)(tempKey[b] ^ InKey1[b]);
}

//Build the 3rd Key
for (int b = 0; b < 256; b++)
{
m_Key3[b] = (byte)(tempKey[3 - (b % 4)] ^ m_Key1[b]);
}


for (int x = 0; x < 4; x++)
{
addResult[x] = tempKey[3 - x];
}
Adder3 = (uint)((addResult[3] << 24) | (addResult[2] << 16) | (addResult[1] << 8) | (addResult[0]));
LMULer = Adder3 * Adder3;
LMULer = LMULer << 32;
LMULer = LMULer >> 32;

Adder3 = Convert.ToUInt32(LMULer & 0xffffffff);

addResult[0] = (byte)(Adder3 & 0xff);
addResult[1] = (byte)((Adder3 >> 8) & 0xff);
addResult[2] = (byte)((Adder3 >> 16) & 0xff);
addResult[3] = (byte)((Adder3 >> 24) & 0xff);

for (int b = 3; b >= 0; b--)
{
tempKey[3 - b] = addResult[b];
}
//Build the 4th Key
for (int b = 0; b < 256; b++)
{
m_Key4[b] = Convert.ToByte(tempKey[3 - (b % 4)] ^ m_Key2[b]);
}
Monitor.Exit(this);

//cout << "Int representation: " << charadd.i << endl;
}

public void DisplayCounters()
{
General.WriteLine("InCounter: " + m_InCounter);
General.WriteLine("OutCounter: " + m_OutCounter);
}

public void ResetCounter()
{
//Monitor.Enter(this);
m_OutCounter = 0;
m_InCounter = 0;
//Monitor.Exit(this);
}

public void EnableAlternateKeys()
{
//Monitor.Enter(this);
m_UseAlt = true;
//m_InCounter = 0;
m_OutCounter = 0;
//Monitor.Exit(this);
}

public void DisableAlternateKeys()
{
//Monitor.Enter(this);
m_UseAlt = false;
m_InCounter = 0;
m_OutCounter = 0;
//Monitor.Exit(this);
}

public void Encrypt(ref byte[] Data)
{
try
{
//Monitor.Enter(this);
for (int b = 0; b < Data.Length; b++)
{
Data[b] = (byte)(Data[b] ^ 0xab);
Data[b] = (byte)(Data[b] << 4 | Data[b] >> 4);
Data[b] = (byte)(m_Key2[m_OutCounter >> 8] ^ Data[b]);
Data[b] = (byte)(m_Key1[m_OutCounter & 0x00ff] ^ Data[b]);
m_OutCounter++;
}
//General.WriteLine("OutCounter = " + m_OutCounter);
//Monitor.Exit(this);
}
catch (Exception e)
{
General.WriteLine(e.ToString());
}

}

public void Decrypt(ref byte[] Data)
{
try
{
byte[] Key1;
byte[] Key2;
if (m_UseAlt)
{
Key1 = m_Key3;
Key2 = m_Key4;
}
else
{
Key1 = m_Key1;
Key2 = m_Key2;
}
//Monitor.Enter(this);
for (int b = 0; b < Data.Length; b++)
{
Data[b] = (byte)(Data[b] ^ 0xab);
Data[b] = (byte)(Data[b] << 4 | Data[b] >> 4);
Data[b] = (byte)(Key2[m_InCounter >> 8] ^ Data[b]);
Data[b] = (byte)(Key1[(m_InCounter & 0x00ff)] ^ Data[b]);
m_InCounter++;
}
//Monitor.Exit(this);
}
catch (Exception e)
{
General.WriteLine(e.ToString());
}
}
public void PeekDecrypt(ref byte[] Data)
{
//Monitor.Enter(this);
for (int b = 0; b < Data.Length; b++)
{
Data[b] = (byte)(m_Key1[((m_InCounter + b) & 0x00ff)] ^ Data[b]);
Data[b] = (byte)(m_Key2[(m_InCounter + b) >> 8] ^ Data[b]);
Data[b] = (byte)(Data[b] << 4 | Data[b] >> 4);
Data[b] = (byte)(Data[b] ^ 0xab);
}
//Monitor.Exit(this);
}

}
There, try that.
_Emme_ is offline  
Old 06/10/2009, 19:46   #5
 
elite*gold: 0
Join Date: May 2009
Posts: 1
Received Thanks: 0
Hi, i was research logining data transfers between client and server. i discovered that server and client are sent to each other a keys that uses for crypt.

i was catch a packets using sniffer. and create a c# app, that accept data from client and return packets that i was captured.

results that it gives to me: client each time send different data arrays (but they not totally different), and my app send each time the same data, and client recognize it as a normal server.

so i think that in game process there are two keys. one for client and one for server, and they are transfered in login process (but i don't know what to look).

Your ideas about it?
JPHcom is offline  
Old 06/10/2009, 23:29   #6
 
Newbb's Avatar
 
elite*gold: 20
Join Date: Oct 2008
Posts: 2,384
Received Thanks: 371
interresting, ill keep my eye on this one, though i dont know annything about it..
Newbb is offline  
Old 07/13/2009, 14:55   #7
 
elite*gold: 0
Join Date: May 2009
Posts: 1
Received Thanks: 0
possible to compile the file?
rona is offline  
Old 07/14/2009, 13:32   #8
 
elite*gold: 0
Join Date: Jun 2008
Posts: 14
Received Thanks: 0
It's not DES or 3DES, The encryption algorithm is a 'broken' version, of a popular fishy (clue!) block cipher
Marveh is offline  
Reply


Similar Threads Similar Threads
[SUCHE]unterstützung beim bearbeiten von meinen server( client und server modder )
08/26/2010 - Metin2 Private Server - 1 Replies
brauch hilfe für meinen zukünftigen root server paar sachen die in epvp unbekannt sind die will ich in meinen server haben aber dafür brauch cih eure hilfe danke
[Client Modden]Mehrer Server auf 1 client
05/23/2010 - Metin2 Private Server - 12 Replies
Hey Wie die überschrift schon sagt würde ich gerne wissen wie mann mehrer Server In einem Client Hinkriegt :D wer mir dass sagt bekommt mehrerer THX und darf schonmal auf die Beta Version Von Dem dyndns Server SkyLand2 :D Aber nur die Mir helfen können :D Hoffe Dass War ein Angebot ;) MFG Megaload HAb die serverinfo.py rein editiert wo soll ich da was ändern dass mann dan auf mehrer client connecten kann stadt auf einem??? Also das mann dann mehrer Client sieht auf denen mann dann auch...



All times are GMT +2. The time now is 13:39.


Powered by vBulletin®
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
SEO by vBSEO ©2011, Crawlability, Inc.
This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Support | Contact Us | FAQ | Advertising | Privacy Policy | Terms of Service | Abuse
Copyright ©2024 elitepvpers All Rights Reserved.