|
You last visited: Today at 15:43
Advertisement
[C++] DHKey Exchange in 5672
Discussion on [C++] DHKey Exchange in 5672 within the CO2 Private Server forum part of the Conquer Online 2 category.
12/31/2017, 17:07
|
#1
|
elite*gold: 0
Join Date: Jul 2009
Posts: 943
Received Thanks: 408
|
[C++] DHKey Exchange in 5672
Hello Epvpers!
Here I am looking for help again! I've been trying to write an source in C++ in the last months, took me a lot since I'm trying to don't take anything from the sources out there and writing a socket system was the worst part xD
Well, first of all, the problem. I'm pretty sure that the problem is on that part of the code. Why? Because I sent the DHKey Challenge, the client is sending it back and I'm able to read it, so the Cast5 Cipher is working properly. But I'm not being able to set the client key to start the game packet exchange.
Code:
CCast5* CNdDhKeyExchange::Respond(const char* publicKey, CCast5* cipher)
{
ASSERT(!cipher);
std::string response = handleResponse(publicKey);
std::string str1(Hex(md5digest(response.c_str()), 16));
std::string concat(str1);
concat += str1;
std::string str2(Hex(md5digest(concat.c_str()), 16));
concat.clear();
concat += str1;
concat += str2;
cipher->KeySchedule((BYTE*)concat.c_str(), concat.size());
cipher->SetIV(m_encryptionIv, m_decryptionIv);
return cipher;
}
std::string Hex(const char* bytes, size_t len)
{
const char hexmap[] = { '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
char* c = new char[len*2+1];
ZeroMemory(c, len*2+1);
for (int i = 0; i < len; ++i) {
c[2 * i] = hexmap[(bytes[i] & 0xF0) >> 4];
c[2 * i + 1] = hexmap[bytes[i] & 0x0F];
}
return c;
}
I've got success upgrading my C# source, I tried it to make sure that what I wrote was correct and it worked on the C# source. The C# Hex thing I've got from somewhere, but the point is that it work.
Code:
public BlowfishCipher Respond(string publicKey, BlowfishCipher cipher)
{
byte[] key = GenerateResponse(publicKey);
var md5 = new MD5CryptoServiceProvider();
string sz1 = Hex(md5.ComputeHash(key, 0, key.Count(x => x != 0)));
string sz2 = Hex(md5.ComputeHash(Encoding.ASCII.GetBytes(string.Concat(sz1, sz1))));
cipher.KeySchedule(Encoding.ASCII.GetBytes(string.Concat(sz1, sz2)));
//cipher.KeySchedule(GenerateResponse(publicKey));
cipher.SetDecryptionIV(_decryptionIv);
cipher.SetEncryptionIV(_encryptionIv);
return cipher;
}
private string Hex(byte[] bytes)
{
char[] c = new char[bytes.Length * 2];
byte b;
for (int bx = 0, cx = 0; bx < bytes.Length; ++bx, ++cx)
{
b = ((byte)(bytes[bx] >> 4));
c[cx] = (char)(b > 9 ? b + 0x37 + 0x20 : b + 0x30);
b = ((byte)(bytes[bx] & 0x0F));
c[++cx] = (char)(b > 9 ? b + 0x37 + 0x20 : b + 0x30);
}
return new string(c);
}
I think that the problem may be in the Hex thing, since the md5 is from the OpenSSL dll and it's the same for everything.
Thank you if you at least read it and if anybody could give me a light, It would be great.
|
|
|
12/31/2017, 18:46
|
#2
|
elite*gold: 12
Join Date: Jul 2011
Posts: 8,283
Received Thanks: 4,192
|
Here's an additional reference from a private branch of Chimera ...
Code:
// Package for the diffie-hellman key exchange and its alternatives. The
// Conquer Online game client uses DH to establish a shared key for CAST-5
// over an insecure communications channel. This does not assist in reducing
// active attacks, and thus adds very little security to the server. Only
// helps reduce passive attacks such as eavesdropping. This package has been
// modified for interoperability with the Conquer Online game client.
package dh
import (
"bytes"
"crypto/rand"
"crypto/md5"
"encoding/hex"
"math/big"
)
const (
Generator = "05"
Modulus = "E7A69EBDF105F2A6BBDEAD7E798F76A209AD73FB466431E2E7352ED2" +
"62F8C558F10BEFEA977DE9E21DCEE9B04D245F300ECCBBA03E726305" +
"56D011023F9E857F"
)
// Exchange defines DH protocol for the server. For documentation purposes,
// the server will be Alice in the exchange protocol. Some variables are
// captitalized incorrectly to be exported.
type Server struct {
P *big.Int // Public prime modulus, known to all parties.
G *big.Int // Public prime generator, known to both parties.
A *big.Int // Alice's public key, known to both parties
a *big.Int // Alice's private key.
B *big.Int // Bob's public key (the client's public key).
}
// NewServer accepts a prime modulus and generator for initializing DH.
func NewServer(p, g string) *Server {
server := new(Server)
server.P = new(big.Int)
server.G = new(big.Int)
server.P.SetString(p, 16)
server.G.SetString(g, 16)
return server
}
// Request starts the exchange and generates the server's public key to be
// sent over the unsecure communications channel. Returns the public key as
// a hexadecimal string to be sent to the game client.
func (server *Server) Request() (string, error) {
var err error
server.a, err = rand.Prime(rand.Reader, 256)
if err != nil { return "", err }
server.A = server.G.Exp(server.G, server.a, server.P)
return server.A.Text(16), nil
}
// Response to be processed from the game client. The response contains the
// client's public key. From this key, the shared key can be computed between
// the parties. Returns the shared key.
func (server *Server) Response(clientkey string) []byte {
server.B = new(big.Int)
server.B.SetString(clientkey, 16)
sharedkey := server.B.Exp(server.B, server.a, server.P)
// The shared key is trimmed for some reason in TQ's version.
sharedkeybuf := sharedkey.Bytes()
sharedkeylen := len(sharedkeybuf)
trimmedkeylen := bytes.IndexByte(sharedkeybuf, 0)
if trimmedkeylen == -1 { trimmedkeylen = sharedkeylen }
trimmedkey := sharedkeybuf[:trimmedkeylen]
// TQ Digital hash modification to the shared key.
hash := md5.New()
hash.Write(trimmedkey)
left := hex.EncodeToString(hash.Sum(nil))
right := left + left
hash = md5.New()
hash.Write([]byte(right))
right = hex.EncodeToString(hash.Sum(nil))
return []byte(left + right)
}
|
|
|
12/31/2017, 21:36
|
#3
|
elite*gold: 0
Join Date: Jan 2008
Posts: 1,445
Received Thanks: 1,176
|
I see multiple errors or possible improvements in your code.
First, if your pointer cannot be NULL (e.g. cipher), you can use references instead of pointers. You're usage of std::string is not optimal. You could reserve the capacity instead of forcing the object to reallocate its internal buffer.
The function Hex has multiple issues. First, you have a memory leak. You allocate memory on the heap for c (it will be implicitly casted to std::string on return), but c will remain allocated when you exit the function. You can improve your code by using memset instead of ZeroMemory, the later being only available on MSVC. In your loop, you compare a int to a size_t. If len is larger than an int (possible on 64 bits platforms), you can loop and get negative indexes when the integer will overlap. Other thing, a char not specified to be signed or unsigned, but most of the time, it is signed. A byte (in C#) is unsigned, as such, either use 'unsigned char', or if you want specifically a 8-bit integer, you should use uint8_t. In C++, basic types do not have fixed sizes. Also, I see a major problem with you using a char. If signed, when you will shift the value by 4 bits, the shift operator will keep the sign.
Have you check that the resulting strings are identical using your C++/C# implementations? For the same data, they should. You can easily compare both and find which part is wrong.
|
|
|
01/01/2018, 01:13
|
#4
|
elite*gold: 0
Join Date: Jul 2009
Posts: 943
Received Thanks: 408
|
Quote:
Originally Posted by CptSky
I see multiple errors or possible improvements in your code.
First, if your pointer cannot be NULL (e.g. cipher), you can use references instead of pointers. You're usage of std::string is not optimal. You could reserve the capacity instead of forcing the object to reallocate its internal buffer.
The function Hex has multiple issues. First, you have a memory leak. You allocate memory on the heap for c (it will be implicitly casted to std::string on return), but c will remain allocated when you exit the function. You can improve your code by using memset instead of ZeroMemory, the later being only available on MSVC. In your loop, you compare a int to a size_t. If len is larger than an int (possible on 64 bits platforms), you can loop and get negative indexes when the integer will overlap. Other thing, a char not specified to be signed or unsigned, but most of the time, it is signed. A byte (in C#) is unsigned, as such, either use 'unsigned char', or if you want specifically a 8-bit integer, you should use uint8_t. In C++, basic types do not have fixed sizes. Also, I see a major problem with you using a char. If signed, when you will shift the value by 4 bits, the shift operator will keep the sign.
Have you check that the resulting strings are identical using your C++/C# implementations? For the same data, they should. You can easily compare both and find which part is wrong.
|
I tested the Hex function and both implementations when receiving the same data return the same value. So, I noticed that the the DHKey (Which I got from cops) returns an string with the bytes (string parsed). I'll now try to convert it to a byte array.
Thank you for the tips.
Also ty Spirited, your code helped me finding out something pretty obvious xD and also something I didn't noticed before. I'll edit here after i commit the changes.
Seryiously, I should kill myself.
The md5 function I built already encoded the chars into the byte strings. I was doing it twice, that's why it was wrong. The Hex function wasn't even needed! Now it's working.
@  your code your code helped me on the array trim and to figure out that my response was the bytes as string xD I needed the array. @  there was a memory problem on the hex function I fixed it XD thank you even if I wont use that anymore, I should pay more atention.
Thanks for the help.
Topic can be closed.
|
|
|
 |
Similar Threads
|
is the DHKey exchange changed ?
09/13/2016 - Conquer Online 2 - 2 Replies
Hello,
i'm trying to decrypt the DHKey but after i get the packet i can't read the IV's or the public key i have tried "Pro4Never" algorithm but the problem is this line
int JunkLength = BR.ReadInt32();
when print it out i get a very big value "not even i the packet", and this is a simple of the packet i get...
|
Proxy Server DHKey Exchance
03/19/2013 - CO2 Programming - 7 Replies
Hello, epvp
how are you guys???
i finally finished my proxy(not bot for now)
i maked the client merged (auth and game)
auth encryption is easy cause it doesnt need a dhkey
but my problem is in game encryption
i have lastest encryption and key
|
[Important]Needed Update For DHKey For ProxyParadise .
09/15/2012 - Conquer Online 2 - 11 Replies
Hello Guys,
Am Here Today To Ask Any Body To Upgrade DH-Key and Add MD5 To Proxy Paradise Pro4Never's Proxy To work on The Latest Co Client That's Will Be Very Useful , I Have Tried Many Times But I Couldn't When I go For Log In It Disconnects From Game Server ... So Please Do It As My First Request Here In Forum ...
I Attached The Source Code In Topic ..
All Rights Go To Pro4Never I didn't Do Any Thing .
Thanks For Your Time ...
Samuel .
|
All times are GMT +1. The time now is 15:43.
|
|