Fix gender exploit.
Now check that character has a valid gender (and not an invalid via packet modifications). This check works when trying to create a character or when building the character list. If gender is invalid (neither male nor female): can't create the character and can't see in the characters' list (and also can't login with it via packet modding). Signed-off-by: Anubisss <[email protected]>
This commit is contained in:
@@ -895,6 +895,9 @@ void Player::CleanupsBeforeDelete(bool finalCleanup)
|
|||||||
bool Player::Create(uint32 guidlow, const std::string& name, uint8 race, uint8 class_, uint8 gender, uint8 skin, uint8 face, uint8 hairStyle, uint8 hairColor, uint8 facialHair, uint8 /*outfitId*/)
|
bool Player::Create(uint32 guidlow, const std::string& name, uint8 race, uint8 class_, uint8 gender, uint8 skin, uint8 face, uint8 hairStyle, uint8 hairColor, uint8 facialHair, uint8 /*outfitId*/)
|
||||||
{
|
{
|
||||||
//FIXME: outfitId not used in player creating
|
//FIXME: outfitId not used in player creating
|
||||||
|
// TODO: need more checks against packet modifications
|
||||||
|
// should check that skin, face, hair* are valid via DBC per race/class
|
||||||
|
// also do it in Player::BuildEnumData, Player::LoadFromDB
|
||||||
|
|
||||||
Object::_Create(guidlow, 0, HIGHGUID_PLAYER);
|
Object::_Create(guidlow, 0, HIGHGUID_PLAYER);
|
||||||
|
|
||||||
@@ -928,6 +931,12 @@ bool Player::Create(uint32 guidlow, const std::string& name, uint8 race, uint8 c
|
|||||||
|
|
||||||
setFactionForRace(race);
|
setFactionForRace(race);
|
||||||
|
|
||||||
|
if (!IsValidGender(gender))
|
||||||
|
{
|
||||||
|
sLog->outError("Player has invalid gender (%hu), can't be loaded.", gender);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
uint32 RaceClassGender = (race) | (class_ << 8) | (gender << 16);
|
uint32 RaceClassGender = (race) | (class_ << 8) | (gender << 16);
|
||||||
|
|
||||||
SetUInt32Value(UNIT_FIELD_BYTES_0, (RaceClassGender | (powertype << 24)));
|
SetUInt32Value(UNIT_FIELD_BYTES_0, (RaceClassGender | (powertype << 24)));
|
||||||
@@ -1842,6 +1851,7 @@ bool Player::BuildEnumData(QueryResult result, WorldPacket * p_data)
|
|||||||
uint32 guid = fields[0].GetUInt32();
|
uint32 guid = fields[0].GetUInt32();
|
||||||
uint8 pRace = fields[2].GetUInt8();
|
uint8 pRace = fields[2].GetUInt8();
|
||||||
uint8 pClass = fields[3].GetUInt8();
|
uint8 pClass = fields[3].GetUInt8();
|
||||||
|
uint8 Gender = fields[4].GetUInt8();
|
||||||
|
|
||||||
PlayerInfo const *info = sObjectMgr->GetPlayerInfo(pRace, pClass);
|
PlayerInfo const *info = sObjectMgr->GetPlayerInfo(pRace, pClass);
|
||||||
if (!info)
|
if (!info)
|
||||||
@@ -1849,12 +1859,17 @@ bool Player::BuildEnumData(QueryResult result, WorldPacket * p_data)
|
|||||||
sLog->outError("Player %u has incorrect race/class pair. Don't build enum.", guid);
|
sLog->outError("Player %u has incorrect race/class pair. Don't build enum.", guid);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
else if (!IsValidGender(Gender))
|
||||||
|
{
|
||||||
|
sLog->outError("Player (%u) has incorrect gender (%hu), don't build enum.", guid, Gender);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
*p_data << uint64(MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER));
|
*p_data << uint64(MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER));
|
||||||
*p_data << fields[1].GetString(); // name
|
*p_data << fields[1].GetString(); // name
|
||||||
*p_data << uint8(pRace); // race
|
*p_data << uint8(pRace); // race
|
||||||
*p_data << uint8(pClass); // class
|
*p_data << uint8(pClass); // class
|
||||||
*p_data << uint8(fields[4].GetUInt8()); // gender
|
*p_data << uint8(Gender); // gender
|
||||||
|
|
||||||
uint32 playerBytes = fields[5].GetUInt32();
|
uint32 playerBytes = fields[5].GetUInt32();
|
||||||
*p_data << uint8(playerBytes); // skin
|
*p_data << uint8(playerBytes); // skin
|
||||||
@@ -16430,11 +16445,18 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder)
|
|||||||
// overwrite possible wrong/corrupted guid
|
// overwrite possible wrong/corrupted guid
|
||||||
SetUInt64Value(OBJECT_FIELD_GUID, MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER));
|
SetUInt64Value(OBJECT_FIELD_GUID, MAKE_NEW_GUID(guid, 0, HIGHGUID_PLAYER));
|
||||||
|
|
||||||
|
uint8 Gender = fields[5].GetUInt8();
|
||||||
|
if (!IsValidGender(Gender))
|
||||||
|
{
|
||||||
|
sLog->outError("Player (GUID: %u) has wrong gender (%hu), can't be loaded.", guid, Gender);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// overwrite some data fields
|
// overwrite some data fields
|
||||||
uint32 bytes0 = 0;
|
uint32 bytes0 = 0;
|
||||||
bytes0 |= fields[3].GetUInt8(); // race
|
bytes0 |= fields[3].GetUInt8(); // race
|
||||||
bytes0 |= fields[4].GetUInt8() << 8; // class
|
bytes0 |= fields[4].GetUInt8() << 8; // class
|
||||||
bytes0 |= fields[5].GetUInt8() << 16; // gender
|
bytes0 |= Gender << 16; // gender
|
||||||
SetUInt32Value(UNIT_FIELD_BYTES_0, bytes0);
|
SetUInt32Value(UNIT_FIELD_BYTES_0, bytes0);
|
||||||
|
|
||||||
SetUInt32Value(UNIT_FIELD_LEVEL, fields[6].GetUInt8());
|
SetUInt32Value(UNIT_FIELD_LEVEL, fields[6].GetUInt8());
|
||||||
|
|||||||
@@ -1471,6 +1471,8 @@ class Player : public Unit, public GridObject<Player>
|
|||||||
static uint32 GetLevelFromDB(uint64 guid);
|
static uint32 GetLevelFromDB(uint64 guid);
|
||||||
static bool LoadPositionFromDB(uint32& mapid, float& x,float& y,float& z,float& o, bool& in_flight, uint64 guid);
|
static bool LoadPositionFromDB(uint32& mapid, float& x,float& y,float& z,float& o, bool& in_flight, uint64 guid);
|
||||||
|
|
||||||
|
static bool IsValidGender(uint8 Gender) { return Gender <= GENDER_FEMALE ; }
|
||||||
|
|
||||||
/*********************************************************/
|
/*********************************************************/
|
||||||
/*** SAVE SYSTEM ***/
|
/*** SAVE SYSTEM ***/
|
||||||
/*********************************************************/
|
/*********************************************************/
|
||||||
|
|||||||
@@ -552,7 +552,7 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket & recv_data)
|
|||||||
Player * pNewChar = new Player(this);
|
Player * pNewChar = new Player(this);
|
||||||
if (!pNewChar->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_PLAYER), name, race_, class_, gender, skin, face, hairStyle, hairColor, facialHair, outfitId))
|
if (!pNewChar->Create(sObjectMgr->GenerateLowGuid(HIGHGUID_PLAYER), name, race_, class_, gender, skin, face, hairStyle, hairColor, facialHair, outfitId))
|
||||||
{
|
{
|
||||||
// Player not create (race/class problem?)
|
// Player not create (race/class/etc problem?)
|
||||||
pNewChar->CleanupsBeforeDelete();
|
pNewChar->CleanupsBeforeDelete();
|
||||||
delete pNewChar;
|
delete pNewChar;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user