void WardenWin::HandleData(ByteBuffer& buff) { sLog.outDebug("Handle data"); m_WardenDataSent = false; m_WardenKickTimer = 0; uint16 Length; buff >> Length; uint32 Checksum; buff >> Checksum; if (!IsValidCheckSum(Checksum, buff.contents() + buff.rpos(), Length)) { buff.rpos(buff.wpos()); if (sWorld.getConfig(CONFIG_WARDEN_KICK)) Client->KickPlayer(); return; } bool found = false; //TIMING_CHECK { uint8 result; buff >> result; // @todo test it. if (result == 0x00) { sLog.outWarden("TIMING CHECK FAIL result 0x00"); found = true; } uint32 newClientTicks; buff >> newClientTicks; uint32 ticksNow = getMSTime(); uint32 ourTicks = newClientTicks + (ticksNow - ServerTicks); sLog.outDebug("ServerTicks %u", ticksNow); // now sLog.outDebug("RequestTicks %u", ServerTicks); // at request sLog.outDebug("Ticks %u", newClientTicks); // at response sLog.outDebug("Ticks diff %u", ourTicks - newClientTicks); } WardenDataResult* rs; WardenData* rd; uint8 type; for (std::vector<uint32>::iterator itr = SendDataId.begin(); itr != SendDataId.end(); ++itr) { rd = WardenDataStorage.GetWardenDataById(*itr); rs = WardenDataStorage.GetWardenResultById(*itr); type = rd->Type; switch (type) { case MEM_CHECK: { uint8 Mem_Result; buff >> Mem_Result; if (Mem_Result != 0) { sLog.outWarden("RESULT MEM_CHECK not 0x00, CheckId %u account Id %u", rd->id, Client->GetAccountId()); found = true; continue; } if (memcmp(buff.contents() + buff.rpos(), rs->res.AsByteArray(0, false), rd->Length) != 0) { sLog.outWarden("RESULT MEM_CHECK fail CheckId %u account Id %u", rd->id, Client->GetAccountId()); found = true; buff.rpos(buff.rpos() + rd->Length); continue; } buff.rpos(buff.rpos() + rd->Length); sLog.outDebug("RESULT MEM_CHECK passed CheckId %u account Id %u", rd->id, Client->GetAccountId()); break; } case PAGE_CHECK_A: case PAGE_CHECK_B: case DRIVER_CHECK: case MODULE_CHECK: { const uint8 byte = 0xE9; if (memcmp(buff.contents() + buff.rpos(), &byte, sizeof(uint8)) != 0) { if (type == PAGE_CHECK_A || type == PAGE_CHECK_B) sLog.outWarden("RESULT PAGE_CHECK fail, CheckId %u account Id %u", rd->id, Client->GetAccountId()); if (type == MODULE_CHECK) sLog.outWarden("RESULT MODULE_CHECK fail, CheckId %u account Id %u", rd->id, Client->GetAccountId()); if (type == DRIVER_CHECK) sLog.outWarden("RESULT DRIVER_CHECK fail, CheckId %u account Id %u", rd->id, Client->GetAccountId()); found = true; buff.rpos(buff.rpos() + 1); continue; } buff.rpos(buff.rpos() + 1); if (type == PAGE_CHECK_A || type == PAGE_CHECK_B) sLog.outDebug("RESULT PAGE_CHECK passed CheckId %u account Id %u", rd->id, Client->GetAccountId()); else if (type == MODULE_CHECK) sLog.outDebug("RESULT MODULE_CHECK passed CheckId %u account Id %u", rd->id, Client->GetAccountId()); else if (type == DRIVER_CHECK) sLog.outDebug("RESULT DRIVER_CHECK passed CheckId %u account Id %u", rd->id, Client->GetAccountId()); break; } case LUA_STR_CHECK: { uint8 Lua_Result; buff >> Lua_Result; if (Lua_Result != 0) { sLog.outWarden("RESULT LUA_STR_CHECK fail, CheckId %u account Id %u", rd->id, Client->GetAccountId()); found = true; continue; } uint8 luaStrLen; buff >> luaStrLen; if (luaStrLen != 0) { char* str = new char[luaStrLen + 1]; memset(str, 0, luaStrLen + 1); memcpy(str, buff.contents() + buff.rpos(), luaStrLen); sLog.outDebug("Lua string: %s", str); delete[] str; } buff.rpos(buff.rpos() + luaStrLen); // skip string sLog.outDebug("RESULT LUA_STR_CHECK passed, CheckId %u account Id %u", rd->id, Client->GetAccountId()); break; } case MPQ_CHECK: { uint8 Mpq_Result; buff >> Mpq_Result; if (Mpq_Result != 0) { sLog.outWarden("RESULT MPQ_CHECK not 0x00 account id %u", Client->GetAccountId()); found = true; continue; } if (memcmp(buff.contents() + buff.rpos(), rs->res.AsByteArray(0), 20) != 0) // SHA1 { sLog.outWarden("RESULT MPQ_CHECK fail, CheckId %u account Id %u", rd->id, Client->GetAccountId()); found = true; buff.rpos(buff.rpos() + 20); // 20 bytes SHA1 continue; } buff.rpos(buff.rpos() + 20); // 20 bytes SHA1 sLog.outDebug("RESULT MPQ_CHECK passed, CheckId %u account Id %u", rd->id, Client->GetAccountId()); break; } default: // should never happens break; } } if (found && sWorld.getConfig(CONFIG_WARDEN_KICK)) Client->KickPlayer(); }
void WardenWin::RequestData() { sLog.outDebug("Request data"); if (MemCheck.empty()) MemCheck.assign(WardenDataStorage.MemCheckIds.begin(), WardenDataStorage.MemCheckIds.end()); ServerTicks = getMSTime(); uint32 id; uint8 type; WardenData* wd; SendDataId.clear(); for (uint32 i = 0; i < sWorld.getConfig(CONFIG_WARDEN_NUM_CHECKS); ++i) // for now include 3 MEM_CHECK's { if (MemCheck.empty()) break; id = MemCheck.back(); SendDataId.push_back(id); MemCheck.pop_back(); } ByteBuffer buff; buff << uint8(WARDEN_SMSG_CHEAT_CHECKS_REQUEST); // This doesn't apply for 2.4.3 //for (int i = 0; i < 5; ++i) // for now include 5 random checks //{ // id = irand(1, maxid - 1); // wd = WardenDataStorage.GetWardenDataById(id); // SendDataId.push_back(id); // switch (wd->Type) // { // case MPQ_CHECK: // case LUA_STR_CHECK: // case DRIVER_CHECK: // buff << uint8(wd->str.size()); // buff.append(wd->str.c_str(), wd->str.size()); // break; // default: // break; // } //} uint8 xorByte = InputKey[0]; buff << uint8(0x00); buff << uint8(TIMING_CHECK ^ xorByte); // check TIMING_CHECK uint8 index = 1; for (std::vector<uint32>::iterator itr = SendDataId.begin(); itr != SendDataId.end(); ++itr) { wd = WardenDataStorage.GetWardenDataById(*itr); type = wd->Type; buff << uint8(type ^ xorByte); switch (type) { case MEM_CHECK: { buff << uint8(0x00); buff << uint32(wd->Address); buff << uint8(wd->Length); break; } case PAGE_CHECK_A: case PAGE_CHECK_B: { buff.append(wd->i.AsByteArray(0), wd->i.GetNumBytes()); buff << uint32(wd->Address); buff << uint8(wd->Length); break; } case MPQ_CHECK: case LUA_STR_CHECK: { buff << uint8(index++); break; } case DRIVER_CHECK: { buff.append(wd->i.AsByteArray(0), wd->i.GetNumBytes()); buff << uint8(index++); break; } case MODULE_CHECK: { uint32 seed = rand32(); buff << uint32(seed); HmacHash hmac(4, (uint8*)&seed); hmac.UpdateData(wd->str); hmac.Finalize(); buff.append(hmac.GetDigest(), hmac.GetLength()); break; } /*case PROC_CHECK: { buff.append(wd->i.AsByteArray(0, false), wd->i.GetNumBytes()); buff << uint8(index++); buff << uint8(index++); buff << uint32(wd->Address); buff << uint8(wd->Length); break; }*/ default: break; // should never happens } } buff << uint8(xorByte); buff.hexlike(); // Encrypt with warden RC4 key. EncryptData(const_cast<uint8*>(buff.contents()), buff.size()); WorldPacket pkt(SMSG_WARDEN_DATA, buff.size()); pkt.append(buff); Client->SendPacket(&pkt); m_WardenDataSent = true; std::stringstream stream; stream << "Sent check id's: "; for (std::vector<uint32>::iterator itr = SendDataId.begin(); itr != SendDataId.end(); ++itr) stream << *itr << " "; sLog.outDebug("%s", stream.str().c_str()); }
void WardenWin::HandleData(ByteBuffer &buff) { sLog->outStaticDebug("Handle data"); m_WardenDataSent = false; m_WardenKickTimer = 0; bool forceKick = false; uint16 Length; buff >> Length; uint32 Checksum; buff >> Checksum; if(!IsValidCheckSum(Checksum, buff.contents() + buff.rpos(), Length)) { buff.rpos(buff.wpos()); if(sWorld->getBoolConfig(CONFIG_BOOL_WARDEN_KICK)) Client->KickPlayer(); return; } bool found = false; uint8 banDays = 0; //TIMING_CHECK { uint8 result; buff >> result; // TODO: test it. if(result == 0x00) { sLog->outWarden("TIMING CHECK FAIL result 0x00"); found = true; } uint32 newClientTicks; buff >> newClientTicks; uint32 ticksNow = getMSTime(); uint32 ourTicks = newClientTicks + (ticksNow - ServerTicks); sLog->outStaticDebug("ServerTicks %u", ticksNow); // now sLog->outStaticDebug("RequestTicks %u", ServerTicks); // at request sLog->outStaticDebug("Ticks %u", newClientTicks); // at response sLog->outStaticDebug("Ticks diff %u", ourTicks - newClientTicks); } WardenDataResult *rs; WardenData *rd; uint8 type; for(std::vector<uint32>::iterator itr = SendDataId.begin(); itr != SendDataId.end(); ++itr) { if(forceKick) break; rd = WardenDataStorage.GetWardenDataById(*itr); rs = WardenDataStorage.GetWardenResultById(*itr); type = rd->Type; switch(type) { case MEM_CHECK: { uint8 Mem_Result; buff >> Mem_Result; if(Mem_Result != 0) { sLog->outWarden("RESULT MEM_CHECK not 0x00, CheckId: %u, account Id: %u, player: %s", rd->DBid, Client->GetAccountId(), Client->GetPlayerName()); forceKick = true; banDays = 0; found = true; continue; } if(memcmp(buff.contents() + buff.rpos(), rs->res.AsByteArray(0, false), rd->Length) != 0) { sLog->outWarden("RESULT MEM_CHECK fail CheckId: %u, account Id: %u, player: %s", rd->DBid, Client->GetAccountId(), Client->GetPlayerName()); found = true; if(rd->banDays > banDays) banDays = rd->banDays; buff.rpos(buff.rpos() + rd->Length); continue; } buff.rpos(buff.rpos() + rd->Length); sLog->outStaticDebug("RESULT MEM_CHECK passed CheckId: %u, account Id: %u, player: %s", rd->DBid, Client->GetAccountId(), Client->GetPlayerName()); break; } case PAGE_CHECK_A: case PAGE_CHECK_B: case DRIVER_CHECK: case MODULE_CHECK: { const uint8 byte = 0xE9; if(memcmp(buff.contents() + buff.rpos(), &byte, sizeof(uint8)) != 0) { if(type == PAGE_CHECK_A || type == PAGE_CHECK_B) sLog->outWarden("RESULT PAGE_CHECK fail, CheckId: %u, account Id: %u, player: %s", rd->DBid, Client->GetAccountId(), Client->GetPlayerName()); if(type == MODULE_CHECK) sLog->outWarden("RESULT MODULE_CHECK fail, CheckId: %u, account Id: %u, player: %s", rd->DBid, Client->GetAccountId(), Client->GetPlayerName()); if(type == DRIVER_CHECK) sLog->outWarden("RESULT DRIVER_CHECK fail, CheckId: %u, account Id: %u, player: %s", rd->DBid, Client->GetAccountId(), Client->GetPlayerName()); found = true; buff.rpos(buff.rpos() + 1); if(rd->banDays > banDays) banDays = rd->banDays; continue; } buff.rpos(buff.rpos() + 1); if(type == PAGE_CHECK_A || type == PAGE_CHECK_B) sLog->outStaticDebug("RESULT PAGE_CHECK passed CheckId: %u, account Id: %u, player: %s", rd->DBid, Client->GetAccountId(), Client->GetPlayerName()); else if(type == MODULE_CHECK) sLog->outStaticDebug("RESULT MODULE_CHECK passed CheckId: %u, account Id: %u, player: %s", rd->DBid, Client->GetAccountId(), Client->GetPlayerName()); else if(type == DRIVER_CHECK) sLog->outStaticDebug("RESULT DRIVER_CHECK passed CheckId: %u, account Id: %u, player: %s", rd->DBid, Client->GetAccountId(), Client->GetPlayerName()); break; } case LUA_STR_CHECK: { uint8 Lua_Result; buff >> Lua_Result; if(Lua_Result != 0) { sLog->outWarden("RESULT LUA_STR_CHECK fail, CheckId: %u, account Id: %u, player: %s", rd->DBid, Client->GetAccountId(), Client->GetPlayerName()); found = true; if(rd->banDays > banDays) banDays = rd->banDays; continue; } uint8 luaStrLen; buff >> luaStrLen; if(luaStrLen != 0) { char *str = new char[luaStrLen + 1]; memset(str, 0, luaStrLen + 1); memcpy(str, buff.contents() + buff.rpos(), luaStrLen); sLog->outStaticDebug("Lua string: %s", str); delete[] str; } buff.rpos(buff.rpos() + luaStrLen); // skip string sLog->outStaticDebug("RESULT LUA_STR_CHECK passed, CheckId: %u, account Id: %u, player: %s", rd->DBid, Client->GetAccountId(), Client->GetPlayerName()); break; } case MPQ_CHECK: { uint8 Mpq_Result; buff >> Mpq_Result; if(Mpq_Result != 0) { sLog->outWarden("RESULT MPQ_CHECK not 0x00 account id %u", Client->GetAccountId()); found = true; if(rd->banDays > banDays) banDays = rd->banDays; continue; } if(memcmp(buff.contents() + buff.rpos(), rs->res.AsByteArray(0, false), 20) != 0) // SHA1 { sLog->outWarden("RESULT MPQ_CHECK fail, CheckId: %u, account Id: %u, player: %s", rd->DBid, Client->GetAccountId(), Client->GetPlayerName()); found = true; buff.rpos(buff.rpos() + 20); // 20 bytes SHA1 if(rd->banDays > banDays) banDays = rd->banDays; continue; } buff.rpos(buff.rpos() + 20); // 20 bytes SHA1 sLog->outStaticDebug("RESULT MPQ_CHECK passed, CheckId: %u, account Id: %u, player: %s", rd->DBid, Client->GetAccountId(), Client->GetPlayerName()); break; } default: // should never happens break; } } if(banDays > 0 && m_previousCheckFailed) banDays = 0; m_previousCheckFailed = false; if(found && banDays > 0) { std::stringstream ssDuration; ssDuration << +banDays << "d"; std::string sDuration; sDuration = ssDuration.str(); std::string sText = ("Player: " + std::string(Client->GetPlayerName()) + " have used Cheating software and have banned for " + sDuration.c_str()); sWorld->SendGMText(LANG_GM_BROADCAST, sText.c_str()); sLog->outWarden("Player %s (account: %u) have used Cheating software and have banned for %s", Client->GetPlayerName(), Client->GetAccountId(), sDuration.c_str()); sWorld->BanAccount(BAN_CHARACTER, Client->GetPlayerName(), sDuration.c_str(), "Cheating software user", "Server guard"); } else if(found && sWorld->getBoolConfig(CONFIG_BOOL_WARDEN_KICK)) Client->KickPlayer(); }
void WardenWin::RequestData() { DEBUG_LOG("WARDEN: Request data"); if (MemCheck.empty()) MemCheck.assign(WardenDataStorage.MemCheckIds.begin(), WardenDataStorage.MemCheckIds.end()); ServerTicks = WorldTimer::getMSTime(); uint32 maxid = WardenDataStorage.InternalDataID; uint32 id; uint8 type; WardenData *wd; SendDataId.clear(); // always! this is SpeedHack on WEH SendDataId.push_back(385); for (int i = 0; i < 3; ++i) // for now include 3 MEM_CHECK's { if (MemCheck.empty()) break; id = MemCheck.back(); SendDataId.push_back(id); MemCheck.pop_back(); } ByteBuffer buff; buff << uint8(WARDEN_SMSG_CHEAT_CHECKS_REQUEST); int maxSize = 8 - MemCheck.size(); for (int i = 0; i < maxSize; ++i) // for now include 5 random checks { id = irand(1, maxid - 1); wd = WardenDataStorage.GetWardenDataById(id); SendDataId.push_back(id); switch (wd->Type) { case MPQ_CHECK: case LUA_STR_CHECK: case DRIVER_CHECK: buff << uint8(wd->str.size()); buff.append(wd->str.c_str(), wd->str.size()); break; default: break; } } uint8 xorByte = InputKey[0]; buff << uint8(0x00); buff << uint8(TIMING_CHECK ^ xorByte); // check TIMING_CHECK uint8 index = 1; for (std::vector<uint32>::iterator itr = SendDataId.begin(); itr != SendDataId.end(); ++itr) { wd = WardenDataStorage.GetWardenDataById(*itr); type = wd->Type; buff << uint8(type ^ xorByte); switch (type) { case MEM_CHECK: { buff << uint8(0x00); buff << uint32(wd->Address); buff << uint8(wd->Length); break; } case PAGE_CHECK_A: case PAGE_CHECK_B: { buff.append(wd->i.AsByteArray(0, false), wd->i.GetNumBytes()); buff << uint32(wd->Address); buff << uint8(wd->Length); break; } case MPQ_CHECK: case LUA_STR_CHECK: { buff << uint8(index++); break; } case DRIVER_CHECK: { buff.append(wd->i.AsByteArray(0, false), wd->i.GetNumBytes()); buff << uint8(index++); break; } case MODULE_CHECK: { uint32 seed = static_cast<uint32>(rand32()); buff << uint32(seed); HMACSHA1 hmac(4, (uint8*)&seed); hmac.UpdateData(wd->str); hmac.Finalize(); buff.append(hmac.GetDigest(), hmac.GetLength()); break; } /*case PROC_CHECK: { buff.append(wd->i.AsByteArray(0, false), wd->i.GetNumBytes()); buff << uint8(index++); buff << uint8(index++); buff << uint32(wd->Address); buff << uint8(wd->Length); break; }*/ default: break; // should never happens } } buff << uint8(xorByte); buff.hexlike(); // Encrypt with warden RC4 key. EncryptData(const_cast<uint8*>(buff.contents()), buff.size()); WorldPacket pkt(SMSG_WARDEN_DATA, buff.size()); pkt.append(buff); Client->SendPacket(&pkt); m_WardenDataSent = true; std::stringstream stream; stream << "Sent check id's: "; for (std::vector<uint32>::iterator itr = SendDataId.begin(); itr != SendDataId.end(); ++itr) stream << *itr << " "; DEBUG_LOG("WARDEN: %s",stream.str().c_str()); }
void WardenWin::RequestData() { sLog->outStaticDebug("Request data"); if(MemCheck.empty()) MemCheck.assign(WardenDataStorage.MemCheckIds.begin(), WardenDataStorage.MemCheckIds.end()); ServerTicks = getMSTime(); uint32 maxid = WardenDataStorage.InternalDataID; uint32 id; uint8 type; WardenData *wd; SendDataId.clear(); uint8 memcheckAdded = 0; for(uint32 i = 1; i <= maxid; ++i) { if(MemCheck.empty()) break; if(memcheckAdded >= 3) // for now include 3 MEM_CHECK's break; id = MemCheck.back(); if(std::find(SendDataId.begin(), SendDataId.end(), id) != SendDataId.end()) continue; memcheckAdded++; SendDataId.push_back(id); MemCheck.pop_back(); } ByteBuffer buff; buff << uint8(WARDEN_SMSG_CHEAT_CHECKS_REQUEST); uint8 cheatCheckAdded = 0; for(uint32 i = 1; i <= maxid; ++i) // for now include 5 random checks { if(cheatCheckAdded >= 5) break; id = urand(1, maxid - 1); if(std::find(SendDataId.begin(), SendDataId.end(), id) != SendDataId.end()) continue; cheatCheckAdded++; wd = WardenDataStorage.GetWardenDataById(id); SendDataId.push_back(id); switch(wd->Type) { case MPQ_CHECK: case LUA_STR_CHECK: case DRIVER_CHECK: buff << uint8(wd->str.size()); buff.append(wd->str.c_str(), wd->str.size()); break; default: break; } } uint8 xorByte = InputKey[0]; buff << uint8(0x00); buff << uint8(TIMING_CHECK ^ xorByte); // check TIMING_CHECK uint8 index = 1; for(std::vector<uint32>::iterator itr = SendDataId.begin(); itr != SendDataId.end(); ++itr) { wd = WardenDataStorage.GetWardenDataById(*itr); type = wd->Type; buff << uint8(type ^ xorByte); switch(type) { case MEM_CHECK: { buff << uint8(0x00); buff << uint32(wd->Address); buff << uint8(wd->Length); break; } case PAGE_CHECK_A: case PAGE_CHECK_B: { buff.append(wd->i.AsByteArray(0, false), wd->i.GetNumBytes()); buff << uint32(wd->Address); buff << uint8(wd->Length); break; } case MPQ_CHECK: case LUA_STR_CHECK: { buff << uint8(index++); break; } case DRIVER_CHECK: { buff.append(wd->i.AsByteArray(0, false), wd->i.GetNumBytes()); buff << uint8(index++); break; } case MODULE_CHECK: { uint32 seed = static_cast<uint32>(rand32()); buff << uint32(seed); HmacHash hmac(4, (uint8*)&seed); hmac.UpdateData(wd->str); hmac.Finalize(); buff.append(hmac.GetDigest(), hmac.GetLength()); break; } default: break; // should never happens } } buff << uint8(xorByte); buff.hexlike(); // Encrypt with warden RC4 key. EncryptData(const_cast<uint8*>(buff.contents()), buff.size()); WorldPacket pkt(SMSG_WARDEN_DATA, buff.size()); pkt.append(buff); Client->SendPacket(&pkt); m_WardenDataSent = true; std::stringstream stream; stream << "Sent check id's: "; for(std::vector<uint32>::iterator itr = SendDataId.begin(); itr != SendDataId.end(); ++itr) stream << *itr << " "; sLog->outStaticDebug(stream.str().c_str()); }