Last active
February 22, 2022 04:26
-
-
Save d33tah/3004d171a7804edbb113 to your computer and use it in GitHub Desktop.
A backup of Deenash Tibia bot I had on my SourceForge account. Dates back to 2008-06-22.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "includes.h" | |
#include <stdlib.h> | |
#include <cmath> | |
#include <string> | |
#include "gmp.h" | |
#ifndef __NETWORK_MESSAGE_H__ | |
#define __NETWORK_MESSAGE_H__ | |
struct Position | |
{ | |
int x, y, z; | |
}; | |
#define NETWORKMESSAGE_MAXSIZE 16768 | |
int MakeConnection(char* host, unsigned short port); | |
class RSA{ | |
public: | |
static RSA* getInstance(); | |
void encrypt(char* msg, long size); | |
void SetKey(const char* mod); | |
protected: | |
RSA(); | |
~RSA(); | |
static RSA* instance; | |
mpz_t m_e, m_mod, m, c; | |
}; | |
class NetworkMessage | |
{ | |
public: | |
// constructor/destructor | |
NetworkMessage(); | |
virtual ~NetworkMessage(); | |
//sets GPG key | |
void SetModulus(std::string modulus); | |
// resets the internal buffer to an empty message | |
void Reset(); | |
// socket functions | |
bool ReadFromSocket(SOCKET socket); | |
bool WriteToSocket(SOCKET socket); | |
bool isEnd(); | |
void DumpToFile(char* namne); | |
// simply read functions for incoming message | |
unsigned char GetByte(); | |
unsigned char InspectByte(); | |
unsigned short GetU16(); | |
unsigned short InspectU16(); | |
unsigned int GetU32(); | |
std::string GetString(); | |
Position GetPosition(); | |
void setEncryptionState(bool state); | |
void setEncryptionKey(const unsigned long* key); | |
// skips count unknown/unused bytes in an incoming message | |
void SkipBytes(int count); | |
// simply write functions for outgoing message | |
void AddByte(unsigned char value); | |
void AddU16 (unsigned short value); | |
void AddU32 (unsigned int value); | |
void AddString(const std::string &value); | |
void AddString(const char* value); | |
bool RSA_encrypt(); | |
int m_ReadPos; | |
std::string m_modulus; | |
int getMessageLength(){ | |
return m_MsgSize; | |
} | |
unsigned char m_MsgBuf[NETWORKMESSAGE_MAXSIZE]; | |
unsigned long m_key[4]; | |
protected: | |
inline bool canAdd(int size){ | |
return (size + m_ReadPos < NETWORKMESSAGE_MAXSIZE - 16); | |
}; | |
void XTEA_encrypt(); | |
void XTEA_decrypt(); | |
bool m_encryptionEnabled; | |
bool m_keyset; | |
int m_MsgSize; | |
}; | |
#endif // #ifndef __NETWORK_MESSAGE_H__ | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef __CONST79H__ | |
#define __CONST79H__ | |
#define CIPSOFT_MODULUS "124710459426827943004376449897985582167801707960697037164044904862948569380850421396904597686953877022394604239428185498284169068581802277612081027966724336319448537811441719076484340922854929273517308661370727105382899118999403808045846444647284499123164879035103627004668521005328367415259939915284902061793" | |
#define OTSERV_MODULUS "109120132967399429278860960508995541528237502902798129123468757937266291492576446330739696001110603907230888610072655818825358503429057592827629436413108566029093628212635953836686562675849720620786279431090218017681061521755056710823876476444260558147179707119674283982419152118103759076030616683978566631413" | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "includes.h" | |
#include "comm.h" | |
#include <iostream> | |
#include <string> | |
int MakeConnection(char* host, unsigned short port) | |
{ | |
#ifdef WIN32 | |
WSAData wsadata; | |
if(WSAStartup(MAKEWORD(1,1),&wsadata) != 0) | |
{ | |
std::cout << "Fatal error - cannot initialize Winsock" << std::endl; | |
exit(1); | |
} | |
#endif | |
int sock = socket(AF_INET, SOCK_STREAM, 0); | |
struct sockaddr_in sin; | |
sin.sin_family = AF_INET; | |
struct hostent* nhost = NULL; | |
nhost = gethostbyname(host); | |
sin.sin_addr.s_addr = ((struct in_addr *)(nhost->h_addr))->s_addr; | |
sin.sin_port = htons(port); | |
if(connect(sock, (struct sockaddr *)&sin, sizeof(sin)) != 0) | |
{ | |
std::cout << "Cannot connect to server." << std::endl; | |
return 0; | |
} | |
return sock; | |
} | |
int ___gmpn_bases = 0; | |
RSA* RSA::instance = NULL; | |
RSA* RSA::getInstance() | |
{ | |
if(!instance){ | |
instance = new RSA; | |
} | |
return instance; | |
} | |
RSA::RSA() | |
{ | |
mpz_init2(m_mod, 1024); | |
mpz_init2(m_e, 32); | |
} | |
RSA::~RSA() | |
{ | |
mpz_clear(m_mod); | |
mpz_clear(m_e); | |
} | |
void RSA::SetKey(const char* mod) | |
{ | |
mpz_set_ui(m_e, 65537); | |
mpz_set_str(m_mod, mod, 10); | |
} | |
void RSA::encrypt(char *msg, long size) | |
{ | |
mpz_init2(m, 1024); | |
mpz_init2(c, 1024); | |
mpz_import(m, 128, 1, 1, 0, 0, msg); | |
mpz_powm(c, m, m_e, m_mod); | |
size_t count = (mpz_sizeinbase(c, 2) + 7)/8; | |
memset(msg, 0, 128 - count); | |
mpz_export(&msg[128 - count], NULL, 1, 1, 0, 0, c); | |
mpz_clear(m); | |
mpz_clear(c); | |
} | |
void NetworkMessage::DumpToFile(char* fname) | |
{ | |
FILE* file=NULL; | |
if (!fname) | |
{ | |
return; | |
} | |
file = fopen(fname,"wb"); | |
if (!file) return; | |
fwrite((char*)m_MsgBuf, 1, m_MsgSize+4, file); | |
fclose(file); | |
} | |
NetworkMessage::NetworkMessage() | |
{ | |
Reset(); | |
m_encryptionEnabled = false; | |
m_keyset = false; | |
} | |
void NetworkMessage::SetModulus(std::string modulus) | |
{ | |
m_modulus=modulus; | |
} | |
NetworkMessage::~NetworkMessage() | |
{ | |
} | |
void NetworkMessage::Reset() | |
{ | |
m_MsgSize = 0; | |
m_ReadPos = 2; | |
} | |
bool NetworkMessage::ReadFromSocket(SOCKET socket) | |
{ | |
int p = 0; | |
int t = 0; | |
while(true) | |
{ | |
if(p == 0) | |
t = recv(socket, (char*)m_MsgBuf, 2, 0); | |
else | |
t = recv(socket, (char*)m_MsgBuf+p, std::min(m_MsgSize-p+2, 1000), 0); | |
if(t == 0){ std::cout << "Failure: [NetworkMessage::ReadFromSocket]. Socket disconnected." << std::endl; }; | |
#if defined WIN32 || defined __WINDOWS__ | |
int errnum; | |
errnum = ::WSAGetLastError(); | |
if(errnum == WSAEWOULDBLOCK){ | |
m_MsgSize = 0; | |
return true; | |
} | |
#endif | |
if(p == 0) m_MsgSize = m_MsgBuf[0] | m_MsgBuf[1] << 8; | |
if(((p == 0) && (t != 2)) || (m_MsgSize > NETWORKMESSAGE_MAXSIZE-2)) | |
{ | |
Reset(); | |
std::cout << "Failure: [NetworkMessage::ReadFromSocket]. Socket error." << | |
( (p == 0) ? "(p == 0)" : "(t != 2)" ) <<std::endl; | |
return false; | |
} | |
p += t; | |
if(m_MsgSize == p-2) break; | |
} | |
m_ReadPos = 2; | |
//decrypt | |
if(m_encryptionEnabled){ | |
if(!m_keyset){ | |
std::cout << "Failure: [NetworkMessage::ReadFromSocket]. Key not set" << std::endl; | |
return false; | |
} | |
if((m_MsgSize) % 8 != 0){ | |
std::cout << "Failure: [NetworkMessage::ReadFromSocket]. Not valid encrypted message size" << std::endl; | |
return false; | |
} | |
XTEA_decrypt(); | |
int tmp = InspectU16(); | |
if(tmp > m_MsgSize - 2){ | |
std::cout << "Failure: [NetworkMessage::ReadFromSocket]. Not valid unencrypted message size" << std::endl; | |
return false; | |
} | |
m_MsgSize = tmp; | |
} | |
return true; | |
} | |
bool NetworkMessage::WriteToSocket(SOCKET socket) | |
{ | |
if (m_MsgSize == 0) | |
return true; | |
m_MsgBuf[0] = (unsigned char)(m_MsgSize); | |
m_MsgBuf[1] = (unsigned char)(m_MsgSize >> 8); | |
bool ret = true; | |
int sendBytes = 0; | |
int flags; | |
#if defined WIN32 || defined __WINDOWS__ | |
// Set the socket I/O mode; iMode = 0 for blocking; iMode != 0 for non-blocking | |
unsigned long mode = 1; | |
ioctlsocket(socket, FIONBIO, &mode); | |
flags = 0; | |
#else | |
flags = MSG_DONTWAIT; | |
#endif | |
int retry = 0; | |
int start; | |
if(m_encryptionEnabled){ | |
if(!m_keyset){ | |
std::cout << "Failure: [NetworkMessage::ReadFromSocket]. Key not set" << std::endl; | |
return false; | |
} | |
start = 0; | |
memcpy((char*)m_MsgBuf+2, (char*)m_MsgBuf, m_MsgSize+2); | |
XTEA_encrypt(); | |
} | |
else{ | |
start = 0; | |
} | |
do{ | |
int b = send(socket, (char*)m_MsgBuf+sendBytes+start, std::min(m_MsgSize-sendBytes+2, 1000), flags); | |
if(b <= 0) | |
{ | |
ret = false; | |
break; | |
} | |
sendBytes += b; | |
}while(sendBytes < m_MsgSize+2); | |
#if defined WIN32 || defined __WINDOWS__ | |
mode = 0; | |
ioctlsocket(socket, FIONBIO, &mode); | |
#endif | |
return ret; | |
} | |
bool NetworkMessage::isEnd() | |
{ | |
return m_MsgSize <= m_ReadPos-4; | |
} | |
unsigned char NetworkMessage::GetByte() | |
{ | |
return m_MsgBuf[m_ReadPos++]; | |
} | |
unsigned char NetworkMessage::InspectByte() | |
{ | |
return m_MsgBuf[m_ReadPos]; | |
} | |
unsigned short NetworkMessage::GetU16() | |
{ | |
unsigned short v = ((m_MsgBuf[m_ReadPos]) | (m_MsgBuf[m_ReadPos+1] << 8)); | |
m_ReadPos += 2; | |
return v; | |
} | |
unsigned short NetworkMessage::InspectU16() | |
{ | |
unsigned short v = ((m_MsgBuf[m_ReadPos]) | (m_MsgBuf[m_ReadPos+1] << 8)); | |
return v; | |
} | |
unsigned int NetworkMessage::GetU32() | |
{ | |
unsigned int v = ((m_MsgBuf[m_ReadPos ] ) | (m_MsgBuf[m_ReadPos+1] << 8) | | |
(m_MsgBuf[m_ReadPos+2] << 16) | (m_MsgBuf[m_ReadPos+3] << 24)); | |
m_ReadPos += 4; | |
return v; | |
} | |
std::string NetworkMessage::GetString() | |
{ | |
int stringlen = GetU16(); | |
if (stringlen >= (16384 - m_ReadPos)) | |
return std::string(); | |
char* v = (char*)(m_MsgBuf+m_ReadPos); | |
m_ReadPos += stringlen; | |
return std::string(v, stringlen); | |
} | |
Position NetworkMessage::GetPosition() | |
{ | |
Position pos; | |
pos.x = GetU16(); | |
pos.y = GetU16(); | |
pos.z = GetByte(); | |
return pos; | |
} | |
void NetworkMessage::SkipBytes(int count) | |
{ | |
m_ReadPos += count; | |
} | |
void NetworkMessage::AddByte(unsigned char value) | |
{ | |
if(!canAdd(1)) | |
return; | |
m_MsgBuf[m_ReadPos++] = value; | |
m_MsgSize++; | |
} | |
void NetworkMessage::AddU16(unsigned short value) | |
{ | |
if(!canAdd(2)) | |
return; | |
m_MsgBuf[m_ReadPos++] = (unsigned char)(value); | |
m_MsgBuf[m_ReadPos++] = (unsigned char)(value >> 8); | |
m_MsgSize += 2; | |
} | |
void NetworkMessage::AddU32(unsigned int value) | |
{ | |
if(!canAdd(4)) | |
return; | |
m_MsgBuf[m_ReadPos++] = (unsigned char)(value); | |
m_MsgBuf[m_ReadPos++] = (unsigned char)(value >> 8); | |
m_MsgBuf[m_ReadPos++] = (unsigned char)(value >> 16); | |
m_MsgBuf[m_ReadPos++] = (unsigned char)(value >> 24); | |
m_MsgSize += 4; | |
} | |
void NetworkMessage::AddString(const std::string &value) | |
{ | |
AddString(value.c_str()); | |
} | |
void NetworkMessage::AddString(const char* value) | |
{ | |
unsigned long stringlen = (unsigned long) strlen(value); | |
if(!canAdd(stringlen+2) || stringlen > 8192) | |
return; | |
AddU16(stringlen); | |
strcpy((char*)m_MsgBuf + m_ReadPos, value); | |
m_ReadPos += stringlen; | |
m_MsgSize += stringlen; | |
} | |
bool NetworkMessage::RSA_encrypt() | |
{ | |
RSA* rsa = RSA::getInstance(); | |
rsa->SetKey(m_modulus.c_str()); | |
rsa->encrypt((char*)&m_MsgBuf[m_ReadPos-128], 128); | |
return true; | |
} | |
void NetworkMessage::setEncryptionState(bool state) | |
{ | |
m_encryptionEnabled = state; | |
} | |
void NetworkMessage::setEncryptionKey(const unsigned long* key) | |
{ | |
memcpy(m_key, key, 16); | |
m_keyset = true; | |
} | |
void NetworkMessage::XTEA_encrypt() | |
{ | |
unsigned long k[4]; | |
k[0] = m_key[0]; k[1] = m_key[1]; k[2] = m_key[2]; k[3] = m_key[3]; | |
//add bytes until reach 8 multiple | |
unsigned long n; | |
if(((m_MsgSize + 2) % 8) != 0){ | |
n = 8 - ((m_MsgSize + 2) % 8); | |
memset((void*)&m_MsgBuf[m_ReadPos], 0, n); | |
m_MsgSize = m_MsgSize + n; | |
} | |
unsigned long read_pos = 0; | |
unsigned long* buffer = (unsigned long*)&m_MsgBuf[2]; | |
while(read_pos < m_MsgSize/4){ | |
unsigned long v0 = buffer[read_pos], v1 = buffer[read_pos + 1]; | |
unsigned long delta = 0x61C88647; | |
unsigned long sum = 0; | |
for(unsigned long i = 0; i<32; i++) { | |
v0 += ((v1 << 4 ^ v1 >> 5) + v1) ^ (sum + k[sum & 3]); | |
sum -= delta; | |
v1 += ((v0 << 4 ^ v0 >> 5) + v0) ^ (sum + k[sum>>11 & 3]); | |
} | |
buffer[read_pos] = v0; buffer[read_pos + 1] = v1; | |
read_pos = read_pos + 2; | |
} | |
m_MsgSize = m_MsgSize + 2; | |
m_MsgBuf[0] = (unsigned char)(m_MsgSize); | |
m_MsgBuf[1] = (unsigned char)(m_MsgSize >> 8); | |
} | |
void NetworkMessage::XTEA_decrypt() | |
{ | |
unsigned long k[4]; | |
k[0] = m_key[0]; k[1] = m_key[1]; k[2] = m_key[2]; k[3] = m_key[3]; | |
unsigned long* buffer = (unsigned long*)&m_MsgBuf[2]; | |
unsigned long read_pos = 0; | |
while(read_pos < m_MsgSize/4){ | |
unsigned long v0 = buffer[read_pos], v1 = buffer[read_pos + 1]; | |
unsigned long delta = 0x61C88647; | |
unsigned long sum = 0xC6EF3720; | |
for(unsigned long i = 0; i<32; i++) { | |
v1 -= ((v0 << 4 ^ v0 >> 5) + v0) ^ (sum + k[sum>>11 & 3]); | |
sum += delta; | |
v0 -= ((v1 << 4 ^ v1 >> 5) + v1) ^ (sum + k[sum & 3]); | |
} | |
buffer[read_pos] = v0; buffer[read_pos + 1] = v1; | |
read_pos = read_pos + 2; | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef __OTTHREAD_H__ | |
#define __OTTHREAD_H__ | |
#if defined WIN32 || defined __WINDOWS__ | |
#include <winsock.h> | |
#else // #if defined WIN32 || defined __WINDOWS__ | |
#include <semaphore.h> | |
#include <time.h> | |
#include <sys/types.h> | |
#include <sys/timeb.h> | |
#include <sys/socket.h> | |
#include <netinet/in.h> | |
#include <arpa/inet.h> | |
#include <netdb.h> | |
#include <stdint.h> | |
#include <errno.h> | |
inline void OTSYS_SLEEP(int t) | |
{ | |
timespec tv; | |
tv.tv_sec = t / 1000; | |
tv.tv_nsec = (t % 1000)*1000000; | |
nanosleep(&tv, NULL); | |
} | |
#ifndef SOCKET | |
#define SOCKET int | |
#endif | |
#ifndef closesocket | |
#define closesocket close | |
#endif | |
#endif // #if defined WIN32 || defined __WINDOWS__ | |
#endif // #ifndef __OTTHREAD_H__ | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "protocol.h" | |
#include <iostream> | |
//change these ones before compiling! | |
#ifndef SERVER | |
#define SERVER "localhost" | |
#endif | |
#ifndef PORT | |
#define PORT 7171 | |
#endif | |
#ifndef ACCNUM | |
#define ACCNUM 111111 | |
#endif | |
#ifndef PASSWORD | |
#define PASSWORD "tibia" | |
#endif | |
//not yet implemented, at the moment it logs first character anyways-configure in protocol.h | |
//(character to log in is the parameter in ConnectToGS in Connection's constructor) | |
#define CHARACTER "GM" | |
int main() | |
{ | |
Connection conn ( SERVER , PORT , ACCNUM , PASSWORD , CHARACTER); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
OBJ = comm.o protocol.o main.o tb_xtea.o | |
all: deenash | |
deenash: $(OBJ) | |
g++ -o deenash $(OBJ) -lgmp | |
%.o:%.cpp | |
g++ -c -g $+ | |
clean: | |
rm -f *.o deenash |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "comm.h" | |
#include "protocol.h" | |
#include "const79.h" | |
//Zionz's XTEA hacks: XTEA code was proved to be wrong, the correct patches are to be used manually | |
#include "tb_xtea.h" | |
int ParseItem ( int ID ) { return 0; } | |
void Connection::PrepareLogin(char* lhost, unsigned short lport, unsigned long laccnum, std::string lpass) | |
{ | |
pass = lpass; | |
port = lport; | |
host = lhost; | |
accnum = laccnum; | |
} | |
void Connection::ConnectToLS() | |
{ | |
netmsg.setEncryptionState(false); | |
socket = MakeConnection(host, port); | |
if (strcmp(host, "login01.tibia.com")) { | |
netmsg.SetModulus(OTSERV_MODULUS); | |
std::cout << "Using OTServ modulus." << std::endl; | |
} | |
else | |
{ | |
netmsg.SetModulus(CIPSOFT_MODULUS); | |
std::cout << "Using Cipsoft modulus." << std::endl; | |
} | |
netmsg.Reset(); | |
netmsg.AddByte(0x01); | |
netmsg.AddU16(0x02); //os | |
netmsg.AddU16(0x32B); //version | |
netmsg.AddU32(0x47f60e37); //tibia.dat signature | |
netmsg.AddU32(0x47ebb9b2); //tibia.spr signature | |
netmsg.AddU32(0x4742fcd7); //tibia.pic signature | |
netmsg.AddByte(0x00); //first byte of encrypted packet should be 0 | |
unsigned long k[4]; | |
k[0] = (rand()%0xFFFFFFFF); //generates random 128 bit key for tea | |
k[1] = (rand()%0xFFFFFFFF); | |
k[2] = (rand()%0xFFFFFFFF); | |
k[3] = (rand()%0xFFFFFFFF); | |
netmsg.AddU32(k[0]); | |
netmsg.AddU32(k[1]); | |
netmsg.AddU32(k[2]); | |
netmsg.AddU32(k[3]); | |
netmsg.AddU32(accnum); | |
netmsg.AddString(pass); | |
//size of buffer should be 128 bytes, so it's filled with 0 | |
for(int x = 23+strlen(pass.c_str()); x != 128; x++) netmsg.AddByte(0x00); | |
netmsg.RSA_encrypt(); | |
if(!netmsg.WriteToSocket(socket)) | |
{ | |
std::cout << "Socket error or encryption failed!" << std::endl; | |
return; | |
} | |
netmsg.setEncryptionState(true); | |
netmsg.setEncryptionKey(k); | |
netmsg.ReadFromSocket(socket); | |
//REMOVE AFTER CHANGING FROM INSPECT TO GET IN NETWORKMESSAGE.CPP! | |
netmsg.SkipBytes(2); | |
unsigned char opt = netmsg.GetByte(); | |
switch(opt) | |
{ | |
case 0x0A: LoginMsg(); | |
break; | |
case 0x14: motd(); | |
break; | |
default: | |
std::cout << "Unknown packet header" << std::endl; | |
break; | |
} | |
CharacterList(); | |
closesocket(socket); | |
socket = 0; | |
} | |
void Connection::LoginMsg() | |
{ | |
std::cout << netmsg.GetString() << std::endl; | |
} | |
void Connection::motd() | |
{ | |
std::cout << netmsg.GetString() << std::endl; | |
} | |
void Connection::CharacterList() | |
{ | |
if(netmsg.GetByte() != 0x64) | |
{ | |
std::cout << "Fatal error, character list header excepted" << std::endl; | |
return; | |
} | |
int count = netmsg.GetByte(); | |
CharList = new Character[count]; | |
int longest = 0; | |
for(int curr = 0;curr != count;curr++) | |
{ | |
CharList[curr].name = netmsg.GetString(); | |
std::cout << curr+1 << "." << CharList[curr].name << "("; | |
CharList[curr].servername = netmsg.GetString(); | |
std::cout << CharList[curr].servername << ")"; | |
unsigned long IP = netmsg.GetU32(); | |
sprintf(CharList[curr].host, "%d.%d.%d.%d", (unsigned char)(IP), (unsigned char)(IP >> 8), (unsigned char)(IP >> 16), (unsigned char)(IP >> 24)); | |
CharList[curr].port = netmsg.GetU16(); | |
std::cout << "[" << CharList[curr].host << ":" << CharList[curr].port << "]" << std::endl; | |
} | |
} | |
void Connection::ConnectToGS(int which) | |
{ | |
socket = MakeConnection(CharList[which].host, CharList[which].port); | |
std::cout << "Connecting to game server. Please wait..." << std::endl; | |
netmsg.setEncryptionState(false); | |
netmsg.Reset(); | |
netmsg.AddByte(0x0A); | |
netmsg.AddU16(0x02); //os | |
netmsg.AddU16(0x32B); //version | |
netmsg.AddByte(0x00); //first byte of encrypted packet should be 0 | |
unsigned long k[4]; | |
k[0] = (rand()%0xFFFFFFFF); //generates random 128 bit key for tea | |
k[1] = (rand()%0xFFFFFFFF); | |
k[2] = (rand()%0xFFFFFFFF); | |
k[3] = (rand()%0xFFFFFFFF); | |
netmsg.AddU32(k[0]); | |
netmsg.AddU32(k[1]); | |
netmsg.AddU32(k[2]); | |
netmsg.AddU32(k[3]); | |
netmsg.AddByte(0x00); //? | |
netmsg.AddU32(accnum); | |
netmsg.AddString(CharList[which].name); | |
netmsg.AddString(pass); | |
//size of buffer should be 128 bytes, so it's filled with 0 | |
for(int x = 26+strlen(pass.c_str())+strlen(CharList[which].name.c_str()); x != 128; x++) netmsg.AddByte(0x00); | |
netmsg.RSA_encrypt(); | |
if(!netmsg.WriteToSocket(socket)) | |
{ | |
std::cout << "Socket error or encryption failed" << std::endl; | |
return; | |
} | |
netmsg.setEncryptionState(true); | |
netmsg.setEncryptionKey(k); | |
netmsg.ReadFromSocket(socket); netmsg.SkipBytes(2); | |
unsigned char opt = netmsg.InspectByte(); | |
if(opt != 0x0A) | |
{ | |
switch(opt) | |
{ | |
case 0x14: netmsg.SkipBytes(1); LoginMsg(); break; | |
case 0x16: netmsg.SkipBytes(1); if(socket) closesocket(socket); socket = 0; WaitingList(); return; break; | |
default: break; | |
} | |
if(socket) closesocket(socket); | |
socket = 0; | |
delete[] CharList; | |
} | |
else //succesfully connected to GS | |
{ | |
delete[] CharList; | |
ReceiveLoop(); | |
} | |
} | |
void Connection::WaitingList() { | |
std::string smsg = netmsg.GetString(); | |
int time = netmsg.GetByte(); | |
for(int x = 0; x != time; x++) | |
{ | |
std::stringstream nmsg; | |
nmsg << smsg << "\nRetry in: " << (time-x) << " seconds."; | |
std::cout << nmsg.str() << std::endl; | |
OTSYS_SLEEP(1000); | |
} | |
ConnectToGS(0); } | |
void Connection::ReceiveLoop() { | |
ParsePacket(); //parse first msg which was already read by Connection | |
while(netmsg.ReadFromSocket(socket)) | |
{ | |
netmsg.SkipBytes(2); | |
ParsePacket(); | |
} | |
if(socket) | |
{ closesocket(socket); | |
socket = 0; | |
} } | |
void Connection::ParsePacket() { | |
unsigned char opt; | |
do | |
{ | |
opt = netmsg.GetByte(); | |
std::cout.setf(std::ios::dec); | |
switch(opt) | |
{ | |
case 0x0A: { netmsg.SkipBytes(7); break; } | |
case 0x1E: { | |
netmsg.AddByte(0x1E); | |
netmsg.WriteToSocket(socket); | |
char buf[1024]; | |
buf[0]=0x08; | |
buf[1]=0x00; | |
buf[2]=0x01; | |
buf[3]=0x00; | |
buf[4]=0x65; | |
EncodeXTEA((unsigned char*)&buf[2],8,netmsg.m_key); | |
send(socket,buf, 10, MSG_DONTWAIT); | |
printf("Ping packet!\n"); | |
break; | |
} | |
case 0x64: { PlayerPos = netmsg.GetPosition(); getMapDescription(PlayerPos.x - 8, PlayerPos.y - 6, PlayerPos.z, 18, 14); break; } | |
default: std::cout << "Unknown packet: 0x" << std::hex << (int) opt << std::endl; netmsg.SkipBytes(netmsg.getMessageLength()); break; | |
} | |
} | |
while(!netmsg.isEnd()); } | |
void Connection::getMapDescription(int x, int y, int z, int width, int height) | |
{ | |
int startz, endz, zstep, skip = 0; | |
if(z> 7) { | |
startz = z - 2; | |
endz = std::min(15, z + 2); | |
zstep = 1; | |
} | |
else { | |
startz = 7; | |
endz = 0; | |
zstep = -1; | |
} | |
int zDescriptionOffset = 0; | |
for(int nz = startz; nz != endz + zstep; nz += zstep) { | |
getFloorDescription(x, y, nz, width, height, z - nz, skip); | |
} | |
} | |
void Connection::getFloorDescription(int x, int y, int z, int width, int height, int offset, int skipTiles) | |
{ | |
int cc = 0; | |
int optbyte; | |
int skip = skipTiles; | |
for (int nx = 0; nx < width; nx++){ | |
for (int ny = 0; ny < height; ny++) { | |
if(skip == 0){ | |
optbyte = netmsg.InspectU16(); | |
if(optbyte >= 0xFF00){ | |
skip = (netmsg.GetU16() & 0xFF); | |
cc++; | |
} | |
else{ | |
//read tile | |
Position pos = {x + nx + offset, y + ny + offset, z}; | |
getTileDescription(pos); | |
cc++; | |
skip = (netmsg.GetU16() & 0xFF); | |
} | |
} | |
else{ | |
cc++; | |
skip--; | |
} | |
} | |
} | |
skipTiles = skip; | |
} | |
void Connection::getTileDescription(Position pos) | |
{ | |
while(1){ | |
unsigned short id = netmsg.InspectU16(); | |
if(id >= 0xFF00) | |
{ | |
return; | |
} | |
else | |
{ | |
getItem(); | |
} | |
} | |
} | |
void Connection::getItem() { | |
unsigned short id = netmsg.InspectU16(); | |
if(id == 0x0061 || id == 0x0062) | |
{ | |
netmsg.SkipBytes(4); | |
(id==0x0062 ? netmsg.SkipBytes(4) : netmsg.SkipBytes(8) ); | |
(netmsg.GetU16()!= 0 ? netmsg.SkipBytes(5) : netmsg.SkipBytes(2) ); | |
netmsg.SkipBytes(6); | |
} | |
else if(id == 0x0063) | |
{ | |
netmsg.SkipBytes(7); | |
} | |
else | |
netmsg.SkipBytes(ParseItem(netmsg.GetU16())); | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef PROTOCOL_H | |
#define PROTOCOL_H | |
#include <string> | |
#include <map> | |
#include <iostream> | |
#include <sstream> | |
#include "comm.h" | |
int MakeConnection(char* host, unsigned short port); | |
struct Character | |
{ | |
char host[16]; | |
std::string servername; | |
std::string name; | |
unsigned short port; | |
}; | |
class Connection | |
{ | |
public: | |
Connection(char* lhost, unsigned short lport, unsigned long laccnum, std::string lpass , std::string lname) | |
{ PrepareLogin (lhost, lport, laccnum, lpass) ; ConnectToLS (); ConnectToGS(0); } ; | |
private: | |
SOCKET socket; | |
Position PlayerPos; | |
NetworkMessage netmsg; | |
void getMapDescription (int x, int y, int z, int width, int height); | |
void getFloorDescription(int x, int y, int z, int width, int height, int offset, int skipTiles); | |
void getTileDescription(Position pos); | |
void getItem (); | |
void CharacterList(); | |
void PrepareLogin(char* lhost, unsigned short lport, unsigned long laccnum, std::string lpass); | |
void ConnectToLS(); | |
void ConnectToGS(int which); | |
void WaitingList(); | |
void motd(); | |
void LoginMsg(); | |
void ParsePacket(); | |
void ReceiveLoop(); | |
unsigned long accnum; | |
Character* CharList; | |
std::string pass; | |
char* host; | |
unsigned short port; | |
}; | |
#endif | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright (C) 2007 ZioNz - juancv87@gmail.com | |
* | |
* This program is free software; you can redistribute it and/or modify | |
* it under the terms of the GNU General Public License as published by | |
* the Free Software Foundation; either version 2 of the License, or | |
* (at your option) any later version. | |
* | |
* This program is distributed in the hope that it will be useful, | |
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
* GNU General Public License for more details. | |
* | |
* You should have received a copy of the GNU General Public License | |
* along with this program; if not, write to the Free Software | |
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
*/ | |
#include <iostream> | |
using namespace std; | |
void xtea_decipher(unsigned long *v, unsigned long *k){ | |
unsigned long v0=v[0], v1=v[1], i; | |
unsigned long sum=0xC6EF3720, delta=0x9E3779B9; | |
for(i=0; i<32; i++){ | |
v1 -= ((v0 << 4 ^ v0 >> 5) + v0) ^ (sum + k[sum>>11 & 3]); | |
sum -= delta; | |
v0 -= ((v1 << 4 ^ v1 >> 5) + v1) ^ (sum + k[sum & 3]); | |
} | |
v[0]=v0; v[1]=v1; | |
} | |
void DecodeXTEA(unsigned char *data,int d_tam,unsigned long *k){ | |
int pos=0; | |
while(pos<d_tam){ | |
xtea_decipher((unsigned long*)&data[pos],k); | |
pos+=8; | |
} | |
} | |
void xtea_encipher(unsigned long* v, unsigned long* k){ | |
unsigned long v0=v[0], v1=v[1], i; | |
unsigned long sum=0, delta=0x9E3779B9; | |
for(i=0; i<32; i++) { | |
v0 += ((v1 << 4 ^ v1 >> 5) + v1) ^ (sum + k[sum & 3]); | |
sum += delta; | |
v1 += ((v0 << 4 ^ v0 >> 5) + v0) ^ (sum + k[sum>>11 & 3]); | |
} | |
v[0]=v0; v[1]=v1; | |
} | |
void EncodeXTEA(unsigned char *data,int d_tam,unsigned long *k){ | |
int pos=0; | |
while(pos<d_tam){ | |
xtea_encipher((unsigned long*)&data[pos],k); | |
pos+=8; | |
} | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright (C) 2007 ZioNz - juancv87@gmail.com | |
* | |
* This program is free software; you can redistribute it and/or modify | |
* it under the terms of the GNU General Public License as published by | |
* the Free Software Foundation; either version 2 of the License, or | |
* (at your option) any later version. | |
* | |
* This program is distributed in the hope that it will be useful, | |
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
* GNU General Public License for more details. | |
* | |
* You should have received a copy of the GNU General Public License | |
* along with this program; if not, write to the Free Software | |
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
*/ | |
#ifndef _TB_XTEA_H | |
#define _TB_XTEA_H | |
#include <iostream> | |
using namespace std; | |
void DecodeXTEA(unsigned char *data,int d_tam,unsigned long *k); | |
void EncodeXTEA(unsigned char *data,int d_tam,unsigned long *k); | |
#endif | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment