AzeorthCore 3.3.5a
OpenSource WoW Emulator
Loading...
Searching...
No Matches
WardenWin Class Reference

#include "WardenWin.h"

Inheritance diagram for WardenWin:
Warden

Public Member Functions

 WardenWin ()
 
 ~WardenWin () override
 
void Init (WorldSession *session, SessionKey const &K) override
 
ClientWardenModuleGetModuleForClient () override
 
void InitializeModule () override
 
void RequestHash () override
 
void HandleHashResult (ByteBuffer &buff) override
 
void RequestChecks () override
 
void HandleData (ByteBuffer &buff) override
 
- Public Member Functions inherited from Warden
 Warden ()
 
virtual ~Warden ()
 
virtual void Init (WorldSession *session, SessionKey const &k)=0
 
virtual ClientWardenModuleGetModuleForClient ()=0
 
virtual void InitializeModule ()=0
 
virtual void RequestHash ()=0
 
virtual void HandleHashResult (ByteBuffer &buff)=0
 
virtual void RequestChecks ()=0
 
virtual void HandleData (ByteBuffer &buff)=0
 
bool ProcessLuaCheckResponse (std::string const &msg)
 
void SendModuleToClient ()
 
void RequestModule ()
 
void Update (uint32 const diff)
 
void DecryptData (uint8 *buffer, uint32 length)
 
void EncryptData (uint8 *buffer, uint32 length)
 
void ApplyPenalty (uint16 checkId, std::string const &reason)
 

Private Attributes

uint32 _serverTicks
 
std::list< uint16_ChecksTodo [MAX_WARDEN_CHECK_TYPES]
 
std::list< uint16_CurrentChecks
 
std::list< uint16_PendingChecks
 

Additional Inherited Members

- Static Public Member Functions inherited from Warden
static bool IsValidCheckSum (uint32 checksum, const uint8 *data, const uint16 length)
 
static uint32 BuildChecksum (const uint8 *data, uint32 length)
 

Detailed Description

Constructor & Destructor Documentation

◆ WardenWin()

WardenWin::WardenWin ( )
98: Warden(), _serverTicks(0) { }
Warden()
Definition: Warden.cpp:33
uint32 _serverTicks
Definition: WardenWin.h:87

◆ ~WardenWin()

WardenWin::~WardenWin ( )
override
101{
102}

Member Function Documentation

◆ GetModuleForClient()

ClientWardenModule * WardenWin::GetModuleForClient ( )
overridevirtual

Implements Warden.

130{
132
133 uint32 length = sizeof(Module.Module);
134
135 // data assign
136 mod->CompressedSize = length;
137 mod->CompressedData = new uint8[length];
138 memcpy(mod->CompressedData, Module.Module, length);
139 memcpy(mod->Key, Module.ModuleKey, 16);
140
141 // md5 hash
142 MD5_CTX ctx;
143 MD5_Init(&ctx);
144 MD5_Update(&ctx, mod->CompressedData, length);
145 MD5_Final((uint8*)&mod->Id, &ctx);
146
147 return mod;
148}
std::uint8_t uint8
Definition: Define.h:110
std::uint32_t uint32
Definition: Define.h:108
struct Module_79C0768D657977D697E10BAD956CCED1 Module
uint8 Module[18756]
Definition: WardenModuleWin.h:31
uint8 ModuleKey[16]
Definition: WardenModuleWin.h:32
Definition: Warden.h:93
uint8 * CompressedData
Definition: Warden.h:97
uint8 Id[16]
Definition: Warden.h:94
uint32 CompressedSize
Definition: Warden.h:96
uint8 Key[16]
Definition: Warden.h:95

References ClientWardenModule::CompressedData, ClientWardenModule::CompressedSize, ClientWardenModule::Id, ClientWardenModule::Key, Module_79C0768D657977D697E10BAD956CCED1::Module, Module, and Module_79C0768D657977D697E10BAD956CCED1::ModuleKey.

Referenced by Init().

◆ HandleData()

void WardenWin::HandleData ( ByteBuffer buff)
overridevirtual
Todo:
: test it.

Implements Warden.

456{
457 LOG_DEBUG("warden", "Handle data");
458
459 _dataSent = false;
461
462 uint16 Length;
463 buff >> Length;
464 uint32 Checksum;
465 buff >> Checksum;
466
467 if (Length != (buff.size() - buff.rpos()))
468 {
469 buff.rfinish();
470 ApplyPenalty(0, "Failed size checks in HandleData");
471 return;
472 }
473
474 if (!IsValidCheckSum(Checksum, buff.contents() + buff.rpos(), Length))
475 {
476 buff.rpos(buff.wpos());
477 LOG_DEBUG("warden", "CHECKSUM FAIL");
478 ApplyPenalty(0, "Failed checksum in HandleData");
479 return;
480 }
481
482 // TIMING_CHECK
483 {
484 uint8 result;
485 buff >> result;
487 if (result == 0x00)
488 {
489 LOG_DEBUG("warden", "TIMING CHECK FAIL result 0x00");
490 // ApplyPenalty(0, "TIMING CHECK FAIL result"); Commented out because of too many false postives. Mostly caused by client stutter.
491 return;
492 }
493
494 uint32 newClientTicks;
495 buff >> newClientTicks;
496
497 uint32 ticksNow = GameTime::GetGameTimeMS().count();
498 uint32 ourTicks = newClientTicks + (ticksNow - _serverTicks);
499
500 LOG_DEBUG("warden", "ServerTicks {}", ticksNow); // Now
501 LOG_DEBUG("warden", "RequestTicks {}", _serverTicks); // At request
502 LOG_DEBUG("warden", "Ticks {}", newClientTicks); // At response
503 LOG_DEBUG("warden", "Ticks diff {}", ourTicks - newClientTicks);
504 }
505
506 uint16 checkFailed = 0;
507
508 for (uint16 const checkId : _CurrentChecks)
509 {
510 WardenCheck const* rd = sWardenCheckMgr->GetWardenDataById(checkId);
511 uint8 const type = rd->Type;
512 switch (type)
513 {
514 case MEM_CHECK:
515 {
516 uint8 Mem_Result;
517 buff >> Mem_Result;
518
519 if (Mem_Result != 0)
520 {
521 LOG_DEBUG("warden", "RESULT MEM_CHECK not 0x00, CheckId {} account Id {}", checkId, _session->GetAccountId());
522 checkFailed = checkId;
523 continue;
524 }
525
526 WardenCheckResult const* rs = sWardenCheckMgr->GetWardenResultById(checkId);
527
528 std::vector<uint8> result = rs->Result.ToByteVector(0, false);
529 if (memcmp(buff.contents() + buff.rpos(), result.data(), rd->Length) != 0)
530 {
531 LOG_DEBUG("warden", "RESULT MEM_CHECK fail CheckId {} account Id {}", checkId, _session->GetAccountId());
532 checkFailed = checkId;
533 buff.rpos(buff.rpos() + rd->Length);
534 continue;
535 }
536
537 buff.rpos(buff.rpos() + rd->Length);
538 LOG_DEBUG("warden", "RESULT MEM_CHECK passed CheckId {} account Id {}", checkId, _session->GetAccountId());
539 break;
540 }
541 case PAGE_CHECK_A:
542 case PAGE_CHECK_B:
543 case DRIVER_CHECK:
544 case MODULE_CHECK:
545 {
546 const uint8 byte = 0xE9;
547 if (memcmp(buff.contents() + buff.rpos(), &byte, sizeof(uint8)) != 0)
548 {
549 if (type == PAGE_CHECK_A || type == PAGE_CHECK_B)
550 LOG_DEBUG("warden", "RESULT PAGE_CHECK fail, CheckId {} account Id {}", checkId, _session->GetAccountId());
551
552 if (type == MODULE_CHECK)
553 LOG_DEBUG("warden", "RESULT MODULE_CHECK fail, CheckId {} account Id {}", checkId, _session->GetAccountId());
554
555 if (type == DRIVER_CHECK)
556 LOG_DEBUG("warden", "RESULT DRIVER_CHECK fail, CheckId {} account Id {}", checkId, _session->GetAccountId());
557 checkFailed = checkId;
558 buff.rpos(buff.rpos() + 1);
559 continue;
560 }
561
562 buff.rpos(buff.rpos() + 1);
563
564 if (type == PAGE_CHECK_A || type == PAGE_CHECK_B)
565 LOG_DEBUG("warden", "RESULT PAGE_CHECK passed CheckId {} account Id {}", checkId, _session->GetAccountId());
566 else if (type == MODULE_CHECK)
567 LOG_DEBUG("warden", "RESULT MODULE_CHECK passed CheckId {} account Id {}", checkId, _session->GetAccountId());
568 else if (type == DRIVER_CHECK)
569 LOG_DEBUG("warden", "RESULT DRIVER_CHECK passed CheckId {} account Id {}", checkId, _session->GetAccountId());
570 break;
571 }
572 case LUA_EVAL_CHECK:
573 {
574 uint8 const result = buff.read<uint8>();
575 if (result == 0)
576 {
577 buff.read_skip(buff.read<uint8>()); // discard attached string
578 }
579
580 LOG_DEBUG("warden", "LUA_EVAL_CHECK CheckId {} account Id {} got in-warden dummy response", checkId, _session->GetAccountId()/* , result */);
581 break;
582 }
583 case MPQ_CHECK:
584 {
585 uint8 Mpq_Result;
586 buff >> Mpq_Result;
587
588 if (Mpq_Result != 0)
589 {
590 LOG_DEBUG("warden", "RESULT MPQ_CHECK not 0x00 account id {}", _session->GetAccountId());
591 checkFailed = checkId;
592 continue;
593 }
594
595 WardenCheckResult const* rs = sWardenCheckMgr->GetWardenResultById(checkId);
596 if (memcmp(buff.contents() + buff.rpos(), rs->Result.ToByteArray<20>(false).data(), Acore::Crypto::Constants::SHA1_DIGEST_LENGTH_BYTES) != 0) // SHA1
597 {
598 LOG_DEBUG("warden", "RESULT MPQ_CHECK fail, CheckId {} account Id {}", checkId, _session->GetAccountId());
599 checkFailed = checkId;
600 buff.rpos(buff.rpos() + Acore::Crypto::Constants::SHA1_DIGEST_LENGTH_BYTES); // 20 bytes SHA1
601 continue;
602 }
603
604 buff.rpos(buff.rpos() + Acore::Crypto::Constants::SHA1_DIGEST_LENGTH_BYTES); // 20 bytes SHA1
605 LOG_DEBUG("warden", "RESULT MPQ_CHECK passed, CheckId {} account Id {}", checkId, _session->GetAccountId());
606 break;
607 }
608 }
609 }
610
611 if (checkFailed > 0)
612 {
613 ApplyPenalty(checkFailed, "");
614 }
615
616 // Set hold off timer, minimum timer should at least be 1 second
617 uint32 const holdOff = sWorld->getIntConfig(CONFIG_WARDEN_CLIENT_CHECK_HOLDOFF);
618 _checkTimer = (holdOff < 1 ? 1 : holdOff) * IN_MILLISECONDS;
619}
constexpr auto IN_MILLISECONDS
Definition: Common.h:62
std::uint16_t uint16
Definition: Define.h:109
#define LOG_DEBUG(filterType__,...)
Definition: Log.h:171
@ DRIVER_CHECK
Definition: Warden.h:53
@ PAGE_CHECK_A
Definition: Warden.h:49
@ PAGE_CHECK_B
Definition: Warden.h:50
@ LUA_EVAL_CHECK
Definition: Warden.h:52
@ MPQ_CHECK
Definition: Warden.h:51
@ MEM_CHECK
Definition: Warden.h:48
@ MODULE_CHECK
Definition: Warden.h:56
#define sWardenCheckMgr
Definition: WardenCheckMgr.h:89
@ CONFIG_WARDEN_CLIENT_CHECK_HOLDOFF
Definition: IWorld.h:377
#define sWorld
Definition: World.h:458
Milliseconds GetGameTimeMS()
Definition: GameTime.cpp:43
std::vector< uint8 > ToByteVector(int32 minSize=0, bool littleEndian=true) const
Definition: BigNumber.cpp:221
std::array< uint8, Size > ToByteArray(bool littleEndian=true) const
Definition: BigNumber.h:112
static constexpr size_t SHA1_DIGEST_LENGTH_BYTES
Definition: CryptoConstants.h:27
uint32 GetAccountId() const
Definition: WorldSession.h:359
uint32 _checkTimer
Definition: Warden.h:139
uint32 _clientResponseTimer
Definition: Warden.h:140
void ApplyPenalty(uint16 checkId, std::string const &reason)
Definition: Warden.cpp:202
static bool IsValidCheckSum(uint32 checksum, const uint8 *data, const uint16 length)
Definition: Warden.cpp:142
bool _dataSent
Definition: Warden.h:141
WorldSession * _session
Definition: Warden.h:133
Definition: WardenCheckMgr.h:44
uint8 Length
Definition: WardenCheckMgr.h:48
uint8 Type
Definition: WardenCheckMgr.h:45
Definition: WardenCheckMgr.h:59
BigNumber Result
Definition: WardenCheckMgr.h:60
std::list< uint16 > _CurrentChecks
Definition: WardenWin.h:90
void read_skip()
Definition: ByteBuffer.h:339
size_t rpos() const
Definition: ByteBuffer.h:317
void rfinish()
Definition: ByteBuffer.h:325
size_t wpos() const
Definition: ByteBuffer.h:330
size_t size() const
Definition: ByteBuffer.h:444
uint8 * contents()
Definition: ByteBuffer.h:424
T read()
Definition: ByteBuffer.h:351

References Warden::_checkTimer, Warden::_clientResponseTimer, _CurrentChecks, Warden::_dataSent, _serverTicks, Warden::_session, Warden::ApplyPenalty(), CONFIG_WARDEN_CLIENT_CHECK_HOLDOFF, ByteBuffer::contents(), DRIVER_CHECK, WorldSession::GetAccountId(), GameTime::GetGameTimeMS(), IN_MILLISECONDS, Warden::IsValidCheckSum(), WardenCheck::Length, LOG_DEBUG, LUA_EVAL_CHECK, MEM_CHECK, MODULE_CHECK, MPQ_CHECK, PAGE_CHECK_A, PAGE_CHECK_B, ByteBuffer::read(), ByteBuffer::read_skip(), WardenCheckResult::Result, ByteBuffer::rfinish(), ByteBuffer::rpos(), Acore::Crypto::Constants::SHA1_DIGEST_LENGTH_BYTES, ByteBuffer::size(), sWardenCheckMgr, sWorld, BigNumber::ToByteArray(), BigNumber::ToByteVector(), WardenCheck::Type, and ByteBuffer::wpos().

◆ HandleHashResult()

void WardenWin::HandleHashResult ( ByteBuffer buff)
overridevirtual

Implements Warden.

225{
226 buff.rpos(buff.wpos());
227
228 // Verify key
230 {
231 LOG_DEBUG("warden", "Request hash reply: failed");
232 ApplyPenalty(0, "Request hash reply: failed");
233 return;
234 }
235
236 LOG_DEBUG("warden", "Request hash reply: succeed");
237
238 // Change keys here
239 memcpy(_inputKey, Module.ClientKeySeed, 16);
240 memcpy(_outputKey, Module.ServerKeySeed, 16);
241
244
245 _initialized = true;
246}
void Init(uint8 const *seed, size_t len)
Definition: ARC4.cpp:34
uint8 ClientKeySeed[16]
Definition: WardenModuleWin.h:35
uint8 ServerKeySeed[16]
Definition: WardenModuleWin.h:34
uint8 ClientKeySeedHash[20]
Definition: WardenModuleWin.h:36
Acore::Crypto::ARC4 _inputCrypto
Definition: Warden.h:137
Acore::Crypto::ARC4 _outputCrypto
Definition: Warden.h:138
uint8 _inputKey[16]
Definition: Warden.h:134
uint8 _outputKey[16]
Definition: Warden.h:135
bool _initialized
Definition: Warden.h:143

References Warden::_initialized, Warden::_inputCrypto, Warden::_inputKey, Warden::_outputCrypto, Warden::_outputKey, Warden::ApplyPenalty(), Module_79C0768D657977D697E10BAD956CCED1::ClientKeySeed, Module_79C0768D657977D697E10BAD956CCED1::ClientKeySeedHash, ByteBuffer::contents(), Acore::Crypto::ARC4::Init(), LOG_DEBUG, Module, ByteBuffer::rpos(), Module_79C0768D657977D697E10BAD956CCED1::ServerKeySeed, Acore::Crypto::Constants::SHA1_DIGEST_LENGTH_BYTES, and ByteBuffer::wpos().

◆ Init()

void WardenWin::Init ( WorldSession session,
SessionKey const &  K 
)
overridevirtual

Implements Warden.

105{
106 _session = session;
107 // Generate Warden Key
109 WK.Generate(_inputKey, 16);
110 WK.Generate(_outputKey, 16);
111
112 memcpy(_seed, Module.Seed, 16);
113
116 LOG_DEBUG("warden", "Server side warden for client {} initializing...", session->GetAccountId());
117 LOG_DEBUG("warden", "C->S Key: {}", Acore::Impl::ByteArrayToHexStr(_inputKey, 16));
118 LOG_DEBUG("warden", "S->C Key: {}", Acore::Impl::ByteArrayToHexStr(_outputKey,16));
119 LOG_DEBUG("warden", " Seed: {}", Acore::Impl::ByteArrayToHexStr(_seed, 16));
120 LOG_DEBUG("warden", "Loading Module...");
121
123
124 LOG_DEBUG("warden", "Module Key: {}", Acore::Impl::ByteArrayToHexStr(_module->Key, 16));
125 LOG_DEBUG("warden", "Module ID: {}", Acore::Impl::ByteArrayToHexStr(_module->Id, 16));
127}
AC_COMMON_API std::string ByteArrayToHexStr(uint8 const *bytes, size_t length, bool reverse=false)
Definition: Util.cpp:541
Definition: SessionKeyGenerator.h:26
uint8 Seed[16]
Definition: WardenModuleWin.h:33
uint8 _seed[16]
Definition: Warden.h:136
void RequestModule()
Definition: Warden.cpp:75
ClientWardenModule * _module
Definition: Warden.h:142
ClientWardenModule * GetModuleForClient() override
Definition: WardenWin.cpp:129

References Warden::_inputCrypto, Warden::_inputKey, Warden::_module, Warden::_outputCrypto, Warden::_outputKey, Warden::_seed, Warden::_session, Acore::Impl::ByteArrayToHexStr(), SessionKeyGenerator< Hash >::Generate(), WorldSession::GetAccountId(), GetModuleForClient(), ClientWardenModule::Id, Acore::Crypto::ARC4::Init(), ClientWardenModule::Key, LOG_DEBUG, Module, Warden::RequestModule(), and Module_79C0768D657977D697E10BAD956CCED1::Seed.

◆ InitializeModule()

void WardenWin::InitializeModule ( )
overridevirtual

Implements Warden.

151{
152 LOG_DEBUG("warden", "Initialize module");
153
154 // Create packet structure
157 Request.Size1 = 20;
158 Request.Unk1 = 1;
159 Request.Unk2 = 0;
160 Request.Type = 1;
161 Request.String_library1 = 0;
162 Request.Function1[0] = 0x00024F80; // 0x00400000 + 0x00024F80 SFileOpenFile
163 Request.Function1[1] = 0x000218C0; // 0x00400000 + 0x000218C0 SFileGetFileSize
164 Request.Function1[2] = 0x00022530; // 0x00400000 + 0x00022530 SFileReadFile
165 Request.Function1[3] = 0x00022910; // 0x00400000 + 0x00022910 SFileCloseFile
167
169 Request.Size2 = 8;
170 Request.Unk3 = 4;
171 Request.Unk4 = 0;
172 Request.String_library2 = 0;
173 Request.Function2 = 0x00419210; // 0x00400000 + 0x00419210 FrameScript::Execute
174 Request.Function2_set = 1;
175 Request.CheckSumm2 = BuildChecksum(&Request.Unk3, 8);
176
178 Request.Size3 = 8;
179 Request.Unk5 = 1;
180 Request.Unk6 = 1;
181 Request.String_library3 = 0;
182 Request.Function3 = 0x0046AE20; // 0x00400000 + 0x0046AE20 PerformanceCounter
183 Request.Function3_set = 1;
184 Request.CheckSumm3 = BuildChecksum(&Request.Unk5, 8);
185
186 EndianConvert(Request.Size1);
187 EndianConvert(Request.CheckSumm1);
188 EndianConvert(Request.Function1[0]);
189 EndianConvert(Request.Function1[1]);
190 EndianConvert(Request.Function1[2]);
191 EndianConvert(Request.Function1[3]);
192 EndianConvert(Request.Size2);
193 EndianConvert(Request.CheckSumm2);
194 EndianConvert(Request.Function2);
195 EndianConvert(Request.Size3);
196 EndianConvert(Request.CheckSumm3);
197 EndianConvert(Request.Function3);
198
199 // Encrypt with warden RC4 key.
200 EncryptData(reinterpret_cast<uint8*>(&Request), sizeof(WardenInitModuleRequest));
201
203 pkt.append(reinterpret_cast<uint8*>(&Request), sizeof(WardenInitModuleRequest));
204 _session->SendPacket(&pkt);
205}
void EndianConvert(T &val)
Definition: ByteConverter.h:47
@ WARDEN_SMSG_MODULE_INITIALIZE
Definition: Warden.h:41
@ SMSG_WARDEN_DATA
Definition: Opcodes.h:772
Definition: WorldPacket.h:27
void SendPacket(WorldPacket const *packet)
Send a packet to the client.
Definition: WorldSession.cpp:208
void EncryptData(uint8 *buffer, uint32 length)
Definition: Warden.cpp:137
static uint32 BuildChecksum(const uint8 *data, uint32 length)
Definition: Warden.cpp:174
Definition: WardenWin.h:34
uint8 Unk6
Definition: WardenWin.h:57
uint8 Unk3
Definition: WardenWin.h:47
uint8 Unk1
Definition: WardenWin.h:38
uint8 String_library1
Definition: WardenWin.h:41
uint8 String_library3
Definition: WardenWin.h:58
uint8 Unk5
Definition: WardenWin.h:56
uint8 Command1
Definition: WardenWin.h:35
uint8 String_library2
Definition: WardenWin.h:49
uint32 Function3
Definition: WardenWin.h:59
uint8 Function2_set
Definition: WardenWin.h:51
uint32 Function1[4]
Definition: WardenWin.h:42
uint32 CheckSumm2
Definition: WardenWin.h:46
uint8 Command2
Definition: WardenWin.h:44
uint32 Function2
Definition: WardenWin.h:50
uint16 Size2
Definition: WardenWin.h:45
uint8 Command3
Definition: WardenWin.h:53
uint8 Function3_set
Definition: WardenWin.h:60
uint32 CheckSumm3
Definition: WardenWin.h:55
uint32 CheckSumm1
Definition: WardenWin.h:37
uint16 Size3
Definition: WardenWin.h:54
uint8 Unk2
Definition: WardenWin.h:39
uint8 Unk4
Definition: WardenWin.h:48
uint8 Type
Definition: WardenWin.h:40
uint16 Size1
Definition: WardenWin.h:36

References Warden::_session, ByteBuffer::append(), Warden::BuildChecksum(), WardenInitModuleRequest::CheckSumm1, WardenInitModuleRequest::CheckSumm2, WardenInitModuleRequest::CheckSumm3, WardenInitModuleRequest::Command1, WardenInitModuleRequest::Command2, WardenInitModuleRequest::Command3, Warden::EncryptData(), EndianConvert(), WardenInitModuleRequest::Function1, WardenInitModuleRequest::Function2, WardenInitModuleRequest::Function2_set, WardenInitModuleRequest::Function3, WardenInitModuleRequest::Function3_set, LOG_DEBUG, WorldSession::SendPacket(), Acore::Crypto::Constants::SHA1_DIGEST_LENGTH_BYTES, WardenInitModuleRequest::Size1, WardenInitModuleRequest::Size2, WardenInitModuleRequest::Size3, SMSG_WARDEN_DATA, WardenInitModuleRequest::String_library1, WardenInitModuleRequest::String_library2, WardenInitModuleRequest::String_library3, WardenInitModuleRequest::Type, WardenInitModuleRequest::Unk1, WardenInitModuleRequest::Unk2, WardenInitModuleRequest::Unk3, WardenInitModuleRequest::Unk4, WardenInitModuleRequest::Unk5, WardenInitModuleRequest::Unk6, and WARDEN_SMSG_MODULE_INITIALIZE.

◆ RequestChecks()

void WardenWin::RequestChecks ( )
overridevirtual

Implements Warden.

249{
250 LOG_DEBUG("warden", "Request data");
251
252 // If all checks were done, fill the todo list again
253 for (uint8 i = 0; i < MAX_WARDEN_CHECK_TYPES; ++i)
254 {
255 if (_ChecksTodo[i].empty())
256 _ChecksTodo[i].assign(sWardenCheckMgr->CheckIdPool[i].begin(), sWardenCheckMgr->CheckIdPool[i].end());
257 }
258
260 _CurrentChecks.clear();
261
262 // No pending checks
263 if (_PendingChecks.empty())
264 {
265 for (uint8 checkType = 0; checkType < MAX_WARDEN_CHECK_TYPES; ++checkType)
266 {
267 for (uint32 y = 0; y < sWorld->getIntConfig(GetMaxWardenChecksForType(checkType)); ++y)
268 {
269 // If todo list is done break loop (will be filled on next Update() run)
270 if (_ChecksTodo[checkType].empty())
271 {
272 break;
273 }
274
275 // Get check id from the end and remove it from todo
276 uint16 const id = _ChecksTodo[checkType].back();
277 _ChecksTodo[checkType].pop_back();
278
279 // Insert check to queue
280 if (checkType == WARDEN_CHECK_LUA_TYPE)
281 {
282 _CurrentChecks.push_front(id);
283 }
284 else
285 {
286 _CurrentChecks.push_back(id);
287 }
288 }
289 }
290 }
291 else
292 {
293 bool hasLuaChecks = false;
294 for (uint16 const checkId : _PendingChecks)
295 {
296 WardenCheck const* check = sWardenCheckMgr->GetWardenDataById(checkId);
297 if (!hasLuaChecks && check->Type == LUA_EVAL_CHECK)
298 {
299 hasLuaChecks = true;
300 }
301
302 _CurrentChecks.push_back(checkId);
303 }
304
305 // Always include lua checks
306 if (!hasLuaChecks)
307 {
308 for (uint32 i = 0; i < sWorld->getIntConfig(GetMaxWardenChecksForType(WARDEN_CHECK_LUA_TYPE)); ++i)
309 {
310 // If todo list is done break loop (will be filled on next Update() run)
312 {
313 break;
314 }
315
316 // Get check id from the end and remove it from todo
317 uint16 const id = _ChecksTodo[WARDEN_CHECK_LUA_TYPE].back();
319
320 // Lua checks must be always in front
321 _CurrentChecks.push_front(id);
322 }
323 }
324 }
325
326 // Filter too high checks queue
327 // Filtered checks will get passed in next checks
328 uint16 expectedSize = 4;
329 _PendingChecks.clear();
331 [this, &expectedSize](uint16 id)
332 {
333 uint16 const thisSize = GetCheckPacketSize(sWardenCheckMgr->GetWardenDataById(id));
334 if ((expectedSize + thisSize) > 500) // warden packets are truncated to 512 bytes clientside
335 {
336 _PendingChecks.push_back(id);
337 return true;
338 }
339 expectedSize += thisSize;
340 return false;
341 }
342 );
343
344 ByteBuffer buff;
346
347 for (uint16 const checkId : _CurrentChecks)
348 {
349 WardenCheck const* check = sWardenCheckMgr->GetWardenDataById(checkId);
350 switch (check->Type)
351 {
352 case LUA_EVAL_CHECK:
353 {
354 buff << uint8(sizeof(_luaEvalPrefix) - 1 + check->Str.size() + sizeof(_luaEvalMidfix) - 1 + check->IdStr.size() + sizeof(_luaEvalPostfix) - 1);
355 buff.append(_luaEvalPrefix, sizeof(_luaEvalPrefix) - 1);
356 buff.append(check->Str.data(), check->Str.size());
357 buff.append(_luaEvalMidfix, sizeof(_luaEvalMidfix) - 1);
358 buff.append(check->IdStr.data(), check->IdStr.size());
359 buff.append(_luaEvalPostfix, sizeof(_luaEvalPostfix) - 1);
360 break;
361 }
362 case MPQ_CHECK:
363 case DRIVER_CHECK:
364 {
365 buff << uint8(check->Str.size());
366 buff.append(check->Str.c_str(), check->Str.size());
367 break;
368 }
369 }
370 }
371
372 uint8 const xorByte = _inputKey[0];
373
374 // Add TIMING_CHECK
375 buff << uint8(0x00);
376 buff << uint8(TIMING_CHECK ^ xorByte);
377
378 uint8 index = 1;
379
380 for (uint16 const checkId : _CurrentChecks)
381 {
382 WardenCheck const* check = sWardenCheckMgr->GetWardenDataById(checkId);
383 buff << uint8(check->Type ^ xorByte);
384 switch (check->Type)
385 {
386 case MEM_CHECK:
387 {
388 buff << uint8(0x00);
389 buff << uint32(check->Address);
390 buff << uint8(check->Length);
391 break;
392 }
393 case PAGE_CHECK_A:
394 case PAGE_CHECK_B:
395 {
396 std::vector<uint8> data = check->Data.ToByteVector(24, false);
397 buff.append(data.data(), data.size());
398 buff << uint32(check->Address);
399 buff << uint8(check->Length);
400 break;
401 }
402 case MPQ_CHECK:
403 case LUA_EVAL_CHECK:
404 {
405 buff << uint8(index++);
406 break;
407 }
408 case DRIVER_CHECK:
409 {
410 std::vector<uint8> data = check->Data.ToByteVector(24, false);
411 buff.append(data.data(), data.size());
412 buff << uint8(index++);
413 break;
414 }
415 case MODULE_CHECK:
416 {
417 std::array<uint8, 4> seed = Acore::Crypto::GetRandomBytes<4>();
418 buff.append(seed);
419 buff.append(Acore::Crypto::HMAC_SHA1::GetDigestOf(seed, check->Str));
420 break;
421 }
422 /*case PROC_CHECK:
423 {
424 buff.append(wd->i.AsByteArray(0, false).get(), wd->i.GetNumBytes());
425 buff << uint8(index++);
426 buff << uint8(index++);
427 buff << uint32(wd->Address);
428 buff << uint8(wd->Length);
429 break;
430 }*/
431 }
432 }
433 buff << uint8(xorByte);
434 buff.hexlike();
435
436 // Encrypt with warden RC4 key
437 EncryptData(buff.contents(), buff.size());
438
439 WorldPacket pkt(SMSG_WARDEN_DATA, buff.size());
440 pkt.append(buff);
441 _session->SendPacket(&pkt);
442
443 _dataSent = true;
444
445 std::stringstream stream;
446 stream << "Sent check id's: ";
447 for (uint16 checkId : _CurrentChecks)
448 {
449 stream << checkId << " ";
450 }
451
452 LOG_DEBUG("warden", "{}", stream.str());
453}
@ TIMING_CHECK
Definition: Warden.h:54
@ WARDEN_SMSG_CHEAT_CHECKS_REQUEST
Definition: Warden.h:40
constexpr uint8 MAX_WARDEN_CHECK_TYPES
Definition: WardenCheckMgr.h:41
@ WARDEN_CHECK_LUA_TYPE
Definition: WardenCheckMgr.h:37
static WorldIntConfigs GetMaxWardenChecksForType(uint8 type)
Definition: WardenWin.cpp:80
static constexpr char _luaEvalPrefix[]
Definition: WardenWin.cpp:37
static constexpr char _luaEvalMidfix[]
Definition: WardenWin.cpp:38
static constexpr char _luaEvalPostfix[]
Definition: WardenWin.cpp:39
static uint16 GetCheckPacketSize(WardenCheck const *check)
Definition: WardenWin.cpp:58
void EraseIf(Container &c, Predicate p)
Definition: Containers.h:230
static Digest GetDigestOf(Container const &seed, uint8 const *data, size_t len)
Definition: HMAC.h:64
std::array< char, 4 > IdStr
Definition: WardenCheckMgr.h:52
std::string Str
Definition: WardenCheckMgr.h:49
BigNumber Data
Definition: WardenCheckMgr.h:46
uint32 Address
Definition: WardenCheckMgr.h:47
std::list< uint16 > _PendingChecks
Definition: WardenWin.h:91
std::list< uint16 > _ChecksTodo[MAX_WARDEN_CHECK_TYPES]
Definition: WardenWin.h:88
Definition: ByteBuffer.h:70

References _ChecksTodo, _CurrentChecks, Warden::_dataSent, Warden::_inputKey, _luaEvalMidfix, _luaEvalPostfix, _luaEvalPrefix, _PendingChecks, _serverTicks, Warden::_session, WardenCheck::Address, ByteBuffer::append(), WardenCheck::Data, DRIVER_CHECK, Warden::EncryptData(), Acore::Containers::EraseIf(), GetCheckPacketSize(), Acore::Impl::GenericHMAC< HashCreator, DigestLength >::GetDigestOf(), GameTime::GetGameTimeMS(), GetMaxWardenChecksForType(), WardenCheck::IdStr, WardenCheck::Length, LOG_DEBUG, LUA_EVAL_CHECK, MAX_WARDEN_CHECK_TYPES, MEM_CHECK, MODULE_CHECK, MPQ_CHECK, PAGE_CHECK_A, PAGE_CHECK_B, WorldSession::SendPacket(), SMSG_WARDEN_DATA, WardenCheck::Str, sWardenCheckMgr, sWorld, TIMING_CHECK, BigNumber::ToByteVector(), WardenCheck::Type, WARDEN_CHECK_LUA_TYPE, and WARDEN_SMSG_CHEAT_CHECKS_REQUEST.

◆ RequestHash()

void WardenWin::RequestHash ( )
overridevirtual

Implements Warden.

208{
209 LOG_DEBUG("warden", "Request hash");
210
211 // Create packet structure
212 WardenHashRequest Request;
214 memcpy(Request.Seed, _seed, 16);
215
216 // Encrypt with warden RC4 key.
217 EncryptData(reinterpret_cast<uint8*>(&Request), sizeof(WardenHashRequest));
218
220 pkt.append(reinterpret_cast<uint8*>(&Request), sizeof(WardenHashRequest));
221 _session->SendPacket(&pkt);
222}
@ WARDEN_SMSG_HASH_REQUEST
Definition: Warden.h:43
Definition: Warden.h:81
uint8 Seed[16]
Definition: Warden.h:83
uint8 Command
Definition: Warden.h:82

References Warden::_seed, Warden::_session, ByteBuffer::append(), WardenHashRequest::Command, Warden::EncryptData(), LOG_DEBUG, WardenHashRequest::Seed, WorldSession::SendPacket(), SMSG_WARDEN_DATA, and WARDEN_SMSG_HASH_REQUEST.

Member Data Documentation

◆ _ChecksTodo

std::list<uint16> WardenWin::_ChecksTodo[MAX_WARDEN_CHECK_TYPES]
private

Referenced by RequestChecks().

◆ _CurrentChecks

std::list<uint16> WardenWin::_CurrentChecks
private

Referenced by HandleData(), and RequestChecks().

◆ _PendingChecks

std::list<uint16> WardenWin::_PendingChecks
private

Referenced by RequestChecks().

◆ _serverTicks

uint32 WardenWin::_serverTicks
private

Referenced by HandleData(), and RequestChecks().