is there anycode for Blowfish here in C++ works with the later clients?! like the one in ExodusBinaries?
Quote:
As usual this has no interest in private server section so here it goes, it's not finished yet. If you see errors / places where it could be better, post here. It's not tested but it should work unless there's a major fuck-up somewhere.
Blowfish.h
Blowfish.cppPHP Code:#pragma once
#include <openssl/blowfish.h>
#pragma comment(lib, "libeay32.lib")
class CBlowfish
{
private:
unsigned char *DecryptIV;
unsigned char *EncryptIV;
int DecryptCounter;
int EncryptCounter;
BF_KEY *Key;
public:
CBlowfish(unsigned char *Data, int Length);
~CBlowfish(void);
unsigned char* Encrypt(unsigned char *Data, int Length);
unsigned char* Decrypt(unsigned char *Data, int Length);
void SetKey(unsigned char *Data, int Length);
void SetIVs(unsigned char *DecryptIV, unsigned char *EncryptIV);
};
DH.hPHP Code:#include "StdAfx.h"
#include "Blowfish.h"
CBlowfish::CBlowfish(unsigned char *Data, int Length)
{
DecryptIV = new unsigned char[8];
EncryptIV = new unsigned char[8];
DecryptCounter = 0;
EncryptCounter = 0;
Key = new BF_KEY();
BF_set_key(Key, Length, Data);
}
CBlowfish::~CBlowfish(void)
{
delete[] DecryptIV;
delete[] EncryptIV;
delete[] Key;
}
unsigned char* CBlowfish::Encrypt(unsigned char *Data, int Length)
{
unsigned char* Out = new unsigned char[Length];
BF_cfb64_encrypt(Data, Out, Length, Key, EncryptIV, &EncryptCounter, 1);
return Out;
}
unsigned char* CBlowfish::Decrypt(unsigned char *Data, int Length)
{
unsigned char* Out = new unsigned char[Length];
BF_cfb64_encrypt(Data, Out, Length, Key, DecryptIV, &DecryptCounter, 0);
return Out;
}
void CBlowfish::SetKey(unsigned char *Data, int Length)
{
BF_set_key(Key, Length, Data);
DecryptCounter = 0;
EncryptCounter = 0;
}
void CBlowfish::SetIVs(unsigned char *DecryptIV, unsigned char *EncryptIV)
{
memcpy(this->DecryptIV, DecryptIV, 8);
memcpy(this->EncryptIV, EncryptIV, 8);
}
DH.cppPHP Code:#pragma once
#include <openssl/dh.h>
#include <openssl/bn.h>
class CDH
{
private:
DH *dh;
public:
CDH(BIGNUM *P, BIGNUM *G);
~CDH(void);
unsigned char* ComputeKey(BIGNUM *PublicKey);
void GenerateKeys();
void SetG(BIGNUM *G);
void SetP(BIGNUM *P);
void SetPrivate(BIGNUM *PrivateKey);
void SetPublic(BIGNUM *PublicKey);
BIGNUM* GetG();
BIGNUM* GetP();
BIGNUM* GetPrivate();
BIGNUM* GetPublic();
__declspec(property(get = GetG, put = SetG)) BIGNUM *G;
__declspec(property(get = GetP, put = SetP)) BIGNUM *P;
__declspec(property(get = GetPrivate, put = SetPrivate)) BIGNUM *PrivateKey;
__declspec(property(get = GetPublic, put = SetPublic)) BIGNUM *PublicKey;
};
PHP Code:#include "StdAfx.h"
#include "DH.h"
CDH::CDH(BIGNUM *P, BIGNUM *G)
{
dh = DH_new();
dh->p = BN_dup(P);
dh->g = BN_dup(G);
}
unsigned char* CDH::ComputeKey(BIGNUM *PublicKey)
{
unsigned char *Key = new unsigned char[DH_size(dh)];
DH_compute_key(Key, PublicKey, dh);
return Key;
}
void CDH::GenerateKeys()
{
DH_generate_key(dh);
}
void CDH::SetG(BIGNUM *G)
{
dh->g = BN_dup(G);
}
void CDH::SetP(BIGNUM *P)
{
dh->p = BN_dup(P);
}
void CDH::SetPrivate(BIGNUM* PrivateKey)
{
dh->priv_key = BN_dup(PrivateKey);
}
void CDH::SetPublic(BIGNUM* PublicKey)
{
dh->pub_key = BN_dup(PublicKey);
}
BIGNUM* CDH::GetP()
{
return dh->p;
}
BIGNUM* CDH::GetG()
{
return dh->g;
}
BIGNUM* CDH::GetPrivate()
{
return dh->priv_key;
}
BIGNUM* CDH::GetPublic()
{
return dh->pub_key;
}
CDH::~CDH(void)
{
delete[] dh;
}
Quote:
GameCryptography.h
GameCryptography.cppPHP Code:#pragma once
#include "Blowfish.h"
class CGameCryptography
{
public:
CGameCryptography(void);
~CGameCryptography(void);
CBlowfish *bf;
unsigned char* Encrypt(unsigned char *Packet, int Length);
unsigned char* Decrypt(unsigned char *Packet, int Length);
};
PHP Code:#include "StdAfx.h"
#include "GameCryptography.h"
CGameCryptography::CGameCryptography(void)
{
char *szInitialKey = "DR654dt34trg4UI6";
bf = new CBlowfish(reinterpret_cast<unsigned char*>(szInitialKey), 16);
/*char *szInitialKey = "DR654dt34trg4UI6";
unsigned char *Key = new unsigned char[sizeof(szInitialKey)];
for(int i = 0; i < sizeof(szInitialKey); i++)
Key[i] = (unsigned char)szInitialKey[i];
bf = new CBlowfish(Key, 16);
reinterpret_cast<*/
}
CGameCryptography::~CGameCryptography(void)
{
delete[] bf;
}
unsigned char *CGameCryptography::Encrypt(unsigned char *Packet, int Length)
{
return bf->Encrypt(Packet, Length);
}
unsigned char *CGameCryptography::Decrypt(unsigned char *Packet, int Length)
{
return bf->Decrypt(Packet, Length);
}
Handshake.h
HandshakeReply.hPHP Code:#pragma once
#include "PacketReader.h"
class Handshake
{
public:
Handshake(void) { }
~Handshake(void) { }
unsigned char *ServerIV, *ClientIV;
char *P, *G, *PublicKey;
void Process(unsigned char *Packet)
{
PacketReader *Reader = new PacketReader(Packet, sizeof(Packet), 15);
Reader->Advance(Reader->ReadDWord());
ServerIV = Reader->ReadBytes(Reader->ReadDWord());
ClientIV = Reader->ReadBytes(Reader->ReadDWord());
P = Reader->ReadString(Reader->ReadDWord());
G = Reader->ReadString(Reader->ReadDWord());
PublicKey = Reader->ReadString(Reader->ReadDWord());
}
};
PacketReader.hPHP Code:#pragma once
#include "PacketReader.h"
class HandshakeReply
{
public:
HandshakeReply(void) { }
~HandshakeReply(void) { }
char *PublicKey;
void Process(unsigned char *Packet)
{
PacketReader *Reader = new PacketReader(Packet, sizeof(Packet), 11);
Reader->Advance(Reader->ReadDWord());
PublicKey = Reader->ReadString(Reader->ReadDWord());
}
};
PHP Code:#pragma once
class PacketReader
{
private:
unsigned char *Packet;
public:
unsigned long Index;
PacketReader(unsigned char *Packet, int Length, int Position = 0)
{
this->Packet = Packet;
this->Index = Position;
}
void Advance(unsigned long Length)
{
Index += Length;
}
unsigned long ReadDWord()
{
unsigned long Value = *((unsigned long*)(Packet + Index));
Index += 4;
return Value;
}
unsigned char* ReadBytes(unsigned long Length)
{
unsigned char *Value = new unsigned char[Length];
memcpy(Value, (Packet + Index), Length);
Index += Length;
return Value;
}
char *ReadString(unsigned long Length)
{
char* Value = new char[Length];
for(int i = 0; i < Length; i++)
Value[i] = (char)Packet[Index + i];
Index += Length;
Value[Length] = 0x00;
return Value;
}
~PacketReader(void)
{
delete[] Packet;
}
};
GameCipher test("DR654dt34trg4UI6");
for(;;)
{
if((sConnect=accept(sListen,(SOCKADDR*)&addr,&addrlen)) != INVALID_SOCKET)
{
Print("Socket Connected -> %s",inet_ntoa(addr.sin_addr));
char rSeed[9];
rPassSeed(rSeed);
char buf[1096];
int buflen=strlen(buf);
send(sListen,rSeed,8,0);
recv(sListen,buf,buflen,0);
test.Decrypt((unsigned char *)buf,(unsigned char *)buf,buflen);
cout << buf;
}
#include <iostream>
#include <iomanip>
void output_hex (std::ostream& out, uint8_t const* const buf, int len) {
for (int i=0;i<len;i++)
out << std::noshowbase
<< std::hex
<< std::setfill ('0')
<< std::setw (2)
<< static_cast<int> (buf[i])
<< " ";
}
//
output_hex (cout, buf, buflen);
but am trying to decrypt what am geting from the client using Blowfish when i used the function u showed me here is the reslut:Quote:
You can't just ouput a binary stream like that. You need to convert it to hexidecimal to be readable at all.
Code:#include <iostream> #include <iomanip> void output_hex (std::ostream& out, uint8_t const* const buf, int len) { for (int i=0;i<len;i++) out << std::noshowbase << std::hex << std::setfill ('0') << std::setw (2) << static_cast<int> (buf[i]) << " "; } // output_hex (cout, buf, buflen);
so lets make every thing clear i send to the client:Quote:
Are you expecting to read plain text? Because that won't happen. The protocol is a binary one, and has very little text in it. For starters, fix this:
Get the result from recv(), which is the actual number of bytes receive (rather than the size of the buffer). Then output_hex (cout, buf, recv_len); You should get something a bit more readable.
const int Seed=74185296; send(sListen,(char *)Seed,8,0);
typedef struct packetSeed
{
unsigned short Length; // 0x8
unsigned short Type; // 0x423
unsigned int Seed; // random
} * PPACKETSEED;
packetSeed * packet = new packetSeed();
packet->length = 8;
packet->type = 0x423;
packet->Seed = 74185296;
send(s, (uint8_t*)packet, sizeof(packetSeed), 0);
delete packet;
a question if i may why should i send it by this way?Quote:
You don't simple send the Seed value like that. You must structure it into the packet you posted in the other thread.
Oh, and I noticed you're sending/recieving on your listen socket. You shouldn't do that. You should be send/receiving on the connected socket that was returned in the call to accept(); I'd suggest go reading Beej's guide to network programming for further details.Code:typedef struct packetSeed { unsigned short Length; // 0x8 unsigned short Type; // 0x423 unsigned int Seed; // random } * PPACKETSEED; packetSeed * packet = new packetSeed(); packet->length = 8; packet->type = 0x423; packet->Seed = 74185296; send(s, (uint8_t*)packet, sizeof(packetSeed), 0); delete packet;
man thanks u made my day xD , really thnx :) , onther question :P why is the client crashs when i use sConnect?Quote:
Because that's what the client expects to receive. The particular pieces of data are required in order to the client to be able to interpret the data you are sending.
For starters, the length field of the packet is required in TCP (stream based) communication, because the client must be able to recognise where a particular piece of information starts and ends. If you call send 5 times on a server, that doesn't necessarily mean that the client will need to call recv 5 times to recv those 5 pieces of data. It may only need to call it once, or it may need to call it 10 times. It depends on the load on the network, it cannot be decided beforehand where each send was sent in the stream. So we add a length to each "send" so that the receiver can interpret the data and decide where each piece of sent information begins and ends.
As for the type - This is a primitive that decides what the receiver should do with the data. There's lots of different pieces of data you can send that do different functions (for example, one might contain login information, another might contain some chat information). The type primitive just identifies each piece of information so that it can be mapped to a function that is to be performed on the payload. (In this case, is the seed).
So if you send data as described. The client will first read the length, to determine when to stop receiving for this particular piece of data. It will then read the type, and see it is the Seed packet type, and it can then call a function which sets the seed for the cryptography using the final piece of data in the stream.
i did the same thing u told me :-sQuote:
Most likely because you are sending incorrectly formed data which the client doesn't expect, and it is unable to recover from the error, so it just shuts down.
packetSeed * packet = new packetSeed(); packet->Length = 8; packet->Type = 0x423; packet->Seed = 74185296; send(sConnect, (char*)packet, sizeof(packetSeed), 0);