public string Penalty(WardenCheck check = null) { WardenActions action; if (check != null) { action = check.Action; } else { action = (WardenActions)WorldConfig.GetIntValue(WorldCfg.WardenClientFailAction); } switch (action) { case WardenActions.Log: return("None"); case WardenActions.Kick: _session.KickPlayer(); return("Kick"); case WardenActions.Ban: { string duration = WorldConfig.GetIntValue(WorldCfg.WardenClientBanDuration) + "s"; string accountName; Global.AccountMgr.GetName(_session.GetAccountId(), out accountName); string banReason = "Warden Anticheat Violation"; // Check can be NULL, for example if the client sent a wrong signature in the warden packet (CHECKSUM FAIL) if (check != null) { banReason += ": " + check.Comment + " (CheckId: " + check.CheckId + ")"; } Global.WorldMgr.BanAccount(BanMode.Account, accountName, duration, banReason, "Server"); return("Ban"); } default: break; } return("Undefined"); }
public void LoadWardenChecks() { // Check if Warden is enabled by config before loading anything if (!WorldConfig.GetBoolValue(WorldCfg.WardenEnabled)) { Log.outInfo(LogFilter.Warden, "Warden disabled, loading checks skipped."); return; } // 0 1 2 3 4 5 6 7 SQLResult result = DB.World.Query("SELECT id, type, data, result, address, length, str, comment FROM warden_checks ORDER BY id ASC"); if (result.IsEmpty()) { Log.outInfo(LogFilter.ServerLoading, "Loaded 0 Warden checks. DB table `warden_checks` is empty!"); return; } uint count = 0; do { ushort id = result.Read <ushort>(0); WardenCheckType checkType = (WardenCheckType)result.Read <byte>(1); string data = result.Read <string>(2); string checkResult = result.Read <string>(3); uint address = result.Read <uint>(4); byte length = result.Read <byte>(5); string str = result.Read <string>(6); string comment = result.Read <string>(7); WardenCheck wardenCheck = new WardenCheck(); wardenCheck.Type = checkType; wardenCheck.CheckId = id; // Initialize action with default action from config wardenCheck.Action = (WardenActions)WorldConfig.GetIntValue(WorldCfg.WardenClientFailAction); if (checkType == WardenCheckType.PageA || checkType == WardenCheckType.PageB || checkType == WardenCheckType.Driver) { wardenCheck.Data = new BigInteger(data.ToByteArray()); int len = data.Length / 2; if (wardenCheck.Data.ToByteArray().Length < len) { byte[] temp = wardenCheck.Data.ToByteArray(); Array.Reverse(temp); wardenCheck.Data = new BigInteger(temp); } } if (checkType == WardenCheckType.Memory || checkType == WardenCheckType.Module) { MemChecksIdPool.Add(id); } else { OtherChecksIdPool.Add(id); } if (checkType == WardenCheckType.Memory || checkType == WardenCheckType.PageA || checkType == WardenCheckType.PageB || checkType == WardenCheckType.Proc) { wardenCheck.Address = address; wardenCheck.Length = length; } // PROC_CHECK support missing if (checkType == WardenCheckType.Memory || checkType == WardenCheckType.MPQ || checkType == WardenCheckType.LuaStr || checkType == WardenCheckType.Driver || checkType == WardenCheckType.Module) { wardenCheck.Str = str; } CheckStore[id] = wardenCheck; if (checkType == WardenCheckType.MPQ || checkType == WardenCheckType.Memory) { BigInteger Result = new BigInteger(checkResult.ToByteArray()); int len = checkResult.Length / 2; if (Result.ToByteArray().Length < len) { byte[] temp = Result.ToByteArray(); Array.Reverse(temp); Result = new BigInteger(temp); } CheckResultStore[id] = Result; } if (comment.IsEmpty()) { wardenCheck.Comment = "Undocumented Check"; } else { wardenCheck.Comment = comment; } ++count; }while (result.NextRow()); Log.outInfo(LogFilter.ServerLoading, "Loaded {0} warden checks.", count); }
public override void HandleData(ByteBuffer buff) { Log.outDebug(LogFilter.Warden, "Handle data"); _dataSent = false; _clientResponseTimer = 0; ushort Length = buff.ReadUInt16(); uint Checksum = buff.ReadUInt32(); if (!IsValidCheckSum(Checksum, buff.GetData(), Length)) { Log.outWarn(LogFilter.Warden, "{0} failed checksum. Action: {1}", _session.GetPlayerInfo(), Penalty()); return; } // TIMING_CHECK { byte result = buff.ReadUInt8(); // @todo test it. if (result == 0x00) { Log.outWarn(LogFilter.Warden, "{0} failed timing check. Action: {1}", _session.GetPlayerInfo(), Penalty()); return; } uint newClientTicks = buff.ReadUInt32(); uint ticksNow = GameTime.GetGameTimeMS(); uint ourTicks = newClientTicks + (ticksNow - _serverTicks); Log.outDebug(LogFilter.Warden, "ServerTicks {0}", ticksNow); // Now Log.outDebug(LogFilter.Warden, "RequestTicks {0}", _serverTicks); // At request Log.outDebug(LogFilter.Warden, "Ticks {0}", newClientTicks); // At response Log.outDebug(LogFilter.Warden, "Ticks diff {0}", ourTicks - newClientTicks); } BigInteger rs; WardenCheck rd; WardenCheckType type; ushort checkFailed = 0; foreach (var id in _currentChecks) { rd = Global.WardenCheckMgr.GetWardenDataById(id); rs = Global.WardenCheckMgr.GetWardenResultById(id); type = rd.Type; switch (type) { case WardenCheckType.Memory: { byte Mem_Result = buff.ReadUInt8(); if (Mem_Result != 0) { Log.outDebug(LogFilter.Warden, "RESULT MEM_CHECK not 0x00, CheckId {0} account Id {1}", id, _session.GetAccountId()); checkFailed = id; continue; } if (buff.ReadBytes(rd.Length).Compare(rs.ToByteArray())) { Log.outDebug(LogFilter.Warden, "RESULT MEM_CHECK fail CheckId {0} account Id {1}", id, _session.GetAccountId()); checkFailed = id; continue; } Log.outDebug(LogFilter.Warden, "RESULT MEM_CHECK passed CheckId {0} account Id {1}", id, _session.GetAccountId()); break; } case WardenCheckType.PageA: case WardenCheckType.PageB: case WardenCheckType.Driver: case WardenCheckType.Module: { byte value = 0xE9; if (buff.ReadUInt8() != value) { if (type == WardenCheckType.PageA || type == WardenCheckType.PageB) { Log.outDebug(LogFilter.Warden, "RESULT PAGE_CHECK fail, CheckId {0} account Id {1}", id, _session.GetAccountId()); } if (type == WardenCheckType.Module) { Log.outDebug(LogFilter.Warden, "RESULT MODULE_CHECK fail, CheckId {0} account Id {1}", id, _session.GetAccountId()); } if (type == WardenCheckType.Driver) { Log.outDebug(LogFilter.Warden, "RESULT DRIVER_CHECK fail, CheckId {0} account Id {1}", id, _session.GetAccountId()); } checkFailed = id; continue; } if (type == WardenCheckType.PageA || type == WardenCheckType.PageB) { Log.outDebug(LogFilter.Warden, "RESULT PAGE_CHECK passed CheckId {0} account Id {1}", id, _session.GetAccountId()); } else if (type == WardenCheckType.Module) { Log.outDebug(LogFilter.Warden, "RESULT MODULE_CHECK passed CheckId {0} account Id {1}", id, _session.GetAccountId()); } else if (type == WardenCheckType.Driver) { Log.outDebug(LogFilter.Warden, "RESULT DRIVER_CHECK passed CheckId {0} account Id {1}", id, _session.GetAccountId()); } break; } case WardenCheckType.LuaStr: { byte Lua_Result = buff.ReadUInt8(); if (Lua_Result != 0) { Log.outDebug(LogFilter.Warden, "RESULT LUA_STR_CHECK fail, CheckId {0} account Id {1}", id, _session.GetAccountId()); checkFailed = id; continue; } byte luaStrLen = buff.ReadUInt8(); if (luaStrLen != 0) { Log.outDebug(LogFilter.Warden, "Lua string: {0}", buff.ReadString(luaStrLen)); } Log.outDebug(LogFilter.Warden, "RESULT LUA_STR_CHECK passed, CheckId {0} account Id {1}", id, _session.GetAccountId()); break; } case WardenCheckType.MPQ: { byte Mpq_Result = buff.ReadUInt8(); if (Mpq_Result != 0) { Log.outDebug(LogFilter.Warden, "RESULT MPQ_CHECK not 0x00 account id {0}", _session.GetAccountId()); checkFailed = id; continue; } if (!buff.ReadBytes(20).Compare(rs.ToByteArray())) // SHA1 { Log.outDebug(LogFilter.Warden, "RESULT MPQ_CHECK fail, CheckId {0} account Id {1}", id, _session.GetAccountId()); checkFailed = id; continue; } Log.outDebug(LogFilter.Warden, "RESULT MPQ_CHECK passed, CheckId {0} account Id {1}", id, _session.GetAccountId()); break; } default: // Should never happen break; } } if (checkFailed > 0) { WardenCheck check = Global.WardenCheckMgr.GetWardenDataById(checkFailed); Log.outWarn(LogFilter.Warden, "{0} failed Warden check {1}. Action: {2}", _session.GetPlayerInfo(), checkFailed, Penalty(check)); } // Set hold off timer, minimum timer should at least be 1 second uint holdOff = WorldConfig.GetUIntValue(WorldCfg.WardenClientCheckHoldoff); _checkTimer = (holdOff < 1 ? 1 : holdOff) * Time.InMilliseconds; }