#include "main.h"
#define online_ver 356
SAMPFUNCS *SF = new SAMPFUNCS();
void encrypt(uint32_t* v, uint32_t* k)
{
/* set up */
uint32_t v0 = v[0];
uint32_t v1 = v[1];
uint32_t sum = 0;
uint32_t i;
/* a key schedule constant */
uint32_t delta = 0x9e3779b9;
/* cache key */
uint32_t k0 = k[0];
uint32_t k1 = k[1];
uint32_t k2 = k[2];
uint32_t k3 = k[3];
/* basic cycle start */
for (i = 0; i < 32; i++)
{
sum += delta;
v0 += ((v1 << 4) + k0) ^ (v1 + sum) ^ ((v1 >> 5) + k1);
v1 += ((v0 << 4) + k2) ^ (v0 + sum) ^ ((v0 >> 5) + k3);
}
/* end cycle */
v[0] = v0;
v[1] = v1;
}
bool __stdcall bypassORPC(stRakNetHookParams* params)
{
if (params->packetId == RPC_ClientJoin)
{
params->bitStream->ResetReadPointer();
params->bitStream->IgnoreBits(40);
char nickname[24];
uint8_t nickLen;
uint32_t challengeResponse;
params->bitStream->Read(nickLen);
params->bitStream->Read(nickname, nickLen);
nickname[nickLen] = '\0';
params->bitStream->Read(challengeResponse);
// 140
for(int i = 0; i < 5; ++i)
{
BitStream bs;
bs.Write<uint32_t>(online_ver);
bs.Write<uint8_t>(0);
SF->getRakNet()->SendRPC(140, &bs, HIGH_PRIORITY, RELIABLE_SEQUENCED, 0, false);
}
// cj
{
BitStream bs;
bs.Write<uint32_t>(0xFD9);
bs.Write<uint8_t>(1);
bs.Write(nickLen);
bs.Write(nickname, nickLen);
bs.Write(challengeResponse);
bs.Write<uint8_t>(42);
bs.Write("FF2BE5E6F5D9392F57C4E66F7AD78767277C6E4F6B", 42);
bs.Write<uint8_t>(5);
bs.Write("0.3.7", 5);
bs.Write<uint8_t>(2);
bs.Write<uint32_t>(online_ver);
SF->getRakNet()->SendRPC(RPC_ClientJoin, &bs, HIGH_PRIORITY, RELIABLE_SEQUENCED, 0, false);
}
return false;
}
return true;
}
bool __stdcall bypassIRPC(stRakNetHookParams* params)
{
if (params->packetId == 87)
{
uint16_t magic{};
uint32_t keys[4]{};
uint32_t data[2]{};
params->bitStream->Read(magic);
if (magic == 0xFFFF)
{
params->bitStream->Read((char*)&keys, sizeof(keys));
params->bitStream->Read((char*)&data, sizeof(data));
encrypt(data, keys);
BitStream bs;
bs.Write<uint16_t>(0xFFFF);
for (int i = 0; i < 17; i++)
{
bs.Write<uint8_t>(rand() & 0xFF);
}
bs.Write((char*)&data, sizeof(data));
SF->getRakNet()->SendRPC(83, &bs, SYSTEM_PRIORITY, RELIABLE_ORDERED, 0, false);
return false;
}
}
return true;
}
void __stdcall mainloop()
{
static bool initialized = false;
if (!initialized)
{
if (GAME && GAME->GetSystemState() == eSystemState::GS_PLAYING_GAME && SF->getSAMP()->IsInitialized())
{
srand((unsigned int)time(nullptr));
SF->getRakNet()->registerRakNetCallback(RAKHOOK_TYPE_OUTCOMING_RPC, bypassORPC);
SF->getRakNet()->registerRakNetCallback(RAKHOOK_TYPE_INCOMING_RPC, bypassIRPC);
initialized = true;
}
}
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReasonForCall, LPVOID lpReserved)
{
if (dwReasonForCall == DLL_PROCESS_ATTACH)
SF->initPlugin(mainloop, hModule);
return TRUE;
}