Since there were some attacks going on last night on several servers abusing uninitialized CUser objects in CDPSrvr, I tried coming up with a fix for it. I just got it working when making my client spam the abused function every 100ms on login. Since it affects multiple servers, I want to share it. No guarantee this is a fix for it, but it worked for me. If you have suggestions about it or concerns, please post here or pm me.
IMPORTANT UPDATE:
This fix will NOT fully fix the attacks that were going on previously. This fix will only filter messages from invalid players sending packets.
The actual fix has been developed with a lot of outside help and in a group of 10 people.
The group in total has decided to not disclose any details as we invested a lot of time into it and simply don't want to share it with everyone out there.
Sharing a fix will also mean making servers that are not present on epvp vulnerable to the attack. We don't want that to happen.
The invalid user filter will stay on here, but nothing else will be disclosed.
Previous Updates:
UPDATE: After receiving several feedback, this fix deflects only certain types of attacks. An updated version is being worked on at the moment.
UPDATE 2: Some improvements were made, all parts have been updated. Still waiting on confirmation is this works for Login spams as well.
Update 3: The fix is only working partly against invalid users. Different causes are still being investigated.
Update 4 (Jan 13): Still working with several people on finding the correct solution as this fix doesn't cover everything. Made some adjustments to the current fix that will be posted once we advanced.
Update 4.2: We found the cause of it, just waiting on permission from everyone involved before making it public.
[b]Update 5 (15. Jan): Updated code style
User.h
below
Code:
map<DWORD, CUser*> m_users;
add
Code:
map<DWORD, CUser*> m_invalid_users;
below
Code:
CUser* GetUser(DPID dpidCache, DPID dpidUser);
add
Code:
CUser* GetInvalidUser(DPID dpidUser);
User.cpp
add
Code:
CUser* CUserMng::GetInvalidUser(DPID dpidUser)
{
auto it = m_invalid_users.find(dpidUser);
if (it != m_invalid_users.end())
return it->second;
else
return nullptr;
}
in
Code:
CUserMng::AddPlayer
add at the top of the function
Code:
m_users.insert({ pUser->m_dwSerial, pUser });
m_invalid_users.erase(pUser->m_dwSerial);
In
replace
Code:
m_users.insert(std::make_pair(dpidUser, pUser));
with
Code:
m_invalid_users.insert({dpidUser, pUser});
in
Code:
CUserMng::RemoveUser
at the top of the function, add
Code:
auto findInvalid = m_invalid_users.find(dwSerial);
if (findInvalid != m_invalid_users.end())
{
m_invalid_users.erase(findInvalid);
return;
}
DPDatabaseClient.cpp
In
OnJoin replace
Code:
CUser* pUser = g_UserMng.GetUser( dpidCache, dpidUser );
with
Code:
CUser* pUser = g_UserMng.GetInvalidUser( dpidUser );
DPSrvr.cpp
In
UserMessageHandler after
GETTYPE( ar ) add
Code:
CUser* pUser = g_UserMng.GetInvalidUser(*(UNALIGNED LPDPID)lpMsg);
if (pUser)
{
Error("Received Packet from Invalid user");
return;
}
in
OnAddUser
after
Code:
if( nSlot >= 3 )
return;
add
Code:
CUser* pInvalidUser = g_UserMng.GetInvalidUser(dpidUser);
if (pInvalidUser)
{
Error("Invalid Connection Attempt UserID [%u]", idPlayer);
return;
}
Consider removing the Errors since multiple logins may work server lag with too many calls. It's mostly for debugging purposes.
After adding that the error triggered twice when logging in local server. As said above, if you have concerns or suggestions on how to improve that code, post here or pm me.
Quick demonstration of the fix:
Contributions and suggestions made by:
Vladi#5038
Dylan#8888
kotori#0001