Added trade hack detection code

This commit is contained in:
Uleat 2016-12-03 18:17:10 -05:00
parent c482738d79
commit 0ab0c5c117
7 changed files with 84 additions and 16 deletions

View File

@ -1,7 +1,12 @@
EQEMu Changelog (Started on Sept 24, 2003 15:50) EQEMu Changelog (Started on Sept 24, 2003 15:50)
------------------------------------------------------- -------------------------------------------------------
== 21/01/2016 == == 12/03/2016 ==
Uleat: Disabled RoF+ clients from augmentation items not in their possessions slots (0-29, 9999, 251-330) to abate an exploit in the current code Uleat: Added hack detection to trade code
- If illegal items are found in trade slots when the 'trade' button is clicked, the trade is cancelled and a message is sent to the offending player
- Future revisions will, at a minimum, log the player as a hacker once the quirks have been worked out
== 12/01/2016 ==
Uleat: Disabled RoF+ clients from augmenting items not in their possessions slots (0-29, 9999, 251-330) to abate an exploit in the current code
== 10/17/2016 == == 10/17/2016 ==
Uleat: Moved namespace ItemField from item_instance.h to shareddb.cpp - the only place it is used Uleat: Moved namespace ItemField from item_instance.h to shareddb.cpp - the only place it is used

View File

@ -819,6 +819,32 @@ bool EQEmu::ItemInstance::IsSlotAllowed(int16 slot_id) const {
else { return false; } else { return false; }
} }
bool EQEmu::ItemInstance::IsDroppable(bool recurse) const
{
if (!m_item)
return false;
/*if (m_ornamentidfile) // not implemented
return false;*/
if (m_attuned)
return false;
/*if (m_item->FVNoDrop != 0) // not implemented
return false;*/
if (m_item->NoDrop == 0)
return false;
if (recurse) {
for (auto iter : m_contents) {
if (!iter.second)
continue;
if (!iter.second->IsDroppable(recurse))
return false;
}
}
return true;
}
void EQEmu::ItemInstance::Initialize(SharedDatabase *db) { void EQEmu::ItemInstance::Initialize(SharedDatabase *db) {
// if there's no actual item, don't do anything // if there's no actual item, don't do anything
if (!m_item) if (!m_item)

View File

@ -188,6 +188,8 @@ namespace EQEmu
bool IsSlotAllowed(int16 slot_id) const; bool IsSlotAllowed(int16 slot_id) const;
bool IsDroppable(bool recurse = true) const;
bool IsScaling() const { return m_scaling; } bool IsScaling() const { return m_scaling; }
bool IsEvolving() const { return (m_evolveLvl >= 1); } bool IsEvolving() const { return (m_evolveLvl >= 1); }
uint32 GetExp() const { return m_exp; } uint32 GetExp() const { return m_exp; }

View File

@ -855,6 +855,7 @@ public:
void SetConsumption(int32 in_hunger, int32 in_thirst); void SetConsumption(int32 in_hunger, int32 in_thirst);
bool CheckTradeLoreConflict(Client* other); bool CheckTradeLoreConflict(Client* other);
bool CheckTradeNonDroppable();
void LinkDead(); void LinkDead();
void Insight(uint32 t_id); void Insight(uint32 t_id);
bool CheckDoubleAttack(); bool CheckDoubleAttack();

View File

@ -13287,7 +13287,6 @@ void Client::Handle_OP_TradeAcceptClick(const EQApplicationPacket *app)
other->trade->state = TradeCompleting; other->trade->state = TradeCompleting;
trade->state = TradeCompleting; trade->state = TradeCompleting;
// should we do this for NoDrop items as well?
if (CheckTradeLoreConflict(other) || other->CheckTradeLoreConflict(this)) { if (CheckTradeLoreConflict(other) || other->CheckTradeLoreConflict(this)) {
Message_StringID(13, TRADE_CANCEL_LORE); Message_StringID(13, TRADE_CANCEL_LORE);
other->Message_StringID(13, TRADE_CANCEL_LORE); other->Message_StringID(13, TRADE_CANCEL_LORE);
@ -13296,6 +13295,26 @@ void Client::Handle_OP_TradeAcceptClick(const EQApplicationPacket *app)
other->trade->Reset(); other->trade->Reset();
trade->Reset(); trade->Reset();
} }
else if (CheckTradeNonDroppable()) {
Message_StringID(13, TRADE_HAS_BEEN_CANCELLED);
other->Message_StringID(13, TRADE_HAS_BEEN_CANCELLED);
this->FinishTrade(this);
other->FinishTrade(other);
other->trade->Reset();
trade->Reset();
Message(15, "Hacking activity detected in trade transaction.");
// TODO: query (this) as a hacker
}
else if (other->CheckTradeNonDroppable()) {
Message_StringID(13, TRADE_HAS_BEEN_CANCELLED);
other->Message_StringID(13, TRADE_HAS_BEEN_CANCELLED);
this->FinishTrade(this);
other->FinishTrade(other);
other->trade->Reset();
trade->Reset();
other->Message(15, "Hacking activity detected in trade transaction.");
// TODO: query (other) as a hacker
}
else { else {
// Audit trade to database for both trade streams // Audit trade to database for both trade streams
other->trade->LogTrade(); other->trade->LogTrade();

View File

@ -255,6 +255,7 @@
#define MEMBER_OF_YOUR_GUILD 1429 #define MEMBER_OF_YOUR_GUILD 1429
#define OFFICER_OF_YOUR_GUILD 1430 #define OFFICER_OF_YOUR_GUILD 1430
#define LEADER_OF_YOUR_GUILD 1431 #define LEADER_OF_YOUR_GUILD 1431
#define TRADE_HAS_BEEN_CANCELLED 1449
#define RECEIVED_PLATINUM 1452 //You receive %1 Platinum from %2. #define RECEIVED_PLATINUM 1452 //You receive %1 Platinum from %2.
#define RECEIVED_GOLD 1453 //You receive %1 Gold from %2. #define RECEIVED_GOLD 1453 //You receive %1 Gold from %2.
#define RECEIVED_SILVER 1454 //You receive %1 Silver from %2. #define RECEIVED_SILVER 1454 //You receive %1 Silver from %2.

View File

@ -967,23 +967,37 @@ bool Client::CheckTradeLoreConflict(Client* other)
{ {
if (!other) if (!other)
return true; return true;
// Move each trade slot into free inventory slot
for (int16 i = EQEmu::legacy::TRADE_BEGIN; i <= EQEmu::legacy::TRADE_END; i++){
const EQEmu::ItemInstance* inst = m_inv[i];
if (inst && inst->GetItem()) { for (int16 index = EQEmu::legacy::TRADE_BEGIN; index <= EQEmu::legacy::TRADE_END; ++index) {
if (other->CheckLoreConflict(inst->GetItem())) const EQEmu::ItemInstance* inst = m_inv[index];
return true; if (!inst || !inst->GetItem())
} continue;
if (other->CheckLoreConflict(inst->GetItem()))
return true;
} }
for (int16 i = EQEmu::legacy::TRADE_BAGS_BEGIN; i <= EQEmu::legacy::TRADE_BAGS_END; i++){ for (int16 index = EQEmu::legacy::TRADE_BAGS_BEGIN; index <= EQEmu::legacy::TRADE_BAGS_END; ++index) {
const EQEmu::ItemInstance* inst = m_inv[i]; const EQEmu::ItemInstance* inst = m_inv[index];
if (!inst || !inst->GetItem())
continue;
if (inst && inst->GetItem()) { if (other->CheckLoreConflict(inst->GetItem()))
if (other->CheckLoreConflict(inst->GetItem())) return true;
return true; }
}
return false;
}
bool Client::CheckTradeNonDroppable()
{
for (int16 index = EQEmu::legacy::TRADE_BEGIN; index <= EQEmu::legacy::TRADE_END; ++index){
const EQEmu::ItemInstance* inst = m_inv[index];
if (!inst)
continue;
if (!inst->IsDroppable())
return true;
} }
return false; return false;