Core/Movement: Do not process server side relocation if reading movementinfo from client resulted in violations (= hacking).

This commit is contained in:
Machiavelli
2012-03-16 18:15:08 +01:00
parent cca93c7a22
commit 65453620e8
5 changed files with 68 additions and 13 deletions
+4
View File
@@ -482,6 +482,9 @@ struct MovementInfo
// spline // spline
float splineElevation; float splineElevation;
//! Server side only:
bool Violated;
MovementInfo() MovementInfo()
{ {
pos.Relocate(0, 0, 0, 0); pos.Relocate(0, 0, 0, 0);
@@ -494,6 +497,7 @@ struct MovementInfo
t_guid = 0; t_guid = 0;
t_pos.Relocate(0, 0, 0, 0); t_pos.Relocate(0, 0, 0, 0);
t_seat = -1; t_seat = -1;
Violated = false;
} }
uint32 GetMovementFlags() { return flags; } uint32 GetMovementFlags() { return flags; }
+6
View File
@@ -1621,6 +1621,12 @@ void WorldSession::HandleMoveSetCanFlyAckOpcode(WorldPacket & recv_data)
recv_data.read_skip<float>(); // unk2 recv_data.read_skip<float>(); // unk2
if (movementInfo.Violated)
{
recv_data.rfinish();
return;
}
_player->m_mover->m_movementInfo.flags = movementInfo.GetMovementFlags(); _player->m_mover->m_movementInfo.flags = movementInfo.GetMovementFlags();
} }
+24 -1
View File
@@ -278,6 +278,14 @@ void WorldSession::HandleMovementOpcodes(WorldPacket & recv_data)
return; return;
} }
//! If some anti-cheat checks in WorldSession::ReadMovementInfo failed, do not process
//! the change of movement server-sided.
if (movementInfo.Violated)
{
recv_data.rfinish();
return;
}
/* handle special cases */ /* handle special cases */
if (movementInfo.flags & MOVEMENTFLAG_ONTRANSPORT) if (movementInfo.flags & MOVEMENTFLAG_ONTRANSPORT)
{ {
@@ -485,9 +493,16 @@ void WorldSession::HandleMoveNotActiveMover(WorldPacket &recv_data)
recv_data.readPackGUID(old_mover_guid); recv_data.readPackGUID(old_mover_guid);
MovementInfo mi; MovementInfo mi;
mi.guid = old_mover_guid;
ReadMovementInfo(recv_data, &mi); ReadMovementInfo(recv_data, &mi);
if (mi.Violated)
{
recv_data.rfinish();
return;
}
mi.guid = old_mover_guid;
_player->m_movementInfo = mi; _player->m_movementInfo = mi;
} }
@@ -513,6 +528,13 @@ void WorldSession::HandleMoveKnockBackAck(WorldPacket & recv_data)
MovementInfo movementInfo; MovementInfo movementInfo;
ReadMovementInfo(recv_data, &movementInfo); ReadMovementInfo(recv_data, &movementInfo);
if (movementInfo.Violated)
{
recv_data.rfinish();
return;
}
_player->m_movementInfo = movementInfo; _player->m_movementInfo = movementInfo;
WorldPacket data(MSG_MOVE_KNOCK_BACK, 66); WorldPacket data(MSG_MOVE_KNOCK_BACK, 66);
@@ -571,3 +593,4 @@ void WorldSession::HandleSummonResponseOpcode(WorldPacket& recv_data)
_player->SummonIfPossible(agree); _player->SummonIfPossible(agree);
} }
#undef IF_VIOLATED_RETURN
+16 -1
View File
@@ -43,6 +43,12 @@ void WorldSession::HandleDismissControlledVehicle(WorldPacket &recv_data)
mi.guid = guid; mi.guid = guid;
ReadMovementInfo(recv_data, &mi); ReadMovementInfo(recv_data, &mi);
if (mi.Violated)
{
recv_data.rfinish();
return;
}
_player->m_movementInfo = mi; _player->m_movementInfo = mi;
_player->ExitVehicle(); _player->ExitVehicle();
@@ -81,7 +87,16 @@ void WorldSession::HandleChangeSeatsOnControlledVehicle(WorldPacket &recv_data)
uint64 guid; // current vehicle guid uint64 guid; // current vehicle guid
recv_data.readPackGUID(guid); recv_data.readPackGUID(guid);
ReadMovementInfo(recv_data, &vehicle_base->m_movementInfo); MovementInfo movementInfo;
ReadMovementInfo(recv_data, &movementInfo);
if (movementInfo.Violated)
{
recv_data.rfinish();
return;
}
vehicle_base->m_movementInfo = movementInfo;
uint64 accessory; // accessory guid uint64 accessory; // accessory guid
recv_data.readPackGUID(accessory); recv_data.readPackGUID(accessory);
+18 -11
View File
@@ -807,48 +807,53 @@ void WorldSession::ReadMovementInfo(WorldPacket &data, MovementInfo* mi)
if (mi->HasMovementFlag(MOVEMENTFLAG_SPLINE_ELEVATION)) if (mi->HasMovementFlag(MOVEMENTFLAG_SPLINE_ELEVATION))
data >> mi->splineElevation; data >> mi->splineElevation;
//! Anti-cheat checks. Please keep them in seperate if() blocks to maintain a clear overview.
#define VIOLATE_AND_RETURN \
mi->Violated = true; \
return; \
/*! This must be a packet spoofing attempt. MOVEMENTFLAG_ROOT sent from the client is not valid, /*! This must be a packet spoofing attempt. MOVEMENTFLAG_ROOT sent from the client is not valid,
and when used in conjunction with any of the moving movement flags such as MOVEMENTFLAG_FORWARD and when used in conjunction with any of the moving movement flags such as MOVEMENTFLAG_FORWARD
it will freeze clients that receive this player's movement info. it will freeze clients that receive this player's movement info.
*/ */
if (mi->HasMovementFlag(MOVEMENTFLAG_ROOT)) if (mi->HasMovementFlag(MOVEMENTFLAG_ROOT))
mi->flags &= ~MOVEMENTFLAG_ROOT; VIOLATE_AND_RETURN;
//! Cannot hover and jump at the same time //! Cannot hover and jump at the same time
if (mi->HasMovementFlag(MOVEMENTFLAG_HOVER) && mi->HasMovementFlag(MOVEMENTFLAG_JUMPING)) if (mi->HasMovementFlag(MOVEMENTFLAG_HOVER) && mi->HasMovementFlag(MOVEMENTFLAG_JUMPING))
mi->flags &= ~MOVEMENTFLAG_JUMPING; VIOLATE_AND_RETURN;
//! Cannot ascend and descend at the same time //! Cannot ascend and descend at the same time
if (mi->HasMovementFlag(MOVEMENTFLAG_ASCENDING) && mi->HasMovementFlag(MOVEMENTFLAG_DESCENDING)) if (mi->HasMovementFlag(MOVEMENTFLAG_ASCENDING) && mi->HasMovementFlag(MOVEMENTFLAG_DESCENDING))
mi->flags &= ~(MOVEMENTFLAG_ASCENDING | MOVEMENTFLAG_DESCENDING); VIOLATE_AND_RETURN;
//! Cannot move left and right at the same time //! Cannot move left and right at the same time
if (mi->HasMovementFlag(MOVEMENTFLAG_LEFT) && mi->HasMovementFlag(MOVEMENTFLAG_RIGHT)) if (mi->HasMovementFlag(MOVEMENTFLAG_LEFT) && mi->HasMovementFlag(MOVEMENTFLAG_RIGHT))
mi->flags &= ~(MOVEMENTFLAG_LEFT | MOVEMENTFLAG_RIGHT); VIOLATE_AND_RETURN;
//! Cannot strafe left and right at the same time //! Cannot strafe left and right at the same time
if (mi->HasMovementFlag(MOVEMENTFLAG_STRAFE_LEFT) && mi->HasMovementFlag(MOVEMENTFLAG_STRAFE_RIGHT)) if (mi->HasMovementFlag(MOVEMENTFLAG_STRAFE_LEFT) && mi->HasMovementFlag(MOVEMENTFLAG_STRAFE_RIGHT))
mi->flags &= ~(MOVEMENTFLAG_STRAFE_LEFT | MOVEMENTFLAG_STRAFE_RIGHT); VIOLATE_AND_RETURN;
//! Cannot pitch up and down at the same time //! Cannot pitch up and down at the same time
if (mi->HasMovementFlag(MOVEMENTFLAG_PITCH_UP) && mi->HasMovementFlag(MOVEMENTFLAG_PITCH_DOWN)) if (mi->HasMovementFlag(MOVEMENTFLAG_PITCH_UP) && mi->HasMovementFlag(MOVEMENTFLAG_PITCH_DOWN))
mi->flags &= ~(MOVEMENTFLAG_PITCH_UP | MOVEMENTFLAG_PITCH_DOWN); VIOLATE_AND_RETURN;
//! Cannot move forwards and backwards at the same time //! Cannot move forwards and backwards at the same time
if (mi->HasMovementFlag(MOVEMENTFLAG_FORWARD) && mi->HasMovementFlag(MOVEMENTFLAG_BACKWARD)) if (mi->HasMovementFlag(MOVEMENTFLAG_FORWARD) && mi->HasMovementFlag(MOVEMENTFLAG_BACKWARD))
mi->flags &= ~(MOVEMENTFLAG_FORWARD | MOVEMENTFLAG_BACKWARD); VIOLATE_AND_RETURN;
//! Cannot walk on water without SPELL_AURA_WATER_WALK //! Cannot walk on water without SPELL_AURA_WATER_WALK
if (mi->HasMovementFlag(MOVEMENTFLAG_WATERWALKING) && !GetPlayer()->HasAuraType(SPELL_AURA_WATER_WALK)) if (mi->HasMovementFlag(MOVEMENTFLAG_WATERWALKING) && !GetPlayer()->HasAuraType(SPELL_AURA_WATER_WALK))
mi->flags &= ~MOVEMENTFLAG_WATERWALKING; VIOLATE_AND_RETURN;
//! Cannot feather fall without SPELL_AURA_FEATHER_FALL //! Cannot feather fall without SPELL_AURA_FEATHER_FALL
if (mi->HasMovementFlag(MOVEMENTFLAG_FALLING_SLOW) && !GetPlayer()->HasAuraType(SPELL_AURA_FEATHER_FALL)) if (mi->HasMovementFlag(MOVEMENTFLAG_FALLING_SLOW) && !GetPlayer()->HasAuraType(SPELL_AURA_FEATHER_FALL))
mi->flags &= ~MOVEMENTFLAG_FALLING_SLOW; VIOLATE_AND_RETURN;
//! Cannot hover without SPELL_AURA_HOVER //! Cannot hover without SPELL_AURA_HOVER
if (mi->HasMovementFlag(MOVEMENTFLAG_HOVER) && !GetPlayer()->HasAuraType(SPELL_AURA_HOVER)) if (mi->HasMovementFlag(MOVEMENTFLAG_HOVER) && !GetPlayer()->HasAuraType(SPELL_AURA_HOVER))
mi->flags &= ~MOVEMENTFLAG_HOVER; VIOLATE_AND_RETURN;
/*! Cannot fly if no fly auras present. Exception is being a GM. /*! Cannot fly if no fly auras present. Exception is being a GM.
Note that we check for account level instead of Player::IsGameMaster() because in some Note that we check for account level instead of Player::IsGameMaster() because in some
@@ -859,7 +864,9 @@ void WorldSession::ReadMovementInfo(WorldPacket &data, MovementInfo* mi)
if (mi->HasMovementFlag(MOVEMENTFLAG_FLYING | MOVEMENTFLAG_CAN_FLY) && GetSecurity() == SEC_PLAYER && if (mi->HasMovementFlag(MOVEMENTFLAG_FLYING | MOVEMENTFLAG_CAN_FLY) && GetSecurity() == SEC_PLAYER &&
!GetPlayer()->m_mover->HasAuraType(SPELL_AURA_FLY) && !GetPlayer()->m_mover->HasAuraType(SPELL_AURA_FLY) &&
!GetPlayer()->m_mover->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED)) !GetPlayer()->m_mover->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED))
mi->flags &= ~(MOVEMENTFLAG_FLYING | MOVEMENTFLAG_CAN_FLY); VIOLATE_AND_RETURN;
#undef VIOLATE_AND_RETURN
} }
void WorldSession::WriteMovementInfo(WorldPacket* data, MovementInfo* mi) void WorldSession::WriteMovementInfo(WorldPacket* data, MovementInfo* mi)