Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] Implement passive anticheat system #16774

Closed
wants to merge 9 commits into from

Conversation

ariel-
Copy link
Contributor

@ariel- ariel- commented Mar 13, 2016

Changes proposed: Original patch taken from here: (created by @maanuel)
https://community.trinitycore.org/topic/10-patch-telenpc2-pvpranks-passive-anticheat-for-trinitycore-2016-02-24-4e4b2b9-35a-only/

  • This adds the core capabilities to passively detect player hacking/cheating using 3rd party tools, it just scans for some flags/speed mismatch and emits a warning to every GM (or rather any account with rbac::RBAC_PERM_RECEIVE_GLOBAL_GM_TEXTMESSAGE)
  • The original version was massively updated, it was optimized and updated to reflect core changes along the way.

Target branch(es): 335/6x

Issues addressed: None, feature request.

Tests performed: (Does it build, tested in-game, etc) It builds and correctly detects many kinds of 3rd party tools, issuing a warning.

Known issues and TODO list:

  • Move anticheat.sql to correct folder and update base sql
  • Move singleton out of header
  • Re evaluate logic of existing checks (specially non-efficient ones)

(@ENTRY+10, '============================='),
(@ENTRY+11, 'Players with the lowest averages:'),
(@ENTRY+12, 'Player: %s Average: %f Total Reports: %u'),
(@ENTRY+13, 'Players with the more reports:'),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Players with the most reports?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Heh, that's what you get for brainless copy pasting hardcoded texts xD

@Ardinis
Copy link
Contributor

Ardinis commented Mar 13, 2016

You should rebase your branch and squash commits.

@ariel-
Copy link
Contributor Author

ariel- commented Mar 13, 2016

When it's deemed for merge into the core, that is.

Until then I prefer to leave the commit history intact so changes may be seen step by step (also different authors on commits)

@@ -1,8 +1,8 @@
-- MySQL dump 10.13 Distrib 5.6.26, for Win64 (x86_64)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see many unrelated changes in the full sql dump - charsets/unsigned on some fields

@Keader
Copy link
Member

Keader commented Mar 13, 2016

The Hitchhiker's Hack is detected?

--Edit

Still dont detect teleport, but detect speed/fly

`jump_reports` bigint(20) unsigned NOT NULL DEFAULT '0',
`waterwalk_reports` bigint(20) unsigned NOT NULL DEFAULT '0',
`teleportplane_reports` bigint(20) unsigned NOT NULL DEFAULT '0',
`climb_reports` bigint(20) unsigned NOT NULL DEFAULT '0',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the bigint is unnecessary as data is saved as uint32, which is unsigned int. And data is never loaded, or I cant see that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Data is queried when using .anticheat global command, however I'll have to rethink if this is necessary at all.

@jackpoz
Copy link
Member

jackpoz commented Mar 13, 2016

I would like this patch to be tested with valgrind, helgrind and a static analyzer of your choice

if (!*args)
return false;

std::string strCommand = const_cast<char*>(args);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doesnt look like a necessary cast. The value should be copied by the string constructor.

@ariel-
Copy link
Contributor Author

ariel- commented Mar 13, 2016

Well, I'm open to suggestions, because I don't know about multi threaded programming. To solve the unsafe issue, then I don't have to clear the map when the command is issued right? Can it be fixed by 0'ing out the associated data instead of clearing the whole map?

About the lastMovementInfo bit: it's saved to compare with new movement, see https://github.com/TrinityCore/TrinityCore/pull/16774/files#diff-cd67866d024cb7e5288fca94a3cd3358R172

@joschiwald
Copy link
Contributor

player->GetMovementInfo() contains the same data like lastMovementInfo, so you don't need to save it twice

@Shauren
Copy link
Member

Shauren commented Mar 13, 2016

Instead of trying to make access to m_playerMap from multiple threads safe (and slow!) you should just drop the delete command entirely

@@ -16,6 +16,7 @@
* with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include "AnticheatMgr.h"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is no change in this file - include not needed

static WorldLocation const jailPos(1, 16226.5f, 16403.6f, -64.5f, 3.2f);

Player* pTarget = nullptr;
char* command = strtok(const_cast<char*>(args), " ");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const_cast is overkill here, simply replace it with a strtok(*args, " ");
That's how commands were handled until now.

Copy link
Contributor

@Rochet2 Rochet2 Mar 13, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not quite sure what you mean. Const cast isn't an overhead, its needed (and probably optimized away as it is only typesafety). Also currently commands use a C style cast: strtok((char*)args, " ");

char* fileStr = strtok((char*)args, " ");

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, yeah. I forgot the actual casting that still needs to happen. But that's the case, we do not need an actual const_cast type of convertion, a simple c-style cast is how we handled it until now. It solves the issues.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need to remove const-ness because strtok requires a char*; and I prefer const_cast for clarity in this regard.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are those commands different to the way other commands are handled ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really, as Rochet2 pointed out in that link, const-ness is casted away as it is here (except the cast there is not explicit, rather a C-style cast, this is why I prefer const_cast, because it's explicit of my intention)

@nawuko
Copy link
Contributor

nawuko commented Mar 14, 2016

I just tested some random cheats for 3.3.5

TeleportPlaneCheck does in 4/5 cases not work. (Player has falling flag).

SpeedhackCheck dosent work in 3/5 cases (Player has OnTransportFlag or the cheat skips/obscure packages, send many many small packages or delays packages).

WalkOnWaterCheck fails in 5/5 cases (all cheats dosent send the waterwalk movementflag but are still able to walk on water)

Edit: FlyhackCheck dosent work in some cases (player has falling flag and has not the flying flag)

Sorry for my bad english 👎

@@ -1289,6 +1290,13 @@ void World::LoadConfigSettings(bool reload)
m_bool_configs[CONFIG_PDUMP_NO_OVERWRITE] = sConfigMgr->GetBoolDefault("PlayerDump.DisallowOverwrite", true);
m_bool_configs[CONFIG_UI_QUESTLEVELS_IN_DIALOGS] = sConfigMgr->GetBoolDefault("UI.ShowQuestLevelsInDialogs", false);

// Passive anticheat
m_bool_configs[CONFIG_ANTICHEAT_ENABLE] = sConfigMgr->GetBoolDefault("Anticheat.Enable", true);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is it enabled by default ?

- Moved scripts to Custom ScriptLoader
- Migrated commands to rbac system, anticheat jail command will also apply freeze aura to target
- Oneline methods moved to header and made inline for maximum performance
- Player data is saved as unordered_map now to save on cpu cycles
- Use of "ObjectGuid::LowType" in order to keep up with core naming rules
- Added a configurable delay between reports of same Player
- Moved reports to chat window, this will also honor rbac for Receive GM messages, meaning it can be configured for gm's players accounts.
@Aokromes Aokromes reopened this Aug 25, 2016
@Demonid
Copy link
Contributor

Demonid commented Sep 4, 2016

@Aokromes Need update after 7026c7e

@tripleslash
Copy link

I'd be sad to see this thing merged into the official TC master...
I'd suggest abandoning this branch and starting to fix the fundamental issues (like movement ACK handling) first. As soon as that's done one can implement the missing handlers for the movement packets and stop handling every different opcode in one handler function and start doing proper timestamp synchronization.

@Aokromes
Copy link
Member

Aokromes commented Sep 4, 2016

@nawuko trinitycore was made with the mind of add custom features since the start.

@jackpoz
Copy link
Member

jackpoz commented Sep 4, 2016

cluttered

?

AHBot

3/4 of crash reports we get always have AHBot, so either we chose to ignore 3/4 of our users or we had to add a supported AHBot that we chose to fix and maintain. We value our users and their efforts to improve TC.

@Keader
Copy link
Member

Keader commented Sep 4, 2016

i cant see problems with custom stuffs. Using "disabled" by default, why not be present?

@Demonid
Copy link
Contributor

Demonid commented Sep 9, 2016

Could anyone check if this PR is still working?

I tried testing it after the last commit 2fb0418 but it doesn't detect anything, maybe the detection system broke after all the code changes?

Thanks!

@Mrgrasser
Copy link

Break passive ? not work now :(

@Mrgrasser
Copy link

@Demonid this AntiCheat have some problem for back jump , Improved Charge warrior , spell Engineering , Some time speed rouge , Aspect of the Pack hunter , Blazing Speed mage
If the configuration is correct is with no trouble AntiCheat.

Then again, what about adding some kind of movement restriction, kinda like this Anticheat does:

https://bitbucket.org/lordpsyan/lordpsyan-patches/src/bd5c2b08de445bafbb4cc70cba56bc391e5f5848/Individual/Anti-Cheats/2016_02_29-Non-Passive-AC2.patch?at=master&fileviewer=file-view-default

Just a suggestion, nothing more.

…passive

# Conflicts:
#	sql/base/auth_database.sql
#	sql/base/characters_database.sql
@chaodhib
Copy link
Member

chaodhib commented Dec 18, 2016

I don't think this should get merged neither to be honest. I think we should keep the good stuff (which is the anti cheat logic, basically every OnCheck method in AnticheatMgr.cpp) and throw the rest out.

The anti cheat logic will already use additional CPU resources. I don't think adding a system that tracks cheating players and does database queries on top of that is a good idea. Also, keeping small the anti movement cheat code will make it easier to maintain and improve. Imo, we should just add a hook in the MovementHandler: It will call a method like bool verifyClientPosition() that takes as input the latest verified MoveInfo of the player and the latest received. If it returns false, the handler should ignore the last packet, force an update on the client to the last known valid position and potentially do one (or more) of the following options (configurable by config file): log the event, kick the player and or ban the player. This change won't take much more than 300 LOC.

I think the focus should be put on validating incoming packets (example: if the unit is already falling, ignore any new MSG_MOVE_JUMP, etc...), not all the extra stuff around it.

PS: @tripleslash What do you mean by implementing proper timestamp synchronization by the way? I'm working on something related and I could use all the help I can get.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet