-
C1/C2/C3/C4 Packet Encryption/Decryption source code (C++)
Authors
----------------------------------------------------------
Decryption: wad <wad@inbox.lv>
Decryption reverse engineering: Evolver <ninzya@inbox.lv>
mu_packet.h
----------------------------------------------------------
#ifndef __EVOL_MUAPI_MU_PACKET_H__
#define __EVOL_MUAPI_MU_PACKET_H__
#include <memory.h>
#define MU_PACKET( buf_ptr) (muPacket*)buf_ptr
#define MU_REFPKT( pkt_ptr) (*pkt_ptr)
class muPacket {
public:
// ...
muPacket() {
}
// ...
~muPacket() {
}
public:
// ...
inline unsigned char* packet() {
return ((unsigned char*)this);
}
// ...
inline unsigned char& packet( unsigned short i) {
return ((unsigned char*)this)[i];
}
// ...
inline void packet( void* out_buf, unsigned short offset, unsigned short bytes) {
memcpy( out_buf, &this->packet()[offset], bytes);
}
// ...
inline unsigned char hdr() {
return this->packet()[0];
}
// ...
unsigned short size() {
unsigned char* buf =(unsigned char*)this;
if( buf[0] ==0xC1 || buf[0] ==0xC3)
return (unsigned short)buf[1];
else if( buf[0] ==0xC2 || buf[0] ==0xC4)
return (((unsigned short)buf[1] << 8) | (unsigned short)buf[2]);
// shouldn't occur
return 0;
}
// ...
inline unsigned char *contents() {
return &(this->packet()[this->hdrSize()]);
}
// ...
inline unsigned char& contents( unsigned short i) {
return this->packet()[this->hdrSize()+i];
}
// ...
inline void contents( void* out_buf, unsigned short offset, unsigned short bytes) {
memcpy( out_buf, &(this->contents()[offset]), bytes);
}
// ...
inline unsigned short contentSize() {
return( this->size() -this->hdrSize());
}
// ...
inline unsigned char opc() {
return( this->operator()( 0));
}
// ...
unsigned char hdrSize() {
unsigned char* buf =(unsigned char*)this;
if( buf[0] ==0xC1 || buf[0] ==0xC3)
return 2;
else if( buf[0] ==0xC2 || buf[0] ==0xC4)
return 3;
// shouldn't occur
return 0;
}
public:// operators
// iterates whole packet
inline unsigned char& operator[]( unsigned short i) {
return this->packet()[i];
}
// iterates contents
inline unsigned char& operator()( unsigned short i) {
return this->packet()[i +this->hdrSize()];
}
// returns pointer to packet
inline operator unsigned char*() {
return this->packet();
}
};
// checks whether the given packet is valid
bool IsMuPacketValid( unsigned char *ptr, unsigned short len);
#endif
mu_packet.cpp
---------------------------------------------------------------------
#include "mu_packet.h"
// checks whether the given packet is valid
bool IsMuPacketValid( unsigned char *ptr, unsigned short len) {
if( len < 3) return false;
if( ptr[0] == 0xC1 || ptr[0] == 0xC3)
return ( ptr[1] == len);
else if (ptr[0] == 0xC2 || ptr[0] == 0xC4) {
unsigned short inlen =(unsigned short)ptr[1] << 8 | (unsigned short)ptr[2];
return ( inlen == len);
} else
return false;
}
mu_encdec.h
----------------------------------------------------------
/*
* Mu Protocol Decryption algorythm fetched from gs by wad. Special thanks.
* Author: Evolver
* Modifications:
* Integrated encryption algorhythm basing on decryption algorhythm by wad. (Evolver)
* Prepared and tested code (Evolver)
*/
#ifndef __EVOL_MUAPI_MU_ENCDEC_H__
#define __EVOL_MUAPI_MU_ENCDEC_H__
#include "mu_packet.h"
enum MuReadEncfileResult_t {
MuReadEncfile_InvalidPath =0,
MuReadEncfile_FileCorrupted =1,
MuReadEncfile_Success =2
};
// this algorythm uses dec data in this order:
// enc client->server (Dec1.dat)
// dec client->server (Dec1.dat)
// enc server->client (Dec2.dat)
// dec server->client (Dec2.dat)
// reads encryption file
MuReadEncfileResult_t MuReadEncfile( char *file, unsigned int* out_dat );
// decrypts login/passwod, and also used to decrypt login and password,
// Terrain*.att files in client-side Data/World*/, bmd files
void MuXor3Byte( unsigned char* ptr, unsigned int len);
// encode c1/c2 packet
extern void MU_EncodeC1C2( muPacket* packet);
// decode c1/c2 packet
extern void MU_DecodeC1C2( muPacket* packet);
// encode c3/c4 packet
bool MU_EncodeC3C4( unsigned char* outbuf, muPacket* pkt, unsigned int* dec_dat, unsigned char enc_key);
// decode c3/c4 packet
bool MU_DecodeC3C4( unsigned char* outbuf, muPacket* pkt, unsigned int* dec_dat, unsigned char* dec_key);
// returns space in bytes, required to fit the encrypted packet to c3/c4
extern unsigned short MuPacketEncSpace( muPacket* pkt);
// returns space in bytes, required to fit the decrypted packet from c3/c4
extern unsigned short MuPacketDecSpace( muPacket* pkt);
#endif
mu_encdec.cpp
----------------------------------------------------------
/*
* Mu Protocol Decryption algorythm fetched from gs by wad. Special thanks.
* Author: Evolver
* Modifications:
* Integrated encryption algorhythm basing on decryption algorhythm by wad. (Evolver)
* Prepared and tested code (Evolver)
*/
#include "mu_encdec.h"
#include "mu_packet.h"
#include <memory.h>
#include <cstdio>
// MuError.log
const static unsigned int xor_tab_muerror[4] = {
0x9F81BD7C, 0x56E2933D, 0x3ED2732A, 0xBF9583F2
};
// used to decrypt login and password, Terrain*.att files in
// client-side Data/World*/
const static unsigned char xor_table_3byte[3] = {
0xFC, 0xCF, 0xAB
};
// used to decrypt client-side Data/Enc1.dat and Data/Dec2.Dat
const unsigned int xor_tab_datfile[4] = {
0x3F08A79B, 0xE25CC287, 0x93D27AB9, 0x20DEA7BF
};
// used to decrypt C1/C2 packets
const unsigned char xor_tab_C1C2[32] = {
0xE7, 0x6D, 0x3A, 0x89, 0xBC, 0xB2, 0x9F, 0x73,
0x23, 0xA8, 0xFE, 0xB6, 0x49, 0x5D, 0x39, 0x5D,
0x8A, 0xCB, 0x63, 0x8D, 0xEA, 0x7D, 0x2B, 0x5F,
0xC3, 0xB1, 0xE9, 0x83, 0x29, 0x51, 0xE8, 0x56
};
// decrypts login/passwod, and also used to decrypt login and password,
// Terrain*.att files in client-side Data/World*/
void MuXor3Byte( unsigned char* ptr, unsigned int len) {
for( unsigned int i = 0; i < len; ++i)
ptr[i] ^= xor_table_3byte[i%3];
}
// ...
void ShiftRight(unsigned char* ptr, unsigned int len, unsigned int shift) {
if (shift == 0) return;
for( unsigned int i = 1; i < len; ++i) {
*ptr = (*ptr << shift) | (*(ptr+1) >> (8 - shift));
++ptr;
}
*ptr <<= shift;
}
// ...
void ShiftLeft(unsigned char* ptr, unsigned int len, unsigned int shift) {
if (shift == 0) return;
ptr +=len -1;
for( unsigned int i = 1; i < len; ++i) {
*ptr = (*ptr >> shift) | (*(ptr-1) << (8 - shift));
--ptr;
}
*ptr >>= shift;
}
// ...
unsigned int ShiftBytes(unsigned char* buf, unsigned int arg_4, unsigned char* pkt, unsigned int arg_C, unsigned int arg_10) {
unsigned int size_ = ((((arg_10 + arg_C) - 1) / 8) + (1 - (arg_C / 8)));
unsigned char tmp1[20] ={ 0 };
memcpy( tmp1, &pkt[arg_C /8], size_);
unsigned int var_4 = (arg_10 + arg_C) & 0x7;
if (var_4) tmp1[size_ - 1] &= 0xFF << (8 - var_4);
arg_C &= 0x7;
ShiftRight(tmp1, size_, arg_C);
ShiftLeft(tmp1, size_ + 1, arg_4 & 0x7);
if ((arg_4 & 0x7) > arg_C)
++size_;
if(size_)
for( unsigned int i =0; i < size_; ++i)
buf[i+(arg_4/8)] |=tmp1[i];
return arg_10 + arg_4;
}
// ...
void Encode8BytesTo11Bytes( unsigned char* outbuf, unsigned char* pktptr, unsigned int num_bytes, unsigned int* dec_dat) {
unsigned char finale[2];
finale[0] =(unsigned char)num_bytes;
finale[0] ^= 0x3D;
finale[1] =0xF8;
for (int k = 0; k < 8; ++k)
finale[1] ^= pktptr[k];
finale[0] ^= finale[1];
ShiftBytes( outbuf, 0x48, finale, 0x00, 0x10);
unsigned int ring[4] ={ 0x000000000, 0x00000000, 0x00000000, 0x00000000 };
unsigned short* cryptbuf =(unsigned short*)pktptr;
ring[0] =((dec_dat[ 8] ^(cryptbuf[0])) *dec_dat[ 4]) %dec_dat[ 0];
ring[1] =((dec_dat[ 9] ^(cryptbuf[1] ^(ring[0] &0xFFFF))) *dec_dat[ 5]) %dec_dat[ 1];
ring[2] =((dec_dat[10] ^(cryptbuf[2] ^(ring[1] &0xFFFF))) *dec_dat[ 6]) %dec_dat[ 2];
ring[3] =((dec_dat[11] ^(cryptbuf[3] ^(ring[2] &0xFFFF))) *dec_dat[ 7]) %dec_dat[ 3];
unsigned int ring_backup[4] ={ ring[0], ring[1], ring[2], ring[3] };
ring[2] =ring[2] ^dec_dat[10] ^(ring_backup[3] &0xFFFF);
ring[1] =ring[1] ^dec_dat[ 9] ^(ring_backup[2] &0xFFFF);
ring[0] =ring[0] ^dec_dat[ 8] ^(ring_backup[1] &0xFFFF);
ShiftBytes( outbuf, 0x00, (unsigned char*)(&ring[0]), 0x00, 0x10);
ShiftBytes( outbuf, 0x10, (unsigned char*)(&ring[0]), 0x16, 0x02);
ShiftBytes( outbuf, 0x12, (unsigned char*)(&ring[1]), 0x00, 0x10);
ShiftBytes( outbuf, 0x22, (unsigned char*)(&ring[1]), 0x16, 0x02);
ShiftBytes( outbuf, 0x24, (unsigned char*)(&ring[2]), 0x00, 0x10);
ShiftBytes( outbuf, 0x34, (unsigned char*)(&ring[2]), 0x16, 0x02);
ShiftBytes( outbuf, 0x36, (unsigned char*)(&ring[3]), 0x00, 0x10);
ShiftBytes( outbuf, 0x46, (unsigned char*)(&ring[3]), 0x16, 0x02);
}
// ...
int Decode11BytesTo8Bytes( unsigned char* outbuf, unsigned char* pktptr, unsigned int* dec_dat) {
unsigned int ring[4] ={ 0x00000000, 0x00000000, 0x00000000, 0x00000000 };
ShiftBytes((unsigned char*)&ring[0], 0x00, pktptr, 0x00, 0x10);
ShiftBytes((unsigned char*)&ring[0], 0x16, pktptr, 0x10, 0x02);
ShiftBytes((unsigned char*)&ring[1], 0x00, pktptr, 0x12, 0x10);
ShiftBytes((unsigned char*)&ring[1], 0x16, pktptr, 0x22, 0x02);
ShiftBytes((unsigned char*)&ring[2], 0x00, pktptr, 0x24, 0x10);
ShiftBytes((unsigned char*)&ring[2], 0x16, pktptr, 0x34, 0x02);
ShiftBytes((unsigned char*)&ring[3], 0x00, pktptr, 0x36, 0x10);
ShiftBytes((unsigned char*)&ring[3], 0x16, pktptr, 0x46, 0x02);
ring[2] =ring[2] ^dec_dat[10] ^(ring[3] &0xFFFF);
ring[1] =ring[1] ^dec_dat[ 9] ^(ring[2] &0xFFFF);
ring[0] =ring[0] ^dec_dat[ 8] ^(ring[1] &0xFFFF);
unsigned short* cryptbuf =(unsigned short*)outbuf;
cryptbuf[0] =dec_dat[ 8] ^((ring[0] *dec_dat[ 4]) %dec_dat[0]);
cryptbuf[1] =dec_dat[ 9] ^((ring[1] *dec_dat[ 5]) %dec_dat[1]) ^(ring[0] &0xFFFF);
cryptbuf[2] =dec_dat[10] ^((ring[2] *dec_dat[ 6]) %dec_dat[2]) ^(ring[1] &0xFFFF);
cryptbuf[3] =dec_dat[11] ^((ring[3] *dec_dat[ 7]) %dec_dat[3]) ^(ring[2] &0xFFFF);
unsigned char finale[2] ={ 0x00, 0x00 };
ShiftBytes(finale, 0, pktptr, 0x48, 0x10);
finale[0] ^= finale[1];
finale[0] ^= 0x3D;
unsigned char m = 0xF8;
for( int k = 0; k < 8; ++k)
m ^= outbuf[k];
if( m ==finale[1])
return finale[0];
return -1;
}
// ...
inline unsigned short MuPacketEncSpace( muPacket* pkt) {
return((( pkt->contentSize() /8) +(((pkt->contentSize() %8) >0) ? 1 : 0)) *11) +pkt->hdrSize();
}
// ...
inline unsigned short MuPacketDecSpace( muPacket* pkt) {
return(( pkt->contentSize() /11) *8) +pkt->hdrSize() -1;
}
// (if C1, offset = 2), (if C2, offset = 3)
void MU_ForceEncodeC1C2( unsigned char* buf, unsigned short len, unsigned short offset =2) {
for( unsigned short p =1; p < len; ++p)
buf[p] ^= buf[p-1] ^ xor_tab_C1C2[(p+offset) %32];
}
// (if C1, offset = 2), (if C2, offset = 3)
void MU_ForceDecodeC1C2( unsigned char* buf, unsigned short len, unsigned short offset =2) {
--len;
for( unsigned short p =len; p > 0; --p)
buf[p] ^= buf[p-1] ^ xor_tab_C1C2[(p+offset) %32];
}
// encode c1/c2 packet
inline void MU_EncodeC1C2( muPacket* packet) {
MU_ForceEncodeC1C2( packet->contents(), packet->contentSize(), packet->hdrSize());
}
// decode c1/c2 packet
inline void MU_DecodeC1C2( muPacket* packet) {
MU_ForceDecodeC1C2( packet->contents(), packet->contentSize(), packet->hdrSize());
}
// encode c3/c4 packet
bool MU_ForceEncodeC3C4( unsigned char* outbuf, unsigned short* outlen, unsigned char* inbuf, unsigned short len, unsigned int* dec_dat) {
*outlen =0;
unsigned int offset =0;
for( offset =0; (offset+8) <= len; offset +=8) {
memset( outbuf, 0, 11);
Encode8BytesTo11Bytes( outbuf, &inbuf[offset], 8, dec_dat);
*outlen += 11;
outbuf += 11;
}
if ( offset < len) {
memset( outbuf, 0, 11);
Encode8BytesTo11Bytes( outbuf, &inbuf[offset], len - offset, dec_dat);
*outlen += 11;
}
return true;
}
// decode c3/c4 packet
bool MU_ForceDecodeC3C4( unsigned char* outbuf, unsigned short* outlen, unsigned char* inbuf, unsigned short len, unsigned int* dec_dat) {
if ((len % 11) != 0)
return false;// invalid size specified
*outlen = 0;
int rez =0;
for( unsigned int offset =0; offset < len; offset +=11) {
rez =Decode11BytesTo8Bytes( outbuf, &inbuf[offset], dec_dat);
if (rez <= 0)
return false;// failed to decrypt
*outlen +=(unsigned int)rez;
outbuf +=8;
}
return true;
}
// decrypt c3/c4 packet
bool MU_DecodeC3C4( unsigned char* outbuf, muPacket* pkt, unsigned int* dec_dat, unsigned char* dec_key) {
unsigned char hdrSize =pkt->hdrSize();
unsigned char hdr =pkt->hdr();
unsigned short dec_size =0;
if( MU_ForceDecodeC3C4( &outbuf[hdrSize -1], &dec_size, pkt->contents(), pkt->contentSize(), dec_dat) ==false)
return false;// decryption fails
dec_size +=hdrSize -1;
*dec_key =outbuf[hdrSize -1];
outbuf[0] =hdr -2;
if( hdrSize ==2)
outbuf[1] =(unsigned char)dec_size;
else {
outbuf[1] =(unsigned char)((dec_size &~0x00FF) >> 8);
outbuf[2] =(unsigned char)(dec_size &~0xFF00);
}
return true;// decrypt success
}
// encrypt c3/c4 packet
bool MU_EncodeC3C4( unsigned char* outbuf, muPacket* pkt, unsigned int* dec_dat, unsigned char enc_key) {
unsigned char hdrSize =pkt->hdrSize();
unsigned char hdr =pkt->hdr();
unsigned short size =pkt->size();
unsigned char tmp =pkt->packet( hdrSize -1);
unsigned short enc_len =0;
pkt->packet( hdrSize -1) =enc_key;
bool rs =MU_ForceEncodeC3C4( &outbuf[hdrSize], &enc_len, &pkt->packet( hdrSize -1), size -hdrSize +1, dec_dat);
pkt->packet( hdrSize -1) =tmp;
if( rs ==true) {
outbuf[0] =hdr +2;
enc_len +=hdrSize;
if( hdrSize ==2)
outbuf[1] =(unsigned char)enc_len;
else {
outbuf[1] =(unsigned char)((enc_len &~0x00FF) >> 8);
outbuf[2] =(unsigned char)(enc_len &~0xFF00);
}
}
return rs;
}
// out_dat element count = 16
MuReadEncfileResult_t MuReadEncfile( char *file, unsigned int* out_dat ) {
FILE* stream =fopen( file, "rb");
if( stream ==0)
return MuReadEncfile_InvalidPath;
fseek( stream, 0, SEEK_END);
long size =ftell( stream);
if( size !=54)
return MuReadEncfile_FileCorrupted;
fseek( stream, 6, SEEK_SET);
unsigned int buf[4];
fread( buf, 4, 4, stream);
out_dat[ 0] = buf[0] ^ xor_tab_datfile[0];
out_dat[ 1] = buf[1] ^ xor_tab_datfile[1];
out_dat[ 2] = buf[2] ^ xor_tab_datfile[2];
out_dat[ 3] = buf[3] ^ xor_tab_datfile[3];
fread( buf, 4, 4, stream);
out_dat[ 4] = buf[0] ^ xor_tab_datfile[0];
out_dat[ 5] = buf[1] ^ xor_tab_datfile[1];
out_dat[ 6] = buf[2] ^ xor_tab_datfile[2];
out_dat[ 7] = buf[3] ^ xor_tab_datfile[3];
fread( buf, 4, 4, stream);
out_dat[ 8] = buf[0] ^ xor_tab_datfile[0];
out_dat[ 9] = buf[1] ^ xor_tab_datfile[1];
out_dat[10] = buf[2] ^ xor_tab_datfile[2];
out_dat[11] = buf[3] ^ xor_tab_datfile[3];
fclose( stream);
return MuReadEncfile_Success;
}
-
Re: C1/C2/C3/C4 Packet Encryption/Decryption source code (C++)
Really usefull but wrong section and forgot to add the [Guide] Tag
-
Re: C1/C2/C3/C4 Packet Encryption/Decryption source code (C++)
just wow, but didnt that already come along with to sobieh sources?
-
Re: C1/C2/C3/C4 Packet Encryption/Decryption source code (C++)
Quote:
Originally Posted by
CockMan
just wow, but didnt that already come along with to sobieh sources?
Yea I'm pretty sure it did.
Would of been nicer if he had used code tags on it, or saved it as a text instead of this long ass stream.
-
Re: C1/C2/C3/C4 Packet Encryption/Decryption source code (C++)
#1, Authors - -1 ....
P.S. -> Well stolen source __hitman47 and little remade under you and all...
P.S. -> The Credits it is necessary to leave CODER.........
-
Re: [Release]C1/C2/C3/C4 Packet Encryption/Decryption source code (C++)
-
1 Attachment(s)
Re: C1/C2/C3/C4 Packet Encryption/Decryption source code (C++)
Quote:
Originally Posted by
Lithic
Yea I'm pretty sure it did.
Would of been nicer if he had used code tags on it, or saved it as a text instead of this long ass stream.
Here you go.
It would be nice if a moderator could edit the thread's topic and place a release tag in front.
-
Re: C1/C2/C3/C4 Packet Encryption/Decryption source code (C++)
Quote:
Originally Posted by
MuForum.Info
#1, Authors - -1 ....
P.S. -> Well stolen source __hitman47 and little remade under you and all...
P.S. -> The Credits it is necessary to leave CODER.........
Well, i'm pretty sure my sources are a little remake of webzen sources too, huh?
-
Re: [Release]C1/C2/C3/C4 Packet Encryption/Decryption source code (C++)
Nice to see some latvian ppl doing something without crying about bugs. Labs darbs xD
-
Re: [Release]C1/C2/C3/C4 Packet Encryption/Decryption source code (C++)
-
Re: [Release]C1/C2/C3/C4 Packet Encryption/Decryption source code (C++)
Just to clear things up because so many idiots together can create a chain reaction of stupidity. Evolver is a known programmer that had enc/dec routines translated from asm a long time ago before anyone else had (maybe except MG group). He also was known for his excellent documentation on MU protocol.
If i am correct the following is a part of his documented list characters packet:
Code:
// not crypted
struct _OPF300
{
unsigned char op; // 0xF3
unsigned char op_2; // 0x00
unsigned char unknown1; // 0x02
unsigned char unknown2; // 0x00
unsigned char num; // number of character info blocks ( 0x00 < num < 0x06 ) ( 5 characters total )
//_OPF301_block character_infos[num]; // character info blocks
};
I think that Evolver is the same as the one here. If you don't know him you are >lol<
btw Evolver don't mind the idiots, good job, you are :ninja: afterall, so i didn't expect less :D
-
Re: [Release] C1/C2/C3/C4 Packet Encryption/Decryption source code (C++)
Thanks for this Evolver, this is great work and incredibly usefull!
quick note, comment in mu_encdec.h should be
Code:
// this algorythm uses dec data in this order:
// enc client->server (enc1.dat)
// dec client->server (dec1.dat)
// enc server->client (enc2.dat)
// dec server->client (dec2.dat)
it took me a while to understand where the problem was :P
-
Re: [Release] C1/C2/C3/C4 Packet Encryption/Decryption source code (C++)
Great job, but would be much better if you give more info such as if it's to hook in gs,or main(xD) & more :)
-
Re: [Release] C1/C2/C3/C4 Packet Encryption/Decryption source code (C++)
-
Re: [Release] C1/C2/C3/C4 Packet Encryption/Decryption source code (C++)
Who knows explain in detail for what mu_encdec and mu_packet
-
Re: [Release] C1/C2/C3/C4 Packet Encryption/Decryption source code (C++)
Quote:
Originally Posted by
=Battle=
Who knows explain in detail for what mu_encdec and mu_packet
mu_packet contents a class that gives to packet location (unsigned char) commons functions that are usually used (get header, get headersize...).
mu_encdec contents functions to decrypt encrypt these packets.
-
Re: [Release] C1/C2/C3/C4 Packet Encryption/Decryption source code (C++)
An issue has been found by sircid in MuPacketEncSize function. It incorrectly calculates destination buffer size if pkt->contentSize() %8 ==0, because in the code there wasn't taken in account one byte for enc_key. Here is a fix:
inline unsigned short MuPacketEncSpace( muPacket* pkt) {
unsigned short contentSize =pkt->contentSize() +1;
return((( contentSize /8) +(((contentSize %8) >0) ? 1 : 0)) *11) +pkt->hdrSize();
}
-
Re: [Release] C1/C2/C3/C4 Packet Encryption/Decryption source code (C++)
Quote:
Originally Posted by
Evolver
An issue has been found by sircid in MuPacketEncSize function. It incorrectly calculates destination buffer size if pkt->contentSize() %8 ==0, because in the code there wasn't taken in account one byte for enc_key. Here is a fix:
inline unsigned short MuPacketEncSpace( muPacket* pkt) {
unsigned short contentSize =pkt->contentSize() +1;
return((( contentSize /8) +(((contentSize %8) >0) ? 1 : 0)) *11) +pkt->hdrSize();
}
Now everything works 100% =)!
-
Re: [Release] C1/C2/C3/C4 Packet Encryption/Decryption source code (C++)
Hey guys, when I need to use MuPacketEncSpace() and MuPacketDecSpace() functions?
Until now, I was able to encrypt and decrypt without them. o_0
-
Re: [Release] C1/C2/C3/C4 Packet Encryption/Decryption source code (C++)
Quote:
Originally Posted by
thiforums
Hey guys, when I need to use MuPacketEncSpace() and MuPacketDecSpace() functions?
Until now, I was able to encrypt and decrypt without them. o_0
You need it coz they give you size of bytes that decrypted/encrypted packet would use. Which size do you set when you create an array :S?
-
1 Attachment(s)
Re: [Release] C1/C2/C3/C4 Packet Encryption/Decryption source code (C++)
here is delphi version
Code:
unit MUOnlineEncrypt;
interface
uses windows,
sysutils,
classes;
var
//Encryptacion
resultadoDesencriptado:TByteArray; //Desencryptado
resultadoEncriptado:TByteArray; //Encryptado
DecryptKeysServer:Array[0..11]of LongWord; //Llave para Desencriptacion en el Servidor y Encriptacion en el Cliente
EncryptKeysServer:Array[0..11]of LongWord; //Llave para Encriptacion en el Servidor y Desencriptacion en el Cliente
EncLen:Integer;
TempEnc:Array[0..3]of LongWord;
TempByte:PByteArray;
TempWord:Array[0..3]of Word;
XorByte:Byte;
TempDest,TempSrc:PByteArray;
TempPtr:PByteArray;
//PROCEDIMIENTOS PARA MUONLINE
procedure LoadKeys(ARchivo:String;var Where:Array of LongWord); //Carga las llaves desde Los archvios Enc1.dat y Dec2.dat
procedure DesencriptarC1(Coded:PByteArray;inicio,size:Integer);
procedure DesencriptarC2(Coded:PByteArray;inicio,size:Integer);
function DesencriptarC3(Coded:PByteArray;inicio,size:Integer;ToServer:Boolean):Integer;
procedure EncriptarC1(Data:PByteArray;inicio,size:Integer);
procedure EncriptarC2(Data:PByteArray;inicio,size:Integer);
function EncriptarC3(Data:PByteArray;inicio,size:Integer;ToServer:Boolean):Integer;
function coef2(a,b:integer):integer;
function coef1(a,b:integer):integer;
//EXAMPLES
const TestLen=$18;
const Temp6: array[0..TestLen-1] of Byte =
// ($C3,$0D,$06,$8A,$36,$37,$0B,$7C,$76,$6D,$35,$05,$30); //ServerToClient
// ($C3,$18,$70,$27,$2D,$95,$0A,$F9,$35,$E1,$08,$BD,$88,$5D,$FC,$2C,$57,$5C,$F5,$A1,$E0,$D1,$42,$77); //ServerToClient
// ($C3,$18,$D2,$39,$20,$BF,$91,$F2,$13,$3C,$C1,$A0,$95,$5D,$FC,$2C,$57,$5C,$F5,$A1,$E0,$D1,$4B,$77); //ServerToClient MOVE CDA+9+S+L (46CCE5) TO HAND (00)
($C3,$18,$8B,$90,$78,$F0,$13,$6A,$50,$31,$2D,$8C,$B9,
$3C,$82,$5D,$25,$D9,$05,$C3,$8B,$24,$57,$69); //ClientToServer NOT WORKING YET!! T_T!!
// ($C3,$0D,$3C,$82,$5D,$25,$D9,$05,$C3,$8B,$24,$57,$69); //ClientToServer NOT WORKING YET!! T_T!!
// ($C3,$18,$8B,$90,$78,$F0,$13,$6A,$50,$31,$2D,$0C,$39,
// $B4,$F0,$04,$94,$56,$07,$30,$A1,$D8,$7B,$4E); //ClientToServer NOT WORKING YET!! T_T!!
const KeyByteC1C2: array[0..31] of Byte =(231, **** 58, 137, 188, 178, 159, ****
35, 168, 254, 182, 73, 93, 57, 93,
138, 203, *** 141, 234, 125, 43, 95,
195, 177, 233, 131, 41, 81, 2*** 86);
const KeyByteC3C4: array[0..15] of Byte =($9B,$A7,$08,$3F,$87,$C2,$5C,$E2,
$B9,$7A,$D2,$93,$BF,$A7,$DE,$20);
//FsGate 1
//7D299AF0C73940FFCCAA1CE39E332A1C
//FsGate 2
//98 25 87 94 3F DE C2 1B B3 A2 0E F8 5B 92 1A A1
//GameServer
Const GameServerKey: Array[0..28] of Byte=($76,$FB,$E3,$9B,$5D,$D8,$B3,$3A,$25,$54,$95,$D0,$9C,$D6,$11,$95,
$A8,$61,$6D,$0B,$B9,$25,$6B,$0B,$74,$B1,$6B,$0B,$F8);
function Test():integer;
implementation
function Test():integer;
var
i:integer;
len:integer;
Str:String;
A,B:String;
P:PByte;
Pc,Pd:PByte;
begin
LoadKeys('Enc1.dat',DecryptKeysServer);
LoadKeys('Dec2.dat',EncryptKeysServer);
A:='';
SetLength(B,TestLen*2);
for i:=0 to TestLen-1 do begin
A:=A+chr(Temp6[i]);
end;
for i:=0 to TestLen*2-1 do begin
B[i+1]:=chr(0);
end;
Str:='';
WriteLn('Mensaje Original');
for i:=0 to TestLen-1 do begin
if ((i mod 16)=0)then begin
WriteLn(Str);
Str:='';
end;
Str:=Str+IntToHex(Temp6[i],2)+' ';
end;
WriteLn(Str);
Str:='';
WriteLn('Llave de Encriptacion en el Servidor');
for i:=0 to 11 do begin
if ((i mod 16)=0)then begin
WriteLn(Str);
Str:='';
end;
Str:=Str+IntToHex(EncryptKeysServer[i],6)+' ';
end;
WriteLn(Str);
Str:='';
WriteLn('Llave de Desencriptacion en el Servidor');
for i:=0 to 11 do begin
if ((i mod 16)=0)then begin
WriteLn(Str);
Str:='';
end;
Str:=Str+IntToHex(DecryptKeysServer[i],6)+' ';
end;
WriteLn(Str);
len:=DesencriptarC3(PByteArray(A),0,TestLen,true);
Str:='';
WriteLn('Mensaje Desencriptado');
for i:=0 to TestLen-1 do begin
if ((i mod 16)=0)then begin
WriteLn(Str);
Str:='';
end;
Str:=Str+IntToHex(ResultadoDesencriptado[i],2)+' ';
end;
WriteLn(Str);
len:=EncriptarC3(Addr(ResultadoDesencriptado[0]),0,len,true);
Str:='';
WriteLn('Mensaje Encriptado');
for i:=0 to len-1 do begin
if ((i mod 16)=0)then begin
WriteLn(Str);
Str:='';
end;
Str:=Str+IntToHex(ResultadoEncriptado[i],2)+' ';
end;
WriteLn(Str);
result:=0;
end;
{---------------------------------------------------------------------
Teorema de Bezout: si c=mcd(a,b) entonces existen enteros
alfa y beta tales que c= alfa*a + beta*b
----------------------------------------------------------------------}
function coef1(a,b:integer):integer;
begin
if (a mod b=0) then result:=0
else result:=coef2(b,a mod b);
end;
function coef2(a,b:integer):integer;
begin
if (a mod b=0) then result:=1
else result:=coef1(b,a mod b)-a div b*coef2(b,a mod b);
end;
{----------------------------------------------------------------------
Calculo del inverso modulo un entero.
Suponiendo que 1=mcd(m,n) entonces existen enteros a y b tales que
1=m.a+n.b y por tanto a es un inverso de a modulo n
Devuelve el inverso de m modulo n o 0 si no es inversible.
----------------------------------------------------------------------}
function invmod(m,n:integer):integer;
var a,b:integer;
begin
a:=coef1(m,n);
b:=coef2(m,n);
if(m*a+n*b <> 1)then begin
result:=0;
exit;
end;
while(a<0)do Inc(a,n);
result:=a;
end;
procedure LoadKeys(ARchivo:String;var Where:Array of LongWord);
var
Buff:Array[0..15]of Byte;
hFile:Cardinal;
BytesRead:LongWord;
i:integer;
begin
hFile:=CreateFile(PAnsiChar(ARchivo),GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
SetFilePointer(hFile,6,0,FILE_BEGIN);
ReadFile(hFile,Buff,16,bytesRead,0);
for i:=0 to 3 do Where[i]:=((KeyByteC3C4[4*i+3]shl 24)+(KeyByteC3C4[4*i+2]shl 16)+(KeyByteC3C4[4*i+1]shl 8)+KeyByteC3C4[4*i]) xor ((Buff[4*i+3]shl 24)+(Buff[4*i+2]shl 16)+(Buff[4*i+1]shl 8)+Buff[4*i]);
ReadFile(hFile,Buff,16,bytesRead,0);
for i:=0 to 3 do Where[i+4]:=((KeyByteC3C4[4*i+3]shl 24)+(KeyByteC3C4[4*i+2]shl 16)+(KeyByteC3C4[4*i+1]shl 8)+KeyByteC3C4[4*i]) xor ((Buff[4*i+3]shl 24)+(Buff[4*i+2]shl 16)+(Buff[4*i+1]shl 8)+Buff[4*i]);
ReadFile(hFile,Buff,16,bytesRead,0);
for i:=0 to 3 do Where[i+8]:=((KeyByteC3C4[4*i+3]shl 24)+(KeyByteC3C4[4*i+2]shl 16)+(KeyByteC3C4[4*i+1]shl 8)+KeyByteC3C4[4*i]) xor ((Buff[4*i+3]shl 24)+(Buff[4*i+2]shl 16)+(Buff[4*i+1]shl 8)+Buff[4*i]);
CloseHandle(hFile);
end;
//DESPLAZA EL BUFFER, USADO PARA ENCRIPTACION OK
procedure ShiftBuffer(Buff:PByteArray;Len:Integer;ShiftLen:integer);
var
i:integer;
begin
if(ShiftLen<>0)then begin
if(ShiftLen>0)then begin
if(Len>1)then begin
i:=Len-1;
while(i>0)do begin
Buff[i]:=(Buff[i-1]shl(8-ShiftLen))or(Buff[i]shr(ShiftLen));
i:=i-1;
end;
end;
Buff[0]:=Buff[0]shr ShiftLen;
exit;
end;
ShiftLen:=-ShiftLen;
if(Len>1)then
for i:=0 to Len-2 do Buff[i]:=(Buff[i+1]shr(8-ShiftLen))or(Buff[i]shl ShiftLen);
Buff[Len-1]:=Buff[Len-1]shl ShiftLen;
end;
end;
//ENCRIPTACION DEL BUFFER
function HashBuffer(Dest:PByteArray;Param10:integer;Src:PByteArray;Param18:integer;Param1c:integer):Integer;
var
BuffLen:integer;
EAX,ESI,EDI,CycleCount,i:integer;
Temp:TByteArray;
begin
BuffLen:=((Param1c+Param18-1)shr 3)-(Param18 shr 3)+2;
Temp[BuffLen-1]:=0;
for i:=0 to BuffLen-2 do Temp[i]:=Src[(Param18 shr 3)+i];
EAX:=(Param1c+Param18)and $80000007;
if(EAX<0)then EAX:=((EAX-1)or-8)+1;
if(EAX<>0)then Temp[BuffLen-2]:=Temp[BuffLen-2]and(($FF)shl LOBYTE(8-EAX));
ESI:=Param18 and $80000007;
if(ESI<0)then ESI:=((ESI-1)or-8)+1;
EDI:=Param10 and $80000007;
if(EDI<0)then EDI:=((EDI-1)or-8)+1;
ShiftBuffer(Addr(Temp),BuffLen-1,-ESI);
ShiftBuffer(Addr(Temp),BuffLen,EDI);
TempPtr:=Addr(Dest[(Param10 shr 3)]);
CycleCount:=BuffLen-1;
if(EDI>ESI)then
Inc(CycleCount);
if(CycleCount<>0)then begin
for i:=0 to CycleCount-1 do begin
TempPtr[i]:=TempPtr[i] or Temp[i];
end;
end;
result:=Param10+Param1c;
end;
function DecC3Bytes(Dest:PByteArray;Src:PByteArray;DecryptKeys:Array of LongWord):integer;
var
i,j:integer;
TempDec:Array[0..3] of LongWord;
Temp,Temp1:LongWord;
XorByte:Byte;
PTempDec:PByteArray;
begin
for i:=0 to 15 do Dest[i]:=0;
j:=0;
for i:=0 to 3 do TempDec[i]:=0;
PTempDec:=Addr(TempDec[0]);
for i:=0 to 3 do begin
HashBuffer(Addr(PTempDec[4*i]),0,Src,j,16);
Inc(j,16);
HashBuffer(Addr(PTempDec[4*i]),22,Src,j,2);
Inc(j,2);
end;
for i:=0 to 2 do TempDec[2-i]:=TempDec[2-i] xor DecryptKeys[8+2-i] xor(TempDec[2-i+1]and $FFFF);
Temp:=0;
for i:=0 to 3 do begin
Temp1:=((DecryptKeys[4+i]*(TempDec[i]))mod(DecryptKeys[i]))xor DecryptKeys[i+8] xor Temp;
Temp:=TempDec[i]and $FFFF;
Dest[2*i]:=LoWord(Temp1) and $FF;
Dest[2*i+1]:=LoWord(Temp1) shr 8;
end;
TempDec[0]:=0;
PTempDec:=Addr(TempDec[0]);
HashBuffer(PTempDec,0,Src,j,16);
PTempDec:=Addr(TempDec[0]);
PTempDec[0]:=PTempDec[1] xor PTempDec[0] xor $3D;
XorByte:=$F8;
for i:=0 to 7 do XorByte:=XorByte xor Dest[i];
if(XorByte<>PTempDec[1])then begin
result:=-1;
//WriteLn('Error al Desencriptar DecC3Bytes');
end else result:=PTempDec[0];
end;
function DecC3Buffer(Dest:PByteArray;Src:PByteArray;Len:Integer;DecryptKeys:Array of LongWord):integer;
var
DecLen:integer;
i:integer;
begin
result:=0;
if(Dest=nil) then exit;
DecLen:=0;
if(Len>0)then begin
i:=0;
while(DecLen<Len)do begin
if(DecC3Bytes(Addr(Dest[8*i]),Addr(Src[11*i]),DecryptKeys)<0)then begin
//exit;
end;
Inc(DecLen,11);
Inc(i);
result:=DecLen;
end;
end;
end;
procedure EncC3Bytes(Dest:PByteArray;Src:PByteArray;const Len:integer;EncryptKeys:Array of LongWord);
var
i,j:integer;
Temp,Temp2:LongWord;
inverse:integer;
begin
Temp:=0;
for i:=0 to 3 do begin
Temp2:=Src[2*i+1]shl 8 or Src[2*i];
inverse:=invmod(EncryptKeys[i+4],EncryptKeys[i])mod EncryptKeys[i];
TempEnc[i]:=((EncryptKeys[i+8]xor Temp2 xor Temp)*inverse)mod EncryptKeys[i];
Temp:=TempEnc[i]and$FFFF;
end;
Temp:=TempEnc[3]and$FFFF;
for i:=0 to 2 do begin
Temp2:=Temp;
Temp:=TempEnc[2-i]and$FFFF;
TempEnc[2-i]:=TempEnc[2-i]xor EncryptKeys[8+2-i]xor Temp2;
end;
j:=0;
for i:=0 to 10 do Dest[i]:=0;
TempByte:=Addr(TempEnc[0]);
for i:=0 to 3 do begin
j:=HashBuffer(Dest,j,Addr(TempByte[4*i]),0,16);
j:=HashBuffer(Dest,j,Addr(TempByte[4*i]),22,2);
end;
XorByte:=$F8;
for i:=0 to 7 do XorByte:=XorByte xor Src[i];
TempByte:=Addr(TempEnc[0]);
TempByte[1]:=XorByte;
TempByte[0]:=XorByte xor Len xor $3D;
HashBuffer(Dest,j,TempByte,0,16);
end;
function EncC3Buffer(Dest:PByteArray;Src:PByteArray;const Len:integer;EncryptKeys:Array of LongWord):integer;
var
i:integer;
begin
result:=0;
if(Dest=nil)then exit;
EncLen:=Len;
if(Len>0)then begin
i:=0;
While(EncLen>0)do begin
if(EncLen>7)then
EncC3Bytes(Addr(Dest[11*i]),Addr(Src[8*i]),8,EncryptKeys)
else
EncC3Bytes(Addr(Dest[11*i]),Addr(Src[8*i]),EncLen,EncryptKeys);
Dec(EncLen,8);
Inc(i);
end;
result:=Len;
end;
end;
procedure DesencriptarC1(Coded:PByteArray;inicio,size:Integer);
var
i:integer;
begin
for i:=0 to size-1 do begin
//Se copian los primeros 3 bytes
if(i<=2)then resultadoDesencriptado[i]:=coded[i+inicio]
else resultadoDesencriptado[i]:=coded[i+inicio] xor ( coded[i-1+inicio] xor keybyteC1C2[i mod 32] );
end;
end;
function DesencriptarC3(Coded:PByteArray;inicio,size:Integer;ToServer:Boolean):integer;
var
DecodedLen:Integer;
i:integer;
begin
resultadoDesencriptado[0]:=$C3;
resultadoDesencriptado[1]:=size;
if(ToServer)then begin
for i:=0 to size-1 do begin
ResultadoDesencriptado[i]:=0;
ResultadoEncriptado[i]:=0;
end;
DecodedLen:=DecC3Buffer(Addr(resultadoDesencriptado[2]),Addr(Coded[2+inicio]),Size-2,DecryptKeysServer);
Inc(DecodedLen,2);
for i:=0 to DecodedLen-1 do ResultadoEncriptado[i]:=ResultadoDesencriptado[i];
DesencriptarC1(Addr(resultadoencriptado[0]),0,DecodedLen);
end else begin
DecC3Buffer(Addr(resultadoDesencriptado[2]),Addr(Coded[2+inicio]),Size-2,EncryptKeysServer);
end;
result:=size;
ResultadoDesencriptado[0]:=$C3;
ResultadoDesencriptado[1]:=size;
end;
procedure DesencriptarC2(Coded:PByteArray;inicio,size:Integer);
var
i:integer;
begin
for i:=0 to size-1 do begin
//Se copian los primeros 3 bytes
if(i<=3)then resultadoDesencriptado[i]:=coded[i+inicio]
else resultadoDesencriptado[i]:=coded[i+inicio] xor ( coded[i-1+inicio] xor keybyteC1C2[i mod 32] );
end;
end;
procedure EncriptarC1(Data:PByteArray;inicio,size:Integer);
var
i:integer;
begin
for i:=0 to size-1 do begin
//Se copian los primeros 3 bytes
if(i<=2)then resultadoencriptado[i]:=Data[i+inicio]
else resultadoencriptado[i]:=Data[i+inicio] xor ( resultadoencriptado[i-1+inicio] xor keybyteC1C2[i mod 32] );
end;
end;
//SE ENCRIPTA 2 VECES
function EncriptarC3(Data:PByteArray;inicio,size:Integer;ToServer:Boolean):integer;
var
Temp:TByteArray;
EncodeLen:Integer;
i:integer;
begin
Temp[0]:=$C3;
if(ToServer)then begin
EncriptarC1(Data,inicio,size);
for i:=0 to size-1 do Temp[i]:=resultadoEncriptado[i];
EncodeLen:=EncC3Buffer(Addr(resultadoEncriptado[2]),Addr(Temp[2]),Size-2,DecryptKeysServer);
Inc(EncodeLen,2);
end else begin
EncodeLen:=EncC3Buffer(Addr(resultadoEncriptado[2]),Addr(Data[2+inicio]),Size-2,EncryptKeysServer);
Inc(EncodeLen,2);
end;
result:=EncodeLen;
ResultadoEncriptado[0]:=$C3;
ResultadoEncriptado[1]:=EncodeLen;
end;
procedure EncriptarC2(Data:PByteArray;inicio,size:Integer);
var
i:integer;
begin
for i:=0 to size-1 do begin
//Se copian los primeros 3 bytes
if(i<=3)then resultadoencriptado[i]:=Data[i+inicio]
else resultadoencriptado[i]:=Data[i+inicio] xor ( resultadoencriptado[i-1+inicio] xor keybyteC1C2[i mod 32] );
end;
end;
end.
i duuno who made this so credits gous to google =D
-
Re: [Release] C1/C2/C3/C4 Packet Encryption/Decryption source code (C++)
I was declaring my desinationt buffer as:
Code:
unsigned char enc_pkt[8192];
I hope the correct way should be:
Code:
unsigned char enc_pkt[MuPacketEncSpace(dec_pkt)];
Right?
-
Re: [Release] C1/C2/C3/C4 Packet Encryption/Decryption source code (C++)
Quote:
Originally Posted by
thiforums
I was declaring my desinationt buffer as:
Code:
unsigned char enc_pkt[8192];
I hope the correct way should be:
Code:
unsigned char enc_pkt[MuPacketEncSpace(dec_pkt)];
Right?
Most packets doesn't use more than 100bytes, so you have about 8kbytes of unused memory.
In other hand, don't know if that packet could exist ;), but theoretically a C4 packet could take up to 65535 bytes (0xFFFF). How do you decrypt it if you only have 8192 bytes?
Your code is wrong, it won't compile, coz [MuPacketEncSpace(dec_pkt) isn't a constant. So you must create a pointer and reserve memory dynamically. Use this form:
Code:
unsigned char* enc_pkt = new unsigned char[MuPacketEncSpace(dec_pkt)];
-
Re: [Release] C1/C2/C3/C4 Packet Encryption/Decryption source code (C++)
i see sircid u moved from vb to c++ =D
-
Re: [Release] C1/C2/C3/C4 Packet Encryption/Decryption source code (C++)
Quote:
Originally Posted by
mauka
i see sircid u moved from vb to c++ =D
yep =)! now I have realized that VB is a shit >.<!
-
Re: [Release] C1/C2/C3/C4 Packet Encryption/Decryption source code (C++)
Quote:
Originally Posted by
mauka
here is delphi version
Code:
unit MUOnlineEncrypt;
interface
uses windows,
sysutils,
classes;
var
//Encryptacion
resultadoDesencriptado:TByteArray; //Desencryptado
resultadoEncriptado:TByteArray; //Encryptado
DecryptKeysServer:Array[0..11]of LongWord; //Llave para Desencriptacion en el Servidor y Encriptacion en el Cliente
EncryptKeysServer:Array[0..11]of LongWord; //Llave para Encriptacion en el Servidor y Desencriptacion en el Cliente
EncLen:Integer;
TempEnc:Array[0..3]of LongWord;
TempByte:PByteArray;
TempWord:Array[0..3]of Word;
XorByte:Byte;
TempDest,TempSrc:PByteArray;
TempPtr:PByteArray;
//PROCEDIMIENTOS PARA MUONLINE
procedure LoadKeys(ARchivo:String;var Where:Array of LongWord); //Carga las llaves desde Los archvios Enc1.dat y Dec2.dat
procedure DesencriptarC1(Coded:PByteArray;inicio,size:Integer);
procedure DesencriptarC2(Coded:PByteArray;inicio,size:Integer);
function DesencriptarC3(Coded:PByteArray;inicio,size:Integer;ToServer:Boolean):Integer;
procedure EncriptarC1(Data:PByteArray;inicio,size:Integer);
procedure EncriptarC2(Data:PByteArray;inicio,size:Integer);
function EncriptarC3(Data:PByteArray;inicio,size:Integer;ToServer:Boolean):Integer;
function coef2(a,b:integer):integer;
function coef1(a,b:integer):integer;
//EXAMPLES
const TestLen=$18;
const Temp6: array[0..TestLen-1] of Byte =
// ($C3,$0D,$06,$8A,$36,$37,$0B,$7C,$76,$6D,$35,$05,$30); //ServerToClient
// ($C3,$18,$70,$27,$2D,$95,$0A,$F9,$35,$E1,$08,$BD,$88,$5D,$FC,$2C,$57,$5C,$F5,$A1,$E0,$D1,$42,$77); //ServerToClient
// ($C3,$18,$D2,$39,$20,$BF,$91,$F2,$13,$3C,$C1,$A0,$95,$5D,$FC,$2C,$57,$5C,$F5,$A1,$E0,$D1,$4B,$77); //ServerToClient MOVE CDA+9+S+L (46CCE5) TO HAND (00)
($C3,$18,$8B,$90,$78,$F0,$13,$6A,$50,$31,$2D,$8C,$B9,
$3C,$82,$5D,$25,$D9,$05,$C3,$8B,$24,$57,$69); //ClientToServer NOT WORKING YET!! T_T!!
// ($C3,$0D,$3C,$82,$5D,$25,$D9,$05,$C3,$8B,$24,$57,$69); //ClientToServer NOT WORKING YET!! T_T!!
// ($C3,$18,$8B,$90,$78,$F0,$13,$6A,$50,$31,$2D,$0C,$39,
// $B4,$F0,$04,$94,$56,$07,$30,$A1,$D8,$7B,$4E); //ClientToServer NOT WORKING YET!! T_T!!
const KeyByteC1C2: array[0..31] of Byte =(231, **** 58, 137, 188, 178, 159, ****
35, 168, 254, 182, 73, 93, 57, 93,
138, 203, *** 141, 234, 125, 43, 95,
195, 177, 233, 131, 41, 81, 2*** 86);
const KeyByteC3C4: array[0..15] of Byte =($9B,$A7,$08,$3F,$87,$C2,$5C,$E2,
$B9,$7A,$D2,$93,$BF,$A7,$DE,$20);
//FsGate 1
//7D299AF0C73940FFCCAA1CE39E332A1C
//FsGate 2
//98 25 87 94 3F DE C2 1B B3 A2 0E F8 5B 92 1A A1
//GameServer
Const GameServerKey: Array[0..28] of Byte=($76,$FB,$E3,$9B,$5D,$D8,$B3,$3A,$25,$54,$95,$D0,$9C,$D6,$11,$95,
$A8,$61,$6D,$0B,$B9,$25,$6B,$0B,$74,$B1,$6B,$0B,$F8);
function Test():integer;
implementation
function Test():integer;
var
i:integer;
len:integer;
Str:String;
A,B:String;
P:PByte;
Pc,Pd:PByte;
begin
LoadKeys('Enc1.dat',DecryptKeysServer);
LoadKeys('Dec2.dat',EncryptKeysServer);
A:='';
SetLength(B,TestLen*2);
for i:=0 to TestLen-1 do begin
A:=A+chr(Temp6[i]);
end;
for i:=0 to TestLen*2-1 do begin
B[i+1]:=chr(0);
end;
Str:='';
WriteLn('Mensaje Original');
for i:=0 to TestLen-1 do begin
if ((i mod 16)=0)then begin
WriteLn(Str);
Str:='';
end;
Str:=Str+IntToHex(Temp6[i],2)+' ';
end;
WriteLn(Str);
Str:='';
WriteLn('Llave de Encriptacion en el Servidor');
for i:=0 to 11 do begin
if ((i mod 16)=0)then begin
WriteLn(Str);
Str:='';
end;
Str:=Str+IntToHex(EncryptKeysServer[i],6)+' ';
end;
WriteLn(Str);
Str:='';
WriteLn('Llave de Desencriptacion en el Servidor');
for i:=0 to 11 do begin
if ((i mod 16)=0)then begin
WriteLn(Str);
Str:='';
end;
Str:=Str+IntToHex(DecryptKeysServer[i],6)+' ';
end;
WriteLn(Str);
len:=DesencriptarC3(PByteArray(A),0,TestLen,true);
Str:='';
WriteLn('Mensaje Desencriptado');
for i:=0 to TestLen-1 do begin
if ((i mod 16)=0)then begin
WriteLn(Str);
Str:='';
end;
Str:=Str+IntToHex(ResultadoDesencriptado[i],2)+' ';
end;
WriteLn(Str);
len:=EncriptarC3(Addr(ResultadoDesencriptado[0]),0,len,true);
Str:='';
WriteLn('Mensaje Encriptado');
for i:=0 to len-1 do begin
if ((i mod 16)=0)then begin
WriteLn(Str);
Str:='';
end;
Str:=Str+IntToHex(ResultadoEncriptado[i],2)+' ';
end;
WriteLn(Str);
result:=0;
end;
{---------------------------------------------------------------------
Teorema de Bezout: si c=mcd(a,b) entonces existen enteros
alfa y beta tales que c= alfa*a + beta*b
----------------------------------------------------------------------}
function coef1(a,b:integer):integer;
begin
if (a mod b=0) then result:=0
else result:=coef2(b,a mod b);
end;
function coef2(a,b:integer):integer;
begin
if (a mod b=0) then result:=1
else result:=coef1(b,a mod b)-a div b*coef2(b,a mod b);
end;
{----------------------------------------------------------------------
Calculo del inverso modulo un entero.
Suponiendo que 1=mcd(m,n) entonces existen enteros a y b tales que
1=m.a+n.b y por tanto a es un inverso de a modulo n
Devuelve el inverso de m modulo n o 0 si no es inversible.
----------------------------------------------------------------------}
function invmod(m,n:integer):integer;
var a,b:integer;
begin
a:=coef1(m,n);
b:=coef2(m,n);
if(m*a+n*b <> 1)then begin
result:=0;
exit;
end;
while(a<0)do Inc(a,n);
result:=a;
end;
procedure LoadKeys(ARchivo:String;var Where:Array of LongWord);
var
Buff:Array[0..15]of Byte;
hFile:Cardinal;
BytesRead:LongWord;
i:integer;
begin
hFile:=CreateFile(PAnsiChar(ARchivo),GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
SetFilePointer(hFile,6,0,FILE_BEGIN);
ReadFile(hFile,Buff,16,bytesRead,0);
for i:=0 to 3 do Where[i]:=((KeyByteC3C4[4*i+3]shl 24)+(KeyByteC3C4[4*i+2]shl 16)+(KeyByteC3C4[4*i+1]shl 8)+KeyByteC3C4[4*i]) xor ((Buff[4*i+3]shl 24)+(Buff[4*i+2]shl 16)+(Buff[4*i+1]shl 8)+Buff[4*i]);
ReadFile(hFile,Buff,16,bytesRead,0);
for i:=0 to 3 do Where[i+4]:=((KeyByteC3C4[4*i+3]shl 24)+(KeyByteC3C4[4*i+2]shl 16)+(KeyByteC3C4[4*i+1]shl 8)+KeyByteC3C4[4*i]) xor ((Buff[4*i+3]shl 24)+(Buff[4*i+2]shl 16)+(Buff[4*i+1]shl 8)+Buff[4*i]);
ReadFile(hFile,Buff,16,bytesRead,0);
for i:=0 to 3 do Where[i+8]:=((KeyByteC3C4[4*i+3]shl 24)+(KeyByteC3C4[4*i+2]shl 16)+(KeyByteC3C4[4*i+1]shl 8)+KeyByteC3C4[4*i]) xor ((Buff[4*i+3]shl 24)+(Buff[4*i+2]shl 16)+(Buff[4*i+1]shl 8)+Buff[4*i]);
CloseHandle(hFile);
end;
//DESPLAZA EL BUFFER, USADO PARA ENCRIPTACION OK
procedure ShiftBuffer(Buff:PByteArray;Len:Integer;ShiftLen:integer);
var
i:integer;
begin
if(ShiftLen<>0)then begin
if(ShiftLen>0)then begin
if(Len>1)then begin
i:=Len-1;
while(i>0)do begin
Buff[i]:=(Buff[i-1]shl(8-ShiftLen))or(Buff[i]shr(ShiftLen));
i:=i-1;
end;
end;
Buff[0]:=Buff[0]shr ShiftLen;
exit;
end;
ShiftLen:=-ShiftLen;
if(Len>1)then
for i:=0 to Len-2 do Buff[i]:=(Buff[i+1]shr(8-ShiftLen))or(Buff[i]shl ShiftLen);
Buff[Len-1]:=Buff[Len-1]shl ShiftLen;
end;
end;
//ENCRIPTACION DEL BUFFER
function HashBuffer(Dest:PByteArray;Param10:integer;Src:PByteArray;Param18:integer;Param1c:integer):Integer;
var
BuffLen:integer;
EAX,ESI,EDI,CycleCount,i:integer;
Temp:TByteArray;
begin
BuffLen:=((Param1c+Param18-1)shr 3)-(Param18 shr 3)+2;
Temp[BuffLen-1]:=0;
for i:=0 to BuffLen-2 do Temp[i]:=Src[(Param18 shr 3)+i];
EAX:=(Param1c+Param18)and $80000007;
if(EAX<0)then EAX:=((EAX-1)or-8)+1;
if(EAX<>0)then Temp[BuffLen-2]:=Temp[BuffLen-2]and(($FF)shl LOBYTE(8-EAX));
ESI:=Param18 and $80000007;
if(ESI<0)then ESI:=((ESI-1)or-8)+1;
EDI:=Param10 and $80000007;
if(EDI<0)then EDI:=((EDI-1)or-8)+1;
ShiftBuffer(Addr(Temp),BuffLen-1,-ESI);
ShiftBuffer(Addr(Temp),BuffLen,EDI);
TempPtr:=Addr(Dest[(Param10 shr 3)]);
CycleCount:=BuffLen-1;
if(EDI>ESI)then
Inc(CycleCount);
if(CycleCount<>0)then begin
for i:=0 to CycleCount-1 do begin
TempPtr[i]:=TempPtr[i] or Temp[i];
end;
end;
result:=Param10+Param1c;
end;
function DecC3Bytes(Dest:PByteArray;Src:PByteArray;DecryptKeys:Array of LongWord):integer;
var
i,j:integer;
TempDec:Array[0..3] of LongWord;
Temp,Temp1:LongWord;
XorByte:Byte;
PTempDec:PByteArray;
begin
for i:=0 to 15 do Dest[i]:=0;
j:=0;
for i:=0 to 3 do TempDec[i]:=0;
PTempDec:=Addr(TempDec[0]);
for i:=0 to 3 do begin
HashBuffer(Addr(PTempDec[4*i]),0,Src,j,16);
Inc(j,16);
HashBuffer(Addr(PTempDec[4*i]),22,Src,j,2);
Inc(j,2);
end;
for i:=0 to 2 do TempDec[2-i]:=TempDec[2-i] xor DecryptKeys[8+2-i] xor(TempDec[2-i+1]and $FFFF);
Temp:=0;
for i:=0 to 3 do begin
Temp1:=((DecryptKeys[4+i]*(TempDec[i]))mod(DecryptKeys[i]))xor DecryptKeys[i+8] xor Temp;
Temp:=TempDec[i]and $FFFF;
Dest[2*i]:=LoWord(Temp1) and $FF;
Dest[2*i+1]:=LoWord(Temp1) shr 8;
end;
TempDec[0]:=0;
PTempDec:=Addr(TempDec[0]);
HashBuffer(PTempDec,0,Src,j,16);
PTempDec:=Addr(TempDec[0]);
PTempDec[0]:=PTempDec[1] xor PTempDec[0] xor $3D;
XorByte:=$F8;
for i:=0 to 7 do XorByte:=XorByte xor Dest[i];
if(XorByte<>PTempDec[1])then begin
result:=-1;
//WriteLn('Error al Desencriptar DecC3Bytes');
end else result:=PTempDec[0];
end;
function DecC3Buffer(Dest:PByteArray;Src:PByteArray;Len:Integer;DecryptKeys:Array of LongWord):integer;
var
DecLen:integer;
i:integer;
begin
result:=0;
if(Dest=nil) then exit;
DecLen:=0;
if(Len>0)then begin
i:=0;
while(DecLen<Len)do begin
if(DecC3Bytes(Addr(Dest[8*i]),Addr(Src[11*i]),DecryptKeys)<0)then begin
//exit;
end;
Inc(DecLen,11);
Inc(i);
result:=DecLen;
end;
end;
end;
procedure EncC3Bytes(Dest:PByteArray;Src:PByteArray;const Len:integer;EncryptKeys:Array of LongWord);
var
i,j:integer;
Temp,Temp2:LongWord;
inverse:integer;
begin
Temp:=0;
for i:=0 to 3 do begin
Temp2:=Src[2*i+1]shl 8 or Src[2*i];
inverse:=invmod(EncryptKeys[i+4],EncryptKeys[i])mod EncryptKeys[i];
TempEnc[i]:=((EncryptKeys[i+8]xor Temp2 xor Temp)*inverse)mod EncryptKeys[i];
Temp:=TempEnc[i]and$FFFF;
end;
Temp:=TempEnc[3]and$FFFF;
for i:=0 to 2 do begin
Temp2:=Temp;
Temp:=TempEnc[2-i]and$FFFF;
TempEnc[2-i]:=TempEnc[2-i]xor EncryptKeys[8+2-i]xor Temp2;
end;
j:=0;
for i:=0 to 10 do Dest[i]:=0;
TempByte:=Addr(TempEnc[0]);
for i:=0 to 3 do begin
j:=HashBuffer(Dest,j,Addr(TempByte[4*i]),0,16);
j:=HashBuffer(Dest,j,Addr(TempByte[4*i]),22,2);
end;
XorByte:=$F8;
for i:=0 to 7 do XorByte:=XorByte xor Src[i];
TempByte:=Addr(TempEnc[0]);
TempByte[1]:=XorByte;
TempByte[0]:=XorByte xor Len xor $3D;
HashBuffer(Dest,j,TempByte,0,16);
end;
function EncC3Buffer(Dest:PByteArray;Src:PByteArray;const Len:integer;EncryptKeys:Array of LongWord):integer;
var
i:integer;
begin
result:=0;
if(Dest=nil)then exit;
EncLen:=Len;
if(Len>0)then begin
i:=0;
While(EncLen>0)do begin
if(EncLen>7)then
EncC3Bytes(Addr(Dest[11*i]),Addr(Src[8*i]),8,EncryptKeys)
else
EncC3Bytes(Addr(Dest[11*i]),Addr(Src[8*i]),EncLen,EncryptKeys);
Dec(EncLen,8);
Inc(i);
end;
result:=Len;
end;
end;
procedure DesencriptarC1(Coded:PByteArray;inicio,size:Integer);
var
i:integer;
begin
for i:=0 to size-1 do begin
//Se copian los primeros 3 bytes
if(i<=2)then resultadoDesencriptado[i]:=coded[i+inicio]
else resultadoDesencriptado[i]:=coded[i+inicio] xor ( coded[i-1+inicio] xor keybyteC1C2[i mod 32] );
end;
end;
function DesencriptarC3(Coded:PByteArray;inicio,size:Integer;ToServer:Boolean):integer;
var
DecodedLen:Integer;
i:integer;
begin
resultadoDesencriptado[0]:=$C3;
resultadoDesencriptado[1]:=size;
if(ToServer)then begin
for i:=0 to size-1 do begin
ResultadoDesencriptado[i]:=0;
ResultadoEncriptado[i]:=0;
end;
DecodedLen:=DecC3Buffer(Addr(resultadoDesencriptado[2]),Addr(Coded[2+inicio]),Size-2,DecryptKeysServer);
Inc(DecodedLen,2);
for i:=0 to DecodedLen-1 do ResultadoEncriptado[i]:=ResultadoDesencriptado[i];
DesencriptarC1(Addr(resultadoencriptado[0]),0,DecodedLen);
end else begin
DecC3Buffer(Addr(resultadoDesencriptado[2]),Addr(Coded[2+inicio]),Size-2,EncryptKeysServer);
end;
result:=size;
ResultadoDesencriptado[0]:=$C3;
ResultadoDesencriptado[1]:=size;
end;
procedure DesencriptarC2(Coded:PByteArray;inicio,size:Integer);
var
i:integer;
begin
for i:=0 to size-1 do begin
//Se copian los primeros 3 bytes
if(i<=3)then resultadoDesencriptado[i]:=coded[i+inicio]
else resultadoDesencriptado[i]:=coded[i+inicio] xor ( coded[i-1+inicio] xor keybyteC1C2[i mod 32] );
end;
end;
procedure EncriptarC1(Data:PByteArray;inicio,size:Integer);
var
i:integer;
begin
for i:=0 to size-1 do begin
//Se copian los primeros 3 bytes
if(i<=2)then resultadoencriptado[i]:=Data[i+inicio]
else resultadoencriptado[i]:=Data[i+inicio] xor ( resultadoencriptado[i-1+inicio] xor keybyteC1C2[i mod 32] );
end;
end;
//SE ENCRIPTA 2 VECES
function EncriptarC3(Data:PByteArray;inicio,size:Integer;ToServer:Boolean):integer;
var
Temp:TByteArray;
EncodeLen:Integer;
i:integer;
begin
Temp[0]:=$C3;
if(ToServer)then begin
EncriptarC1(Data,inicio,size);
for i:=0 to size-1 do Temp[i]:=resultadoEncriptado[i];
EncodeLen:=EncC3Buffer(Addr(resultadoEncriptado[2]),Addr(Temp[2]),Size-2,DecryptKeysServer);
Inc(EncodeLen,2);
end else begin
EncodeLen:=EncC3Buffer(Addr(resultadoEncriptado[2]),Addr(Data[2+inicio]),Size-2,EncryptKeysServer);
Inc(EncodeLen,2);
end;
result:=EncodeLen;
ResultadoEncriptado[0]:=$C3;
ResultadoEncriptado[1]:=EncodeLen;
end;
procedure EncriptarC2(Data:PByteArray;inicio,size:Integer);
var
i:integer;
begin
for i:=0 to size-1 do begin
//Se copian los primeros 3 bytes
if(i<=3)then resultadoencriptado[i]:=Data[i+inicio]
else resultadoencriptado[i]:=Data[i+inicio] xor ( resultadoencriptado[i-1+inicio] xor keybyteC1C2[i mod 32] );
end;
end;
end.
i duuno who made this so credits gous to google =D
does this code works? can som1 aprove it..
i try to decrypt c3 then encrypt it back and its rtrn wrong...
:grr:
c1&c2 works fine.. but c3 nope.. meybe i do somthing wrong
PS.
seems even test code retourn encrypted c3 wrong:grr::thumbdown:
Edited:
nwm! i got fully working enc/dec c1/c2/c3/c4 delphi unit
source posted above does not work..
-
Re: [Release] C1/C2/C3/C4 Packet Encryption/Decryption source code (C++)
Quote:
Originally Posted by
sircid
yep =)! now I have realized that VB is a shit >.<!
good for you:)
and dont forget foxes the client count c3/c4 packages and use it as 1'st byte of new one included within ecnryption ...
-
Re: C1/C2/C3/C4 Packet Encryption/Decryption source code (C++)
Is that so called old or new encryption ?