Skip to content

Instantly share code, notes, and snippets.

@d33tah
Last active February 22, 2022 04:26
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save d33tah/3004d171a7804edbb113 to your computer and use it in GitHub Desktop.
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.
#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__
#ifndef __CONST79H__
#define __CONST79H__
#define CIPSOFT_MODULUS "124710459426827943004376449897985582167801707960697037164044904862948569380850421396904597686953877022394604239428185498284169068581802277612081027966724336319448537811441719076484340922854929273517308661370727105382899118999403808045846444647284499123164879035103627004668521005328367415259939915284902061793"
#define OTSERV_MODULUS "109120132967399429278860960508995541528237502902798129123468757937266291492576446330739696001110603907230888610072655818825358503429057592827629436413108566029093628212635953836686562675849720620786279431090218017681061521755056710823876476444260558147179707119674283982419152118103759076030616683978566631413"
#endif
#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;
}
}
#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__
#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);
}
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
#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()));
}
#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
/*
* 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;
}
}
/*
* 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