Questions about Proxy

08/01/2010 08:53 fm_sparkart#1
I've been a Conquer Online player a few years ago but quit for some unknown reason. Now, I am a programmer (been using C++ for about 5 years now) and thought it would be interesting to write a Conquer Online bot.

I thought that I should write the bot via proxy since I have networking experience and not as much code injection experience.

Right now I have a pretty clear idea how I'll be implementing things but need some help with a few things (since I am not much of a "hacker" type of programmer but more of a "game programmer").

First off, how should I go about setting up the initial connection? I know that there are two steps: Connecting to the "Account Server" and then connecting to the "Game Server". However, I need to direct the client to my program although I am not exactly sure which file CO reads this info from (I'd rather not mess with code injection).

Once I get the client connected to my program I believe I will simply send the packet the client would send to account server via proxy program, receive a response, send the packet back to the client, the packet sends another packet, etc. etc. I am not too sure it is this simple as the packets seem to be encrypted. Also, I would like to know if there are any references to Conquer Online's packet structure as I am not much of a hacker and it will probably take me several months to finish sniffing the packets.

So, I have absolutely no experience with cryptography (except for simple bitwise encryptions). So I was wondering if anyone could shed some light for me with Conquer Online's packet encryption.

I am going to start off slow with the basics such as: movement and environment updates, chat, and inventory updates. Then move on from there. I see a lot of Conquer Online bots but find most of them lacking.


So I am pretty much asking about how to properly connect everything (I am not talking about the basics of networking like binding sockets) and the encryption of Conquer Online.

Also, it would be great if you posted source code of any Conquer Online proxy-based bots (preferably C++, but I can make due with any other language).
08/01/2010 11:54 tanelipe#2
I assume you're going to use C++ for this project right? I'll be more than happy to pass you the cryptography that I have in C++ (I'm not 'native' C++ coder so you could probably improve it.) The authentication cryptography has remained the same so I'm sure that you'll find it lying around here somewhere. As my previous sentences tell you, there's two types of encryption used in conquer, login and game encryption. Login encryption is pretty simple. Game encryption is Blowfish using DHKeyExchange, when you finish login part, the server will send you handshake packet, which has values P, G, ServerIV, ClientIV (Google Blowfish/DHKeyExchange). This is just summary, if you want to know more about it, I'm sure unknownone would be more than happy to help you (You'll have to PM him though)

The login sequence changed a little bit a while back. Basically you have to connect to login server at their end, they will send you a packet with the seed for password cryptography. After that you send the login request to their server. The initial 'seed' packet is no concern unless you're trying to log passwords or make a standalone (which would require you to have knowledge about botchecks, which only handful of people have.)

You're going to have to code inject, or figure out a way for the client to connect to your ipaddress, code injection would be the simplest.

For packet structures you could look at the private server section and a sticky thread made by Korvacs ([Only registered and activated users can see links. Click Here To Register...]) I'm not sure how updated it is because I haven't used it much lately myself, should give you the direction to go on about packets and what they contain.
08/01/2010 12:02 fm_sparkart#3
Thank you for all of the helpful pointers. I'm sure I can get the code injection sorted out. Thank you for the reference for the packet structures. Although they may be outdated, they are better than nothing.
08/01/2010 20:31 pro4never#4
Tried to reply lastnight but phone fucked up.

If you like, there is a thread i started to compile with links and info on how to write a proxy. Not sure how much use you will get seeing as you are doing c++ but alot of it is just theory/explanations

Other than that looks like T covered most of the basics and you seem to know most of how things should work already.

Best of luck on your project
08/02/2010 04:10 fm_sparkart#5
Quote:
Originally Posted by pro4never View Post
Tried to reply lastnight but phone fucked up.

If you like, there is a thread i started to compile with links and info on how to write a proxy. Not sure how much use you will get seeing as you are doing c++ but alot of it is just theory/explanations

Other than that looks like T covered most of the basics and you seem to know most of how things should work already.

Best of luck on your project
You have an excellent guide... I'm surprised I didn't catch it, since it is stickied.
08/02/2010 04:41 pro4never#6
Thanks for the compliment. Keep us updated with your progress. It's always interesting to hear about new people attempting some more serious hacks/tools
08/02/2010 05:14 gabrola#7
This should help Man-in-the-middle attack - Wikipedia, the free encyclopedia
Too lazy to type anymore on a phone :p
08/08/2010 04:57 fm_sparkart#8
I've written something basic that accepts a CO client connection.
Code:
bool Proxy::Accept()
{
    sf::Socket::Status acceptStatus = _listeningSocket.Accept( _client );

    if ( acceptStatus == sf::Socket::Done )
    {
        _client.SetBlocking( false );
        std::cout << "[SYSTEM] - NEW CLIENT CONNECTION ACCEPTED.\n";
        return true;
    }

    return false;
}
Any pointers on how to redirect the client to connect to the proxy?
08/08/2010 05:11 pro4never#9
Use null's loader to make it connect to proxy ip for login server, you edit the auth response packet to make the client connect to the proxy for game server.
08/08/2010 05:17 cod235#10
spawm
08/08/2010 09:41 fm_sparkart#11
Quote:
Originally Posted by pro4never View Post
Use null's loader to make it connect to proxy ip for login server, you edit the auth response packet to make the client connect to the proxy for game server.
I thanked the wrong post, but oh well (this was the post I meant to thank).

I've done some searching before and found an alternative method which involves a "decrypted server.dat".

Which of the two do you think I should lean on?

edit:
I also stumbled across the following for which I believe is the encryption for the authentication routine: [Only registered and activated users can see links. Click Here To Register...]

What's going on in there? I read somewhere that the authentication just uses RC5, so I am guessing that is what it is or is it just a non-general simple encryption algorithm.

Also, with the initial packet containing the "password seed", what's this seed for? Is there any reason I cannot simply send this packet to the client without first decrypting it then re-encrypting?
08/08/2010 12:13 tanelipe#12
You can send the initial packet to the client, without decrypting it, you can do this for all authentication packets if you wish. However if you do that, you must have method to make the client connect() to your loopback address because one of the authentication packets contains the game address and port which they'll use to connect to game server. You will have to do some editing to conquer.exe because I don't think they allow to use loopback address in server.dat nor the authentication response packet.

Well this is the only way I personally know, I'm sure that more advanced users could shed some light into this.

Authentication routine is as follows

PHP Code:
public class AuthenticationCipher IPacketCipher
    
{
        
#region AuthenticationCipher.Variables
        
public ushort EncryptCounter 0;
        public 
ushort DecryptCounter 0;
        public 
byte[] Key1Key2;
        
#endregion
        #region Initialization method
        
public void Init()
        {
            
Key1 = new byte[256];
            
Key2 = new byte[256];
            
byte iKeyOne 0x9D;
            
byte iKeyTwo 0x62;
            for (
ushort i 0256i++)
            {
                
Key1[i] = iKeyOne;
                
Key2[i] = iKeyTwo;
                
iKeyOne = (byte)((0x0F + (byte)(iKeyOne 0xFA)) * iKeyOne 0x13);
                
iKeyTwo = (byte)((0x79 - (byte)(iKeyTwo 0x5C)) * iKeyTwo 0x6D);
            }
            
DecryptCounter 0;
            
EncryptCounter 0;
        }
        
#endregion
        #region Encrypt methods
        
public void Encrypt(byte[] Packet)
        {
            for (
ushort i 0Packet.Lengthi++)
            {
                
Packet[i] = (byte)(Packet[i] ^ 0xAB);
                
Packet[i] = (byte)((Packet[i] << 4) | (Packet[i] >> 4));
                
Packet[i] = (byte)(Key2[EncryptCounter >> 8] ^ Packet[i]);
                
Packet[i] = (byte)(Key1[EncryptCounter 0xFF] ^ Packet[i]);
                
EncryptCounter++;
            }
        }
        public 
void IEncrypt(byte[] Packet)
        {
            for (
ushort i 0Packet.Lengthi++)
            {
                
Packet[i] = (byte)(Key1[EncryptCounter 0xFF] ^ Packet[i]);
                
Packet[i] = (byte)(Key2[EncryptCounter >> 8] ^ Packet[i]);
                
Packet[i] = (byte)(Packet[i] >> Packet[i] << 4);
                
Packet[i] = (byte)(Packet[i] ^ 0xAB);
                
EncryptCounter++;
            }
        }
        
#endregion
        #region Decrypt methods
        
public void Decrypt(byte[] Packet)
        {
            for (
ushort i 0Packet.Lengthi++)
            {
                
Packet[i] = (byte)(Packet[i] ^ 0xAB);
                
Packet[i] = (byte)((Packet[i] << 4) | (Packet[i] >> 4));
                
Packet[i] = (byte)(Key2[DecryptCounter >> 8] ^ Packet[i]);
                
Packet[i] = (byte)(Key1[DecryptCounter 0xFF] ^ Packet[i]);
                
DecryptCounter++;
            }
        }
        public 
void IDecrypt(byte[] Packet)
        {
            for (
ushort i 0Packet.Lengthi++)
            {
                
Packet[i] = (byte)(Key1[DecryptCounter 0xFF] ^ Packet[i]);
                
Packet[i] = (byte)(Key2[DecryptCounter >> 8] ^ Packet[i]);
                
Packet[i] = (byte)((Packet[i] >> 4) | (Packet[i] << 4));
                
Packet[i] = (byte)(Packet[i] ^ 0xAB);
                
DecryptCounter++;
            }
        }
        
#endregion
    

and IPacketCipher is as follows, sorry about the bad naming (IDecrypt,IEncrypt the interface gives them proper meanings)

PHP Code:
 public interface IPacketCipher
    
{
        
/// <summary>
        /// Init() must be called before using any of the other methods.
        /// </summary>
        
void Init();
        
/// <summary>
        /// [Proxy -> Client, Encrypt]
        /// </summary>
        
void Encrypt(byte[] Packet);
        
/// <summary>
        /// [Client -> Proxy, Decrypt]
        /// </summary>
        
void Decrypt(byte[] Packet);
        
/// <summary>
        /// [Proxy -> Server, Encrypt]
        /// </summary>
        
void IEncrypt(byte[] Packet);
        
/// <summary>
        /// [Server -> Proxy, Decrypt]
        /// </summary>
        
void IDecrypt(byte[] Packet);
    } 
08/08/2010 12:28 fm_sparkart#13
Okay, to my understanding.... as soon as I get my proxy to connect to the authentication server, an 8 byte sized packet is sent (which supposedly holds the 'password seed'). What do I need this information for? Can I simply relay this packet to the client without decrypting to figure out what this 'password seed' is?

Your authentication routine is nice, but how is it encrypting/decrypting? Is that RC5 encryption? Sorry but I am not heavily experienced with encryption and I would like to know what exactly is going on in those encrypting/decrypting methods during the authentication routine.
08/08/2010 12:38 tanelipe#14
To be honest, I'm not sure what encryption that is. It's probably TQs own variation of simple XOR encryption. The old password cryptography used modified RC5, and it still does with some extra layers of cryptography. You can check @ unknowones posts, not sure which one was it.

You don't need the 'seed packet' for anything. It's only used to seed the new password cryptography, which, unless you want to log your passwords, has no usage. So yes, you can just forward it to the client.
08/08/2010 12:49 fm_sparkart#15
Quote:
Originally Posted by tanelipe View Post
To be honest, I'm not sure what encryption that is. It's probably TQs own variation of simple XOR encryption. The old password cryptography used modified RC5, and it still does with some extra layers of cryptography. You can check @ unknowones posts, not sure which one was it.

You don't need the 'seed packet' for anything. It's only used to seed the new password cryptography, which, unless you want to log your passwords, has no usage. So yes, you can just forward it to the client.
I was hoping it was a general encryption algorithm. How often do they change the method of encryption? How soon is information about the encryption disclosed to the public?