- Joined
- Feb 4, 2010
- Messages
- 2,203
- Reaction score
- 1,012
YOU WILL NEED TO EDIT IT ACCORDINGLY FOR YOUR MATCHSERVER(probably)
That is easy though, I've done it for myself and got it working there is a spot for a command of !stats that will not work for you no matter what as you don't have a /stats command
main.cpp
packet.h
struct.h
Have fun, and avoid fighting over who's it is.
That is easy though, I've done it for myself and got it working there is a spot for a command of !stats that will not work for you no matter what as you don't have a /stats command
main.cpp
Code:
#include <string>
#include <conio.h>
#include <windows.h>
#include "packet.h"
#include "struct.h"
#define BUFFER_SIZE 256
BYTE ran[] = {0x37, 0x04, 0x5D, 0x2E, 0x43, 0x3A, 0x49, 0x53, 0x50, 0x05, 0x13, 0xC9, 0x28, 0xA4, 0x4D, 0x05};
BYTE xor[] = {0x57, 0x02, 0x5B, 0x04, 0x34, 0x06, 0x01, 0x08, 0x37, 0x0A, 0x12, 0x69, 0x41, 0x38, 0x0F, 0x78};
#define VERSION 0x3a
#define FILELIST_CRC 0
#define ACCOUNT_NAME "testing22"
#define CHAR_NAME "testing22"
#define ACCOUNT_PASSWORD "notreallysecure"
#define HOME_CHANNEL MUID(0, 1)
MUID SVID;
MUID MYID;
MUID CHID;
BYTE KEY[32];
BYTE COUNTER;
SOCKET SOCK;
sockaddr_in SIN;
void WriteHex(void* A, char* B){
std::string patchstring = B;
char* token = strtok((char*)patchstring.c_str(), " ");
for(int i = 0; token != NULL; ++i){
BYTE b;
sscanf(token, "%X", &b);
((BYTE*)A)[i] = b;
token = strtok(NULL, " ");
}
}
void Talk(){
start:
SOCK = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
SIN.sin_family = AF_INET;
SIN.sin_addr.s_addr = inet_addr("89.46.35.33");
SIN.sin_port = htons(6000);
connect(SOCK, (sockaddr*)&SIN, sizeof(SIN));
PACKET_MANAGER in;
for(;;){
int rc;
rc = recv(SOCK, in.sbuffer, PACKET_MANAGER_BUFFER_SIZE, 0);
if(rc == 0 || rc == SOCKET_ERROR){
printf("DISCONNECTED\n");
goto start;
}
if(in.packet->version == 0xA){
printf("HANDSHAKE\n");
in.index = 6;
SVID = in.READ<MUID>();
MYID = in.READ<MUID>();
DWORD time = in.READ<DWORD>();
memcpy(KEY, in.buffer + 22, 4);
memcpy(KEY + 4, in.buffer + 10, 12);
memcpy(KEY + 16, ran, 16);
for(int i = 0; i < 16; ++i){
KEY[i] ^= xor[i];
}
PACKET_MANAGER out;
out.index = 8;
out.WRITE<WORD>(0x3e9);//login
out.WRITE<BYTE>(++COUNTER);//counter
out.WRITES(ACCOUNT_NAME);//name
out.WRITES(ACCOUNT_PASSWORD);//pass
out.WRITE<int>(VERSION);//version
out.WRITE<DWORD>(FILELIST_CRC);//crc
FILE* hashfile = fopen("hash.txt", "rb");
char hashstring[3 * 16];
fread(hashstring, 3, 16, hashfile);
fclose(hashfile);
BYTE hash[16];
WriteHex(hash, hashstring);
out.WRITEB(1, 16);//md5
out.WRITER((void*)hash, 16);
out.SET<WORD>(out.packet->size - 6, 6);
out.ENCRYPT(KEY);
send(SOCK, out.sbuffer, out.index, 0);
continue;
}
if(in.packet->version == 0x65){
in.DECRYPT(KEY);
}
WORD command = in.GET<WORD>(8);
switch(command){
case 0x142:{//ping
in.index = 11;
DWORD time = in.READ<DWORD>();
PACKET_MANAGER out;
out.index = 8;
out.WRITE<WORD>(0x143);//pong
out.WRITE<BYTE>(++COUNTER);//counter
out.WRITE<DWORD>(time);//time
out.SET<WORD>(out.packet->size - 6, 6);
out.ENCRYPT(KEY);
send(SOCK, out.sbuffer, out.index, 0);
break;
}
case 0x169:{//clock synch
break;
}
case 0x192:{//announce
in.index = 11;
int type = in.READ<int>();
char* msg = in.READS();
PACKET_MANAGER out;
out.index = 8;
out.WRITE<WORD>(0x4c9);//request channel chat
out.WRITE<BYTE>(++COUNTER);//counter
out.WRITE<MUID>(MYID);
out.WRITE<MUID>(CHID);
out.WRITES(msg);
out.SET<WORD>(out.packet->size - 6, 6);
out.ENCRYPT(KEY);
send(SOCK, out.sbuffer, out.index, 0);
break;
}
case 0x1f5:{//admin announce
in.index = 11;
MUID adminid = in.READ<MUID>();
char* message = in.READS();
printf("WALL: %s\n", message);
break;
}
case 0x3ea:{//response login
in.index = 11;
DWORD result = in.READ<DWORD>();
if(result != 0){
printf("LOGIN FAILED: %d\n", result);
goto start;
}
PACKET_MANAGER out;
out.index = 8;
out.WRITE<WORD>(0x6a5);//request char list
out.WRITE<BYTE>(++COUNTER);
out.WRITEB(1, 1);//dunno, but needed (message)
out.WRITE<BYTE>(0);
out.SET<WORD>(out.packet->size - 6, 6);
out.ENCRYPT(KEY);
send(SOCK, out.sbuffer, out.index, 0);
break;
}
case 0x4b7:{//response channel join
in.index = 11;
CHID = in.READ<MUID>();
DWORD type = in.READ<DWORD>();
char* name = in.READS();
printf("JOINED CHANNEL '%s'\n", name);
break;
}
case 0x4c6:{//channel player list
break;
}
case 0x4ca:{//channel chat
in.index = 11;
MUID id = in.READ<MUID>();
char* name = in.READS();
char* msg = in.READS();
int ugrade = in.READ<int>();
printf("%s: %s\n", name, msg);
if(id == MYID){
break;
}
char buffer[BUFFER_SIZE];
char* command = strtok(msg, " ");
if(command == NULL){
break;
}
if(_stricmp(command, "!stats") == 0){
sprintf_s(buffer, BUFFER_SIZE, "/stats %s", name);
char* target = strtok(NULL, "");
if(target != NULL){
sprintf_s(buffer, BUFFER_SIZE, "/stats %s", target);
}
PACKET_MANAGER out;
out.index = 8;
out.WRITE<WORD>(0x4c9);//request channel chat
out.WRITE<BYTE>(++COUNTER);//counter
out.WRITE<MUID>(MYID);//player id
out.WRITE<MUID>(MUID(0, -1));//channel id
out.WRITES(buffer);//message
out.SET<WORD>(out.packet->size - 6, 6);
out.ENCRYPT(KEY);
send(SOCK, out.sbuffer, out.index, 0);
break;
}
break;
}
case 0x4cf:{//channel rules
break;
}
case 0x522:{//stage list
break;
}
case 0x641:{
in.index = 11;
char* sender = in.READS();
char* receiver = in.READS();
char* msg = in.READS();
printf("from %s: %s\n", sender, msg);
PACKET_MANAGER out;
out.index = 8;
out.WRITE<WORD>(0x4c9);//request channel chat
out.WRITE<BYTE>(++COUNTER);//counter
out.WRITE<MUID>(MYID);
out.WRITE<MUID>(CHID);
char buffer[BUFFER_SIZE];
sprintf_s(buffer, BUFFER_SIZE, "%s says '%s'", sender, msg);
out.WRITES(buffer);
out.SET<WORD>(out.packet->size - 6, 6);
out.ENCRYPT(KEY);
send(SOCK, out.sbuffer, out.index, 0);
break;
}
case 0x6a6:{//response char list
in.index = 11;
in.READ<int>();//blob total size
in.READ<int>();//blob member size
int count = in.READ<int>();//blob member count
if(count > 0){
MTD_CharListInfo cli = in.READ<MTD_CharListInfo>();
PACKET_MANAGER out;
out.index = 8;
out.WRITE<WORD>(0x6a7);//request select char
out.WRITE<BYTE>(++COUNTER);
out.WRITE<MUID>(MYID);//player id
out.WRITE<int>(cli.nIndex);//index of char
out.SET<WORD>(out.packet->size - 6, 6);
out.ENCRYPT(KEY);
send(SOCK, out.sbuffer, out.index, 0);
break;
}
if(count == 0){
MTD_CharListInfo cli = in.READ<MTD_CharListInfo>();
PACKET_MANAGER out;
out.index = 8;
out.WRITE<WORD>(0x6af);//request create char
out.WRITE<BYTE>(++COUNTER);
out.WRITE<MUID>(MYID);//player id
out.WRITE<int>(0);//index
out.WRITES(CHAR_NAME);//name
out.WRITE<int>(0);//sex
out.WRITE<int>(0);//hair
out.WRITE<int>(0);//face
out.WRITE<int>(0);//class
out.SET<WORD>(out.packet->size - 6, 6);
out.ENCRYPT(KEY);
send(SOCK, out.sbuffer, out.index, 0);
break;
}
}
case 0x6a8:{//response select character
in.index = 11;
DWORD result = in.READ<DWORD>();
PACKET_MANAGER out;
out.index = 8;
out.WRITE<WORD>(0x4b5);//request channel join
out.WRITE<BYTE>(++COUNTER);
out.WRITE<MUID>(MYID);//player id
out.WRITE<MUID>(HOME_CHANNEL);//channel id
out.SET<WORD>(out.packet->size - 6, 6);
out.ENCRYPT(KEY);
send(SOCK, out.sbuffer, out.index, 0);
break;
}
case 0x6b0:{//response select character
in.index = 11;
DWORD result = in.READ<DWORD>();
if(result != 0){
printf("CHARACTER CREATION FAILED: %d\n", result);
goto start;
}
PACKET_MANAGER out;
out.index = 8;
out.WRITE<WORD>(0x6a5);//request char list
out.WRITE<BYTE>(++COUNTER);
out.WRITEB(1, 1);//dunno, but needed (message)
out.WRITE<BYTE>(0);
out.SET<WORD>(out.packet->size - 6, 6);
out.ENCRYPT(KEY);
send(SOCK, out.sbuffer, out.index, 0);
break;
}
default:{
print_packet((BYTE*)in.buffer, in.packet->size);
break;
}
}
}
}
int main(){
WSAData wsad;
WSAStartup(0x202, &wsad);
Talk();
return 0;
}
packet.h
Code:
#pragma once
typedef struct PACKET{
WORD version;
WORD size;
WORD checksum;
} PACKET;
#define PACKET_MANAGER_BUFFER_SIZE 0x400
typedef struct PACKET_MANAGER{
WORD index;
union{
PACKET* packet;
char* sbuffer;
BYTE* buffer;
};
void RESET(){
packet->version = 0x64;
packet->size = 0;
}
PACKET_MANAGER(){
sbuffer = (char*)malloc(PACKET_MANAGER_BUFFER_SIZE);
RESET();
}
PACKET_MANAGER(char* A){
sbuffer = A;
}
~PACKET_MANAGER(){
try{
free(buffer);
}
catch(...){
}
}
template <class T> void SET(T A, WORD B){
memcpy(buffer + B, &A, sizeof(T));
if((B + sizeof(T)) > packet->size){
packet->size = B + sizeof(T);
}
}
template <class T> T& GET(WORD B){
return *(T*)(buffer + B);
}
template <class T> void WRITE(T A){
memcpy(buffer + index, &A, sizeof(T));
index += sizeof(T);
if(index > packet->size){
packet->size = index;
}
}
template <class T> T& READ(){
T* ret = (T*)(buffer + index);
index += sizeof(T);
return *ret;
}
char* READS(){
WORD len = READ<WORD>();
char* ret = (char*)(buffer + index);
index += len;
if(index > packet->size){
return NULL;
}
return ret;
}
void WRITES(char* A){
WORD len = (WORD)strlen(A);
WRITE<WORD>(len + 2);
memcpy(buffer + index, A, len);
index += len;
WRITE<WORD>(0);
}
void WRITEB(DWORD A, DWORD B){
WRITE<DWORD>(A * B + 8);
WRITE<DWORD>(A);
WRITE<DWORD>(B);
}
void WRITER(void* A, WORD B){
memcpy(buffer + index, A, B);
index += B;
if(index > packet->size){
packet->size = index;
}
}
char* READR(WORD B){
char* ret = (char*)(buffer + index);
index += B;
return ret;
}
void ENCRYPT(BYTE* K){
index = packet->size;
for(int i = 0; i < packet->size; ++i){
WORD a = buffer[6 + i];
a ^= K[i % 32];
a <<= 5;
BYTE b = a >> 8;
b |= a & 0xff;
b ^= 0xf0;
buffer[6 + i] = b;
}
for(int i = 0; i < 2; ++i){
WORD a = buffer[2 + i];
a ^= K[i % 32];
a <<= 5;
BYTE b = a >> 8;
b |= a & 0xff;
b ^= 0xf0;
buffer[2 + i] = b;
}
packet->version = 0x65;
packet->checksum = 0;
for(int i = 6; i < index; ++i){
packet->checksum += buffer[i];
}
for(int i = 0; i < 4; ++i){
packet->checksum -= buffer[i];
}
#pragma warning(disable:4333)
packet->checksum += packet->checksum >> 0x10;
#pragma warning(default:4333)
}
void DECRYPT(BYTE* K){
for(int i = 0; i < 2; ++i){
BYTE a = buffer[2 + i];
a ^= 0xf0;
BYTE b = a & 0x1f;
a >>= 5;
b <<= 3;
b = a | b;
buffer[2 + i] = b ^ K[i % 32];
}
for(int i = 0; i < packet->size; ++i){
BYTE a = buffer[6 + i];
a ^= 0xf0;
BYTE b = a & 0x1f;
a >>= 5;
b <<= 3;
b = a | b;
buffer[6 + i] = b ^ K[i % 32];
}
packet->version = 0x64;
}
void CHECKSUM(){
index = packet->size;
packet->checksum = 0;
for(int i = 6; i < index; ++i){
packet->checksum += buffer[i];
}
for(int i = 0; i < 4; ++i){
packet->checksum -= buffer[i];
}
#pragma warning(disable:4333)
packet->checksum += packet->checksum >> 0x10;
#pragma warning(default:4333)
}
} PACKET_MANAGER;
void print_packet(BYTE* A, int B){
for(int i = 0; i < B; ++i){
printf("%.2x ", A[i]);
if(i % 16 == 0x0f && i != B){
printf("\n");
}
}
if(B % 16 != 0){
printf("\n");
}
}
struct.h
Code:
#pragma once
typedef struct MUID {
DWORD LowPart;
LONG HighPart;
MUID(){
LowPart = 0;
HighPart = 0;
}
MUID(DWORD A, LONG B){
LowPart = A;
HighPart = B;
}
operator bool(){
return this->HighPart != 0 || this->LowPart != 0;
}
} MUID;
bool operator==(const MUID& A, const MUID& B){
return A.HighPart == B.HighPart && A.LowPart == B.LowPart;
}
bool operator!=(const MUID& A, const MUID& B){
return (A == B) == false;
}
bool operator<(const MUID& A, const MUID& B){
return *(__int64*)&A < *(__int64*)&B;
}
bool operator>(const MUID& A, const MUID& B){
return *(__int64*)&A > *(__int64*)&B;
}
typedef struct LocatorData{
BYTE ip[4];
DWORD port;
BYTE index;
WORD playersmax;
WORD playerscurrent;
BYTE type;
BYTE active;
char name[64];
} LocatorData;
typedef struct MTD_CharListInfo{
char szName[32];
BYTE nIndex;
BYTE nLevel;
} MTD_CharListInfo;
typedef struct MTD_CharInfo{
char szName[32];
char szClanName[16];
DWORD nClanGrade;
WORD nClanContPoint;
char nCharNum;
WORD nLevel;
char nSex;
char nHair;
char nFace;
DWORD nXP;
int nBP;
float fBonusRate;
WORD nPrize;
WORD nHP;
WORD nAP;
WORD nMaxWeight;
WORD nSafeFalls;
WORD nFR;
WORD nCR;
WORD nER;
WORD nWR;
DWORD nEquipedItemDesc[12];
DWORD nUGradeID;
DWORD nClanCLID;
} MTD_CharInfo;
typedef struct MTD_ChannelPlayerListNode{
MUID uidPlayer;
char szName[32];
char szClanName[16];
char nLevel;
int nPlace;
BYTE nGrade;
BYTE nPlayerFlags;
DWORD nCLID;
DWORD nEmblemChecksum;
} MTD_ChannelPlayerListNode;
Have fun, and avoid fighting over who's it is.
Last edited:

