PDA

View Full Version : Flood Protection



Wise
11-01-14, 10:26 PM
Hello everyone,

This flood protection system will currently only defend your server against the infamous CMSG_CHAR_ENUM opcode.
I made it somewhat dynamic so you can add a part of the code inside other packet handling functions aswell so you can defend your server against those packets too.

I was too lazy to create a patch ( Git and stuff ), so below you'll find a guide that guides you through the adding process.

Guide to add it:
If you're sure you haven't edited anything in WorldSession.h, WorldSession.cpp or CharacterHandler.cpp and you are on the latest TC revision ( the latest rev at the time of writing this ) you can download the already edited files

here (http://www.mediafire.com/?o076bmuo3wso6l9)
, simply replacing the files and adding the custom script 'packet_prot.cpp' to your core will do the trick.

else, you'll have to read a boring guide and add multiple lines on far too many places( I don't make the rules):
1. Open up WorldSession.h

2. Find the PartyOperations enumeration, looking like this :




enum PartyOperation
{
PARTY_OP_INVITE = 0,
PARTY_OP_UNINVITE = 1,
PARTY_OP_LEAVE = 2,
PARTY_OP_SWAP = 4
};


3. Add this code below that enumeration:




enum ProtectedPackets
{
PACKET_CMSG_CHAR_ENUM,
MAX_PROTECTED_PACKETS
};


4. Now, scroll all the way down or just use CTRL+F to find "void InvalidateRBACData();"

5. Below that function declaration, add a new array :


uint32 protectedPacketsCounter[MAX_PROTECTED_PACKETS];

6. Now open up WorldSession.cpp and head to the WorldSession class constructor, looking like this :





/// WorldSession constructor
WorldSession::WorldSession(uint32 id, WorldSocket* sock, AccountTypes sec, uint8 expansion, time_t mute_time, LocaleConstant locale, uint32 recruiter, bool isARecruiter):
m_muteTime(mute_time),
m_timeOutTime(0),
_player(NULL),
m_Socket(sock),
_security(sec),
_accountId(id),
m_expansion(expansion),
_warden(NULL),
_logoutTime(0),
m_inQueue(false),
m_playerLoading(false),
m_playerLogout(false),
m_playerRecentlyLogout(false),
m_playerSave(false),
m_sessionDbcLocale(sWorld->GetAvailableDbcLocale(locale)),
m_sessionDbLocaleIndex(locale),
m_latency(0),
m_TutorialsChanged(false),
recruiterId(recruiter),
isRecruiter(isARecruiter),
timeLastWhoCommand(0),
_RBACData(NULL)
{
if (sock)
{
m_Address = sock->GetRemoteAddress();
sock->AddReference();
ResetTimeOutTime();
LoginDatabase.PExecute("UPDATE account SET online = 1 WHERE id = %u;", GetAccountId()); // One-time query
}

InitializeQueryCallbackParameters();
}


7. Now, head to this line


_RBACData(NULL)

add a comma ( , ) after the statement. press the enter key ( good job ) and add this line:



protectedPacketsCounter()


8. Last edit we need to make is in the Characterhandler.cpp, so open it up.

9. Find


void WorldSession::HandleCharEnumOpcode(WorldPacket & /*recvData*/)

10. Replace the function ( just cause I'm too lazy to actually tell you where you need to add it exactly ) with mine :



void WorldSession::HandleCharEnumOpcode(WorldPacket & /*recvData*/)
{
if(++protectedPacketsCounter[PACKET_CMSG_CHAR_ENUM] >= 3)
{
std::ostringstream ss;
if(protectedPacketsCounter[PACKET_CMSG_CHAR_ENUM] < 5 || protectedPacketsCounter[PACKET_CMSG_CHAR_ENUM] % 25 == 0)
{
ss << "[Overflood Protection] : Session with ";
ss << "IP address ";
ss << GetRemoteAddress();
ss << " triggered OverFlood Protection for packet CMSG_CHAR_ENUM. info : ";
ss << "Account ID : ";
ss << GetAccountId();
ss << " Account Name : ";
std::string accountName;
sAccountMgr->GetName(GetAccountId(), accountName);
ss << accountName;
ss << " Player Name : ";
if(GetPlayer() && GetPlayer()->IsInWorld())
ss << GetPlayer()->GetName();
else
ss << " No Name ( not logged in )";
ss << " current packet count : ";
ss << (uint32)protectedPacketsCounter[PACKET_CMSG_CHAR_ENUM];
ss << ", ignoring.";
sLog->outError(LOG_FILTER_GENERAL, ss.str().c_str());
}
return;
}
// remove expired bans
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_EX PIRED_BANS);
CharacterDatabase.Execute(stmt);

/// get all the data necessary for loading all characters (along with their pets) on the account

if (sWorld->getBoolConfig(CONFIG_DECLINED_NAMES_USED))
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_EN UM_DECLINED_NAME);
else
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_EN UM);

stmt->setUInt8(0, PET_SAVE_AS_CURRENT);
stmt->setUInt32(1, GetAccountId());

_charEnumCallback = CharacterDatabase.AsyncQuery(stmt);
}

11. last step, add this custom script to your core :

packet prot - jamey - Pastebin.com (http://pastebin.com/iNhK2jMj)


That's that, you're done, recompile.

Atm, this will only log that there are too many packets and will just not handle them, no further action is taken.

To add protection against another packet you will need to add a new enumeration, like this :




enum ProtectedPackets
{
PACKET_CMSG_CHAR_ENUM,
PACKET_ANOTHER_PACKET_NAME,
MAX_PROTECTED_PACKETS
};


Then just copy the if statement of the CMSG_CHAR_ENUM, change any appearances with CMSG_CHAR_ENUM to your own packet name and paste it inside the other function that handles the packet ( at the top of the function ).





I will NOT
give support to people having trouble adding this, I think that you should be able to add this to your core if you're running a server... or in other words:
"you can supply toilet paper, doesn't mean you have to wipe every retards ass" ( Thanks Foe )

Adios