// Sending this packet to initialize engine functions warden uses void WardenMgr::SendWardenData(WorldSession* const session) { sLog->outStaticDebug("WardenMgr::SendWardenData"); WorldPacket data( SMSG_WARDEN_DATA, 1 + 2+4+20 + 1 + 2+4+8 + 1 +2+4+8); // 42 // 57 // 3.3.5a init packet data << uint8(WARDS_DATA); { data << uint16(20); uint8 buff[20] = { 0x01, 0x00, 0x02, 0x00, 0x80, 0x4F, 0x02, 0x00, // 0x00400000 + 0x00024F80 SFileOpenFile 0xC0, 0x18, 0x02, 0x00, // 0x00400000 + 0x000218C0 SFileGetFileSize 0x30, 0x25, 0x02, 0x00, // 0x00400000 + 0x00022530 SFileReadFile 0x10, 0x29, 0x02, 0x00 // 0x00400000 + 0x00022910 SFileCloseFile }; data << uint32(BuildChecksum(buff, 20)); data.append(buff, 20); } data << uint8(WARDS_DATA); { data << uint16(8); uint8 buff[8] = { 0x04, 0x00, 0x00, 0x40, 0x9D, 0x41, 0x00, // 0x00400000 + 0x00419D40 FrameScript__GetText 0x01 }; data << uint32(BuildChecksum(buff, 8)); data.append(buff, 8); } // Computed part for timing checks (did not exist on Offy 3.3.5a) data << uint8(WARDS_DATA); { data << uint16(8); uint8 buff[8] = { 0x01, 0x01, 0x00, 0x20, 0xAE, 0x46, 0x00, // 0x00400000 + 0x0046AE20 PerformanceCounter 0x01 }; data << uint32(BuildChecksum(buff, 8)); data.append(buff, 8); } data.hexlike(); data.crypt(&session->m_rc4ServerKey[0], &rc4_crypt); session->SendPacket(&data); }
void WardenWin::InitializeModule() { #if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS) sLog->outDebug(LOG_FILTER_WARDEN, "Initialize module"); #endif // Create packet structure WardenInitModuleRequest Request; Request.Command1 = WARDEN_SMSG_MODULE_INITIALIZE; Request.Size1 = 20; Request.Unk1 = 1; Request.Unk2 = 0; Request.Type = 1; Request.String_library1 = 0; Request.Function1[0] = 0x00024F80; // 0x00400000 + 0x00024F80 SFileOpenFile Request.Function1[1] = 0x000218C0; // 0x00400000 + 0x000218C0 SFileGetFileSize Request.Function1[2] = 0x00022530; // 0x00400000 + 0x00022530 SFileReadFile Request.Function1[3] = 0x00022910; // 0x00400000 + 0x00022910 SFileCloseFile Request.CheckSumm1 = BuildChecksum(&Request.Unk1, 20); Request.Command2 = WARDEN_SMSG_MODULE_INITIALIZE; Request.Size2 = 8; Request.Unk3 = 4; Request.Unk4 = 0; Request.String_library2 = 0; Request.Function2 = 0x00419D40; // 0x00400000 + 0x00419D40 FrameScript::GetText Request.Function2_set = 1; Request.CheckSumm2 = BuildChecksum(&Request.Unk2, 8); Request.Command3 = WARDEN_SMSG_MODULE_INITIALIZE; Request.Size3 = 8; Request.Unk5 = 1; Request.Unk6 = 1; Request.String_library3 = 0; Request.Function3 = 0x0046AE20; // 0x00400000 + 0x0046AE20 PerformanceCounter Request.Function3_set = 1; Request.CheckSumm3 = BuildChecksum(&Request.Unk5, 8); // Encrypt with warden RC4 key. EncryptData((uint8*)&Request, sizeof(WardenInitModuleRequest)); WorldPacket pkt(SMSG_WARDEN_DATA, sizeof(WardenInitModuleRequest)); pkt.append((uint8*)&Request, sizeof(WardenInitModuleRequest)); _session->SendPacket(&pkt); }
bool Warden::IsValidCheckSum(uint32 checksum, const uint8* data, const uint16 length) { uint32 newChecksum = BuildChecksum(data, length); if (checksum != newChecksum) { sLog->outDebug(LOG_FILTER_WARDEN, "CHECKSUM IS NOT VALID"); return false; } else { sLog->outDebug(LOG_FILTER_WARDEN, "CHECKSUM IS VALID"); return true; } }
bool Warden::IsValidCheckSum(uint32 checksum, const uint8* data, const uint16 length) { uint32 newChecksum = BuildChecksum(data, length); if (checksum != newChecksum) { TC_LOG_DEBUG("warden", "CHECKSUM IS NOT VALID"); return false; } else { TC_LOG_DEBUG("warden", "CHECKSUM IS VALID"); return true; } }
bool WardenBase::IsValidCheckSum(uint32 checksum, const uint8 *Data, const uint16 Length) { uint32 newchecksum = BuildChecksum(Data, Length); if (checksum != newchecksum) { sLog->outWarden("CHECKSUM IS NOT VALID"); return false; } else { sLog->outStaticDebug("CHECKSUM IS VALID"); return true; } }
bool WardenMgr::ValidateCheatCheckResult(WorldSession* const session, WorldPacket& clientPacket) { uint32 accountId = session->GetAccountId(); sLog->outStaticDebug("Wardend::ValidateCheatCheckResult(%u, *pkt)", accountId); bool valid = true; uint16 pktLen; uint32 checksum; clientPacket >> pktLen; clientPacket >> checksum; if (checksum != BuildChecksum(clientPacket.contents() + clientPacket.rpos(), clientPacket.size() - clientPacket.rpos())) { if (session->GetPlayer()) { sLog->outWarden("Warden Cheat-check: Kicking player %s for failed check, Packet Checksum 0x%08X is invalid!", session->GetPlayerName(), checksum); } else { sLog->outWarden("Warden Cheat-check: Kicking account %u for failed check, Packet Checksum 0x%08X is invalid!", session->GetAccountId(), checksum); } ReactToCheatCheckResult(session, false); return false; } if (pktLen == 0) return false; // parse the timing check always sent sLog->outStaticDebug("TimeCheck"); uint8 res; uint32 ticks; clientPacket >> res; // should be 1 clientPacket >> ticks; // Need to compare ticks based on last one using server ticks diff since sLog->outStaticDebug("Warden: Time unk 0x%08X", ticks); pktLen = pktLen - 5; WardenClientCheckList* checkList = (WardenClientCheckList*)session->m_WardenClientChecks; if (!checkList) return false; for (uint8 i=0; i<checkList->size(); ++i) { switch ((*checkList)[i].check) { case WARD_CHECK_TIMING: { sLog->outStaticDebug("Warden: TimeCheck"); uint8 res; uint32 ticks; clientPacket >> res; // should be 1 clientPacket >> ticks; // Need to compare ticks based on last one using server ticks diff since sLog->outStaticDebug("Warden: Time unk 0x%08X", ticks); pktLen = pktLen - 5; break; } case WARD_CHECK_MEMORY: { sLog->outStaticDebug("Warden: MemCheck"); uint8 res; clientPacket >> res; // should be 0 if (res) { valid = false; if (session->GetPlayer()) { sLog->outWarden("Warden: player %s failed check, MEM at Offset 0x%04X, lentgh %u could not be read by client", session->GetPlayerName(), (*checkList)[i].mem->Offset, (*checkList)[i].mem->Length); } else { sLog->outWarden("Warden: account %u failed check, MEM at Offset 0x%04X, lentgh %u could not be read by client", session->GetAccountId(), (*checkList)[i].mem->Offset, (*checkList)[i].mem->Length); } } else { uint8 memContent[20]; bool memcheck_failed = false; for (uint8 pos=0; pos<(*checkList)[i].mem->Length; ++pos) { clientPacket >> memContent[pos]; if (memContent[pos]!=(*checkList)[i].mem->Result[pos]) { valid = false; memcheck_failed = true; } } pktLen = pktLen - (1 + (*checkList)[i].mem->Length); if (memcheck_failed) { std::string strContent, strContent2; hexEncodeByteArray(memContent, (*checkList)[i].mem->Length, strContent); hexEncodeByteArray((*checkList)[i].mem->Result, (*checkList)[i].mem->Length, strContent2); if (session->GetPlayer()) { sLog->outWarden("Warden: player %s failed check, MEM Offset 0x%04X length %u has content '%s' instead of '%s'", session->GetPlayerName(), (*checkList)[i].mem->Offset, (*checkList)[i].mem->Length, strContent.c_str(), strContent2.c_str()); } else { sLog->outWarden("Warden: account %u failed check, MEM Offset 0x%04X length %u has content '%s' instead of '%s'", session->GetAccountId(), (*checkList)[i].mem->Offset, (*checkList)[i].mem->Length, strContent.c_str(), strContent2.c_str()); } } } sLog->outStaticDebug("Warden: Mem %s", valid ? "Ok" : "Failed"); break; } case WARD_CHECK_FILE: { sLog->outStaticDebug("Warden: MPQCheck"); uint8 res; uint8 resSHA1[20]; clientPacket >> res; // should be 0 if (res) { valid = false; if (session->GetPlayer()) { sLog->outWarden("Warden: player %s failed check, MPQ '%s' not found by client", session->GetPlayerName(), (*checkList)[i].file->String.c_str()); } else { sLog->outWarden("Warden: account %u failed check, MPQ '%s' not found by client", session->GetAccountId(), (*checkList)[i].file->String.c_str()); } pktLen = pktLen - 1; } else { for (uint8 pos=0; pos<20; ++pos) clientPacket >> resSHA1[pos]; if (res || memcmp(resSHA1, (*checkList)[i].file->SHA, 20)) { valid = false; std::string strResSHA1, strReqSHA1; hexEncodeByteArray(resSHA1, 20, strResSHA1); hexEncodeByteArray((*checkList)[i].file->SHA, 20, strReqSHA1); if (session->GetPlayer()) { sLog->outWarden("Warden: player %s failed check, MPQ '%s' SHA1 is '%s' instead of '%s'", session->GetPlayerName(), (*checkList)[i].file->String.c_str(), strResSHA1.c_str(), strReqSHA1.c_str()); } else { sLog->outWarden("Warden: account %u failed check, MPQ '%s' SHA1 is '%s' instead of '%s'", session->GetAccountId(), (*checkList)[i].file->String.c_str(), strResSHA1.c_str(), strReqSHA1.c_str()); } } pktLen = pktLen - 21; } sLog->outStaticDebug("Warden: MPQ %s", valid ? "Ok" : "Failed"); break; } case WARD_CHECK_LUA: { sLog->outStaticDebug("Warden: LUACheck"); uint8 res; uint8 foundLuaLen; clientPacket >> res; // should be 0 clientPacket >> foundLuaLen; // should be 0 uint8 *luaStr; if (foundLuaLen > 0) { luaStr = (uint8*)malloc(foundLuaLen+1); for (uint8 pos=0; pos<foundLuaLen; ++pos) { clientPacket >> luaStr[pos]; } luaStr[foundLuaLen] = 0; if (session->GetPlayer()) { sLog->outWarden("Warden: player %s failed lua check, Lua '%s' found as '%s'", session->GetPlayerName(), (*checkList)[i].lua->String.c_str(), (char*)luaStr); } else { sLog->outWarden("Warden: account %u failed lua check, Lua '%s' found as '%s'", session->GetAccountId(), (*checkList)[i].lua->String.c_str(), (char*)luaStr); } valid = false; free(luaStr); } sLog->outStaticDebug("Lua %s", valid ? "Ok" : "Failed"); pktLen = pktLen - 2; break; } case WARD_CHECK_PAGE1: case WARD_CHECK_PAGE2: case WARD_CHECK_DRIVER: { sLog->outStaticDebug("PageCheck or DriverCheck"); uint8 res; clientPacket >> res; // should be 0xE9 if (res != 0xE9) { if ((*checkList)[i].check == WARD_CHECK_DRIVER) { if (session->GetPlayer()) { sLog->outWarden("Warden: player %s failed driver check '%s'", session->GetPlayerName(), (*checkList)[i].driver->String.c_str()); } else { sLog->outWarden("Warden: account %u failed driver check '%s'", session->GetAccountId(), (*checkList)[i].driver->String.c_str()); } } else { if (session->GetPlayer()) { sLog->outWarden("Warden: player %s failed page check Offset 0x%08X, length %u", session->GetPlayerName(), (*checkList)[i].page->Offset, (*checkList)[i].page->Length); } else { sLog->outWarden("Warden: account %u failed page check Offset 0x%08X, length %u", session->GetAccountId(), (*checkList)[i].page->Offset, (*checkList)[i].page->Length); } } valid = false; } sLog->outStaticDebug("Page or Driver %s",valid?"Ok":"Failed"); pktLen = pktLen - 1; break; } default: sLog->outStaticDebug("Warden: Other!!"); // Finish skiping the rest of the packet and return failed checks if (session->GetPlayer()) { sLog->outWarden("Wrong packet for player %s or problem to parse it, I had to clean %u bytes", session->GetPlayerName(), clientPacket.size() - clientPacket.rpos()); } else { sLog->outWarden("Wrong packet for account %u or problem to parse it, I had to clean %u bytes", session->GetAccountId(), clientPacket.size() - clientPacket.rpos()); } clientPacket.read_skip(clientPacket.size() - clientPacket.rpos()); return false; } }